@use-pico/cls
Version:
Type-safe, composable styling system for React, Vue, Svelte, and vanilla JS
866 lines (838 loc) • 36.2 kB
TypeScript
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 };