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.
@@ -1,3 +1,16 @@
1
+ <!--
2
+ @component
3
+ Renders a `createContractComponent` bundle. Every praxis-kit component in the Svelte adapter
4
+ is a bundle passed to this component via the `bundle` prop:
5
+
6
+ ```svelte
7
+ <Polymorphic {bundle} intent="ghost" as="a" href="/home">Home</Polymorphic>
8
+ ```
9
+
10
+ Resolves the tag (`as` or the bundle's default), variant classes, filtered props, and ARIA
11
+ attributes, then renders the result via `<svelte:element>` — or, with `asChild`, renders
12
+ `children` as a snippet receiving the resolved props instead of a host element.
13
+ -->
1
14
  <script module lang="ts">
2
15
  declare const process: { env: { NODE_ENV: string } }
3
16
  </script>
@@ -134,6 +147,18 @@
134
147
  ?.(tag)
135
148
  ?.evaluate(childArray, { tag, props: normalizedProps })
136
149
  })
150
+
151
+ const onElement = $derived(bundle.onElement)
152
+
153
+ // Unlike the effect above, this runs in every environment (not dev-only) — onElement is a
154
+ // real runtime feature, not a diagnostic. Re-runs (cleaning up the previous call first, via
155
+ // the returned teardown) whenever hostEl changes identity, e.g. the resolved tag changes and
156
+ // Svelte mounts a new host element.
157
+ $effect(() => {
158
+ if (!hostEl) return
159
+ const cleanup = onElement?.(hostEl, () => normalizedProps)
160
+ return () => cleanup?.()
161
+ })
137
162
  }
138
163
  </script>
139
164
 
@@ -1,9 +1,72 @@
1
1
  import { RequireAtLeastOne, Simplify, ReadonlyDeep } from 'type-fest';
2
2
  import { Diagnostics, DiagnosticInput, DiagnosticsMode } from '../_shared/diagnostics.js';
3
3
 
4
+ /**
5
+ * A string-keyed object whose values are of type `T`.
6
+ */
4
7
  type StringMap<T = unknown> = Record<string, T>;
8
+ /**
9
+ * A string-keyed object with values of unknown type.
10
+ */
5
11
  type AnyRecord = StringMap<unknown>;
12
+ /**
13
+ * An object type with no named properties.
14
+ *
15
+ * Unlike `{}`, this excludes arbitrary properties during type operations while
16
+ * still satisfying `extends object`.
17
+ */
6
18
  type EmptyRecord = Record<never, never>;
19
+ /**
20
+ * A compound component's named sub-components, for example
21
+ * `{ Header, Content, Footer }`.
22
+ */
23
+ type SubComponentMap = Readonly<AnyRecord>;
24
+ /**
25
+ * Default `Variants` type for components that declare no variants.
26
+ *
27
+ * Structurally identical to `Readonly<EmptyRecord>`, but named separately so
28
+ * editor hovers remain self-descriptive.
29
+ */
30
+ type NoVariants = Readonly<EmptyRecord>;
31
+ /**
32
+ * Default `TPreset` type for components that declare no named presets.
33
+ *
34
+ * Structurally identical to `Readonly<EmptyRecord>`, but named separately so
35
+ * editor hovers remain self-descriptive.
36
+ */
37
+ type NoPreset = Readonly<EmptyRecord>;
38
+ /**
39
+ * Fallback for `ExtractPluginProps<TPlugin>` when a plugin contributes no
40
+ * props, including the no-plugin case.
41
+ *
42
+ * Structurally identical to `EmptyRecord`, but named separately so editor
43
+ * hovers remain self-descriptive.
44
+ */
45
+ type NoPluginProps = EmptyRecord;
46
+ /**
47
+ * Determines whether an object type should be treated as empty.
48
+ *
49
+ * `keyof T` ignores call and construct signatures...
50
+ */
51
+ type IsEmptyRecord<T extends object> = T extends (...args: never[]) => unknown ? false : T extends new (...args: never[]) => unknown ? false : keyof T extends never ? true : false;
52
+ /**
53
+ * Merges two object types while eliding empty operands.
54
+ *
55
+ * If either operand is {@link EmptyRecord}, the other operand is returned
56
+ * directly instead of producing intersections such as
57
+ * `Component & EmptyRecord` in editor hovers.
58
+ *
59
+ * Unlike a homomorphic mapped type (for example `Simplify<T>`), this preserves
60
+ * call and construct signatures. Many component types are callable objects,
61
+ * and mapped types silently discard those signatures.
62
+ *
63
+ * @remarks
64
+ * Instantiate `MergeRecords` directly. Introducing an intermediate alias for
65
+ * one operand (for example `type C = PolymorphicComponent<G>`) can prevent
66
+ * `IsEmptyRecord` from evaluating eagerly, which breaks assignability under
67
+ * `exactOptionalPropertyTypes`.
68
+ */
69
+ type MergeRecords<A extends object, B extends object> = IsEmptyRecord<A> extends true ? B : IsEmptyRecord<B> extends true ? A : A & B;
7
70
 
