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.
package/dist/lit/index.js CHANGED
@@ -13,6 +13,11 @@ function makeResolveTag(defaultTag) {
13
13
  // ../../lib/primitive/src/rule/rule-brand.ts
14
14
  var RULE_BRAND = /* @__PURE__ */ Symbol("praxis-kit/dynamic-rule");
15
15
 
16
+ // ../../lib/primitive/src/rule/dynamic.ts
17
+ function dynamic(resolve) {
18
+ return { [RULE_BRAND]: true, resolve };
19
+ }
20
+
16
21
  // ../../lib/primitive/src/guards/foundational/is-defined.ts
17
22
  function isUndefined(value) {
18
23
  return value === void 0;
@@ -26,7 +31,7 @@ function isNonNull(value) {
26
31
  return value != null;
27
32
  }
28
33
  function isNullish(value) {
29
- return isNull(value) || value === void 0;
34
+ return isNull(value) || isUndefined(value);
30
35
  }
31
36
 
32
37
  // ../../lib/primitive/src/utils/type-guards.ts
@@ -517,6 +522,24 @@ var ROLE_RESTRICTED_ATTRIBUTES = /* @__PURE__ */ new Map([
517
522
  ]
518
523
  ]);
519
524
 
525
+ // ../../lib/primitive/src/constants/html/void-tags.ts
526
+ var VOID_TAGS = [
527
+ "area",
528
+ "base",
529
+ "br",
530
+ "col",
531
+ "embed",
532
+ "hr",
533
+ "img",
534
+ "input",
535
+ "link",
536
+ "meta",
537
+ "param",
538
+ "source",
539
+ "track",
540
+ "wbr"
541
+ ];
542
+
520
543
  // ../../lib/primitive/src/guards/aria/is-aria-attribute.ts
521
544
  function isGlobalAriaAttribute(attr) {
522
545
  return GLOBAL_ARIA_ATTRIBUTES.has(attr);
@@ -1446,7 +1469,8 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
1446
1469
  const cached = _AriaPolicyEngine.#removeAttributeFixCache.get(attr);
1447
1470
  if (cached) return cached;
1448
1471
  const fix = {
1449
- kind: `removeAttribute:${attr}`,
1472
+ kind: "removeAttribute",
1473
+ attribute: attr,
1450
1474
  apply: ({ props }) => {
1451
1475
  if (!(attr in props)) return { applied: false, next: props };
1452
1476
  return { applied: true, next: omitProp(props, attr), previous: props };
@@ -1717,7 +1741,8 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
1717
1741
  if (!impliedLive) return NO_VIOLATIONS2;
1718
1742
  if ("aria-live" in props) return NO_VIOLATIONS2;
1719
1743
  const injectLive = {
1720
- kind: `injectLive:${effectiveRole}`,
1744
+ kind: "injectLive",
1745
+ attribute: "aria-live",
1721
1746
  apply: (ctx) => ({
1722
1747
  applied: true,
1723
1748
  next: { ...ctx.props, "aria-live": impliedLive },
@@ -1786,6 +1811,23 @@ var AriaPolicyEngine = class _AriaPolicyEngine extends InvariantBase {
1786
1811
  }
1787
1812
  };
1788
1813
 
1814
+ // ../../lib/contract/src/aria/factories.ts
1815
+ function removeProp(props, key) {
1816
+ const next = { ...props };
1817
+ delete next[key];
1818
+ return next;
1819
+ }
1820
+ function removeAttributeFix(attribute) {
1821
+ return Object.freeze({
1822
+ kind: "removeAttribute",
1823
+ attribute,
1824
+ apply: ({ props }) => {
1825
+ if (!(attribute in props)) return { applied: false, next: props };
1826
+ return { applied: true, next: removeProp(props, attribute), previous: props };
1827
+ }
1828
+ });
1829
+ }
1830
+
1789
1831
  // ../../lib/contract/src/children/get-type-name.ts
1790
1832
  function getTypeName(value) {
1791
1833
  if (value === null) return "null";
@@ -2102,6 +2144,77 @@ var readonlyProps = ({
2102
2144
  // ../core/src/html/evaluators.ts
2103
2145
  import { warnDiagnostics as warnDiagnostics2 } from "../_shared/diagnostics.js";
2104
2146
 
2147
+ // ../core/src/html/contracts/categories.ts
2148
+ var METADATA_TAGS = ["script", "template"];
2149
+ var TEXT_ONLY_TAGS = [
2150
+ "option",
2151
+ "script",
2152
+ "style",
2153
+ "textarea",
2154
+ "title"
2155
+ ];
2156
+ var LANDMARK_TAGS = [
2157
+ "article",
2158
+ "aside",
2159
+ "footer",
2160
+ "header",
2161
+ "main",
2162
+ "nav"
2163
+ ];
2164
+ var INTERACTIVE_CONTENT_TAGS = [
2165
+ "a",
2166
+ "button",
2167
+ "input",
2168
+ "select",
2169
+ "textarea",
2170
+ "label"
2171
+ ];
2172
+ var LABELABLE_TAGS = [
2173
+ "button",
2174
+ "input",
2175
+ "meter",
2176
+ "output",
2177
+ "progress",
2178
+ "select",
2179
+ "textarea"
2180
+ ];
2181
+ var OTHER_INTERACTIVE_TAGS = [
2182
+ "a",
2183
+ "details",
2184
+ "embed",
2185
+ "iframe"
2186
+ ];
2187
+ var P_BLOCKED_TAGS = [
2188
+ "address",
2189
+ "article",
2190
+ "aside",
2191
+ "blockquote",
2192
+ "details",
2193
+ "dialog",
2194
+ "div",
2195
+ "dl",
2196
+ "fieldset",
2197
+ "figure",
2198
+ "footer",
2199
+ "form",
2200
+ "h1",
2201
+ "h2",
2202
+ "h3",
2203
+ "h4",
2204
+ "h5",
2205
+ "h6",
2206
+ "header",
2207
+ "hr",
2208
+ "main",
2209
+ "nav",
2210
+ "ol",
2211
+ "p",
2212
+ "pre",
2213
+ "section",
2214
+ "table",
2215
+ "ul"
2216
+ ];
2217
+
2105
2218
  // ../core/src/html/spec/vocabulary/input.ts
2106
2219
  var TEXT_INPUT_TYPES = ["text", "search", "url", "tel", "email", "password"];
2107
2220
  var NUMERIC_INPUT_TYPES = [
@@ -2156,20 +2269,6 @@ var INPUT_MUTUALLY_EXCLUSIVE_POLICIES = [
2156
2269
 
2157
2270
  // ../core/src/html/spec/validators/attribute-type-validator.ts
2158
2271
  var DEFAULT_INPUT_TYPE = "text";
2159
- function omit(props, key) {
2160
- const next = { ...props };
2161
- delete next[key];
2162
- return next;
2163
- }
2164
- function removeAttributeFix(attribute) {
2165
- return {
2166
- kind: `removeAttribute:${attribute}`,
2167
- apply: ({ props }) => {
2168
- if (!(attribute in props)) return { applied: false, next: props };
2169
- return { applied: true, next: omit(props, attribute), previous: props };
2170
- }
2171
- };
2172
- }
2173
2272
  function createInputAttributeTypeRule({
2174
2273
  attribute,
2175
2274
  allowedTypes
@@ -2481,7 +2580,11 @@ var ALLOWED_ROLES = {
2481
2580
  "treeitem"
2482
2581
  ],
2483
2582
  dialog: ["alertdialog"],
2484
- fieldset: ["none", "presentation", "radiogroup"]
2583
+ fieldset: ["none", "presentation", "radiogroup"],
2584
+ // `<label>` has no implicit role and no documented alternates — its native labeling
2585
+ // semantics (control association, accessible-name contribution) aren't reproducible via
2586
+ // ARIA, so any explicit `role` should be avoided rather than substituted.
2587
+ label: []
2485
2588
  };
2486
2589
  var ELEMENT_SPECS = {
2487
2590
  input: inputElementSpec,
@@ -2522,7 +2625,10 @@ var roleNotPermittedRule = Object.assign(
2522
2625
  );
2523
2626
 
2524
2627
  // ../core/src/html/aria-rules.ts
2525
- var LANDMARK_TAG_SET = /* @__PURE__ */ new Set(["article", "aside", "footer", "header", "main", "nav"]);
2628
+ function defineAriaRule(tags, rule) {
2629
+ return Object.assign(rule, { tags });
2630
+ }
2631
+ var LANDMARK_TAG_SET = new Set(LANDMARK_TAGS);
2526
2632
  var removeLandmarkRoleOverride = {
2527
2633
  kind: "removeRole",
2528
2634
  apply: ({ props }) => {
@@ -2531,10 +2637,11 @@ var removeLandmarkRoleOverride = {
2531
2637
  return { applied: true, next: rest, previous: props };
2532
2638
  }
2533
2639
  };
2534
- var landmarkRoleRule = Object.assign(
2640
+ var landmarkRoleRule = defineAriaRule(
2641
+ LANDMARK_TAGS,
2535
2642
  ({ tag, props, implicitRole }) => {
2536
2643
  if (!LANDMARK_TAG_SET.has(tag) || !implicitRole) return [];
2537
- const role = props.role;
2644
+ const { role } = props;
2538
2645
  if (!role || role === implicitRole) return [];
2539
2646
  const diagnostic = HtmlDiagnostics.landmarkRoleOverride(tag, implicitRole, role);
2540
2647
  return [
@@ -2546,8 +2653,7 @@ var landmarkRoleRule = Object.assign(
2546
2653
  diagnostic
2547
2654
  }
2548
2655
  ];
2549
- },
2550
- { tags: [...LANDMARK_TAG_SET] }
2656
+ }
2551
2657
  );
2552
2658
  function requireAccessibleName({ tag, props }) {
2553
2659
  if ("aria-label" in props || "aria-labelledby" in props) return [];
@@ -2560,38 +2666,44 @@ function requireAccessibleName({ tag, props }) {
2560
2666
  }
2561
2667
  ];
2562
2668
  }
2563
- var NAMED_LANDMARK_TAGS = /* @__PURE__ */ new Set(["nav", "aside"]);
2564
- var landmarkNameAdvisory = Object.assign(
2669
+ var NAMED_LANDMARK_TAGS = ["nav", "aside"];
2670
+ var NAMED_LANDMARK_TAG_SET = new Set(NAMED_LANDMARK_TAGS);
2671
+ var landmarkAccessibleNameRule = defineAriaRule(
2672
+ NAMED_LANDMARK_TAGS,
2565
2673
  (ctx) => {
2566
- if (!ctx.implicitRole || !NAMED_LANDMARK_TAGS.has(ctx.tag)) return [];
2674
+ if (!ctx.implicitRole || !NAMED_LANDMARK_TAG_SET.has(ctx.tag)) return [];
2567
2675
  return requireAccessibleName(ctx);
2568
- },
2569
- { tags: [...NAMED_LANDMARK_TAGS] }
2676
+ }
2570
2677
  );
2571
2678
  var HTML_ARIA_RULES = [
2572
2679
  landmarkRoleRule,
2573
- landmarkNameAdvisory,
2680
+ landmarkAccessibleNameRule,
2574
2681
  roleNotPermittedRule,
2575
2682
  ...INPUT_RULES
2576
2683
  ];
2577
2684
 
2578
- // ../core/src/html/contracts.ts
2685
+ // ../core/src/html/contracts/helpers.ts
2579
2686
  import { warnDiagnostics } from "../_shared/diagnostics.js";
2687
+ function isVNodeLike(child) {
2688
+ return isObject(child) && "type" in child;
2689
+ }
2580
2690
  function isOpenContent(...blockedTags) {
2581
2691
  const set2 = new Set(blockedTags);
2582
2692
  return (child) => {
2583
- if (!isObject(child) || !("type" in child)) return false;
2693
+ if (!isVNodeLike(child)) return false;
2584
2694
  const tag = getTag(child);
2585
2695
  return tag === void 0 || !set2.has(tag);
2586
2696
  };
2587
2697
  }
2588
- var METADATA_TAGS = ["script", "template"];
2589
2698
  var metadataMatch = isTag(...METADATA_TAGS);
2590
2699
  function metadata(name = "metadata") {
2591
2700
  return { name, match: metadataMatch };
2592
2701
  }
2702
+ function optional(name, tag) {
2703
+ return { name, match: isTag(tag), cardinality: { max: 1 } };
2704
+ }
2593
2705
  function firstOptional(name, tag) {
2594
- return { name, match: isTag(tag), cardinality: { max: 1 }, position: "first" };
2706
+ return { ...optional(name, tag), position: "first" };
2595
2707
  }
2596
2708
  function contract(children, options) {
2597
2709
  return { diagnostics: warnDiagnostics, children, ...options };
@@ -2605,50 +2717,41 @@ function ariaContract(aria) {
2605
2717
  function firstChildContract(name, tag) {
2606
2718
  return contract([firstOptional(name, tag), { name: "content", match: isOpenContent(tag) }]);
2607
2719
  }
2608
- var VOID_TAGS = [
2609
- "area",
2610
- "base",
2611
- "br",
2612
- "col",
2613
- "embed",
2614
- "hr",
2615
- "img",
2616
- "input",
2617
- "link",
2618
- "meta",
2619
- "param",
2620
- "source",
2621
- "track",
2622
- "wbr"
2623
- ];
2624
- var TEXT_ONLY_TAGS = ["option", "script", "style", "textarea", "title"];
2625
- var LANDMARK_TAGS = ["article", "aside", "footer", "header", "main", "nav"];
2626
- var listContract = closedContract([
2627
- { name: "list-item", match: isTag("li", ...METADATA_TAGS) }
2628
- ]);
2629
- var tableContract = closedContract([
2630
- firstOptional("caption", "caption"),
2631
- { name: "colgroup", match: isTag("colgroup") },
2632
- { name: "thead", match: isTag("thead"), cardinality: { max: 1 } },
2633
- { name: "tbody", match: isTag("tbody") },
2634
- { name: "tfoot", match: isTag("tfoot"), cardinality: { max: 1 } },
2635
- { name: "table-row", match: isTag("tr", ...METADATA_TAGS) }
2636
- ]);
2637
- var tableBodyContract = closedContract([
2638
- { name: "table-row", match: isTag("tr", ...METADATA_TAGS) }
2639
- ]);
2640
- var tableRowContract = closedContract([
2641
- { name: "table-cell", match: isTag("td", "th", ...METADATA_TAGS) }
2642
- ]);
2643
- var colgroupContract = closedContract([
2644
- { name: "column", match: isTag("col", "template") }
2720
+ function getChildProp(child, key) {
2721
+ if (!isVNodeLike(child)) return void 0;
2722
+ const { props } = child;
2723
+ if (!isObject(props)) return void 0;
2724
+ return props[key];
2725
+ }
2726
+
2727
+ // ../core/src/html/contracts/aria/landmarks.ts
2728
+ var landmarkContract = ariaContract([landmarkRoleRule, landmarkAccessibleNameRule]);
2729
+
2730
+ // ../core/src/html/contracts/aria/widgets.ts
2731
+ var dialogContract = ariaContract([requireAccessibleName]);
2732
+ var menuContract = ariaContract([requireAccessibleName]);
2733
+ var menubarContract = ariaContract([requireAccessibleName]);
2734
+ var treeContract = ariaContract([requireAccessibleName]);
2735
+ var gridContract = ariaContract([requireAccessibleName]);
2736
+ var listboxContract = ariaContract([requireAccessibleName]);
2737
+ var tablistContract = ariaContract([requireAccessibleName]);
2738
+ var radiogroupContract = ariaContract([requireAccessibleName]);
2739
+
2740
+ // ../core/src/html/contracts/html/document.ts
2741
+ var headContract = closedContract([
2742
+ {
2743
+ name: "metadata",
2744
+ match: isTag("base", "link", "meta", "noscript", "script", "style", "template", "title")
2745
+ }
2645
2746
  ]);
2646
- var dlContract = closedContract([
2647
- { name: "term", match: isTag("dt") },
2648
- { name: "description", match: isTag("dd") },
2649
- { name: "group", match: isTag("div") },
2650
- metadata()
2747
+ var htmlContract = closedContract([
2748
+ { name: "head", match: isTag("head"), cardinality: { min: 1, max: 1 }, position: "first" },
2749
+ { name: "body", match: isTag("body"), cardinality: { min: 1, max: 1 } }
2651
2750
  ]);
2751
+ var voidContract = contract([], { exclusiveChildren: true, allowText: false });
2752
+ var textOnlyContract = contract([], { exclusiveChildren: true });
2753
+
2754
+ // ../core/src/html/contracts/html/forms.ts
2652
2755
  var selectContract = closedContract([
2653
2756
  { name: "option", match: isTag("option", "optgroup", "hr", ...METADATA_TAGS) }
2654
2757
  ]);
@@ -2658,6 +2761,59 @@ var optgroupContract = closedContract([
2658
2761
  var datalistContract = closedContract([
2659
2762
  { name: "option", match: isTag("option", ...METADATA_TAGS) }
2660
2763
  ]);
2764
+ var buttonContract = closedContract([
2765
+ { name: "content", match: isOpenContent(...INTERACTIVE_CONTENT_TAGS) }
2766
+ ]);
2767
+ var anchorContract = closedContract([
2768
+ { name: "content", match: isOpenContent(...INTERACTIVE_CONTENT_TAGS) }
2769
+ ]);
2770
+ var labelableTagMatch = isTag(...LABELABLE_TAGS);
2771
+ function isLabelableControl(child) {
2772
+ if (!labelableTagMatch(child)) return false;
2773
+ if (getTag(child) !== "input") return true;
2774
+ const type = getChildProp(child, "type");
2775
+ return !isString(type) || type !== "hidden";
2776
+ }
2777
+ function hasAccessibleNameProp(props) {
2778
+ return "aria-label" in props || "aria-labelledby" in props;
2779
+ }
2780
+ function isNonEmptyTextChild(child) {
2781
+ if (isNumber(child)) return true;
2782
+ return isString(child) && child.trim().length > 0;
2783
+ }
2784
+ var labelContract = contract([
2785
+ { name: "control", match: isLabelableControl, cardinality: { max: 1 } },
2786
+ { name: "nested-label", match: isTag("label"), cardinality: { max: 0 } },
2787
+ {
2788
+ name: "other-interactive-content",
2789
+ match: isTag(...OTHER_INTERACTIVE_TAGS),
2790
+ cardinality: { max: 0 }
2791
+ },
2792
+ {
2793
+ name: "accessible-name",
2794
+ match: isNonEmptyTextChild,
2795
+ cardinality: dynamic(
2796
+ (ctx) => hasAccessibleNameProp(ctx.props) ? { min: 0 } : { min: 1 }
2797
+ )
2798
+ }
2799
+ ]);
2800
+
2801
+ // ../core/src/html/contracts/html/grouping.ts
2802
+ var detailsContract = firstChildContract("summary", "summary");
2803
+ var fieldsetContract = firstChildContract("legend", "legend");
2804
+
2805
+ // ../core/src/html/contracts/html/lists.ts
2806
+ var listContract = closedContract([
2807
+ { name: "list-item", match: isTag("li", ...METADATA_TAGS) }
2808
+ ]);
2809
+ var dlContract = closedContract([
2810
+ { name: "term", match: isTag("dt") },
2811
+ { name: "description", match: isTag("dd") },
2812
+ { name: "group", match: isTag("div") },
2813
+ metadata()
2814
+ ]);
2815
+
2816
+ // ../core/src/html/contracts/html/media.ts
2661
2817
  var pictureContract = closedContract([
2662
2818
  { name: "source", match: isTag("source", ...METADATA_TAGS) },
2663
2819
  { name: "image", match: isTag("img"), cardinality: { min: 1, max: 1 }, position: "last" }
@@ -2666,91 +2822,49 @@ var figureContract = contract([
2666
2822
  { name: "caption", match: isTag("figcaption"), cardinality: { max: 1 } },
2667
2823
  { name: "content", match: isOpenContent("figcaption") }
2668
2824
  ]);
2669
- var detailsContract = firstChildContract("summary", "summary");
2670
- var fieldsetContract = firstChildContract("legend", "legend");
2671
2825
  var objectContract = contract([
2672
2826
  { name: "param", match: isTag("param") },
2673
2827
  { name: "content", match: isOpenContent("param") }
2674
2828
  ]);
2675
- var INTERACTIVE_CONTENT_TAGS = ["a", "button", "input", "select", "textarea", "label"];
2676
- var buttonContract = closedContract([
2677
- { name: "content", match: isOpenContent(...INTERACTIVE_CONTENT_TAGS) }
2678
- ]);
2679
- var anchorContract = closedContract([
2680
- { name: "content", match: isOpenContent(...INTERACTIVE_CONTENT_TAGS) }
2681
- ]);
2682
- var LABELABLE_TAGS = [
2683
- "button",
2684
- "input",
2685
- "meter",
2686
- "output",
2687
- "progress",
2688
- "select",
2689
- "textarea"
2690
- ];
2691
- var labelContract = contract([
2692
- { name: "control", match: isTag(...LABELABLE_TAGS), cardinality: { max: 1 } }
2693
- ]);
2694
- var P_BLOCKED_TAGS = [
2695
- "address",
2696
- "article",
2697
- "aside",
2698
- "blockquote",
2699
- "details",
2700
- "dialog",
2701
- "div",
2702
- "dl",
2703
- "fieldset",
2704
- "figure",
2705
- "footer",
2706
- "form",
2707
- "h1",
2708
- "h2",
2709
- "h3",
2710
- "h4",
2711
- "h5",
2712
- "h6",
2713
- "header",
2714
- "hr",
2715
- "main",
2716
- "nav",
2717
- "ol",
2718
- "p",
2719
- "pre",
2720
- "section",
2721
- "table",
2722
- "ul"
2723
- ];
2724
- var pContract = closedContract([
2725
- { name: "content", match: isOpenContent(...P_BLOCKED_TAGS) }
2726
- ]);
2727
2829
  var mediaContract = contract([
2728
2830
  { name: "source", match: isTag("source") },
2729
2831
  { name: "track", match: isTag("track") },
2730
2832
  metadata(),
2731
2833
  { name: "content", match: isOpenContent("source", "track", ...METADATA_TAGS) }
2732
2834
  ]);
2733
- var headContract = closedContract([
2734
- {
2735
- name: "metadata",
2736
- match: isTag("base", "link", "meta", "noscript", "script", "style", "template", "title")
2737
- }
2835
+
2836
+ // ../core/src/html/contracts/html/tables.ts
2837
+ var tableContract = closedContract([
2838
+ firstOptional("caption", "caption"),
2839
+ { name: "colgroup", match: isTag("colgroup") },
2840
+ { name: "thead", match: isTag("thead"), cardinality: { max: 1 } },
2841
+ { name: "tbody", match: isTag("tbody") },
2842
+ { name: "tfoot", match: isTag("tfoot"), cardinality: { max: 1 } },
2843
+ { name: "table-row", match: isTag("tr", ...METADATA_TAGS) }
2738
2844
  ]);
2739
- var htmlContract = closedContract([
2740
- { name: "head", match: isTag("head"), cardinality: { min: 1, max: 1 }, position: "first" },
2741
- { name: "body", match: isTag("body"), cardinality: { min: 1, max: 1 } }
2845
+ var tableBodyContract = closedContract([
2846
+ { name: "table-row", match: isTag("tr", ...METADATA_TAGS) }
2742
2847
  ]);
2743
- var voidContract = contract([], { exclusiveChildren: true, allowText: false });
2744
- var textOnlyContract = contract([], { exclusiveChildren: true });
2745
- var landmarkContract = ariaContract([landmarkRoleRule, landmarkNameAdvisory]);
2746
- var dialogContract = ariaContract([requireAccessibleName]);
2747
- var menuContract = ariaContract([requireAccessibleName]);
2748
- var menubarContract = ariaContract([requireAccessibleName]);
2749
- var treeContract = ariaContract([requireAccessibleName]);
2750
- var gridContract = ariaContract([requireAccessibleName]);
2751
- var listboxContract = ariaContract([requireAccessibleName]);
2752
- var tablistContract = ariaContract([requireAccessibleName]);
2753
- var radiogroupContract = ariaContract([requireAccessibleName]);
2848
+ var tableRowContract = closedContract([
2849
+ { name: "table-cell", match: isTag("td", "th", ...METADATA_TAGS) }
2850
+ ]);
2851
+ var colgroupContract = closedContract([
2852
+ { name: "column", match: isTag("col", "template") }
2853
+ ]);
2854
+
2855
+ // ../core/src/html/contracts/html/text.ts
2856
+ var pContract = closedContract([
2857
+ { name: "content", match: isOpenContent(...P_BLOCKED_TAGS) }
2858
+ ]);
2859
+
2860
+ // ../core/src/html/contracts/build-map.ts
2861
+ function buildMap(groups) {
2862
+ return Object.fromEntries(
2863
+ groups.flatMap(([keys2, value]) => keys2.map((key) => [key, value]))
2864
+ );
2865
+ }
2866
+
2867
+ // ../core/src/html/contracts/maps.ts
2754
2868
  var CONTRACT_GROUPS = [
2755
2869
  [VOID_TAGS, voidContract],
2756
2870
  [TEXT_ONLY_TAGS, textOnlyContract],
@@ -2759,13 +2873,8 @@ var CONTRACT_GROUPS = [
2759
2873
  [["audio", "video"], mediaContract],
2760
2874
  [["thead", "tbody", "tfoot"], tableBodyContract]
2761
2875
  ];
2762
- function contractMap(groups) {
2763
- return Object.fromEntries(
2764
- groups.flatMap(([tags, enforcement]) => tags.map((tag) => [tag, enforcement]))
2765
- );
2766
- }
2767
2876
  var htmlContracts = {
2768
- ...contractMap(CONTRACT_GROUPS),
2877
+ ...buildMap(CONTRACT_GROUPS),
2769
2878
  table: tableContract,
2770
2879
  tr: tableRowContract,
2771
2880
  colgroup: colgroupContract,
@@ -3532,7 +3641,7 @@ function createContractComponent(options) {
3532
3641
  if (bundle.childrenEvaluator) {
3533
3642
  bundle.childrenEvaluator.evaluate(children, { tag, props: normalizedProps });
3534
3643
  }
3535
- bundle.runtime.options.htmlChildrenEvaluatorFn?.(tag)?.evaluate(children);
3644
+ bundle.runtime.options.htmlChildrenEvaluatorFn?.(tag)?.evaluate(children, { tag, props: normalizedProps });
3536
3645
  return html`<slot></slot>`;
3537
3646
  }
3538
3647
  }
@@ -196,8 +196,8 @@ type AriaContext = {
196
196
  readonly props: ReadonlyDeep<IntrinsicProps>;
197
197
  };
198
198
 
199
- type RemoveAttributeFixKind = `removeAttribute:${string}`;
200
- type InjectLiveFixKind = `injectLive:${string}`;
199
+ type RemoveAttributeFixKind = 'removeAttribute';
200
+ type InjectLiveFixKind = 'injectLive';
201
201
  type FixKind = 'removeRole' | 'setRole' | 'normalizeRelevantAll' | RemoveAttributeFixKind | InjectLiveFixKind;
202
202
 
203
203
  type AriaFixResult = {
@@ -210,6 +210,9 @@ type AriaFixResult = {
210
210
  };
211
211
  type AriaFix = {
212
212
  readonly kind: FixKind;
213
+ /** The attribute a `'removeAttribute'`/`'injectLive'` fix targets — always set for those
214
+ * kinds, absent for kinds with no single-attribute target (`'removeRole'`, etc.). */
215
+ readonly attribute?: string;
213
216
  readonly priority?: number;
214
217
  readonly source?: string;
215
218
  readonly apply: (context: AriaContext) => AriaFixResult;