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.
@@ -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) {
@@ -13,6 +19,11 @@ function makeResolveTag(defaultTag) {
13
19
  // ../../lib/primitive/src/rule/rule-brand.ts
14
20
  var RULE_BRAND = /* @__PURE__ */ Symbol("praxis-kit/dynamic-rule");
15
21
 
22
+ // ../../lib/primitive/src/rule/dynamic.ts
23
+ function dynamic(resolve) {
24
+ return { [RULE_BRAND]: true, resolve };
25
+ }
26
+
16
27
  // ../../lib/primitive/src/guards/foundational/is-defined.ts
17
28
  function isUndefined(value) {
18
29
  return value === void 0;
@@ -26,7 +37,7 @@ function isNonNull(value) {
26
37
  return value != null;
27
38
  }
28
39
  function isNullish(value) {
29
- return isNull(value) || value === void 0;
40
+ return isNull(value) || isUndefined(value);
30
41
  }
31
42
 
32
43
  // ../../lib/primitive/src/utils/type-guards.ts
@@ -43,7 +54,7 @@ function isNumber(value) {
43
54
 
44
55
  // ../../lib/primitive/src/rule/is-dynamic-rule.ts
45
56
  function isDynamicRule(rule) {
46
- return isObject(rule, true) && rule[RULE_BRAND] === true;
57
+ return isObject(rule, true) && Reflect.get(rule, RULE_BRAND) === true;
47
58
  }
48
59
 
49
60
  // ../../lib/primitive/src/rule/resolve-rule.ts
@@ -517,6 +528,24 @@ var ROLE_RESTRICTED_ATTRIBUTES = /* @__PURE__ */ new Map([
517
528
  ]
518
529
  ]);
519
530
 
531
+ // ../../lib/primitive/src/constants/html/void-tags.ts
532
+ var VOID_TAGS = [
533
+ "area",
534
+ "base",
535
+ "br",
536
+ "col",
537
+ "embed",
538
+ "hr",
539
+ "img",
540
+ "input",
541
+ "link",
542
+ "meta",
543
+ "param",
544
+ "source",
545
+ "track",
546
+ "wbr"
547
+ ];
548
+
520
549
  // ../../lib/primitive/src/guards/aria/is-aria-attribute.ts
521
550
  function isGlobalAriaAttribute(attr) {
522
551
  return GLOBAL_ARIA_ATTRIBUTES.has(attr);
@@ -564,17 +593,17 @@ var COMPONENT_DEFAULT_TAG = /* @__PURE__ */ Symbol.for("praxis.component-default
564
593
  // ../../lib/primitive/src/guards/children/is-tag.ts
565
594
  function getAsProp(child) {
566
595
  if (!isObject(child) || !("props" in child)) return void 0;
567
- const props = child.props;
596
+ const { props } = child;
568
597
  if (!isObject(props)) return void 0;
569
- const as = props.as;
598
+ const as = Reflect.get(props, "as");
570
599
  return isString(as) && as !== "" ? as : void 0;
571
600
  }
572
601
  function getTag(child) {
573
602
  if (!isObject(child) || !("type" in child)) return void 0;
574
- const t = child.type;
603
+ const { type: t } = child;
575
604
  if (isString(t)) return t;
576
605
  if (typeof t === "function" || isObject(t)) {
577
- const defaultTag = t[COMPONENT_DEFAULT_TAG];
606
+ const defaultTag = Reflect.get(t, COMPONENT_DEFAULT_TAG);
578
607
  if (!isString(defaultTag)) return void 0;
579
608
  return getAsProp(child) ?? defaultTag;
580
609
  }
@@ -1492,7 +1521,8 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
1492
1521
  const cached = _AriaPolicyEngine.#removeAttributeFixCache.get(attr);
1493
1522
  if (cached) return cached;
1494
1523
  const fix = {
1495
- kind: `removeAttribute:${attr}`,
1524
+ kind: "removeAttribute",
1525
+ attribute: attr,
1496
1526
  apply: ({ props }) => {
1497
1527
  if (!(attr in props)) return { applied: false, next: props };
1498
1528
  return { applied: true, next: omitProp(props, attr), previous: props };
@@ -1763,7 +1793,8 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
1763
1793
  if (!impliedLive) return NO_VIOLATIONS2;
1764
1794
  if ("aria-live" in props) return NO_VIOLATIONS2;
1765
1795
  const injectLive = {
1766
- kind: `injectLive:${effectiveRole}`,
1796
+ kind: "injectLive",
1797
+ attribute: "aria-live",
1767
1798
  apply: (ctx) => ({
1768
1799
  applied: true,
1769
1800
  next: { ...ctx.props, "aria-live": impliedLive },
@@ -1832,6 +1863,23 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
1832
1863
  }
1833
1864
  };
1834
1865
 
1866
+ // ../../lib/contract/src/aria/factories.ts
1867
+ function removeProp(props, key) {
1868
+ const next = { ...props };
1869
+ delete next[key];
1870
+ return next;
1871
+ }
1872
+ function removeAttributeFix(attribute) {
1873
+ return Object.freeze({
1874
+ kind: "removeAttribute",
1875
+ attribute,
1876
+ apply: ({ props }) => {
1877
+ if (!(attribute in props)) return { applied: false, next: props };
1878
+ return { applied: true, next: removeProp(props, attribute), previous: props };
1879
+ }
1880
+ });
1881
+ }
1882
+
1835
1883
  // ../../lib/contract/src/children/get-type-name.ts
1836
1884
  function getTypeName(value) {
1837
1885
  if (value === null) return "null";
@@ -2150,22 +2198,6 @@ import { warnDiagnostics as warnDiagnostics2 } from "../_shared/diagnostics.js";
2150
2198
 
2151
2199
  // ../core/src/html/contracts/categories.ts
2152
2200
  var METADATA_TAGS = ["script", "template"];
2153
- var VOID_TAGS = [
2154
- "area",
2155
- "base",
2156
- "br",
2157
- "col",
2158
- "embed",
2159
- "hr",
2160
- "img",
2161
- "input",
2162
- "link",
2163
- "meta",
2164
- "param",
2165
- "source",
2166
- "track",
2167
- "wbr"
2168
- ];
2169
2201
  var TEXT_ONLY_TAGS = [
2170
2202
  "option",
2171
2203
  "script",
@@ -2289,20 +2321,6 @@ var INPUT_MUTUALLY_EXCLUSIVE_POLICIES = [
2289
2321
 
2290
2322
  // ../core/src/html/spec/validators/attribute-type-validator.ts
2291
2323
  var DEFAULT_INPUT_TYPE = "text";
2292
- function omit(props, key) {
2293
- const next = { ...props };
2294
- delete next[key];
2295
- return next;
2296
- }
2297
- function removeAttributeFix(attribute) {
2298
- return {
2299
- kind: `removeAttribute:${attribute}`,
2300
- apply: ({ props }) => {
2301
- if (!(attribute in props)) return { applied: false, next: props };
2302
- return { applied: true, next: omit(props, attribute), previous: props };
2303
- }
2304
- };
2305
- }
2306
2324
  function createInputAttributeTypeRule({
2307
2325
  attribute,
2308
2326
  allowedTypes
@@ -2755,7 +2773,7 @@ function getChildProp(child, key) {
2755
2773
  if (!isVNodeLike(child)) return void 0;
2756
2774
  const { props } = child;
2757
2775
  if (!isObject(props)) return void 0;
2758
- return props[key];
2776
+ return Reflect.get(props, key);
2759
2777
  }
2760
2778
 
2761
2779
  // ../core/src/html/contracts/aria/landmarks.ts
@@ -2808,6 +2826,13 @@ function isLabelableControl(child) {
2808
2826
  const type = getChildProp(child, "type");
2809
2827
  return !isString(type) || type !== "hidden";
2810
2828
  }
2829
+ function hasAccessibleNameProp(props) {
2830
+ return "aria-label" in props || "aria-labelledby" in props;
2831
+ }
2832
+ function isNonEmptyTextChild(child) {
2833
+ if (isNumber(child)) return true;
2834
+ return isString(child) && child.trim().length > 0;
2835
+ }
2811
2836
  var labelContract = contract([
2812
2837
  { name: "control", match: isLabelableControl, cardinality: { max: 1 } },
2813
2838
  { name: "nested-label", match: isTag("label"), cardinality: { max: 0 } },
@@ -2815,6 +2840,13 @@ var labelContract = contract([
2815
2840
  name: "other-interactive-content",
2816
2841
  match: isTag(...OTHER_INTERACTIVE_TAGS),
2817
2842
  cardinality: { max: 0 }
2843
+ },
2844
+ {
2845
+ name: "accessible-name",
2846
+ match: isNonEmptyTextChild,
2847
+ cardinality: dynamic(
2848
+ (ctx) => hasAccessibleNameProp(ctx.props) ? { min: 0 } : { min: 1 }
2849
+ )
2818
2850
  }
2819
2851
  ]);
2820
2852
 
@@ -3414,15 +3446,17 @@ function buildRuntime(options) {
3414
3446
  runtime,
3415
3447
  filterProps,
3416
3448
  slotValidator,
3417
- ...childrenEvaluator !== void 0 && { childrenEvaluator }
3449
+ ...childrenEvaluator !== void 0 && { childrenEvaluator },
3450
+ ...options.onElement !== void 0 && { onElement: options.onElement }
3418
3451
  };
3419
3452
  }
3420
3453
 
3421
3454
  // ../../adapters/svelte/src/create-contract-component.ts
3422
3455
  function createContractComponent(options) {
3423
- return buildRuntime(
3456
+ const bundle = buildRuntime(
3424
3457
  options
3425
3458
  );
3459
+ return assembleCompoundComponent(bundle, options.subComponents);
3426
3460
  }
3427
3461
  export {
3428
3462
  createContractComponent,
@@ -223,6 +223,24 @@ var LRUCache = class {
223
223
  }
224
224
  };
225
225
 
226
+ // ../../lib/primitive/src/constants/html/void-tags.ts
227
+ var VOID_TAGS = [
228
+ "area",
229
+ "base",
230
+ "br",
231
+ "col",
232
+ "embed",
233
+ "hr",
234
+ "img",
235
+ "input",
236
+ "link",
237
+ "meta",
238
+ "param",
239
+ "source",
240
+ "track",
241
+ "wbr"
242
+ ];
243
+
226
244
  // ../../node_modules/.pnpm/class-variance-authority@0.7.1/node_modules/class-variance-authority/dist/index.mjs
227
245
  import { clsx as clsx2 } from "clsx";
228
246
  var falsyToString = (value) => typeof value === "boolean" ? `${value}` : value === 0 ? "0" : value;
@@ -597,6 +615,13 @@ var TailwindDiagnostics = {
597
615
  category: DiagnosticCategory.Contract,
598
616
  message: `[createTailwindPipeline] Variant "${dim}=${value}" contributes only classes stripped under layout mode "${mode}" ("${classStr}") \u2014 it produces nothing in this mode.`
599
617
  };
618
+ },
619
+ layoutOnVoidTag(tag, mode) {
620
+ return {
621
+ code: DiagnosticCode.TailwindLayoutOnVoidTag,
622
+ category: DiagnosticCategory.Contract,
623
+ message: `[createTailwindPipeline] "${mode}" sets <${tag}>'s inner display, but <${tag}> is a void element and can never have children \u2014 there is nothing for a flex/grid formatting context to apply to, so "${mode}" (and any gap-* utility) has no effect here.`
624
+ };
600
625
  }
601
626
  };
602
627
 
@@ -626,6 +651,7 @@ var devDiagnostics = new Diagnostics(
626
651
  var classifier = new ClassClassifier();
627
652
  var evaluator = new DependencyEvaluator(defaultDependencyRules);
628
653
  var builder = new ClassBuilder();
654
+ var VOID_TAG_SET = new Set(VOID_TAGS);
629
655
  function normalizeVariantValue(value) {
630
656
  if (isString(value)) return value;
631
657
  return value.join(" ");
@@ -640,6 +666,10 @@ function resolveLayout(diagnostics, props) {
640
666
  }
641
667
  return active[0] ?? "none";
642
668
  }
669
+ function warnLayoutOnVoidTag(diagnostics, tag, state) {
670
+ if (state.family === "none" || !isString(tag) || !VOID_TAG_SET.has(tag)) return;
671
+ diagnostics.warn(TailwindDiagnostics.layoutOnVoidTag(tag, state.mode));
672
+ }
643
673
  function warnReservedLayoutLiterals(diagnostics, tokens) {
644
674
  const reserved = [];
645
675
  iterate.forEach(tokens, (token) => {
@@ -705,6 +735,7 @@ function createTailwindPipeline(options, diagnostics) {
705
735
  const tokens = classifyTokens(resolvedClasses);
706
736
  const state = new LayoutState(mode);
707
737
  const filtered = tokens.filter((token) => evaluator.evaluate(token, state));
738
+ if (DEV) warnLayoutOnVoidTag(devDiagnostics, tag, state);
708
739
  return { mode, state, filtered, tokens, props, recipe };
709
740
  };
710
741
  const buildClassString = (ctx) => {
@@ -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);
@@ -97,6 +97,7 @@ declare enum DiagnosticCode {
97
97
  TailwindMultipleDisplayProps = "CSS6001",
98
98
  TailwindReservedLayoutLiteral = "CSS6002",
99
99
  TailwindDeadVariantClass = "CSS6003",
100
+ TailwindLayoutOnVoidTag = "CSS6004",
100
101
  PluginInvalidShape = "PLUGIN7001",
101
102
  PluginPipelineReturnType = "PLUGIN7002",
102
103
  InternalError = "INTERNAL9000"
@@ -6,6 +6,8 @@ import { AllowedComponentProps } from 'vue';
6
6
  type StringMap<T = unknown> = Record<string, T>;
7
7
  type AnyRecord = StringMap<unknown>;
8
8
  type EmptyRecord = Record<never, never>;
9
+ /** A compound component's named sub-components, e.g. `{ Header, Content, Footer }`. */
10
+ type SubComponentMap = Readonly<AnyRecord>;
9
11
 
10
12
  type IntrinsicTag = keyof HTMLElementTagNameMap;
11
13
 
@@ -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
  declare function defineContractComponent<O extends FactoryOptions>(options: O): <R>(factory: (options: O) => R) => R;
@@ -367,6 +396,8 @@ type PolymorphicComponent<G extends PolymorphicGenerics> = {
367
396
  displayName?: string;
368
397
  };
369
398
 
370
- 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: VueFactoryOptions<TDefault, Props, Variants, TPreset, TPlugin>): PolymorphicComponent<PolymorphicGenerics<TDefault, Props & ExtractPluginProps<TPlugin>, Variants, TPreset>>;
399
+ 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: VueFactoryOptions<TDefault, Props, Variants, TPreset, TPlugin> & {
400
+ readonly subComponents?: TSubComponents;
401
+ }): PolymorphicComponent<PolymorphicGenerics<TDefault, Props & ExtractPluginProps<TPlugin>, Variants, TPreset>> & TSubComponents;
371
402
 
372
403
  export { type AnyFactoryOptions, type ElementType, type EmptyRecord, type PolymorphicComponent, type PolymorphicGenerics, type PolymorphicProps, type PolymorphicWithAsChild, Slottable, type SlottableProps, type VueFactoryOptions, createContractComponent, defineContractComponent };