Skip to content

Commit

Permalink
Add common tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
mimshins committed Apr 16, 2024
1 parent 62b5ae0 commit 8b169e3
Showing 1 changed file with 59 additions and 17 deletions.
76 changes: 59 additions & 17 deletions lib/create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,21 @@ import VariableGenerator, {
getCSSVariablesAsInlineStyle,
type Props as VariableGeneratorProps,
} from "./VariableGenerator";
import { Logger } from "./utils";
import { Logger, shallowMerge } from "./utils";

const create = <TVariants extends Record<string, Record<string, unknown>>>(
variants: TVariants,
const create = <
TVariants extends Record<string, Record<string, unknown>>,
TCommon extends Record<string, unknown>,
>(
tokens: { variants: TVariants; common: TCommon },
config?: {
cssVariableGenerator?: VariableGeneratorProps["cssVariableGenerator"];
},
) => {
const { cssVariableGenerator = defaultCSSVariableGenerator } = config ?? {};

const { common, variants } = tokens;

type TVariantsKeys = keyof TVariants;

type VariantSelectorProps = {
Expand All @@ -24,56 +29,93 @@ const create = <TVariants extends Record<string, Record<string, unknown>>>(
variant: TVariantsKeys;
};

const TokensContext = React.createContext<TVariants[TVariantsKeys] | null>(
null,
);
const VariantTokensContext = React.createContext<
TVariants[TVariantsKeys] | null
>(null);

const CommonTokensContext = React.createContext<TCommon | null>(null);

const VariantSelector = (props: VariantSelectorProps) => {
const { variant, children, disableCSSVariableGeneration = false } = props;

const tokens = variants[variant];
const commonTokens = React.useContext(CommonTokensContext);

const variantTokens = variants[variant];

const tokens = React.useMemo<Record<string, unknown>>(() => {
if (!variantTokens) return {};

if (!tokens) {
if (commonTokens) return variantTokens;

return shallowMerge(variantTokens, common);
}, [commonTokens, variantTokens]);

if (!variantTokens) {
Logger.error(`No variant found with key ${String(variant)}.`);

return null;
}

const renderContent = () => {
if (commonTokens) return children;

return (
<CommonTokensContext.Provider value={common}>
{children}
</CommonTokensContext.Provider>
);
};

return (
<VariableGenerator
tokens={tokens}
variant={String(variant)}
disableCSSVariableGeneration={disableCSSVariableGeneration}
cssVariableGenerator={cssVariableGenerator}
>
<TokensContext.Provider value={tokens}>
{children}
</TokensContext.Provider>
<VariantTokensContext.Provider value={variantTokens}>
{renderContent()}
</VariantTokensContext.Provider>
</VariableGenerator>
);
};

const useTokens = () => {
const tokensCtx = React.useContext(TokensContext);
const variantTokens = React.useContext(VariantTokensContext);
const commonTokens = React.useContext(CommonTokensContext);

if (!tokensCtx) {
if (!variantTokens || !commonTokens) {
throw new Error(
"You must use this hook in a component that is a descendant of <VariantSelector>.",
);
}

return tokensCtx;
const tokens = React.useMemo(
() => shallowMerge(variantTokens, commonTokens),
[variantTokens, commonTokens],
);

return tokens;
};

const generateCSSVariablesAsInlineStyle = (variant: TVariantsKeys) => {
const tokens = variants[variant];
const generateCSSVariablesAsInlineStyle = (
variant: TVariantsKeys,
options?: { disableCommonTokensGeneration?: boolean },
) => {
const { disableCommonTokensGeneration = false } = options ?? {};

const variantTokens = variants[variant];

if (!tokens) {
if (!variantTokens) {
Logger.error(`No variant found with key ${String(variant)}.`);

return null;
}

const tokens = disableCommonTokensGeneration
? variantTokens
: shallowMerge(variantTokens, common);

const cssVariables = generateCssVariables(tokens, cssVariableGenerator);
const inlineStyle = getCSSVariablesAsInlineStyle(cssVariables);

Expand Down

0 comments on commit 8b169e3

Please sign in to comment.