praxis-kit 6.6.1 → 7.3.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.
@@ -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) {
@@ -11,6 +35,11 @@ var EVENT_HANDLER_RE = /^on[A-Z]/;
11
35
  // ../../lib/primitive/src/rule/rule-brand.ts
12
36
  var RULE_BRAND = /* @__PURE__ */ Symbol("praxis-kit/dynamic-rule");
13
37
 
38
+ // ../../lib/primitive/src/rule/dynamic.ts
39
+ function dynamic(resolve) {
40
+ return { [RULE_BRAND]: true, resolve };
41
+ }
42
+
14
43
  // ../../lib/primitive/src/guards/foundational/is-defined.ts
15
44
  function isUndefined(value) {
16
45
  return value === void 0;
@@ -24,7 +53,7 @@ function isNonNull(value) {
24
53
  return value != null;
25
54
  }
26
55
  function isNullish(value) {
27
- return isNull(value) || value === void 0;
56
+ return isNull(value) || isUndefined(value);
28
57
  }
29
58
 
30
59
  // ../../lib/primitive/src/utils/type-guards.ts
@@ -49,7 +78,7 @@ function isPlainObject(value) {
49
78
 
50
79
  // ../../lib/primitive/src/rule/is-dynamic-rule.ts
51
80
  function isDynamicRule(rule) {
52
- return isObject(rule, true) && rule[RULE_BRAND] === true;
81
+ return isObject(rule, true) && Reflect.get(rule, RULE_BRAND) === true;
53
82
  }
54
83
 
55
84
  // ../../lib/primitive/src/rule/resolve-rule.ts
@@ -625,6 +654,24 @@ var ROLE_RESTRICTED_ATTRIBUTES = /* @__PURE__ */ new Map([
625
654
  ]
626
655
  ]);
627
656
 
657
+ // ../../lib/primitive/src/constants/html/void-tags.ts
658
+ var VOID_TAGS = [
659
+ "area",
660
+ "base",
661
+ "br",
662
+ "col",
663
+ "embed",
664
+ "hr",
665
+ "img",
666
+ "input",
667
+ "link",
668
+ "meta",
669
+ "param",
670
+ "source",
671
+ "track",
672
+ "wbr"
673
+ ];
674
+
628
675
  // ../../lib/primitive/src/constants/primitive/slot-name.ts
629
676
  var SLOT_NAME = "Slot";
630
677
 
@@ -680,17 +727,17 @@ var COMPONENT_DEFAULT_TAG = /* @__PURE__ */ Symbol.for("praxis.component-default
680
727
  // ../../lib/primitive/src/guards/children/is-tag.ts
681
728
  function getAsProp(child) {
682
729
  if (!isObject(child) || !("props" in child)) return void 0;
683
- const props = child.props;
730
+ const { props } = child;
684
731
  if (!isObject(props)) return void 0;
685
- const as = props.as;
732
+ const as = Reflect.get(props, "as");
686
733
  return isString(as) && as !== "" ? as : void 0;
687
734
  }
688
735
  function getTag(child) {
689
736
  if (!isObject(child) || !("type" in child)) return void 0;
690
- const t = child.type;
737
+ const { type: t } = child;
691
738
  if (isString(t)) return t;
692
739
  if (typeof t === "function" || isObject(t)) {
693
- const defaultTag = t[COMPONENT_DEFAULT_TAG];
740
+ const defaultTag = Reflect.get(t, COMPONENT_DEFAULT_TAG);
694
741
  if (!isString(defaultTag)) return void 0;
695
742
  return getAsProp(child) ?? defaultTag;
696
743
  }
@@ -710,25 +757,34 @@ function isTag(...args) {
710
757
  return tag !== void 0 && set2.has(tag);
711
758
  }
712
759
 
713
- // ../../adapters/preact/src/create-contract-component.ts
714
- import { forwardRef as forwardRef2 } from "preact/compat";
715
-
716
- // ../../lib/adapter-utils/src/invariant.ts
717
- function panic(message) {
718
- throw new Error(message);
719
- }
720
- function invariant(condition, message) {
721
- if (!condition) panic(message);
722
- }
723
-
724
- // ../../lib/adapter-utils/src/runtime/apply-display-name.ts
725
- function applyDisplayName(component, name) {
726
- Object.assign(component, { displayName: name ?? "PolymorphicComponent" });
727
- }
728
-
729
- // ../../lib/adapter-utils/src/runtime/define-component.ts
730
- function defineContractComponent(options) {
731
- return (factory) => factory(options);
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;
732
788
  }
733
789
 
734
790
  // ../../lib/contract/src/aria/aria-role-policy.ts
@@ -1629,7 +1685,8 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
1629
1685
  const cached = _AriaPolicyEngine.#removeAttributeFixCache.get(attr);
1630
1686
  if (cached) return cached;
1631
1687
  const fix = {
1632
- kind: `removeAttribute:${attr}`,
1688
+ kind: "removeAttribute",
1689
+ attribute: attr,
1633
1690
  apply: ({ props }) => {
1634
1691
  if (!(attr in props)) return { applied: false, next: props };
1635
1692
  return { applied: true, next: omitProp(props, attr), previous: props };
@@ -1900,7 +1957,8 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
1900
1957
  if (!impliedLive) return NO_VIOLATIONS2;
1901
1958
  if ("aria-live" in props) return NO_VIOLATIONS2;
1902
1959
  const injectLive = {
1903
- kind: `injectLive:${effectiveRole}`,
1960
+ kind: "injectLive",
1961
+ attribute: "aria-live",
1904
1962
  apply: (ctx) => ({
1905
1963
  applied: true,
1906
1964
  next: { ...ctx.props, "aria-live": impliedLive },
@@ -1969,6 +2027,23 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
1969
2027
  }
1970
2028
  };
1971
2029
 
2030
+ // ../../lib/contract/src/aria/factories.ts
2031
+ function removeProp(props, key) {
2032
+ const next = { ...props };
2033
+ delete next[key];
2034
+ return next;
2035
+ }
2036
+ function removeAttributeFix(attribute) {
2037
+ return Object.freeze({
2038
+ kind: "removeAttribute",
2039
+ attribute,
2040
+ apply: ({ props }) => {
2041
+ if (!(attribute in props)) return { applied: false, next: props };
2042
+ return { applied: true, next: removeProp(props, attribute), previous: props };
2043
+ }
2044
+ });
2045
+ }
2046
+
1972
2047
  // ../../lib/contract/src/children/get-type-name.ts
1973
2048
  function getTypeName(value) {
1974
2049
  if (value === null) return "null";
@@ -2287,22 +2362,6 @@ import { warnDiagnostics as warnDiagnostics2 } from "../_shared/diagnostics.js";
2287
2362
 
2288
2363
  // ../core/src/html/contracts/categories.ts
2289
2364
  var METADATA_TAGS = ["script", "template"];
2290
- var VOID_TAGS = [
2291
- "area",
2292
- "base",
2293
- "br",
2294
- "col",
2295
- "embed",
2296
- "hr",
2297
- "img",
2298
- "input",
2299
- "link",
2300
- "meta",
2301
- "param",
2302
- "source",
2303
- "track",
2304
- "wbr"
2305
- ];
2306
2365
  var TEXT_ONLY_TAGS = [
2307
2366
  "option",
2308
2367
  "script",
@@ -2426,20 +2485,6 @@ var INPUT_MUTUALLY_EXCLUSIVE_POLICIES = [
2426
2485
 
2427
2486
  // ../core/src/html/spec/validators/attribute-type-validator.ts
2428
2487
  var DEFAULT_INPUT_TYPE = "text";
2429
- function omit(props, key) {
2430
- const next = { ...props };
2431
- delete next[key];
2432
- return next;
2433
- }
2434
- function removeAttributeFix(attribute) {
2435
- return {
2436
- kind: `removeAttribute:${attribute}`,
2437
- apply: ({ props }) => {
2438
- if (!(attribute in props)) return { applied: false, next: props };
2439
- return { applied: true, next: omit(props, attribute), previous: props };
2440
- }
2441
- };
2442
- }
2443
2488
  function createInputAttributeTypeRule({
2444
2489
  attribute,
2445
2490
  allowedTypes
@@ -2892,7 +2937,7 @@ function getChildProp(child, key) {
2892
2937
  if (!isVNodeLike(child)) return void 0;
2893
2938
  const { props } = child;
2894
2939
  if (!isObject(props)) return void 0;
2895
- return props[key];
2940
+ return Reflect.get(props, key);
2896
2941
  }
2897
2942
 
2898
2943
  // ../core/src/html/contracts/aria/landmarks.ts
@@ -2945,6 +2990,13 @@ function isLabelableControl(child) {
2945
2990
  const type = getChildProp(child, "type");
2946
2991
  return !isString(type) || type !== "hidden";
2947
2992
  }
2993
+ function hasAccessibleNameProp(props) {
2994
+ return "aria-label" in props || "aria-labelledby" in props;
2995
+ }
2996
+ function isNonEmptyTextChild(child) {
2997
+ if (isNumber(child)) return true;
2998
+ return isString(child) && child.trim().length > 0;
2999
+ }
2948
3000
  var labelContract = contract([
2949
3001
  { name: "control", match: isLabelableControl, cardinality: { max: 1 } },
2950
3002
  { name: "nested-label", match: isTag("label"), cardinality: { max: 0 } },
@@ -2952,6 +3004,13 @@ var labelContract = contract([
2952
3004
  name: "other-interactive-content",
2953
3005
  match: isTag(...OTHER_INTERACTIVE_TAGS),
2954
3006
  cardinality: { max: 0 }
3007
+ },
3008
+ {
3009
+ name: "accessible-name",
3010
+ match: isNonEmptyTextChild,
3011
+ cardinality: dynamic(
3012
+ (ctx) => hasAccessibleNameProp(ctx.props) ? { min: 0 } : { min: 1 }
3013
+ )
2955
3014
  }
2956
3015
  ]);
2957
3016
 
@@ -3593,6 +3652,10 @@ function applyMergePolicy(key, slotVal, childVal) {
3593
3652
  return policyHandlers[classifyProp(key, slotVal, childVal)](slotVal, childVal);
3594
3653
  }
3595
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
+
3596
3659
  // ../../adapters/preact/src/render.tsx
3597
3660
  import { h as h2 } from "preact";
3598
3661
 
@@ -3803,7 +3866,10 @@ function render({
3803
3866
  tag: state.tag,
3804
3867
  props: state.normalizedProps
3805
3868
  });
3806
- runtime.options.htmlChildrenEvaluatorFn?.(state.tag)?.evaluate(getNormalizedChildren());
3869
+ runtime.options.htmlChildrenEvaluatorFn?.(state.tag)?.evaluate(getNormalizedChildren(), {
3870
+ tag: state.tag,
3871
+ props: state.normalizedProps
3872
+ });
3807
3873
  }
3808
3874
  const slotResult = tryRenderAsChild(
3809
3875
  state,
@@ -3852,18 +3918,54 @@ function buildRuntime(options) {
3852
3918
  return built;
3853
3919
  }
3854
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
+
3855
3937
  // ../../adapters/preact/src/create-contract-component.ts
3856
3938
  function createContractComponent(options) {
3939
+ invariant(isPreactFactoryOptions(options), "options is not a valid PreactFactoryOptions object");
3857
3940
  const bundle = buildRuntime(options);
3941
+ const { onElement } = options;
3858
3942
  const Component = forwardRef2(function Component2(props, ref) {
3859
- return render({ ...bundle, props, ref: ref ?? null });
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 });
3860
3957
  });
3861
3958
  applyDisplayName(Component, options.name);
3862
- const defaultTag = bundle.runtime.options.defaultTag;
3863
- if (typeof defaultTag === "string") {
3864
- Object.assign(Component, { [COMPONENT_DEFAULT_TAG]: defaultTag });
3865
- }
3866
- return Component;
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;
3867
3969
  }
3868
3970
  export {
3869
3971
  Slottable,
@@ -1,5 +1,5 @@
1
- import { U as UnknownProps, E as ElementType, a as EmptyRecord, V as VariantMap, R as RecipeMap, A as AnyClassPluginFactory, b as ReactFactoryOptions, P as PolymorphicComponent, c as PolymorphicGenerics, d as ExtractPluginProps } from '../react-options-BUBVohU6.js';
2
- export { e as AnyFactoryOptions, f as ElementRef, F as FactoryOptions, g as PolymorphicProps, h as PolymorphicWithAsChild, i as PolymorphicWithRender, j as RenderCallbackProps, S as Slottable, k as SlottableProps, m as composeRefs, l as defineContractComponent, m as mergeRefs } from '../react-options-BUBVohU6.js';
1
+ import { U as UnknownProps, E as ElementType, a as EmptyRecord, V as VariantMap, R as RecipeMap, A as AnyClassPluginFactory, b as AnyRecord, c as ReactFactoryOptions, P as PolymorphicComponent, d as PolymorphicGenerics, e as ExtractPluginProps } from '../react-options-DLDsA4Tn.js';
2
+ export { f as AnyFactoryOptions, g as ElementRef, F as FactoryOptions, h as PolymorphicProps, i as PolymorphicWithAsChild, j as PolymorphicWithRender, k as RenderCallbackProps, S as Slottable, l as SlottableProps, m as composeRefs, n as defineContractComponent, m as mergeRefs } from '../react-options-DLDsA4Tn.js';
3
3
  import * as react from 'react';
4
4
  import { ReactElement, Ref } from 'react';
5
5
  import 'type-fest';
@@ -22,7 +22,9 @@ type CloneInput = {
22
22
  ref: NormalizedRef;
23
23
  };
24
24
 
25
- declare function createContractComponent<TDefault extends ElementType, Props extends UnknownProps = EmptyRecord, Variants extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<Variants> = Readonly<EmptyRecord>, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory, TAllowed extends ElementType = ElementType>(options: ReactFactoryOptions<TDefault, Props, Variants, TPreset, TPlugin, TAllowed>): PolymorphicComponent<PolymorphicGenerics<TDefault, Props & ExtractPluginProps<TPlugin>, Variants, TPreset, TAllowed>>;
25
+ declare function createContractComponent<TDefault extends ElementType, Props extends UnknownProps = EmptyRecord, Variants extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<Variants> = Readonly<EmptyRecord>, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory, TAllowed extends ElementType = ElementType, TSubComponents extends Readonly<AnyRecord> = EmptyRecord>(options: ReactFactoryOptions<TDefault, Props, Variants, TPreset, TPlugin, TAllowed> & {
26
+ readonly subComponents?: TSubComponents;
27
+ }): PolymorphicComponent<PolymorphicGenerics<TDefault, Props & ExtractPluginProps<TPlugin>, Variants, TPreset, TAllowed>> & TSubComponents;
26
28
 
27
29
  type SlotProps = {
28
30
  ref?: Ref<unknown> | null;
@@ -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-6JILZ6GQ.js";
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
- return render({ ...bundle, props, ref: ref ?? null });
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 defaultTag = bundle.runtime.options.defaultTag;
52
- if (typeof defaultTag === "string") {
53
- Object.assign(Component, { [COMPONENT_DEFAULT_TAG]: defaultTag });
54
- }
55
- return Component;
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,
@@ -1,5 +1,5 @@
1
- import { E as ElementType, U as UnknownProps, a as EmptyRecord, V as VariantMap, R as RecipeMap, A as AnyClassPluginFactory, b as ReactFactoryOptions, P as PolymorphicComponent, c as PolymorphicGenerics, d as ExtractPluginProps } from '../react-options-BUBVohU6.js';
2
- export { e as AnyFactoryOptions, f as ElementRef, F as FactoryOptions, g as PolymorphicProps, h as PolymorphicWithAsChild, i as PolymorphicWithRender, j as RenderCallbackProps, S as Slottable, k as SlottableProps, l as defineContractComponent, m as mergeRefs } from '../react-options-BUBVohU6.js';
1
+ import { E as ElementType, U as UnknownProps, a as EmptyRecord, V as VariantMap, R as RecipeMap, A as AnyClassPluginFactory, c as ReactFactoryOptions, P as PolymorphicComponent, d as PolymorphicGenerics, e as ExtractPluginProps } from '../react-options-DLDsA4Tn.js';
2
+ export { f as AnyFactoryOptions, g as ElementRef, F as FactoryOptions, h as PolymorphicProps, i as PolymorphicWithAsChild, j as PolymorphicWithRender, k as RenderCallbackProps, S as Slottable, l as SlottableProps, n as defineContractComponent, m as mergeRefs } from '../react-options-DLDsA4Tn.js';
3
3
  import * as react from 'react';
4
4
  import 'type-fest';
5
5
  import '../_shared/diagnostics.js';
@@ -13,10 +13,10 @@ import {
13
13
  makeCloneSlotChild,
14
14
  mergeRefs,
15
15
  render
16
- } from "../chunk-6JILZ6GQ.js";
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
- return render({ ...bundle, props, ref });
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;
@@ -5,6 +5,8 @@ import { Diagnostics, DiagnosticInput, DiagnosticsMode } from './_shared/diagnos
5
5
  type StringMap<T = unknown> = Record<string, T>;
6
6
  type AnyRecord = StringMap<unknown>;
7
7
  type EmptyRecord = Record<never, never>;
8
+ /** A compound component's named sub-components, e.g. `{ Header, Content, Footer }`. */
9
+ type SubComponentMap = Readonly<AnyRecord>;
8
10
 
9
11
  type IntrinsicTag = keyof HTMLElementTagNameMap;
10
12
 
@@ -197,8 +199,8 @@ type AriaContext = {
197
199
  readonly props: ReadonlyDeep<IntrinsicProps>;
198
200
  };
199
201
 
200
- type RemoveAttributeFixKind = `removeAttribute:${string}`;
201
- type InjectLiveFixKind = `injectLive:${string}`;
202
+ type RemoveAttributeFixKind = 'removeAttribute';
203
+ type InjectLiveFixKind = 'injectLive';
202
204
  type FixKind = 'removeRole' | 'setRole' | 'normalizeRelevantAll' | RemoveAttributeFixKind | InjectLiveFixKind;
203
205
 
204
206
  type AriaFixResult = {
@@ -211,6 +213,9 @@ type AriaFixResult = {
211
213
  };
212
214
  type AriaFix = {
213
215
  readonly kind: FixKind;
216
+ /** The attribute a `'removeAttribute'`/`'injectLive'` fix targets — always set for those
217
+ * kinds, absent for kinds with no single-attribute target (`'removeRole'`, etc.). */
218
+ readonly attribute?: string;
214
219
  readonly priority?: number;
215
220
  readonly source?: string;
216
221
  readonly apply: (context: AriaContext) => AriaFixResult;
@@ -304,6 +309,30 @@ type FactoryOptions<TDefault extends ElementType = ElementType, Props extends An
304
309
  * be set directly by component authors — use `enforcement.diagnostics` to override per component.
305
310
  */
306
311
  readonly diagnostics?: Diagnostics;
312
+ /**
313
+ * Sub-components to attach to the generated root component, producing a
314
+ * compound component API (for example, `Card.Header`, `Card.Content`,
315
+ * and `Card.Footer`). Purely additive — has no effect on
316
+ * `enforcement.children`; author child rules explicitly if the component
317
+ * needs to validate its children.
318
+ */
319
+ readonly subComponents?: SubComponentMap;
320
+ /**
321
+ * Called once per instance, when the real underlying DOM element first
322
+ * exists, in every adapter — via that adapter's own native mount
323
+ * lifecycle, never through the props/attribute pipeline. Use this for
324
+ * wiring that needs the actual element (native imperative methods like
325
+ * `dialogEl.showModal()`, native events like `close`/`cancel` that have
326
+ * no prop-based equivalent), not for anything expressible as a plain
327
+ * prop.
328
+ *
329
+ * `getProps` returns the instance's *current* resolved props at call
330
+ * time — read it from inside a listener registered once at mount, rather
331
+ * than re-subscribing on every prop change.
332
+ *
333
+ * Return a cleanup function to run when the instance unmounts.
334
+ */
335
+ readonly onElement?: (element: Element, getProps: () => Readonly<Props>) => void | (() => void);
307
336
  };
308
337
 
309
338
  type MetadataMap = AnyRecord;
@@ -518,4 +547,4 @@ type ReactFactoryOptions<TDefault extends ElementType, Props extends UnknownProp
518
547
  artifact?: CompiledArtifact;
519
548
  };
520
549
 
521
- export { type AnyClassPluginFactory as A, type ElementType as E, type FactoryOptions as F, type PolymorphicComponent as P, type RecipeMap as R, Slottable as S, type UnknownProps as U, type VariantMap as V, type EmptyRecord as a, type ReactFactoryOptions as b, type PolymorphicGenerics as c, type ExtractPluginProps as d, type AnyFactoryOptions as e, type ElementRef as f, type PolymorphicProps as g, type PolymorphicWithAsChild as h, type PolymorphicWithRender as i, type RenderCallbackProps as j, type SlottableProps as k, defineContractComponent as l, mergeRefs as m };
550
+ export { type AnyClassPluginFactory as A, type ElementType as E, type FactoryOptions as F, type PolymorphicComponent as P, type RecipeMap as R, Slottable as S, type UnknownProps as U, type VariantMap as V, type EmptyRecord as a, type AnyRecord as b, type ReactFactoryOptions as c, type PolymorphicGenerics as d, type ExtractPluginProps as e, type AnyFactoryOptions as f, type ElementRef as g, type PolymorphicProps as h, type PolymorphicWithAsChild as i, type PolymorphicWithRender as j, type RenderCallbackProps as k, type SlottableProps as l, mergeRefs as m, defineContractComponent as n };
@@ -5,6 +5,8 @@ import { JSX } from 'solid-js';
5
5
  type StringMap<T = unknown> = Record<string, T>;
6
6
  type AnyRecord = StringMap<unknown>;
7
7
  type EmptyRecord = Record<never, never>;
8
+ /** A compound component's named sub-components, e.g. `{ Header, Content, Footer }`. */
9
+ type SubComponentMap = Readonly<AnyRecord>;
8
10
 
9
11
  type IntrinsicTag = keyof HTMLElementTagNameMap;
10
12
 
@@ -196,8 +198,8 @@ type AriaContext = {
196
198
  readonly props: ReadonlyDeep<IntrinsicProps>;
197
199
  };
198
200
 
199
- type RemoveAttributeFixKind = `removeAttribute:${string}`;
200
- type InjectLiveFixKind = `injectLive:${string}`;
201
+ type RemoveAttributeFixKind = 'removeAttribute';
202
+ type InjectLiveFixKind = 'injectLive';
201
203
  type FixKind = 'removeRole' | 'setRole' | 'normalizeRelevantAll' | RemoveAttributeFixKind | InjectLiveFixKind;
202
204
 
203
205
  type AriaFixResult = {
@@ -210,6 +212,9 @@ type AriaFixResult = {
210
212
  };
211
213
  type AriaFix = {
212
214
  readonly kind: FixKind;
215
+ /** The attribute a `'removeAttribute'`/`'injectLive'` fix targets — always set for those
216
+ * kinds, absent for kinds with no single-attribute target (`'removeRole'`, etc.). */
217
+ readonly attribute?: string;
213
218
  readonly priority?: number;
214
219
  readonly source?: string;
215
220
  readonly apply: (context: AriaContext) => AriaFixResult;
@@ -303,6 +308,30 @@ type FactoryOptions<TDefault extends ElementType = ElementType, Props extends An
303
308
  * be set directly by component authors — use `enforcement.diagnostics` to override per component.
304
309
  */
305
310
  readonly diagnostics?: Diagnostics;
311
+ /**
312
+ * Sub-components to attach to the generated root component, producing a
313
+ * compound component API (for example, `Card.Header`, `Card.Content`,
314
+ * and `Card.Footer`). Purely additive — has no effect on
315
+ * `enforcement.children`; author child rules explicitly if the component
316
+ * needs to validate its children.
317
+ */
318
+ readonly subComponents?: SubComponentMap;
319
+ /**
320
+ * Called once per instance, when the real underlying DOM element first
321
+ * exists, in every adapter — via that adapter's own native mount
322
+ * lifecycle, never through the props/attribute pipeline. Use this for
323
+ * wiring that needs the actual element (native imperative methods like
324
+ * `dialogEl.showModal()`, native events like `close`/`cancel` that have
325
+ * no prop-based equivalent), not for anything expressible as a plain
326
+ * prop.
327
+ *
328
+ * `getProps` returns the instance's *current* resolved props at call
329
+ * time — read it from inside a listener registered once at mount, rather
330
+ * than re-subscribing on every prop change.
331
+ *
332
+ * Return a cleanup function to run when the instance unmounts.
333
+ */
334
+ readonly onElement?: (element: Element, getProps: () => Readonly<Props>) => void | (() => void);
306
335
  };
307
336
 
308
337
  declare function defineContractComponent<O extends FactoryOptions>(options: O): <R>(factory: (options: O) => R) => R;
@@ -354,6 +383,8 @@ type PolymorphicComponent<G extends PolymorphicGenerics> = {
354
383
  displayName?: string;
355
384
  };
356
385
 
357
- declare function createContractComponent<TDefault extends ElementType, Props extends UnknownProps = EmptyRecord, Variants extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<Variants> = Readonly<EmptyRecord>, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory>(options: SolidFactoryOptions<TDefault, Props, Variants, TPreset, TPlugin>): PolymorphicComponent<PolymorphicGenerics<TDefault, Props & ExtractPluginProps<TPlugin>, Variants, TPreset>>;
386
+ declare function createContractComponent<TDefault extends ElementType, Props extends UnknownProps = EmptyRecord, Variants extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<Variants> = Readonly<EmptyRecord>, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory, TSubComponents extends Readonly<AnyRecord> = EmptyRecord>(options: SolidFactoryOptions<TDefault, Props, Variants, TPreset, TPlugin> & {
387
+ readonly subComponents?: TSubComponents;
388
+ }): PolymorphicComponent<PolymorphicGenerics<TDefault, Props & ExtractPluginProps<TPlugin>, Variants, TPreset>> & TSubComponents;
358
389
 
359
390
  export { type AnyFactoryOptions, type ElementRef, type ElementType, type EmptyRecord, type PolymorphicComponent, type PolymorphicGenerics, type PolymorphicProps, type SolidFactoryOptions, createContractComponent, defineContractComponent };