UNPKG

react-tailwind-variants

Version:

React Stitches-like variants API for tailwindcss classes

112 lines (106 loc) 5.61 kB
import * as react from 'react'; import { ForwardRefExoticComponent, ElementType, JSX, ComponentPropsWithoutRef, ComponentRef } from 'react'; /** * This is a modified version of the `classname-variants` * See https://github.com/fgnass/classname-variants/ */ type PickRequiredKeys<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? never : K; }[keyof T]; type OmitByValue<T, Value> = { [P in keyof T as T[P] extends Value ? never : P]: T[P]; }; type StringToBoolean<T> = T extends 'true' | 'false' ? boolean : T; type Simplify<T> = { [KeyType in keyof T]: T[KeyType]; }; type ClassNameValue = string | null | undefined | ClassNameValue[]; /** * Definition of the available variants and their options. * @example * { * color: { * white: "bg-white" * green: "bg-green-500", * }, * size: { * small: "text-xs", * large: "text-lg" * } * } */ type VariantsSchema = Record<string, Record<string, ClassNameValue>>; type VariantsConfig<V extends VariantsSchema> = { base?: ClassNameValue; variants?: V; defaultVariants?: keyof V extends never ? Record<string, never> : Partial<Variants<V>>; compoundVariants?: keyof V extends never ? never[] : CompoundVariant<V>[]; }; /** * Rules for class names that are applied for certain variant combinations. */ interface CompoundVariant<V extends VariantsSchema> { variants: Partial<VariantsMulti<V>>; className: ClassNameValue; } type Variants<V extends VariantsSchema> = { [Variant in keyof V]: StringToBoolean<keyof V[Variant]>; }; type VariantsMulti<V extends VariantsSchema> = { [Variant in keyof V]: StringToBoolean<keyof V[Variant]> | StringToBoolean<keyof V[Variant]>[]; }; /** * Only the boolean variants, i.e. ones that have "true" or "false" as options. */ type BooleanVariants<C extends VariantsConfig<V>, V extends VariantsSchema = NonNullable<C['variants']>> = { [Variant in keyof V as V[Variant] extends { true: any; } | { false: any; } ? Variant : never]: V[Variant]; }; /** * Only the variants for which a default options is set. */ type DefaultVariants<C extends VariantsConfig<V>, V extends VariantsSchema = NonNullable<C['variants']>> = { [Variant in keyof V as Variant extends keyof OmitByValue<C['defaultVariants'], undefined> ? Variant : never]: V[Variant]; }; /** * Names of all optional variants, i.e. booleans or ones with default options. */ type OptionalVariantNames<C extends VariantsConfig<V>, V extends VariantsSchema = NonNullable<C['variants']>> = keyof BooleanVariants<C, V> | keyof DefaultVariants<C, V>; /** * Extracts the possible options. */ type VariantOptions<C extends VariantsConfig<V>, V extends VariantsSchema = NonNullable<C['variants']>> = keyof V extends never ? {} : Required<Omit<Variants<V>, OptionalVariantNames<C, V>>> & Partial<Pick<Variants<V>, OptionalVariantNames<C, V>>>; type VariantsHandlerFn<P> = PickRequiredKeys<P> extends never ? (props?: P) => string : (props: P) => string; declare function variants<C extends VariantsConfig<V>, V extends VariantsSchema = NonNullable<C['variants']>>(config: Simplify<C>): VariantsHandlerFn<VariantOptions<C, NonNullable<C["variants"]>> & { className?: ClassNameValue; }>; type CxOptions = ClassNameValue[]; type CxReturn = string; declare const cx: <T extends CxOptions>(...classes: T) => CxReturn; declare const StyledComponentConfigKey = "$$tailwindVariantsConfig"; interface StyledComponentConfigProp<C extends VariantsConfig<any>> { readonly [StyledComponentConfigKey]: C; } type StyledComponent<ForwardRefComponent extends ForwardRefExoticComponent<any>, C extends VariantsConfig<any>> = ForwardRefComponent & StyledComponentConfigProp<C>; declare function variantProps<C extends VariantsConfig<V>, V extends VariantsSchema = NonNullable<C['variants']>>(config: Simplify<C>): <P extends VariantOptions<C> & { className?: string; }>(props: P) => { className: string; } & Omit<P, "className" | keyof VariantOptions<C>>; type SlottableProps<T extends ElementType, P> = T extends keyof JSX.IntrinsicElements ? Omit<P, 'asChild'> & { asChild?: boolean; } : P; declare function styled<T extends ElementType, C extends VariantsConfig<V>, V extends VariantsSchema = NonNullable<C['variants']>>(baseType: T, config: Simplify<C>): StyledComponent<ForwardRefExoticComponent<react.PropsWithoutRef<SlottableProps<T, VariantOptions<C> & Omit<ComponentPropsWithoutRef<T>, keyof VariantOptions<C>>>> & react.RefAttributes<ComponentRef<T>>>, typeof config>; type VariantsConfigOf<Component extends StyledComponent<ForwardRefExoticComponent<any>, C>, C extends VariantsConfig<V> = Component[typeof StyledComponentConfigKey], V extends VariantsSchema = NonNullable<C['variants']>> = C; type VariantPropsOf<Component extends StyledComponent<ForwardRefExoticComponent<any>, C>, C extends VariantsConfig<V> = Component[typeof StyledComponentConfigKey], V extends VariantsSchema = NonNullable<C['variants']>> = VariantOptions<C>; declare function extractVariantsConfig<C extends VariantsConfig<V>, V extends VariantsSchema = NonNullable<C['variants']>>(styledComponent: StyledComponent<ForwardRefExoticComponent<any>, C>): C; /** * No-op function to mark template literals as tailwind strings. */ declare const tw: (template: { raw: readonly string[] | ArrayLike<string>; }, ...substitutions: any[]) => string; export { type CxOptions, type CxReturn, type StyledComponent, type VariantOptions, type VariantPropsOf, type VariantsConfig, type VariantsConfigOf, type VariantsSchema, cx, extractVariantsConfig, styled, tw, variantProps, variants };