praxis-kit 7.0.0 → 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.
@@ -3,6 +3,12 @@ function defineContractComponent(options) {
3
3
  return (factory) => factory(options);
4
4
  }
5
5
 
6
+ // ../../lib/adapter-utils/src/runtime/assemble-compound-component.ts
7
+ function assembleCompoundComponent(root, subComponents) {
8
+ if (!subComponents) return root;
9
+ return Object.assign(root, subComponents);
10
+ }
11
+
6
12
  // ../../lib/primitive/src/tag/resolve-tag.ts
7
13
  function makeResolveTag(defaultTag) {
8
14
  return function tag(as) {
@@ -59,7 +65,7 @@ function isPlainObject(value) {
59
65
 
60
66
  // ../../lib/primitive/src/rule/is-dynamic-rule.ts
61
67
  function isDynamicRule(rule) {
62
- return isObject(rule, true) && rule[RULE_BRAND] === true;
68
+ return isObject(rule, true) && Reflect.get(rule, RULE_BRAND) === true;
63
69
  }
64
70
 
65
71
  // ../../lib/primitive/src/rule/resolve-rule.ts
@@ -722,17 +728,17 @@ var COMPONENT_DEFAULT_TAG = /* @__PURE__ */ Symbol.for("praxis.component-default
722
728
  // ../../lib/primitive/src/guards/children/is-tag.ts
723
729
  function getAsProp(child) {
724
730
  if (!isObject(child) || !("props" in child)) return void 0;
725
- const props = child.props;
731
+ const { props } = child;
726
732
  if (!isObject(props)) return void 0;
727
- const as = props.as;
733
+ const as = Reflect.get(props, "as");
728
734
  return isString(as) && as !== "" ? as : void 0;
729
735
  }
730
736
  function getTag(child) {
731
737
  if (!isObject(child) || !("type" in child)) return void 0;
732
- const t = child.type;
738
+ const { type: t } = child;
733
739
  if (isString(t)) return t;
734
740
  if (typeof t === "function" || isObject(t)) {
735
- const defaultTag = t[COMPONENT_DEFAULT_TAG];
741
+ const defaultTag = Reflect.get(t, COMPONENT_DEFAULT_TAG);
736
742
  if (!isString(defaultTag)) return void 0;
737
743
  return getAsProp(child) ?? defaultTag;
738
744
  }
@@ -752,6 +758,36 @@ function isTag(...args) {
752
758
  return tag !== void 0 && set2.has(tag);
753
759
  }
754
760
 
761
+ // ../../lib/adapter-utils/src/runtime/finalize-component.ts
762
+ function finalizeComponent(component, defaultTag, subComponents) {
763
+ if (typeof defaultTag === "string") {
764
+ Object.assign(component, { [COMPONENT_DEFAULT_TAG]: defaultTag });
765
+ }
766
+ return assembleCompoundComponent(component, subComponents);
767
+ }
768
+
769
+ // ../../lib/adapter-utils/src/runtime/is-factory-options-like.ts
770
+ var FACTORY_OPTIONS_FIELD_VALIDATORS = {
771
+ tag: (v) => v === void 0 || isString(v),
772
+ name: (v) => v === void 0 || isString(v),
773
+ defaults: (v) => v === void 0 || isObject(v),
774
+ normalize: (v) => v === void 0 || isFunction(v),
775
+ styling: (v) => v === void 0 || isObject(v),
776
+ enforcement: (v) => v === void 0 || isObject(v),
777
+ diagnostics: (v) => v === void 0 || isObject(v),
778
+ subComponents: (v) => v === void 0 || isObject(v),
779
+ onElement: (v) => v === void 0 || isFunction(v)
780
+ };
781
+ function isFactoryOptionsLike(options, extraFieldValidators) {
782
+ if (!isObject(options)) return false;
783
+ const validators = { ...FACTORY_OPTIONS_FIELD_VALIDATORS, ...extraFieldValidators };
784
+ for (const [key, value] of Object.entries(options)) {
785
+ const validate = validators[key];
786
+ if (!validate || !validate(value)) return false;
787
+ }
788
+ return true;
789
+ }
790
+
755
791
  // ../../lib/contract/src/aria/aria-role-policy.ts
756
792
  function getImplicitRole(tag, props) {
757
793
  if (tag in IMPLICIT_ROLE_RECORD) return IMPLICIT_ROLE_RECORD[tag];
@@ -2902,7 +2938,7 @@ function getChildProp(child, key) {
2902
2938
  if (!isVNodeLike(child)) return void 0;
2903
2939
  const { props } = child;
2904
2940
  if (!isObject(props)) return void 0;
2905
- return props[key];
2941
+ return Reflect.get(props, key);
2906
2942
  }
2907
2943
 
2908
2944
  // ../core/src/html/contracts/aria/landmarks.ts
@@ -3725,6 +3761,23 @@ function applySlot(children, slotProps, ref, cloneSlotChild) {
3725
3761
  return cloneSlotChild({ child: children, slotProps, ref });
3726
3762
  }
3727
3763
 
3764
+ // ../../adapters/react/src/shared/to-react-factory-options.ts
3765
+ var REACT_FIELD_VALIDATORS = {
3766
+ slotComponent: (v) => v === void 0 || isFunction(v) || isObject(v),
3767
+ filterProps: (v) => v === void 0 || isFunction(v),
3768
+ artifact: (v) => v === void 0 || isObject(v)
3769
+ };
3770
+ function isReactFactoryOptions(options) {
3771
+ return isFactoryOptionsLike(options, REACT_FIELD_VALIDATORS);
3772
+ }
3773
+
3774
+ // ../../adapters/react/src/shared/is-polymorphic-component.ts
3775
+ function isPolymorphicComponent(value) {
3776
+ if (!isFunction(value)) return false;
3777
+ if (!("displayName" in value)) return true;
3778
+ return value.displayName === void 0 || isString(value.displayName);
3779
+ }
3780
+
3728
3781
  // ../../adapters/react/src/shared/apply-display-name.ts
3729
3782
  function applyDisplayName(component, name) {
3730
3783
  const displayName = name ?? "PolymorphicComponent";
@@ -3901,10 +3954,14 @@ function buildRuntime(options, defaultSlotComponent, normalizeChildren) {
3901
3954
  }
3902
3955
 
3903
3956
  export {
3957
+ invariant,
3904
3958
  defineContractComponent,
3905
3959
  isString,
3906
3960
  SLOT_NAME,
3907
3961
  COMPONENT_DEFAULT_TAG,
3962
+ finalizeComponent,
3963
+ isReactFactoryOptions,
3964
+ isPolymorphicComponent,
3908
3965
  mergeRefs,
3909
3966
  applyDisplayName,
3910
3967
  Slottable,
@@ -211608,12 +211608,12 @@ var require_commonjs = __commonJS({
211608
211608
  }
211609
211609
  });
211610
211610
 
211611
- // ../../node_modules/.pnpm/brace-expansion@5.0.7/node_modules/brace-expansion/dist/commonjs/index.js
211611
+ // ../../node_modules/.pnpm/brace-expansion@5.0.9/node_modules/brace-expansion/dist/commonjs/index.js
211612
211612
  var require_commonjs2 = __commonJS({
211613
- "../../node_modules/.pnpm/brace-expansion@5.0.7/node_modules/brace-expansion/dist/commonjs/index.js"(exports) {
211613
+ "../../node_modules/.pnpm/brace-expansion@5.0.9/node_modules/brace-expansion/dist/commonjs/index.js"(exports) {
211614
211614
  "use strict";
211615
211615
  Object.defineProperty(exports, "__esModule", { value: true });
211616
- exports.EXPANSION_MAX = void 0;
211616
+ exports.EXPANSION_MAX_LENGTH = exports.EXPANSION_MAX = void 0;
211617
211617
  exports.expand = expand;
211618
211618
  var balanced_match_1 = require_commonjs();
211619
211619
  var escSlash = "\0SLASH" + Math.random() + "\0";
@@ -211632,6 +211632,7 @@ var require_commonjs2 = __commonJS({
211632
211632
  var commaPattern = /\\,/g;
211633
211633
  var periodPattern = /\\\./g;
211634
211634
  exports.EXPANSION_MAX = 1e5;
211635
+ exports.EXPANSION_MAX_LENGTH = 4e6;
211635
211636
  function numeric(str) {
211636
211637
  return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
211637
211638
  }
@@ -211666,11 +211667,11 @@ var require_commonjs2 = __commonJS({
211666
211667
  if (!str) {
211667
211668
  return [];
211668
211669
  }
211669
- const { max = exports.EXPANSION_MAX } = options;
211670
+ const { max = exports.EXPANSION_MAX, maxLength = exports.EXPANSION_MAX_LENGTH } = options;
211670
211671
  if (str.slice(0, 2) === "{}") {
211671
211672
  str = "\\{\\}" + str.slice(2);
211672
211673
  }
211673
- return expand_(escapeBraces(str), max, true).map(unescapeBraces);
211674
+ return expand_(escapeBraces(str), max, maxLength, true).map(unescapeBraces);
211674
211675
  }
211675
211676
  function embrace(str) {
211676
211677
  return "{" + str + "}";
@@ -211684,20 +211685,87 @@ var require_commonjs2 = __commonJS({
211684
211685
  function gte(i, y) {
211685
211686
  return i >= y;
211686
211687
  }
211687
- function expand_(str, max, isTop) {
211688
- const expansions = [];
211688
+ function combine(acc, pre, values, max, maxLength, dropEmpties) {
211689
+ const out = [];
211690
+ let length = 0;
211691
+ for (let a = 0; a < acc.length; a++) {
211692
+ for (let v = 0; v < values.length; v++) {
211693
+ if (out.length >= max)
211694
+ return out;
211695
+ const expansion = acc[a] + pre + values[v];
211696
+ if (dropEmpties && !expansion)
211697
+ continue;
211698
+ if (length + expansion.length > maxLength)
211699
+ return out;
211700
+ out.push(expansion);
211701
+ length += expansion.length;
211702
+ }
211703
+ }
211704
+ return out;
211705
+ }
211706
+ function expandSequence(body, isAlphaSequence, max, maxLength) {
211707
+ const n = body.split(/\.\./);
211708
+ const N = [];
211709
+ if (n[0] === void 0 || n[1] === void 0) {
211710
+ return N;
211711
+ }
211712
+ const x = numeric(n[0]);
211713
+ const y = numeric(n[1]);
211714
+ const width = Math.max(n[0].length, n[1].length);
211715
+ let incr = n.length === 3 && n[2] !== void 0 ? Math.max(Math.abs(numeric(n[2])), 1) : 1;
211716
+ let test = lte;
211717
+ const reverse = y < x;
211718
+ if (reverse) {
211719
+ incr *= -1;
211720
+ test = gte;
211721
+ }
211722
+ const pad = n.some(isPadded);
211723
+ let length = 0;
211724
+ for (let i = x; test(i, y) && N.length < max; i += incr) {
211725
+ let c;
211726
+ if (isAlphaSequence) {
211727
+ c = String.fromCharCode(i);
211728
+ if (c === "\\") {
211729
+ c = "";
211730
+ }
211731
+ } else {
211732
+ c = String(i);
211733
+ if (pad) {
211734
+ const need = width - c.length;
211735
+ if (need > 0) {
211736
+ const z = new Array(need + 1).join("0");
211737
+ if (i < 0) {
211738
+ c = "-" + z + c.slice(1);
211739
+ } else {
211740
+ c = z + c;
211741
+ }
211742
+ }
211743
+ }
211744
+ }
211745
+ if (length + c.length > maxLength)
211746
+ break;
211747
+ N.push(c);
211748
+ length += c.length;
211749
+ }
211750
+ return N;
211751
+ }
211752
+ function expand_(str, max, maxLength, isTop) {
211753
+ let acc = [""];
211754
+ let dropEmpties = false;
211755
+ let firstGroup = true;
211689
211756
  for (; ; ) {
211690
211757
  const m = (0, balanced_match_1.balanced)("{", "}", str);
211691
- if (!m)
211692
- return [str];
211758
+ if (!m) {
211759
+ return combine(acc, str, [""], max, maxLength, dropEmpties);
211760
+ }
211693
211761
  const pre = m.pre;
211694
- if (/\$$/.test(m.pre)) {
211695
- const post2 = m.post.length ? expand_(m.post, max, false) : [""];
211696
- for (let k = 0; k < post2.length && k < max; k++) {
211697
- const expansion = pre + "{" + m.body + "}" + post2[k];
211698
- expansions.push(expansion);
211699
- }
211700
- return expansions;
211762
+ if (/\$$/.test(pre)) {
211763
+ acc = combine(acc, pre + "{" + m.body + "}", [""], max, maxLength, dropEmpties && !m.post.length);
211764
+ firstGroup = false;
211765
+ if (!m.post.length)
211766
+ break;
211767
+ str = m.post;
211768
+ continue;
211701
211769
  }
211702
211770
  const isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
211703
211771
  const isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
@@ -211709,74 +211777,55 @@ var require_commonjs2 = __commonJS({
211709
211777
  isTop = true;
211710
211778
  continue;
211711
211779
  }
211712
- return [str];
211780
+ return combine(acc, pre + "{" + m.body + "}" + m.post, [""], max, maxLength, dropEmpties);
211713
211781
  }
211714
- const post = m.post.length ? expand_(m.post, max, false) : [""];
211715
- let n;
211782
+ if (firstGroup) {
211783
+ dropEmpties = isTop && !isSequence;
211784
+ firstGroup = false;
211785
+ }
211786
+ let values;
211716
211787
  if (isSequence) {
211717
- n = m.body.split(/\.\./);
211788
+ values = expandSequence(m.body, isAlphaSequence, max, maxLength);
211718
211789
  } else {
211719
- n = parseCommaParts(m.body);
211790
+ let n = parseCommaParts(m.body);
211720
211791
  if (n.length === 1 && n[0] !== void 0) {
211721
- n = expand_(n[0], max, false).map(embrace);
211792
+ n = expand_(n[0], max, maxLength, false).map(embrace);
211722
211793
  if (n.length === 1) {
211723
- return post.map((p) => m.pre + n[0] + p);
211724
- }
211725
- }
211726
- }
211727
- let N;
211728
- if (isSequence && n[0] !== void 0 && n[1] !== void 0) {
211729
- const x = numeric(n[0]);
211730
- const y = numeric(n[1]);
211731
- const width = Math.max(n[0].length, n[1].length);
211732
- let incr = n.length === 3 && n[2] !== void 0 ? Math.max(Math.abs(numeric(n[2])), 1) : 1;
211733
- let test = lte;
211734
- const reverse = y < x;
211735
- if (reverse) {
211736
- incr *= -1;
211737
- test = gte;
211738
- }
211739
- const pad = n.some(isPadded);
211740
- N = [];
211741
- for (let i = x; test(i, y) && N.length < max; i += incr) {
211742
- let c;
211743
- if (isAlphaSequence) {
211744
- c = String.fromCharCode(i);
211745
- if (c === "\\") {
211746
- c = "";
211747
- }
211748
- } else {
211749
- c = String(i);
211750
- if (pad) {
211751
- const need = width - c.length;
211752
- if (need > 0) {
211753
- const z = new Array(need + 1).join("0");
211754
- if (i < 0) {
211755
- c = "-" + z + c.slice(1);
211756
- } else {
211757
- c = z + c;
211758
- }
211759
- }
211760
- }
211794
+ acc = combine(acc, pre + n[0], [""], max, maxLength, dropEmpties && !m.post.length);
211795
+ if (!m.post.length)
211796
+ break;
211797
+ str = m.post;
211798
+ continue;
211761
211799
  }
211762
- N.push(c);
211763
211800
  }
211764
- } else {
211765
- N = [];
211766
- for (let j = 0; j < n.length; j++) {
211767
- N.push.apply(N, expand_(n[j], max, false));
211801
+ let dropsEmpties = dropEmpties && !m.post.length && !pre;
211802
+ for (let d = 0; dropsEmpties && d < acc.length; d++) {
211803
+ if (acc[d]) {
211804
+ dropsEmpties = false;
211805
+ }
211768
211806
  }
211769
- }
211770
- for (let j = 0; j < N.length; j++) {
211771
- for (let k = 0; k < post.length && expansions.length < max; k++) {
211772
- const expansion = pre + N[j] + post[k];
211773
- if (!isTop || isSequence || expansion) {
211774
- expansions.push(expansion);
211807
+ values = [];
211808
+ let valuesLength = 0;
211809
+ outer: for (let j = 0; j < n.length; j++) {
211810
+ const expanded = expand_(n[j], max, maxLength, false);
211811
+ for (let k = 0; k < expanded.length; k++) {
211812
+ const v = expanded[k];
211813
+ if (dropsEmpties && !v)
211814
+ continue;
211815
+ if (values.length >= max || valuesLength + v.length > maxLength) {
211816
+ break outer;
211817
+ }
211818
+ values.push(v);
211819
+ valuesLength += v.length;
211775
211820
  }
211776
211821
  }
211777
211822
  }
211778
- return expansions;
211823
+ acc = combine(acc, pre, values, max, maxLength, dropEmpties && !m.post.length);
211824
+ if (!m.post.length)
211825
+ break;
211826
+ str = m.post;
211779
211827
  }
211828
+ return acc;
211780
211829
  }
211781
211830
  }
211782
211831
  });
@@ -4,6 +4,8 @@ import { RequireAtLeastOne, Simplify, ReadonlyDeep } from 'type-fest';
4
4
  type StringMap<T = unknown> = Record<string, T>;
5
5
  type AnyRecord = StringMap<unknown>;
6
6
  type EmptyRecord = Record<never, never>;
7
+ /** A compound component's named sub-components, e.g. `{ Header, Content, Footer }`. */
8
+ type SubComponentMap = Readonly<AnyRecord>;
7
9
 
8
10
  type IntrinsicTag = keyof HTMLElementTagNameMap;
9
11
 
@@ -288,6 +290,30 @@ type FactoryOptions<TDefault extends ElementType = ElementType, Props extends An
288
290
  * be set directly by component authors — use `enforcement.diagnostics` to override per component.
289
291
  */
290
292
  readonly diagnostics?: Diagnostics$1;
293
+ /**
294
+ * Sub-components to attach to the generated root component, producing a
295
+ * compound component API (for example, `Card.Header`, `Card.Content`,
296
+ * and `Card.Footer`). Purely additive — has no effect on
297
+ * `enforcement.children`; author child rules explicitly if the component
298
+ * needs to validate its children.
299
+ */
300
+ readonly subComponents?: SubComponentMap;
301
+ /**
302
+ * Called once per instance, when the real underlying DOM element first
303
+ * exists, in every adapter — via that adapter's own native mount
304
+ * lifecycle, never through the props/attribute pipeline. Use this for
305
+ * wiring that needs the actual element (native imperative methods like
306
+ * `dialogEl.showModal()`, native events like `close`/`cancel` that have
307
+ * no prop-based equivalent), not for anything expressible as a plain
308
+ * prop.
309
+ *
310
+ * `getProps` returns the instance's *current* resolved props at call
311
+ * time — read it from inside a listener registered once at mount, rather
312
+ * than re-subscribing on every prop change.
313
+ *
314
+ * Return a cleanup function to run when the instance unmounts.
315
+ */
316
+ readonly onElement?: (element: Element, getProps: () => Readonly<Props>) => void | (() => void);
291
317
  };
292
318
 
293
319
  /** Shared input shape for `invalidWithFix`/`invalidWithoutFix`. */
@@ -41,17 +41,17 @@ function getComponentDefaultTag(component) {
41
41
  // ../../lib/primitive/src/guards/children/is-tag.ts
42
42
  function getAsProp(child) {
43
43
  if (!isObject(child) || !("props" in child)) return void 0;
44
- const props = child.props;
44
+ const { props } = child;
45
45
  if (!isObject(props)) return void 0;
46
- const as = props.as;
46
+ const as = Reflect.get(props, "as");
47
47
  return isString(as) && as !== "" ? as : void 0;
48
48
  }
49
49
  function getTag(child) {
50
50
  if (!isObject(child) || !("type" in child)) return void 0;
51
- const t = child.type;
51
+ const { type: t } = child;
52
52
  if (isString(t)) return t;
53
53
  if (typeof t === "function" || isObject(t)) {
54
- const defaultTag = t[COMPONENT_DEFAULT_TAG];
54
+ const defaultTag = Reflect.get(t, COMPONENT_DEFAULT_TAG);
55
55
  if (!isString(defaultTag)) return void 0;
56
56
  return getAsProp(child) ?? defaultTag;
57
57
  }
@@ -5,6 +5,8 @@ import { LitElement } from 'lit';
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
 
@@ -289,6 +291,30 @@ type FactoryOptions<TDefault extends ElementType = ElementType, Props extends An
289
291
  * be set directly by component authors — use `enforcement.diagnostics` to override per component.
290
292
  */
291
293
  readonly diagnostics?: Diagnostics;
294
+ /**
295
+ * Sub-components to attach to the generated root component, producing a
296
+ * compound component API (for example, `Card.Header`, `Card.Content`,
297
+ * and `Card.Footer`). Purely additive — has no effect on
298
+ * `enforcement.children`; author child rules explicitly if the component
299
+ * needs to validate its children.
300
+ */
301
+ readonly subComponents?: SubComponentMap;
302
+ /**
303
+ * Called once per instance, when the real underlying DOM element first
304
+ * exists, in every adapter — via that adapter's own native mount
305
+ * lifecycle, never through the props/attribute pipeline. Use this for
306
+ * wiring that needs the actual element (native imperative methods like
307
+ * `dialogEl.showModal()`, native events like `close`/`cancel` that have
308
+ * no prop-based equivalent), not for anything expressible as a plain
309
+ * prop.
310
+ *
311
+ * `getProps` returns the instance's *current* resolved props at call
312
+ * time — read it from inside a listener registered once at mount, rather
313
+ * than re-subscribing on every prop change.
314
+ *
315
+ * Return a cleanup function to run when the instance unmounts.
316
+ */
317
+ readonly onElement?: (element: Element, getProps: () => Readonly<Props>) => void | (() => void);
292
318
  };
293
319
 
294
320
  type FilterPredicate = (key: string, variantKeys: ReadonlySet<string>) => boolean;
@@ -348,7 +374,9 @@ type LitContractComponent<TVariants extends Readonly<VariantMap> = Readonly<Empt
348
374
  * customElements.define('praxis-button', Button)
349
375
  * ```
350
376
  */
351
- declare function createContractComponent<TDefault extends ElementType, TProps extends UnknownProps = EmptyRecord, TVariants extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<TVariants> = Readonly<EmptyRecord>, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory>(options: LitFactoryOptions<TDefault, TProps, TVariants, TPreset, TPlugin>): LitContractComponent<TVariants, ExtractPluginProps<TPlugin>>;
377
+ declare function createContractComponent<TDefault extends ElementType, TProps extends UnknownProps = EmptyRecord, TVariants extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<TVariants> = Readonly<EmptyRecord>, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory, TSubComponents extends Readonly<AnyRecord> = EmptyRecord>(options: LitFactoryOptions<TDefault, TProps, TVariants, TPreset, TPlugin> & {
378
+ readonly subComponents?: TSubComponents;
379
+ }): LitContractComponent<TVariants, ExtractPluginProps<TPlugin>> & TSubComponents;
352
380
 
353
381
  /**
354
382
  * Renders a praxis-kit Lit component to an HTML string without requiring a DOM.
package/dist/lit/index.js CHANGED
@@ -1,8 +1,22 @@
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
+
1
9
  // ../../lib/adapter-utils/src/runtime/define-component.ts
2
10
  function defineContractComponent(options) {
3
11
  return (factory) => factory(options);
4
12
  }
5
13
 
14
+ // ../../lib/adapter-utils/src/runtime/assemble-compound-component.ts
15
+ function assembleCompoundComponent(root, subComponents) {
16
+ if (!subComponents) return root;
17
+ return Object.assign(root, subComponents);
18
+ }
19
+
6
20
  // ../../lib/primitive/src/tag/resolve-tag.ts
7
21
  function makeResolveTag(defaultTag) {
8
22
  return function tag(as) {
@@ -45,10 +59,13 @@ function isString(value) {
45
59
  function isNumber(value) {
46
60
  return typeof value === "number";
47
61
  }
62
+ function isFunction(value) {
63
+ return typeof value === "function";
64
+ }
48
65
 
49
66
  // ../../lib/primitive/src/rule/is-dynamic-rule.ts
50
67
  function isDynamicRule(rule) {
51
- return isObject(rule, true) && rule[RULE_BRAND] === true;
68
+ return isObject(rule, true) && Reflect.get(rule, RULE_BRAND) === true;
52
69
  }
53
70
 
54
71
  // ../../lib/primitive/src/rule/resolve-rule.ts
@@ -587,17 +604,17 @@ var COMPONENT_DEFAULT_TAG = /* @__PURE__ */ Symbol.for("praxis.component-default
587
604
  // ../../lib/primitive/src/guards/children/is-tag.ts
588
605
  function getAsProp(child) {
589
606
  if (!isObject(child) || !("props" in child)) return void 0;
590
- const props = child.props;
607
+ const { props } = child;
591
608
  if (!isObject(props)) return void 0;
592
- const as = props.as;
609
+ const as = Reflect.get(props, "as");
593
610
  return isString(as) && as !== "" ? as : void 0;
594
611
  }
595
612
  function getTag(child) {
596
613
  if (!isObject(child) || !("type" in child)) return void 0;
597
- const t = child.type;
614
+ const { type: t } = child;
598
615
  if (isString(t)) return t;
599
616
  if (typeof t === "function" || isObject(t)) {
600
- const defaultTag = t[COMPONENT_DEFAULT_TAG];
617
+ const defaultTag = Reflect.get(t, COMPONENT_DEFAULT_TAG);
601
618
  if (!isString(defaultTag)) return void 0;
602
619
  return getAsProp(child) ?? defaultTag;
603
620
  }
@@ -617,6 +634,28 @@ function isTag(...args) {
617
634
  return tag !== void 0 && set2.has(tag);
618
635
  }
619
636
 
637
+ // ../../lib/adapter-utils/src/runtime/is-factory-options-like.ts
638
+ var FACTORY_OPTIONS_FIELD_VALIDATORS = {
639
+ tag: (v) => v === void 0 || isString(v),
640
+ name: (v) => v === void 0 || isString(v),
641
+ defaults: (v) => v === void 0 || isObject(v),
642
+ normalize: (v) => v === void 0 || isFunction(v),
643
+ styling: (v) => v === void 0 || isObject(v),
644
+ enforcement: (v) => v === void 0 || isObject(v),
645
+ diagnostics: (v) => v === void 0 || isObject(v),
646
+ subComponents: (v) => v === void 0 || isObject(v),
647
+ onElement: (v) => v === void 0 || isFunction(v)
648
+ };
649
+ function isFactoryOptionsLike(options, extraFieldValidators) {
650
+ if (!isObject(options)) return false;
651
+ const validators = { ...FACTORY_OPTIONS_FIELD_VALIDATORS, ...extraFieldValidators };
652
+ for (const [key, value] of Object.entries(options)) {
653
+ const validate = validators[key];
654
+ if (!validate || !validate(value)) return false;
655
+ }
656
+ return true;
657
+ }
658
+
620
659
  // ../../lib/contract/src/aria/aria-role-policy.ts
621
660
  function getImplicitRole(tag, props) {
622
661
  if (tag in IMPLICIT_ROLE_RECORD) return IMPLICIT_ROLE_RECORD[tag];
@@ -2721,7 +2760,7 @@ function getChildProp(child, key) {
2721
2760
  if (!isVNodeLike(child)) return void 0;
2722
2761
  const { props } = child;
2723
2762
  if (!isObject(props)) return void 0;
2724
- return props[key];
2763
+ return Reflect.get(props, key);
2725
2764
  }
2726
2765
 
2727
2766
  // ../core/src/html/contracts/aria/landmarks.ts
@@ -3503,7 +3542,7 @@ function diffAndApplyAttributes(host, state, prevPipelineAttrs, incomingProps) {
3503
3542
  }
3504
3543
 
3505
3544
  // ../../adapters/lit/src/create-contract-component.ts
3506
- import { LitElement, html } from "lit";
3545
+ import { LitElement as LitElement2, html } from "lit";
3507
3546
 
3508
3547
  // ../../adapters/lit/src/build-runtime.ts
3509
3548
  import { silentDiagnostics as silentDiagnostics4 } from "../_shared/diagnostics.js";
@@ -3531,6 +3570,12 @@ function buildRuntime(options) {
3531
3570
  };
3532
3571
  }
3533
3572
 
3573
+ // ../../adapters/lit/src/is-lit-contract-component.ts
3574
+ import { LitElement } from "lit";
3575
+ function isLitContractComponent(value) {
3576
+ return isFunction(value) && value.prototype instanceof LitElement;
3577
+ }
3578
+
3534
3579
  // ../../adapters/lit/src/render-to-string.ts
3535
3580
  var ssrRegistry = /* @__PURE__ */ new WeakMap();
3536
3581
  function registerForSsr(cls, bundle) {
@@ -3547,8 +3592,17 @@ function renderToString(component, props = {}, innerHTML = "") {
3547
3592
  return renderBundleToString(entry.bundle, props, innerHTML);
3548
3593
  }
3549
3594
 
3595
+ // ../../adapters/lit/src/to-lit-factory-options.ts
3596
+ var LIT_FIELD_VALIDATORS = {
3597
+ filterProps: (v) => v === void 0 || isFunction(v)
3598
+ };
3599
+ function isLitFactoryOptions(options) {
3600
+ return isFactoryOptionsLike(options, LIT_FIELD_VALIDATORS);
3601
+ }
3602
+
3550
3603
  // ../../adapters/lit/src/create-contract-component.ts
3551
3604
  function createContractComponent(options) {
3605
+ invariant(isLitFactoryOptions(options), "options is not a valid LitFactoryOptions object");
3552
3606
  const bundle = buildRuntime(options);
3553
3607
  const looseBundle = toLooseBundle(bundle);
3554
3608
  const variantKeys = options.styling?.variants ? Object.keys(options.styling.variants) : [];
@@ -3573,7 +3627,7 @@ function createContractComponent(options) {
3573
3627
  iterate.forEach(pluginKeys, (key) => {
3574
3628
  staticProps[key] = { type: String, attribute: key };
3575
3629
  });
3576
- class PolymorphicLitElement extends LitElement {
3630
+ class PolymorphicLitElement extends LitElement2 {
3577
3631
  // Tracks keys set by the pipeline last render so stale attrs are removed.
3578
3632
  _pipelineAttrs = /* @__PURE__ */ new Set();
3579
3633
  // Starts true so the first update always runs the pipeline regardless of
@@ -3635,6 +3689,21 @@ function createContractComponent(options) {
3635
3689
  const props = this._buildProps();
3636
3690
  diffAndApplyAttributes(this, resolveHostState(looseBundle, props), this._pipelineAttrs, props);
3637
3691
  }
3692
+ // Light DOM means `this` already is the real host element — no ref/indirection needed.
3693
+ // connectedCallback/disconnectedCallback are the native mount/unmount lifecycle, called
3694
+ // once per instance regardless of how many pipeline re-runs `_applyPraxis` does.
3695
+ _onElementCleanup;
3696
+ connectedCallback() {
3697
+ super.connectedCallback();
3698
+ if (options.onElement) {
3699
+ this._onElementCleanup = options.onElement(this, () => this._buildProps()) ?? void 0;
3700
+ }
3701
+ }
3702
+ disconnectedCallback() {
3703
+ super.disconnectedCallback();
3704
+ this._onElementCleanup?.();
3705
+ this._onElementCleanup = void 0;
3706
+ }
3638
3707
  render() {
3639
3708
  const children = Array.from(this.childNodes);
3640
3709
  const { tag, normalizedProps } = resolveTagAndNormalizedProps(looseBundle, this._buildProps());
@@ -3648,8 +3717,13 @@ function createContractComponent(options) {
3648
3717
  if (options.name) {
3649
3718
  Object.defineProperty(PolymorphicLitElement, "name", { value: options.name });
3650
3719
  }
3720
+ invariant(
3721
+ isLitContractComponent(PolymorphicLitElement),
3722
+ "Generated class failed to satisfy the LitContractComponent shape"
3723
+ );
3651
3724
  registerForSsr(PolymorphicLitElement, looseBundle);
3652
- return PolymorphicLitElement;
3725
+ const assembled = assembleCompoundComponent(PolymorphicLitElement, options.subComponents);
3726
+ return assembled;
3653
3727
  }
3654
3728
  export {
3655
3729
  createContractComponent,