react-tailwind-variants
Version:
React Stitches-like variants API for tailwindcss classes
112 lines (106 loc) • 5.61 kB
TypeScript
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 };