praxis-kit 4.1.3 → 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/_shared/diagnostics.d.ts +10 -1
- package/dist/_shared/diagnostics.js +12 -0
- package/dist/{chunk-R2RKHZNX.js → chunk-P5ZJBPAR.js} +147 -52
- package/dist/codemod/index.js +39 -22
- package/dist/contract/index.d.ts +45 -3
- package/dist/eslint/index.js +16 -16
- package/dist/lit/index.d.ts +45 -3
- package/dist/lit/index.js +155 -58
- package/dist/preact/index.d.ts +45 -3
- package/dist/preact/index.js +146 -52
- 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-XrRof248.d.ts → react-options-AitAOrje.d.ts} +45 -3
- package/dist/solid/index.d.ts +45 -3
- package/dist/solid/index.js +180 -80
- package/dist/svelte/Polymorphic.svelte +146 -0
- package/dist/svelte/index.d.ts +66 -5
- package/dist/svelte/index.js +134 -48
- package/dist/tailwind/index.d.ts +89 -54
- package/dist/tailwind/index.js +85 -46
- package/dist/vite-plugin/index.d.ts +31 -0
- package/dist/vite-plugin/index.js +32 -15
- package/dist/vue/index.d.ts +45 -3
- package/dist/vue/index.js +136 -49
- package/dist/web/index.d.ts +45 -3
- package/dist/web/index.js +155 -63
- package/package.json +61 -8
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)}`);
|
|
@@ -1867,32 +1880,68 @@ var RuleValidator = class _RuleValidator extends InvariantBase {
|
|
|
1867
1880
|
};
|
|
1868
1881
|
|
|
1869
1882
|
// ../../lib/contract/src/children/children-evaluator.ts
|
|
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
|
+
}
|
|
1870
1894
|
var ChildrenEvaluator = class extends InvariantBase {
|
|
1871
1895
|
#context;
|
|
1872
|
-
|
|
1873
|
-
#
|
|
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;
|
|
1874
1900
|
#matcher;
|
|
1875
1901
|
#ruleValidator;
|
|
1876
|
-
|
|
1902
|
+
#exclusiveChildren;
|
|
1903
|
+
#allowText;
|
|
1904
|
+
constructor(rules, diagnostics, context = "Component", options = {}) {
|
|
1877
1905
|
super(diagnostics);
|
|
1878
1906
|
this.#context = context;
|
|
1879
|
-
this.#
|
|
1880
|
-
this.#
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
);
|
|
1887
|
-
}
|
|
1907
|
+
this.#exclusiveChildren = options.exclusiveChildren ?? false;
|
|
1908
|
+
this.#allowText = options.allowText ?? true;
|
|
1909
|
+
const staticRuleInputs = [];
|
|
1910
|
+
const dynamicRuleInputs = [];
|
|
1911
|
+
iterate.forEach(rules, (rule) => {
|
|
1912
|
+
if (isDynamicRule(rule.cardinality)) dynamicRuleInputs.push(rule);
|
|
1913
|
+
else staticRuleInputs.push(rule);
|
|
1888
1914
|
});
|
|
1889
|
-
this.#
|
|
1915
|
+
this.#dynamicRuleInputs = dynamicRuleInputs;
|
|
1916
|
+
this.#staticRules = staticRuleInputs.map(
|
|
1917
|
+
(r) => normalizeChildRule(r)
|
|
1918
|
+
);
|
|
1890
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
|
+
}
|
|
1891
1926
|
}
|
|
1892
|
-
|
|
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) {
|
|
1893
1932
|
if (!this.active) return;
|
|
1894
|
-
const {
|
|
1895
|
-
|
|
1933
|
+
const { rules, matcher } = this.#resolveRules(context);
|
|
1934
|
+
const {
|
|
1935
|
+
matrix,
|
|
1936
|
+
unexpectedIndices: rawUnexpectedIndices,
|
|
1937
|
+
ambiguousIndices
|
|
1938
|
+
} = matcher.match(children);
|
|
1939
|
+
this.#ruleValidator.validate(rules, matrix, children.length);
|
|
1940
|
+
const unexpectedIndices = new Set(
|
|
1941
|
+
[...rawUnexpectedIndices].filter(
|
|
1942
|
+
(ci) => isTextLike(children[ci]) ? this.#allowText === false : this.#exclusiveChildren
|
|
1943
|
+
)
|
|
1944
|
+
);
|
|
1896
1945
|
if (unexpectedIndices.size === 0 && ambiguousIndices.size === 0) return;
|
|
1897
1946
|
const violating = [...unexpectedIndices, ...ambiguousIndices].sort((a, b) => a - b);
|
|
1898
1947
|
iterate.forEach(violating, (ci) => {
|
|
@@ -1901,11 +1950,28 @@ var ChildrenEvaluator = class extends InvariantBase {
|
|
|
1901
1950
|
this.violate(ContractDiagnostics.unexpectedChild(typeName, ci, this.#context));
|
|
1902
1951
|
} else {
|
|
1903
1952
|
const matches = matrix.childToRules.forward.get(ci);
|
|
1904
|
-
const names = [...matches].map((ri) =>
|
|
1953
|
+
const names = [...matches].map((ri) => rules[ri]?.name ?? `#${ri}`);
|
|
1905
1954
|
this.violate(ContractDiagnostics.ambiguousChild(typeName, ci, names, this.#context));
|
|
1906
1955
|
}
|
|
1907
1956
|
});
|
|
1908
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
|
+
}
|
|
1909
1975
|
};
|
|
1910
1976
|
|
|
1911
1977
|
// ../../lib/contract/src/props/get-disabled-props.ts
|
|
@@ -2014,8 +2080,11 @@ function metadata(name = "metadata") {
|
|
|
2014
2080
|
function firstOptional(name, tag) {
|
|
2015
2081
|
return { name, match: isTag(tag), cardinality: { max: 1 }, position: "first" };
|
|
2016
2082
|
}
|
|
2017
|
-
function contract(children) {
|
|
2018
|
-
return { diagnostics: warnDiagnostics, children };
|
|
2083
|
+
function contract(children, options) {
|
|
2084
|
+
return { diagnostics: warnDiagnostics, children, ...options };
|
|
2085
|
+
}
|
|
2086
|
+
function closedContract(children) {
|
|
2087
|
+
return contract(children, { exclusiveChildren: true });
|
|
2019
2088
|
}
|
|
2020
2089
|
function ariaContract(aria) {
|
|
2021
2090
|
return { diagnostics: warnDiagnostics, aria };
|
|
@@ -2041,8 +2110,10 @@ var VOID_TAGS = [
|
|
|
2041
2110
|
];
|
|
2042
2111
|
var TEXT_ONLY_TAGS = ["option", "script", "style", "textarea", "title"];
|
|
2043
2112
|
var LANDMARK_TAGS = ["article", "aside", "footer", "header", "main", "nav"];
|
|
2044
|
-
var listContract =
|
|
2045
|
-
|
|
2113
|
+
var listContract = closedContract([
|
|
2114
|
+
{ name: "list-item", match: isTag("li", ...METADATA_TAGS) }
|
|
2115
|
+
]);
|
|
2116
|
+
var tableContract = closedContract([
|
|
2046
2117
|
firstOptional("caption", "caption"),
|
|
2047
2118
|
{ name: "colgroup", match: isTag("colgroup") },
|
|
2048
2119
|
{ name: "thead", match: isTag("thead"), cardinality: { max: 1 } },
|
|
@@ -2050,29 +2121,31 @@ var tableContract = contract([
|
|
|
2050
2121
|
{ name: "tfoot", match: isTag("tfoot"), cardinality: { max: 1 } },
|
|
2051
2122
|
{ name: "table-row", match: isTag("tr", ...METADATA_TAGS) }
|
|
2052
2123
|
]);
|
|
2053
|
-
var tableBodyContract =
|
|
2124
|
+
var tableBodyContract = closedContract([
|
|
2054
2125
|
{ name: "table-row", match: isTag("tr", ...METADATA_TAGS) }
|
|
2055
2126
|
]);
|
|
2056
|
-
var tableRowContract =
|
|
2127
|
+
var tableRowContract = closedContract([
|
|
2057
2128
|
{ name: "table-cell", match: isTag("td", "th", ...METADATA_TAGS) }
|
|
2058
2129
|
]);
|
|
2059
|
-
var colgroupContract =
|
|
2060
|
-
|
|
2130
|
+
var colgroupContract = closedContract([
|
|
2131
|
+
{ name: "column", match: isTag("col", "template") }
|
|
2132
|
+
]);
|
|
2133
|
+
var dlContract = closedContract([
|
|
2061
2134
|
{ name: "term", match: isTag("dt") },
|
|
2062
2135
|
{ name: "description", match: isTag("dd") },
|
|
2063
2136
|
{ name: "group", match: isTag("div") },
|
|
2064
2137
|
metadata()
|
|
2065
2138
|
]);
|
|
2066
|
-
var selectContract =
|
|
2139
|
+
var selectContract = closedContract([
|
|
2067
2140
|
{ name: "option", match: isTag("option", "optgroup", "hr", ...METADATA_TAGS) }
|
|
2068
2141
|
]);
|
|
2069
|
-
var optgroupContract =
|
|
2142
|
+
var optgroupContract = closedContract([
|
|
2070
2143
|
{ name: "option", match: isTag("option", ...METADATA_TAGS) }
|
|
2071
2144
|
]);
|
|
2072
|
-
var datalistContract =
|
|
2145
|
+
var datalistContract = closedContract([
|
|
2073
2146
|
{ name: "option", match: isTag("option", ...METADATA_TAGS) }
|
|
2074
2147
|
]);
|
|
2075
|
-
var pictureContract =
|
|
2148
|
+
var pictureContract = closedContract([
|
|
2076
2149
|
{ name: "source", match: isTag("source", ...METADATA_TAGS) },
|
|
2077
2150
|
{ name: "image", match: isTag("img"), cardinality: { min: 1, max: 1 }, position: "last" }
|
|
2078
2151
|
]);
|
|
@@ -2088,23 +2161,18 @@ var mediaContract = contract([
|
|
|
2088
2161
|
metadata(),
|
|
2089
2162
|
{ name: "content", match: isOpenContent("source", "track", ...METADATA_TAGS) }
|
|
2090
2163
|
]);
|
|
2091
|
-
var headContract =
|
|
2164
|
+
var headContract = closedContract([
|
|
2092
2165
|
{
|
|
2093
2166
|
name: "metadata",
|
|
2094
2167
|
match: isTag("base", "link", "meta", "noscript", "script", "style", "template", "title")
|
|
2095
2168
|
}
|
|
2096
2169
|
]);
|
|
2097
|
-
var htmlContract =
|
|
2170
|
+
var htmlContract = closedContract([
|
|
2098
2171
|
{ name: "head", match: isTag("head"), cardinality: { min: 1, max: 1 }, position: "first" },
|
|
2099
2172
|
{ name: "body", match: isTag("body"), cardinality: { min: 1, max: 1 } }
|
|
2100
2173
|
]);
|
|
2101
|
-
var voidContract = contract([]);
|
|
2102
|
-
var textOnlyContract = contract([
|
|
2103
|
-
{
|
|
2104
|
-
name: "text",
|
|
2105
|
-
match: (child) => isString(child) || isNumber(child)
|
|
2106
|
-
}
|
|
2107
|
-
]);
|
|
2174
|
+
var voidContract = contract([], { exclusiveChildren: true, allowText: false });
|
|
2175
|
+
var textOnlyContract = contract([], { exclusiveChildren: true });
|
|
2108
2176
|
var landmarkContract = ariaContract([landmarkRoleRule, landmarkNameAdvisory]);
|
|
2109
2177
|
var dialogContract = ariaContract([requireAccessibleName]);
|
|
2110
2178
|
var menuContract = ariaContract([requireAccessibleName]);
|
|
@@ -2149,9 +2217,15 @@ var htmlContracts = {
|
|
|
2149
2217
|
var htmlDiagnostics = warnDiagnostics2;
|
|
2150
2218
|
function buildEvaluatorMap() {
|
|
2151
2219
|
const map2 = /* @__PURE__ */ new Map();
|
|
2152
|
-
iterate.forEachEntry(htmlContracts, (tag, { children }) => {
|
|
2153
|
-
if (children?.length) {
|
|
2154
|
-
map2.set(
|
|
2220
|
+
iterate.forEachEntry(htmlContracts, (tag, { children, exclusiveChildren, allowText }) => {
|
|
2221
|
+
if (children?.length || exclusiveChildren || allowText === false) {
|
|
2222
|
+
map2.set(
|
|
2223
|
+
tag,
|
|
2224
|
+
new ChildrenEvaluator(children ?? [], htmlDiagnostics, `<${tag}>`, {
|
|
2225
|
+
exclusiveChildren,
|
|
2226
|
+
allowText
|
|
2227
|
+
})
|
|
2228
|
+
);
|
|
2155
2229
|
}
|
|
2156
2230
|
});
|
|
2157
2231
|
return map2;
|
|
@@ -2362,7 +2436,7 @@ function definePipeline(factory) {
|
|
|
2362
2436
|
}
|
|
2363
2437
|
|
|
2364
2438
|
// ../core/src/options/resolve-factory-options.ts
|
|
2365
|
-
import { silentDiagnostics } from "../_shared/diagnostics.js";
|
|
2439
|
+
import { resolveDiagnostics, silentDiagnostics } from "../_shared/diagnostics.js";
|
|
2366
2440
|
var EMPTY_VARIANT_KEYS = /* @__PURE__ */ new Set();
|
|
2367
2441
|
function composeNormalizers(normalizers, fn) {
|
|
2368
2442
|
if (!normalizers?.length) return fn;
|
|
@@ -2383,7 +2457,7 @@ function resolveFactoryOptions(options = {}) {
|
|
|
2383
2457
|
const variantKeys = styling?.variants === void 0 ? EMPTY_VARIANT_KEYS : new Set(Object.keys(styling.variants));
|
|
2384
2458
|
return Object.freeze({
|
|
2385
2459
|
defaultTag: options.tag ?? "div",
|
|
2386
|
-
diagnostics: enforcement?.diagnostics
|
|
2460
|
+
diagnostics: resolveDiagnostics(enforcement?.diagnostics, silentDiagnostics),
|
|
2387
2461
|
variantKeys,
|
|
2388
2462
|
...whenDefined("displayName", options.name),
|
|
2389
2463
|
...whenDefined("defaultProps", options.defaults),
|
|
@@ -2396,6 +2470,8 @@ function resolveFactoryOptions(options = {}) {
|
|
|
2396
2470
|
...whenDefined("normalizeFn", composedNormalizeFn),
|
|
2397
2471
|
...whenDefined("ariaRules", enforcement?.aria),
|
|
2398
2472
|
...whenDefined("childRules", enforcement?.children),
|
|
2473
|
+
...whenDefined("exclusiveChildren", enforcement?.exclusiveChildren),
|
|
2474
|
+
...whenDefined("allowText", enforcement?.allowText),
|
|
2399
2475
|
...whenDefined("allowedAs", enforcement?.allowedAs),
|
|
2400
2476
|
...whenDefined("precomputedClasses", styling?.precomputedClasses)
|
|
2401
2477
|
});
|
|
@@ -2580,16 +2656,22 @@ function buildCoreRuntime(normalized) {
|
|
|
2580
2656
|
}
|
|
2581
2657
|
|
|
2582
2658
|
// ../../lib/adapter-utils/src/runtime/build-engines.ts
|
|
2583
|
-
function buildEngines(diagnostics, childRules, context) {
|
|
2584
|
-
|
|
2659
|
+
function buildEngines(diagnostics, childRules, context, childrenOptions) {
|
|
2660
|
+
const { exclusiveChildren, allowText } = childrenOptions ?? {};
|
|
2661
|
+
return childRules?.length || exclusiveChildren || allowText === false ? {
|
|
2662
|
+
childrenEvaluator: new ChildrenEvaluator(childRules ?? [], diagnostics, context, {
|
|
2663
|
+
exclusiveChildren,
|
|
2664
|
+
allowText
|
|
2665
|
+
})
|
|
2666
|
+
} : {};
|
|
2585
2667
|
}
|
|
2586
2668
|
|
|
2587
2669
|
// ../../lib/adapter-utils/src/runtime/resolve-adapter-common-options.ts
|
|
2588
|
-
import { throwDiagnostics as throwDiagnostics2, silentDiagnostics as silentDiagnostics3 } from "../_shared/diagnostics.js";
|
|
2670
|
+
import { throwDiagnostics as throwDiagnostics2, silentDiagnostics as silentDiagnostics3, resolveDiagnostics as resolveDiagnostics2 } from "../_shared/diagnostics.js";
|
|
2589
2671
|
function resolveAdapterCommonOptions(options, defaultName = "PolymorphicComponent", defaultDiagnostics = throwDiagnostics2) {
|
|
2590
2672
|
return {
|
|
2591
2673
|
name: options.name ?? defaultName,
|
|
2592
|
-
diagnostics: options.enforcement?.diagnostics
|
|
2674
|
+
diagnostics: resolveDiagnostics2(options.enforcement?.diagnostics, defaultDiagnostics)
|
|
2593
2675
|
};
|
|
2594
2676
|
}
|
|
2595
2677
|
|
|
@@ -2646,7 +2728,10 @@ function buildRuntime(options) {
|
|
|
2646
2728
|
const normalized = normalizeOptions(options);
|
|
2647
2729
|
const { runtime, ownedKeys } = buildCoreRuntime(normalized);
|
|
2648
2730
|
const { diagnostics, enforcement, filterProps: userFilter, name } = normalized;
|
|
2649
|
-
const { childrenEvaluator } = buildEngines(diagnostics, enforcement?.children, name
|
|
2731
|
+
const { childrenEvaluator } = buildEngines(diagnostics, enforcement?.children, name, {
|
|
2732
|
+
exclusiveChildren: enforcement?.exclusiveChildren,
|
|
2733
|
+
allowText: enforcement?.allowText
|
|
2734
|
+
});
|
|
2650
2735
|
const filterProps = composeFilter(ownedKeys, userFilter);
|
|
2651
2736
|
const slotValidator = new SlotValidator(name, diagnostics, "VNode");
|
|
2652
2737
|
const built = {
|
|
@@ -2752,6 +2837,7 @@ function prepareRenderState(runtime, attrs, filterProps) {
|
|
|
2752
2837
|
...asChild !== void 0 && { asChild }
|
|
2753
2838
|
},
|
|
2754
2839
|
props: filteredProps,
|
|
2840
|
+
normalizedProps,
|
|
2755
2841
|
className
|
|
2756
2842
|
};
|
|
2757
2843
|
}
|
|
@@ -2798,7 +2884,8 @@ function render({
|
|
|
2798
2884
|
}) {
|
|
2799
2885
|
const { vnodes: children, discarded } = normalizeChildren(slots);
|
|
2800
2886
|
if (process.env.NODE_ENV !== "production") {
|
|
2801
|
-
childrenEvaluator?.evaluate(children);
|
|
2887
|
+
childrenEvaluator?.evaluate(children, { tag: state.tag, props: state.normalizedProps });
|
|
2888
|
+
runtime.options.htmlChildrenEvaluatorFn?.(state.tag)?.evaluate(children);
|
|
2802
2889
|
}
|
|
2803
2890
|
const slotResult = tryRenderAsChild(state, children, discarded, slotValidator);
|
|
2804
2891
|
return slotResult ?? renderIntrinsic(state, runtime, slots);
|
package/dist/web/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RequireAtLeastOne, Simplify, ReadonlyDeep } from 'type-fest';
|
|
2
|
-
import { Diagnostics, DiagnosticInput } from '../_shared/diagnostics.js';
|
|
2
|
+
import { Diagnostics, DiagnosticInput, DiagnosticsMode } from '../_shared/diagnostics.js';
|
|
3
3
|
|
|
4
4
|
type StringMap<T = unknown> = Record<string, T>;
|
|
5
5
|
type AnyRecord = StringMap<unknown>;
|
|
@@ -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.
|
|
@@ -195,9 +221,25 @@ type AriaRule<C extends AriaContext = AriaContext> = (context: C) => readonly Ar
|
|
|
195
221
|
type PropNormalizer = (props: Readonly<AnyRecord & IntrinsicProps>) => Partial<AnyRecord & IntrinsicProps>;
|
|
196
222
|
|
|
197
223
|
type EnforcementOptions<TAllowed extends ElementType = ElementType> = {
|
|
198
|
-
|
|
224
|
+
/**
|
|
225
|
+
* Accepts a preset name (`'warn'`, `'throw'`, `'silent'`) or a full `Diagnostics`
|
|
226
|
+
* instance for custom reporting/policy. The string form needs no import from
|
|
227
|
+
* `@praxis-kit/diagnostics`.
|
|
228
|
+
*/
|
|
229
|
+
readonly diagnostics?: Diagnostics | DiagnosticsMode;
|
|
199
230
|
readonly aria?: readonly AriaRule[];
|
|
200
231
|
readonly children?: readonly ChildRuleInput[];
|
|
232
|
+
/**
|
|
233
|
+
* When true, only children matching a `children` rule (or text, per `allowText`)
|
|
234
|
+
* are valid — anything else is rejected. Default: false (open — children not
|
|
235
|
+
* matching any rule are allowed).
|
|
236
|
+
*/
|
|
237
|
+
readonly exclusiveChildren?: boolean;
|
|
238
|
+
/**
|
|
239
|
+
* When false, text/number child nodes are rejected regardless of exclusiveChildren
|
|
240
|
+
* or any listed rule. Default: true.
|
|
241
|
+
*/
|
|
242
|
+
readonly allowText?: boolean;
|
|
201
243
|
readonly props?: readonly PropNormalizer[];
|
|
202
244
|
/** Restricts the `as` prop to this set of tags. Violations route through diagnostics. */
|
|
203
245
|
readonly allowedAs?: readonly TAllowed[];
|