praxis-kit 6.6.0 → 7.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.
@@ -8,6 +8,11 @@ function makeResolveTag(defaultTag) {
8
8
  // ../../lib/primitive/src/rule/rule-brand.ts
9
9
  var RULE_BRAND = /* @__PURE__ */ Symbol("praxis-kit/dynamic-rule");
10
10
 
11
+ // ../../lib/primitive/src/rule/dynamic.ts
12
+ function dynamic(resolve) {
13
+ return { [RULE_BRAND]: true, resolve };
14
+ }
15
+
11
16
  // ../../lib/primitive/src/guards/foundational/is-defined.ts
12
17
  function isUndefined(value) {
13
18
  return value === void 0;
@@ -21,7 +26,7 @@ function isNonNull(value) {
21
26
  return value != null;
22
27
  }
23
28
  function isNullish(value) {
24
- return isNull(value) || value === void 0;
29
+ return isNull(value) || isUndefined(value);
25
30
  }
26
31
 
27
32
  // ../../lib/primitive/src/utils/type-guards.ts
@@ -598,6 +603,24 @@ var ROLE_RESTRICTED_ATTRIBUTES = /* @__PURE__ */ new Map([
598
603
  ]
599
604
  ]);
600
605
 
606
+ // ../../lib/primitive/src/constants/html/void-tags.ts
607
+ var VOID_TAGS = [
608
+ "area",
609
+ "base",
610
+ "br",
611
+ "col",
612
+ "embed",
613
+ "hr",
614
+ "img",
615
+ "input",
616
+ "link",
617
+ "meta",
618
+ "param",
619
+ "source",
620
+ "track",
621
+ "wbr"
622
+ ];
623
+
601
624
  // ../../lib/primitive/src/guards/aria/is-aria-attribute.ts
602
625
  function isGlobalAriaAttribute(attr) {
603
626
  return GLOBAL_ARIA_ATTRIBUTES.has(attr);
@@ -1588,7 +1611,8 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
1588
1611
  const cached = _AriaPolicyEngine.#removeAttributeFixCache.get(attr);
1589
1612
  if (cached) return cached;
1590
1613
  const fix = {
1591
- kind: `removeAttribute:${attr}`,
1614
+ kind: "removeAttribute",
1615
+ attribute: attr,
1592
1616
  apply: ({ props }) => {
1593
1617
  if (!(attr in props)) return { applied: false, next: props };
1594
1618
  return { applied: true, next: omitProp(props, attr), previous: props };
@@ -1859,7 +1883,8 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
1859
1883
  if (!impliedLive) return NO_VIOLATIONS2;
1860
1884
  if ("aria-live" in props) return NO_VIOLATIONS2;
1861
1885
  const injectLive = {
1862
- kind: `injectLive:${effectiveRole}`,
1886
+ kind: "injectLive",
1887
+ attribute: "aria-live",
1863
1888
  apply: (ctx) => ({
1864
1889
  applied: true,
1865
1890
  next: { ...ctx.props, "aria-live": impliedLive },
@@ -1928,6 +1953,23 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
1928
1953
  }
1929
1954
  };
1930
1955
 
1956
+ // ../../lib/contract/src/aria/factories.ts
1957
+ function removeProp(props, key) {
1958
+ const next = { ...props };
1959
+ delete next[key];
1960
+ return next;
1961
+ }
1962
+ function removeAttributeFix(attribute) {
1963
+ return Object.freeze({
1964
+ kind: "removeAttribute",
1965
+ attribute,
1966
+ apply: ({ props }) => {
1967
+ if (!(attribute in props)) return { applied: false, next: props };
1968
+ return { applied: true, next: removeProp(props, attribute), previous: props };
1969
+ }
1970
+ });
1971
+ }
1972
+
1931
1973
  // ../../lib/contract/src/children/get-type-name.ts
1932
1974
  function getTypeName(value) {
1933
1975
  if (value === null) return "null";
@@ -2244,6 +2286,77 @@ var readonlyProps = ({
2244
2286
  // ../core/src/html/evaluators.ts
2245
2287
  import { warnDiagnostics as warnDiagnostics2 } from "../_shared/diagnostics.js";
2246
2288
 
2289
+ // ../core/src/html/contracts/categories.ts
2290
+ var METADATA_TAGS = ["script", "template"];
2291
+ var TEXT_ONLY_TAGS = [
2292
+ "option",
2293
+ "script",
2294
+ "style",
2295
+ "textarea",
2296
+ "title"
2297
+ ];
2298
+ var LANDMARK_TAGS = [
2299
+ "article",
2300
+ "aside",
2301
+ "footer",
2302
+ "header",
2303
+ "main",
2304
+ "nav"
2305
+ ];
2306
+ var INTERACTIVE_CONTENT_TAGS = [
2307
+ "a",
2308
+ "button",
2309
+ "input",
2310
+ "select",
2311
+ "textarea",
2312
+ "label"
2313
+ ];
2314
+ var LABELABLE_TAGS = [
2315
+ "button",
2316
+ "input",
2317
+ "meter",
2318
+ "output",
2319
+ "progress",
2320
+ "select",
2321
+ "textarea"
2322
+ ];
2323
+ var OTHER_INTERACTIVE_TAGS = [
2324
+ "a",
2325
+ "details",
2326
+ "embed",
2327
+ "iframe"
2328
+ ];
2329
+ var P_BLOCKED_TAGS = [
2330
+ "address",
2331
+ "article",
2332
+ "aside",
2333
+ "blockquote",
2334
+ "details",
2335
+ "dialog",
2336
+ "div",
2337
+ "dl",
2338
+ "fieldset",
2339
+ "figure",
2340
+ "footer",
2341
+ "form",
2342
+ "h1",
2343
+ "h2",
2344
+ "h3",
2345
+ "h4",
2346
+ "h5",
2347
+ "h6",
2348
+ "header",
2349
+ "hr",
2350
+ "main",
2351
+ "nav",
2352
+ "ol",
2353
+ "p",
2354
+ "pre",
2355
+ "section",
2356
+ "table",
2357
+ "ul"
2358
+ ];
2359
+
2247
2360
  // ../core/src/html/spec/vocabulary/input.ts
2248
2361
  var TEXT_INPUT_TYPES = ["text", "search", "url", "tel", "email", "password"];
2249
2362
  var NUMERIC_INPUT_TYPES = [
@@ -2298,20 +2411,6 @@ var INPUT_MUTUALLY_EXCLUSIVE_POLICIES = [
2298
2411
 
2299
2412
  // ../core/src/html/spec/validators/attribute-type-validator.ts
2300
2413
  var DEFAULT_INPUT_TYPE = "text";
2301
- function omit(props, key) {
2302
- const next = { ...props };
2303
- delete next[key];
2304
- return next;
2305
- }
2306
- function removeAttributeFix(attribute) {
2307
- return {
2308
- kind: `removeAttribute:${attribute}`,
2309
- apply: ({ props }) => {
2310
- if (!(attribute in props)) return { applied: false, next: props };
2311
- return { applied: true, next: omit(props, attribute), previous: props };
2312
- }
2313
- };
2314
- }
2315
2414
  function createInputAttributeTypeRule({
2316
2415
  attribute,
2317
2416
  allowedTypes
@@ -2623,7 +2722,11 @@ var ALLOWED_ROLES = {
2623
2722
  "treeitem"
2624
2723
  ],
2625
2724
  dialog: ["alertdialog"],
2626
- fieldset: ["none", "presentation", "radiogroup"]
2725
+ fieldset: ["none", "presentation", "radiogroup"],
2726
+ // `<label>` has no implicit role and no documented alternates — its native labeling
2727
+ // semantics (control association, accessible-name contribution) aren't reproducible via
2728
+ // ARIA, so any explicit `role` should be avoided rather than substituted.
2729
+ label: []
2627
2730
  };
2628
2731
  var ELEMENT_SPECS = {
2629
2732
  input: inputElementSpec,
@@ -2664,7 +2767,10 @@ var roleNotPermittedRule = Object.assign(
2664
2767
  );
2665
2768
 
2666
2769
  // ../core/src/html/aria-rules.ts
2667
- var LANDMARK_TAG_SET = /* @__PURE__ */ new Set(["article", "aside", "footer", "header", "main", "nav"]);
2770
+ function defineAriaRule(tags, rule) {
2771
+ return Object.assign(rule, { tags });
2772
+ }
2773
+ var LANDMARK_TAG_SET = new Set(LANDMARK_TAGS);
2668
2774
  var removeLandmarkRoleOverride = {
2669
2775
  kind: "removeRole",
2670
2776
  apply: ({ props }) => {
@@ -2673,10 +2779,11 @@ var removeLandmarkRoleOverride = {
2673
2779
  return { applied: true, next: rest, previous: props };
2674
2780
  }
2675
2781
  };
2676
- var landmarkRoleRule = Object.assign(
2782
+ var landmarkRoleRule = defineAriaRule(
2783
+ LANDMARK_TAGS,
2677
2784
  ({ tag, props, implicitRole }) => {
2678
2785
  if (!LANDMARK_TAG_SET.has(tag) || !implicitRole) return [];
2679
- const role = props.role;
2786
+ const { role } = props;
2680
2787
  if (!role || role === implicitRole) return [];
2681
2788
  const diagnostic = HtmlDiagnostics.landmarkRoleOverride(tag, implicitRole, role);
2682
2789
  return [
@@ -2688,8 +2795,7 @@ var landmarkRoleRule = Object.assign(
2688
2795
  diagnostic
2689
2796
  }
2690
2797
  ];
2691
- },
2692
- { tags: [...LANDMARK_TAG_SET] }
2798
+ }
2693
2799
  );
2694
2800
  function requireAccessibleName({ tag, props }) {
2695
2801
  if ("aria-label" in props || "aria-labelledby" in props) return [];
@@ -2702,38 +2808,44 @@ function requireAccessibleName({ tag, props }) {
2702
2808
  }
2703
2809
  ];
2704
2810
  }
2705
- var NAMED_LANDMARK_TAGS = /* @__PURE__ */ new Set(["nav", "aside"]);
2706
- var landmarkNameAdvisory = Object.assign(
2811
+ var NAMED_LANDMARK_TAGS = ["nav", "aside"];
2812
+ var NAMED_LANDMARK_TAG_SET = new Set(NAMED_LANDMARK_TAGS);
2813
+ var landmarkAccessibleNameRule = defineAriaRule(
2814
+ NAMED_LANDMARK_TAGS,
2707
2815
  (ctx) => {
2708
- if (!ctx.implicitRole || !NAMED_LANDMARK_TAGS.has(ctx.tag)) return [];
2816
+ if (!ctx.implicitRole || !NAMED_LANDMARK_TAG_SET.has(ctx.tag)) return [];
2709
2817
  return requireAccessibleName(ctx);
2710
- },
2711
- { tags: [...NAMED_LANDMARK_TAGS] }
2818
+ }
2712
2819
  );
2713
2820
  var HTML_ARIA_RULES = [
2714
2821
  landmarkRoleRule,
2715
- landmarkNameAdvisory,
2822
+ landmarkAccessibleNameRule,
2716
2823
  roleNotPermittedRule,
2717
2824
  ...INPUT_RULES
2718
2825
  ];
2719
2826
 
2720
- // ../core/src/html/contracts.ts
2827
+ // ../core/src/html/contracts/helpers.ts
2721
2828
  import { warnDiagnostics } from "../_shared/diagnostics.js";
2829
+ function isVNodeLike(child) {
2830
+ return isObject(child) && "type" in child;
2831
+ }
2722
2832
  function isOpenContent(...blockedTags) {
2723
2833
  const set2 = new Set(blockedTags);
2724
2834
  return (child) => {
2725
- if (!isObject(child) || !("type" in child)) return false;
2835
+ if (!isVNodeLike(child)) return false;
2726
2836
  const tag = getTag(child);
2727
2837
  return tag === void 0 || !set2.has(tag);
2728
2838
  };
2729
2839
  }
2730
- var METADATA_TAGS = ["script", "template"];
2731
2840
  var metadataMatch = isTag(...METADATA_TAGS);
2732
2841
  function metadata(name = "metadata") {
2733
2842
  return { name, match: metadataMatch };
2734
2843
  }
2844
+ function optional(name, tag) {
2845
+ return { name, match: isTag(tag), cardinality: { max: 1 } };
2846
+ }
2735
2847
  function firstOptional(name, tag) {
2736
- return { name, match: isTag(tag), cardinality: { max: 1 }, position: "first" };
2848
+ return { ...optional(name, tag), position: "first" };
2737
2849
  }
2738
2850
  function contract(children, options) {
2739
2851
  return { diagnostics: warnDiagnostics, children, ...options };
@@ -2747,50 +2859,41 @@ function ariaContract(aria) {
2747
2859
  function firstChildContract(name, tag) {
2748
2860
  return contract([firstOptional(name, tag), { name: "content", match: isOpenContent(tag) }]);
2749
2861
  }
2750
- var VOID_TAGS = [
2751
- "area",
2752
- "base",
2753
- "br",
2754
- "col",
2755
- "embed",
2756
- "hr",
2757
- "img",
2758
- "input",
2759
- "link",
2760
- "meta",
2761
- "param",
2762
- "source",
2763
- "track",
2764
- "wbr"
2765
- ];
2766
- var TEXT_ONLY_TAGS = ["option", "script", "style", "textarea", "title"];
2767
- var LANDMARK_TAGS = ["article", "aside", "footer", "header", "main", "nav"];
2768
- var listContract = closedContract([
2769
- { name: "list-item", match: isTag("li", ...METADATA_TAGS) }
2770
- ]);
2771
- var tableContract = closedContract([
2772
- firstOptional("caption", "caption"),
2773
- { name: "colgroup", match: isTag("colgroup") },
2774
- { name: "thead", match: isTag("thead"), cardinality: { max: 1 } },
2775
- { name: "tbody", match: isTag("tbody") },
2776
- { name: "tfoot", match: isTag("tfoot"), cardinality: { max: 1 } },
2777
- { name: "table-row", match: isTag("tr", ...METADATA_TAGS) }
2778
- ]);
2779
- var tableBodyContract = closedContract([
2780
- { name: "table-row", match: isTag("tr", ...METADATA_TAGS) }
2781
- ]);
2782
- var tableRowContract = closedContract([
2783
- { name: "table-cell", match: isTag("td", "th", ...METADATA_TAGS) }
2784
- ]);
2785
- var colgroupContract = closedContract([
2786
- { name: "column", match: isTag("col", "template") }
2862
+ function getChildProp(child, key) {
2863
+ if (!isVNodeLike(child)) return void 0;
2864
+ const { props } = child;
2865
+ if (!isObject(props)) return void 0;
2866
+ return props[key];
2867
+ }
2868
+
2869
+ // ../core/src/html/contracts/aria/landmarks.ts
2870
+ var landmarkContract = ariaContract([landmarkRoleRule, landmarkAccessibleNameRule]);
2871
+
2872
+ // ../core/src/html/contracts/aria/widgets.ts
2873
+ var dialogContract = ariaContract([requireAccessibleName]);
2874
+ var menuContract = ariaContract([requireAccessibleName]);
2875
+ var menubarContract = ariaContract([requireAccessibleName]);
2876
+ var treeContract = ariaContract([requireAccessibleName]);
2877
+ var gridContract = ariaContract([requireAccessibleName]);
2878
+ var listboxContract = ariaContract([requireAccessibleName]);
2879
+ var tablistContract = ariaContract([requireAccessibleName]);
2880
+ var radiogroupContract = ariaContract([requireAccessibleName]);
2881
+
2882
+ // ../core/src/html/contracts/html/document.ts
2883
+ var headContract = closedContract([
2884
+ {
2885
+ name: "metadata",
2886
+ match: isTag("base", "link", "meta", "noscript", "script", "style", "template", "title")
2887
+ }
2787
2888
  ]);
2788
- var dlContract = closedContract([
2789
- { name: "term", match: isTag("dt") },
2790
- { name: "description", match: isTag("dd") },
2791
- { name: "group", match: isTag("div") },
2792
- metadata()
2889
+ var htmlContract = closedContract([
2890
+ { name: "head", match: isTag("head"), cardinality: { min: 1, max: 1 }, position: "first" },
2891
+ { name: "body", match: isTag("body"), cardinality: { min: 1, max: 1 } }
2793
2892
  ]);
2893
+ var voidContract = contract([], { exclusiveChildren: true, allowText: false });
2894
+ var textOnlyContract = contract([], { exclusiveChildren: true });
2895
+
2896
+ // ../core/src/html/contracts/html/forms.ts
2794
2897
  var selectContract = closedContract([
2795
2898
  { name: "option", match: isTag("option", "optgroup", "hr", ...METADATA_TAGS) }
2796
2899
  ]);
@@ -2800,6 +2903,59 @@ var optgroupContract = closedContract([
2800
2903
  var datalistContract = closedContract([
2801
2904
  { name: "option", match: isTag("option", ...METADATA_TAGS) }
2802
2905
  ]);
2906
+ var buttonContract = closedContract([
2907
+ { name: "content", match: isOpenContent(...INTERACTIVE_CONTENT_TAGS) }
2908
+ ]);
2909
+ var anchorContract = closedContract([
2910
+ { name: "content", match: isOpenContent(...INTERACTIVE_CONTENT_TAGS) }
2911
+ ]);
2912
+ var labelableTagMatch = isTag(...LABELABLE_TAGS);
2913
+ function isLabelableControl(child) {
2914
+ if (!labelableTagMatch(child)) return false;
2915
+ if (getTag(child) !== "input") return true;
2916
+ const type = getChildProp(child, "type");
2917
+ return !isString(type) || type !== "hidden";
2918
+ }
2919
+ function hasAccessibleNameProp(props) {
2920
+ return "aria-label" in props || "aria-labelledby" in props;
2921
+ }
2922
+ function isNonEmptyTextChild(child) {
2923
+ if (isNumber(child)) return true;
2924
+ return isString(child) && child.trim().length > 0;
2925
+ }
2926
+ var labelContract = contract([
2927
+ { name: "control", match: isLabelableControl, cardinality: { max: 1 } },
2928
+ { name: "nested-label", match: isTag("label"), cardinality: { max: 0 } },
2929
+ {
2930
+ name: "other-interactive-content",
2931
+ match: isTag(...OTHER_INTERACTIVE_TAGS),
2932
+ cardinality: { max: 0 }
2933
+ },
2934
+ {
2935
+ name: "accessible-name",
2936
+ match: isNonEmptyTextChild,
2937
+ cardinality: dynamic(
2938
+ (ctx) => hasAccessibleNameProp(ctx.props) ? { min: 0 } : { min: 1 }
2939
+ )
2940
+ }
2941
+ ]);
2942
+
2943
+ // ../core/src/html/contracts/html/grouping.ts
2944
+ var detailsContract = firstChildContract("summary", "summary");
2945
+ var fieldsetContract = firstChildContract("legend", "legend");
2946
+
2947
+ // ../core/src/html/contracts/html/lists.ts
2948
+ var listContract = closedContract([
2949
+ { name: "list-item", match: isTag("li", ...METADATA_TAGS) }
2950
+ ]);
2951
+ var dlContract = closedContract([
2952
+ { name: "term", match: isTag("dt") },
2953
+ { name: "description", match: isTag("dd") },
2954
+ { name: "group", match: isTag("div") },
2955
+ metadata()
2956
+ ]);
2957
+
2958
+ // ../core/src/html/contracts/html/media.ts
2803
2959
  var pictureContract = closedContract([
2804
2960
  { name: "source", match: isTag("source", ...METADATA_TAGS) },
2805
2961
  { name: "image", match: isTag("img"), cardinality: { min: 1, max: 1 }, position: "last" }
@@ -2808,91 +2964,49 @@ var figureContract = contract([
2808
2964
  { name: "caption", match: isTag("figcaption"), cardinality: { max: 1 } },
2809
2965
  { name: "content", match: isOpenContent("figcaption") }
2810
2966
  ]);
2811
- var detailsContract = firstChildContract("summary", "summary");
2812
- var fieldsetContract = firstChildContract("legend", "legend");
2813
2967
  var objectContract = contract([
2814
2968
  { name: "param", match: isTag("param") },
2815
2969
  { name: "content", match: isOpenContent("param") }
2816
2970
  ]);
2817
- var INTERACTIVE_CONTENT_TAGS = ["a", "button", "input", "select", "textarea", "label"];
2818
- var buttonContract = closedContract([
2819
- { name: "content", match: isOpenContent(...INTERACTIVE_CONTENT_TAGS) }
2820
- ]);
2821
- var anchorContract = closedContract([
2822
- { name: "content", match: isOpenContent(...INTERACTIVE_CONTENT_TAGS) }
2823
- ]);
2824
- var LABELABLE_TAGS = [
2825
- "button",
2826
- "input",
2827
- "meter",
2828
- "output",
2829
- "progress",
2830
- "select",
2831
- "textarea"
2832
- ];
2833
- var labelContract = contract([
2834
- { name: "control", match: isTag(...LABELABLE_TAGS), cardinality: { max: 1 } }
2835
- ]);
2836
- var P_BLOCKED_TAGS = [
2837
- "address",
2838
- "article",
2839
- "aside",
2840
- "blockquote",
2841
- "details",
2842
- "dialog",
2843
- "div",
2844
- "dl",
2845
- "fieldset",
2846
- "figure",
2847
- "footer",
2848
- "form",
2849
- "h1",
2850
- "h2",
2851
- "h3",
2852
- "h4",
2853
- "h5",
2854
- "h6",
2855
- "header",
2856
- "hr",
2857
- "main",
2858
- "nav",
2859
- "ol",
2860
- "p",
2861
- "pre",
2862
- "section",
2863
- "table",
2864
- "ul"
2865
- ];
2866
- var pContract = closedContract([
2867
- { name: "content", match: isOpenContent(...P_BLOCKED_TAGS) }
2868
- ]);
2869
2971
  var mediaContract = contract([
2870
2972
  { name: "source", match: isTag("source") },
2871
2973
  { name: "track", match: isTag("track") },
2872
2974
  metadata(),
2873
2975
  { name: "content", match: isOpenContent("source", "track", ...METADATA_TAGS) }
2874
2976
  ]);
2875
- var headContract = closedContract([
2876
- {
2877
- name: "metadata",
2878
- match: isTag("base", "link", "meta", "noscript", "script", "style", "template", "title")
2879
- }
2977
+
2978
+ // ../core/src/html/contracts/html/tables.ts
2979
+ var tableContract = closedContract([
2980
+ firstOptional("caption", "caption"),
2981
+ { name: "colgroup", match: isTag("colgroup") },
2982
+ { name: "thead", match: isTag("thead"), cardinality: { max: 1 } },
2983
+ { name: "tbody", match: isTag("tbody") },
2984
+ { name: "tfoot", match: isTag("tfoot"), cardinality: { max: 1 } },
2985
+ { name: "table-row", match: isTag("tr", ...METADATA_TAGS) }
2880
2986
  ]);
2881
- var htmlContract = closedContract([
2882
- { name: "head", match: isTag("head"), cardinality: { min: 1, max: 1 }, position: "first" },
2883
- { name: "body", match: isTag("body"), cardinality: { min: 1, max: 1 } }
2987
+ var tableBodyContract = closedContract([
2988
+ { name: "table-row", match: isTag("tr", ...METADATA_TAGS) }
2884
2989
  ]);
2885
- var voidContract = contract([], { exclusiveChildren: true, allowText: false });
2886
- var textOnlyContract = contract([], { exclusiveChildren: true });
2887
- var landmarkContract = ariaContract([landmarkRoleRule, landmarkNameAdvisory]);
2888
- var dialogContract = ariaContract([requireAccessibleName]);
2889
- var menuContract = ariaContract([requireAccessibleName]);
2890
- var menubarContract = ariaContract([requireAccessibleName]);
2891
- var treeContract = ariaContract([requireAccessibleName]);
2892
- var gridContract = ariaContract([requireAccessibleName]);
2893
- var listboxContract = ariaContract([requireAccessibleName]);
2894
- var tablistContract = ariaContract([requireAccessibleName]);
2895
- var radiogroupContract = ariaContract([requireAccessibleName]);
2990
+ var tableRowContract = closedContract([
2991
+ { name: "table-cell", match: isTag("td", "th", ...METADATA_TAGS) }
2992
+ ]);
2993
+ var colgroupContract = closedContract([
2994
+ { name: "column", match: isTag("col", "template") }
2995
+ ]);
2996
+
2997
+ // ../core/src/html/contracts/html/text.ts
2998
+ var pContract = closedContract([
2999
+ { name: "content", match: isOpenContent(...P_BLOCKED_TAGS) }
3000
+ ]);
3001
+
3002
+ // ../core/src/html/contracts/build-map.ts
3003
+ function buildMap(groups) {
3004
+ return Object.fromEntries(
3005
+ groups.flatMap(([keys2, value]) => keys2.map((key) => [key, value]))
3006
+ );
3007
+ }
3008
+
3009
+ // ../core/src/html/contracts/maps.ts
2896
3010
  var CONTRACT_GROUPS = [
2897
3011
  [VOID_TAGS, voidContract],
2898
3012
  [TEXT_ONLY_TAGS, textOnlyContract],
@@ -2901,13 +3015,8 @@ var CONTRACT_GROUPS = [
2901
3015
  [["audio", "video"], mediaContract],
2902
3016
  [["thead", "tbody", "tfoot"], tableBodyContract]
2903
3017
  ];
2904
- function contractMap(groups) {
2905
- return Object.fromEntries(
2906
- groups.flatMap(([tags, enforcement]) => tags.map((tag) => [tag, enforcement]))
2907
- );
2908
- }
2909
3018
  var htmlContracts = {
2910
- ...contractMap(CONTRACT_GROUPS),
3019
+ ...buildMap(CONTRACT_GROUPS),
2911
3020
  table: tableContract,
2912
3021
  tr: tableRowContract,
2913
3022
  colgroup: colgroupContract,
@@ -3546,7 +3655,10 @@ function render({
3546
3655
  }));
3547
3656
  }
3548
3657
  if (process.env.NODE_ENV !== "production") {
3549
- createEffect(() => runtime.options.htmlChildrenEvaluatorFn?.(tag())?.evaluate(toChildArray(known.children)));
3658
+ createEffect(() => runtime.options.htmlChildrenEvaluatorFn?.(tag())?.evaluate(toChildArray(known.children), {
3659
+ tag: tag(),
3660
+ props: normalizedProps()
3661
+ }));
3550
3662
  }
3551
3663
  const slotResult = tryRenderAsChild(known, filteredProps, resolvedClass, slotValidator);
3552
3664
  if (slotResult !== null) return slotResult;
@@ -130,7 +130,9 @@
130
130
  if (process.env.NODE_ENV === 'production' || !hostEl) return
131
131
  const childArray = Array.from(hostEl.childNodes)
132
132
  bundle.childrenEvaluator?.evaluate(childArray, { tag, props: normalizedProps })
133
- bundle.runtime.options.htmlChildrenEvaluatorFn?.(tag)?.evaluate(childArray)
133
+ bundle.runtime.options.htmlChildrenEvaluatorFn
134
+ ?.(tag)
135
+ ?.evaluate(childArray, { tag, props: normalizedProps })
134
136
  })
135
137
  }
136
138
  </script>
@@ -29,13 +29,6 @@ type MinMax = {
29
29
  };
30
30
  type CardinalityInput = Partial<MinMax>;
31
31
 
32
- /** Structural counterpart to `@praxis-kit/contract`'s `ChildrenEvaluator` class — `lib/primitive`
33
- * may not depend on `lib/contract` (see `primitive-no-upper-layers` in .dependency-cruiser.cjs),
34
- * so this describes only the shape consumers actually call. Mirrors `AriaEngine`'s pattern. */
35
- type ChildrenEvaluator$1 = {
36
- evaluate: (children: unknown[]) => void;
37
- };
38
-
39
32
  /**
40
33
  * Resolved per-instance state available to a dynamic (`dynamic(...)`) child
41
34
  * rule field — the same tag/props every adapter already computes before
@@ -47,6 +40,13 @@ type ChildRuleContext = {
47
40
  readonly props: Readonly<AnyRecord>;
48
41
  };
49
42
 
43
+ /** Structural counterpart to `@praxis-kit/contract`'s `ChildrenEvaluator` class — `lib/primitive`
44
+ * may not depend on `lib/contract` (see `primitive-no-upper-layers` in .dependency-cruiser.cjs),
45
+ * so this describes only the shape consumers actually call. Mirrors `AriaEngine`'s pattern. */
46
+ type ChildrenEvaluator$1 = {
47
+ evaluate: (children: unknown[], context?: ChildRuleContext) => void;
48
+ };
49
+
50
50
  declare const RULE_BRAND: unique symbol;
51
51
 
52
52
  type DynamicRule<T, C = unknown> = {
@@ -200,8 +200,8 @@ type AriaContext = {
200
200
  readonly props: ReadonlyDeep<IntrinsicProps>;
201
201
  };
202
202
 
203
- type RemoveAttributeFixKind = `removeAttribute:${string}`;
204
- type InjectLiveFixKind = `injectLive:${string}`;
203
+ type RemoveAttributeFixKind = 'removeAttribute';
204
+ type InjectLiveFixKind = 'injectLive';
205
205
  type FixKind = 'removeRole' | 'setRole' | 'normalizeRelevantAll' | RemoveAttributeFixKind | InjectLiveFixKind;
206
206
 
207
207
  type AriaFixResult = {
@@ -214,6 +214,9 @@ type AriaFixResult = {
214
214
  };
215
215
  type AriaFix = {
216
216
  readonly kind: FixKind;
217
+ /** The attribute a `'removeAttribute'`/`'injectLive'` fix targets — always set for those
218
+ * kinds, absent for kinds with no single-attribute target (`'removeRole'`, etc.). */
219
+ readonly attribute?: string;
217
220
  readonly priority?: number;
218
221
  readonly source?: string;
219
222
  readonly apply: (context: AriaContext) => AriaFixResult;