import { ComponentType } from 'react'; import { createSetupError } from '../utils/error'; import { CssFunction, BasicTemplateInterpolations } from '../types'; export interface FunctionIterpolation { (props: TProps): string | number; } /** * Typing for the CSS object. */ export type CssObject = CssFunction>; /** * Extra props added to the output Styled Component. */ export interface StyledProps { as?: keyof JSX.IntrinsicElements; } /** * This allows us to take the generic `TTag` (that will be a valid `DOM` tag) and then use it to * define correct props based on it from `JSX.IntrinsicElements`, while also injecting our own * props from `StyledProps`. */ export interface StyledFunctionFromTag { ( // Allows either string or object (`` or ({})) css: CssObject | CssObject[], ...interpoltations: (BasicTemplateInterpolations | FunctionIterpolation)[] ): React.ComponentType; } export interface StyledFunctionFromComponent { ( // Allows either string or object (`` or ({})) css: CssObject | TemplateStringsArray, ...interpoltations: (BasicTemplateInterpolations | FunctionIterpolation)[] ): React.ComponentType; } export type StyledComponentMap = { // This creates the DOM element types for `styled.blah`, e.g. `span`, `div`, `h1`, etc. [Tag in keyof JSX.IntrinsicElements]: StyledFunctionFromTag; }; export interface StyledComponentInstantiator extends StyledComponentMap { /** * Typing to enable consumers to compose components, e.g: `styled(Component)` */ ( Component: ComponentType ): StyledFunctionFromComponent; } export const styled: StyledComponentInstantiator = new Proxy( {}, { get() { return () => { // Blow up if the transformer isn't turned on. // This code won't ever be executed when setup correctly. throw createSetupError(); }; }, } ) as any;