praxis-kit 5.0.0 → 6.0.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.
- package/dist/{chunk-SKAY22CZ.js → chunk-P5ZJBPAR.js} +81 -20
- package/dist/contract/index.d.ts +27 -1
- package/dist/lit/index.d.ts +27 -1
- package/dist/lit/index.js +92 -26
- package/dist/preact/index.d.ts +27 -1
- package/dist/preact/index.js +81 -20
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +1 -1
- package/dist/react/legacy.d.ts +2 -2
- package/dist/react/legacy.js +1 -1
- package/dist/{react-options-D6rRB2gJ.d.ts → react-options-AitAOrje.d.ts} +27 -1
- package/dist/solid/index.d.ts +27 -1
- package/dist/solid/index.js +72 -17
- package/dist/svelte/Polymorphic.svelte +1 -1
- package/dist/svelte/index.d.ts +32 -2
- package/dist/svelte/index.js +68 -16
- package/dist/tailwind/index.d.ts +89 -54
- package/dist/tailwind/index.js +85 -46
- package/dist/vue/index.d.ts +27 -1
- package/dist/vue/index.js +70 -17
- package/dist/web/index.d.ts +27 -1
- package/dist/web/index.js +92 -31
- package/package.json +4 -4
package/dist/tailwind/index.js
CHANGED
|
@@ -358,6 +358,14 @@ function createClassPipeline(resolved) {
|
|
|
358
358
|
};
|
|
359
359
|
}
|
|
360
360
|
|
|
361
|
+
// ../../lib/pipeline-kit/src/core/compose-pipelines.ts
|
|
362
|
+
function composePipelines(first, second) {
|
|
363
|
+
return (...args) => second(first(...args));
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// ../../lib/tailwind/src/create-tailwind-pipeline.ts
|
|
367
|
+
import { ConsoleReporter, DefaultPolicy, Diagnostics, Severity } from "../_shared/diagnostics.js";
|
|
368
|
+
|
|
361
369
|
// ../../lib/tailwind/src/class-builder.ts
|
|
362
370
|
var ClassBuilder = class {
|
|
363
371
|
build(tokens) {
|
|
@@ -371,6 +379,7 @@ var ClassBuilder = class {
|
|
|
371
379
|
}
|
|
372
380
|
case "utility":
|
|
373
381
|
case "gap":
|
|
382
|
+
case "shared":
|
|
374
383
|
case "conditional": {
|
|
375
384
|
normal.push(token.raw);
|
|
376
385
|
break;
|
|
@@ -444,6 +453,16 @@ var CONDITIONALS = {
|
|
|
444
453
|
"[&.flex": "flex",
|
|
445
454
|
"[&.grid": "grid"
|
|
446
455
|
};
|
|
456
|
+
var SHARED_PREFIXES = [
|
|
457
|
+
/^order/,
|
|
458
|
+
/^justify-(?!items-|self-)/,
|
|
459
|
+
/^content-/,
|
|
460
|
+
/^items-/,
|
|
461
|
+
/^self-/,
|
|
462
|
+
/^place-content-/,
|
|
463
|
+
/^place-items-/,
|
|
464
|
+
/^place-self-/
|
|
465
|
+
];
|
|
447
466
|
var ClassClassifier = class _ClassClassifier {
|
|
448
467
|
static #getBaseUtility(token) {
|
|
449
468
|
let depth = 0;
|
|
@@ -476,23 +495,16 @@ var ClassClassifier = class _ClassClassifier {
|
|
|
476
495
|
}
|
|
477
496
|
);
|
|
478
497
|
if (conditional !== null) return conditional;
|
|
479
|
-
|
|
480
|
-
kind: "gap",
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
kind: "
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
};
|
|
498
|
+
if (base === "gap" || base.startsWith("gap-")) {
|
|
499
|
+
return { kind: "gap", raw: token };
|
|
500
|
+
}
|
|
501
|
+
if (SHARED_PREFIXES.some((rule) => rule.test(base))) {
|
|
502
|
+
return { kind: "shared", raw: token };
|
|
503
|
+
}
|
|
504
|
+
return { kind: "utility", base, raw: token };
|
|
487
505
|
}
|
|
488
506
|
};
|
|
489
507
|
|
|
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
508
|
// ../../lib/tailwind/src/dependency-evaluator.ts
|
|
497
509
|
var DependencyEvaluator = class {
|
|
498
510
|
constructor(rules) {
|
|
@@ -513,7 +525,8 @@ var DependencyEvaluator = class {
|
|
|
513
525
|
(layout) => this.rules[layout].some((rule) => rule.test(token.base)) ? state.family === layout : null
|
|
514
526
|
) ?? true;
|
|
515
527
|
}
|
|
516
|
-
case "gap":
|
|
528
|
+
case "gap":
|
|
529
|
+
case "shared": {
|
|
517
530
|
return state.family !== "none";
|
|
518
531
|
}
|
|
519
532
|
default:
|
|
@@ -522,26 +535,22 @@ var DependencyEvaluator = class {
|
|
|
522
535
|
}
|
|
523
536
|
};
|
|
524
537
|
|
|
525
|
-
// ../../lib/tailwind/src/
|
|
526
|
-
var
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
}
|
|
538
|
+
// ../../lib/tailwind/src/dependency-rules.ts
|
|
539
|
+
var defaultDependencyRules = {
|
|
540
|
+
flex: [/^flex-/, /^grow/, /^shrink/, /^basis-/],
|
|
541
|
+
grid: [
|
|
542
|
+
/^grid-/,
|
|
543
|
+
/^col-/,
|
|
544
|
+
/^row-/,
|
|
545
|
+
/^auto-cols-/,
|
|
546
|
+
/^auto-rows-/,
|
|
547
|
+
// justify-items/-self are no-ops on flex containers per the CSS box
|
|
548
|
+
// alignment spec (flex items ignore them), so treat as grid-only.
|
|
549
|
+
/^justify-items-/,
|
|
550
|
+
/^justify-self-/
|
|
551
|
+
]
|
|
540
552
|
};
|
|
541
553
|
|
|
542
|
-
// ../../lib/tailwind/src/create-tailwind-pipeline.ts
|
|
543
|
-
import { ConsoleReporter, Diagnostics, DefaultPolicy, Severity } from "../_shared/diagnostics.js";
|
|
544
|
-
|
|
545
554
|
// ../../lib/tailwind/src/diagnostics.ts
|
|
546
555
|
import { DiagnosticCategory, DiagnosticCode } from "../_shared/diagnostics.js";
|
|
547
556
|
var TailwindDiagnostics = {
|
|
@@ -568,6 +577,23 @@ var TailwindDiagnostics = {
|
|
|
568
577
|
}
|
|
569
578
|
};
|
|
570
579
|
|
|
580
|
+
// ../../lib/tailwind/src/layout-state.ts
|
|
581
|
+
var LayoutState = class {
|
|
582
|
+
#mode;
|
|
583
|
+
#family;
|
|
584
|
+
constructor(mode) {
|
|
585
|
+
this.#mode = mode;
|
|
586
|
+
this.#family = mode === "none" ? "none" : LAYOUT_FAMILY_MAP[mode];
|
|
587
|
+
Object.freeze(this);
|
|
588
|
+
}
|
|
589
|
+
get mode() {
|
|
590
|
+
return this.#mode;
|
|
591
|
+
}
|
|
592
|
+
get family() {
|
|
593
|
+
return this.#family;
|
|
594
|
+
}
|
|
595
|
+
};
|
|
596
|
+
|
|
571
597
|
// ../../lib/tailwind/src/create-tailwind-pipeline.ts
|
|
572
598
|
var DEV = process.env.NODE_ENV !== "production";
|
|
573
599
|
var devDiagnostics = new Diagnostics(
|
|
@@ -648,23 +674,36 @@ function warnDeadVariants(diagnostics, options, compoundDims, props, recipe, sta
|
|
|
648
674
|
});
|
|
649
675
|
}
|
|
650
676
|
function createTailwindPipeline(options, diagnostics) {
|
|
651
|
-
const
|
|
677
|
+
const innerPipeline = createClassPipeline(options);
|
|
652
678
|
const compoundDims = compoundDimensions(getCompoundVariants(options));
|
|
679
|
+
const resolveLayoutContext = (tag, props, className, recipe) => {
|
|
680
|
+
const mode = resolveLayout(devDiagnostics, props);
|
|
681
|
+
const resolvedClasses = innerPipeline(tag, props, className, recipe);
|
|
682
|
+
const tokens = classifyTokens(resolvedClasses);
|
|
683
|
+
const state = new LayoutState(mode);
|
|
684
|
+
const filtered = tokens.filter((token) => evaluator.evaluate(token, state));
|
|
685
|
+
return { mode, state, filtered, tokens, props, recipe };
|
|
686
|
+
};
|
|
687
|
+
const buildClassString = (ctx) => {
|
|
688
|
+
const built = builder.build(ctx.filtered);
|
|
689
|
+
if (ctx.mode === "none") return built;
|
|
690
|
+
return ctx.filtered.some((t) => t.kind === "layout" && t.value === ctx.mode) ? built : cn(ctx.mode, built);
|
|
691
|
+
};
|
|
692
|
+
const emitDiagnosticsFromContext = (ctx) => {
|
|
693
|
+
if (!DEV) return;
|
|
694
|
+
warnReservedLayoutLiterals(diagnostics, ctx.tokens);
|
|
695
|
+
warnDeadVariants(diagnostics, options, compoundDims, ctx.props, ctx.recipe, ctx.state);
|
|
696
|
+
};
|
|
697
|
+
const combined = (ctx) => {
|
|
698
|
+
const built = buildClassString(ctx);
|
|
699
|
+
emitDiagnosticsFromContext(ctx);
|
|
700
|
+
return built;
|
|
701
|
+
};
|
|
702
|
+
const mainPipeline = composePipelines(resolveLayoutContext, combined);
|
|
653
703
|
return {
|
|
654
704
|
ownedKeys: LAYOUT_OWNED_KEYS,
|
|
655
705
|
pipeline(tag, props, className, recipe) {
|
|
656
|
-
|
|
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);
|
|
706
|
+
return mainPipeline(tag, props, className, recipe);
|
|
668
707
|
}
|
|
669
708
|
};
|
|
670
709
|
}
|
package/dist/vue/index.d.ts
CHANGED
|
@@ -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
|
-
|
|
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)}`);
|
|
@@ -1868,10 +1881,22 @@ var RuleValidator = class _RuleValidator extends InvariantBase {
|
|
|
1868
1881
|
|
|
1869
1882
|
// ../../lib/contract/src/children/children-evaluator.ts
|
|
1870
1883
|
var isTextLike = (child) => isString(child) || isNumber(child);
|
|
1884
|
+
function checkPositionCardinalityInvariant(rules, context) {
|
|
1885
|
+
iterate.forEach(rules, (rule) => {
|
|
1886
|
+
const { name, position, cardinality } = rule;
|
|
1887
|
+
if ((position === "first" || position === "last") && (cardinality.kind === "unbounded" || cardinality.max > 1)) {
|
|
1888
|
+
throw new RangeError(
|
|
1889
|
+
`ChildrenEvaluator [${context}]: rule "${name}" sets position="${position}" with an unbound or >1 max. position="first|last" implies max=1.`
|
|
1890
|
+
);
|
|
1891
|
+
}
|
|
1892
|
+
});
|
|
1893
|
+
}
|
|
1871
1894
|
var ChildrenEvaluator = class extends InvariantBase {
|
|
1872
1895
|
#context;
|
|
1873
|
-
|
|
1874
|
-
#
|
|
1896
|
+
/** Rules with a static cardinality — normalized once, reused on every evaluate() call. */
|
|
1897
|
+
#staticRules;
|
|
1898
|
+
/** Rules whose cardinality is `dynamic(...)` — re-resolved against a ChildRuleContext per call. */
|
|
1899
|
+
#dynamicRuleInputs;
|
|
1875
1900
|
#matcher;
|
|
1876
1901
|
#ruleValidator;
|
|
1877
1902
|
#exclusiveChildren;
|
|
@@ -1879,29 +1904,39 @@ var ChildrenEvaluator = class extends InvariantBase {
|
|
|
1879
1904
|
constructor(rules, diagnostics, context = "Component", options = {}) {
|
|
1880
1905
|
super(diagnostics);
|
|
1881
1906
|
this.#context = context;
|
|
1882
|
-
this.#rules = rules.map((r) => normalizeChildRule(r));
|
|
1883
|
-
this.#ruleNames = this.#rules.map((r) => r.name);
|
|
1884
1907
|
this.#exclusiveChildren = options.exclusiveChildren ?? false;
|
|
1885
1908
|
this.#allowText = options.allowText ?? true;
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
);
|
|
1892
|
-
}
|
|
1909
|
+
const staticRuleInputs = [];
|
|
1910
|
+
const dynamicRuleInputs = [];
|
|
1911
|
+
iterate.forEach(rules, (rule) => {
|
|
1912
|
+
if (isDynamicRule(rule.cardinality)) dynamicRuleInputs.push(rule);
|
|
1913
|
+
else staticRuleInputs.push(rule);
|
|
1893
1914
|
});
|
|
1894
|
-
this.#
|
|
1915
|
+
this.#dynamicRuleInputs = dynamicRuleInputs;
|
|
1916
|
+
this.#staticRules = staticRuleInputs.map(
|
|
1917
|
+
(r) => normalizeChildRule(r)
|
|
1918
|
+
);
|
|
1895
1919
|
this.#ruleValidator = new RuleValidator(context, diagnostics);
|
|
1920
|
+
if (this.#dynamicRuleInputs.length === 0) {
|
|
1921
|
+
checkPositionCardinalityInvariant(this.#staticRules, context);
|
|
1922
|
+
this.#matcher = new RuleMatcher(this.#staticRules);
|
|
1923
|
+
} else {
|
|
1924
|
+
this.#matcher = void 0;
|
|
1925
|
+
}
|
|
1896
1926
|
}
|
|
1897
|
-
|
|
1927
|
+
/**
|
|
1928
|
+
* @param context Required when any rule has a `dynamic(...)` cardinality —
|
|
1929
|
+
* supplies the resolved tag/props those rules are evaluated against.
|
|
1930
|
+
*/
|
|
1931
|
+
evaluate(children, context) {
|
|
1898
1932
|
if (!this.active) return;
|
|
1933
|
+
const { rules, matcher } = this.#resolveRules(context);
|
|
1899
1934
|
const {
|
|
1900
1935
|
matrix,
|
|
1901
1936
|
unexpectedIndices: rawUnexpectedIndices,
|
|
1902
1937
|
ambiguousIndices
|
|
1903
|
-
} =
|
|
1904
|
-
this.#ruleValidator.validate(
|
|
1938
|
+
} = matcher.match(children);
|
|
1939
|
+
this.#ruleValidator.validate(rules, matrix, children.length);
|
|
1905
1940
|
const unexpectedIndices = new Set(
|
|
1906
1941
|
[...rawUnexpectedIndices].filter(
|
|
1907
1942
|
(ci) => isTextLike(children[ci]) ? this.#allowText === false : this.#exclusiveChildren
|
|
@@ -1915,11 +1950,28 @@ var ChildrenEvaluator = class extends InvariantBase {
|
|
|
1915
1950
|
this.violate(ContractDiagnostics.unexpectedChild(typeName, ci, this.#context));
|
|
1916
1951
|
} else {
|
|
1917
1952
|
const matches = matrix.childToRules.forward.get(ci);
|
|
1918
|
-
const names = [...matches].map((ri) =>
|
|
1953
|
+
const names = [...matches].map((ri) => rules[ri]?.name ?? `#${ri}`);
|
|
1919
1954
|
this.violate(ContractDiagnostics.ambiguousChild(typeName, ci, names, this.#context));
|
|
1920
1955
|
}
|
|
1921
1956
|
});
|
|
1922
1957
|
}
|
|
1958
|
+
#resolveRules(context) {
|
|
1959
|
+
if (this.#dynamicRuleInputs.length === 0) {
|
|
1960
|
+
return { rules: this.#staticRules, matcher: this.#matcher };
|
|
1961
|
+
}
|
|
1962
|
+
if (context === void 0) {
|
|
1963
|
+
throw new RangeError(
|
|
1964
|
+
`ChildrenEvaluator [${this.#context}]: rule(s) have a dynamic(...) cardinality \u2014 evaluate() requires a context argument to resolve them.`
|
|
1965
|
+
);
|
|
1966
|
+
}
|
|
1967
|
+
const resolvedDynamicRules = this.#dynamicRuleInputs.map((r) => {
|
|
1968
|
+
const cardinality = resolveRule(r.cardinality, context);
|
|
1969
|
+
return normalizeChildRule({ ...r, cardinality });
|
|
1970
|
+
});
|
|
1971
|
+
checkPositionCardinalityInvariant(resolvedDynamicRules, this.#context);
|
|
1972
|
+
const rules = [...this.#staticRules, ...resolvedDynamicRules];
|
|
1973
|
+
return { rules, matcher: new RuleMatcher(rules) };
|
|
1974
|
+
}
|
|
1923
1975
|
};
|
|
1924
1976
|
|
|
1925
1977
|
// ../../lib/contract/src/props/get-disabled-props.ts
|
|
@@ -2785,6 +2837,7 @@ function prepareRenderState(runtime, attrs, filterProps) {
|
|
|
2785
2837
|
...asChild !== void 0 && { asChild }
|
|
2786
2838
|
},
|
|
2787
2839
|
props: filteredProps,
|
|
2840
|
+
normalizedProps,
|
|
2788
2841
|
className
|
|
2789
2842
|
};
|
|
2790
2843
|
}
|
|
@@ -2831,7 +2884,7 @@ function render({
|
|
|
2831
2884
|
}) {
|
|
2832
2885
|
const { vnodes: children, discarded } = normalizeChildren(slots);
|
|
2833
2886
|
if (process.env.NODE_ENV !== "production") {
|
|
2834
|
-
childrenEvaluator?.evaluate(children);
|
|
2887
|
+
childrenEvaluator?.evaluate(children, { tag: state.tag, props: state.normalizedProps });
|
|
2835
2888
|
runtime.options.htmlChildrenEvaluatorFn?.(state.tag)?.evaluate(children);
|
|
2836
2889
|
}
|
|
2837
2890
|
const slotResult = tryRenderAsChild(state, children, discarded, slotValidator);
|
package/dist/web/index.d.ts
CHANGED
|
@@ -29,6 +29,26 @@ type MinMax = {
|
|
|
29
29
|
};
|
|
30
30
|
type CardinalityInput = Partial<MinMax>;
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Resolved per-instance state available to a dynamic (`dynamic(...)`) child
|
|
34
|
+
* rule field — the same tag/props every adapter already computes before
|
|
35
|
+
* evaluating children, exposed so a rule can vary by them (e.g. cardinality
|
|
36
|
+
* that depends on the resolved `as` tag).
|
|
37
|
+
*/
|
|
38
|
+
type ChildRuleContext = {
|
|
39
|
+
readonly tag: unknown;
|
|
40
|
+
readonly props: Readonly<AnyRecord>;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
declare const RULE_BRAND: unique symbol;
|
|
44
|
+
|
|
45
|
+
type DynamicRule<T, C = unknown> = {
|
|
46
|
+
readonly [RULE_BRAND]: true;
|
|
47
|
+
resolve(context: C): T;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
type Rule<T, C = unknown> = T | DynamicRule<T, C>;
|
|
51
|
+
|
|
32
52
|
type ChildRuleMatch<T, U extends T = T> = (child: T) => child is U;
|
|
33
53
|
|
|
34
54
|
type ChildRulePosition = 'first' | 'last' | 'any';
|
|
@@ -36,7 +56,13 @@ type ChildRulePosition = 'first' | 'last' | 'any';
|
|
|
36
56
|
type ChildRuleInput<T = unknown, U extends T = T> = {
|
|
37
57
|
name: string;
|
|
38
58
|
match: ChildRuleMatch<T, U>;
|
|
39
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Either a static cardinality, or `dynamic((ctx) => ...)` to derive it from
|
|
61
|
+
* the resolved tag/props (e.g. a different max depending on `as`). `match`
|
|
62
|
+
* stays static-only — it's already a function, so a dynamic wrapper would
|
|
63
|
+
* be indistinguishable from the predicate itself without one.
|
|
64
|
+
*/
|
|
65
|
+
cardinality?: Rule<CardinalityInput, ChildRuleContext>;
|
|
40
66
|
position?: ChildRulePosition;
|
|
41
67
|
/**
|
|
42
68
|
* Optional component-type reference for O(1) dispatch index.
|
package/dist/web/index.js
CHANGED
|
@@ -313,6 +313,19 @@ function makeResolveTag(defaultTag) {
|
|
|
313
313
|
};
|
|
314
314
|
}
|
|
315
315
|
|
|
316
|
+
// ../../lib/primitive/src/rule/rule-brand.ts
|
|
317
|
+
var RULE_BRAND = /* @__PURE__ */ Symbol("praxis-kit/dynamic-rule");
|
|
318
|
+
|
|
319
|
+
// ../../lib/primitive/src/rule/is-dynamic-rule.ts
|
|
320
|
+
function isDynamicRule(rule) {
|
|
321
|
+
return isObject(rule, true) && rule[RULE_BRAND] === true;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// ../../lib/primitive/src/rule/resolve-rule.ts
|
|
325
|
+
function resolveRule(rule, context) {
|
|
326
|
+
return isDynamicRule(rule) ? rule.resolve(context) : rule;
|
|
327
|
+
}
|
|
328
|
+
|
|
316
329
|
// ../../lib/primitive/src/utils/assert-never.ts
|
|
317
330
|
function assertNever(value) {
|
|
318
331
|
throw new Error(`Unexpected value: ${String(value)}`);
|
|
@@ -1715,10 +1728,22 @@ var RuleValidator = class _RuleValidator extends InvariantBase {
|
|
|
1715
1728
|
|
|
1716
1729
|
// ../../lib/contract/src/children/children-evaluator.ts
|
|
1717
1730
|
var isTextLike = (child) => isString(child) || isNumber(child);
|
|
1731
|
+
function checkPositionCardinalityInvariant(rules, context) {
|
|
1732
|
+
iterate.forEach(rules, (rule) => {
|
|
1733
|
+
const { name, position, cardinality } = rule;
|
|
1734
|
+
if ((position === "first" || position === "last") && (cardinality.kind === "unbounded" || cardinality.max > 1)) {
|
|
1735
|
+
throw new RangeError(
|
|
1736
|
+
`ChildrenEvaluator [${context}]: rule "${name}" sets position="${position}" with an unbound or >1 max. position="first|last" implies max=1.`
|
|
1737
|
+
);
|
|
1738
|
+
}
|
|
1739
|
+
});
|
|
1740
|
+
}
|
|
1718
1741
|
var ChildrenEvaluator = class extends InvariantBase {
|
|
1719
1742
|
#context;
|
|
1720
|
-
|
|
1721
|
-
#
|
|
1743
|
+
/** Rules with a static cardinality — normalized once, reused on every evaluate() call. */
|
|
1744
|
+
#staticRules;
|
|
1745
|
+
/** Rules whose cardinality is `dynamic(...)` — re-resolved against a ChildRuleContext per call. */
|
|
1746
|
+
#dynamicRuleInputs;
|
|
1722
1747
|
#matcher;
|
|
1723
1748
|
#ruleValidator;
|
|
1724
1749
|
#exclusiveChildren;
|
|
@@ -1726,29 +1751,39 @@ var ChildrenEvaluator = class extends InvariantBase {
|
|
|
1726
1751
|
constructor(rules, diagnostics, context = "Component", options = {}) {
|
|
1727
1752
|
super(diagnostics);
|
|
1728
1753
|
this.#context = context;
|
|
1729
|
-
this.#rules = rules.map((r) => normalizeChildRule(r));
|
|
1730
|
-
this.#ruleNames = this.#rules.map((r) => r.name);
|
|
1731
1754
|
this.#exclusiveChildren = options.exclusiveChildren ?? false;
|
|
1732
1755
|
this.#allowText = options.allowText ?? true;
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
);
|
|
1739
|
-
}
|
|
1756
|
+
const staticRuleInputs = [];
|
|
1757
|
+
const dynamicRuleInputs = [];
|
|
1758
|
+
iterate.forEach(rules, (rule) => {
|
|
1759
|
+
if (isDynamicRule(rule.cardinality)) dynamicRuleInputs.push(rule);
|
|
1760
|
+
else staticRuleInputs.push(rule);
|
|
1740
1761
|
});
|
|
1741
|
-
this.#
|
|
1762
|
+
this.#dynamicRuleInputs = dynamicRuleInputs;
|
|
1763
|
+
this.#staticRules = staticRuleInputs.map(
|
|
1764
|
+
(r) => normalizeChildRule(r)
|
|
1765
|
+
);
|
|
1742
1766
|
this.#ruleValidator = new RuleValidator(context, diagnostics);
|
|
1767
|
+
if (this.#dynamicRuleInputs.length === 0) {
|
|
1768
|
+
checkPositionCardinalityInvariant(this.#staticRules, context);
|
|
1769
|
+
this.#matcher = new RuleMatcher(this.#staticRules);
|
|
1770
|
+
} else {
|
|
1771
|
+
this.#matcher = void 0;
|
|
1772
|
+
}
|
|
1743
1773
|
}
|
|
1744
|
-
|
|
1774
|
+
/**
|
|
1775
|
+
* @param context Required when any rule has a `dynamic(...)` cardinality —
|
|
1776
|
+
* supplies the resolved tag/props those rules are evaluated against.
|
|
1777
|
+
*/
|
|
1778
|
+
evaluate(children, context) {
|
|
1745
1779
|
if (!this.active) return;
|
|
1780
|
+
const { rules, matcher } = this.#resolveRules(context);
|
|
1746
1781
|
const {
|
|
1747
1782
|
matrix,
|
|
1748
1783
|
unexpectedIndices: rawUnexpectedIndices,
|
|
1749
1784
|
ambiguousIndices
|
|
1750
|
-
} =
|
|
1751
|
-
this.#ruleValidator.validate(
|
|
1785
|
+
} = matcher.match(children);
|
|
1786
|
+
this.#ruleValidator.validate(rules, matrix, children.length);
|
|
1752
1787
|
const unexpectedIndices = new Set(
|
|
1753
1788
|
[...rawUnexpectedIndices].filter(
|
|
1754
1789
|
(ci) => isTextLike(children[ci]) ? this.#allowText === false : this.#exclusiveChildren
|
|
@@ -1762,11 +1797,28 @@ var ChildrenEvaluator = class extends InvariantBase {
|
|
|
1762
1797
|
this.violate(ContractDiagnostics.unexpectedChild(typeName, ci, this.#context));
|
|
1763
1798
|
} else {
|
|
1764
1799
|
const matches = matrix.childToRules.forward.get(ci);
|
|
1765
|
-
const names = [...matches].map((ri) =>
|
|
1800
|
+
const names = [...matches].map((ri) => rules[ri]?.name ?? `#${ri}`);
|
|
1766
1801
|
this.violate(ContractDiagnostics.ambiguousChild(typeName, ci, names, this.#context));
|
|
1767
1802
|
}
|
|
1768
1803
|
});
|
|
1769
1804
|
}
|
|
1805
|
+
#resolveRules(context) {
|
|
1806
|
+
if (this.#dynamicRuleInputs.length === 0) {
|
|
1807
|
+
return { rules: this.#staticRules, matcher: this.#matcher };
|
|
1808
|
+
}
|
|
1809
|
+
if (context === void 0) {
|
|
1810
|
+
throw new RangeError(
|
|
1811
|
+
`ChildrenEvaluator [${this.#context}]: rule(s) have a dynamic(...) cardinality \u2014 evaluate() requires a context argument to resolve them.`
|
|
1812
|
+
);
|
|
1813
|
+
}
|
|
1814
|
+
const resolvedDynamicRules = this.#dynamicRuleInputs.map((r) => {
|
|
1815
|
+
const cardinality = resolveRule(r.cardinality, context);
|
|
1816
|
+
return normalizeChildRule({ ...r, cardinality });
|
|
1817
|
+
});
|
|
1818
|
+
checkPositionCardinalityInvariant(resolvedDynamicRules, this.#context);
|
|
1819
|
+
const rules = [...this.#staticRules, ...resolvedDynamicRules];
|
|
1820
|
+
return { rules, matcher: new RuleMatcher(rules) };
|
|
1821
|
+
}
|
|
1770
1822
|
};
|
|
1771
1823
|
|
|
1772
1824
|
// ../../lib/contract/src/props/get-disabled-props.ts
|
|
@@ -2558,13 +2610,10 @@ function toLooseBundle(bundle) {
|
|
|
2558
2610
|
}
|
|
2559
2611
|
return bundle;
|
|
2560
2612
|
}
|
|
2561
|
-
function
|
|
2562
|
-
const { as, className, recipe, ...rest } = props;
|
|
2563
|
-
const { options,
|
|
2613
|
+
function resolveTagAndNormalizedProps(bundle, props) {
|
|
2614
|
+
const { as, className: _className, recipe: _recipe, ...rest } = props;
|
|
2615
|
+
const { options, resolveProps, resolveTag: resolveTag2 } = bundle.runtime;
|
|
2564
2616
|
const tag = resolveTag2(as);
|
|
2565
|
-
if (options.allowedAs !== void 0) {
|
|
2566
|
-
enforceAllowedAs(tag, options.allowedAs, options.diagnostics, options.displayName);
|
|
2567
|
-
}
|
|
2568
2617
|
const mergedProps = resolveProps(rest);
|
|
2569
2618
|
const normalizedProps = typeof options.normalizeFn === "function" ? options.normalizeFn(mergedProps) : mergedProps;
|
|
2570
2619
|
const htmlNormalizers = options.htmlPropNormalizersFn?.(tag);
|
|
@@ -2574,6 +2623,15 @@ function resolveHostState(bundle, props) {
|
|
|
2574
2623
|
Object.assign(finalProps, normalize(finalProps));
|
|
2575
2624
|
}
|
|
2576
2625
|
}
|
|
2626
|
+
return { tag, normalizedProps: finalProps };
|
|
2627
|
+
}
|
|
2628
|
+
function resolveHostState(bundle, props) {
|
|
2629
|
+
const { className, recipe } = props;
|
|
2630
|
+
const { options, resolveAria, resolveClasses } = bundle.runtime;
|
|
2631
|
+
const { tag, normalizedProps: finalProps } = resolveTagAndNormalizedProps(bundle, props);
|
|
2632
|
+
if (options.allowedAs !== void 0) {
|
|
2633
|
+
enforceAllowedAs(tag, options.allowedAs, options.diagnostics, options.displayName);
|
|
2634
|
+
}
|
|
2577
2635
|
const resolvedClass = resolveClasses(
|
|
2578
2636
|
tag,
|
|
2579
2637
|
finalProps,
|
|
@@ -2582,7 +2640,7 @@ function resolveHostState(bundle, props) {
|
|
|
2582
2640
|
);
|
|
2583
2641
|
const ariaResult = resolveAria(tag, finalProps);
|
|
2584
2642
|
const attributes = applyFilter(ariaResult.props, bundle.filterProps, options.variantKeys);
|
|
2585
|
-
return { className: resolvedClass, attributes };
|
|
2643
|
+
return { className: resolvedClass, attributes, tag, normalizedProps: finalProps };
|
|
2586
2644
|
}
|
|
2587
2645
|
function diffAndApplyAttributes(host, state, prevPipelineAttrs, incomingProps) {
|
|
2588
2646
|
const hasOwn2 = Object.hasOwn;
|
|
@@ -2689,14 +2747,8 @@ function createContractComponent(options) {
|
|
|
2689
2747
|
const self = this._self;
|
|
2690
2748
|
const {
|
|
2691
2749
|
childrenEvaluator,
|
|
2692
|
-
runtime: { options: options2
|
|
2750
|
+
runtime: { options: options2 }
|
|
2693
2751
|
} = bundle;
|
|
2694
|
-
const tag = resolveTag2(self.as);
|
|
2695
|
-
const children = Array.from(this.childNodes);
|
|
2696
|
-
if (childrenEvaluator) {
|
|
2697
|
-
childrenEvaluator.evaluate(children);
|
|
2698
|
-
}
|
|
2699
|
-
options2.htmlChildrenEvaluatorFn?.(tag)?.evaluate(children);
|
|
2700
2752
|
const observedSet = new Set(
|
|
2701
2753
|
this.constructor.observedAttributes ?? []
|
|
2702
2754
|
);
|
|
@@ -2712,7 +2764,16 @@ function createContractComponent(options) {
|
|
|
2712
2764
|
const val = self[key] ?? this.getAttribute(key);
|
|
2713
2765
|
if (val != null) props[key] = val;
|
|
2714
2766
|
}
|
|
2715
|
-
|
|
2767
|
+
const hostState = resolveHostState(looseBundle, props);
|
|
2768
|
+
const children = Array.from(this.childNodes);
|
|
2769
|
+
if (childrenEvaluator) {
|
|
2770
|
+
childrenEvaluator.evaluate(children, {
|
|
2771
|
+
tag: hostState.tag,
|
|
2772
|
+
props: hostState.normalizedProps
|
|
2773
|
+
});
|
|
2774
|
+
}
|
|
2775
|
+
options2.htmlChildrenEvaluatorFn?.(hostState.tag)?.evaluate(children);
|
|
2776
|
+
diffAndApplyAttributes(this, hostState, this._pipelineAttrs, props);
|
|
2716
2777
|
}
|
|
2717
2778
|
}
|
|
2718
2779
|
if (options.name) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "praxis-kit",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./react": {
|
|
@@ -184,10 +184,10 @@
|
|
|
184
184
|
"vue": "^3.5.38",
|
|
185
185
|
"@praxis-kit/core": "0.0.0",
|
|
186
186
|
"@praxis-kit/adapter-utils": "0.0.0",
|
|
187
|
-
"@praxis-kit/pipeline": "0.0.0",
|
|
188
|
-
"@praxis-kit/primitive": "0.0.0",
|
|
189
187
|
"@praxis-kit/diagnostics": "0.0.0",
|
|
190
|
-
"@praxis-kit/
|
|
188
|
+
"@praxis-kit/pipeline": "0.0.0",
|
|
189
|
+
"@praxis-kit/vite-plugin": "0.0.0",
|
|
190
|
+
"@praxis-kit/primitive": "0.0.0"
|
|
191
191
|
},
|
|
192
192
|
"publishConfig": {
|
|
193
193
|
"access": "public"
|