UNPKG

tailwind-variants

Version:

🦄 Tailwindcss first-class variant API

341 lines (304 loc) • 10.2 kB
import type {ClassNameValue as ClassValue} from "tailwind-merge"; import {TVConfig, TWMConfig} from "./config"; /** * ---------------------------------------- * Base Types * ---------------------------------------- */ export type {ClassValue}; export type ClassProp<V extends unknown = ClassValue> = | {class?: V; className?: never} | {class?: never; className?: V}; type TVBaseName = "base"; type TVScreens = "initial"; type TVSlots = Record<string, ClassValue> | undefined; /** * ---------------------------------------------------------------------- * Utils * ---------------------------------------------------------------------- */ export type OmitUndefined<T> = T extends undefined ? never : T; export type StringToBoolean<T> = T extends "true" | "false" ? boolean : T; export type CnOptions = ClassValue[]; export type CnReturn = string | undefined; export declare const cnBase: <T extends CnOptions>(...classes: T) => CnReturn; export declare const cn: <T extends CnOptions>(...classes: T) => (config?: TWMConfig) => CnReturn; // compare if the value is true or array of values export type isTrueOrArray<T> = T extends true | unknown[] ? true : false; export type WithInitialScreen<T extends Array<string>> = ["initial", ...T]; /** * ---------------------------------------------------------------------- * TV Types * ---------------------------------------------------------------------- */ type TVSlotsWithBase<S extends TVSlots, B extends ClassValue> = B extends undefined ? keyof S : keyof S | TVBaseName; type SlotsClassValue<S extends TVSlots, B extends ClassValue> = { [K in TVSlotsWithBase<S, B>]?: ClassValue; }; type TVVariantsDefault<S extends TVSlots, B extends ClassValue> = S extends undefined ? {} : { [key: string]: { [key: string]: S extends TVSlots ? SlotsClassValue<S, B> | ClassValue : ClassValue; }; }; export type TVVariants< S extends TVSlots | undefined, B extends ClassValue | undefined = undefined, EV extends TVVariants<ES> | undefined = undefined, ES extends TVSlots | undefined = undefined, > = EV extends undefined ? TVVariantsDefault<S, B> : | { [K in keyof EV]: { [K2 in keyof EV[K]]: S extends TVSlots ? SlotsClassValue<S, B> | ClassValue : ClassValue; }; } | TVVariantsDefault<S, B>; export type TVCompoundVariants< V extends TVVariants<S>, S extends TVSlots, B extends ClassValue, EV extends TVVariants<ES>, ES extends TVSlots, > = Array< { [K in keyof V | keyof EV]?: | (K extends keyof V ? StringToBoolean<keyof V[K]> : never) | (K extends keyof EV ? StringToBoolean<keyof EV[K]> : never) | (K extends keyof V ? StringToBoolean<keyof V[K]>[] : never); } & ClassProp<SlotsClassValue<S, B> | ClassValue> >; export type TVCompoundSlots< V extends TVVariants<S>, S extends TVSlots, B extends ClassValue, > = Array< V extends undefined ? { slots: Array<TVSlotsWithBase<S, B>>; } & ClassProp : { slots: Array<TVSlotsWithBase<S, B>>; } & { [K in keyof V]?: StringToBoolean<keyof V[K]> | StringToBoolean<keyof V[K]>[]; } & ClassProp >; export type TVDefaultVariants< V extends TVVariants<S>, S extends TVSlots, EV extends TVVariants<ES>, ES extends TVSlots, > = { [K in keyof V | keyof EV]?: | (K extends keyof V ? StringToBoolean<keyof V[K]> : never) | (K extends keyof EV ? StringToBoolean<keyof EV[K]> : never); }; export type TVScreenPropsValue<V extends TVVariants<S>, S extends TVSlots, K extends keyof V> = { [Screen in TVScreens]?: StringToBoolean<keyof V[K]>; }; export type TVProps< V extends TVVariants<S>, S extends TVSlots, EV extends TVVariants<ES>, ES extends TVSlots, > = EV extends undefined ? V extends undefined ? ClassProp<ClassValue> : { [K in keyof V]?: StringToBoolean<keyof V[K]> | undefined; } & ClassProp<ClassValue> : V extends undefined ? { [K in keyof EV]?: StringToBoolean<keyof EV[K]> | undefined; } & ClassProp<ClassValue> : { [K in keyof V | keyof EV]?: | (K extends keyof V ? StringToBoolean<keyof V[K]> : never) | (K extends keyof EV ? StringToBoolean<keyof EV[K]> : never) | undefined; } & ClassProp<ClassValue>; export type TVVariantKeys<V extends TVVariants<S>, S extends TVSlots> = V extends Object ? Array<keyof V> : undefined; export type TVReturnProps< V extends TVVariants<S>, S extends TVSlots, B extends ClassValue, EV extends TVVariants<ES>, ES extends TVSlots, // @ts-expect-error E extends TVReturnType = undefined, > = { extend: E; base: B; slots: S; variants: V; defaultVariants: TVDefaultVariants<V, S, EV, ES>; compoundVariants: TVCompoundVariants<V, S, B, EV, ES>; compoundSlots: TVCompoundSlots<V, S, B>; variantKeys: TVVariantKeys<V, S>; }; type HasSlots<S extends TVSlots, ES extends TVSlots> = S extends undefined ? ES extends undefined ? false : true : true; export type TVReturnType< V extends TVVariants<S>, S extends TVSlots, B extends ClassValue, EV extends TVVariants<ES>, ES extends TVSlots, // @ts-expect-error E extends TVReturnType = undefined, > = { (props?: TVProps<V, S, EV, ES>): HasSlots<S, ES> extends true ? { [K in keyof (ES extends undefined ? {} : ES)]: ( slotProps?: TVProps<V, S, EV, ES>, ) => string; } & { [K in keyof (S extends undefined ? {} : S)]: (slotProps?: TVProps<V, S, EV, ES>) => string; } & { [K in TVSlotsWithBase<{}, B>]: (slotProps?: TVProps<V, S, EV, ES>) => string; } : string; } & TVReturnProps<V, S, B, EV, ES, E>; export type TV = { < V extends TVVariants<S, B, EV>, CV extends TVCompoundVariants<V, S, B, EV, ES>, DV extends TVDefaultVariants<V, S, EV, ES>, B extends ClassValue = undefined, S extends TVSlots = undefined, // @ts-expect-error E extends TVReturnType = TVReturnType< V, S, B, // @ts-expect-error EV extends undefined ? {} : EV, // @ts-expect-error ES extends undefined ? {} : ES >, EV extends TVVariants<ES, B, E["variants"], ES> = E["variants"], ES extends TVSlots = E["slots"] extends TVSlots ? E["slots"] : undefined, >( options: { /** * Extend allows for easy composition of components. * @see https://www.tailwind-variants.org/docs/composing-components */ extend?: E; /** * Base allows you to set a base class for a component. */ base?: B; /** * Slots allow you to separate a component into multiple parts. * @see https://www.tailwind-variants.org/docs/slots */ slots?: S; /** * Variants allow you to create multiple versions of the same component. * @see https://www.tailwind-variants.org/docs/variants#adding-variants */ variants?: V; /** * Compound variants allow you to apply classes to multiple variants at once. * @see https://www.tailwind-variants.org/docs/variants#compound-variants */ compoundVariants?: CV; /** * Compound slots allow you to apply classes to multiple slots at once. */ compoundSlots?: TVCompoundSlots<V, S, B>; /** * Default variants allow you to set default variants for a component. * @see https://www.tailwind-variants.org/docs/variants#default-variants */ defaultVariants?: DV; }, /** * The config object allows you to modify the default configuration. * @see https://www.tailwind-variants.org/docs/api-reference#config-optional */ config?: TVConfig, ): TVReturnType<V, S, B, EV, ES, E>; }; export type CreateTV = { < V extends TVVariants<S, B, EV>, CV extends TVCompoundVariants<V, S, B, EV, ES>, DV extends TVDefaultVariants<V, S, EV, ES>, B extends ClassValue = undefined, S extends TVSlots = undefined, // @ts-expect-error E extends TVReturnType = TVReturnType< V, S, B, // @ts-expect-error EV extends undefined ? {} : EV, // @ts-expect-error ES extends undefined ? {} : ES >, EV extends TVVariants<ES, B, E["variants"], ES> = E["variants"], ES extends TVSlots = E["slots"] extends TVSlots ? E["slots"] : undefined, >( options: { /** * Extend allows for easy composition of components. * @see https://www.tailwind-variants.org/docs/composing-components */ extend?: E; /** * Base allows you to set a base class for a component. */ base?: B; /** * Slots allow you to separate a component into multiple parts. * @see https://www.tailwind-variants.org/docs/slots */ slots?: S; /** * Variants allow you to create multiple versions of the same component. * @see https://www.tailwind-variants.org/docs/variants#adding-variants */ variants?: V; /** * Compound variants allow you to apply classes to multiple variants at once. * @see https://www.tailwind-variants.org/docs/variants#compound-variants */ compoundVariants?: CV; /** * Compound slots allow you to apply classes to multiple slots at once. */ compoundSlots?: TVCompoundSlots<V, S, B>; /** * Default variants allow you to set default variants for a component. * @see https://www.tailwind-variants.org/docs/variants#default-variants */ defaultVariants?: DV; }, /** * The config object allows you to modify the default configuration. * @see https://www.tailwind-variants.org/docs/api-reference#config-optional */ config?: TVConfig, ): TVReturnType<V, S, B, EV, ES, E>; }; // main function export declare const tv: TV; export declare function createTV(config: TVConfig): CreateTV; export declare const defaultConfig: TVConfig; export type VariantProps<Component extends (...args: any) => any> = Omit< OmitUndefined<Parameters<Component>[0]>, "class" | "className" >;