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
package/dist/tailwind/index.d.ts
CHANGED
|
@@ -17,8 +17,20 @@ import { RequireAtLeastOne, Simplify, ValueOf } from 'type-fest';
|
|
|
17
17
|
*/
|
|
18
18
|
declare const layoutKeys: readonly ["flex", "inline-flex", "grid", "inline-grid", "block", "inline-block", "inline", "hidden", "contents", "flow-root", "list-item", "table", "inline-table", "table-caption", "table-cell", "table-column", "table-column-group", "table-footer-group", "table-header-group", "table-row-group", "table-row"];
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* A string-keyed object whose values are of type `T`.
|
|
22
|
+
*/
|
|
20
23
|
type StringMap<T = unknown> = Record<string, T>;
|
|
24
|
+
/**
|
|
25
|
+
* A string-keyed object with values of unknown type.
|
|
26
|
+
*/
|
|
21
27
|
type AnyRecord = StringMap<unknown>;
|
|
28
|
+
/**
|
|
29
|
+
* An object type with no named properties.
|
|
30
|
+
*
|
|
31
|
+
* Unlike `{}`, this excludes arbitrary properties during type operations while
|
|
32
|
+
* still satisfying `extends object`.
|
|
33
|
+
*/
|
|
22
34
|
type EmptyRecord = Record<never, never>;
|
|
23
35
|
|
|
24
36
|
type IntrinsicTag = keyof HTMLElementTagNameMap;
|
|
@@ -2,7 +2,13 @@ import { Plugin } from 'vite';
|
|
|
2
2
|
import { Except, Simplify } from 'type-fest';
|
|
3
3
|
import ts from 'typescript';
|
|
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>;
|
|
7
13
|
|
|
8
14
|
declare enum DiagnosticCategory {
|
package/dist/vue/index.d.ts
CHANGED
|
@@ -3,15 +3,89 @@ import { Diagnostics, DiagnosticInput, DiagnosticsMode } from '../_shared/diagno
|
|
|
3
3
|
import * as vue from 'vue';
|
|
4
4
|
import { AllowedComponentProps } from 'vue';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* A string-keyed object whose values are of type `T`.
|
|
8
|
+
*/
|
|
6
9
|
type StringMap<T = unknown> = Record<string, T>;
|
|
10
|
+
/**
|
|
11
|
+
* A string-keyed object with values of unknown type.
|
|
12
|
+
*/
|
|
7
13
|
type AnyRecord = StringMap<unknown>;
|
|
14
|
+
/**
|
|
15
|
+
* An object type with no named properties.
|
|
16
|
+
*
|
|
17
|
+
* Unlike `{}`, this excludes arbitrary properties during type operations while
|
|
18
|
+
* still satisfying `extends object`.
|
|
19
|
+
*/
|
|
8
20
|
type EmptyRecord = Record<never, never>;
|
|
9
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* A compound component's named sub-components, for example
|
|
23
|
+
* `{ Header, Content, Footer }`.
|
|
24
|
+
*/
|
|
10
25
|
type SubComponentMap = Readonly<AnyRecord>;
|
|
26
|
+
/**
|
|
27
|
+
* Default `Variants` type for components that declare no variants.
|
|
28
|
+
*
|
|
29
|
+
* Structurally identical to `Readonly<EmptyRecord>`, but named separately so
|
|
30
|
+
* editor hovers remain self-descriptive.
|
|
31
|
+
*/
|
|
32
|
+
type NoVariants = Readonly<EmptyRecord>;
|
|
33
|
+
/**
|
|
34
|
+
* Default `TPreset` type for components that declare no named presets.
|
|
35
|
+
*
|
|
36
|
+
* Structurally identical to `Readonly<EmptyRecord>`, but named separately so
|
|
37
|
+
* editor hovers remain self-descriptive.
|
|
38
|
+
*/
|
|
39
|
+
type NoPreset = Readonly<EmptyRecord>;
|
|
40
|
+
/**
|
|
41
|
+
* Fallback for `ExtractPluginProps<TPlugin>` when a plugin contributes no
|
|
42
|
+
* props, including the no-plugin case.
|
|
43
|
+
*
|
|
44
|
+
* Structurally identical to `EmptyRecord`, but named separately so editor
|
|
45
|
+
* hovers remain self-descriptive.
|
|
46
|
+
*/
|
|
47
|
+
type NoPluginProps = EmptyRecord;
|
|
48
|
+
/**
|
|
49
|
+
* Determines whether an object type should be treated as empty.
|
|
50
|
+
*
|
|
51
|
+
* `keyof T` ignores call and construct signatures...
|
|
52
|
+
*/
|
|
53
|
+
type IsEmptyRecord<T extends object> = T extends (...args: never[]) => unknown ? false : T extends new (...args: never[]) => unknown ? false : keyof T extends never ? true : false;
|
|
54
|
+
/**
|
|
55
|
+
* Merges two object types while eliding empty operands.
|
|
56
|
+
*
|
|
57
|
+
* If either operand is {@link EmptyRecord}, the other operand is returned
|
|
58
|
+
* directly instead of producing intersections such as
|
|
59
|
+
* `Component & EmptyRecord` in editor hovers.
|
|
60
|
+
*
|
|
61
|
+
* Unlike a homomorphic mapped type (for example `Simplify<T>`), this preserves
|
|
62
|
+
* call and construct signatures. Many component types are callable objects,
|
|
63
|
+
* and mapped types silently discard those signatures.
|
|
64
|
+
*
|
|
65
|
+
* @remarks
|
|
66
|
+
* Instantiate `MergeRecords` directly. Introducing an intermediate alias for
|
|
67
|
+
* one operand (for example `type C = PolymorphicComponent<G>`) can prevent
|
|
68
|
+
* `IsEmptyRecord` from evaluating eagerly, which breaks assignability under
|
|
69
|
+
* `exactOptionalPropertyTypes`.
|
|
70
|
+
*/
|
|
71
|
+
type MergeRecords<A extends object, B extends object> = IsEmptyRecord<A> extends true ? B : IsEmptyRecord<B> extends true ? A : A & B;
|
|
11
72
|
|
|
12
73
|
type IntrinsicTag = keyof HTMLElementTagNameMap;
|
|
13
74
|
|
|
14
75
|
type ElementType = IntrinsicTag | (string & {});
|
|
76
|
+
/**
|
|
77
|
+
* Resolves a component's default tag to its real DOM interface — `HTMLDialogElement` for
|
|
78
|
+
* `'dialog'`, `HTMLDetailsElement` for `'details'`, and so on — falling back to `HTMLElement`
|
|
79
|
+
* for custom-element tags or anything not in `HTMLElementTagNameMap`. Used to type
|
|
80
|
+
* `FactoryOptions.onElement`'s `element` param so component authors get direct, correctly-typed
|
|
81
|
+
* access to tag-specific native members (`dialogEl.showModal()`) without an unsafe cast.
|
|
82
|
+
*
|
|
83
|
+
* The fallback is `HTMLElement`, not the more generic `Element` — every tag reachable through
|
|
84
|
+
* `IntrinsicTag` extends it, and so does every custom element per spec, so members `HTMLElement`
|
|
85
|
+
* itself declares (`showPopover()`/`hidePopover()`/`togglePopover()`, the `popover` attribute)
|
|
86
|
+
* stay directly accessible even for tags with no dedicated entry in `HTMLElementTagNameMap`.
|
|
87
|
+
*/
|
|
88
|
+
type ElementForTag<TDefault extends ElementType> = TDefault extends keyof HTMLElementTagNameMap ? HTMLElementTagNameMap[TDefault] : HTMLElement;
|
|
15
89
|
|
|
16
90
|
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"];
|
|
17
91
|
type KnownAriaRole = (typeof KNOWN_ARIA_ROLES)[number];
|
|
@@ -190,7 +264,7 @@ type ClassPluginFactory<TProps extends AnyRecord = EmptyRecord> = <V extends Var
|
|
|
190
264
|
* wherever a factory's concrete plugin-props shape isn't tracked (factory generics,
|
|
191
265
|
* capability wiring). */
|
|
192
266
|
type AnyClassPluginFactory = ClassPluginFactory<AnyRecord> | undefined;
|
|
193
|
-
type ExtractPluginProps<TPlugin extends AnyClassPluginFactory> = TPlugin extends ClassPluginFactory<infer T> ? string extends keyof T ?
|
|
267
|
+
type ExtractPluginProps<TPlugin extends AnyClassPluginFactory> = TPlugin extends ClassPluginFactory<infer T> ? string extends keyof T ? NoPluginProps : T : NoPluginProps;
|
|
194
268
|
|
|
195
269
|
type AriaContext = {
|
|
196
270
|
readonly tag: IntrinsicTag;
|
|
@@ -254,6 +328,12 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
|
|
|
254
328
|
* `@praxis-kit/diagnostics`.
|
|
255
329
|
*/
|
|
256
330
|
readonly diagnostics?: Diagnostics | DiagnosticsMode;
|
|
331
|
+
/**
|
|
332
|
+
* ARIA/accessibility rules evaluated against the resolved tag and props on every render.
|
|
333
|
+
* Each rule is a function receiving the current context and returning zero or more
|
|
334
|
+
* violations, some of which can carry an auto-applicable fix (see `createRemoveAttributeRule`
|
|
335
|
+
* and friends in `praxis-kit/contract`).
|
|
336
|
+
*/
|
|
257
337
|
readonly aria?: readonly AriaRule[];
|
|
258
338
|
/**
|
|
259
339
|
* Rules that need `AriaPolicyEngine`'s fix-application/caching machinery
|
|
@@ -265,6 +345,11 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
|
|
|
265
345
|
* misleading `aria` name to get the machinery it needs.
|
|
266
346
|
*/
|
|
267
347
|
readonly rules?: readonly AriaRule[];
|
|
348
|
+
/**
|
|
349
|
+
* Declares which children are valid, by name, match predicate, and cardinality (e.g. "at
|
|
350
|
+
* least 1, at most 4 `Button` children"). Open by default — children matching no rule are
|
|
351
|
+
* still allowed unless `exclusiveChildren` is set.
|
|
352
|
+
*/
|
|
268
353
|
readonly children?: readonly ChildRuleInput[];
|
|
269
354
|
/**
|
|
270
355
|
* When true, only children matching a `children` rule (or text, per `allowText`)
|
|
@@ -277,19 +362,49 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
|
|
|
277
362
|
* or any listed rule. Default: true.
|
|
278
363
|
*/
|
|
279
364
|
readonly allowText?: boolean;
|
|
365
|
+
/**
|
|
366
|
+
* Prop transforms composed with the component's own `normalize` (from `FactoryOptions`) and
|
|
367
|
+
* run before it. Unlike `normalize`, these live in the enforcement bucket because they
|
|
368
|
+
* typically encode a built-in HTML/ARIA fact rather than component-specific behavior.
|
|
369
|
+
*/
|
|
280
370
|
readonly props?: readonly PropNormalizer[];
|
|
281
371
|
/** Restricts the `as` prop to this set of tags. Violations route through diagnostics. */
|
|
282
372
|
readonly allowedAs?: readonly TAllowed[];
|
|
283
373
|
};
|
|
284
374
|
|
|
285
375
|
type StylingOptions<V extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<V> = Readonly<EmptyRecord>, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory> = {
|
|
376
|
+
/** Class applied to every instance regardless of variant selection. */
|
|
286
377
|
readonly base?: ClassName;
|
|
378
|
+
/**
|
|
379
|
+
* Named variant groups (e.g. `intent`, `size`), each mapping its possible values to a
|
|
380
|
+
* class string. A consumer selects a value per group as a prop (`<Button intent="primary">`).
|
|
381
|
+
*/
|
|
287
382
|
readonly variants?: V;
|
|
383
|
+
/** Value used for a variant group when the consumer doesn't pass one explicitly. */
|
|
288
384
|
readonly defaults?: Partial<DefaultVariants<V>>;
|
|
385
|
+
/**
|
|
386
|
+
* Applies an extra class only when a specific *combination* of variant selections matches —
|
|
387
|
+
* for cases `variants` alone can't express (e.g. `intent: 'primary'` + `size: 'lg'` together
|
|
388
|
+
* need a class neither variant would add on its own).
|
|
389
|
+
*/
|
|
289
390
|
readonly compounds?: readonly CompoundVariant<V>[];
|
|
391
|
+
/**
|
|
392
|
+
* Named bundles of variant values, selectable as a single unit via the `recipe` prop (e.g.
|
|
393
|
+
* `<Button recipe="cta">` instead of setting `intent`/`size` individually).
|
|
394
|
+
*/
|
|
290
395
|
readonly presets?: TPreset;
|
|
396
|
+
/** Maps a resolved tag directly to a raw class string, independent of the variant system. */
|
|
291
397
|
readonly tags?: Readonly<TagMap>;
|
|
398
|
+
/**
|
|
399
|
+
* A `ClassPluginFactory` (e.g. the Tailwind layout pipeline) that extends class resolution
|
|
400
|
+
* with its own owned props, layered on top of `variants`/`presets`/`tags`.
|
|
401
|
+
*/
|
|
292
402
|
readonly plugin?: TPlugin;
|
|
403
|
+
/**
|
|
404
|
+
* A cache-key → resolved-class-string lookup for every statically-known variant
|
|
405
|
+
* combination, skipping runtime class computation entirely when a match is found. Normally
|
|
406
|
+
* generated by a build-time class-extraction plugin rather than hand-authored.
|
|
407
|
+
*/
|
|
293
408
|
readonly precomputedClasses?: Readonly<Record<string, string>>;
|
|
294
409
|
};
|
|
295
410
|
|
|
@@ -298,11 +413,21 @@ type NormalizeFn<Props extends AnyRecord = AnyRecord> = {
|
|
|
298
413
|
}['normalize'];
|
|
299
414
|
type AnyFactoryOptions = FactoryOptions<ElementType, AnyRecord, VariantMap, RecipeMap<VariantMap>, AnyClassPluginFactory>;
|
|
300
415
|
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> = {
|
|
416
|
+
/** The intrinsic tag the component renders by default. Overridable per instance via `as`. */
|
|
301
417
|
readonly tag?: TDefault;
|
|
418
|
+
/** Display name used in diagnostics, dev tools, and generated component naming. */
|
|
302
419
|
readonly name?: string;
|
|
420
|
+
/** Values used for the component's own (non-variant) props when the consumer omits them. */
|
|
303
421
|
readonly defaults?: Partial<NoInfer<Props>>;
|
|
422
|
+
/**
|
|
423
|
+
* A pure `(props) => props` transform run on every render, after `enforcement.props`'s
|
|
424
|
+
* normalizers see the same input. Use this for component-specific prop shaping — anything
|
|
425
|
+
* that depends on live instance state or the real DOM element belongs in `onElement` instead.
|
|
426
|
+
*/
|
|
304
427
|
readonly normalize?: NormalizeFn<NoInfer<Props>>;
|
|
428
|
+
/** Variant groups, base classes, presets, and the optional class-resolution plugin. */
|
|
305
429
|
readonly styling?: StylingOptions<V, TPreset, TPlugin>;
|
|
430
|
+
/** ARIA rules, child-content contracts, and other runtime validation for this component. */
|
|
306
431
|
readonly enforcement?: EnforcementOptions<TAllowed>;
|
|
307
432
|
/**
|
|
308
433
|
* Adapter-resolved diagnostics default, spread in by `resolveAdapterCommonOptions`. Not meant to
|
|
@@ -326,13 +451,23 @@ type FactoryOptions<TDefault extends ElementType = ElementType, Props extends An
|
|
|
326
451
|
* no prop-based equivalent), not for anything expressible as a plain
|
|
327
452
|
* prop.
|
|
328
453
|
*
|
|
454
|
+
* `element` is typed to the real DOM interface of every tag the rendered
|
|
455
|
+
* element could actually be — `TDefault` plus whatever `enforcement.allowed`
|
|
456
|
+
* permits via `as` (`HTMLDialogElement` for `tag: 'dialog'`,
|
|
457
|
+
* `HTMLDetailsElement` for `tag: 'details'`, and so on) — no cast needed to
|
|
458
|
+
* reach tag-specific members. A component that leaves `allowed`
|
|
459
|
+
* unconstrained (any tag reachable via `as`) falls back to `HTMLElement`,
|
|
460
|
+
* which still covers members every element shares (`showPopover()` and
|
|
461
|
+
* friends); restrict `enforcement.allowed` to the tags `onElement`
|
|
462
|
+
* actually knows how to handle to get real narrowing.
|
|
463
|
+
*
|
|
329
464
|
* `getProps` returns the instance's *current* resolved props at call
|
|
330
465
|
* time — read it from inside a listener registered once at mount, rather
|
|
331
466
|
* than re-subscribing on every prop change.
|
|
332
467
|
*
|
|
333
468
|
* Return a cleanup function to run when the instance unmounts.
|
|
334
469
|
*/
|
|
335
|
-
readonly onElement?: (element:
|
|
470
|
+
readonly onElement?: (element: ElementForTag<TDefault | TAllowed>, getProps: () => Readonly<Props>) => void | (() => void);
|
|
336
471
|
};
|
|
337
472
|
|
|
338
473
|
declare function defineContractComponent<O extends FactoryOptions>(options: O): <R>(factory: (options: O) => R) => R;
|
|
@@ -350,7 +485,7 @@ declare const Slottable: vue.DefineComponent<{}, () => vue.VNode<vue.RendererNod
|
|
|
350
485
|
|
|
351
486
|
type UnknownProps = AnyRecord;
|
|
352
487
|
|
|
353
|
-
type VueFactoryOptions<TDefault extends ElementType, Props extends UnknownProps, Variants extends Readonly<VariantMap>, TPreset extends RecipeMap<Variants> =
|
|
488
|
+
type VueFactoryOptions<TDefault extends ElementType, Props extends UnknownProps, Variants extends Readonly<VariantMap>, TPreset extends RecipeMap<Variants> = NoPreset, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory> = FactoryOptions<TDefault, Props, Variants, TPreset, TPlugin> & {
|
|
354
489
|
/**
|
|
355
490
|
* Return true for any prop key that should be consumed but not forwarded to
|
|
356
491
|
* the DOM. Variant keys are always stripped automatically.
|
|
@@ -396,8 +531,31 @@ type PolymorphicComponent<G extends PolymorphicGenerics> = {
|
|
|
396
531
|
displayName?: string;
|
|
397
532
|
};
|
|
398
533
|
|
|
399
|
-
|
|
534
|
+
/**
|
|
535
|
+
* Creates a polymorphic Vue component with praxis-kit contracts applied.
|
|
536
|
+
*
|
|
537
|
+
* ```ts
|
|
538
|
+
* const Button = createContractComponent({
|
|
539
|
+
* tag: 'button',
|
|
540
|
+
* name: 'Button',
|
|
541
|
+
* styling: {
|
|
542
|
+
* base: 'btn',
|
|
543
|
+
* variants: { intent: { primary: 'btn--primary', ghost: 'btn--ghost' } },
|
|
544
|
+
* defaults: { intent: 'primary' },
|
|
545
|
+
* },
|
|
546
|
+
* })
|
|
547
|
+
* ```
|
|
548
|
+
*
|
|
549
|
+
* ```vue
|
|
550
|
+
* <Button intent="ghost" as="a" href="/home">Home</Button>
|
|
551
|
+
* ```
|
|
552
|
+
*
|
|
553
|
+
* Pass `subComponents` to attach named sub-components (`Card.Header`) and `onElement` to run
|
|
554
|
+
* setup once the real DOM element exists — both purely additive on top of the generated
|
|
555
|
+
* component.
|
|
556
|
+
*/
|
|
557
|
+
declare function createContractComponent<TDefault extends ElementType, Props extends UnknownProps = EmptyRecord, Variants extends Readonly<VariantMap> = NoVariants, TPreset extends RecipeMap<Variants> = NoPreset, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory, TSubComponents extends Readonly<AnyRecord> = EmptyRecord>(options: VueFactoryOptions<TDefault, Props, Variants, TPreset, TPlugin> & {
|
|
400
558
|
readonly subComponents?: TSubComponents;
|
|
401
|
-
}): PolymorphicComponent<PolymorphicGenerics<TDefault, Props
|
|
559
|
+
}): MergeRecords<PolymorphicComponent<PolymorphicGenerics<TDefault, MergeRecords<Props, ExtractPluginProps<TPlugin>>, Variants, TPreset>>, TSubComponents>;
|
|
402
560
|
|
|
403
561
|
export { type AnyFactoryOptions, type ElementType, type EmptyRecord, type PolymorphicComponent, type PolymorphicGenerics, type PolymorphicProps, type PolymorphicWithAsChild, Slottable, type SlottableProps, type VueFactoryOptions, createContractComponent, defineContractComponent };
|
package/dist/vue/index.js
CHANGED
|
@@ -3811,7 +3811,10 @@ function createContractComponent(options) {
|
|
|
3811
3811
|
}
|
|
3812
3812
|
boundElement = element;
|
|
3813
3813
|
if (element) {
|
|
3814
|
-
cleanup = onElement(
|
|
3814
|
+
cleanup = onElement(
|
|
3815
|
+
element,
|
|
3816
|
+
() => attrs
|
|
3817
|
+
) ?? void 0;
|
|
3815
3818
|
}
|
|
3816
3819
|
} : void 0;
|
|
3817
3820
|
return () => render({ ...bundle, state: state.value, slots, elementRef: onElementRef });
|
package/dist/web/index.d.ts
CHANGED
|
@@ -1,15 +1,65 @@
|
|
|
1
1
|
import { RequireAtLeastOne, Simplify, ReadonlyDeep } from 'type-fest';
|
|
2
2
|
import { Diagnostics, DiagnosticInput, DiagnosticsMode } 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>;
|
|
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>;
|
|
24
|
+
/**
|
|
25
|
+
* Default `Variants` type for components that declare no variants.
|
|
26
|
+
*
|
|
27
|
+
* Structurally identical to `Readonly<EmptyRecord>`, but named separately so
|
|
28
|
+
* editor hovers remain self-descriptive.
|
|
29
|
+
*/
|
|
30
|
+
type NoVariants = Readonly<EmptyRecord>;
|
|
31
|
+
/**
|
|
32
|
+
* Default `TPreset` type for components that declare no named presets.
|
|
33
|
+
*
|
|
34
|
+
* Structurally identical to `Readonly<EmptyRecord>`, but named separately so
|
|
35
|
+
* editor hovers remain self-descriptive.
|
|
36
|
+
*/
|
|
37
|
+
type NoPreset = Readonly<EmptyRecord>;
|
|
38
|
+
/**
|
|
39
|
+
* Fallback for `ExtractPluginProps<TPlugin>` when a plugin contributes no
|
|
40
|
+
* props, including the no-plugin case.
|
|
41
|
+
*
|
|
42
|
+
* Structurally identical to `EmptyRecord`, but named separately so editor
|
|
43
|
+
* hovers remain self-descriptive.
|
|
44
|
+
*/
|
|
45
|
+
type NoPluginProps = EmptyRecord;
|
|
9
46
|
|
|
10
47
|
type IntrinsicTag = keyof HTMLElementTagNameMap;
|
|
11
48
|
|
|
12
49
|
type ElementType = IntrinsicTag | (string & {});
|
|
50
|
+
/**
|
|
51
|
+
* Resolves a component's default tag to its real DOM interface — `HTMLDialogElement` for
|
|
52
|
+
* `'dialog'`, `HTMLDetailsElement` for `'details'`, and so on — falling back to `HTMLElement`
|
|
53
|
+
* for custom-element tags or anything not in `HTMLElementTagNameMap`. Used to type
|
|
54
|
+
* `FactoryOptions.onElement`'s `element` param so component authors get direct, correctly-typed
|
|
55
|
+
* access to tag-specific native members (`dialogEl.showModal()`) without an unsafe cast.
|
|
56
|
+
*
|
|
57
|
+
* The fallback is `HTMLElement`, not the more generic `Element` — every tag reachable through
|
|
58
|
+
* `IntrinsicTag` extends it, and so does every custom element per spec, so members `HTMLElement`
|
|
59
|
+
* itself declares (`showPopover()`/`hidePopover()`/`togglePopover()`, the `popover` attribute)
|
|
60
|
+
* stay directly accessible even for tags with no dedicated entry in `HTMLElementTagNameMap`.
|
|
61
|
+
*/
|
|
62
|
+
type ElementForTag<TDefault extends ElementType> = TDefault extends keyof HTMLElementTagNameMap ? HTMLElementTagNameMap[TDefault] : HTMLElement;
|
|
13
63
|
|
|
14
64
|
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
65
|
type KnownAriaRole = (typeof KNOWN_ARIA_ROLES)[number];
|
|
@@ -171,7 +221,7 @@ type ClassPluginFactory<TProps extends AnyRecord = EmptyRecord> = <V extends Var
|
|
|
171
221
|
* wherever a factory's concrete plugin-props shape isn't tracked (factory generics,
|
|
172
222
|
* capability wiring). */
|
|
173
223
|
type AnyClassPluginFactory = ClassPluginFactory<AnyRecord> | undefined;
|
|
174
|
-
type ExtractPluginProps<TPlugin extends AnyClassPluginFactory> = TPlugin extends ClassPluginFactory<infer T> ? string extends keyof T ?
|
|
224
|
+
type ExtractPluginProps<TPlugin extends AnyClassPluginFactory> = TPlugin extends ClassPluginFactory<infer T> ? string extends keyof T ? NoPluginProps : T : NoPluginProps;
|
|
175
225
|
|
|
176
226
|
type AriaContext = {
|
|
177
227
|
readonly tag: IntrinsicTag;
|
|
@@ -235,6 +285,12 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
|
|
|
235
285
|
* `@praxis-kit/diagnostics`.
|
|
236
286
|
*/
|
|
237
287
|
readonly diagnostics?: Diagnostics | DiagnosticsMode;
|
|
288
|
+
/**
|
|
289
|
+
* ARIA/accessibility rules evaluated against the resolved tag and props on every render.
|
|
290
|
+
* Each rule is a function receiving the current context and returning zero or more
|
|
291
|
+
* violations, some of which can carry an auto-applicable fix (see `createRemoveAttributeRule`
|
|
292
|
+
* and friends in `praxis-kit/contract`).
|
|
293
|
+
*/
|
|
238
294
|
readonly aria?: readonly AriaRule[];
|
|
239
295
|
/**
|
|
240
296
|
* Rules that need `AriaPolicyEngine`'s fix-application/caching machinery
|
|
@@ -246,6 +302,11 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
|
|
|
246
302
|
* misleading `aria` name to get the machinery it needs.
|
|
247
303
|
*/
|
|
248
304
|
readonly rules?: readonly AriaRule[];
|
|
305
|
+
/**
|
|
306
|
+
* Declares which children are valid, by name, match predicate, and cardinality (e.g. "at
|
|
307
|
+
* least 1, at most 4 `Button` children"). Open by default — children matching no rule are
|
|
308
|
+
* still allowed unless `exclusiveChildren` is set.
|
|
309
|
+
*/
|
|
249
310
|
readonly children?: readonly ChildRuleInput[];
|
|
250
311
|
/**
|
|
251
312
|
* When true, only children matching a `children` rule (or text, per `allowText`)
|
|
@@ -258,19 +319,49 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
|
|
|
258
319
|
* or any listed rule. Default: true.
|
|
259
320
|
*/
|
|
260
321
|
readonly allowText?: boolean;
|
|
322
|
+
/**
|
|
323
|
+
* Prop transforms composed with the component's own `normalize` (from `FactoryOptions`) and
|
|
324
|
+
* run before it. Unlike `normalize`, these live in the enforcement bucket because they
|
|
325
|
+
* typically encode a built-in HTML/ARIA fact rather than component-specific behavior.
|
|
326
|
+
*/
|
|
261
327
|
readonly props?: readonly PropNormalizer[];
|
|
262
328
|
/** Restricts the `as` prop to this set of tags. Violations route through diagnostics. */
|
|
263
329
|
readonly allowedAs?: readonly TAllowed[];
|
|
264
330
|
};
|
|
265
331
|
|
|
266
332
|
type StylingOptions<V extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<V> = Readonly<EmptyRecord>, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory> = {
|
|
333
|
+
/** Class applied to every instance regardless of variant selection. */
|
|
267
334
|
readonly base?: ClassName;
|
|
335
|
+
/**
|
|
336
|
+
* Named variant groups (e.g. `intent`, `size`), each mapping its possible values to a
|
|
337
|
+
* class string. A consumer selects a value per group as a prop (`<Button intent="primary">`).
|
|
338
|
+
*/
|
|
268
339
|
readonly variants?: V;
|
|
340
|
+
/** Value used for a variant group when the consumer doesn't pass one explicitly. */
|
|
269
341
|
readonly defaults?: Partial<DefaultVariants<V>>;
|
|
342
|
+
/**
|
|
343
|
+
* Applies an extra class only when a specific *combination* of variant selections matches —
|
|
344
|
+
* for cases `variants` alone can't express (e.g. `intent: 'primary'` + `size: 'lg'` together
|
|
345
|
+
* need a class neither variant would add on its own).
|
|
346
|
+
*/
|
|
270
347
|
readonly compounds?: readonly CompoundVariant<V>[];
|
|
348
|
+
/**
|
|
349
|
+
* Named bundles of variant values, selectable as a single unit via the `recipe` prop (e.g.
|
|
350
|
+
* `<Button recipe="cta">` instead of setting `intent`/`size` individually).
|
|
351
|
+
*/
|
|
271
352
|
readonly presets?: TPreset;
|
|
353
|
+
/** Maps a resolved tag directly to a raw class string, independent of the variant system. */
|
|
272
354
|
readonly tags?: Readonly<TagMap>;
|
|
355
|
+
/**
|
|
356
|
+
* A `ClassPluginFactory` (e.g. the Tailwind layout pipeline) that extends class resolution
|
|
357
|
+
* with its own owned props, layered on top of `variants`/`presets`/`tags`.
|
|
358
|
+
*/
|
|
273
359
|
readonly plugin?: TPlugin;
|
|
360
|
+
/**
|
|
361
|
+
* A cache-key → resolved-class-string lookup for every statically-known variant
|
|
362
|
+
* combination, skipping runtime class computation entirely when a match is found. Normally
|
|
363
|
+
* generated by a build-time class-extraction plugin rather than hand-authored.
|
|
364
|
+
*/
|
|
274
365
|
readonly precomputedClasses?: Readonly<Record<string, string>>;
|
|
275
366
|
};
|
|
276
367
|
|
|
@@ -279,11 +370,21 @@ type NormalizeFn<Props extends AnyRecord = AnyRecord> = {
|
|
|
279
370
|
}['normalize'];
|
|
280
371
|
type AnyFactoryOptions = FactoryOptions<ElementType, AnyRecord, VariantMap, RecipeMap<VariantMap>, AnyClassPluginFactory>;
|
|
281
372
|
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> = {
|
|
373
|
+
/** The intrinsic tag the component renders by default. Overridable per instance via `as`. */
|
|
282
374
|
readonly tag?: TDefault;
|
|
375
|
+
/** Display name used in diagnostics, dev tools, and generated component naming. */
|
|
283
376
|
readonly name?: string;
|
|
377
|
+
/** Values used for the component's own (non-variant) props when the consumer omits them. */
|
|
284
378
|
readonly defaults?: Partial<NoInfer<Props>>;
|
|
379
|
+
/**
|
|
380
|
+
* A pure `(props) => props` transform run on every render, after `enforcement.props`'s
|
|
381
|
+
* normalizers see the same input. Use this for component-specific prop shaping — anything
|
|
382
|
+
* that depends on live instance state or the real DOM element belongs in `onElement` instead.
|
|
383
|
+
*/
|
|
285
384
|
readonly normalize?: NormalizeFn<NoInfer<Props>>;
|
|
385
|
+
/** Variant groups, base classes, presets, and the optional class-resolution plugin. */
|
|
286
386
|
readonly styling?: StylingOptions<V, TPreset, TPlugin>;
|
|
387
|
+
/** ARIA rules, child-content contracts, and other runtime validation for this component. */
|
|
287
388
|
readonly enforcement?: EnforcementOptions<TAllowed>;
|
|
288
389
|
/**
|
|
289
390
|
* Adapter-resolved diagnostics default, spread in by `resolveAdapterCommonOptions`. Not meant to
|
|
@@ -307,15 +408,37 @@ type FactoryOptions<TDefault extends ElementType = ElementType, Props extends An
|
|
|
307
408
|
* no prop-based equivalent), not for anything expressible as a plain
|
|
308
409
|
* prop.
|
|
309
410
|
*
|
|
411
|
+
* `element` is typed to the real DOM interface of every tag the rendered
|
|
412
|
+
* element could actually be — `TDefault` plus whatever `enforcement.allowed`
|
|
413
|
+
* permits via `as` (`HTMLDialogElement` for `tag: 'dialog'`,
|
|
414
|
+
* `HTMLDetailsElement` for `tag: 'details'`, and so on) — no cast needed to
|
|
415
|
+
* reach tag-specific members. A component that leaves `allowed`
|
|
416
|
+
* unconstrained (any tag reachable via `as`) falls back to `HTMLElement`,
|
|
417
|
+
* which still covers members every element shares (`showPopover()` and
|
|
418
|
+
* friends); restrict `enforcement.allowed` to the tags `onElement`
|
|
419
|
+
* actually knows how to handle to get real narrowing.
|
|
420
|
+
*
|
|
310
421
|
* `getProps` returns the instance's *current* resolved props at call
|
|
311
422
|
* time — read it from inside a listener registered once at mount, rather
|
|
312
423
|
* than re-subscribing on every prop change.
|
|
313
424
|
*
|
|
314
425
|
* Return a cleanup function to run when the instance unmounts.
|
|
315
426
|
*/
|
|
316
|
-
readonly onElement?: (element:
|
|
427
|
+
readonly onElement?: (element: ElementForTag<TDefault | TAllowed>, getProps: () => Readonly<Props>) => void | (() => void);
|
|
317
428
|
};
|
|
318
429
|
|
|
430
|
+
/**
|
|
431
|
+
* Determines whether a prop should be stripped before forwarding to the
|
|
432
|
+
* rendered element.
|
|
433
|
+
*
|
|
434
|
+
* Returning `true` excludes the prop from the output; returning `false`
|
|
435
|
+
* keeps it. This is the inverse polarity of `shouldForwardProp`-style
|
|
436
|
+
* predicates (Emotion/styled-components), where `true` means include.
|
|
437
|
+
*
|
|
438
|
+
* @param key - The prop name being evaluated.
|
|
439
|
+
* @param variantKeys - The set of configured variant prop names.
|
|
440
|
+
* @returns `true` to strip the prop; `false` to forward it.
|
|
441
|
+
*/
|
|
319
442
|
type FilterPredicate = (key: string, variantKeys: ReadonlySet<string>) => boolean;
|
|
320
443
|
|
|
321
444
|
declare function defineContractComponent<O extends FactoryOptions>(options: O): <R>(factory: (options: O) => R) => R;
|
|
@@ -326,7 +449,7 @@ declare function defineContractComponent<O extends FactoryOptions>(options: O):
|
|
|
326
449
|
* Identical shape to LitFactoryOptions — a plain HTMLElement subclass with
|
|
327
450
|
* no framework dependency. Light DOM only; Shadow DOM is out of scope.
|
|
328
451
|
*/
|
|
329
|
-
type WebFactoryOptions<TDefault extends ElementType = ElementType, TProps extends AnyRecord = EmptyRecord, TVariants extends Readonly<VariantMap> =
|
|
452
|
+
type WebFactoryOptions<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> & {
|
|
330
453
|
readonly filterProps?: FilterPredicate;
|
|
331
454
|
};
|
|
332
455
|
|
|
@@ -337,7 +460,7 @@ type UnknownProps = AnyRecord;
|
|
|
337
460
|
* Describes the public contract without exposing HTMLElement's internal members.
|
|
338
461
|
* Variant key instance properties are typed via TVariants.
|
|
339
462
|
*/
|
|
340
|
-
type WebContractComponent<TVariants extends Readonly<VariantMap> =
|
|
463
|
+
type WebContractComponent<TVariants extends Readonly<VariantMap> = NoVariants, TPluginProps extends AnyRecord = EmptyRecord> = {
|
|
341
464
|
new (): HTMLElement & {
|
|
342
465
|
as: string | undefined;
|
|
343
466
|
recipe: string | undefined;
|
|
@@ -378,7 +501,7 @@ type WebContractComponent<TVariants extends Readonly<VariantMap> = Readonly<Empt
|
|
|
378
501
|
* For non-reactive attributes (`aria-*`, `role`, `data-*`) call `element.update()`
|
|
379
502
|
* after setting them to trigger an explicit pipeline re-run.
|
|
380
503
|
*/
|
|
381
|
-
declare function createContractComponent<TDefault extends ElementType, TProps extends UnknownProps = EmptyRecord, TVariants extends Readonly<VariantMap> =
|
|
504
|
+
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: WebFactoryOptions<TDefault, TProps, TVariants, TPreset, TPlugin> & {
|
|
382
505
|
readonly subComponents?: TSubComponents;
|
|
383
506
|
}): WebContractComponent<TVariants, ExtractPluginProps<TPlugin>> & TSubComponents;
|
|
384
507
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "praxis-kit",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./react": {
|
|
@@ -203,11 +203,11 @@
|
|
|
203
203
|
"typescript": "^6.0.3",
|
|
204
204
|
"vite": "^8.1.5",
|
|
205
205
|
"vue": "^3.5.40",
|
|
206
|
-
"@praxis-kit/adapter-utils": "0.0.0",
|
|
207
206
|
"@praxis-kit/core": "0.0.0",
|
|
207
|
+
"@praxis-kit/adapter-utils": "0.0.0",
|
|
208
|
+
"@praxis-kit/primitive": "0.0.0",
|
|
208
209
|
"@praxis-kit/diagnostics": "0.0.0",
|
|
209
210
|
"@praxis-kit/pipeline": "0.0.0",
|
|
210
|
-
"@praxis-kit/primitive": "0.0.0",
|
|
211
211
|
"@praxis-kit/vite-plugin": "0.0.0"
|
|
212
212
|
},
|
|
213
213
|
"publishConfig": {
|
|
File without changes
|