UNPKG

use-styled

Version:

A powerful library for creating React/React Native components

165 lines 6.73 kB
import type { ElementType, ComponentProps, ComponentType, RefAttributes } from 'react'; export type { ComponentProps } from 'react'; /** * Defines the expected structure of the component configuration. */ export type Config = { base?: object; variants?: { [key: string]: { [key: string]: object; }; }; defaultVariants?: { [key: string]: string | boolean; }; compoundVariants?: Array<object>; }; /** * Alias for ElementType representing a valid React component. */ export type Component = ElementType; /** * Validates a properties object `P` against the valid properties of a component `T`, * also allowing `data-*` attributes and rejecting other invalid props. */ type AllowedProps<T extends Component> = ComponentProps<T> & { [key: `data-${string}`]: unknown; }; type ForbidExtraProps<T extends Component, P> = { [K in keyof P as K extends keyof AllowedProps<T> ? never : K]: never; }; export type OnlyValidProps<T extends Component, P> = P extends AllowedProps<T> ? P & ForbidExtraProps<T, P> : AllowedProps<T>; /** * Recursively applies `OnlyValidProps` to each style object within the variants structure `V`. * Ensures that all properties defined within the variants are valid for the component `T`. * * @template T The type of the base component. * @template V The type of the `variants` section of the configuration object. */ export type ValidatedVariants<T extends Component, V> = V extends object ? { [VK in keyof V]: VK extends string ? { [SK in keyof V[VK]]: SK extends string ? OnlyValidProps<T, V[VK][SK]> : never; } : never; } : V; /** * Defines the expected type for the `defaultVariants` section and improves IntelliSense. * For each variant key `K` in `V`, the expected value is the union of style keys (`keyof V[K]`) * If the style keys are 'true' | 'false', the expected type is `boolean`. * * @template V The type of the `variants` section of the configuration object. */ export type ValidatedDefaultVariants<V> = V extends object ? { [K in keyof V]?: keyof V[K] extends 'true' | 'false' ? boolean : keyof V[K]; } : {}; /** * Defines the structure and expected types for the CONDITIONS of a `compoundVariants` item. * Based on the keys and values defined in the `variants` section (`V`). * Improves IntelliSense when defining conditions. * * @template V The type of the `variants` section of the configuration object. */ export type CompoundVariantConditions<V> = V extends object ? { [K in keyof V]?: keyof V[K] extends 'true' | 'false' ? boolean : keyof V[K]; } : {}; /** * Validates a SINGLE item within the `compoundVariants` array. * PRIORITIZES IntelliSense for props, sacrificing local validation on them. */ export type ValidatedCompoundVariantItem<T extends Component, V, Item extends object> = CompoundVariantConditions<V> & // 1. Apply expected conditions (Item extends { props: infer P; } ? { props?: Partial<ComponentProps<T>>; } : { props?: never; }) & { [K in keyof Item as K extends keyof V | 'props' ? never : K]?: never; } & Item; type ValidatedCompoundVariants<T extends Component, V, CV> = CV extends ReadonlyArray<infer Item extends object> ? ReadonlyArray<ValidatedCompoundVariantItem<T, V, Item>> : CV; /** * Defines the expected structure of the debug configuration. */ export type DebugConfig = { name?: string; debug?: boolean; }; /** * Validates the complete structure of the configuration object `C` against the component `T`. * Applies specific validations for `base`, `variants`, `defaultVariants`, and `compoundVariants`. * Uses conditional types to handle the optional absence of `defaultVariants` or `compoundVariants`. * * @template T The type of the base component. * @template C The literal type of the complete configuration object passed. */ export type ConfigSchema<T extends Component, C extends Config> = C extends { base?: infer B; variants?: infer V; defaultVariants?: infer DV; compoundVariants?: infer CompV; } ? { base?: OnlyValidProps<T, B>; variants?: ValidatedVariants<T, V>; defaultVariants?: DV & ValidatedDefaultVariants<V> & { [KDV in keyof DV as KDV extends keyof V ? never : KDV]?: never; }; compoundVariants?: ValidatedCompoundVariants<T, V, CompV>; } : C extends { base?: infer B; variants?: infer V; defaultVariants?: infer DV; } ? { base?: OnlyValidProps<T, B>; variants?: ValidatedVariants<T, V>; defaultVariants?: DV & ValidatedDefaultVariants<V> & { [KDV in keyof DV as KDV extends keyof V ? never : KDV]?: never; }; } : C extends { base?: infer B; variants?: infer V; compoundVariants?: infer CompV; } ? { base?: OnlyValidProps<T, B>; variants?: ValidatedVariants<T, V>; compoundVariants?: ValidatedCompoundVariants<T, V, CompV>; } : C extends { base?: infer B; variants?: infer V; } ? { base?: OnlyValidProps<T, B>; variants?: ValidatedVariants<T, V>; } : { base?: unknown; variants?: unknown; }; /** * Calculates the type of the properties representing the active variants. * Based on the `variants` section of the configuration object `C`. * If a variant has keys 'true'|'false', the resulting type is `boolean`. * * @template C The literal type of the complete configuration object passed. */ export type CalculateVariantProps<C extends Config> = C extends { variants?: infer V; } ? V extends object ? { [K in keyof V]?: keyof V[K] extends 'true' | 'false' ? boolean : keyof V[K]; } : {} : {}; /** * Calculates the final props type for the styled component returned by `useStyled`. * Combines the original props of the base component `T` (omitting collisions with variant names) * with the calculated variant properties (`CalculateVariantProps`) and adds `ref`. * * @template T The type of the base component. * @template C The literal type of the complete configuration object passed. */ export type FinalProps<T extends Component, C extends Config> = RefAttributes<ComponentProps<T>['ref'] extends React.Ref<infer RefType> ? RefType : unknown> & Omit<ComponentProps<T>, keyof CalculateVariantProps<C>> & CalculateVariantProps<C>; /** * Defines the generic type for the final component returned by `useStyled`. * It is a `ComponentType` (from React) whose props are defined by `FinalProps`, * using the specific types `T` (base component) and `C` (configuration) provided. * * @template T The type of the base component. * @template C The literal type of the complete configuration object passed. */ export type StyledComponent<T extends Component, C extends Config> = ComponentType<FinalProps<T, C>>; //# sourceMappingURL=types.d.ts.map