8
71
  type IntrinsicTag = keyof HTMLElementTagNameMap;
9
72
 
@@ -131,6 +194,7 @@ interface PolymorphicGenerics<TDefault extends ElementType = ElementType, Props
131
194
  preset: TPreset;
132
195
  allowed: TAllowed;
133
196
  }
197
+ type PropsOf<T extends PolymorphicGenerics> = T['props'];
134
198
 
135
199
  type RequireAtLeastOneIfNotEmpty<T> = keyof T extends never ? EmptyRecord : RequireAtLeastOne<T>;
136
200
  type CompoundVariantConditionValue<V extends VariantMap, K extends keyof V> = VariantKey<V, K> | NonEmptyArray<VariantKey<V, K>>;
@@ -190,7 +254,7 @@ type ClassPluginFactory<TProps extends AnyRecord = EmptyRecord> = <V extends Var
190
254
  * wherever a factory's concrete plugin-props shape isn't tracked (factory generics,
191
255
  * capability wiring). */
192
256
  type AnyClassPluginFactory = ClassPluginFactory<AnyRecord> | undefined;
193
- type ExtractPluginProps<TPlugin extends AnyClassPluginFactory> = TPlugin extends ClassPluginFactory<infer T> ? string extends keyof T ? EmptyRecord : T : EmptyRecord;
257
+ type ExtractPluginProps<TPlugin extends AnyClassPluginFactory> = TPlugin extends ClassPluginFactory<infer T> ? string extends keyof T ? NoPluginProps : T : NoPluginProps;
194
258
  type PluginInstance<TPlugin extends AnyClassPluginFactory> = TPlugin extends ClassPluginFactory<infer TProps> ? ClassPlugin<TProps> : undefined;
195
259
 
196
260
  type AriaContext = {
@@ -255,6 +319,12 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
255
319
  * `@praxis-kit/diagnostics`.
256
320
  */
257
321
  readonly diagnostics?: Diagnostics | DiagnosticsMode;
322
+ /**
323
+ * ARIA/accessibility rules evaluated against the resolved tag and props on every render.
324
+ * Each rule is a function receiving the current context and returning zero or more
325
+ * violations, some of which can carry an auto-applicable fix (see `createRemoveAttributeRule`
326
+ * and friends in `praxis-kit/contract`).
327
+ */
258
328
  readonly aria?: readonly AriaRule[];
259
329
  /**
260
330
  * Rules that need `AriaPolicyEngine`'s fix-application/caching machinery
@@ -266,6 +336,11 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
266
336
  * misleading `aria` name to get the machinery it needs.
267
337
  */
268
338
  readonly rules?: readonly AriaRule[];
339
+ /**
340
+ * Declares which children are valid, by name, match predicate, and cardinality (e.g. "at
341
+ * least 1, at most 4 `Button` children"). Open by default — children matching no rule are
342
+ * still allowed unless `exclusiveChildren` is set.
343
+ */
269
344
  readonly children?: readonly ChildRuleInput[];
270
345
  /**
271
346
  * When true, only children matching a `children` rule (or text, per `allowText`)
@@ -278,19 +353,49 @@ type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
278
353
  * or any listed rule. Default: true.
279
354
  */
280
355
  readonly allowText?: boolean;
356
+ /**
357
+ * Prop transforms composed with the component's own `normalize` (from `FactoryOptions`) and
358
+ * run before it. Unlike `normalize`, these live in the enforcement bucket because they
359
+ * typically encode a built-in HTML/ARIA fact rather than component-specific behavior.
360
+ */
281
361
  readonly props?: readonly PropNormalizer[];
282
362
  /** Restricts the `as` prop to this set of tags. Violations route through diagnostics. */
283
363
  readonly allowedAs?: readonly TAllowed[];
284
364
  };
