diff --git a/package.json b/package.json index c196b9d..861cb3a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@swan-io/css", - "version": "0.1.1", + "version": "0.1.2", "license": "MIT", "description": "A lightweight and performant atomic CSS-in-JS library", "author": "Mathieu Acthernoene ", diff --git a/src/hash.ts b/src/hash.ts new file mode 100644 index 0000000..4e63881 --- /dev/null +++ b/src/hash.ts @@ -0,0 +1,4 @@ +import rawHash from "@emotion/hash"; +import { memoize } from "./utils"; + +export const hash = memoize(rawHash); diff --git a/src/hyphenateName.ts b/src/hyphenateName.ts index f1295a2..0fba74f 100644 --- a/src/hyphenateName.ts +++ b/src/hyphenateName.ts @@ -1,12 +1,9 @@ // https://github.com/facebook/react/blob/v19.0.0/packages/react-dom-bindings/src/shared/hyphenateStyleName.js -const uppercasePattern = /([A-Z])/g; -const hyphenateNameCache: Record = {}; +import { memoize } from "./utils"; -export const hyphenateName = (name: string): string => { - hyphenateNameCache[name] ??= name - .replace(uppercasePattern, "-$1") - .toLowerCase(); +const uppercasePattern = /([A-Z])/g; - return hyphenateNameCache[name]; -}; +export const hyphenateName = memoize((name: string): string => + name.replace(uppercasePattern, "-$1").toLowerCase(), +); diff --git a/src/normalizeValue.ts b/src/normalizeValue.ts index 0ba0467..99f74f2 100644 --- a/src/normalizeValue.ts +++ b/src/normalizeValue.ts @@ -1,7 +1,7 @@ import normalizeColor from "@react-native/normalize-colors"; import { Property } from "./types"; -const normalizeValueCache: Record = {}; +const normalizeValueCache: Record = Object.create(null); /** * CSS properties which accept numbers but are not in units of "px" @@ -64,16 +64,13 @@ const isWebColor = (color: string): boolean => color === "inherit" || color.indexOf("var(") === 0; -export const normalizeValue = ( - value: string | number | undefined, - property: string, -): string | undefined => { +export const normalizeValue = (key: string, value: string | number): string => { if (typeof value === "number") { - return unitlessProperties.has(property) ? String(value) : `${value}px`; + return unitlessProperties.has(key) ? String(value) : `${value}px`; } - if (colorProperties.has(property)) { - if (value == null || isWebColor(value)) { + if (colorProperties.has(key)) { + if (isWebColor(value)) { return value; } diff --git a/src/sheet.ts b/src/sheet.ts index ceb9aaa..4378218 100644 --- a/src/sheet.ts +++ b/src/sheet.ts @@ -1,4 +1,4 @@ -import hash from "@emotion/hash"; +import { hash } from "./hash"; import { hyphenateName } from "./hyphenateName"; import { normalizeValue } from "./normalizeValue"; import { ClassNames, Keyframes, Nestable, Style } from "./types"; @@ -53,15 +53,15 @@ const insertRule = (sheet: CSSMediaRule, rule: string): void => { } }; -const stringifyRule = (name: string, value: string | number): string => { - if (name === "appearance") { +const stringifyRule = (key: string, value: string | number): string => { + if (key === "appearance") { return `-webkit-appearance: ${value}; appearance: ${value};`; } - if (name === "lineClamp") { + if (key === "lineClamp") { return `-webkit-line-clamp: ${value}; line-clamp: ${value};`; } - return `${hyphenateName(name)}: ${normalizeValue(value, name)};`; + return `${hyphenateName(key)}: ${normalizeValue(key, value)};`; }; const extractClassNames = (items: ClassNames, acc: string[]): string[] => { diff --git a/src/utils.ts b/src/utils.ts index 0854ae6..9164b8b 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -14,3 +14,15 @@ export const forEach = >( } } }; + +export const memoize = (fn: (arg: string) => T) => { + const cache: Record = Object.create(null); + + return (arg: string): T => { + if (cache[arg] == null) { + cache[arg] = fn(arg); + } + + return cache[arg]; + }; +};