import * as CSS from 'csstype'; // ======================================================== // Debug // ======================================================== export type DebugData = { componentName: string; siteVariables: Object[]; componentVariables: Object[]; componentStyles: Record; }; // ======================================================== // Utility types // ======================================================== export type Extendable = T & { [key: string]: V; }; export type ObjectOrFunc = ((arg: TArg) => TResult) | TResult; // ======================================================== // CSS in JS // ======================================================== type AnimationKeyFrame = Record<'from' | 'to' | string, ICSSInJSStyle>; export interface AnimationName

> { keyframe?: AnimationKeyFrame | ((params: P) => AnimationKeyFrame); params?: P; } type CSSProperties = Omit, 'animationName'> & { animationName?: AnimationName | AnimationKeyFrame | string | 'none'; }; export interface ICSSPseudoElementStyle extends ICSSInJSStyle { content?: string; } export type ICSSInJSStyle = Omit & { // TODO Questionable: how else would users target their own children? [key: string]: any; display?: CSSProperties['display'] | CSSProperties['display'][]; // missing React.CSSProperties speak?: CSS.Globals | 'none' | 'normal' | 'spell-out'; // CSS in JS Properties '::before'?: ICSSPseudoElementStyle; '::after'?: ICSSPseudoElementStyle; ':hover'?: ICSSInJSStyle; ':active'?: ICSSInJSStyle; ':focus'?: ICSSInJSStyle; ':visited'?: ICSSInJSStyle; // TODO Questionable: avoid order specific styles ':first-child'?: ICSSInJSStyle; ':last-child'?: ICSSInJSStyle; ':nth-child(n+2)'?: ICSSInJSStyle; // TODO Questionable: unsupported by autoprefixer, one-off vendors // we could expand these ourselves so that "font-smoothing" works, but which values? '-webkit-font-smoothing'?: CSS.Globals | 'auto' | 'none' | 'antialiased' | 'subpixel-antialiased'; '-moz-osx-font-smoothing'?: CSS.Globals | 'auto' | 'grayscale'; }; export interface ThemeAnimation { keyframe: ((kp: KP) => object) | object | string; delay?: string; direction?: string; duration?: string; fillMode?: string; iterationCount?: string; playState?: string; timingFunction?: string; keyframeParams?: KP; } // ======================================================== // Fonts // ======================================================== export interface FontFaceProps { fontStretch?: string; fontStyle?: string; fontVariant?: string; fontWeight?: number; localAlias?: string | string[]; unicodeRange?: string; } export interface FontFace { name: string; paths: string[]; props: FontFaceProps; } export type FontFaces = FontFace[]; // ======================================================== // Site Variables // ======================================================== export interface SiteVariablesInput extends Record {} export interface SiteVariablesPrepared extends SiteVariablesInput { fontSizes: Record; } // ======================================================== // Component Variables // ======================================================== export type ComponentVariablesObject = any; // TODO: Make this generic export type ComponentVariablesInput = ComponentVariablesObject | ComponentVariablesPrepared; export type ComponentVariablesPrepared = (siteVariables?: SiteVariablesPrepared) => ComponentVariablesObject; // ======================================================== // Component Style Props // ======================================================== export type ComponentSlotStyle = ComponentSlotStyleFunction | ICSSInJSStyle; export type PropsWithVarsAndStyles = Extendable<{ variables?: ComponentVariablesInput; styles?: ComponentSlotStyle; }>; // ======================================================== // Component Styles // ======================================================== export interface ComponentSlotStylesInput extends Record> {} export interface ComponentSlotStylesPrepared extends Record> {} export interface ComponentSlotStylesResolved extends Record {} export interface ComponentStyleFunctionParam< TProps extends PropsWithVarsAndStyles = PropsWithVarsAndStyles, TVars extends ComponentVariablesObject = ComponentVariablesObject > { props: TProps; variables: TVars; theme: ThemePrepared; rtl: boolean; disableAnimations: boolean; } export type ComponentSlotStyleFunction = ( styleParam: ComponentStyleFunctionParam, ) => ICSSInJSStyle; export interface ComponentSlotStylesPrepared extends Record> {} // ======================================================== // Static Styles // ======================================================== export type StaticStyleObject = Record; export type StaticStyleRenderable = string | StaticStyleObject; export type StaticStyleFunction = (siteVariables?: SiteVariablesPrepared) => StaticStyleObject; export type StaticStyle = StaticStyleRenderable | StaticStyleFunction; export type StaticStyles = StaticStyle[]; // ======================================================== // TODO: Theme typings that have no sense // ======================================================== export type ThemeComponentVariablesInput = { [K in keyof ThemeStylesProps]?: ComponentVariablesInput; } & Record; export type ThemeComponentVariablesPrepared = { [K in keyof ThemeStylesProps]?: ComponentVariablesPrepared; } & Record; export type ThemeComponentStylesInput = { [K in keyof ThemeStylesProps]?: ComponentSlotStylesInput; } & Record; export type ThemeComponentStylesPrepared = { [K in keyof ThemeStylesProps]?: ComponentSlotStylesPrepared; } & Record; // ======================================================== // Theme // ======================================================== export interface ThemeInput = any> { siteVariables?: SiteVariablesInput; componentVariables?: ThemeComponentVariablesInput; componentStyles?: ThemeComponentStylesInput; fontFaces?: FontFaces; staticStyles?: StaticStyles; animations?: { [key: string]: ThemeAnimation }; } // Component variables and styles must be resolved by the component after // all cascading is complete, not by any Provider in the middle of the tree. // This ensures the final site variables are used in the component's variables // and styles. Resolving component variables/styles in the Provider would mean // the latest site variables might not be applied to the component. // // As a theme cascades down the tree and is merged with the previous theme on // context, the resulting theme takes this shape. export interface ThemePrepared = any> { siteVariables: SiteVariablesPrepared; componentVariables: { [key in keyof ThemeComponentVariablesPrepared]: ComponentVariablesPrepared; }; componentStyles: { [key in keyof ThemeComponentStylesPrepared]: ComponentSlotStylesPrepared; }; fontFaces: FontFaces; staticStyles: StaticStyles; animations: Record; }