285
365
 
286
366
  type StylingOptions<V extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<V> = Readonly<EmptyRecord>, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory> = {
367
+ /** Class applied to every instance regardless of variant selection. */
287
368
  readonly base?: ClassName;
369
+ /**
370
+ * Named variant groups (e.g. `intent`, `size`), each mapping its possible values to a
371
+ * class string. A consumer selects a value per group as a prop (`<Button intent="primary">`).
372
+ */
288
373
  readonly variants?: V;
374
+ /** Value used for a variant group when the consumer doesn't pass one explicitly. */
289
375
  readonly defaults?: Partial<DefaultVariants<V>>;
376
+ /**
377
+ * Applies an extra class only when a specific *combination* of variant selections matches —
378
+ * for cases `variants` alone can't express (e.g. `intent: 'primary'` + `size: 'lg'` together
379
+ * need a class neither variant would add on its own).
380
+ */
290
381
  readonly compounds?: readonly CompoundVariant<V>[];
382
+ /**
383
+ * Named bundles of variant values, selectable as a single unit via the `recipe` prop (e.g.
384
+ * `<Button recipe="cta">` instead of setting `intent`/`size` individually).
385
+ */
291
386
  readonly presets?: TPreset;
387
+ /** Maps a resolved tag directly to a raw class string, independent of the variant system. */
292
388
  readonly tags?: Readonly<TagMap>;
389
+ /**
390
+ * A `ClassPluginFactory` (e.g. the Tailwind layout pipeline) that extends class resolution
391
+ * with its own owned props, layered on top of `variants`/`presets`/`tags`.
392
+ */
293
393
  readonly plugin?: TPlugin;
394
+ /**
395
+ * A cache-key → resolved-class-string lookup for every statically-known variant
396
+ * combination, skipping runtime class computation entirely when a match is found. Normally
397
+ * generated by a build-time class-extraction plugin rather than hand-authored.
398
+ */
294
399
  readonly precomputedClasses?: Readonly<Record<string, string>>;
295
400
  };
296
401
 
@@ -299,17 +404,51 @@ type NormalizeFn<Props extends AnyRecord = AnyRecord> = {
299
404
  }['normalize'];
300
405
  type AnyFactoryOptions = FactoryOptions<ElementType, AnyRecord, VariantMap, RecipeMap<VariantMap>, AnyClassPluginFactory>;
