praxis-kit 7.3.0 → 7.5.0
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.
- package/dist/_shared/diagnostics.d.ts +6 -0
- package/dist/contract/index.d.ts +91 -2
- package/dist/guards/index.d.ts +6 -0
- package/dist/html/index.d.ts +6 -0
- package/dist/lit/index.d.ts +156 -9
- package/dist/preact/index.d.ts +162 -6
- package/dist/preact/index.js +5 -1
- package/dist/react/index.d.ts +25 -4
- package/dist/react/index.js +7 -2
- package/dist/react/legacy.d.ts +25 -3
- package/dist/react/legacy.js +6 -2
- package/dist/{react-options-DLDsA4Tn.d.ts → react-options-5GbZ8Tbv.d.ts} +140 -5
- package/dist/solid/index.d.ts +161 -6
- package/dist/solid/index.js +4 -1
- package/dist/svelte/Polymorphic.svelte +13 -0
- package/dist/svelte/index.d.ts +230 -18
- package/dist/tailwind/index.d.ts +12 -0
- package/dist/vite-plugin/index.d.ts +6 -0
- package/dist/vue/index.d.ts +164 -6
- package/dist/vue/index.js +4 -1
- package/dist/web/index.d.ts +129 -6
- package/package.json +3 -3
- /package/dist/{chunk-EIKPSL26.js → chunk-SMHJEFNE.js} +0 -0
|
@@ -98,7 +98,13 @@ declare enum DiagnosticCode {
|
|
|
98
98
|
InternalError = "INTERNAL9000"
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
/**
|
|
102
|
+
* A string-keyed object whose values are of type `T`.
|
|
103
|
+
*/
|
|
101
104
|
type StringMap<T = unknown> = Record<string, T>;
|
|
105
|
+
/**
|
|
106
|
+
* A string-keyed object with values of unknown type.
|
|
107
|
+
*/
|
|
102
108
|
type AnyRecord = StringMap<unknown>;
|
|
103
109
|
|
|
104
110
|
declare enum Severity {
|
package/dist/contract/index.d.ts
CHANGED
|
@@ -1,15 +1,43 @@
|
|
|
1
1
|
import { Diagnostics as Diagnostics$1, DiagnosticInput, DiagnosticsMode } from '../_shared/diagnostics.js';
|
|
2
2
|
import { RequireAtLeastOne, Simplify, ReadonlyDeep } from 'type-fest';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* A string-keyed object whose values are of type `T`.
|
|
6
|
+
*/
|
|
4
7
|
type StringMap<T = unknown> = Record<string, T>;
|
|
8
|
+
/**
|
|
9
|
+
* A string-keyed object with values of unknown type.
|
|
10
|
+
*/
|
|
5
11
|
type AnyRecord = StringMap<unknown>;
|
|
12
|
+
/**
|
|
13
|
+
* An object type with no named properties.
|
|
14
|
+
*
|
|
15
|
+
* Unlike `{}`, this excludes arbitrary properties during type operations while
|
|
16
|
+
* still satisfying `extends object`.
|
|
17
|
+
*/
|
|
6
18
|
type EmptyRecord = Record<never, never>;
|
|
7
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* A compound component's named sub-components, for example
|
|
21
|
+
* `{ Header, Content, Footer }`.
|
|
22
|
+
*/
|
|
8
23
|
type SubComponentMap = Readonly<AnyRecord>;
|
|
9
24
|
|
|
10
25
|
type IntrinsicTag = keyof HTMLElementTagNameMap;
|
|
11
26
|
|
|
12
27
|
type ElementType = IntrinsicTag | (string & {});
|
|
28
|
+
/**
|
|
29
|
+
* Resolves a component's default tag to its real DOM interface — `HTMLDialogElement` for
|
|
30
|
+
* `'dialog'`, `HTMLDetailsElement` for `'details'`, and so on — falling back to `HTMLElement`
|
|
31
|
+
* for custom-element tags or anything not in `HTMLElementTagNameMap`. Used to type
|
|
32
|
+
* `FactoryOptions.onElement`'s `element` param so component authors get direct, correctly-typed
|
|
33
|
+
* access to tag-specific native members (`dialogEl.showModal()`) without an unsafe cast.
|
|
34
|
+
*
|
|
35
|
+
* The fallback is `HTMLElement`, not the more generic `Element` — every tag reachable through
|
|
36
|
+
* `IntrinsicTag` extends it, and so does every custom element per spec, so members `HTMLElement`
|
|
37
|
+
* itself declares (`showPopover()`/`hidePopover()`/`togglePopover()`, the `popover` attribute)
|
|
38
|
+
* stay directly accessible even for tags with no dedicated entry in `HTMLElementTagNameMap`.
|
|
39
|
+
*/
|
|
40
|
+
type ElementForTag<TDefault extends ElementType> = TDefault extends keyof HTMLElementTagNameMap ? HTMLElementTagNameMap[TDefault] : HTMLElement;
|
|
13
41
|
|
|
14
42
|
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"];
|
|
15
43
|
type KnownAriaRole = (typeof KNOWN_ARIA_ROLES)[number];
|
|
@@ -235,6 +263,12 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
|
|
|
235
263
|
* `@praxis-kit/diagnostics`.
|
|
236
264
|
*/
|
|
237
265
|
readonly diagnostics?: Diagnostics$1 | DiagnosticsMode;
|
|
266
|
+
/**
|
|
267
|
+
* ARIA/accessibility rules evaluated against the resolved tag and props on every render.
|
|
268
|
+
* Each rule is a function receiving the current context and returning zero or more
|
|
269
|
+
* violations, some of which can carry an auto-applicable fix (see `createRemoveAttributeRule`
|
|
270
|
+
* and friends in `praxis-kit/contract`).
|
|
271
|
+
*/
|
|
238
272
|
readonly aria?: readonly AriaRule[];
|
|
239
273
|
/**
|
|
240
274
|
* Rules that need `AriaPolicyEngine`'s fix-application/caching machinery
|
|
@@ -246,6 +280,11 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
|
|
|
246
280
|
* misleading `aria` name to get the machinery it needs.
|
|
247
281
|
*/
|
|
248
282
|
readonly rules?: readonly AriaRule[];
|
|
283
|
+
/**
|
|
284
|
+
* Declares which children are valid, by name, match predicate, and cardinality (e.g. "at
|
|
285
|
+
* least 1, at most 4 `Button` children"). Open by default — children matching no rule are
|
|
286
|
+
* still allowed unless `exclusiveChildren` is set.
|
|
287
|
+
*/
|
|
249
288
|
readonly children?: readonly ChildRuleInput[];
|
|
250
289
|
/**
|
|
251
290
|
* When true, only children matching a `children` rule (or text, per `allowText`)
|
|
@@ -258,19 +297,49 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
|
|
|
258
297
|
* or any listed rule. Default: true.
|
|
259
298
|
*/
|
|
260
299
|
readonly allowText?: boolean;
|
|
300
|
+
/**
|
|
301
|
+
* Prop transforms composed with the component's own `normalize` (from `FactoryOptions`) and
|
|
302
|
+
* run before it. Unlike `normalize`, these live in the enforcement bucket because they
|
|
303
|
+
* typically encode a built-in HTML/ARIA fact rather than component-specific behavior.
|
|
304
|
+
*/
|
|
261
305
|
readonly props?: readonly PropNormalizer[];
|
|
262
306
|
/** Restricts the `as` prop to this set of tags. Violations route through diagnostics. */
|
|
263
307
|
readonly allowedAs?: readonly TAllowed[];
|
|
264
308
|
};
|
|
265
309
|
|
|
266
310
|
type StylingOptions<V extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<V> = Readonly<EmptyRecord>, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory> = {
|
|
311
|
+
/** Class applied to every instance regardless of variant selection. */
|
|
267
312
|
readonly base?: ClassName;
|
|
313
|
+
/**
|
|
314
|
+
* Named variant groups (e.g. `intent`, `size`), each mapping its possible values to a
|
|
315
|
+
* class string. A consumer selects a value per group as a prop (`<Button intent="primary">`).
|
|
316
|
+
*/
|
|
268
317
|
readonly variants?: V;
|
|
318
|
+
/** Value used for a variant group when the consumer doesn't pass one explicitly. */
|
|
269
319
|
readonly defaults?: Partial<DefaultVariants<V>>;
|
|
320
|
+
/**
|
|
321
|
+
* Applies an extra class only when a specific *combination* of variant selections matches —
|
|
322
|
+
* for cases `variants` alone can't express (e.g. `intent: 'primary'` + `size: 'lg'` together
|
|
323
|
+
* need a class neither variant would add on its own).
|
|
324
|
+
*/
|
|
270
325
|
readonly compounds?: readonly CompoundVariant<V>[];
|
|
326
|
+
/**
|
|
327
|
+
* Named bundles of variant values, selectable as a single unit via the `recipe` prop (e.g.
|
|
328
|
+
* `<Button recipe="cta">` instead of setting `intent`/`size` individually).
|
|
329
|
+
*/
|
|
271
330
|
readonly presets?: TPreset;
|
|
331
|
+
/** Maps a resolved tag directly to a raw class string, independent of the variant system. */
|
|
272
332
|
readonly tags?: Readonly<TagMap>;
|
|
333
|
+
/**
|
|
334
|
+
* A `ClassPluginFactory` (e.g. the Tailwind layout pipeline) that extends class resolution
|
|
335
|
+
* with its own owned props, layered on top of `variants`/`presets`/`tags`.
|
|
336
|
+
*/
|
|
273
337
|
readonly plugin?: TPlugin;
|
|
338
|
+
/**
|
|
339
|
+
* A cache-key → resolved-class-string lookup for every statically-known variant
|
|
340
|
+
* combination, skipping runtime class computation entirely when a match is found. Normally
|
|
341
|
+
* generated by a build-time class-extraction plugin rather than hand-authored.
|
|
342
|
+
*/
|
|
274
343
|
readonly precomputedClasses?: Readonly<Record<string, string>>;
|
|
275
344
|
};
|
|
276
345
|
|
|
@@ -279,11 +348,21 @@ type NormalizeFn<Props extends AnyRecord = AnyRecord> = {
|
|
|
279
348
|
}['normalize'];
|
|
280
349
|
type AnyFactoryOptions = FactoryOptions<ElementType, AnyRecord, VariantMap, RecipeMap<VariantMap>, AnyClassPluginFactory>;
|
|
281
350
|
type FactoryOptions<TDefault extends ElementType = ElementType, Props extends AnyRecord = EmptyRecord, V extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<V> = Readonly<EmptyRecord>, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory, TAllowed extends ElementType = ElementType> = {
|
|
351
|
+
/** The intrinsic tag the component renders by default. Overridable per instance via `as`. */
|
|
282
352
|
readonly tag?: TDefault;
|
|
353
|
+
/** Display name used in diagnostics, dev tools, and generated component naming. */
|
|
283
354
|
readonly name?: string;
|
|
355
|
+
/** Values used for the component's own (non-variant) props when the consumer omits them. */
|
|
284
356
|
readonly defaults?: Partial<NoInfer<Props>>;
|
|
357
|
+
/**
|
|
358
|
+
* A pure `(props) => props` transform run on every render, after `enforcement.props`'s
|
|
359
|
+
* normalizers see the same input. Use this for component-specific prop shaping — anything
|
|
360
|
+
* that depends on live instance state or the real DOM element belongs in `onElement` instead.
|
|
361
|
+
*/
|
|
285
362
|
readonly normalize?: NormalizeFn<NoInfer<Props>>;
|
|
363
|
+
/** Variant groups, base classes, presets, and the optional class-resolution plugin. */
|
|
286
364
|
readonly styling?: StylingOptions<V, TPreset, TPlugin>;
|
|
365
|
+
/** ARIA rules, child-content contracts, and other runtime validation for this component. */
|
|
287
366
|
readonly enforcement?: EnforcementOptions<TAllowed>;
|
|
288
367
|
/**
|
|
289
368
|
* Adapter-resolved diagnostics default, spread in by `resolveAdapterCommonOptions`. Not meant to
|
|
@@ -307,13 +386,23 @@ type FactoryOptions<TDefault extends ElementType = ElementType, Props extends An
|
|
|
307
386
|
* no prop-based equivalent), not for anything expressible as a plain
|
|
308
387
|
* prop.
|
|
309
388
|
*
|
|
389
|
+
* `element` is typed to the real DOM interface of every tag the rendered
|
|
390
|
+
* element could actually be — `TDefault` plus whatever `enforcement.allowed`
|
|
391
|
+
* permits via `as` (`HTMLDialogElement` for `tag: 'dialog'`,
|
|
392
|
+
* `HTMLDetailsElement` for `tag: 'details'`, and so on) — no cast needed to
|
|
393
|
+
* reach tag-specific members. A component that leaves `allowed`
|
|
394
|
+
* unconstrained (any tag reachable via `as`) falls back to `HTMLElement`,
|
|
395
|
+
* which still covers members every element shares (`showPopover()` and
|
|
396
|
+
* friends); restrict `enforcement.allowed` to the tags `onElement`
|
|
397
|
+
* actually knows how to handle to get real narrowing.
|
|
398
|
+
*
|
|
310
399
|
* `getProps` returns the instance's *current* resolved props at call
|
|
311
400
|
* time — read it from inside a listener registered once at mount, rather
|
|
312
401
|
* than re-subscribing on every prop change.
|
|
313
402
|
*
|
|
314
403
|
* Return a cleanup function to run when the instance unmounts.
|
|
315
404
|
*/
|
|
316
|
-
readonly onElement?: (element:
|
|
405
|
+
readonly onElement?: (element: ElementForTag<TDefault | TAllowed>, getProps: () => Readonly<Props>) => void | (() => void);
|
|
317
406
|
};
|
|
318
407
|
|
|
319
408
|
/** Shared input shape for `invalidWithFix`/`invalidWithoutFix`. */
|
package/dist/guards/index.d.ts
CHANGED
package/dist/html/index.d.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { ReadonlyDeep } from 'type-fest';
|
|
2
2
|
import { DiagnosticInput } from '../_shared/diagnostics.js';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* A string-keyed object whose values are of type `T`.
|
|
6
|
+
*/
|
|
4
7
|
type StringMap<T = unknown> = Record<string, T>;
|
|
8
|
+
/**
|
|
9
|
+
* A string-keyed object with values of unknown type.
|
|
10
|
+
*/
|
|
5
11
|
type AnyRecord = StringMap<unknown>;
|
|
6
12
|
|
|
7
13
|
type IntrinsicTag = keyof HTMLElementTagNameMap;
|
package/dist/lit/index.d.ts
CHANGED
|
@@ -2,15 +2,89 @@ import { RequireAtLeastOne, Simplify, ReadonlyDeep } from 'type-fest';
|
|
|
2
2
|
import { Diagnostics, DiagnosticInput, DiagnosticsMode } from '../_shared/diagnostics.js';
|
|
3
3
|
import { LitElement } from 'lit';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* A string-keyed object whose values are of type `T`.
|
|
7
|
+
*/
|
|
5
8
|
type StringMap<T = unknown> = Record<string, T>;
|
|
9
|
+
/**
|
|
10
|
+
* A string-keyed object with values of unknown type.
|
|
11
|
+
*/
|
|
6
12
|
type AnyRecord = StringMap<unknown>;
|
|
13
|
+
/**
|
|
14
|
+
* An object type with no named properties.
|
|
15
|
+
*
|
|
16
|
+
* Unlike `{}`, this excludes arbitrary properties during type operations while
|
|
17
|
+
* still satisfying `extends object`.
|
|
18
|
+
*/
|
|
7
19
|
type EmptyRecord = Record<never, never>;
|
|
8
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* A compound component's named sub-components, for example
|
|
22
|
+
* `{ Header, Content, Footer }`.
|
|
23
|
+
*/
|
|
9
24
|
type SubComponentMap = Readonly<AnyRecord>;
|
|
25
|
+
/**
|
|
26
|
+
* Default `Variants` type for components that declare no variants.
|
|
27
|
+
*
|
|
28
|
+
* Structurally identical to `Readonly<EmptyRecord>`, but named separately so
|
|
29
|
+
* editor hovers remain self-descriptive.
|
|
30
|
+
*/
|
|
31
|
+
type NoVariants = Readonly<EmptyRecord>;
|
|
32
|
+
/**
|
|
33
|
+
* Default `TPreset` type for components that declare no named presets.
|
|
34
|
+
*
|
|
35
|
+
* Structurally identical to `Readonly<EmptyRecord>`, but named separately so
|
|
36
|
+
* editor hovers remain self-descriptive.
|
|
37
|
+
*/
|
|
38
|
+
type NoPreset = Readonly<EmptyRecord>;
|
|
39
|
+
/**
|
|
40
|
+
* Fallback for `ExtractPluginProps<TPlugin>` when a plugin contributes no
|
|
41
|
+
* props, including the no-plugin case.
|
|
42
|
+
*
|
|
43
|
+
* Structurally identical to `EmptyRecord`, but named separately so editor
|
|
44
|
+
* hovers remain self-descriptive.
|
|
45
|
+
*/
|
|
46
|
+
type NoPluginProps = EmptyRecord;
|
|
47
|
+
/**
|
|
48
|
+
* Determines whether an object type should be treated as empty.
|
|
49
|
+
*
|
|
50
|
+
* `keyof T` ignores call and construct signatures...
|
|
51
|
+
*/
|
|
52
|
+
type IsEmptyRecord<T extends object> = T extends (...args: never[]) => unknown ? false : T extends new (...args: never[]) => unknown ? false : keyof T extends never ? true : false;
|
|
53
|
+
/**
|
|
54
|
+
* Merges two object types while eliding empty operands.
|
|
55
|
+
*
|
|
56
|
+
* If either operand is {@link EmptyRecord}, the other operand is returned
|
|
57
|
+
* directly instead of producing intersections such as
|
|
58
|
+
* `Component & EmptyRecord` in editor hovers.
|
|
59
|
+
*
|
|
60
|
+
* Unlike a homomorphic mapped type (for example `Simplify<T>`), this preserves
|
|
61
|
+
* call and construct signatures. Many component types are callable objects,
|
|
62
|
+
* and mapped types silently discard those signatures.
|
|
63
|
+
*
|
|
64
|
+
* @remarks
|
|
65
|
+
* Instantiate `MergeRecords` directly. Introducing an intermediate alias for
|
|
66
|
+
* one operand (for example `type C = PolymorphicComponent<G>`) can prevent
|
|
67
|
+
* `IsEmptyRecord` from evaluating eagerly, which breaks assignability under
|
|
68
|
+
* `exactOptionalPropertyTypes`.
|
|
69
|
+
*/
|
|
70
|
+
type MergeRecords<A extends object, B extends object> = IsEmptyRecord<A> extends true ? B : IsEmptyRecord<B> extends true ? A : A & B;
|
|
10
71
|
|
|
11
72
|
type IntrinsicTag = keyof HTMLElementTagNameMap;
|
|
12
73
|
|
|
13
74
|
type ElementType = IntrinsicTag | (string & {});
|
|
75
|
+
/**
|
|
76
|
+
* Resolves a component's default tag to its real DOM interface — `HTMLDialogElement` for
|
|
77
|
+
* `'dialog'`, `HTMLDetailsElement` for `'details'`, and so on — falling back to `HTMLElement`
|
|
78
|
+
* for custom-element tags or anything not in `HTMLElementTagNameMap`. Used to type
|
|
79
|
+
* `FactoryOptions.onElement`'s `element` param so component authors get direct, correctly-typed
|
|
80
|
+
* access to tag-specific native members (`dialogEl.showModal()`) without an unsafe cast.
|
|
81
|
+
*
|
|
82
|
+
* The fallback is `HTMLElement`, not the more generic `Element` — every tag reachable through
|
|
83
|
+
* `IntrinsicTag` extends it, and so does every custom element per spec, so members `HTMLElement`
|
|
84
|
+
* itself declares (`showPopover()`/`hidePopover()`/`togglePopover()`, the `popover` attribute)
|
|
85
|
+
* stay directly accessible even for tags with no dedicated entry in `HTMLElementTagNameMap`.
|
|
86
|
+
*/
|
|
87
|
+
type ElementForTag<TDefault extends ElementType> = TDefault extends keyof HTMLElementTagNameMap ? HTMLElementTagNameMap[TDefault] : HTMLElement;
|
|
14
88
|
|
|
15
89
|
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"];
|
|
16
90
|
type KnownAriaRole = (typeof KNOWN_ARIA_ROLES)[number];
|
|
@@ -172,7 +246,7 @@ type ClassPluginFactory<TProps extends AnyRecord = EmptyRecord> = <V extends Var
|
|
|
172
246
|
* wherever a factory's concrete plugin-props shape isn't tracked (factory generics,
|
|
173
247
|
* capability wiring). */
|
|
174
248
|
type AnyClassPluginFactory = ClassPluginFactory<AnyRecord> | undefined;
|
|
175
|
-
type ExtractPluginProps<TPlugin extends AnyClassPluginFactory> = TPlugin extends ClassPluginFactory<infer T> ? string extends keyof T ?
|
|
249
|
+
type ExtractPluginProps<TPlugin extends AnyClassPluginFactory> = TPlugin extends ClassPluginFactory<infer T> ? string extends keyof T ? NoPluginProps : T : NoPluginProps;
|
|
176
250
|
|
|
177
251
|
type AriaContext = {
|
|
178
252
|
readonly tag: IntrinsicTag;
|
|
@@ -236,6 +310,12 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
|
|
|
236
310
|
* `@praxis-kit/diagnostics`.
|
|
237
311
|
*/
|
|
238
312
|
readonly diagnostics?: Diagnostics | DiagnosticsMode;
|
|
313
|
+
/**
|
|
314
|
+
* ARIA/accessibility rules evaluated against the resolved tag and props on every render.
|
|
315
|
+
* Each rule is a function receiving the current context and returning zero or more
|
|
316
|
+
* violations, some of which can carry an auto-applicable fix (see `createRemoveAttributeRule`
|
|
317
|
+
* and friends in `praxis-kit/contract`).
|
|
318
|
+
*/
|
|
239
319
|
readonly aria?: readonly AriaRule[];
|
|
240
320
|
/**
|
|
241
321
|
* Rules that need `AriaPolicyEngine`'s fix-application/caching machinery
|
|
@@ -247,6 +327,11 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
|
|
|
247
327
|
* misleading `aria` name to get the machinery it needs.
|
|
248
328
|
*/
|
|
249
329
|
readonly rules?: readonly AriaRule[];
|
|
330
|
+
/**
|
|
331
|
+
* Declares which children are valid, by name, match predicate, and cardinality (e.g. "at
|
|
332
|
+
* least 1, at most 4 `Button` children"). Open by default — children matching no rule are
|
|
333
|
+
* still allowed unless `exclusiveChildren` is set.
|
|
334
|
+
*/
|
|
250
335
|
readonly children?: readonly ChildRuleInput[];
|
|
251
336
|
/**
|
|
252
337
|
* When true, only children matching a `children` rule (or text, per `allowText`)
|
|
@@ -259,19 +344,49 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
|
|
|
259
344
|
* or any listed rule. Default: true.
|
|
260
345
|
*/
|
|
261
346
|
readonly allowText?: boolean;
|
|
347
|
+
/**
|
|
348
|
+
* Prop transforms composed with the component's own `normalize` (from `FactoryOptions`) and
|
|
349
|
+
* run before it. Unlike `normalize`, these live in the enforcement bucket because they
|
|
350
|
+
* typically encode a built-in HTML/ARIA fact rather than component-specific behavior.
|
|
351
|
+
*/
|
|
262
352
|
readonly props?: readonly PropNormalizer[];
|
|
263
353
|
/** Restricts the `as` prop to this set of tags. Violations route through diagnostics. */
|
|
264
354
|
readonly allowedAs?: readonly TAllowed[];
|
|
265
355
|
};
|
|
266
356
|
|
|
267
357
|
type StylingOptions<V extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<V> = Readonly<EmptyRecord>, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory> = {
|
|
358
|
+
/** Class applied to every instance regardless of variant selection. */
|
|
268
359
|
readonly base?: ClassName;
|
|
360
|
+
/**
|
|
361
|
+
* Named variant groups (e.g. `intent`, `size`), each mapping its possible values to a
|
|
362
|
+
* class string. A consumer selects a value per group as a prop (`<Button intent="primary">`).
|
|
363
|
+
*/
|
|
269
364
|
readonly variants?: V;
|
|
365
|
+
/** Value used for a variant group when the consumer doesn't pass one explicitly. */
|
|
270
366
|
readonly defaults?: Partial<DefaultVariants<V>>;
|
|
367
|
+
/**
|
|
368
|
+
* Applies an extra class only when a specific *combination* of variant selections matches —
|
|
369
|
+
* for cases `variants` alone can't express (e.g. `intent: 'primary'` + `size: 'lg'` together
|
|
370
|
+
* need a class neither variant would add on its own).
|
|
371
|
+
*/
|
|
271
372
|
readonly compounds?: readonly CompoundVariant<V>[];
|
|
373
|
+
/**
|
|
374
|
+
* Named bundles of variant values, selectable as a single unit via the `recipe` prop (e.g.
|
|
375
|
+
* `<Button recipe="cta">` instead of setting `intent`/`size` individually).
|
|
376
|
+
*/
|
|
272
377
|
readonly presets?: TPreset;
|
|
378
|
+
/** Maps a resolved tag directly to a raw class string, independent of the variant system. */
|
|
273
379
|
readonly tags?: Readonly<TagMap>;
|
|
380
|
+
/**
|
|
381
|
+
* A `ClassPluginFactory` (e.g. the Tailwind layout pipeline) that extends class resolution
|
|
382
|
+
* with its own owned props, layered on top of `variants`/`presets`/`tags`.
|
|
383
|
+
*/
|
|
274
384
|
readonly plugin?: TPlugin;
|
|
385
|
+
/**
|
|
386
|
+
* A cache-key → resolved-class-string lookup for every statically-known variant
|
|
387
|
+
* combination, skipping runtime class computation entirely when a match is found. Normally
|
|
388
|
+
* generated by a build-time class-extraction plugin rather than hand-authored.
|
|
389
|
+
*/
|
|
275
390
|
readonly precomputedClasses?: Readonly<Record<string, string>>;
|
|
276
391
|
};
|
|
277
392
|
|
|
@@ -280,11 +395,21 @@ type NormalizeFn<Props extends AnyRecord = AnyRecord> = {
|
|
|
280
395
|
}['normalize'];
|
|
281
396
|
type AnyFactoryOptions = FactoryOptions<ElementType, AnyRecord, VariantMap, RecipeMap<VariantMap>, AnyClassPluginFactory>;
|
|
282
397
|
type FactoryOptions<TDefault extends ElementType = ElementType, Props extends AnyRecord = EmptyRecord, V extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<V> = Readonly<EmptyRecord>, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory, TAllowed extends ElementType = ElementType> = {
|
|
398
|
+
/** The intrinsic tag the component renders by default. Overridable per instance via `as`. */
|
|
283
399
|
readonly tag?: TDefault;
|
|
400
|
+
/** Display name used in diagnostics, dev tools, and generated component naming. */
|
|
284
401
|
readonly name?: string;
|
|
402
|
+
/** Values used for the component's own (non-variant) props when the consumer omits them. */
|
|
285
403
|
readonly defaults?: Partial<NoInfer<Props>>;
|
|
404
|
+
/**
|
|
405
|
+
* A pure `(props) => props` transform run on every render, after `enforcement.props`'s
|
|
406
|
+
* normalizers see the same input. Use this for component-specific prop shaping — anything
|
|
407
|
+
* that depends on live instance state or the real DOM element belongs in `onElement` instead.
|
|
408
|
+
*/
|
|
286
409
|
readonly normalize?: NormalizeFn<NoInfer<Props>>;
|
|
410
|
+
/** Variant groups, base classes, presets, and the optional class-resolution plugin. */
|
|
287
411
|
readonly styling?: StylingOptions<V, TPreset, TPlugin>;
|
|
412
|
+
/** ARIA rules, child-content contracts, and other runtime validation for this component. */
|
|
288
413
|
readonly enforcement?: EnforcementOptions<TAllowed>;
|
|
289
414
|
/**
|
|
290
415
|
* Adapter-resolved diagnostics default, spread in by `resolveAdapterCommonOptions`. Not meant to
|
|
@@ -308,15 +433,37 @@ type FactoryOptions<TDefault extends ElementType = ElementType, Props extends An
|
|
|
308
433
|
* no prop-based equivalent), not for anything expressible as a plain
|
|
309
434
|
* prop.
|
|
310
435
|
*
|
|
436
|
+
* `element` is typed to the real DOM interface of every tag the rendered
|
|
437
|
+
* element could actually be — `TDefault` plus whatever `enforcement.allowed`
|
|
438
|
+
* permits via `as` (`HTMLDialogElement` for `tag: 'dialog'`,
|
|
439
|
+
* `HTMLDetailsElement` for `tag: 'details'`, and so on) — no cast needed to
|
|
440
|
+
* reach tag-specific members. A component that leaves `allowed`
|
|
441
|
+
* unconstrained (any tag reachable via `as`) falls back to `HTMLElement`,
|
|
442
|
+
* which still covers members every element shares (`showPopover()` and
|
|
443
|
+
* friends); restrict `enforcement.allowed` to the tags `onElement`
|
|
444
|
+
* actually knows how to handle to get real narrowing.
|
|
445
|
+
*
|
|
311
446
|
* `getProps` returns the instance's *current* resolved props at call
|
|
312
447
|
* time — read it from inside a listener registered once at mount, rather
|
|
313
448
|
* than re-subscribing on every prop change.
|
|
314
449
|
*
|
|
315
450
|
* Return a cleanup function to run when the instance unmounts.
|
|
316
451
|
*/
|
|
317
|
-
readonly onElement?: (element:
|
|
452
|
+
readonly onElement?: (element: ElementForTag<TDefault | TAllowed>, getProps: () => Readonly<Props>) => void | (() => void);
|
|
318
453
|
};
|
|
319
454
|
|
|
455
|
+
/**
|
|
456
|
+
* Determines whether a prop should be stripped before forwarding to the
|
|
457
|
+
* rendered element.
|
|
458
|
+
*
|
|
459
|
+
* Returning `true` excludes the prop from the output; returning `false`
|
|
460
|
+
* keeps it. This is the inverse polarity of `shouldForwardProp`-style
|
|
461
|
+
* predicates (Emotion/styled-components), where `true` means include.
|
|
462
|
+
*
|
|
463
|
+
* @param key - The prop name being evaluated.
|
|
464
|
+
* @param variantKeys - The set of configured variant prop names.
|
|
465
|
+
* @returns `true` to strip the prop; `false` to forward it.
|
|
466
|
+
*/
|
|
320
467
|
type FilterPredicate = (key: string, variantKeys: ReadonlySet<string>) => boolean;
|
|
321
468
|
|
|
322
469
|
declare function defineContractComponent<O extends FactoryOptions>(options: O): <R>(factory: (options: O) => R) => R;
|
|
@@ -332,7 +479,7 @@ declare function defineContractComponent<O extends FactoryOptions>(options: O):
|
|
|
332
479
|
* Note: this adapter targets Light DOM composition only. Shadow DOM slot
|
|
333
480
|
* protocol is intentionally out of scope.
|
|
334
481
|
*/
|
|
335
|
-
type LitFactoryOptions<TDefault extends ElementType = ElementType, TProps extends AnyRecord = EmptyRecord, TVariants extends Readonly<VariantMap> =
|
|
482
|
+
type LitFactoryOptions<TDefault extends ElementType = ElementType, TProps extends AnyRecord = EmptyRecord, TVariants extends Readonly<VariantMap> = NoVariants, TPreset extends RecipeMap<TVariants> = NoPreset, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory> = FactoryOptions<TDefault, TProps, TVariants, TPreset, TPlugin> & {
|
|
336
483
|
readonly filterProps?: FilterPredicate;
|
|
337
484
|
};
|
|
338
485
|
|
|
@@ -344,14 +491,14 @@ type UnknownProps = AnyRecord;
|
|
|
344
491
|
* (which would trigger TS4094 in declaration emit). Variant key instance
|
|
345
492
|
* properties are typed via the TVariants parameter.
|
|
346
493
|
*/
|
|
347
|
-
type LitContractComponent<TVariants extends Readonly<VariantMap> =
|
|
348
|
-
new (): LitElement & {
|
|
494
|
+
type LitContractComponent<TVariants extends Readonly<VariantMap> = NoVariants, TPluginProps extends AnyRecord = EmptyRecord> = {
|
|
495
|
+
new (): MergeRecords<LitElement & {
|
|
349
496
|
as: string | undefined;
|
|
350
497
|
recipe: string | undefined;
|
|
351
498
|
praxisClass: string | undefined;
|
|
352
499
|
} & {
|
|
353
500
|
[K in Extract<keyof TVariants, string>]?: string | null;
|
|
354
|
-
}
|
|
501
|
+
}, TPluginProps>;
|
|
355
502
|
};
|
|
356
503
|
|
|
357
504
|
/**
|
|
@@ -374,9 +521,9 @@ type LitContractComponent<TVariants extends Readonly<VariantMap> = Readonly<Empt
|
|
|
374
521
|
* customElements.define('praxis-button', Button)
|
|
375
522
|
* ```
|
|
376
523
|
*/
|
|
377
|
-
declare function createContractComponent<TDefault extends ElementType, TProps extends UnknownProps = EmptyRecord, TVariants extends Readonly<VariantMap> =
|
|
524
|
+
declare function createContractComponent<TDefault extends ElementType, TProps extends UnknownProps = EmptyRecord, TVariants extends Readonly<VariantMap> = NoVariants, TPreset extends RecipeMap<TVariants> = NoPreset, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory, TSubComponents extends Readonly<AnyRecord> = EmptyRecord>(options: LitFactoryOptions<TDefault, TProps, TVariants, TPreset, TPlugin> & {
|
|
378
525
|
readonly subComponents?: TSubComponents;
|
|
379
|
-
}): LitContractComponent<TVariants, ExtractPluginProps<TPlugin
|
|
526
|
+
}): MergeRecords<LitContractComponent<TVariants, ExtractPluginProps<TPlugin>>, TSubComponents>;
|
|
380
527
|
|
|
381
528
|
/**
|
|
382
529
|
* Renders a praxis-kit Lit component to an HTML string without requiring a DOM.
|