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/vue/index.d.ts
CHANGED
|
@@ -3,9 +3,72 @@ 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>;
|
|
21
|
+
/**
|
|
22
|
+
* A compound component's named sub-components, for example
|
|
23
|
+
* `{ Header, Content, Footer }`.
|
|
24
|
+
*/
|
|
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;
|
|
9
72
|
|
|
10
73
|
type IntrinsicTag = keyof HTMLElementTagNameMap;
|
|
11
74
|
|
|
@@ -188,7 +251,7 @@ type ClassPluginFactory<TProps extends AnyRecord = EmptyRecord> = <V extends Var
|
|
|
188
251
|
* wherever a factory's concrete plugin-props shape isn't tracked (factory generics,
|
|
189
252
|
* capability wiring). */
|
|
190
253
|
type AnyClassPluginFactory = ClassPluginFactory<AnyRecord> | undefined;
|
|
191
|
-
type ExtractPluginProps<TPlugin extends AnyClassPluginFactory> = TPlugin extends ClassPluginFactory<infer T> ? string extends keyof T ?
|
|
254
|
+
type ExtractPluginProps<TPlugin extends AnyClassPluginFactory> = TPlugin extends ClassPluginFactory<infer T> ? string extends keyof T ? NoPluginProps : T : NoPluginProps;
|
|
192
255
|
|
|
193
256
|
type AriaContext = {
|
|
194
257
|
readonly tag: IntrinsicTag;
|
|
@@ -252,6 +315,12 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
|
|
|
252
315
|
* `@praxis-kit/diagnostics`.
|
|
253
316
|
*/
|
|
254
317
|
readonly diagnostics?: Diagnostics | DiagnosticsMode;
|
|
318
|
+
/**
|
|
319
|
+
* ARIA/accessibility rules evaluated against the resolved tag and props on every render.
|
|
320
|
+
* Each rule is a function receiving the current context and returning zero or more
|
|
321
|
+
* violations, some of which can carry an auto-applicable fix (see `createRemoveAttributeRule`
|
|
322
|
+
* and friends in `praxis-kit/contract`).
|
|
323
|
+
*/
|
|
255
324
|
readonly aria?: readonly AriaRule[];
|
|
256
325
|
/**
|
|
257
326
|
* Rules that need `AriaPolicyEngine`'s fix-application/caching machinery
|
|
@@ -263,6 +332,11 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
|
|
|
263
332
|
* misleading `aria` name to get the machinery it needs.
|
|
264
333
|
*/
|
|
265
334
|
readonly rules?: readonly AriaRule[];
|
|
335
|
+
/**
|
|
336
|
+
* Declares which children are valid, by name, match predicate, and cardinality (e.g. "at
|
|
337
|
+
* least 1, at most 4 `Button` children"). Open by default — children matching no rule are
|
|
338
|
+
* still allowed unless `exclusiveChildren` is set.
|
|
339
|
+
*/
|
|
266
340
|
readonly children?: readonly ChildRuleInput[];
|
|
267
341
|
/**
|
|
268
342
|
* When true, only children matching a `children` rule (or text, per `allowText`)
|
|
@@ -275,19 +349,49 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
|
|
|
275
349
|
* or any listed rule. Default: true.
|
|
276
350
|
*/
|
|
277
351
|
readonly allowText?: boolean;
|
|
352
|
+
/**
|
|
353
|
+
* Prop transforms composed with the component's own `normalize` (from `FactoryOptions`) and
|
|
354
|
+
* run before it. Unlike `normalize`, these live in the enforcement bucket because they
|
|
355
|
+
* typically encode a built-in HTML/ARIA fact rather than component-specific behavior.
|
|
356
|
+
*/
|
|
278
357
|
readonly props?: readonly PropNormalizer[];
|
|
279
358
|
/** Restricts the `as` prop to this set of tags. Violations route through diagnostics. */
|
|
280
359
|
readonly allowedAs?: readonly TAllowed[];
|
|
281
360
|
};
|
|
282
361
|
|
|
283
362
|
type StylingOptions<V extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<V> = Readonly<EmptyRecord>, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory> = {
|
|
363
|
+
/** Class applied to every instance regardless of variant selection. */
|
|
284
364
|
readonly base?: ClassName;
|
|
365
|
+
/**
|
|
366
|
+
* Named variant groups (e.g. `intent`, `size`), each mapping its possible values to a
|
|
367
|
+
* class string. A consumer selects a value per group as a prop (`<Button intent="primary">`).
|
|
368
|
+
*/
|
|
285
369
|
readonly variants?: V;
|
|
370
|
+
/** Value used for a variant group when the consumer doesn't pass one explicitly. */
|
|
286
371
|
readonly defaults?: Partial<DefaultVariants<V>>;
|
|
372
|
+
/**
|
|
373
|
+
* Applies an extra class only when a specific *combination* of variant selections matches —
|
|
374
|
+
* for cases `variants` alone can't express (e.g. `intent: 'primary'` + `size: 'lg'` together
|
|
375
|
+
* need a class neither variant would add on its own).
|
|
376
|
+
*/
|
|
287
377
|
readonly compounds?: readonly CompoundVariant<V>[];
|
|
378
|
+
/**
|
|
379
|
+
* Named bundles of variant values, selectable as a single unit via the `recipe` prop (e.g.
|
|
380
|
+
* `<Button recipe="cta">` instead of setting `intent`/`size` individually).
|
|
381
|
+
*/
|
|
288
382
|
readonly presets?: TPreset;
|
|
383
|
+
/** Maps a resolved tag directly to a raw class string, independent of the variant system. */
|
|
289
384
|
readonly tags?: Readonly<TagMap>;
|
|
385
|
+
/**
|
|
386
|
+
* A `ClassPluginFactory` (e.g. the Tailwind layout pipeline) that extends class resolution
|
|
387
|
+
* with its own owned props, layered on top of `variants`/`presets`/`tags`.
|
|
388
|
+
*/
|
|
290
389
|
readonly plugin?: TPlugin;
|
|
390
|
+
/**
|
|
391
|
+
* A cache-key → resolved-class-string lookup for every statically-known variant
|
|
392
|
+
* combination, skipping runtime class computation entirely when a match is found. Normally
|
|
393
|
+
* generated by a build-time class-extraction plugin rather than hand-authored.
|
|
394
|
+
*/
|
|
291
395
|
readonly precomputedClasses?: Readonly<Record<string, string>>;
|
|
292
396
|
};
|
|
293
397
|
|
|
@@ -296,17 +400,51 @@ type NormalizeFn<Props extends AnyRecord = AnyRecord> = {
|
|
|
296
400
|
}['normalize'];
|
|
297
401
|
type AnyFactoryOptions = FactoryOptions<ElementType, AnyRecord, VariantMap, RecipeMap<VariantMap>, AnyClassPluginFactory>;
|
|
298
402
|
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> = {
|
|
403
|
+
/** The intrinsic tag the component renders by default. Overridable per instance via `as`. */
|
|
299
404
|
readonly tag?: TDefault;
|
|
405
|
+
/** Display name used in diagnostics, dev tools, and generated component naming. */
|
|
300
406
|
readonly name?: string;
|
|
407
|
+
/** Values used for the component's own (non-variant) props when the consumer omits them. */
|
|
301
408
|
readonly defaults?: Partial<NoInfer<Props>>;
|
|
409
|
+
/**
|
|
410
|
+
* A pure `(props) => props` transform run on every render, after `enforcement.props`'s
|
|
411
|
+
* normalizers see the same input. Use this for component-specific prop shaping — anything
|
|
412
|
+
* that depends on live instance state or the real DOM element belongs in `onElement` instead.
|
|
413
|
+
*/
|
|
302
414
|
readonly normalize?: NormalizeFn<NoInfer<Props>>;
|
|
415
|
+
/** Variant groups, base classes, presets, and the optional class-resolution plugin. */
|
|
303
416
|
readonly styling?: StylingOptions<V, TPreset, TPlugin>;
|
|
417
|
+
/** ARIA rules, child-content contracts, and other runtime validation for this component. */
|
|
304
418
|
readonly enforcement?: EnforcementOptions<TAllowed>;
|
|
305
419
|
/**
|
|
306
420
|
* Adapter-resolved diagnostics default, spread in by `resolveAdapterCommonOptions`. Not meant to
|
|
307
421
|
* be set directly by component authors — use `enforcement.diagnostics` to override per component.
|
|
308
422
|
*/
|
|
309
423
|
readonly diagnostics?: Diagnostics;
|
|
424
|
+
/**
|
|
425
|
+
* Sub-components to attach to the generated root component, producing a
|
|
426
|
+
* compound component API (for example, `Card.Header`, `Card.Content`,
|
|
427
|
+
* and `Card.Footer`). Purely additive — has no effect on
|
|
428
|
+
* `enforcement.children`; author child rules explicitly if the component
|
|
429
|
+
* needs to validate its children.
|
|
430
|
+
*/
|
|
431
|
+
readonly subComponents?: SubComponentMap;
|
|
432
|
+
/**
|
|
433
|
+
* Called once per instance, when the real underlying DOM element first
|
|
434
|
+
* exists, in every adapter — via that adapter's own native mount
|
|
435
|
+
* lifecycle, never through the props/attribute pipeline. Use this for
|
|
436
|
+
* wiring that needs the actual element (native imperative methods like
|
|
437
|
+
* `dialogEl.showModal()`, native events like `close`/`cancel` that have
|
|
438
|
+
* no prop-based equivalent), not for anything expressible as a plain
|
|
439
|
+
* prop.
|
|
440
|
+
*
|
|
441
|
+
* `getProps` returns the instance's *current* resolved props at call
|
|
442
|
+
* time — read it from inside a listener registered once at mount, rather
|
|
443
|
+
* than re-subscribing on every prop change.
|
|
444
|
+
*
|
|
445
|
+
* Return a cleanup function to run when the instance unmounts.
|
|
446
|
+
*/
|
|
447
|
+
readonly onElement?: (element: Element, getProps: () => Readonly<Props>) => void | (() => void);
|
|
310
448
|
};
|
|
311
449
|
|
|
312
450
|
declare function defineContractComponent<O extends FactoryOptions>(options: O): <R>(factory: (options: O) => R) => R;
|
|
@@ -324,7 +462,7 @@ declare const Slottable: vue.DefineComponent<{}, () => vue.VNode<vue.RendererNod
|
|
|
324
462
|
|
|
325
463
|
type UnknownProps = AnyRecord;
|
|
326
464
|
|
|
327
|
-
type VueFactoryOptions<TDefault extends ElementType, Props extends UnknownProps, Variants extends Readonly<VariantMap>, TPreset extends RecipeMap<Variants> =
|
|
465
|
+
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> & {
|
|
328
466
|
/**
|
|
329
467
|
* Return true for any prop key that should be consumed but not forwarded to
|
|
330
468
|
* the DOM. Variant keys are always stripped automatically.
|
|
@@ -370,6 +508,31 @@ type PolymorphicComponent<G extends PolymorphicGenerics> = {
|
|
|
370
508
|
displayName?: string;
|
|
371
509
|
};
|
|
372
510
|
|
|
373
|
-
|
|
511
|
+
/**
|
|
512
|
+
* Creates a polymorphic Vue component with praxis-kit contracts applied.
|
|
513
|
+
*
|
|
514
|
+
* ```ts
|
|
515
|
+
* const Button = createContractComponent({
|
|
516
|
+
* tag: 'button',
|
|
517
|
+
* name: 'Button',
|
|
518
|
+
* styling: {
|
|
519
|
+
* base: 'btn',
|
|
520
|
+
* variants: { intent: { primary: 'btn--primary', ghost: 'btn--ghost' } },
|
|
521
|
+
* defaults: { intent: 'primary' },
|
|
522
|
+
* },
|
|
523
|
+
* })
|
|
524
|
+
* ```
|
|
525
|
+
*
|
|
526
|
+
* ```vue
|
|
527
|
+
* <Button intent="ghost" as="a" href="/home">Home</Button>
|
|
528
|
+
* ```
|
|
529
|
+
*
|
|
530
|
+
* Pass `subComponents` to attach named sub-components (`Card.Header`) and `onElement` to run
|
|
531
|
+
* setup once the real DOM element exists — both purely additive on top of the generated
|
|
532
|
+
* component.
|
|
533
|
+
*/
|
|
534
|
+
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> & {
|
|
535
|
+
readonly subComponents?: TSubComponents;
|
|
536
|
+
}): MergeRecords<PolymorphicComponent<PolymorphicGenerics<TDefault, MergeRecords<Props, ExtractPluginProps<TPlugin>>, Variants, TPreset>>, TSubComponents>;
|
|
374
537
|
|
|
375
538
|
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
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
// ../../adapters/vue/src/create-contract-component.ts
|
|
2
2
|
import { computed, defineComponent as defineComponent2 } from "vue";
|
|
3
3
|
|
|
4
|
+
// ../../lib/adapter-utils/src/invariant.ts
|
|
5
|
+
function panic(message) {
|
|
6
|
+
throw new Error(message);
|
|
7
|
+
}
|
|
8
|
+
function invariant(condition, message) {
|
|
9
|
+
if (!condition) panic(message);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// ../../lib/adapter-utils/src/runtime/apply-display-name.ts
|
|
13
|
+
function applyDisplayName(component, name) {
|
|
14
|
+
Object.assign(component, { displayName: name ?? "PolymorphicComponent" });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// ../../lib/adapter-utils/src/runtime/define-component.ts
|
|
18
|
+
function defineContractComponent(options) {
|
|
19
|
+
return (factory) => factory(options);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// ../../lib/adapter-utils/src/runtime/assemble-compound-component.ts
|
|
23
|
+
function assembleCompoundComponent(root, subComponents) {
|
|
24
|
+
if (!subComponents) return root;
|
|
25
|
+
return Object.assign(root, subComponents);
|
|
26
|
+
}
|
|
27
|
+
|
|
4
28
|
// ../../lib/primitive/src/tag/resolve-tag.ts
|
|
5
29
|
function makeResolveTag(defaultTag) {
|
|
6
30
|
return function tag(as) {
|
|
@@ -43,10 +67,13 @@ function isString(value) {
|
|
|
43
67
|
function isNumber(value) {
|
|
44
68
|
return typeof value === "number";
|
|
45
69
|
}
|
|
70
|
+
function isFunction(value) {
|
|
71
|
+
return typeof value === "function";
|
|
72
|
+
}
|
|
46
73
|
|
|
47
74
|
// ../../lib/primitive/src/rule/is-dynamic-rule.ts
|
|
48
75
|
function isDynamicRule(rule) {
|
|
49
|
-
return isObject(rule, true) && rule
|
|
76
|
+
return isObject(rule, true) && Reflect.get(rule, RULE_BRAND) === true;
|
|
50
77
|
}
|
|
51
78
|
|
|
52
79
|
// ../../lib/primitive/src/rule/resolve-rule.ts
|
|
@@ -676,17 +703,17 @@ var COMPONENT_DEFAULT_TAG = /* @__PURE__ */ Symbol.for("praxis.component-default
|
|
|
676
703
|
// ../../lib/primitive/src/guards/children/is-tag.ts
|
|
677
704
|
function getAsProp(child) {
|
|
678
705
|
if (!isObject(child) || !("props" in child)) return void 0;
|
|
679
|
-
const props = child
|
|
706
|
+
const { props } = child;
|
|
680
707
|
if (!isObject(props)) return void 0;
|
|
681
|
-
const as = props
|
|
708
|
+
const as = Reflect.get(props, "as");
|
|
682
709
|
return isString(as) && as !== "" ? as : void 0;
|
|
683
710
|
}
|
|
684
711
|
function getTag(child) {
|
|
685
712
|
if (!isObject(child) || !("type" in child)) return void 0;
|
|
686
|
-
const t = child
|
|
713
|
+
const { type: t } = child;
|
|
687
714
|
if (isString(t)) return t;
|
|
688
715
|
if (typeof t === "function" || isObject(t)) {
|
|
689
|
-
const defaultTag = t
|
|
716
|
+
const defaultTag = Reflect.get(t, COMPONENT_DEFAULT_TAG);
|
|
690
717
|
if (!isString(defaultTag)) return void 0;
|
|
691
718
|
return getAsProp(child) ?? defaultTag;
|
|
692
719
|
}
|
|
@@ -706,22 +733,34 @@ function isTag(...args) {
|
|
|
706
733
|
return tag !== void 0 && set2.has(tag);
|
|
707
734
|
}
|
|
708
735
|
|
|
709
|
-
// ../../lib/adapter-utils/src/
|
|
710
|
-
function
|
|
711
|
-
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
// ../../lib/adapter-utils/src/runtime/
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
736
|
+
// ../../lib/adapter-utils/src/runtime/finalize-component.ts
|
|
737
|
+
function finalizeComponent(component, defaultTag, subComponents) {
|
|
738
|
+
if (typeof defaultTag === "string") {
|
|
739
|
+
Object.assign(component, { [COMPONENT_DEFAULT_TAG]: defaultTag });
|
|
740
|
+
}
|
|
741
|
+
return assembleCompoundComponent(component, subComponents);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
// ../../lib/adapter-utils/src/runtime/is-factory-options-like.ts
|
|
745
|
+
var FACTORY_OPTIONS_FIELD_VALIDATORS = {
|
|
746
|
+
tag: (v) => v === void 0 || isString(v),
|
|
747
|
+
name: (v) => v === void 0 || isString(v),
|
|
748
|
+
defaults: (v) => v === void 0 || isObject(v),
|
|
749
|
+
normalize: (v) => v === void 0 || isFunction(v),
|
|
750
|
+
styling: (v) => v === void 0 || isObject(v),
|
|
751
|
+
enforcement: (v) => v === void 0 || isObject(v),
|
|
752
|
+
diagnostics: (v) => v === void 0 || isObject(v),
|
|
753
|
+
subComponents: (v) => v === void 0 || isObject(v),
|
|
754
|
+
onElement: (v) => v === void 0 || isFunction(v)
|
|
755
|
+
};
|
|
756
|
+
function isFactoryOptionsLike(options, extraFieldValidators) {
|
|
757
|
+
if (!isObject(options)) return false;
|
|
758
|
+
const validators = { ...FACTORY_OPTIONS_FIELD_VALIDATORS, ...extraFieldValidators };
|
|
759
|
+
for (const [key, value] of Object.entries(options)) {
|
|
760
|
+
const validate = validators[key];
|
|
761
|
+
if (!validate || !validate(value)) return false;
|
|
762
|
+
}
|
|
763
|
+
return true;
|
|
725
764
|
}
|
|
726
765
|
|
|
727
766
|
// ../../lib/contract/src/aria/aria-role-policy.ts
|
|
@@ -2874,7 +2913,7 @@ function getChildProp(child, key) {
|
|
|
2874
2913
|
if (!isVNodeLike(child)) return void 0;
|
|
2875
2914
|
const { props } = child;
|
|
2876
2915
|
if (!isObject(props)) return void 0;
|
|
2877
|
-
return props
|
|
2916
|
+
return Reflect.get(props, key);
|
|
2878
2917
|
}
|
|
2879
2918
|
|
|
2880
2919
|
// ../core/src/html/contracts/aria/landmarks.ts
|
|
@@ -3571,6 +3610,13 @@ function buildRuntime(options) {
|
|
|
3571
3610
|
return built;
|
|
3572
3611
|
}
|
|
3573
3612
|
|
|
3613
|
+
// ../../adapters/vue/src/is-polymorphic-component.ts
|
|
3614
|
+
function isPolymorphicComponent(value) {
|
|
3615
|
+
if (!isObject(value)) return false;
|
|
3616
|
+
if (!("displayName" in value)) return true;
|
|
3617
|
+
return value.displayName === void 0 || isString(value.displayName);
|
|
3618
|
+
}
|
|
3619
|
+
|
|
3574
3620
|
// ../../adapters/vue/src/render.ts
|
|
3575
3621
|
import { cloneVNode, h as h3 } from "vue";
|
|
3576
3622
|
|
|
@@ -3669,7 +3715,7 @@ function prepareRenderState(runtime, attrs, filterProps) {
|
|
|
3669
3715
|
className
|
|
3670
3716
|
};
|
|
3671
3717
|
}
|
|
3672
|
-
function buildElementProps(props, className) {
|
|
3718
|
+
function buildElementProps(props, className, elementRef) {
|
|
3673
3719
|
const { role, ...rest } = props;
|
|
3674
3720
|
return {
|
|
3675
3721
|
...normalizeListenerKeys(rest),
|
|
@@ -3677,11 +3723,17 @@ function buildElementProps(props, className) {
|
|
|
3677
3723
|
// normalizeClass turns it into '' and still emits class="", while the client patcher
|
|
3678
3724
|
// removes the attribute outright. Omitting the key entirely keeps both paths consistent.
|
|
3679
3725
|
...className !== void 0 && { class: className },
|
|
3680
|
-
...isKnownAriaRole(role) && { role }
|
|
3726
|
+
...isKnownAriaRole(role) && { role },
|
|
3727
|
+
// Vue calls a function-ref with the element on mount and with null on unmount, same
|
|
3728
|
+
// contract as React/Preact's callback refs — a natural fit for FactoryOptions.onElement.
|
|
3729
|
+
// Cast: Vue's own VNodeRef type also accepts a resolved *component* instance, since refs
|
|
3730
|
+
// can target components as well as elements — irrelevant here, this is only ever attached
|
|
3731
|
+
// to an intrinsic host tag, which always resolves to a real Element.
|
|
3732
|
+
...elementRef !== void 0 && { ref: elementRef }
|
|
3681
3733
|
};
|
|
3682
3734
|
}
|
|
3683
|
-
function renderIntrinsic(state, runtime, slots) {
|
|
3684
|
-
const elementProps = buildElementProps(state.props, state.className);
|
|
3735
|
+
function renderIntrinsic(state, runtime, slots, elementRef) {
|
|
3736
|
+
const elementProps = buildElementProps(state.props, state.className, elementRef);
|
|
3685
3737
|
const domProps = runtime.resolveAria(state.tag, elementProps).props;
|
|
3686
3738
|
return h3(state.tag, domProps, slots.default ? { default: slots.default } : void 0);
|
|
3687
3739
|
}
|
|
@@ -3694,12 +3746,13 @@ function validateSlotDirectives(directives, validator) {
|
|
|
3694
3746
|
}
|
|
3695
3747
|
return true;
|
|
3696
3748
|
}
|
|
3697
|
-
function tryRenderAsChild(state, children, discarded, validator) {
|
|
3749
|
+
function tryRenderAsChild(state, children, discarded, validator, elementRef) {
|
|
3698
3750
|
if (!validateSlotDirectives(state.directives, validator)) return null;
|
|
3699
3751
|
if (discarded > 0) validator.warnDiscardedChildren(discarded);
|
|
3700
3752
|
const attrs = {
|
|
3701
3753
|
...pickAttributes(state.props),
|
|
3702
|
-
...state.className !== void 0 && { class: state.className }
|
|
3754
|
+
...state.className !== void 0 && { class: state.className },
|
|
3755
|
+
...elementRef !== void 0 && { ref: elementRef }
|
|
3703
3756
|
};
|
|
3704
3757
|
const slottable = extractSlottable(children);
|
|
3705
3758
|
if (slottable) return slottable.rebuild(cloneVNode(slottable.child, attrs));
|
|
@@ -3714,20 +3767,31 @@ function render({
|
|
|
3714
3767
|
state,
|
|
3715
3768
|
slots,
|
|
3716
3769
|
slotValidator,
|
|
3717
|
-
childrenEvaluator
|
|
3770
|
+
childrenEvaluator,
|
|
3771
|
+
elementRef
|
|
3718
3772
|
}) {
|
|
3719
3773
|
const { vnodes: children, discarded } = normalizeChildren(slots);
|
|
3720
3774
|
if (process.env.NODE_ENV !== "production") {
|
|
3721
3775
|
childrenEvaluator?.evaluate(children, { tag: state.tag, props: state.normalizedProps });
|
|
3722
3776
|
runtime.options.htmlChildrenEvaluatorFn?.(state.tag)?.evaluate(children, { tag: state.tag, props: state.normalizedProps });
|
|
3723
3777
|
}
|
|
3724
|
-
const slotResult = tryRenderAsChild(state, children, discarded, slotValidator);
|
|
3725
|
-
return slotResult ?? renderIntrinsic(state, runtime, slots);
|
|
3778
|
+
const slotResult = tryRenderAsChild(state, children, discarded, slotValidator, elementRef);
|
|
3779
|
+
return slotResult ?? renderIntrinsic(state, runtime, slots, elementRef);
|
|
3780
|
+
}
|
|
3781
|
+
|
|
3782
|
+
// ../../adapters/vue/src/to-vue-factory-options.ts
|
|
3783
|
+
var VUE_FIELD_VALIDATORS = {
|
|
3784
|
+
filterProps: (v) => v === void 0 || isFunction(v)
|
|
3785
|
+
};
|
|
3786
|
+
function isVueFactoryOptions(options) {
|
|
3787
|
+
return isFactoryOptionsLike(options, VUE_FIELD_VALIDATORS);
|
|
3726
3788
|
}
|
|
3727
3789
|
|
|
3728
3790
|
// ../../adapters/vue/src/create-contract-component.ts
|
|
3729
3791
|
function createContractComponent(options) {
|
|
3792
|
+
invariant(isVueFactoryOptions(options), "options is not a valid VueFactoryOptions object");
|
|
3730
3793
|
const bundle = buildRuntime(options);
|
|
3794
|
+
const { onElement } = options;
|
|
3731
3795
|
const Component = defineComponent2({
|
|
3732
3796
|
// normalizeOptions always supplies `name`, so displayName is always defined here —
|
|
3733
3797
|
// the fallback only satisfies the type, which allows it to be absent in general.
|
|
@@ -3737,15 +3801,33 @@ function createContractComponent(options) {
|
|
|
3737
3801
|
const state = computed(
|
|
3738
3802
|
() => prepareRenderState(bundle.runtime, attrs, bundle.filterProps)
|
|
3739
3803
|
);
|
|
3740
|
-
|
|
3804
|
+
let cleanup;
|
|
3805
|
+
let boundElement = null;
|
|
3806
|
+
const onElementRef = onElement ? (element) => {
|
|
3807
|
+
if (element === boundElement) return;
|
|
3808
|
+
if (boundElement) {
|
|
3809
|
+
cleanup?.();
|
|
3810
|
+
cleanup = void 0;
|
|
3811
|
+
}
|
|
3812
|
+
boundElement = element;
|
|
3813
|
+
if (element) {
|
|
3814
|
+
cleanup = onElement(element, () => attrs) ?? void 0;
|
|
3815
|
+
}
|
|
3816
|
+
} : void 0;
|
|
3817
|
+
return () => render({ ...bundle, state: state.value, slots, elementRef: onElementRef });
|
|
3741
3818
|
}
|
|
3742
3819
|
});
|
|
3743
3820
|
applyDisplayName(Component, options.name);
|
|
3744
|
-
const
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3821
|
+
const assembled = finalizeComponent(
|
|
3822
|
+
Component,
|
|
3823
|
+
bundle.runtime.options.defaultTag,
|
|
3824
|
+
options.subComponents
|
|
3825
|
+
);
|
|
3826
|
+
invariant(
|
|
3827
|
+
isPolymorphicComponent(assembled),
|
|
3828
|
+
"Generated component failed to satisfy the PolymorphicComponent shape"
|
|
3829
|
+
);
|
|
3830
|
+
return assembled;
|
|
3749
3831
|
}
|
|
3750
3832
|
export {
|
|
3751
3833
|
Slottable,
|