301
406
  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> = {
407
+ /** The intrinsic tag the component renders by default. Overridable per instance via `as`. */
302
408
  readonly tag?: TDefault;
409
+ /** Display name used in diagnostics, dev tools, and generated component naming. */
303
410
  readonly name?: string;
411
+ /** Values used for the component's own (non-variant) props when the consumer omits them. */
304
412
  readonly defaults?: Partial<NoInfer<Props>>;
413
+ /**
414
+ * A pure `(props) => props` transform run on every render, after `enforcement.props`'s
415
+ * normalizers see the same input. Use this for component-specific prop shaping — anything
416
+ * that depends on live instance state or the real DOM element belongs in `onElement` instead.
417
+ */
305
418
  readonly normalize?: NormalizeFn<NoInfer<Props>>;
419
+ /** Variant groups, base classes, presets, and the optional class-resolution plugin. */
306
420
  readonly styling?: StylingOptions<V, TPreset, TPlugin>;
421
+ /** ARIA rules, child-content contracts, and other runtime validation for this component. */
307
422
  readonly enforcement?: EnforcementOptions<TAllowed>;
308
423
  /**
309
424
  * Adapter-resolved diagnostics default, spread in by `resolveAdapterCommonOptions`. Not meant to
310
425
  * be set directly by component authors — use `enforcement.diagnostics` to override per component.
311
426
  */
312
427
  readonly diagnostics?: Diagnostics;
428
+ /**
429
+ * Sub-components to attach to the generated root component, producing a
430
+ * compound component API (for example, `Card.Header`, `Card.Content`,
431
+ * and `Card.Footer`). Purely additive — has no effect on
432
+ * `enforcement.children`; author child rules explicitly if the component
433
+ * needs to validate its children.
434
+ */
435
+ readonly subComponents?: SubComponentMap;
436
+ /**
437
+ * Called once per instance, when the real underlying DOM element first
438
+ * exists, in every adapter — via that adapter's own native mount
439
+ * lifecycle, never through the props/attribute pipeline. Use this for
440
+ * wiring that needs the actual element (native imperative methods like
441
+ * `dialogEl.showModal()`, native events like `close`/`cancel` that have
442
+ * no prop-based equivalent), not for anything expressible as a plain
443
+ * prop.
444
+ *
445
+ * `getProps` returns the instance's *current* resolved props at call
446
+ * time — read it from inside a listener registered once at mount, rather
447
+ * than re-subscribing on every prop change.
448
+ *
449
+ * Return a cleanup function to run when the instance unmounts.
450
+ */
451
+ readonly onElement?: (element: Element, getProps: () => Readonly<Props>) => void | (() => void);
313
452
  };
314
453
 
