UNPKG

@use-pico/cls

Version:

Type-safe, composable styling system for React, Vue, Svelte, and vanilla JS

866 lines (838 loc) 36.2 kB
import { ClassNameValue } from 'tailwind-merge'; import { PropsWithChildren, JSX, DependencyList } from 'react'; import * as react_jsx_runtime from 'react/jsx-runtime'; /** * Type alias for CSS class names, re-exported from tailwind-merge for consistency */ type ClassName = ClassNameValue; /** * What namespace - creates typesafe way to tell "what" we're using to style. * * This namespace is used to create typesafe way how to tell "what" we're using to style * (e.g. css or tokens). Provides utilities for specifying styling approaches and values. */ declare namespace What { /** * CSS class-based styling value. * * Represents styling using traditional CSS class names. */ interface Class { /** CSS class name for styling */ class: ClassName; } /** * Token-based styling value. * * Represents styling using design tokens from the contract. * * @template TContract - The contract type containing the tokens */ type Token<TContract extends Contract.Any> = { /** Array of optional tokens for styling */ token: Token.Raw<TContract>[]; }; /** * Union type for any styling value. * * Can be either CSS class-based or token-based styling. * * @template TContract - The contract type for token-based styling */ type Any<TContract extends Contract.Any> = Class | Token<TContract>; /** * Union type for styling values with override support. * * Can be either CSS class-based or token-based styling with override behavior. * This type is used for slot-level What values where override behavior is meaningful. * * @template TContract - The contract type for token-based styling */ type AnyOverride<TContract extends Contract.Any> = (Class | Token<TContract>) & { /** * If specified, this What will override the previous value (regardless of * What was set - class or token). */ override?: boolean; }; } /** * Namespace for token-related types and utilities */ declare namespace Token { /** * Base token type - array of token names */ type Type = readonly string[]; /** * Extracts all token names from a contract and its inheritance chain */ type Raw<TContract extends Contract.Any> = TContract extends { "~use"?: infer TUse; } ? TUse extends Contract.Any ? TContract["tokens"][number] | Raw<TUse> : TContract["tokens"][number] : TContract["tokens"][number]; /** * Check local presence of tokens */ type Has<TContract extends Contract.Any> = TContract["tokens"][number] extends never ? false : true; /** * Check presence of tokens in the inheritance chain */ type With<TContract extends Contract.Any> = Raw<TContract> extends never ? false : true; /** * Extended token definitions that handle both required and optional tokens */ type Required<TContract extends Contract.Any> = Has<TContract> extends false ? Optional<TContract> : Optional<TContract> & { [K in TContract["tokens"][number]]: What.Any<TContract>; }; /** * Optional token definitions for inherited tokens */ type Optional<TContract extends Contract.Any> = Partial<{ [K in Raw<TContract>]: What.Any<TContract>; }>; } /** * Namespace for general utility types used throughout the CLS system */ declare namespace Utils { /** * Converts the string "bool" to boolean type, otherwise preserves the string type * Used for variant value type mapping where "bool" represents boolean variants */ type Value<T extends string> = T extends "bool" ? boolean : T; /** * Utility type to deduplicate array elements at the type level */ type Dedupe<T extends readonly any[]> = T extends readonly [ infer Head, ...infer Tail ] ? Head extends Tail[number] ? Dedupe<Tail> : [ Head, ...Dedupe<Tail> ] : []; /** * Merges two arrays and deduplicates the result */ type DedupeConcat<A extends readonly any[], B extends readonly any[]> = Dedupe<[ ...A, ...B ]>; /** * Merges two record types by combining their array values with deduplication * Used for merging variant contracts in inheritance chains */ type Merge<A extends Record<string, readonly any[]>, B extends Record<string, readonly any[]>> = { [K in keyof A | keyof B]: K extends keyof B ? K extends keyof A ? Dedupe<[ ...A[K], ...B[K] ]> : B[K] : K extends keyof A ? A[K] : never; }; } /** * Namespace for variant-related types and utilities */ declare namespace Variant { /** * Base variant contract type that defines the structure of variant names and their allowed values */ type Type = Record<string, readonly string[]>; /** * Extracts all variants from inheritance chain and builds merged result of the chain, * providing variant name as property and values are all available variants. * This is raw input (no value translation done). * * This utility type recursively traverses the inheritance chain (via the "~use" property) * and merges all variant contracts into a single, flattened variant contract. The result * contains the raw variant definitions as they were declared, without any value type * transformations. * * @template TContract - The contract type to extract variants from * @returns A merged variant contract containing all variants from the inheritance chain */ type Raw<TContract extends Contract.Any> = TContract extends { variant: infer V extends Type; "~use"?: infer U; } ? U extends Contract.Any ? Utils.Merge<Raw<U>, V> : V : Record<string, never>; /** * Check if any variants are present in the contract only */ type Has<TContract extends Contract.Any> = keyof TContract["variant"] extends never ? false : true; /** * Check if any variants are present in the inheritance chain */ type With<TContract extends Contract.Any> = keyof Raw<TContract> extends never ? false : true; /** * Extracts all variants from inheritance chain and builds an object with "bool" variants * translated to literal booleans and values mapped to individual object properties. * * This utility type recursively traverses the inheritance chain to collect all variant * definitions, then creates a type-safe object where each variant name becomes a property * with its corresponding value type. Boolean variants (defined with "bool") are mapped * to the `boolean` type, while other variants are mapped to their string literal union types. * * @template TContract - The contract type to extract variant value mappings from * @returns A mapping of variant names to their resolved value types */ type VariantOf<TContract extends Contract.Any> = { [K in keyof Raw<TContract>]: Utils.Value<Raw<TContract>[K][number]>; }; type Required<TContract extends Contract.Any> = With<TContract> extends false ? Record<string, never> : VariantOf<TContract>; type Optional<TContract extends Contract.Any> = With<TContract> extends false ? Record<string, never> : Partial<VariantOf<TContract>>; } /** * Tweak - Overall tool to adjust already existing "cls" instance. * * Provides a way to modify cls instances during creation or on slot usage. * Allows fine-tuning of variants, slots, overrides, and tokens in a type-safe manner. */ declare namespace Tweak { /** * The tweak type itself holding stuff user can tweak (change). * * Defines the structure of modifications that can be applied to a cls instance. * All properties are optional, allowing partial modifications. * * @template TContract - The contract type to tweak */ type Type<TContract extends Contract.Any> = { /** * When set to true, this tweak will override the previous tweak(s). * * From user's perspective this allows to brute force user's tweak. */ override?: boolean; /** * Brute force - kills previous tweaks and set this as a new baseline. */ clear?: boolean; /** Optional variant modifications */ variant?: Variant.Optional<TContract>; /** Optional slot modifications */ slot?: Slot.Optional<TContract>; /** Optional token modifications */ token?: Token.Optional<TContract>; }; /** * Tweaks are used as an input to make... a tweak */ type Tweaks<TContract extends Contract.Any> = (Tweak.Type<TContract> | Tweaks<TContract> | undefined)[] | Tweak.Type<TContract> | undefined; type TweaksFn<TContract extends Contract.Any> = (...tweaks: Tweak.Tweaks<TContract>[]) => Tweak.Type<TContract>; } /** * Namespace for slot-related types and utilities */ declare namespace Slot { /** * Base slot contract type that defines the structure of slot names */ type Type = readonly string[]; /** * Extracts all slot names from a contract and its inheritance chain. * * This utility type recursively traverses the inheritance chain (via the "~use" property) * and extracts all slot names from the current contract and all parent contracts. * This provides a complete view of all available slots in the inheritance chain. * * @template TContract - The contract type to extract slot names from * @returns A union type of all slot names from the inheritance chain */ type Raw<TContract extends Contract.Any> = TContract extends { "~use"?: infer U; } ? U extends Contract.Any ? TContract["slot"][number] | Raw<U> : TContract["slot"][number] : TContract["slot"][number]; type Has<TContract extends Contract.Any> = TContract["slot"][number] extends never ? false : true; type With<TContract extends Contract.Any> = Raw<TContract> extends never ? false : true; /** * Mapping type for slot styling values */ type SlotOf<TContract extends Contract.Any> = { [K in Raw<TContract>]?: What.AnyOverride<TContract>; }; type Required<TContract extends Contract.Any> = With<TContract> extends false ? Record<string, never> : SlotOf<TContract>; type RequiredFn<TContract extends Contract.Any> = (slot: Required<TContract>) => Required<TContract>; type Optional<TContract extends Contract.Any> = With<TContract> extends false ? Record<string, never> : Partial<SlotOf<TContract>>; type OptionalFn<TContract extends Contract.Any> = (slot: Optional<TContract>) => Optional<TContract>; /** * Function type for individual slot functions that return CSS class strings */ type Fn<TContract extends Contract.Any> = (...tweak: Tweak.Tweaks<TContract>[]) => string; /** * Object type containing all slot functions for a contract * * This type is directly facing an user when using the cls instance. */ type Kit<TContract extends Contract.Any> = { [K in Raw<TContract>]: Fn<TContract>; }; } /** * Namespace for contract-related types and utilities */ declare namespace Contract { /** * Base contract type that defines the structure of a CLS contract */ type Type<TToken extends Token.Type, TSlot extends Slot.Type, TVariant extends Variant.Type, TUse extends Any | unknown = unknown> = { tokens: TToken; slot: TSlot; variant: TVariant; "~use"?: TUse; "~definition"?: unknown; }; /** * Contract type with any generics for flexible usage */ type Any = Type<any, any, any>; } /** * Namespace for type-level conditional checks */ declare namespace Check { /** * Type-level utility to check if a condition is met */ type If<TRequired extends boolean, TFulfilled extends boolean | undefined> = TRequired extends true ? TFulfilled extends true ? true : false : true; /** * Type-level utility to check if ALL requirements in an array are true (AND logic) */ type Each<TChecks extends readonly boolean[]> = TChecks extends readonly [ infer First, ...infer Rest ] ? First extends true ? Rest extends readonly boolean[] ? Each<Rest> : true : false : true; /** * Type-level utility to check if ANY requirement in an array is true (OR logic) */ type Some<TChecks extends readonly boolean[]> = TChecks extends readonly [ infer First, ...infer Rest ] ? First extends true ? true : Rest extends readonly boolean[] ? Some<Rest> : false : false; } /** * Namespace for rule-related types and utilities */ declare namespace Rule { type Type<TContract extends Contract.Any> = { override?: boolean; match?: Variant.Optional<TContract>; slot?: Slot.Optional<TContract>; token?: Token.Optional<TContract>; }; } /** * Namespace for definition-related types and utilities */ declare namespace Definition { /** * Complete styling definition that provides concrete values for a CLS contract. * * This type represents the implementation of a CLS contract, containing all the * styling values, rules, and defaults that determine how a component is actually * styled. It's returned by definition functions and used internally by CLS instances * to generate styled components. * * @template T - The contract type that defines the structure (tokens, slots, variants) */ type Type<T extends Contract.Any> = { token: Token.Required<T>; rules: Rule.Type<T>[]; defaults: Variant.VariantOf<T>; }; } /** * Namespace for CLS helper types */ declare namespace Cls { /** * Various interesting things returned from the create method */ interface Kit<TContract extends Contract.Any> { /** * Slots for your component(s) to style */ slots: Slot.Kit<TContract>; /** * Resolved variants - if you need to access them as a single source of truth, * this is the way. */ variant: Variant.VariantOf<TContract>; } interface Type<TContract extends Contract.Any> { create(...tweak: Tweak.Tweaks<TContract>[]): Kit<TContract>; extend<const TToken extends Token.Type, const TSlot extends Slot.Type, const TVariant extends Variant.Type>(contract: Contract.Type<TToken, TSlot, TVariant, TContract>, definition: Definition.Type<Contract.Type<TToken, TSlot, TVariant, TContract>>): Type<Contract.Type<TToken, TSlot, TVariant, TContract>>; use<Sub extends Contract.Any>(sub: Type<Sub> & { contract: IsChildrenOf<Sub, TContract> extends true ? unknown : [ "❌ Not derived from Base contract", { sub: Sub; base: TContract; } ]; }): Type<TContract>; tweak<Sub extends Contract.Any = TContract>(...tweak: { hack: Tweak.Tweaks<IsChildrenOf<Sub, TContract> extends true ? Sub : never>; }["hack"][]): Tweak.Type<TContract> | undefined; contract: TContract; definition: Definition.Type<TContract>; } /** * Checks if a contract type has a specific base type in its inheritance chain * Used for validating contract inheritance relationships * * @template TChildren - The child contract to check * @template TAncestor - The ancestor contract to look for * @returns true if TChildren extends TAncestor, false otherwise */ type IsChildrenOf<TChildren, TAncestor> = TChildren extends TAncestor ? true : TChildren extends { "~use"?: infer U; } ? IsChildrenOf<U, TAncestor> : false; /** * Extracts the slot functions type from a CLS instance for use in component props */ type SlotsOf<TCls extends Type<any>> = Slot.Kit<TCls["contract"]>; type VariantOf<TCls extends Type<any>, TVariant extends keyof Variant.Raw<TCls["contract"]>> = Variant.Raw<TCls["contract"]>[TVariant] extends readonly (infer U extends string)[] ? Utils.Value<U> : never; type VariantsOf<TCls extends Type<any>> = Variant.Optional<TCls["contract"]>; type TweaksOf<TCls extends Type<any>> = Tweak.Tweaks<TCls["contract"]>; /** * Props are used in React components when an user wants to work with Cls. * * Provides a way to pass a Cls instance or tweak styles on an existing component. * Combines Cls-specific props with additional component props while preventing conflicts. * * @Note This type also removes "className" prop, so you'll not get surprise using it. * * @template TCls - The CLS instance type * @template P - Additional component props (defaults to unknown) */ type Props<TCls extends Type<any>, P = unknown> = { /** * Optional CLS instance to use for styling. * * If you want to replace "cls" of a component, you must extend from the component's contract, * e.g. `MyButtonCls = contract(ButtonCls.contract)` and in this prop call `cls={ButtonCls.use(MyButtonCls)}`. */ cls?: TCls; /** * Optional tweak function to modify styles on existing component */ tweak?: Tweak.Tweaks<TCls["contract"]>; } & Omit<P, "cls" | "tweak" | "className">; } /** * Builder for creating definitions with a fluent API. * Allows chaining token(), rule(), root(), and defaults() calls. */ declare namespace DefinitionBuilder { /** * Utility type: keys of variants that are declared as boolean ("bool") */ type BoolKeys<TContract extends Contract.Any> = { [K in keyof Variant.Raw<TContract>]: "bool" extends Variant.Raw<TContract>[K][number] ? K : never; }[keyof Variant.Raw<TContract>]; /** * Definition builder state that accumulates definition parts */ export interface State<TContract extends Contract.Any, TUse extends Contract.Any | unknown = unknown> { contract: TContract; token?: Token.Required<TContract>; rules: Rule.Type<TContract>[]; defaults?: Variant.VariantOf<TContract>; use?: TUse; } /** * Type-level flags to track which required methods have been called */ export interface CompletionState { hasToken?: boolean; hasDefaults?: boolean; } /** * Token method interface - only available when contract has tokens */ interface WithToken<TContract extends Contract.Any, TState extends CompletionState = {}> { /** * Set token definitions (overrides previous if called multiple times) */ token(token: Token.Required<TContract>): Builder<TContract, TState & { hasToken: true; }>; /** * Special case for setting up rules for tokens */ tokens: { /** * Add a rule (can be called multiple times, rules accumulate) */ rule(match: Variant.Optional<TContract>, token: Token.Optional<TContract>, override?: boolean): Builder<TContract, TState>; /** * Match helper (switch-like) to add a rule for a specific variant key/value. */ match<const TKey extends keyof Variant.VariantOf<TContract>, const TValue extends Variant.VariantOf<TContract>[TKey]>(key: TKey, value: TValue, token: Token.Optional<TContract>, override?: boolean): Builder<TContract, TState>; /** * Convenience helper for boolean variants. Generates two rules: * - when variant[key] is true -> applies `whenTrue` slot * - when variant[key] is false -> applies `whenFalse` slot */ switch<K extends BoolKeys<TContract>>(key: K, whenTrue: Token.Optional<TContract>, whenFalse: Token.Optional<TContract>): Builder<TContract, TState>; }; } /** * Rule method interface - only available when contract has variants */ interface WithVariant<TContract extends Contract.Any, TState extends CompletionState = {}> { /** * Add a root rule (can be called multiple times, rules accumulate) */ root(slot: Slot.Optional<TContract>, override?: boolean): Builder<TContract, TState>; /** * Add a rule (can be called multiple times, rules accumulate) */ rule(match: Variant.Optional<TContract>, slot: Slot.Optional<TContract>, override?: boolean): Builder<TContract, TState>; /** * Match helper (switch-like) to add a rule for a specific variant key/value. */ match<const TKey extends keyof Variant.VariantOf<TContract>, const TValue extends Variant.VariantOf<TContract>[TKey]>(key: TKey, value: TValue, slot: Slot.Optional<TContract>, override?: boolean): Builder<TContract, TState>; /** * Convenience helper for boolean variants. Generates two rules: * - when variant[key] is true -> applies `whenTrue` slot * - when variant[key] is false -> applies `whenFalse` slot */ switch<K extends BoolKeys<TContract>>(key: K, whenTrue: Slot.Optional<TContract>, whenFalse: Slot.Optional<TContract>): Builder<TContract, TState>; /** * Set defaults (overrides previous if called multiple times) */ defaults(defaults: Variant.VariantOf<TContract>): Builder<TContract, TState & { hasDefaults: true; }>; } interface NoTokenCls { cls(error: "There are no tokens in the contract"): never; } /** * Type to conditionally add token method based on contract capabilities */ type TokenBuilder<TContract extends Contract.Any, TState extends CompletionState = {}> = Token.With<TContract> extends true ? WithToken<TContract, TState> : { token(error: "There are no tokens in the contract"): NoTokenCls; tokens: "There are no tokens in the contract"; }; interface NoVariantCls { cls(error: "There are no variants in the contract"): never; } interface NoSlotCls { cls(error: "There are no slots in the contract"): never; } /** * Type to conditionally add variant-related methods based on contract capabilities */ type VariantBuilder<TContract extends Contract.Any, TState extends CompletionState = {}> = Variant.With<TContract> extends true ? Slot.With<TContract> extends true ? WithVariant<TContract, TState> : { root(error: "There are no slots in the contract"): NoSlotCls; rule(error: "There are no slots in the contract"): NoSlotCls; match(error: "There are no slots in the contract"): NoSlotCls; switch(error: "There are no slots in the contract"): NoSlotCls; defaults: WithVariant<TContract, TState>["defaults"]; } : Slot.With<TContract> extends true ? { root: WithVariant<TContract, TState>["root"]; rule(error: "There are no variants in the contract"): NoVariantCls; match(error: "There are no variants in the contract"): NoVariantCls; switch(error: "There are no variants in the contract"): NoVariantCls; defaults(error: "There are no variants in the contract"): NoVariantCls; } : { root(error: "There are no variants in the contract"): NoVariantCls; rule(error: "There are no variants in the contract"): NoVariantCls; match(error: "There are no variants in the contract"): NoVariantCls; switch(error: "There are no variants in the contract"): NoVariantCls; defaults(error: "There are no variants in the contract"): NoVariantCls; }; /** * Base builder type that combines all available methods based on contract capabilities */ type BaseBuilder<TContract extends Contract.Any, TState extends CompletionState = {}> = TokenBuilder<TContract, TState> & VariantBuilder<TContract, TState>; /** * Definition builder interface with fluent methods and type-level validation */ export type Builder<TContract extends Contract.Any, TState extends CompletionState = {}> = BaseBuilder<TContract, TState> & (Check.If<Token.Has<TContract>, TState["hasToken"]> extends false ? { cls(error: `Tokens are defined on a contract, but you've not called token() definition method`): never; } : {}) & (Check.If<Variant.With<TContract>, TState["hasDefaults"]> extends false ? { cls(error: `Variants are defined on a contract, but you've not called defaults() definition method`): never; } : {}) & (Check.Each<[ Check.If<Token.Has<TContract>, TState["hasToken"]>, Check.If<Variant.With<TContract>, TState["hasDefaults"]> ]> extends true ? { /** * Create the final CLS instance - only available when all required methods have been called */ cls(): Cls.Type<TContract>; } : {}); export {}; } /** * Builder for creating contracts with a fluent API. * Allows chaining token(), slot(), and variant() calls with proper type accumulation. */ declare namespace ContractBuilder { /** * State representing the accumulated contract data during building */ interface State<TToken extends Token.Type, TSlot extends Slot.Type, TVariant extends Variant.Type, TUse extends Contract.Any | unknown = unknown> { tokens: TToken; slot: TSlot; variant: TVariant; use?: TUse; } /** * Contract builder interface with fluent methods */ interface Builder<TToken extends Token.Type, TSlot extends Slot.Type, TVariant extends Variant.Type, TUse extends Contract.Any | unknown = unknown> { /** * Add multiple tokens (can be called multiple times, tokens accumulate with deduplication) */ tokens<const TNewTokens extends Token.Type>(tokens: TNewTokens): Builder<readonly [ ...TToken, ...TNewTokens ], TSlot, TVariant, TUse>; /** * Add a single token (can be called multiple times, tokens accumulate with deduplication) */ token<const TNewToken extends string>(token: TNewToken): Builder<readonly [ ...TToken, TNewToken ], TSlot, TVariant, TUse>; /** * Add multiple slots (can be called multiple times, slots accumulate with deduplication) */ slots<const TNewSlots extends Slot.Type>(slots: TNewSlots): Builder<TToken, readonly [ ...TSlot, ...TNewSlots ], TVariant, TUse>; /** * Add a single slot (can be called multiple times, slots accumulate with deduplication) */ slot<const TNewSlot extends string>(slot: TNewSlot): Builder<TToken, readonly [ ...TSlot, TNewSlot ], TVariant, TUse>; /** * Add multiple variants (can be called multiple times, variants merge) */ variants<const TNewVariants extends Variant.Type>(variants: TNewVariants): Builder<TToken, TSlot, Utils.Merge<TVariant, TNewVariants>, TUse>; /** * Add a single variant (can be called multiple times, variants merge) */ variant<const TName extends string, const TValues extends readonly string[]>(name: TName, values: TValues): Builder<TToken, TSlot, Utils.Merge<TVariant, Record<TName, TValues>>, TUse>; bool<const TName extends string>(name: TName): Builder<TToken, TSlot, Utils.Merge<TVariant, Record<TName, [ "bool" ]>>, TUse>; /** * Build the final contract with accumulated types */ build(): Contract.Type<TToken, TSlot, TVariant, TUse>; /** * Creates a definition builder for the contract */ def(): DefinitionBuilder.Builder<Contract.Type<TToken, TSlot, TVariant, TUse>, {}>; } } /** * Creates a new contract builder instance. * Provides a fluent API for building contracts with proper type accumulation. * * @example * ```typescript * const myContract = contract() * .tokens(["color.primary", "color.secondary"]) * .slots(["root", "label"]) * .variant("size", ["sm", "md", "lg"]) * .build(); * ``` */ declare function contract(): Omit<ContractBuilder.Builder<readonly [], readonly [], {}, unknown>, "build">; declare function contract<const TUse extends Contract.Any>(use: TUse): ContractBuilder.Builder<readonly [], readonly [], {}, TUse>; declare const definition: <const TContract extends Contract.Any, const TUse extends Contract.Any | unknown = unknown>(contract: TContract, use?: TUse) => DefinitionBuilder.Builder<TContract, {}>; declare function cls<const TToken extends Token.Type, const TSlot extends Slot.Type, const TVariant extends Variant.Type, const TContract extends Contract.Type<TToken, TSlot, TVariant, any>>(contract: TContract, definition: Definition.Type<TContract>): Cls.Type<TContract>; /** * TokenProvider namespace containing component and related types */ declare namespace TokenProvider { /** * Props for TokenProvider component */ interface Props<TContract extends Contract.Any> extends PropsWithChildren { /** * CLS instance to extract tokens from */ cls: Cls.Type<TContract>; } } /** * Provider component that extracts tokens from a CLS instance and provides them via context. * * This component takes a CLS instance and extracts its token definitions to provide them * to child components via TokenContext. This makes the API more intuitive as you can pass * a complete CLS instance rather than manually extracting tokens. * * @template TContract - The contract type of the CLS instance * @param cls - CLS instance to extract tokens from * @param children - Child components that will receive the token context * * @example * ```tsx * // Pass a theme CLS instance * <TokenProvider cls={ThemeCls}> * <Button>Click me</Button> * </TokenProvider> * ``` * * @example * ```tsx * // Pass a component CLS instance for token overrides * <TokenProvider cls={CustomButtonCls}> * <Button>Custom styled button</Button> * </TokenProvider> * ``` */ declare function TokenProvider<TContract extends Contract.Any>({ cls, children, }: TokenProvider.Props<TContract>): JSX.Element; /** * React hook to create a CLS kit from a cls instance, merging user tweaks with context. * * **Tweak Precedence (highest to lowest):** * 1. **User tweak** - Direct user customization passed as parameter * 2. **Context tweak** - Automatically merged from TokenContext and VariantContext * * **Context Integration:** * - Automatically subscribes to `TokenContext` for token overrides * - Automatically subscribes to `VariantContext` for variant overrides * - Context values have lower precedence than user-provided tweaks * * **Tweak Merging:** * - Uses the `tweaks()` function with parameter-based syntax * - User tweak takes precedence over context values * - Undefined values are automatically filtered out * * @template TContract - CLS contract type defining tokens, slots, and variants * @param cls - CLS instance to create kit from * @param tweaks - Optional user-provided tweak (variant/slot/token/override) * @returns A `Cls.Kit<TContract>` with slot functions (e.g., `slots.root()`) and resolved variants * * @example * ```tsx * // Basic usage with user tweak * const { slots, variant } = useCls(ButtonCls, { * variant: { size: "lg", tone: "primary" }, * slot: { root: { class: ["font-bold"] } } * }); * ``` * * @example * ```tsx * // Without user tweak - uses context only * const { slots, variant } = useCls(ButtonCls); * ``` * * @example * ```tsx * // User tweak overrides context values * const { slots, variant } = useCls(ButtonCls, { * variant: { size: "sm" } // Overrides context variant.size * }); * ``` */ declare function useCls<TContract extends Contract.Any>(cls: Cls.Type<TContract>, ...tweaks: Tweak.Tweaks<TContract>[]): Cls.Kit<TContract>; /** * Memoized version of `useCls` with explicit dependency control for performance optimization. * * **Tweak Precedence (highest to lowest):** * 1. **User tweak** - Direct user customization passed as parameter * 2. **Context tweak** - Automatically merged from TokenContext and VariantContext * * **Context Integration:** * - Automatically subscribes to `TokenContext` for token overrides * - Automatically subscribes to `VariantContext` for variant overrides * - Context values have lower precedence than user-provided tweaks * * **Memoization Control:** * - Uses `useMemo` with the provided dependency list * - Recreates the CLS kit only when dependencies change * - Essential for performance when tweaks depend on props or state * * **Tweak Merging:** * - Uses the `tweaks()` function with parameter-based syntax * - User tweak takes precedence over context values * - Undefined values are automatically filtered out * * @template TContract - CLS contract type defining tokens, slots, and variants * @param cls - CLS instance to create kit from * @param tweaks - Optional user-provided tweak (variant/slot/token/override) * @param deps - Dependency list controlling memoization (defaults to empty array) * @returns A memoized `Cls.Kit<TContract>` with slot functions (e.g., `slots.root()`) and resolved variants * * @example * ```tsx * // Basic usage with memoization based on props * const { slots, variant } = useClsMemo( * ButtonCls, * { variant: { size, tone } }, * [size, tone] // Re-memoize when size or tone changes * ); * ``` * * @example * ```tsx * // Complex tweak with multiple dependencies * const { slots, variant } = useClsMemo( * ButtonCls, * { * variant: { size, tone, disabled }, * slot: { root: { class: disabled ? ["opacity-50"] : [] } } * }, * [size, tone, disabled] // Re-memoize when any dependency changes * ); * ``` * * @example * ```tsx * // No user tweak - memoizes context-only result * const { slots, variant } = useClsMemo( * ButtonCls, * undefined, * [] // Never re-memoize (context changes handled internally) * ); * ``` */ declare function useClsMemo<TContract extends Contract.Any>(cls: Cls.Type<TContract>, tweaks?: Tweak.Tweaks<TContract>, deps?: DependencyList): Cls.Kit<TContract>; /** * Hook to access the TokenContext. * * Returns the current token tweaks provided via context, * or undefined if no provider is present. Only tokens are affected by this context. */ declare function useTokenContext(): Token.Optional<Contract.Any>; declare const useVariantContext: () => Tweak.Type<Contract.Any>["variant"]; declare namespace VariantProvider { interface Props<TContract extends Contract.Any> extends PropsWithChildren { cls: Cls.Type<TContract>; variant: Variant.Optional<TContract>; inherit?: boolean; } } declare const VariantProvider: <TContract extends Contract.Any>({ cls: _, variant, inherit, children, }: VariantProvider.Props<TContract>) => react_jsx_runtime.JSX.Element; declare namespace wrap { interface Props<TContract extends Contract.Any> { cls: Cls.Type<TContract>; } } /** * React wrapper - useful for preparing type-safe variants for React components. */ declare const wrap: <TContract extends Contract.Any>(cls: Cls.Type<TContract>) => { readonly VariantProvider: (props: Omit<VariantProvider.Props<TContract>, "cls">) => react_jsx_runtime.JSX.Element; }; declare const tvc: (...classLists: ClassNameValue[]) => string; /** * Just a true boolean. * * I don't like boolean hells, so this is a little compromise. * * You _can_ use this for rules, when you want override to keep it * explicit, purely optional for you. */ declare const OVERRIDE = true; export { Check, Cls, Contract, Definition, OVERRIDE, Rule, Slot, Token, TokenProvider, Utils, Variant, VariantProvider, What, cls, contract, definition, tvc, useCls, useClsMemo, useTokenContext, useVariantContext, wrap }; export type { ClassName };