praxis-kit 4.0.0 → 4.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,399 @@
1
+ import { ComponentType, PropsWithChildren, ReactElement, JSX, Ref, ReactNode } from 'react';
2
+ import { RequireAtLeastOne, Simplify, ReadonlyDeep, NonEmptyTuple } from 'type-fest';
3
+ import { Diagnostics, DiagnosticInput } from './_shared/diagnostics.js';
4
+
5
+ type StringMap<T = unknown> = Record<string, T>;
6
+ type AnyRecord = StringMap<unknown>;
7
+
8
+ type IntrinsicTag = keyof HTMLElementTagNameMap;
9
+
10
+ type ElementType = IntrinsicTag | (string & {});
11
+
12
+ declare const KNOWN_ARIA_ROLES: readonly ["alert", "alertdialog", "application", "article", "banner", "blockquote", "button", "caption", "cell", "checkbox", "code", "columnheader", "combobox", "complementary", "contentinfo", "definition", "deletion", "dialog", "document", "emphasis", "feed", "figure", "form", "generic", "grid", "gridcell", "group", "heading", "img", "insertion", "link", "list", "listbox", "listitem", "log", "main", "marquee", "math", "menu", "menubar", "menuitem", "menuitemcheckbox", "menuitemradio", "meter", "navigation", "none", "note", "option", "paragraph", "presentation", "progressbar", "radio", "radiogroup", "region", "row", "rowgroup", "rowheader", "scrollbar", "search", "searchbox", "separator", "slider", "spinbutton", "status", "strong", "subscript", "superscript", "switch", "tab", "table", "tablist", "tabpanel", "term", "textbox", "time", "timer", "toolbar", "tooltip", "tree", "treegrid", "treeitem"];
13
+ type KnownAriaRole = (typeof KNOWN_ARIA_ROLES)[number];
14
+
15
+ type Booleanish = boolean | 'true' | 'false';
16
+ type ClassName = string | string[];
17
+ type EmptyRecord = Record<never, never>;
18
+ type NonEmptyArray<T> = [T, ...T[]];
19
+ type Numberish = number | `${number}`;
20
+ type Primitive = string | number | boolean;
21
+ type AriaRole = KnownAriaRole | (string & {});
22
+ type IntrinsicProps = AnyRecord & {
23
+ role?: AriaRole;
24
+ };
25
+ type TagMap = Partial<Record<IntrinsicTag | (string & {}), ClassName>>;
26
+
27
+ type MinMax = {
28
+ min: number;
29
+ max: number;
30
+ };
31
+ type CardinalityInput = Partial<MinMax>;
32
+
33
+ type ChildRuleMatch<T, U extends T = T> = (child: T) => child is U;
34
+
35
+ type ChildRulePosition = 'first' | 'last' | 'any';
36
+
37
+ type ChildRuleInput<T = unknown, U extends T = T> = {
38
+ name: string;
39
+ match: ChildRuleMatch<T, U>;
40
+ cardinality?: CardinalityInput;
41
+ position?: ChildRulePosition;
42
+ /**
43
+ * Optional component-type reference for O(1) dispatch index.
44
+ * When provided for every rule, the matcher reads child.type instead of
45
+ * calling every match function on every child (O(n×m) → O(n+m)).
46
+ */
47
+ type?: unknown;
48
+ };
49
+
50
+ type ValidResult = {
51
+ valid: true;
52
+ };
53
+
54
+ type RequireAtLeastOneIfNotEmpty<T> = keyof T extends never ? EmptyRecord : RequireAtLeastOne<T>;
55
+ type CompoundVariantConditionValue<V extends VariantMap, K extends keyof V> = VariantKey<V, K> | NonEmptyArray<VariantKey<V, K>>;
56
+ type CompoundVariantConditions<V extends VariantMap> = Simplify<{
57
+ [K in keyof V]: CompoundVariantConditionValue<V, K>;
58
+ }>;
59
+ type CompoundVariantRequiredConditions<V extends VariantMap> = RequireAtLeastOneIfNotEmpty<CompoundVariantConditions<V>>;
60
+ type CompoundVariantBase<V extends VariantMap> = keyof V extends never ? EmptyRecord : CompoundVariantRequiredConditions<V>;
61
+ type CompoundVariant<V extends VariantMap> = CompoundVariantBase<V> & {
62
+ class: VariantValue;
63
+ };
64
+
65
+ interface CVACompounds<V extends VariantMap> {
66
+ compoundVariants?: readonly CompoundVariant<V>[];
67
+ }
68
+
69
+ interface CVADefaults<V extends VariantMap> {
70
+ defaultVariants?: DefaultVariants<V>;
71
+ }
72
+
73
+ interface CVAVariants<V extends VariantMap> {
74
+ variants?: V;
75
+ }
76
+
77
+ type StringToBoolean<T> = T extends 'true' | 'false' ? boolean : T;
78
+ type VariantValue = string | string[];
79
+ type VariantStates<K extends string = string> = Record<K, VariantValue>;
80
+ type VariantMap<V extends string = string, K extends string = string> = Record<V, VariantStates<K>>;
81
+ type VariantKey<V extends VariantMap, K extends keyof V> = StringToBoolean<keyof V[K] & string>;
82
+ /**
83
+ * A partial selection of variant states authored at factory definition time.
84
+ *
85
+ * Uses `keyof V[K]` directly (not `VariantKey`) so TypeScript can eagerly
86
+ * resolve the union at constraint-check time without deferred conditional types.
87
+ */
88
+ type VariantSelection<V extends VariantMap> = {
89
+ [K in keyof V]?: keyof V[K];
90
+ };
91
+ /** The full optional prop surface exposed to callers for a given variant map. */
92
+ type VariantProps<V extends VariantMap> = {
93
+ [K in keyof V]?: VariantKey<V, K>;
94
+ };
95
+ type NormalizedVariantValue<K extends string> = string extends K ? Primitive : K extends 'true' | 'false' ? Booleanish : K extends `${number}` ? Numberish : K;
96
+ type DefaultVariants<V extends VariantMap> = {
97
+ [K in keyof V]?: NormalizedVariantValue<keyof V[K] & string>;
98
+ };
99
+ /**
100
+ * A static, immutable map of named presets to partial variant selections.
101
+ *
102
+ * Presets are named bundles of variant props that callers activate by key,
103
+ * avoiding the need to repeat variant combinations at each call site.
104
+ */
105
+ type RecipeMap<V extends VariantMap = VariantMap> = Readonly<Record<string, VariantSelection<V>>>;
106
+ type RecipeTarget<TVariants extends VariantMap = VariantMap> = VariantSelection<TVariants>;
107
+ interface PolymorphicGenerics<TDefault extends ElementType = ElementType, Props extends AnyRecord = AnyRecord, Variants extends Readonly<VariantMap> = Readonly<VariantMap>, TPreset extends RecipeMap<Variants> = Readonly<EmptyRecord>, TAllowed extends ElementType = ElementType> {
108
+ default: TDefault;
109
+ props: Props;
110
+ variants: Variants;
111
+ preset: TPreset;
112
+ allowed: TAllowed;
113
+ }
114
+ type VariantsOf<T extends PolymorphicGenerics> = T['variants'];
115
+ type RecipeOf<T extends PolymorphicGenerics> = T['preset'];
116
+ type AllowedOf<T extends PolymorphicGenerics> = T['allowed'];
117
+ type DefaultOf<T extends PolymorphicGenerics> = T['default'];
118
+ type PropsOf<T extends PolymorphicGenerics> = T['props'];
119
+
120
+ interface BaseClassOptions {
121
+ baseClassName?: ClassName;
122
+ }
123
+
124
+ type ClassPipelineFn = (tag: unknown, props: AnyRecord, className?: ClassName, recipe?: string) => string;
125
+
126
+ interface RecipeOptions<TVariants extends VariantMap = VariantMap> {
127
+ recipeMap?: Record<string, RecipeTarget<TVariants>>;
128
+ }
129
+
130
+ interface TagMapOptions {
131
+ tagMap?: TagMap;
132
+ }
133
+
134
+ type CompositionOptions<TVariants extends VariantMap = VariantMap> = Simplify<TagMapOptions & RecipeOptions<TVariants>>;
135
+
136
+ type CVASystemOptions<TVariants extends VariantMap = VariantMap> = Simplify<CVAVariants<TVariants> & CVADefaults<TVariants> & CVACompounds<TVariants>>;
137
+
138
+ type StyleOptions<TVariants extends VariantMap = VariantMap> = Simplify<BaseClassOptions & CVASystemOptions<TVariants>>;
139
+
140
+ type ClassPipelineOptions<TVariants extends VariantMap = VariantMap> = Simplify<StyleOptions<TVariants> & CompositionOptions<TVariants>>;
141
+
142
+ type OwnedPropKeys = ReadonlySet<string>;
143
+
144
+ type ClassPlugin<TProps extends AnyRecord = EmptyRecord> = Readonly<{
145
+ pipeline: ClassPipelineFn;
146
+ ownedKeys?: OwnedPropKeys;
147
+ readonly _pluginProps?: TProps;
148
+ }>;
149
+
150
+ type ClassPluginFactory<TProps extends AnyRecord = EmptyRecord> = <V extends VariantMap>(options: ClassPipelineOptions<V>, diagnostics: Diagnostics) => ClassPlugin<TProps>;
151
+ type ExtractPluginProps<TPlugin extends ClassPluginFactory<AnyRecord> | undefined> = TPlugin extends ClassPluginFactory<infer T> ? string extends keyof T ? EmptyRecord : T : EmptyRecord;
152
+
153
+ type AriaContext = {
154
+ readonly tag: IntrinsicTag;
155
+ readonly implicitRole: AriaRole | undefined;
156
+ readonly effectiveRole: string | undefined;
157
+ readonly props: ReadonlyDeep<IntrinsicProps>;
158
+ };
159
+
160
+ type RemoveAttributeFixKind = `removeAttribute:${string}`;
161
+ type InjectLiveFixKind = `injectLive:${string}`;
162
+ type FixKind = 'removeRole' | 'setRole' | 'normalizeRelevantAll' | RemoveAttributeFixKind | InjectLiveFixKind;
163
+
164
+ type AriaFixResult = {
165
+ applied: false;
166
+ next: ReadonlyDeep<IntrinsicProps>;
167
+ } | {
168
+ applied: true;
169
+ next: ReadonlyDeep<IntrinsicProps>;
170
+ previous: ReadonlyDeep<IntrinsicProps>;
171
+ };
172
+ type AriaFix = {
173
+ readonly kind: FixKind;
174
+ readonly priority?: number;
175
+ readonly source?: string;
176
+ readonly apply: (context: AriaContext) => AriaFixResult;
177
+ };
178
+
179
+ type Severity = 'error' | 'warning' | (string & {});
180
+
181
+ type AriaInvalidBase<M extends string = string> = {
182
+ valid: false;
183
+ severity: Severity;
184
+ message?: M;
185
+ attribute?: string;
186
+ diagnostic?: DiagnosticInput;
187
+ };
188
+ type AriaInvalidWithFix<M extends string = string> = AriaInvalidBase<M> & {
189
+ fixable: true;
190
+ fix: AriaFix;
191
+ };
192
+ type AriaInvalidWithoutFix<M extends string = string> = AriaInvalidBase<M> & {
193
+ fixable: false;
194
+ };
195
+ type AriaInvalidResult<M extends string = string> = AriaInvalidWithFix<M> | AriaInvalidWithoutFix<M>;
196
+ type AriaResult = ValidResult | AriaInvalidResult;
197
+
198
+ type AriaRule<C extends AriaContext = AriaContext> = (context: C) => readonly AriaResult[];
199
+
200
+ type PropNormalizer = (props: Readonly<AnyRecord & IntrinsicProps>) => Partial<AnyRecord & IntrinsicProps>;
201
+
202
+ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
203
+ readonly diagnostics?: Diagnostics;
204
+ readonly aria?: readonly AriaRule[];
205
+ readonly children?: readonly ChildRuleInput[];
206
+ readonly props?: readonly PropNormalizer[];
207
+ /** Restricts the `as` prop to this set of tags. Violations route through diagnostics. */
208
+ readonly allowedAs?: readonly TAllowed[];
209
+ };
210
+
211
+ type StylingOptions<V extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<V> = Readonly<EmptyRecord>, TPlugin extends ClassPluginFactory<AnyRecord> | undefined = ClassPluginFactory<AnyRecord> | undefined> = {
212
+ readonly base?: ClassName;
213
+ readonly variants?: V;
214
+ readonly defaults?: Partial<DefaultVariants<V>>;
215
+ readonly compounds?: readonly CompoundVariant<V>[];
216
+ readonly presets?: TPreset;
217
+ readonly tags?: Readonly<TagMap>;
218
+ readonly plugin?: TPlugin;
219
+ readonly precomputedClasses?: Readonly<Record<string, string>>;
220
+ };
221
+
222
+ type NormalizeFn<Props extends AnyRecord = AnyRecord> = {
223
+ normalize(props: Readonly<Props & IntrinsicProps>): Props & IntrinsicProps;
224
+ }['normalize'];
225
+ type AnyFactoryOptions = FactoryOptions<ElementType, AnyRecord, VariantMap, RecipeMap<VariantMap>, ClassPluginFactory<AnyRecord> | undefined>;
226
+ type FactoryOptions<TDefault extends ElementType = ElementType, Props extends AnyRecord = EmptyRecord, V extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<V> = Readonly<EmptyRecord>, TPlugin extends ClassPluginFactory<AnyRecord> | undefined = ClassPluginFactory<AnyRecord> | undefined, TAllowed extends ElementType = ElementType> = {
227
+ readonly tag?: TDefault;
228
+ readonly name?: string;
229
+ readonly defaults?: Partial<NoInfer<Props>>;
230
+ readonly normalize?: NormalizeFn<NoInfer<Props>>;
231
+ readonly styling?: StylingOptions<V, TPreset, TPlugin>;
232
+ readonly enforcement?: EnforcementOptions<TAllowed>;
233
+ };
234
+
235
+ type MetadataMap = AnyRecord;
236
+ type NodeId = string;
237
+
238
+ interface Diagnostic {
239
+ code: string;
240
+ message: string;
241
+ severity: 'error' | 'warning' | 'info';
242
+ }
243
+
244
+ type CapabilityMap = StringMap<boolean>;
245
+
246
+ declare function defineContractComponent<O extends FactoryOptions>(options: O): <R>(factory: (options: O) => R) => R;
247
+
248
+ interface ComponentIdentity {
249
+ id: NodeId;
250
+ name: string;
251
+ tag: string;
252
+ }
253
+
254
+ interface ComponentDefinition {
255
+ identity: ComponentIdentity;
256
+ capabilities: CapabilityMap;
257
+ metadata: MetadataMap;
258
+ diagnostics: Diagnostic[];
259
+ }
260
+
261
+ type UnknownProps = Record<string, unknown>;
262
+ type SlotComponent = ComponentType<UnknownProps>;
263
+
264
+ /**
265
+ * Props passed to the `render` callback — the component's resolved className,
266
+ * filtered own props, and ref. Spread these onto the target element.
267
+ *
268
+ * Typed loosely to accommodate any element tag the user chooses.
269
+ */
270
+ type RenderCallbackProps = Readonly<Record<string, unknown>>;
271
+
272
+ type SlottableProps = PropsWithChildren;
273
+ declare function Slottable({ children }: SlottableProps): ReactElement;
274
+
275
+ /** Structural subset of `CompiledComponentArtifact` consumed by the React adapter. */
276
+ interface CompiledArtifact {
277
+ readonly definition: ComponentDefinition;
278
+ readonly precomputed?: {
279
+ readonly variantLookup?: Record<string, string>;
280
+ };
281
+ }
282
+ /**
283
+ * Extends FactoryOptions with React-specific configuration.
284
+ * slotComponent is intentionally not in core — it is a React rendering concern.
285
+ */
286
+ type ReactFactoryOptions<TDefault extends ElementType, Props extends UnknownProps, Variants extends Readonly<VariantMap>, TPreset extends RecipeMap<Variants> = Readonly<EmptyRecord>, TPlugin extends ClassPluginFactory<AnyRecord> | undefined = ClassPluginFactory<AnyRecord> | undefined, TAllowed extends ElementType = ElementType> = FactoryOptions<TDefault, Props, Variants, TPreset, TPlugin, TAllowed> & {
287
+ /** Component used to render the asChild slot. Defaults to the built-in Slot. */
288
+ slotComponent?: SlotComponent;
289
+ /**
290
+ * Return true for any prop key that should be consumed but not forwarded to the DOM.
291
+ * The adapter strips nothing by default — implementations decide what is safe to drop.
292
+ * Receives `runtime.options.variantKeys` as a convenience if needed.
293
+ */
294
+ filterProps?: (key: string, variantKeys: ReadonlySet<string>) => boolean;
295
+ /** Pre-compiled artifact from `@praxis-kit/runtime`'s compiler. When provided, replaces the stub
296
+ * definition and enables the precomputed variant lookup fast path. */
297
+ artifact?: CompiledArtifact;
298
+ };
299
+
300
+ /** Maps a core ElementType to its DOM instance type for ref inference. */
301
+ type ElementRef<T extends ElementType> = T extends IntrinsicTag ? HTMLElementTagNameMap[T] : unknown;
302
+ /** @internal React JSX intrinsic props for a given element type. */
303
+ type IntrinsicJSXProps<T extends ElementType> = T extends IntrinsicTag ? JSX.IntrinsicElements[T] : UnknownProps;
304
+ /**
305
+ * @internal
306
+ * Removes index signatures (e.g. `[key: string]: T`) from a type, keeping only
307
+ * explicitly named properties. Used to prevent fallback-to-constraint generics
308
+ * like `Record<string, unknown>` or `Readonly<VariantMap>` from producing a
309
+ * `[key: string]: T` member that makes `keyof` resolve to `string` — which
310
+ * would cause `Omit<IntrinsicJSXProps<TAs>, string>` to remove all HTML props.
311
+ */
312
+ type StripIndexSignature<T> = {
313
+ [K in keyof T as string extends K ? never : K]: T[K];
314
+ };
315
+ type ComponentProps<G extends PolymorphicGenerics> = StripIndexSignature<PropsOf<G>>;
316
+ type ComponentVariants<G extends PolymorphicGenerics> = StripIndexSignature<VariantProps<VariantsOf<G>>>;
317
+ type OwnedProps<G extends PolymorphicGenerics> = ComponentProps<G> & ComponentVariants<G>;
318
+ /**
319
+ * @internal
320
+ * Polymorphic machinery props. Separated from `OwnedProps` so the two concerns
321
+ * are distinct: user-defined props vs. the tag/ref/class system.
322
+ *
323
+ * `asChild` and `children` are excluded — typed separately in the discriminated
324
+ * union below so each render mode can enforce different child constraints.
325
+ */
326
+ type PolymorphicControlProps<G extends PolymorphicGenerics, TAs extends ElementType> = {
327
+ as?: TAs & AllowedOf<G>;
328
+ className?: ClassName | undefined;
329
+ recipe?: keyof RecipeOf<G>;
330
+ ref?: Ref<ElementRef<TAs>>;
331
+ };
332
+ /** @internal Full set of props owned by the component — used as the Omit key in IntrinsicPropsWithoutOwned. */
333
+ type ControlProps<G extends PolymorphicGenerics, TAs extends ElementType> = OwnedProps<G> & PolymorphicControlProps<G, TAs>;
334
+ type IntrinsicPropsWithoutOwned<G extends PolymorphicGenerics, TAs extends ElementType> = Omit<IntrinsicJSXProps<TAs>, keyof ControlProps<G, TAs> | 'children'>;
335
+ type SharedProps<G extends PolymorphicGenerics, TAs extends ElementType> = IntrinsicPropsWithoutOwned<G, TAs> & ControlProps<G, TAs>;
336
+ /** Discriminant for the normal render path: `asChild` absent or false, any children. */
337
+ type NormalRenderMode = {
338
+ asChild?: false;
339
+ children?: ReactNode | undefined;
340
+ };
341
+ /**
342
+ * Discriminant for the slot render path. One or more `ReactElement` children required.
343
+ * `as` is forbidden — combining `as` with `asChild` is a runtime invariant violation.
344
+ */
345
+ type SlotRenderMode = {
346
+ asChild: true;
347
+ as?: never;
348
+ children: ReactElement | NonEmptyTuple<ReactElement>;
349
+ };
350
+ /**
351
+ * Discriminant for the render-prop path. The callback receives all resolved props
352
+ * (className, ref, filtered component props) and returns the target element.
353
+ *
354
+ * This is the output form for the compile-time `asChild` transform: keeps the same
355
+ * rendering flexibility as `asChild` without the `cloneElement` cost at runtime.
356
+ * Unlike `asChild`, the render callback does not auto-merge conflicting event
357
+ * handlers — spread position determines precedence.
358
+ *
359
+ * ```tsx
360
+ * <Button render={(p) => <a href="/home" {...p} />} size="lg" />
361
+ * ```
362
+ */
363
+ type CallbackRenderMode = {
364
+ render: (props: RenderCallbackProps) => ReactElement;
365
+ asChild?: never;
366
+ children?: never;
367
+ };
368
+ /**
369
+ * Props for the normal render path. HTML attributes are inferred from `TAs`.
370
+ *
371
+ * `Omit + intersection` (not `Merge`) is used so TypeScript can infer `TAs` from
372
+ * the `as` prop value; control props win on key conflicts.
373
+ */
374
+ type PolymorphicProps<G extends PolymorphicGenerics, TAs extends ElementType = DefaultOf<G>> = Simplify<SharedProps<G, TAs> & NormalRenderMode>;
375
+ /**
376
+ * Props for the slot render path (`asChild: true`). One or more `ReactElement`
377
+ * children are required. Multiple children are permitted for the Slottable
378
+ * sibling pattern where one child is a `<Slottable>` wrapper.
379
+ */
380
+ type PolymorphicWithAsChild<G extends PolymorphicGenerics, TAs extends ElementType = DefaultOf<G>> = Simplify<SharedProps<G, TAs> & SlotRenderMode>;
381
+ type PolymorphicWithRender<G extends PolymorphicGenerics, TAs extends ElementType = DefaultOf<G>> = Simplify<SharedProps<G, TAs> & CallbackRenderMode>;
382
+ /**
383
+ * A polymorphic component that infers HTML attributes and ref type from the `as` prop.
384
+ *
385
+ * Three call signatures form a discriminated union:
386
+ * - `render` present → render-prop path; no Slot or cloneElement at runtime
387
+ * - `asChild: true` → slot path; exactly one `ReactElement` child required
388
+ * - `asChild?: false` → normal path; any `ReactNode` children accepted
389
+ */
390
+ type PolymorphicComponent<G extends PolymorphicGenerics> = {
391
+ <TAs extends ElementType = DefaultOf<G>>(props: PolymorphicWithRender<G, TAs>): ReactElement;
392
+ <TAs extends ElementType = DefaultOf<G>>(props: PolymorphicWithAsChild<G, TAs>): ReactElement;
393
+ <TAs extends ElementType = DefaultOf<G>>(props: PolymorphicProps<G, TAs>): ReactElement;
394
+ displayName?: string;
395
+ };
396
+
397
+ declare function mergeRefs<T>(...refs: (Ref<T> | null | undefined)[]): Ref<T> | null;
398
+
399
+ export { type AnyRecord as A, type ClassPluginFactory as C, type ElementType as E, type FactoryOptions as F, type PolymorphicComponent as P, type RecipeMap as R, Slottable as S, type UnknownProps as U, type VariantMap as V, type EmptyRecord as a, type ReactFactoryOptions as b, type PolymorphicGenerics as c, type ExtractPluginProps as d, type AnyFactoryOptions as e, type ElementRef as f, type PolymorphicProps as g, type PolymorphicWithAsChild as h, type PolymorphicWithRender as i, type RenderCallbackProps as j, type SlottableProps as k, defineContractComponent as l, mergeRefs as m };
@@ -1,8 +1,237 @@
1
- import { ElementType, VariantMap, RecipeMap, EmptyRecord, ClassPluginFactory, AnyRecord, FactoryOptions, IntrinsicTag, PolymorphicGenerics, DefaultOf, PropsOf, VariantProps, VariantsOf, ClassName, RecipeOf, ExtractPluginProps } from '@praxis-kit/core';
2
- export { AnyFactoryOptions, ElementType, EmptyRecord, PolymorphicGenerics } from '@praxis-kit/core';
1
+ import { RequireAtLeastOne, Simplify, ReadonlyDeep, OmitIndexSignature } from 'type-fest';
2
+ import { Diagnostics, DiagnosticInput } from '../_shared/diagnostics.js';
3
3
  import { ComponentChildren, VNode, ComponentType, JSX, Ref } from 'preact';