315
454
  type ResolvedFactoryOptions<TDefault extends ElementType = ElementType, Props extends AnyRecord = EmptyRecord, V extends Readonly<VariantMap> = Readonly<EmptyRecord>, TPreset extends RecipeMap<V> = Readonly<EmptyRecord>> = {
@@ -392,6 +531,57 @@ declare class ChildrenEvaluator extends InvariantBase {
392
531
 
393
532
  declare function createPolymorphic2<TDefault extends ElementType, Props extends AnyRecord, Variants extends Readonly<VariantMap>, TPreset extends RecipeMap<Variants> = Readonly<EmptyRecord>, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory>(options?: FactoryOptions<TDefault, Props, Variants, TPreset, TPlugin>): PolymorphicRuntime<TDefault, Props, Variants, Extract<keyof TPreset, string>, TPreset, PluginInstance<TPlugin>>;
394
533
 
534
+ /**
535
+ * Matches option types that declare child enforcement rules.
536
+ *
537
+ * This type is used to determine whether a
538
+ * {@link ChildrenEvaluator} should be included in a built bundle.
539
+ */
540
+ type WithChildrenEnforcement = {
541
+ enforcement: {
542
+ children: readonly unknown[];
543
+ };
544
+ };
545
+ /**
546
+ * The bundle of child evaluation services produced when
547
+ * child enforcement rules are configured.
548
+ */
549
+ type ChildrenEvaluatorBundle = {
550
+ childrenEvaluator: ChildrenEvaluator;
551
+ };
552
+ /**
553
+ * Conditionally includes a {@link ChildrenEvaluator} in the
554
+ * built bundle when child enforcement rules are present.
555
+ *
556
+ * When no child enforcement rules are configured, this type
557
+ * resolves to {@link EmptyRecord}, omitting the property
558
+ * entirely rather than making it optional. Consumers can
559
+ * safely narrow using:
560
+ *
561
+ * ```ts
562
+ * if ('childrenEvaluator' in bundle) {
563
+ * // bundle.childrenEvaluator is available
564
+ * }
565
+ * ```
566
+ *
567
+ * @typeParam TOptions - The component configuration options.
568
+ */
569
+ type BuiltChildrenEvaluator<TOptions extends WithChildRules> = TOptions extends WithChildrenEnforcement ? ChildrenEvaluatorBundle : EmptyRecord;
570
+
571
+ /**
572
+ * Determines whether a prop should be stripped before forwarding to the
573
+ * rendered element.
574
+ *
575
+ * Returning `true` excludes the prop from the output; returning `false`
576
+ * keeps it. This is the inverse polarity of `shouldForwardProp`-style
577
+ * predicates (Emotion/styled-components), where `true` means include.
578
+ *
579
+ * @param key - The prop name being evaluated.
580
+ * @param variantKeys - The set of configured variant prop names.
581
+ * @returns `true` to strip the prop; `false` to forward it.
582
+ */
583
+ type FilterPredicate = (key: string, variantKeys: ReadonlySet<string>) => boolean;
584
+
395
585
  declare class SlotValidator extends InvariantBase {
396
586
  #private;
397
587
  constructor(name: string, diagnostics: Diagnostics, elementTerm: string);
@@ -400,21 +590,11 @@ declare class SlotValidator extends InvariantBase {
400
590
  assertSingleChild(count: number): void;
401
591
  }
402
592
 
403
- type FilterPredicate = (key: string, variantKeys: ReadonlySet<string>) => boolean;
404
-
405
- type BuiltChildrenEvaluator<TOptions extends WithChildRules> = TOptions extends {
406
- enforcement: {
407
- children: readonly unknown[];
408
- };
409
- } ? {
410
- childrenEvaluator: ChildrenEvaluator;
411
- } : EmptyRecord;
412
-
413
593
  declare function defineContractComponent<O extends FactoryOptions>(options: O): <R>(factory: (options: O) => R) => R;
414
594
 
415
595
  type UnknownProps = AnyRecord;
416
596
 
417
- type SvelteFactoryOptions<TDefault extends ElementType, Props extends UnknownProps, Variants extends Readonly<VariantMap>, TPreset extends RecipeMap<Variants> = Readonly<EmptyRecord>, TPlugin extends AnyClassPluginFactory = AnyClassPluginFactory> = FactoryOptions<TDefault, Props, Variants, TPreset, TPlugin> & {
597
+ type SvelteFactoryOptions<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> & {
418
598
  /**
419
599
  * Return true for any prop key that should be consumed but not forwarded to the DOM.
420
600
  * Receives `runtime.options.variantKeys` as a convenience if needed.
@@ -424,12 +604,50 @@ type SvelteFactoryOptions<TDefault extends ElementType, Props extends UnknownPro
424
604
 
425
605
  type TypedRuntime<G extends PolymorphicGenerics> = ReturnType<typeof createPolymorphic2<DefaultOf<G>, PropsOf<G>, VariantsOf<G>, RecipeOf<G>>>;
426
606
 
607
+ type OnElementFn<Props = unknown> = (element: Element, getProps: () => Readonly<Props>) => void | (() => void);
427
608
  type BuiltRuntime<G extends PolymorphicGenerics = PolymorphicGenerics, TOptions extends WithChildRules = WithChildRules> = BuiltChildrenEvaluator<TOptions> & {
428
609
  runtime: TypedRuntime<G>;
429
610
  filterProps: FilterPredicate;
430
611
  slotValidator: SlotValidator;
612
+ onElement?: OnElementFn<PropsOf<G>>;
431
613
  };
432
614
 
433
- 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, TOptions extends WithChildRules = SvelteFactoryOptions<TDefault, Props & ExtractPluginProps<TPlugin>, Variants, TPreset>>(options: SvelteFactoryOptions<TDefault, Props, Variants, TPreset, TPlugin> & TOptions): BuiltRuntime<PolymorphicGenerics<TDefault, Props & ExtractPluginProps<TPlugin>, Variants, TPreset>, TOptions>;
615
+ /**
616
+ * Creates a praxis-kit contract bundle for use with Svelte's `<Polymorphic>` component.
617
+ *
618
+ * Unlike the other adapters, this returns a plain bundle object rather than a component —
619
+ * Svelte components must come from `.svelte` files, a compile-time constraint — so the bundle
620
+ * is passed as the `bundle` prop:
621
+ *
622
+ * ```ts
623
+ * // button.ts
624
+ * export const buttonBundle = createContractComponent({
625
+ * tag: 'button',
626
+ * name: 'Button',
627
+ * styling: {
628
+ * base: 'btn',
629
+ * variants: { intent: { primary: 'btn--primary', ghost: 'btn--ghost' } },
630
+ * defaults: { intent: 'primary' },
631
+ * },
632
+ * })
633
+ * ```
634
+ *
635
+ * ```svelte
636
+ * <!-- Button.svelte -->
637
+ * <script lang="ts">
638
+ * import Polymorphic from 'praxis-kit/svelte/Polymorphic.svelte'
639
+ * import { buttonBundle } from './button'
640
+ * </script>
641
+ * <Polymorphic bundle={buttonBundle} intent="ghost" as="a" href="/home">Home</Polymorphic>
642
+ * ```
643
+ *
644
+ * Pass `subComponents` to attach named sub-components (`Card.Header`) — `Object.assign` works
645
+ * the same way on a plain bundle as on a component function/class, so `Card.Header` is itself
646
+ * just another bundle, passed to its own `<Polymorphic bundle={Card.Header}>`. Pass `onElement`
647
+ * to run setup once the real DOM element exists.
648
+ */
649
+ 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, TOptions extends WithChildRules = SvelteFactoryOptions<TDefault, MergeRecords<Props, ExtractPluginProps<TPlugin>>, Variants, TPreset>>(options: SvelteFactoryOptions<TDefault, Props, Variants, TPreset, TPlugin> & TOptions & {
650
+ readonly subComponents?: TSubComponents;
651
+ }): MergeRecords<BuiltRuntime<PolymorphicGenerics<TDefault, MergeRecords<Props, ExtractPluginProps<TPlugin>>, Variants, TPreset>, TOptions>, TSubComponents>;
434
652
 
435
653
  export { type AnyFactoryOptions, type BuiltRuntime, type ElementType, type EmptyRecord, type FilterPredicate, type PolymorphicGenerics, type SvelteFactoryOptions, type UnknownProps, type WithChildRules, createContractComponent, defineContractComponent };
@@ -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) {
@@ -48,7 +54,7 @@ function isNumber(value) {
48
54
 
49
55
  // ../../lib/primitive/src/rule/is-dynamic-rule.ts
50
56
  function isDynamicRule(rule) {
51
- return isObject(rule, true) && rule[RULE_BRAND] === true;
57
+ return isObject(rule, true) && Reflect.get(rule, RULE_BRAND) === true;
52
58
  }
53
59
 
54
60
  // ../../lib/primitive/src/rule/resolve-rule.ts
@@ -587,17 +593,17 @@ var COMPONENT_DEFAULT_TAG = /* @__PURE__ */ Symbol.for("praxis.component-default
587
593
  // ../../lib/primitive/src/guards/children/is-tag.ts
588
594
  function getAsProp(child) {
589
595
  if (!isObject(child) || !("props" in child)) return void 0;
590
- const props = child.props;
596
+ const { props } = child;
591
597
  if (!isObject(props)) return void 0;
592
- const as = props.as;
598
+ const as = Reflect.get(props, "as");
593
599
  return isString(as) && as !== "" ? as : void 0;
594
600
  }
595
601
  function getTag(child) {
596
602
  if (!isObject(child) || !("type" in child)) return void 0;
597
- const t = child.type;
603
+ const { type: t } = child;
598
604
  if (isString(t)) return t;
599
605
  if (typeof t === "function" || isObject(t)) {
600
- const defaultTag = t[COMPONENT_DEFAULT_TAG];
606
+ const defaultTag = Reflect.get(t, COMPONENT_DEFAULT_TAG);
601
607
  if (!isString(defaultTag)) return void 0;
602
608
  return getAsProp(child) ?? defaultTag;
603
609
  }
@@ -2767,7 +2773,7 @@ function getChildProp(child, key) {
2767
2773
  if (!isVNodeLike(child)) return void 0;
2768
2774
  const { props } = child;
2769
2775
  if (!isObject(props)) return void 0;
2770
- return props[key];
2776
+ return Reflect.get(props, key);
2771
2777
  }
2772
2778
 
2773
2779
  // ../core/src/html/contracts/aria/landmarks.ts
@@ -3440,15 +3446,17 @@ function buildRuntime(options) {
3440
3446
  runtime,
3441
3447
  filterProps,
3442
3448
  slotValidator,
3443
- ...childrenEvaluator !== void 0 && { childrenEvaluator }
3449
+ ...childrenEvaluator !== void 0 && { childrenEvaluator },
3450
+ ...options.onElement !== void 0 && { onElement: options.onElement }
3444
3451
  };
3445
3452
  }
3446
3453
 
3447
3454
  // ../../adapters/svelte/src/create-contract-component.ts
3448
3455
  function createContractComponent(options) {
3449
- return buildRuntime(
3456
+ const bundle = buildRuntime(
3450
3457
  options
3451
3458
  );
3459
+ return assembleCompoundComponent(bundle, options.subComponents);
3452
3460
  }
3453
3461
  export {
3454
3462
  createContractComponent,
@@ -17,8 +17,20 @@ import { RequireAtLeastOne, Simplify, ValueOf } from 'type-fest';
17
17
  */
18
18
  declare const layoutKeys: readonly ["flex", "inline-flex", "grid", "inline-grid", "block", "inline-block", "inline", "hidden", "contents", "flow-root", "list-item", "table", "inline-table", "table-caption", "table-cell", "table-column", "table-column-group", "table-footer-group", "table-header-group", "table-row-group", "table-row"];
19
19
 
20
+ /**
21
+ * A string-keyed object whose values are of type `T`.
22
+ */
20
23
  type StringMap<T = unknown> = Record<string, T>;
24
+ /**
25
+ * A string-keyed object with values of unknown type.
26
+ */
21
27
  type AnyRecord = StringMap<unknown>;
28
+ /**
29
+ * An object type with no named properties.
30
+ *
31
+ * Unlike `{}`, this excludes arbitrary properties during type operations while
32
+ * still satisfying `extends object`.
33
+ */
22
34
  type EmptyRecord = Record<never, never>;
23
35
 
24
36
  type IntrinsicTag = keyof HTMLElementTagNameMap;
@@ -167,10 +167,13 @@ function init(modules) {
167
167
  info.config.calleeNames ?? DEFAULT_CALLEE_NAMES
168
168
  );
169
169
  const proxy = /* @__PURE__ */ Object.create(null);
170
- const proxyRecord = proxy;
171
170
  for (const k of Object.keys(info.languageService)) {
172
171
  const x = info.languageService[k];
173
- proxyRecord[k] = typeof x === "function" ? x.bind(info.languageService) : x;
172
+ Reflect.set(
173
+ proxy,
174
+ k,
175
+ typeof x === "function" ? x.bind(info.languageService) : x
176
+ );
174
177
  }
175
178
  proxy.getSemanticDiagnostics = (fileName) => {
176
179
  const existing = info.languageService.getSemanticDiagnostics(fileName);
@@ -2,7 +2,13 @@ import { Plugin } from 'vite';
2
2
  import { Except, Simplify } from 'type-fest';
3
3
  import ts from 'typescript';
4
4
 
5
+ /**
6
+ * A string-keyed object whose values are of type `T`.
7
+ */
5
8
  type StringMap<T = unknown> = Record<string, T>;
9
+ /**
10
+ * A string-keyed object with values of unknown type.
11
+ */
6
12
  type AnyRecord = StringMap<unknown>;
7
13
 
8
14
  declare enum DiagnosticCategory {