import React from 'react'; import styled, { ThemeProvider } from 'styled-components'; import { space, layout, color, border, shadow, typography, } from 'styled-system'; import { Clipboard } from '~/clipboard'; import { shortText, longText } from '~/text'; import { getVariations } from './theme-helper'; import { ZIndexShowcases } from '~/z-index'; import { Space } from '~/space'; interface SystemUIShowcasesProps { /** A theme object that minds the System UI theme spec */ theme: Record; /** The key from the theme for which to showcase the variations. */ showcaseKey: string; /** Props of component used to render the variations of the specified theme key. The component will be either a box or text depending on the theme key. */ componentProps?: Record; /** Specifies the distance between rendered components, used to adjust the layout. */ gap?: { horizontal?: string; vertical?: string }; } const Box = styled.div` ${shadow}; ${border}; ${space}; ${layout}; ${color}; `; const CheckeredBackground = styled.div` ${shadow}; ${border}; ${space}; ${layout}; ${color}; opacity: 1; background-color: #000000; background-image: linear-gradient(45deg, #999 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #999 75%), linear-gradient(45deg, transparent 75%, #999 75%), linear-gradient(45deg, #999 25%, #fff 25%); background-size: 1rem 1rem; background-position: 0 0, 0 0, -0.5rem -0.5rem, 0.5rem 0.5rem; position: absolute; top: 0; z-index: -1; boxshadow: none; `; const TextContainer = styled.div` display: flex; align-items: center; justify-content: center; ${shadow}; ${border}; ${space}; ${layout}; ${color}; ${typography}; `; const Text = ({ useLongText = false, ...rest }) => ( {useLongText ? longText : shortText} ); const Container = styled.div` display: flex; flex-direction: ${(props) => (props.type === 'text' ? 'column' : 'row')}; align-items: flex-start; flex-wrap: wrap; `; const ComponentContainer = styled.div` margin-right: ${(props) => props.gap?.horizontal}; margin-bottom: ${(props) => props.gap?.vertical}; min-width: ${(props) => props.minWidth}; display: flex; flex-direction: ${(props) => (props.usedForText ? 'row-reverse' : 'column')}; align-items: baseline; `; const Error = styled.div` color: 'red'; `; interface ShowcaseComponentProps { componentProps?: Record; gap?: { horizontal?: string; vertical?: string }; caption: string; minWidth: string; type: 'box' | 'text'; useLongText: boolean; key?: any; } const ShowcaseComponent = ({ componentProps, caption, gap, minWidth, type, useLongText, }: ShowcaseComponentProps) => { const { checkeredBackground, ...props } = componentProps; return ( {type === 'text' ? ( ) : (
{checkeredBackground && }
)} {caption}
); }; const keyDetails = { bg: { themeProp: 'colors', componentType: 'box' }, backgroundColor: { themeProp: 'colors', componentType: 'box' }, boxShadow: { themeProp: 'shadows', componentType: 'box' }, width: { themeProp: 'sizes', componentType: 'box' }, height: { themeProp: 'sizes', componentType: 'box' }, borderRadius: { themeProp: 'radii', componentType: 'box' }, borderWidth: { themeProp: 'borderWidths', componentType: 'box' }, borderStyle: { themeProp: 'borderStyles', componentType: 'box' }, borderColor: { themeProp: 'colors', componentType: 'box' }, border: { themeProp: 'borders', componentType: 'box' }, borderTop: { themeProp: 'borders', componentType: 'box' }, borderBottom: { themeProp: 'borders', componentType: 'box' }, borderLeft: { themeProp: 'borders', componentType: 'box' }, borderRight: { themeProp: 'borders', componentType: 'box' }, fontSize: { themeProp: 'fontSizes', componentType: 'text' }, fontFamily: { themeProp: 'fonts', componentType: 'text' }, fontWeight: { themeProp: 'fontWeights', componentType: 'text' }, lineHeight: { themeProp: 'lineHeights', componentType: 'text', useLongText: true, }, letterSpacing: { themeProp: 'letterSpacings', componentType: 'text', useLongText: true, }, color: { themeProp: 'colors', componentType: 'text' }, zIndex: { themeProp: 'zIndex', StandaloneComponent: ({ theme }) => { const variations = getVariations('zIndices', theme); return ( ); }, }, space: { themeProp: 'space', StandaloneComponent: ({ theme }) => , }, }; export const showcaseKeys = Object.keys(keyDetails); /** With this component you can render all variations of a property from System UI specification abiding theme https://system-ui.com/theme/. */ export const SystemUIShowcases = ({ theme, showcaseKey, componentProps = {}, gap = { horizontal: '2rem', vertical: '2rem' }, }: SystemUIShowcasesProps) => { if (!keyDetails[showcaseKey]) return {`"${showcaseKey}" is not yet supported.`}; const { themeProp, componentType, useLongText, StandaloneComponent } = keyDetails[showcaseKey]; if (!!StandaloneComponent) { return ; } const variations = getVariations(themeProp, theme); if (!variations.length) return ( {`"${showcaseKey}" has no values in the provided theme`} ); const longestPropertyName = variations.reduce( (max, e) => Math.max(`${e}`.length, max), 0 ); const componentWidth = `${longestPropertyName / 2 + 0.5}rem`; return ( {variations.map((v) => { const props = { ...componentProps, [showcaseKey]: v }; return ( ); })} ); };