4
- import { Simplify, OmitIndexSignature } from 'type-fest';
5
- export { defineContractComponent } from '@praxis-kit/adapter-utils';
4
+
5
+ type StringMap<T = unknown> = Record<string, T>;
6
+ type AnyRecord = StringMap<unknown>;
7
+
8
+ type IntrinsicTag = keyof HTMLElementTagNameMap;
9
+
10
+ type ElementType = IntrinsicTag | (string & {});
11
+
12
+ declare const KNOWN_ARIA_ROLES: readonly ["alert", "alertdialog", "application", "article", "banner", "blockquote", "button", "caption", "cell", "checkbox", "code", "columnheader", "combobox", "complementary", "contentinfo", "definition", "deletion", "dialog", "document", "emphasis", "feed", "figure", "form", "generic", "grid", "gridcell", "group", "heading", "img", "insertion", "link", "list", "listbox", "listitem", "log", "main", "marquee", "math", "menu", "menubar", "menuitem", "menuitemcheckbox", "menuitemradio", "meter", "navigation", "none", "note", "option", "paragraph", "presentation", "progressbar", "radio", "radiogroup", "region", "row", "rowgroup", "rowheader", "scrollbar", "search", "searchbox", "separator", "slider", "spinbutton", "status", "strong", "subscript", "superscript", "switch", "tab", "table", "tablist", "tabpanel", "term", "textbox", "time", "timer", "toolbar", "tooltip", "tree", "treegrid", "treeitem"];
13
+ type KnownAriaRole = (typeof KNOWN_ARIA_ROLES)[number];
14
+
15
+ type Booleanish = boolean | 'true' | 'false';
16
+ type ClassName = string | string[];
17
+ type EmptyRecord = Record<never, never>;
18
+ type NonEmptyArray<T> = [T, ...T[]];
19
+ type Numberish = number | `${number}`;
20
+ type Primitive = string | number | boolean;
21
+ type AriaRole = KnownAriaRole | (string & {});
22
+ type IntrinsicProps = AnyRecord & {
23
+ role?: AriaRole;
24
+ };
25
+ type TagMap = Partial<Record<IntrinsicTag | (string & {}), ClassName>>;
26
+
27
+ type MinMax = {
28
+ min: number;
29
+ max: number;
30
+ };
31
+ type CardinalityInput = Partial<MinMax>;
32
+
33
+ type ChildRuleMatch<T, U extends T = T> = (child: T) => child is U;
34
+
35
+ type ChildRulePosition = 'first' | 'last' | 'any';
36
+
37
+ type ChildRuleInput<T = unknown, U extends T = T> = {
38
+ name: string;
39
+ match: ChildRuleMatch<T, U>;
40
+ cardinality?: CardinalityInput;
41
+ position?: ChildRulePosition;
42
+ /**
43
+ * Optional component-type reference for O(1) dispatch index.
44
+ * When provided for every rule, the matcher reads child.type instead of
45
+ * calling every match function on every child (O(n×m) → O(n+m)).
46
+ */
47
+ type?: unknown;
48
+ };
49
+
50
+ type ValidResult = {
51
+ valid: true;
52
+ };
53
+
54
+ type RequireAtLeastOneIfNotEmpty<T> = keyof T extends never ? EmptyRecord : RequireAtLeastOne<T>;
55
+ type CompoundVariantConditionValue<V extends VariantMap, K extends keyof V> = VariantKey<V, K> | NonEmptyArray<VariantKey<V, K>>;
56
+ type CompoundVariantConditions<V extends VariantMap> = Simplify<{
57
+ [K in keyof V]: CompoundVariantConditionValue<V, K>;
58
+ }>;
59
+ type CompoundVariantRequiredConditions<V extends VariantMap> = RequireAtLeastOneIfNotEmpty<CompoundVariantConditions<V>>;
60
+ type CompoundVariantBase<V extends VariantMap> = keyof V extends never ? EmptyRecord : CompoundVariantRequiredConditions<V>;
61
+ type CompoundVariant<V extends VariantMap> = CompoundVariantBase<V> & {
62
+ class: VariantValue;
63
+ };
64
+
65
+ interface CVACompounds<V extends VariantMap> {
66
+ compoundVariants?: readonly CompoundVariant<V>[];
67
+ }
68
+
69
+ interface CVADefaults<V extends VariantMap> {
70
+ defaultVariants?: DefaultVariants<V>;
71
+ }
72
+
73
+ interface CVAVariants<V extends VariantMap> {
74
+ variants?: V;
75
+ }
76
+
77
+ type StringToBoolean<T> = T extends 'true' | 'false' ? boolean : T;
78
+ type VariantValue = string | string[];
79
+ type VariantStates<K extends string = string> = Record<K, VariantValue>;
80
+ type VariantMap<V extends string = string, K extends string = string> = Record<V, VariantStates<K>>;
81
+ type VariantKey<V extends VariantMap, K extends keyof V> = StringToBoolean<keyof V[K] & string>;
82
+ /**
83
+ * A partial selection of variant states authored at factory definition time.
84
+ *
85
+ * Uses `keyof V[K]` directly (not `VariantKey`) so TypeScript can eagerly
86
+ * resolve the union at constraint-check time without deferred conditional types.
87
+ */
88
+ type VariantSelection<V extends VariantMap> = {
89
+ [K in keyof V]?: keyof V[K];
90
+ };
91
+ /** The full optional prop surface exposed to callers for a given variant map. */
92
+ type VariantProps<V extends VariantMap> = {
93
+ [K in keyof V]?: VariantKey<V, K>;
94
+ };
95
+ type NormalizedVariantValue<K extends string> = string extends K ? Primitive : K extends 'true' | 'false' ? Booleanish : K extends `${number}` ? Numberish : K;
96
+ type DefaultVariants<V extends VariantMap> = {
97
+ [K in keyof V]?: NormalizedVariantValue<keyof V[K] & string>;
98
+ };
99
+ /**
100
+ * A static, immutable map of named presets to partial variant selections.
101
+ *
102
+ * Presets are named bundles of variant props that callers activate by key,
103
+ * avoiding the need to repeat variant combinations at each call site.
104
+ */
105
+ type RecipeMap<V extends VariantMap = VariantMap> = Readonly<Record<string, VariantSelection<V>>>;
106
+ type RecipeTarget<TVariants extends VariantMap = VariantMap> = VariantSelection<TVariants>;
107
+ interface PolymorphicGenerics<TDefault extends ElementType = ElementType, Props extends AnyRecord = AnyRecord, Variants extends Readonly<VariantMap> = Readonly<VariantMap>, TPreset extends RecipeMap<Variants> = Readonly<EmptyRecord>, TAllowed extends ElementType = ElementType> {
108
+ default: TDefault;
109
+ props: Props;
110
+ variants: Variants;
111
+ preset: TPreset;
112
+ allowed: TAllowed;
113
+ }
114
+ type VariantsOf<T extends PolymorphicGenerics> = T['variants'];
115
+ type RecipeOf<T extends PolymorphicGenerics> = T['preset'];
116
+ type DefaultOf<T extends PolymorphicGenerics> = T['default'];
117
+ type PropsOf<T extends PolymorphicGenerics> = T['props'];
118
+
119
+ interface BaseClassOptions {
120
+ baseClassName?: ClassName;
121
+ }
122
+
123
+ type ClassPipelineFn = (tag: unknown, props: AnyRecord, className?: ClassName, recipe?: string) => string;
124
+
125
+ interface RecipeOptions<TVariants extends VariantMap = VariantMap> {
126
+ recipeMap?: Record<string, RecipeTarget<TVariants>>;
127
+ }
128
+
129
+ interface TagMapOptions {
130
+ tagMap?: TagMap;
131
+ }
132
+
133
+ type CompositionOptions<TVariants extends VariantMap = VariantMap> = Simplify<TagMapOptions & RecipeOptions<TVariants>>;
134
+
135
+ type CVASystemOptions<TVariants extends VariantMap = VariantMap> = Simplify<CVAVariants<TVariants> & CVADefaults<TVariants> & CVACompounds<TVariants>>;
136
+
137
+ type StyleOptions<TVariants extends VariantMap = VariantMap> = Simplify<BaseClassOptions & CVASystemOptions<TVariants>>;
138
+
139
+ type ClassPipelineOptions<TVariants extends VariantMap = VariantMap> = Simplify<StyleOptions<TVariants> & CompositionOptions<TVariants>>;
140
+
141
+ type OwnedPropKeys = ReadonlySet<string>;
142
+
143
+ type ClassPlugin<TProps extends AnyRecord = EmptyRecord> = Readonly<{
144
+ pipeline: ClassPipelineFn;
145
+ ownedKeys?: OwnedPropKeys;
146
+ readonly _pluginProps?: TProps;
147
+ }>;
148
+
149
+ type ClassPluginFactory<TProps extends AnyRecord = EmptyRecord> = <V extends VariantMap>(options: ClassPipelineOptions<V>, diagnostics: Diagnostics) => ClassPlugin<TProps>;
150
+ type ExtractPluginProps<TPlugin extends ClassPluginFactory<AnyRecord> | undefined> = TPlugin extends ClassPluginFactory<infer T> ? string extends keyof T ? EmptyRecord : T : EmptyRecord;
151
+
152
+ type AriaContext = {
153
+ readonly tag: IntrinsicTag;
154
+ readonly implicitRole: AriaRole | undefined;
155
+ readonly effectiveRole: string | undefined;
156
+ readonly props: ReadonlyDeep<IntrinsicProps>;
157
+ };
158
+
159
+ type RemoveAttributeFixKind = `removeAttribute:${string}`;
160
+ type InjectLiveFixKind = `injectLive:${string}`;
161
+ type FixKind = 'removeRole' | 'setRole' | 'normalizeRelevantAll' | RemoveAttributeFixKind | InjectLiveFixKind;
162
+
163
+ type AriaFixResult = {
164
+ applied: false;
165
+ next: ReadonlyDeep<IntrinsicProps>;
166
+ } | {
167
+ applied: true;
168
+ next: ReadonlyDeep<IntrinsicProps>;
169
+ previous: ReadonlyDeep<IntrinsicProps>;
170
+ };
171
+ type AriaFix = {
172
+ readonly kind: FixKind;
173
+ readonly priority?: number;
174
+ readonly source?: string;
175
+ readonly apply: (context: AriaContext) => AriaFixResult;
176
+ };
177
+
178
+ type Severity = 'error' | 'warning' | (string & {});
179
+
180
+ type AriaInvalidBase<M extends string = string> = {
181
+ valid: false;
182
+ severity: Severity;
183
+ message?: M;
184
+ attribute?: string;
185
+ diagnostic?: DiagnosticInput;
186
+ };
187
+ type AriaInvalidWithFix<M extends string = string> = AriaInvalidBase<M> & {
188
+ fixable: true;
189
+ fix: AriaFix;
190
+ };
191
+ type AriaInvalidWithoutFix<M extends string = string> = AriaInvalidBase<M> & {
192
+ fixable: false;
193
+ };
194
+ type AriaInvalidResult<M extends string = string> = AriaInvalidWithFix<M> | AriaInvalidWithoutFix<M>;
195
+ type AriaResult = ValidResult | AriaInvalidResult;
196
+
197
+ type AriaRule<C extends AriaContext = AriaContext> = (context: C) => readonly AriaResult[];
198
+
199
+ type PropNormalizer = (props: Readonly<AnyRecord & IntrinsicProps>) => Partial<AnyRecord & IntrinsicProps>;
200
+
201
+ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
202
+ readonly diagnostics?: Diagnostics;
203
+ readonly aria?: readonly AriaRule[];
204
+ readonly children?: readonly ChildRuleInput[];
205
+ readonly props?: readonly PropNormalizer[];
206
+ /** Restricts the `as` prop to this set of tags. Violations route through diagnostics. */
207
+ readonly allowedAs?: readonly TAllowed[];
208
+ };
209
+
210
+ type StylingOptions<V extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<V> = Readonly<EmptyRecord>, TPlugin extends ClassPluginFactory<AnyRecord> | undefined = ClassPluginFactory<AnyRecord> | undefined> = {
211
+ readonly base?: ClassName;
212
+ readonly variants?: V;
213
+ readonly defaults?: Partial<DefaultVariants<V>>;
214
+ readonly compounds?: readonly CompoundVariant<V>[];
215
+ readonly presets?: TPreset;
216
+ readonly tags?: Readonly<TagMap>;
217
+ readonly plugin?: TPlugin;
218
+ readonly precomputedClasses?: Readonly<Record<string, string>>;
219
+ };
220
+
221
+ type NormalizeFn<Props extends AnyRecord = AnyRecord> = {
222
+ normalize(props: Readonly<Props & IntrinsicProps>): Props & IntrinsicProps;
223
+ }['normalize'];
224
+ type AnyFactoryOptions = FactoryOptions<ElementType, AnyRecord, VariantMap, RecipeMap<VariantMap>, ClassPluginFactory<AnyRecord> | undefined>;
225
+ type FactoryOptions<TDefault extends ElementType = ElementType, Props extends AnyRecord = EmptyRecord, V extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<V> = Readonly<EmptyRecord>, TPlugin extends ClassPluginFactory<AnyRecord> | undefined = ClassPluginFactory<AnyRecord> | undefined, TAllowed extends ElementType = ElementType> = {
226
+ readonly tag?: TDefault;
227
+ readonly name?: string;
228
+ readonly defaults?: Partial<NoInfer<Props>>;
229
+ readonly normalize?: NormalizeFn<NoInfer<Props>>;
230
+ readonly styling?: StylingOptions<V, TPreset, TPlugin>;
231
+ readonly enforcement?: EnforcementOptions<TAllowed>;
232
+ };
233
+
234
+ declare function defineContractComponent<O extends FactoryOptions>(options: O): <R>(factory: (options: O) => R) => R;
6
235
 
7
236
  type SlottableProps = {
8
237
  children?: ComponentChildren;
@@ -49,4 +278,4 @@ type PolymorphicComponent<G extends PolymorphicGenerics> = {
49
278
 
50
279
  declare function createContractComponent<TDefault extends ElementType, Props extends UnknownProps = EmptyRecord, Variants extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<Variants> = Readonly<EmptyRecord>, TPlugin extends ClassPluginFactory<AnyRecord> | undefined = ClassPluginFactory<AnyRecord> | undefined>(options: PreactFactoryOptions<TDefault, Props, Variants, TPreset, TPlugin>): PolymorphicComponent<PolymorphicGenerics<TDefault, Props & ExtractPluginProps<TPlugin>, Variants, TPreset>>;
51
280
 
52
- export { type ElementRef, type PolymorphicComponent, type PolymorphicProps, type PolymorphicWithAsChild, type PreactFactoryOptions, Slottable, createContractComponent };
281
+ export { type AnyFactoryOptions, type ElementRef, type ElementType, type EmptyRecord, type PolymorphicComponent, type PolymorphicGenerics, type PolymorphicProps, type PolymorphicWithAsChild, type PreactFactoryOptions, Slottable, createContractComponent, defineContractComponent };