praxis-kit 5.0.0 → 6.1.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.
@@ -184,6 +184,45 @@ var iterate = Object.freeze({
184
184
  values
185
185
  });
186
186
 
187
+ // ../../lib/primitive/src/utils/lru-cache.ts
188
+ var LRUCache = class {
189
+ #maxSize;
190
+ #store = /* @__PURE__ */ new Map();
191
+ constructor(maxSize) {
192
+ if (!Number.isInteger(maxSize) || maxSize < 1) {
193
+ throw new RangeError("LRUCache maxSize must be a positive integer.");
194
+ }
195
+ this.#maxSize = maxSize;
196
+ }
197
+ get(key) {
198
+ if (!this.#store.has(key)) return void 0;
199
+ const value = this.#store.get(key);
200
+ this.#store.delete(key);
201
+ this.#store.set(key, value);
202
+ return value;
203
+ }
204
+ set(key, value) {
205
+ this.#store.delete(key);
206
+ this.#store.set(key, value);
207
+ if (this.#store.size > this.#maxSize) {
208
+ const lru = this.#store.keys().next().value;
209
+ if (lru !== void 0) this.#store.delete(lru);
210
+ }
211
+ }
212
+ has(key) {
213
+ return this.#store.has(key);
214
+ }
215
+ delete(key) {
216
+ return this.#store.delete(key);
217
+ }
218
+ get size() {
219
+ return this.#store.size;
220
+ }
221
+ clear() {
222
+ this.#store.clear();
223
+ }
224
+ };
225
+
187
226
  // ../../node_modules/.pnpm/class-variance-authority@0.7.1/node_modules/class-variance-authority/dist/index.mjs
188
227
  import { clsx as clsx2 } from "clsx";
189
228
  var falsyToString = (value) => typeof value === "boolean" ? `${value}` : value === 0 ? "0" : value;
@@ -236,7 +275,7 @@ function cva2(base, config) {
236
275
  // ../../lib/styling/src/static-class-resolver.ts
237
276
  var StaticClassResolver = class {
238
277
  #baseClass;
239
- #cache = /* @__PURE__ */ new Map();
278
+ #cache = new LRUCache(200);
240
279
  #resolveTag;
241
280
  constructor(baseClass, tagMap) {
242
281
  this.#baseClass = Array.isArray(baseClass) ? baseClass.join(" ") : baseClass;
@@ -250,17 +289,9 @@ var StaticClassResolver = class {
250
289
  resolve(tag, skipTagMap = false) {
251
290
  if (typeof tag !== "string" || skipTagMap) return this.#baseClass;
252
291
  const cached = this.#cache.get(tag);
253
- if (cached !== void 0) {
254
- this.#cache.delete(tag);
255
- this.#cache.set(tag, cached);
256
- return cached;
257
- }
292
+ if (cached !== void 0) return cached;
258
293
  const result = this.#resolveTag(tag);
259
294
  this.#cache.set(tag, result);
260
- if (this.#cache.size > 200) {
261
- const lru = this.#cache.keys().next().value;
262
- if (lru !== void 0) this.#cache.delete(lru);
263
- }
264
295
  return result;
265
296
  }
266
297
  };
@@ -271,7 +302,7 @@ var VariantClassResolver = class _VariantClassResolver {
271
302
  #recipeMap;
272
303
  #variantKeys;
273
304
  #precomputedClasses;
274
- #cache = /* @__PURE__ */ new Map();
305
+ #cache = new LRUCache(1e3);
275
306
  constructor(cvaFn, recipeMap, variantKeys, precomputedClasses) {
276
307
  this.#cvaFn = cvaFn ?? null;
277
308
  this.#recipeMap = Object.freeze(recipeMap ?? {});
@@ -286,17 +317,9 @@ var VariantClassResolver = class _VariantClassResolver {
286
317
  if (precomputed !== void 0) return precomputed;
287
318
  }
288
319
  const cached = this.#cache.get(cacheKey);
289
- if (cached !== void 0) {
290
- this.#cache.delete(cacheKey);
291
- this.#cache.set(cacheKey, cached);
292
- return cached;
293
- }
320
+ if (cached !== void 0) return cached;
294
321
  const result = this.#compute(props, recipe);
295
322
  this.#cache.set(cacheKey, result);
296
- if (this.#cache.size > 1e3) {
297
- const lru = this.#cache.keys().next().value;
298
- if (lru !== void 0) this.#cache.delete(lru);
299
- }
300
323
  return result;
301
324
  }
302
325
  #compute(props, recipe) {
@@ -358,6 +381,14 @@ function createClassPipeline(resolved) {
358
381
  };
359
382
  }
360
383
 
384
+ // ../../lib/pipeline-kit/src/core/compose-pipelines.ts
385
+ function composePipelines(first, second) {
386
+ return (...args) => second(first(...args));
387
+ }
388
+
389
+ // ../../lib/tailwind/src/create-tailwind-pipeline.ts
390
+ import { ConsoleReporter, DefaultPolicy, Diagnostics, Severity } from "../_shared/diagnostics.js";
391
+
361
392
  // ../../lib/tailwind/src/class-builder.ts
362
393
  var ClassBuilder = class {
363
394
  build(tokens) {
@@ -371,6 +402,7 @@ var ClassBuilder = class {
371
402
  }
372
403
  case "utility":
373
404
  case "gap":
405
+ case "shared":
374
406
  case "conditional": {
375
407
  normal.push(token.raw);
376
408
  break;
@@ -444,6 +476,16 @@ var CONDITIONALS = {
444
476
  "[&.flex": "flex",
445
477
  "[&.grid": "grid"
446
478
  };
479
+ var SHARED_PREFIXES = [
480
+ /^order/,
481
+ /^justify-(?!items-|self-)/,
482
+ /^content-/,
483
+ /^items-/,
484
+ /^self-/,
485
+ /^place-content-/,
486
+ /^place-items-/,
487
+ /^place-self-/
488
+ ];
447
489
  var ClassClassifier = class _ClassClassifier {
448
490
  static #getBaseUtility(token) {
449
491
  let depth = 0;
@@ -476,23 +518,16 @@ var ClassClassifier = class _ClassClassifier {
476
518
  }
477
519
  );
478
520
  if (conditional !== null) return conditional;
479
- return base === "gap" || base.startsWith("gap-") ? {
480
- kind: "gap",
481
- raw: token
482
- } : {
483
- kind: "utility",
484
- base,
485
- raw: token
486
- };
521
+ if (base === "gap" || base.startsWith("gap-")) {
522
+ return { kind: "gap", raw: token };
523
+ }
524
+ if (SHARED_PREFIXES.some((rule) => rule.test(base))) {
525
+ return { kind: "shared", raw: token };
526
+ }
527
+ return { kind: "utility", base, raw: token };
487
528
  }
488
529
  };
489
530
 
490
- // ../../lib/tailwind/src/dependency-rules.ts
491
- var defaultDependencyRules = {
492
- flex: [/^flex-/, /^grow/, /^shrink/, /^basis-/],
493
- grid: [/^grid-/, /^col-/, /^row-/, /^auto-cols-/, /^auto-rows-/]
494
- };
495
-
496
531
  // ../../lib/tailwind/src/dependency-evaluator.ts
497
532
  var DependencyEvaluator = class {
498
533
  constructor(rules) {
@@ -513,7 +548,8 @@ var DependencyEvaluator = class {
513
548
  (layout) => this.rules[layout].some((rule) => rule.test(token.base)) ? state.family === layout : null
514
549
  ) ?? true;
515
550
  }
516
- case "gap": {
551
+ case "gap":
552
+ case "shared": {
517
553
  return state.family !== "none";
518
554
  }
519
555
  default:
@@ -522,26 +558,22 @@ var DependencyEvaluator = class {
522
558
  }
523
559
  };
524
560
 
525
- // ../../lib/tailwind/src/layout-state.ts
526
- var LayoutState = class {
527
- #mode;
528
- #family;
529
- constructor(mode) {
530
- this.#mode = mode;
531
- this.#family = mode === "none" ? "none" : LAYOUT_FAMILY_MAP[mode];
532
- Object.freeze(this);
533
- }
534
- get mode() {
535
- return this.#mode;
536
- }
537
- get family() {
538
- return this.#family;
539
- }
561
+ // ../../lib/tailwind/src/dependency-rules.ts
562
+ var defaultDependencyRules = {
563
+ flex: [/^flex-/, /^grow/, /^shrink/, /^basis-/],
564
+ grid: [
565
+ /^grid-/,
566
+ /^col-/,
567
+ /^row-/,
568
+ /^auto-cols-/,
569
+ /^auto-rows-/,
570
+ // justify-items/-self are no-ops on flex containers per the CSS box
571
+ // alignment spec (flex items ignore them), so treat as grid-only.
572
+ /^justify-items-/,
573
+ /^justify-self-/
574
+ ]
540
575
  };
541
576
 
542
- // ../../lib/tailwind/src/create-tailwind-pipeline.ts
543
- import { ConsoleReporter, Diagnostics, DefaultPolicy, Severity } from "../_shared/diagnostics.js";
544
-
545
577
  // ../../lib/tailwind/src/diagnostics.ts
546
578
  import { DiagnosticCategory, DiagnosticCode } from "../_shared/diagnostics.js";
547
579
  var TailwindDiagnostics = {
@@ -568,6 +600,23 @@ var TailwindDiagnostics = {
568
600
  }
569
601
  };
570
602
 
603
+ // ../../lib/tailwind/src/layout-state.ts
604
+ var LayoutState = class {
605
+ #mode;
606
+ #family;
607
+ constructor(mode) {
608
+ this.#mode = mode;
609
+ this.#family = mode === "none" ? "none" : LAYOUT_FAMILY_MAP[mode];
610
+ Object.freeze(this);
611
+ }
612
+ get mode() {
613
+ return this.#mode;
614
+ }
615
+ get family() {
616
+ return this.#family;
617
+ }
618
+ };
619
+
571
620
  // ../../lib/tailwind/src/create-tailwind-pipeline.ts
572
621
  var DEV = process.env.NODE_ENV !== "production";
573
622
  var devDiagnostics = new Diagnostics(
@@ -648,23 +697,36 @@ function warnDeadVariants(diagnostics, options, compoundDims, props, recipe, sta
648
697
  });
649
698
  }
650
699
  function createTailwindPipeline(options, diagnostics) {
651
- const pipeline = createClassPipeline(options);
700
+ const innerPipeline = createClassPipeline(options);
652
701
  const compoundDims = compoundDimensions(getCompoundVariants(options));
702
+ const resolveLayoutContext = (tag, props, className, recipe) => {
703
+ const mode = resolveLayout(devDiagnostics, props);
704
+ const resolvedClasses = innerPipeline(tag, props, className, recipe);
705
+ const tokens = classifyTokens(resolvedClasses);
706
+ const state = new LayoutState(mode);
707
+ const filtered = tokens.filter((token) => evaluator.evaluate(token, state));
708
+ return { mode, state, filtered, tokens, props, recipe };
709
+ };
710
+ const buildClassString = (ctx) => {
711
+ const built = builder.build(ctx.filtered);
712
+ if (ctx.mode === "none") return built;
713
+ return ctx.filtered.some((t) => t.kind === "layout" && t.value === ctx.mode) ? built : cn(ctx.mode, built);
714
+ };
715
+ const emitDiagnosticsFromContext = (ctx) => {
716
+ if (!DEV) return;
717
+ warnReservedLayoutLiterals(diagnostics, ctx.tokens);
718
+ warnDeadVariants(diagnostics, options, compoundDims, ctx.props, ctx.recipe, ctx.state);
719
+ };
720
+ const combined = (ctx) => {
721
+ const built = buildClassString(ctx);
722
+ emitDiagnosticsFromContext(ctx);
723
+ return built;
724
+ };
725
+ const mainPipeline = composePipelines(resolveLayoutContext, combined);
653
726
  return {
654
727
  ownedKeys: LAYOUT_OWNED_KEYS,
655
728
  pipeline(tag, props, className, recipe) {
656
- const mode = resolveLayout(devDiagnostics, props);
657
- const raw = pipeline(tag, props, className, recipe);
658
- const tokens = classifyTokens(raw);
659
- const state = new LayoutState(mode);
660
- if (DEV) {
661
- warnReservedLayoutLiterals(diagnostics, tokens);
662
- warnDeadVariants(diagnostics, options, compoundDims, props, recipe, state);
663
- }
664
- const filtered = tokens.filter((token) => evaluator.evaluate(token, state));
665
- const built = builder.build(filtered);
666
- if (mode === "none") return built;
667
- return filtered.some((t) => t.kind === "layout" && t.value === mode) ? built : cn(mode, built);
729
+ return mainPipeline(tag, props, className, recipe);
668
730
  }
669
731
  };
670
732
  }
@@ -171,6 +171,19 @@ var iterate = Object.freeze({
171
171
  values
172
172
  });
173
173
 
174
+ // ../../lib/primitive/src/utils/lazy.ts
175
+ function lazy(factory) {
176
+ let initialized = false;
177
+ let value;
178
+ return () => {
179
+ if (!initialized) {
180
+ value = factory();
181
+ initialized = true;
182
+ }
183
+ return value;
184
+ };
185
+ }
186
+
174
187
  // ../../plugins/vite/src/ast.ts
175
188
  function getProperty(obj, key) {
176
189
  return iterate.find(obj.properties, (prop) => {
@@ -744,8 +757,7 @@ function analyzeJsxSites(source, constraints, severity) {
744
757
  count = ZERO;
745
758
  }
746
759
  if (!tagName) return;
747
- let pos;
748
- const getPos = () => pos ??= source.getLineAndCharacterOfPosition(node.getStart(source));
760
+ const getPos = lazy(() => source.getLineAndCharacterOfPosition(node.getStart(source)));
749
761
  if (count !== void 0) {
750
762
  const c = byName.get(tagName);
751
763
  if (c && (count.max < c.totalMin || c.exclusiveChildren && count.min > c.totalMax)) {
@@ -31,6 +31,26 @@ type MinMax = {
31
31
  };
32
32
  type CardinalityInput = Partial<MinMax>;
33
33
 
34
+ /**
35
+ * Resolved per-instance state available to a dynamic (`dynamic(...)`) child
36
+ * rule field — the same tag/props every adapter already computes before
37
+ * evaluating children, exposed so a rule can vary by them (e.g. cardinality
38
+ * that depends on the resolved `as` tag).
39
+ */
40
+ type ChildRuleContext = {
41
+ readonly tag: unknown;
42
+ readonly props: Readonly<AnyRecord>;
43
+ };
44
+
45
+ declare const RULE_BRAND: unique symbol;
46
+
47
+ type DynamicRule<T, C = unknown> = {
48
+ readonly [RULE_BRAND]: true;
49
+ resolve(context: C): T;
50
+ };
51
+
52
+ type Rule<T, C = unknown> = T | DynamicRule<T, C>;
53
+
34
54
  type ChildRuleMatch<T, U extends T = T> = (child: T) => child is U;
35
55
 
36
56
  type ChildRulePosition = 'first' | 'last' | 'any';
@@ -38,7 +58,13 @@ type ChildRulePosition = 'first' | 'last' | 'any';
38
58
  type ChildRuleInput<T = unknown, U extends T = T> = {
39
59
  name: string;
40
60
  match: ChildRuleMatch<T, U>;
41
- cardinality?: CardinalityInput;
61
+ /**
62
+ * Either a static cardinality, or `dynamic((ctx) => ...)` to derive it from
63
+ * the resolved tag/props (e.g. a different max depending on `as`). `match`
64
+ * stays static-only — it's already a function, so a dynamic wrapper would
65
+ * be indistinguishable from the predicate itself without one.
66
+ */
67
+ cardinality?: Rule<CardinalityInput, ChildRuleContext>;
42
68
  position?: ChildRulePosition;
43
69
  /**
44
70
  * Optional component-type reference for O(1) dispatch index.
package/dist/vue/index.js CHANGED
@@ -456,6 +456,19 @@ function makeResolveTag(defaultTag) {
456
456
  };
457
457
  }
458
458
 
459
+ // ../../lib/primitive/src/rule/rule-brand.ts
460
+ var RULE_BRAND = /* @__PURE__ */ Symbol("praxis-kit/dynamic-rule");
461
+
462
+ // ../../lib/primitive/src/rule/is-dynamic-rule.ts
463
+ function isDynamicRule(rule) {
464
+ return isObject(rule, true) && rule[RULE_BRAND] === true;
465
+ }
466
+
467
+ // ../../lib/primitive/src/rule/resolve-rule.ts
468
+ function resolveRule(rule, context) {
469
+ return isDynamicRule(rule) ? rule.resolve(context) : rule;
470
+ }
471
+
459
472
  // ../../lib/primitive/src/utils/assert-never.ts
460
473
  function assertNever(value) {
461
474
  throw new Error(`Unexpected value: ${String(value)}`);
@@ -637,6 +650,45 @@ var iterate = Object.freeze({
637
650
  values
638
651
  });
639
652
 
653
+ // ../../lib/primitive/src/utils/lru-cache.ts
654
+ var LRUCache = class {
655
+ #maxSize;
656
+ #store = /* @__PURE__ */ new Map();
657
+ constructor(maxSize) {
658
+ if (!Number.isInteger(maxSize) || maxSize < 1) {
659
+ throw new RangeError("LRUCache maxSize must be a positive integer.");
660
+ }
661
+ this.#maxSize = maxSize;
662
+ }
663
+ get(key) {
664
+ if (!this.#store.has(key)) return void 0;
665
+ const value = this.#store.get(key);
666
+ this.#store.delete(key);
667
+ this.#store.set(key, value);
668
+ return value;
669
+ }
670
+ set(key, value) {
671
+ this.#store.delete(key);
672
+ this.#store.set(key, value);
673
+ if (this.#store.size > this.#maxSize) {
674
+ const lru = this.#store.keys().next().value;
675
+ if (lru !== void 0) this.#store.delete(lru);
676
+ }
677
+ }
678
+ has(key) {
679
+ return this.#store.has(key);
680
+ }
681
+ delete(key) {
682
+ return this.#store.delete(key);
683
+ }
684
+ get size() {
685
+ return this.#store.size;
686
+ }
687
+ clear() {
688
+ this.#store.clear();
689
+ }
690
+ };
691
+
640
692
  // ../../lib/primitive/src/utils/merge-props.ts
641
693
  function mergeProps(defaultProps, props) {
642
694
  return {
@@ -645,28 +697,6 @@ function mergeProps(defaultProps, props) {
645
697
  };
646
698
  }
647
699
 
648
- // ../../lib/contract/src/strict/invariant-base.ts
649
- var InvariantBase = class {
650
- diagnostics;
651
- constructor(diagnostics) {
652
- this.diagnostics = diagnostics;
653
- }
654
- get active() {
655
- return this.diagnostics.active;
656
- }
657
- violate(input) {
658
- this.diagnostics.error(input);
659
- }
660
- // Always caps at warn — never throws. ARIA 'warning' violations route here
661
- // so they surface even in strict='throw' mode without aborting a render.
662
- warn(input) {
663
- this.diagnostics.warn(input);
664
- }
665
- invariant(condition, input) {
666
- if (!condition) this.violate(input);
667
- }
668
- };
669
-
670
700
  // ../../lib/contract/src/diagnostics/aria.ts
671
701
  import { DiagnosticCategory, DiagnosticCode } from "../_shared/diagnostics.js";
672
702
  var AriaDiagnostics = {
@@ -1023,6 +1053,28 @@ var SlotDiagnostics = {
1023
1053
  }
1024
1054
  };
1025
1055
 
1056
+ // ../../lib/contract/src/strict/invariant-base.ts
1057
+ var InvariantBase = class {
1058
+ diagnostics;
1059
+ constructor(diagnostics) {
1060
+ this.diagnostics = diagnostics;
1061
+ }
1062
+ get active() {
1063
+ return this.diagnostics.active;
1064
+ }
1065
+ violate(input) {
1066
+ this.diagnostics.error(input);
1067
+ }
1068
+ // Always caps at warn — never throws. ARIA 'warning' violations route here
1069
+ // so they surface even in strict='throw' mode without aborting a render.
1070
+ warn(input) {
1071
+ this.diagnostics.warn(input);
1072
+ }
1073
+ invariant(condition, input) {
1074
+ if (!condition) this.violate(input);
1075
+ }
1076
+ };
1077
+
1026
1078
  // ../../lib/contract/src/aria/polymorphic-validator.ts
1027
1079
  var VALID = [{ valid: true }];
1028
1080
  function isIntrinsicTag(tag) {
@@ -1034,8 +1086,7 @@ function omitProp(obj, key) {
1034
1086
  }
1035
1087
  var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
1036
1088
  #extraRules;
1037
- #planCache = /* @__PURE__ */ new Map();
1038
- static #MAX_CACHE = 100;
1089
+ #planCache = new LRUCache(100);
1039
1090
  // Memoized AriaFix objects keyed by attribute name — the ARIA attribute set is
1040
1091
  // finite so this Map is bounded and avoids recreating closures on every cache miss.
1041
1092
  static #removeAttributeFixCache = /* @__PURE__ */ new Map();
@@ -1191,8 +1242,6 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
1191
1242
  if (!isNull(key)) {
1192
1243
  const cached = this.#planCache.get(key);
1193
1244
  if (cached !== void 0) {
1194
- this.#planCache.delete(key);
1195
- this.#planCache.set(key, cached);
1196
1245
  if (cached.violations.length > 0) this.report(cached.violations);
1197
1246
  return {
1198
1247
  props: _AriaPolicyEngine.#applyPlan(props, cached.removals, cached.updates),
@@ -1209,10 +1258,6 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
1209
1258
  );
1210
1259
  const plan = { removals, updates, violations: result.violations };
1211
1260
  this.#planCache.set(key, plan);
1212
- if (this.#planCache.size > _AriaPolicyEngine.#MAX_CACHE) {
1213
- const lru = this.#planCache.keys().next().value;
1214
- if (lru !== void 0) this.#planCache.delete(lru);
1215
- }
1216
1261
  }
1217
1262
  return result;
1218
1263
  }
@@ -1868,10 +1913,22 @@ var RuleValidator = class _RuleValidator extends InvariantBase {
1868
1913
 
1869
1914
  // ../../lib/contract/src/children/children-evaluator.ts
1870
1915
  var isTextLike = (child) => isString(child) || isNumber(child);
1916
+ function checkPositionCardinalityInvariant(rules, context) {
1917
+ iterate.forEach(rules, (rule) => {
1918
+ const { name, position, cardinality } = rule;
1919
+ if ((position === "first" || position === "last") && (cardinality.kind === "unbounded" || cardinality.max > 1)) {
1920
+ throw new RangeError(
1921
+ `ChildrenEvaluator [${context}]: rule "${name}" sets position="${position}" with an unbound or >1 max. position="first|last" implies max=1.`
1922
+ );
1923
+ }
1924
+ });
1925
+ }
1871
1926
  var ChildrenEvaluator = class extends InvariantBase {
1872
1927
  #context;
1873
- #rules;
1874
- #ruleNames;
1928
+ /** Rules with a static cardinality — normalized once, reused on every evaluate() call. */
1929
+ #staticRules;
1930
+ /** Rules whose cardinality is `dynamic(...)` — re-resolved against a ChildRuleContext per call. */
1931
+ #dynamicRuleInputs;
1875
1932
  #matcher;
1876
1933
  #ruleValidator;
1877
1934
  #exclusiveChildren;
@@ -1879,29 +1936,39 @@ var ChildrenEvaluator = class extends InvariantBase {
1879
1936
  constructor(rules, diagnostics, context = "Component", options = {}) {
1880
1937
  super(diagnostics);
1881
1938
  this.#context = context;
1882
- this.#rules = rules.map((r) => normalizeChildRule(r));
1883
- this.#ruleNames = this.#rules.map((r) => r.name);
1884
1939
  this.#exclusiveChildren = options.exclusiveChildren ?? false;
1885
1940
  this.#allowText = options.allowText ?? true;
1886
- iterate.forEach(this.#rules, (rule) => {
1887
- const { name, position, cardinality } = rule;
1888
- if ((position === "first" || position === "last") && (cardinality.kind === "unbounded" || cardinality.max > 1)) {
1889
- throw new RangeError(
1890
- `ChildrenEvaluator [${context}]: rule "${name}" sets position="${position}" with an unbound or >1 max. position="first|last" implies max=1.`
1891
- );
1892
- }
1941
+ const staticRuleInputs = [];
1942
+ const dynamicRuleInputs = [];
1943
+ iterate.forEach(rules, (rule) => {
1944
+ if (isDynamicRule(rule.cardinality)) dynamicRuleInputs.push(rule);
1945
+ else staticRuleInputs.push(rule);
1893
1946
  });
1894
- this.#matcher = new RuleMatcher(this.#rules);
1947
+ this.#dynamicRuleInputs = dynamicRuleInputs;
1948
+ this.#staticRules = staticRuleInputs.map(
1949
+ (r) => normalizeChildRule(r)
1950
+ );
1895
1951
  this.#ruleValidator = new RuleValidator(context, diagnostics);
1952
+ if (this.#dynamicRuleInputs.length === 0) {
1953
+ checkPositionCardinalityInvariant(this.#staticRules, context);
1954
+ this.#matcher = new RuleMatcher(this.#staticRules);
1955
+ } else {
1956
+ this.#matcher = void 0;
1957
+ }
1896
1958
  }
1897
- evaluate(children) {
1959
+ /**
1960
+ * @param context Required when any rule has a `dynamic(...)` cardinality —
1961
+ * supplies the resolved tag/props those rules are evaluated against.
1962
+ */
1963
+ evaluate(children, context) {
1898
1964
  if (!this.active) return;
1965
+ const { rules, matcher } = this.#resolveRules(context);
1899
1966
  const {
1900
1967
  matrix,
1901
1968
  unexpectedIndices: rawUnexpectedIndices,
1902
1969
  ambiguousIndices
1903
- } = this.#matcher.match(children);
1904
- this.#ruleValidator.validate(this.#rules, matrix, children.length);
1970
+ } = matcher.match(children);
1971
+ this.#ruleValidator.validate(rules, matrix, children.length);
1905
1972
  const unexpectedIndices = new Set(
1906
1973
  [...rawUnexpectedIndices].filter(
1907
1974
  (ci) => isTextLike(children[ci]) ? this.#allowText === false : this.#exclusiveChildren
@@ -1915,11 +1982,28 @@ var ChildrenEvaluator = class extends InvariantBase {
1915
1982
  this.violate(ContractDiagnostics.unexpectedChild(typeName, ci, this.#context));
1916
1983
  } else {
1917
1984
  const matches = matrix.childToRules.forward.get(ci);
1918
- const names = [...matches].map((ri) => this.#ruleNames[ri] ?? `#${ri}`);
1985
+ const names = [...matches].map((ri) => rules[ri]?.name ?? `#${ri}`);
1919
1986
  this.violate(ContractDiagnostics.ambiguousChild(typeName, ci, names, this.#context));
1920
1987
  }
1921
1988
  });
1922
1989
  }
1990
+ #resolveRules(context) {
1991
+ if (this.#dynamicRuleInputs.length === 0) {
1992
+ return { rules: this.#staticRules, matcher: this.#matcher };
1993
+ }
1994
+ if (context === void 0) {
1995
+ throw new RangeError(
1996
+ `ChildrenEvaluator [${this.#context}]: rule(s) have a dynamic(...) cardinality \u2014 evaluate() requires a context argument to resolve them.`
1997
+ );
1998
+ }
1999
+ const resolvedDynamicRules = this.#dynamicRuleInputs.map((r) => {
2000
+ const cardinality = resolveRule(r.cardinality, context);
2001
+ return normalizeChildRule({ ...r, cardinality });
2002
+ });
2003
+ checkPositionCardinalityInvariant(resolvedDynamicRules, this.#context);
2004
+ const rules = [...this.#staticRules, ...resolvedDynamicRules];
2005
+ return { rules, matcher: new RuleMatcher(rules) };
2006
+ }
1923
2007
  };
1924
2008
 
1925
2009
  // ../../lib/contract/src/props/get-disabled-props.ts
@@ -2248,7 +2332,7 @@ function cva2(base, config) {
2248
2332
  // ../../lib/styling/src/static-class-resolver.ts
2249
2333
  var StaticClassResolver = class {
2250
2334
  #baseClass;
2251
- #cache = /* @__PURE__ */ new Map();
2335
+ #cache = new LRUCache(200);
2252
2336
  #resolveTag;
2253
2337
  constructor(baseClass, tagMap) {
2254
2338
  this.#baseClass = Array.isArray(baseClass) ? baseClass.join(" ") : baseClass;
@@ -2262,17 +2346,9 @@ var StaticClassResolver = class {
2262
2346
  resolve(tag, skipTagMap = false) {
2263
2347
  if (typeof tag !== "string" || skipTagMap) return this.#baseClass;
2264
2348
  const cached = this.#cache.get(tag);
2265
- if (cached !== void 0) {
2266
- this.#cache.delete(tag);
2267
- this.#cache.set(tag, cached);
2268
- return cached;
2269
- }
2349
+ if (cached !== void 0) return cached;
2270
2350
  const result = this.#resolveTag(tag);
2271
2351
  this.#cache.set(tag, result);
2272
- if (this.#cache.size > 200) {
2273
- const lru = this.#cache.keys().next().value;
2274
- if (lru !== void 0) this.#cache.delete(lru);
2275
- }
2276
2352
  return result;
2277
2353
  }
2278
2354
  };
@@ -2283,7 +2359,7 @@ var VariantClassResolver = class _VariantClassResolver {
2283
2359
  #recipeMap;
2284
2360
  #variantKeys;
2285
2361
  #precomputedClasses;
2286
- #cache = /* @__PURE__ */ new Map();
2362
+ #cache = new LRUCache(1e3);
2287
2363
  constructor(cvaFn, recipeMap, variantKeys, precomputedClasses) {
2288
2364
  this.#cvaFn = cvaFn ?? null;
2289
2365
  this.#recipeMap = Object.freeze(recipeMap ?? {});
@@ -2298,17 +2374,9 @@ var VariantClassResolver = class _VariantClassResolver {
2298
2374
  if (precomputed !== void 0) return precomputed;
2299
2375
  }
2300
2376
  const cached = this.#cache.get(cacheKey);
2301
- if (cached !== void 0) {
2302
- this.#cache.delete(cacheKey);
2303
- this.#cache.set(cacheKey, cached);
2304
- return cached;
2305
- }
2377
+ if (cached !== void 0) return cached;
2306
2378
  const result = this.#compute(props, recipe);
2307
2379
  this.#cache.set(cacheKey, result);
2308
- if (this.#cache.size > 1e3) {
2309
- const lru = this.#cache.keys().next().value;
2310
- if (lru !== void 0) this.#cache.delete(lru);
2311
- }
2312
2380
  return result;
2313
2381
  }
2314
2382
  #compute(props, recipe) {
@@ -2785,6 +2853,7 @@ function prepareRenderState(runtime, attrs, filterProps) {
2785
2853
  ...asChild !== void 0 && { asChild }
2786
2854
  },
2787
2855
  props: filteredProps,
2856
+ normalizedProps,
2788
2857
  className
2789
2858
  };
2790
2859
  }
@@ -2831,7 +2900,7 @@ function render({
2831
2900
  }) {
2832
2901
  const { vnodes: children, discarded } = normalizeChildren(slots);
2833
2902
  if (process.env.NODE_ENV !== "production") {
2834
- childrenEvaluator?.evaluate(children);
2903
+ childrenEvaluator?.evaluate(children, { tag: state.tag, props: state.normalizedProps });
2835
2904
  runtime.options.htmlChildrenEvaluatorFn?.(state.tag)?.evaluate(children);
2836
2905
  }
2837
2906
  const slotResult = tryRenderAsChild(state, children, discarded, slotValidator);