import React, { useMemo } from 'react';
import { useTheme } from '@aws-amplify/ui-react';
import { createTokenList, getTokenBlock } from './utils';
export type Namespace =
| 'colors'
| 'radii'
| 'space'
| 'borderWidths'
| 'lineHeights'
| 'fonts'
| 'fontSizes'
| 'fontWeights';
type TokenItemProps = {
namespace: Namespace;
children: React.ReactNode;
};
export function TokenItem({ namespace, children }: TokenItemProps) {
return (
{children}
);
}
type TokenPathProps = {
path: Array;
};
export function TokenPath({ path }: TokenPathProps) {
return (
{path.map((pathFragment, index) => {
/**
* We show a delimiter (.) between path fragments, unless that
* fragment is first in the list, or can be interpreted as a number.
* We use isNaN() here because our path returns all fragments as strings.
**/
const showDelimiter = index !== 1 && isNaN(pathFragment as any);
/**
* Wrap any path fragments that can be interpreted as a number in brackets.
*/
const wrapFragmentInBrackets = !isNaN(pathFragment as any);
/**
* Skip the first index which matches our namespace and is redundant in the UI
*/
return index !== 0 ? (
{showDelimiter && '.'}
{wrapFragmentInBrackets ? `[${pathFragment}]` : pathFragment}
) : null;
})}
);
}
type TokenMetaProps = {
children: string;
};
export function TokenMeta({ children }: TokenMetaProps) {
return {children}
;
}
type TokenListProps = {
namespace: Namespace;
/**
* TODO: better type for childNamespace? This should be children
* of whatever namespace you chose. e.g. namespace: 'colors', childNamespace: 'brand,primary'
*/
childNamespace?: Array;
};
export function TokenList({ namespace, childNamespace }: TokenListProps) {
const { tokens } = useTheme();
/**
* Get the tokens from useTheme() depending on namespace and childNamespace(s).
* e.g. for namespace: 'colors' and childNamespace: ['brand', 'primary'],
* tokenNamespace will equal tokens.colors.brand.primary
*/
const tokenNamespace = childNamespace
? childNamespace.reduce((namespace, childNamespace) => {
return namespace && namespace[childNamespace];
}, tokens[namespace])
: tokens[namespace];
/**
* Create a more iteratable list (array) from our tokens
*/
const tokenList = createTokenList(tokenNamespace);
/**
* getTokenBlock() returns a visual element (like a color circle)
* depending on the namespace.
*/
const TokenBlock = getTokenBlock(namespace);
const tokenItems = useMemo(() => {
return (
<>
{tokenList.map((tokenItem) => {
const { name, path, value } = tokenItem;
return (
{name}
{value}
);
})}
>
);
}, [tokenList, TokenBlock, namespace]);
return (
);
}