praxis-kit 7.0.0 → 7.4.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/{chunk-35CJAOJW.js → chunk-EIKPSL26.js} +63 -6
- package/dist/codemod/index.js +121 -72
- package/dist/contract/index.d.ts +92 -0
- package/dist/guards/index.d.ts +6 -0
- package/dist/guards/index.js +4 -4
- package/dist/html/index.d.ts +6 -0
- package/dist/lit/index.d.ts +158 -6
- package/dist/lit/index.js +83 -9
- package/dist/preact/index.d.ts +164 -3
- package/dist/preact/index.js +104 -31
- package/dist/react/index.d.ts +26 -3
- package/dist/react/index.js +34 -8
- package/dist/react/legacy.d.ts +25 -3
- package/dist/react/legacy.js +17 -3
- package/dist/{react-options-Cm99IE5J.d.ts → react-options-BnjZpdVh.d.ts} +141 -3
- package/dist/solid/index.d.ts +163 -3
- package/dist/solid/index.js +100 -17
- package/dist/svelte/Polymorphic.svelte +25 -0
- package/dist/svelte/index.d.ts +231 -13
- package/dist/svelte/index.js +16 -8
- package/dist/tailwind/index.d.ts +12 -0
- package/dist/ts-plugin/index.cjs +5 -2
- package/dist/vite-plugin/index.d.ts +6 -0
- package/dist/vue/index.d.ts +166 -3
- package/dist/vue/index.js +119 -37
- package/dist/web/index.d.ts +132 -4
- package/dist/web/index.js +94 -13
- package/package.json +4 -4
package/dist/preact/index.d.ts
CHANGED
|
@@ -2,9 +2,72 @@ import { RequireAtLeastOne, Simplify, ReadonlyDeep, OmitIndexSignature } from 't
|
|
|
2
2
|
import { Diagnostics, DiagnosticInput, DiagnosticsMode } from '../_shared/diagnostics.js';
|
|
3
3
|
import { ComponentChildren, VNode, ComponentType, JSX, Ref } from 'preact';
|
|
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>;
|
|
20
|
+
/**
|
|
21
|
+
* A compound component's named sub-components, for example
|
|
22
|
+
* `{ Header, Content, Footer }`.
|
|
23
|
+
*/
|
|
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;
|
|
8
71
|
|
|
9
72
|
type IntrinsicTag = keyof HTMLElementTagNameMap;
|
|
10
73
|
|
|
@@ -187,7 +250,7 @@ type ClassPluginFactory<TProps extends AnyRecord = EmptyRecord> = <V extends Var
|
|
|
187
250
|
* wherever a factory's concrete plugin-props shape isn't tracked (factory generics,
|
|
188
251
|
* capability wiring). */
|
|
189
252
|
type AnyClassPluginFactory = ClassPluginFactory<AnyRecord> | undefined;
|
|
190
|
-
type ExtractPluginProps<TPlugin extends AnyClassPluginFactory> = TPlugin extends ClassPluginFactory<infer T> ? string extends keyof T ?
|
|
253
|
+
type ExtractPluginProps<TPlugin extends AnyClassPluginFactory> = TPlugin extends ClassPluginFactory<infer T> ? string extends keyof T ? NoPluginProps : T : NoPluginProps;
|
|
191
254
|
|
|
192
255
|
type AriaContext = {
|
|
193
256
|
readonly tag: IntrinsicTag;
|
|
@@ -251,6 +314,12 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
|
|
|
251
314
|
* `@praxis-kit/diagnostics`.
|
|
252
315
|
*/
|
|
253
316
|
readonly diagnostics?: Diagnostics | DiagnosticsMode;
|
|
317
|
+
/**
|
|
318
|
+
* ARIA/accessibility rules evaluated against the resolved tag and props on every render.
|
|
319
|
+
* Each rule is a function receiving the current context and returning zero or more
|
|
320
|
+
* violations, some of which can carry an auto-applicable fix (see `createRemoveAttributeRule`
|
|
321
|
+
* and friends in `praxis-kit/contract`).
|
|
322
|
+
*/
|
|
254
323
|
readonly aria?: readonly AriaRule[];
|
|
255
324
|
/**
|
|
256
325
|
* Rules that need `AriaPolicyEngine`'s fix-application/caching machinery
|
|
@@ -262,6 +331,11 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
|
|
|
262
331
|
* misleading `aria` name to get the machinery it needs.
|
|
263
332
|
*/
|
|
264
333
|
readonly rules?: readonly AriaRule[];
|
|
334
|
+
/**
|
|
335
|
+
* Declares which children are valid, by name, match predicate, and cardinality (e.g. "at
|
|
336
|
+
* least 1, at most 4 `Button` children"). Open by default — children matching no rule are
|
|
337
|
+
* still allowed unless `exclusiveChildren` is set.
|
|
338
|
+
*/
|
|
265
339
|
readonly children?: readonly ChildRuleInput[];
|
|
266
340
|
/**
|
|
267
341
|
* When true, only children matching a `children` rule (or text, per `allowText`)
|
|
@@ -274,19 +348,49 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
|
|
|
274
348
|
* or any listed rule. Default: true.
|
|
275
349
|
*/
|
|
276
350
|
readonly allowText?: boolean;
|
|
351
|
+
/**
|
|
352
|
+
* Prop transforms composed with the component's own `normalize` (from `FactoryOptions`) and
|
|
353
|
+
* run before it. Unlike `normalize`, these live in the enforcement bucket because they
|
|
354
|
+
* typically encode a built-in HTML/ARIA fact rather than component-specific behavior.
|
|
355
|
+
*/
|
|
277
356
|
readonly props?: readonly PropNormalizer[];
|
|
278
357
|
/** Restricts the `as` prop to this set of tags. Violations route through diagnostics. */
|
|
279
358
|
readonly allowedAs?: readonly TAllowed[];
|
|
280
359
|
};
|
|
281
360
|
|
|
282
361
|
type StylingOptions<V extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<V> = Readonly<EmptyRecord>, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory> = {
|
|
362
|
+
/** Class applied to every instance regardless of variant selection. */
|
|
283
363
|
readonly base?: ClassName;
|
|
364
|
+
/**
|
|
365
|
+
* Named variant groups (e.g. `intent`, `size`), each mapping its possible values to a
|
|
366
|
+
* class string. A consumer selects a value per group as a prop (`<Button intent="primary">`).
|
|
367
|
+
*/
|
|
284
368
|
readonly variants?: V;
|
|
369
|
+
/** Value used for a variant group when the consumer doesn't pass one explicitly. */
|
|
285
370
|
readonly defaults?: Partial<DefaultVariants<V>>;
|
|
371
|
+
/**
|
|
372
|
+
* Applies an extra class only when a specific *combination* of variant selections matches —
|
|
373
|
+
* for cases `variants` alone can't express (e.g. `intent: 'primary'` + `size: 'lg'` together
|
|
374
|
+
* need a class neither variant would add on its own).
|
|
375
|
+
*/
|
|
286
376
|
readonly compounds?: readonly CompoundVariant<V>[];
|
|
377
|
+
/**
|
|
378
|
+
* Named bundles of variant values, selectable as a single unit via the `recipe` prop (e.g.
|
|
379
|
+
* `<Button recipe="cta">` instead of setting `intent`/`size` individually).
|
|
380
|
+
*/
|
|
287
381
|
readonly presets?: TPreset;
|
|
382
|
+
/** Maps a resolved tag directly to a raw class string, independent of the variant system. */
|
|
288
383
|
readonly tags?: Readonly<TagMap>;
|
|
384
|
+
/**
|
|
385
|
+
* A `ClassPluginFactory` (e.g. the Tailwind layout pipeline) that extends class resolution
|
|
386
|
+
* with its own owned props, layered on top of `variants`/`presets`/`tags`.
|
|
387
|
+
*/
|
|
289
388
|
readonly plugin?: TPlugin;
|
|
389
|
+
/**
|
|
390
|
+
* A cache-key → resolved-class-string lookup for every statically-known variant
|
|
391
|
+
* combination, skipping runtime class computation entirely when a match is found. Normally
|
|
392
|
+
* generated by a build-time class-extraction plugin rather than hand-authored.
|
|
393
|
+
*/
|
|
290
394
|
readonly precomputedClasses?: Readonly<Record<string, string>>;
|
|
291
395
|
};
|
|
292
396
|
|
|
@@ -295,17 +399,51 @@ type NormalizeFn<Props extends AnyRecord = AnyRecord> = {
|
|
|
295
399
|
}['normalize'];
|
|
296
400
|
type AnyFactoryOptions = FactoryOptions<ElementType, AnyRecord, VariantMap, RecipeMap<VariantMap>, AnyClassPluginFactory>;
|
|
297
401
|
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> = {
|
|
402
|
+
/** The intrinsic tag the component renders by default. Overridable per instance via `as`. */
|
|
298
403
|
readonly tag?: TDefault;
|
|
404
|
+
/** Display name used in diagnostics, dev tools, and generated component naming. */
|
|
299
405
|
readonly name?: string;
|
|
406
|
+
/** Values used for the component's own (non-variant) props when the consumer omits them. */
|
|
300
407
|
readonly defaults?: Partial<NoInfer<Props>>;
|
|
408
|
+
/**
|
|
409
|
+
* A pure `(props) => props` transform run on every render, after `enforcement.props`'s
|
|
410
|
+
* normalizers see the same input. Use this for component-specific prop shaping — anything
|
|
411
|
+
* that depends on live instance state or the real DOM element belongs in `onElement` instead.
|
|
412
|
+
*/
|
|
301
413
|
readonly normalize?: NormalizeFn<NoInfer<Props>>;
|
|
414
|
+
/** Variant groups, base classes, presets, and the optional class-resolution plugin. */
|
|
302
415
|
readonly styling?: StylingOptions<V, TPreset, TPlugin>;
|
|
416
|
+
/** ARIA rules, child-content contracts, and other runtime validation for this component. */
|
|
303
417
|
readonly enforcement?: EnforcementOptions<TAllowed>;
|
|
304
418
|
/**
|
|
305
419
|
* Adapter-resolved diagnostics default, spread in by `resolveAdapterCommonOptions`. Not meant to
|
|
306
420
|
* be set directly by component authors — use `enforcement.diagnostics` to override per component.
|
|
307
421
|
*/
|
|
308
422
|
readonly diagnostics?: Diagnostics;
|
|
423
|
+
/**
|
|
424
|
+
* Sub-components to attach to the generated root component, producing a
|
|
425
|
+
* compound component API (for example, `Card.Header`, `Card.Content`,
|
|
426
|
+
* and `Card.Footer`). Purely additive — has no effect on
|
|
427
|
+
* `enforcement.children`; author child rules explicitly if the component
|
|
428
|
+
* needs to validate its children.
|
|
429
|
+
*/
|
|
430
|
+
readonly subComponents?: SubComponentMap;
|
|
431
|
+
/**
|
|
432
|
+
* Called once per instance, when the real underlying DOM element first
|
|
433
|
+
* exists, in every adapter — via that adapter's own native mount
|
|
434
|
+
* lifecycle, never through the props/attribute pipeline. Use this for
|
|
435
|
+
* wiring that needs the actual element (native imperative methods like
|
|
436
|
+
* `dialogEl.showModal()`, native events like `close`/`cancel` that have
|
|
437
|
+
* no prop-based equivalent), not for anything expressible as a plain
|
|
438
|
+
* prop.
|
|
439
|
+
*
|
|
440
|
+
* `getProps` returns the instance's *current* resolved props at call
|
|
441
|
+
* time — read it from inside a listener registered once at mount, rather
|
|
442
|
+
* than re-subscribing on every prop change.
|
|
443
|
+
*
|
|
444
|
+
* Return a cleanup function to run when the instance unmounts.
|
|
445
|
+
*/
|
|
446
|
+
readonly onElement?: (element: Element, getProps: () => Readonly<Props>) => void | (() => void);
|
|
309
447
|
};
|
|
310
448
|
|
|
311
449
|
declare function defineContractComponent<O extends FactoryOptions>(options: O): <R>(factory: (options: O) => R) => R;
|
|
@@ -319,7 +457,7 @@ type UnknownProps = AnyRecord;
|
|
|
319
457
|
type SlotComponent = ComponentType<UnknownProps>;
|
|
320
458
|
type AnyVNode = VNode<any>;
|
|
321
459
|
|
|
322
|
-
type PreactFactoryOptions<TDefault extends ElementType, Props extends UnknownProps, Variants extends Readonly<VariantMap>, TPreset extends RecipeMap<Variants> =
|
|
460
|
+
type PreactFactoryOptions<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> & {
|
|
323
461
|
/** Component used to render the asChild slot. Defaults to the built-in Slot. */
|
|
324
462
|
slotComponent?: SlotComponent;
|
|
325
463
|
/**
|
|
@@ -362,6 +500,29 @@ type PolymorphicComponent<G extends PolymorphicGenerics> = {
|
|
|
362
500
|
displayName?: string;
|
|
363
501
|
};
|
|
364
502
|
|
|
365
|
-
|
|
503
|
+
/**
|
|
504
|
+
* Creates a polymorphic Preact component with praxis-kit contracts applied.
|
|
505
|
+
*
|
|
506
|
+
* ```tsx
|
|
507
|
+
* const Button = createContractComponent({
|
|
508
|
+
* tag: 'button',
|
|
509
|
+
* name: 'Button',
|
|
510
|
+
* styling: {
|
|
511
|
+
* base: 'btn',
|
|
512
|
+
* variants: { intent: { primary: 'btn--primary', ghost: 'btn--ghost' } },
|
|
513
|
+
* defaults: { intent: 'primary' },
|
|
514
|
+
* },
|
|
515
|
+
* })
|
|
516
|
+
*
|
|
517
|
+
* <Button intent="ghost" as="a" href="/home">Home</Button>
|
|
518
|
+
* ```
|
|
519
|
+
*
|
|
520
|
+
* Returns a `forwardRef` component — `ref` is forwarded to the rendered host element. Pass
|
|
521
|
+
* `subComponents` to attach named sub-components (`Card.Header`) and `onElement` to run setup
|
|
522
|
+
* once the real DOM element exists.
|
|
523
|
+
*/
|
|
524
|
+
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: PreactFactoryOptions<TDefault, Props, Variants, TPreset, TPlugin> & {
|
|
525
|
+
readonly subComponents?: TSubComponents;
|
|
526
|
+
}): MergeRecords<PolymorphicComponent<PolymorphicGenerics<TDefault, MergeRecords<Props, ExtractPluginProps<TPlugin>>, Variants, TPreset>>, TSubComponents>;
|
|
366
527
|
|
|
367
528
|
export { type AnyFactoryOptions, type ElementRef, type ElementType, type EmptyRecord, type PolymorphicComponent, type PolymorphicGenerics, type PolymorphicProps, type PolymorphicWithAsChild, type PreactFactoryOptions, Slottable, createContractComponent, defineContractComponent };
|
package/dist/preact/index.js
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
// ../../lib/adapter-utils/src/invariant.ts
|
|
2
|
+
function panic(message) {
|
|
3
|
+
throw new Error(message);
|
|
4
|
+
}
|
|
5
|
+
function invariant(condition, message) {
|
|
6
|
+
if (!condition) panic(message);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// ../../lib/adapter-utils/src/runtime/apply-display-name.ts
|
|
10
|
+
function applyDisplayName(component, name) {
|
|
11
|
+
Object.assign(component, { displayName: name ?? "PolymorphicComponent" });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// ../../lib/adapter-utils/src/runtime/define-component.ts
|
|
15
|
+
function defineContractComponent(options) {
|
|
16
|
+
return (factory) => factory(options);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// ../../lib/adapter-utils/src/runtime/assemble-compound-component.ts
|
|
20
|
+
function assembleCompoundComponent(root, subComponents) {
|
|
21
|
+
if (!subComponents) return root;
|
|
22
|
+
return Object.assign(root, subComponents);
|
|
23
|
+
}
|
|
24
|
+
|
|
1
25
|
// ../../lib/primitive/src/tag/resolve-tag.ts
|
|
2
26
|
function makeResolveTag(defaultTag) {
|
|
3
27
|
return function tag(as) {
|
|
@@ -54,7 +78,7 @@ function isPlainObject(value) {
|
|
|
54
78
|
|
|
55
79
|
// ../../lib/primitive/src/rule/is-dynamic-rule.ts
|
|
56
80
|
function isDynamicRule(rule) {
|
|
57
|
-
return isObject(rule, true) && rule
|
|
81
|
+
return isObject(rule, true) && Reflect.get(rule, RULE_BRAND) === true;
|
|
58
82
|
}
|
|
59
83
|
|
|
60
84
|
// ../../lib/primitive/src/rule/resolve-rule.ts
|
|
@@ -703,17 +727,17 @@ var COMPONENT_DEFAULT_TAG = /* @__PURE__ */ Symbol.for("praxis.component-default
|
|
|
703
727
|
// ../../lib/primitive/src/guards/children/is-tag.ts
|
|
704
728
|
function getAsProp(child) {
|
|
705
729
|
if (!isObject(child) || !("props" in child)) return void 0;
|
|
706
|
-
const props = child
|
|
730
|
+
const { props } = child;
|
|
707
731
|
if (!isObject(props)) return void 0;
|
|
708
|
-
const as = props
|
|
732
|
+
const as = Reflect.get(props, "as");
|
|
709
733
|
return isString(as) && as !== "" ? as : void 0;
|
|
710
734
|
}
|
|
711
735
|
function getTag(child) {
|
|
712
736
|
if (!isObject(child) || !("type" in child)) return void 0;
|
|
713
|
-
const t = child
|
|
737
|
+
const { type: t } = child;
|
|
714
738
|
if (isString(t)) return t;
|
|
715
739
|
if (typeof t === "function" || isObject(t)) {
|
|
716
|
-
const defaultTag = t
|
|
740
|
+
const defaultTag = Reflect.get(t, COMPONENT_DEFAULT_TAG);
|
|
717
741
|
if (!isString(defaultTag)) return void 0;
|
|
718
742
|
return getAsProp(child) ?? defaultTag;
|
|
719
743
|
}
|
|
@@ -733,25 +757,34 @@ function isTag(...args) {
|
|
|
733
757
|
return tag !== void 0 && set2.has(tag);
|
|
734
758
|
}
|
|
735
759
|
|
|
736
|
-
// ../../
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
760
|
+
// ../../lib/adapter-utils/src/runtime/finalize-component.ts
|
|
761
|
+
function finalizeComponent(component, defaultTag, subComponents) {
|
|
762
|
+
if (typeof defaultTag === "string") {
|
|
763
|
+
Object.assign(component, { [COMPONENT_DEFAULT_TAG]: defaultTag });
|
|
764
|
+
}
|
|
765
|
+
return assembleCompoundComponent(component, subComponents);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
// ../../lib/adapter-utils/src/runtime/is-factory-options-like.ts
|
|
769
|
+
var FACTORY_OPTIONS_FIELD_VALIDATORS = {
|
|
770
|
+
tag: (v) => v === void 0 || isString(v),
|
|
771
|
+
name: (v) => v === void 0 || isString(v),
|
|
772
|
+
defaults: (v) => v === void 0 || isObject(v),
|
|
773
|
+
normalize: (v) => v === void 0 || isFunction(v),
|
|
774
|
+
styling: (v) => v === void 0 || isObject(v),
|
|
775
|
+
enforcement: (v) => v === void 0 || isObject(v),
|
|
776
|
+
diagnostics: (v) => v === void 0 || isObject(v),
|
|
777
|
+
subComponents: (v) => v === void 0 || isObject(v),
|
|
778
|
+
onElement: (v) => v === void 0 || isFunction(v)
|
|
779
|
+
};
|
|
780
|
+
function isFactoryOptionsLike(options, extraFieldValidators) {
|
|
781
|
+
if (!isObject(options)) return false;
|
|
782
|
+
const validators = { ...FACTORY_OPTIONS_FIELD_VALIDATORS, ...extraFieldValidators };
|
|
783
|
+
for (const [key, value] of Object.entries(options)) {
|
|
784
|
+
const validate = validators[key];
|
|
785
|
+
if (!validate || !validate(value)) return false;
|
|
786
|
+
}
|
|
787
|
+
return true;
|
|
755
788
|
}
|
|
756
789
|
|
|
757
790
|
// ../../lib/contract/src/aria/aria-role-policy.ts
|
|
@@ -2904,7 +2937,7 @@ function getChildProp(child, key) {
|
|
|
2904
2937
|
if (!isVNodeLike(child)) return void 0;
|
|
2905
2938
|
const { props } = child;
|
|
2906
2939
|
if (!isObject(props)) return void 0;
|
|
2907
|
-
return props
|
|
2940
|
+
return Reflect.get(props, key);
|
|
2908
2941
|
}
|
|
2909
2942
|
|
|
2910
2943
|
// ../core/src/html/contracts/aria/landmarks.ts
|
|
@@ -3619,6 +3652,10 @@ function applyMergePolicy(key, slotVal, childVal) {
|
|
|
3619
3652
|
return policyHandlers[classifyProp(key, slotVal, childVal)](slotVal, childVal);
|
|
3620
3653
|
}
|
|
3621
3654
|
|
|
3655
|
+
// ../../adapters/preact/src/create-contract-component.ts
|
|
3656
|
+
import { forwardRef as forwardRef2 } from "preact/compat";
|
|
3657
|
+
import { useCallback, useRef } from "preact/hooks";
|
|
3658
|
+
|
|
3622
3659
|
// ../../adapters/preact/src/render.tsx
|
|
3623
3660
|
import { h as h2 } from "preact";
|
|
3624
3661
|
|
|
@@ -3881,18 +3918,54 @@ function buildRuntime(options) {
|
|
|
3881
3918
|
return built;
|
|
3882
3919
|
}
|
|
3883
3920
|
|
|
3921
|
+
// ../../adapters/preact/src/is-polymorphic-component.ts
|
|
3922
|
+
function isPolymorphicComponent(value) {
|
|
3923
|
+
if (!isFunction(value)) return false;
|
|
3924
|
+
if (!("displayName" in value)) return true;
|
|
3925
|
+
return value.displayName === void 0 || isString(value.displayName);
|
|
3926
|
+
}
|
|
3927
|
+
|
|
3928
|
+
// ../../adapters/preact/src/to-preact-factory-options.ts
|
|
3929
|
+
var PREACT_FIELD_VALIDATORS = {
|
|
3930
|
+
slotComponent: (v) => v === void 0 || isFunction(v) || isObject(v),
|
|
3931
|
+
filterProps: (v) => v === void 0 || isFunction(v)
|
|
3932
|
+
};
|
|
3933
|
+
function isPreactFactoryOptions(options) {
|
|
3934
|
+
return isFactoryOptionsLike(options, PREACT_FIELD_VALIDATORS);
|
|
3935
|
+
}
|
|
3936
|
+
|
|
3884
3937
|
// ../../adapters/preact/src/create-contract-component.ts
|
|
3885
3938
|
function createContractComponent(options) {
|
|
3939
|
+
invariant(isPreactFactoryOptions(options), "options is not a valid PreactFactoryOptions object");
|
|
3886
3940
|
const bundle = buildRuntime(options);
|
|
3941
|
+
const { onElement } = options;
|
|
3887
3942
|
const Component = forwardRef2(function Component2(props, ref) {
|
|
3888
|
-
|
|
3943
|
+
const propsRef = useRef(props);
|
|
3944
|
+
propsRef.current = props;
|
|
3945
|
+
const cleanupRef = useRef(void 0);
|
|
3946
|
+
const onElementRef = useCallback((el) => {
|
|
3947
|
+
if (!onElement) return;
|
|
3948
|
+
if (el) {
|
|
3949
|
+
cleanupRef.current = onElement(el, () => propsRef.current) ?? void 0;
|
|
3950
|
+
} else {
|
|
3951
|
+
cleanupRef.current?.();
|
|
3952
|
+
cleanupRef.current = void 0;
|
|
3953
|
+
}
|
|
3954
|
+
}, []);
|
|
3955
|
+
const mergedRef = onElement ? mergeRefs(ref, onElementRef) : ref;
|
|
3956
|
+
return render({ ...bundle, props, ref: mergedRef });
|
|
3889
3957
|
});
|
|
3890
3958
|
applyDisplayName(Component, options.name);
|
|
3891
|
-
const
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3959
|
+
const assembled = finalizeComponent(
|
|
3960
|
+
Component,
|
|
3961
|
+
bundle.runtime.options.defaultTag,
|
|
3962
|
+
options.subComponents
|
|
3963
|
+
);
|
|
3964
|
+
invariant(
|
|
3965
|
+
isPolymorphicComponent(assembled),
|
|
3966
|
+
"Generated component failed to satisfy the PolymorphicComponent shape"
|
|
3967
|
+
);
|
|
3968
|
+
return assembled;
|
|
3896
3969
|
}
|
|
3897
3970
|
export {
|
|
3898
3971
|
Slottable,
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { U as UnknownProps, E as ElementType, a as EmptyRecord, V as VariantMap, R as RecipeMap, A as AnyClassPluginFactory,
|
|
2
|
-
export {
|
|
1
|
+
import { U as UnknownProps, E as ElementType, a as EmptyRecord, V as VariantMap, N as NoVariants, R as RecipeMap, b as NoPreset, A as AnyClassPluginFactory, c as AnyRecord, d as ReactFactoryOptions, M as MergeRecords, P as PolymorphicComponent, e as PolymorphicGenerics, f as ExtractPluginProps } from '../react-options-BnjZpdVh.js';
|
|
2
|
+
export { g as AnyFactoryOptions, h as ElementRef, F as FactoryOptions, i as PolymorphicProps, j as PolymorphicWithAsChild, k as PolymorphicWithRender, l as RenderCallbackProps, S as Slottable, m as SlottableProps, n as composeRefs, o as defineContractComponent, n as mergeRefs } from '../react-options-BnjZpdVh.js';
|
|
3
3
|
import * as react from 'react';
|
|
4
4
|
import { ReactElement, Ref } from 'react';
|
|
5
5
|
import 'type-fest';
|
|
@@ -22,7 +22,30 @@ type CloneInput = {
|
|
|
22
22
|
ref: NormalizedRef;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Creates a polymorphic React 19 component with praxis-kit contracts applied.
|
|
27
|
+
*
|
|
28
|
+
* ```tsx
|
|
29
|
+
* const Button = createContractComponent({
|
|
30
|
+
* tag: 'button',
|
|
31
|
+
* name: 'Button',
|
|
32
|
+
* styling: {
|
|
33
|
+
* base: 'btn',
|
|
34
|
+
* variants: { intent: { primary: 'btn--primary', ghost: 'btn--ghost' } },
|
|
35
|
+
* defaults: { intent: 'primary' },
|
|
36
|
+
* },
|
|
37
|
+
* })
|
|
38
|
+
*
|
|
39
|
+
* <Button intent="ghost" as="a" href="/home">Home</Button>
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* `ref` is accepted as a plain prop (React 19) and forwarded to the rendered host element or,
|
|
43
|
+
* with `asChild`, to the consumer's own element. Pass `subComponents` to attach named
|
|
44
|
+
* sub-components (`Card.Header`) and `onElement` to run setup once the real DOM element exists.
|
|
45
|
+
*/
|
|
46
|
+
declare function createContractComponent<TDefault extends ElementType, Props extends UnknownProps = EmptyRecord, Variants extends Readonly<VariantMap> = NoVariants, TPreset extends RecipeMap<Variants> = NoPreset, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory, TAllowed extends ElementType = ElementType, TSubComponents extends Readonly<AnyRecord> = EmptyRecord>(options: ReactFactoryOptions<TDefault, Props, Variants, TPreset, TPlugin, TAllowed> & {
|
|
47
|
+
readonly subComponents?: TSubComponents;
|
|
48
|
+
}): MergeRecords<PolymorphicComponent<PolymorphicGenerics<TDefault, MergeRecords<Props, ExtractPluginProps<TPlugin>>, Variants, TPreset, TAllowed>>, TSubComponents>;
|
|
26
49
|
|
|
27
50
|
type SlotProps = {
|
|
28
51
|
ref?: Ref<unknown> | null;
|
package/dist/react/index.js
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
import {
|
|
2
|
-
COMPONENT_DEFAULT_TAG,
|
|
3
2
|
SLOT_NAME,
|
|
4
3
|
Slottable,
|
|
5
4
|
applyDisplayName,
|
|
6
5
|
applySlot,
|
|
7
6
|
buildRuntime,
|
|
8
7
|
defineContractComponent,
|
|
8
|
+
finalizeComponent,
|
|
9
9
|
getElementRef,
|
|
10
10
|
getPropsRef,
|
|
11
11
|
hasWarningGetter,
|
|
12
|
+
invariant,
|
|
13
|
+
isPolymorphicComponent,
|
|
14
|
+
isReactFactoryOptions,
|
|
12
15
|
makeCloneSlotChild,
|
|
13
16
|
mergeRefs,
|
|
14
17
|
render
|
|
15
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-EIKPSL26.js";
|
|
19
|
+
|
|
20
|
+
// ../../adapters/react/src/current/create-contract-component.ts
|
|
21
|
+
import { useCallback, useRef } from "react";
|
|
16
22
|
|
|
17
23
|
// ../../adapters/react/src/current/slot/composeRefs.ts
|
|
18
24
|
function getChildRef(element) {
|
|
@@ -43,16 +49,36 @@ function buildRuntime2(options) {
|
|
|
43
49
|
|
|
44
50
|
// ../../adapters/react/src/current/create-contract-component.ts
|
|
45
51
|
function createContractComponent(options) {
|
|
52
|
+
invariant(isReactFactoryOptions(options), "options is not a valid ReactFactoryOptions object");
|
|
46
53
|
const bundle = buildRuntime2(options);
|
|
54
|
+
const { onElement } = options;
|
|
47
55
|
function Component({ ref, ...props }) {
|
|
48
|
-
|
|
56
|
+
const propsRef = useRef(props);
|
|
57
|
+
propsRef.current = props;
|
|
58
|
+
const cleanupRef = useRef(void 0);
|
|
59
|
+
const onElementRef = useCallback((el) => {
|
|
60
|
+
if (!onElement) return;
|
|
61
|
+
if (el) {
|
|
62
|
+
cleanupRef.current = onElement(el, () => propsRef.current) ?? void 0;
|
|
63
|
+
} else {
|
|
64
|
+
cleanupRef.current?.();
|
|
65
|
+
cleanupRef.current = void 0;
|
|
66
|
+
}
|
|
67
|
+
}, []);
|
|
68
|
+
const mergedRef = onElement ? mergeRefs(ref, onElementRef) : ref;
|
|
69
|
+
return render({ ...bundle, props, ref: mergedRef ?? null });
|
|
49
70
|
}
|
|
50
71
|
applyDisplayName(Component, options.name);
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
72
|
+
const assembled = finalizeComponent(
|
|
73
|
+
Component,
|
|
74
|
+
bundle.runtime.options.defaultTag,
|
|
75
|
+
options.subComponents
|
|
76
|
+
);
|
|
77
|
+
invariant(
|
|
78
|
+
isPolymorphicComponent(assembled),
|
|
79
|
+
"Generated component failed to satisfy the PolymorphicComponent shape"
|
|
80
|
+
);
|
|
81
|
+
return assembled;
|
|
56
82
|
}
|
|
57
83
|
export {
|
|
58
84
|
Slot,
|
package/dist/react/legacy.d.ts
CHANGED
|
@@ -1,10 +1,32 @@
|
|
|
1
|
-
import { E as ElementType, U as UnknownProps, a as EmptyRecord, V as VariantMap, R as RecipeMap, A as AnyClassPluginFactory,
|
|
2
|
-
export {
|
|
1
|
+
import { E as ElementType, U as UnknownProps, a as EmptyRecord, V as VariantMap, N as NoVariants, R as RecipeMap, b as NoPreset, A as AnyClassPluginFactory, d as ReactFactoryOptions, P as PolymorphicComponent, e as PolymorphicGenerics, M as MergeRecords, f as ExtractPluginProps } from '../react-options-BnjZpdVh.js';
|
|
2
|
+
export { g as AnyFactoryOptions, h as ElementRef, F as FactoryOptions, i as PolymorphicProps, j as PolymorphicWithAsChild, k as PolymorphicWithRender, l as RenderCallbackProps, S as Slottable, m as SlottableProps, o as defineContractComponent, n as mergeRefs } from '../react-options-BnjZpdVh.js';
|
|
3
3
|
import * as react from 'react';
|
|
4
4
|
import 'type-fest';
|
|
5
5
|
import '../_shared/diagnostics.js';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Creates a polymorphic React component with praxis-kit contracts applied, for React 18 and
|
|
9
|
+
* earlier (use `praxis-kit/react` instead on React 19, which accepts `ref` as a plain prop).
|
|
10
|
+
*
|
|
11
|
+
* ```tsx
|
|
12
|
+
* const Button = createContractComponent({
|
|
13
|
+
* tag: 'button',
|
|
14
|
+
* name: 'Button',
|
|
15
|
+
* styling: {
|
|
16
|
+
* base: 'btn',
|
|
17
|
+
* variants: { intent: { primary: 'btn--primary', ghost: 'btn--ghost' } },
|
|
18
|
+
* defaults: { intent: 'primary' },
|
|
19
|
+
* },
|
|
20
|
+
* })
|
|
21
|
+
*
|
|
22
|
+
* <Button intent="ghost" as="a" href="/home">Home</Button>
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* Returns a `forwardRef` component — `ref` is forwarded to the rendered host element the same
|
|
26
|
+
* way it works in `praxis-kit/react`. Pass `onElement` to run setup once the real DOM element
|
|
27
|
+
* exists; this adapter doesn't support `subComponents`.
|
|
28
|
+
*/
|
|
29
|
+
declare function createContractComponent<TDefault extends ElementType, Props extends UnknownProps = EmptyRecord, Variants extends Readonly<VariantMap> = NoVariants, TPreset extends RecipeMap<Variants> = NoPreset, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory, TAllowed extends ElementType = ElementType>(options: ReactFactoryOptions<TDefault, Props, Variants, TPreset, TPlugin, TAllowed>): PolymorphicComponent<PolymorphicGenerics<TDefault, MergeRecords<Props, ExtractPluginProps<TPlugin>>, Variants, TPreset, TAllowed>>;
|
|
8
30
|
|
|
9
31
|
type SlotProps = {
|
|
10
32
|
[key: string]: unknown;
|
package/dist/react/legacy.js
CHANGED
|
@@ -13,10 +13,10 @@ import {
|
|
|
13
13
|
makeCloneSlotChild,
|
|
14
14
|
mergeRefs,
|
|
15
15
|
render
|
|
16
|
-
} from "../chunk-
|
|
16
|
+
} from "../chunk-EIKPSL26.js";
|
|
17
17
|
|
|
18
18
|
// ../../adapters/react/src/legacy/create-contract-component.ts
|
|
19
|
-
import { forwardRef as forwardRef2 } from "react";
|
|
19
|
+
import { forwardRef as forwardRef2, useCallback, useRef } from "react";
|
|
20
20
|
|
|
21
21
|
// ../../adapters/react/src/legacy/slot/Slot.tsx
|
|
22
22
|
import { forwardRef } from "react";
|
|
@@ -49,8 +49,22 @@ function buildRuntime2(options) {
|
|
|
49
49
|
// ../../adapters/react/src/legacy/create-contract-component.ts
|
|
50
50
|
function createContractComponent(options) {
|
|
51
51
|
const bundle = buildRuntime2(options);
|
|
52
|
+
const { onElement } = options;
|
|
52
53
|
const Component = forwardRef2(function Component2(props, ref) {
|
|
53
|
-
|
|
54
|
+
const propsRef = useRef(props);
|
|
55
|
+
propsRef.current = props;
|
|
56
|
+
const cleanupRef = useRef(void 0);
|
|
57
|
+
const onElementRef = useCallback((el) => {
|
|
58
|
+
if (!onElement) return;
|
|
59
|
+
if (el) {
|
|
60
|
+
cleanupRef.current = onElement(el, () => propsRef.current) ?? void 0;
|
|
61
|
+
} else {
|
|
62
|
+
cleanupRef.current?.();
|
|
63
|
+
cleanupRef.current = void 0;
|
|
64
|
+
}
|
|
65
|
+
}, []);
|
|
66
|
+
const mergedRef = onElement ? mergeRefs(ref, onElementRef) : ref;
|
|
67
|
+
return render({ ...bundle, props, ref: mergedRef });
|
|
54
68
|
});
|
|
55
69
|
applyDisplayName(Component, options.name);
|
|
56
70
|
const defaultTag = bundle.runtime.options.defaultTag;
|