@heartlandone/vega 2.95.0 → 2.96.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.
Files changed (181) hide show
  1. package/dist/cjs/{app-globals-76815382.js → app-globals-38afea36.js} +7 -7
  2. package/dist/cjs/{code-block-493c7ce7.js → code-block-4126dc3b.js} +1501 -55
  3. package/dist/cjs/{component-value-history-controller-slimmer.abstract-ab21fcbf.js → component-value-history-controller-slimmer.abstract-38ba956e.js} +2 -2
  4. package/dist/cjs/{content-state-fc34a814.js → content-state-50e8a03c.js} +142 -580
  5. package/dist/cjs/{element-appender-slimmer-1d6323c2.js → element-appender-slimmer-7773fdab.js} +115 -0
  6. package/dist/cjs/{image-annotation-action-7c4cd316.js → image-annotation-action-89363de8.js} +2 -2
  7. package/dist/cjs/{image-extension-30a7c10f.js → image-extension-c881c454.js} +2 -2
  8. package/dist/cjs/index.cjs.js +10 -10
  9. package/dist/cjs/{link-extension-92a63cb7.js → link-extension-b7f99a52.js} +2 -2
  10. package/dist/cjs/loader.cjs.js +7 -7
  11. package/dist/cjs/{public-rules-9e1ea1d9.js → public-rules-72894208.js} +3 -3
  12. package/dist/cjs/{range-30219330.js → range-95d41dea.js} +1 -1
  13. package/dist/cjs/{rich-text-editor-required-rule-23bf7485.js → rich-text-editor-required-rule-4d6d2493.js} +1 -1
  14. package/dist/cjs/{split-cell-operation-43752212.js → split-cell-operation-70be116d.js} +2 -2
  15. package/dist/cjs/{token-extension-d123d9d0.js → token-extension-eb828948.js} +35 -11
  16. package/dist/cjs/vega-code-block.cjs.entry.js +3 -3
  17. package/dist/cjs/vega-date-picker_2.cjs.entry.js +1 -1
  18. package/dist/cjs/vega-dropdown_5.cjs.entry.js +27 -4
  19. package/dist/cjs/vega-env-manager-23b8b23c.js +2 -2
  20. package/dist/cjs/vega-popover_2.cjs.entry.js +1 -1
  21. package/dist/cjs/vega-rich-text-content.cjs.entry.js +58 -9
  22. package/dist/cjs/vega-rich-text-editor_4.cjs.entry.js +608 -90
  23. package/dist/cjs/vega-rich-text-table-properties_3.cjs.entry.js +3 -3
  24. package/dist/cjs/vega-section-title.cjs.entry.js +896 -14
  25. package/dist/cjs/vega-time-picker_2.cjs.entry.js +1 -1
  26. package/dist/cjs/vega-tooltip_2.cjs.entry.js +1 -1
  27. package/dist/cjs/vega.cjs.js +7 -7
  28. package/dist/collection/components/vega-combo-box/vega-combo-box.js +2 -2
  29. package/dist/collection/components/vega-dropdown/vega-dropdown.js +30 -7
  30. package/dist/collection/components/vega-input-select/vega-input-select.js +2 -2
  31. package/dist/collection/components/vega-rich-text-content/vega-rich-text-content.css +4 -0
  32. package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-delete-node-content-strategy.js +29 -0
  33. package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-delete-text-or-decorator-node-strategy.js +10 -1
  34. package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/block-transform-to-list-strategy.js +8 -3
  35. package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-annotation-strategy.abstract.js +60 -0
  36. package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-item-replace-nest-list-strategy.js +36 -4
  37. package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-items-strategy.abstract.js +27 -0
  38. package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-nest-items-strategy.js +74 -0
  39. package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-remove-list-item-strategy.js +81 -1
  40. package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-transform-selection.js +30 -0
  41. package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-transform-to-list-strategy.js +160 -9
  42. package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-transform-to-paragraph-strategy.js +376 -10
  43. package/dist/collection/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-unnest-items-strategy.js +104 -0
  44. package/dist/collection/components/vega-rich-text-editor/dto/actions/modify-content-action.abstract.js +2 -0
  45. package/dist/collection/components/vega-rich-text-editor/dto/actions/nest-list-items-action.js +12 -0
  46. package/dist/collection/components/vega-rich-text-editor/dto/actions/unnest-list-items-action.js +12 -0
  47. package/dist/collection/components/vega-rich-text-editor/dto/annotations/list-annotation.js +12 -0
  48. package/dist/collection/components/vega-rich-text-editor/dto/blocks/list-block.js +10 -1
  49. package/dist/collection/components/vega-rich-text-editor/dto/blocks/list-item-block.js +11 -3
  50. package/dist/collection/components/vega-rich-text-editor/dto/content-state.js +7 -1
  51. package/dist/collection/components/vega-rich-text-editor/dto/filter-styles-strategies/list-block/list-block-filter-styles-strategy.js +8 -4
  52. package/dist/collection/components/vega-rich-text-editor/dto/renderers/blocks/list-block-renderer.js +34 -1
  53. package/dist/collection/components/vega-rich-text-editor/dto/renderers/blocks/list-item-block-renderer.js +20 -3
  54. package/dist/collection/components/vega-rich-text-editor/extensions/table/annotation-handler/table-annotation-handler-base.js +25 -1
  55. package/dist/collection/components/vega-rich-text-editor/slimmers/controllers/helper/element-to-dto-strategy/li-to-rte-list-item-block-strategy.js +2 -0
  56. package/dist/collection/components/vega-rich-text-editor/slimmers/controllers/helper/input-event-handler/abstract-delete-content-handler.js +29 -0
  57. package/dist/collection/components/vega-rich-text-editor/slimmers/renderers/tools/bullets-numbers/bullets-numbers-toolbar-button-slimmer.js +30 -1
  58. package/dist/collection/components/vega-rich-text-editor/slimmers/renderers/tools/bullets-numbers/helper/abstract-list-keyboard-handler.js +204 -0
  59. package/dist/collection/components/vega-rich-text-editor/slimmers/renderers/tools/bullets-numbers/helper/list-shift-tab-outdent-handler.js +42 -0
  60. package/dist/collection/components/vega-rich-text-editor/slimmers/renderers/tools/bullets-numbers/helper/list-tab-indent-handler.js +34 -0
  61. package/dist/collection/components/vega-rich-text-editor/slimmers/renderers/tools/bullets-numbers/list-keyboard-slimmer.js +180 -0
  62. package/dist/collection/components/vega-section-title/slimmers/a11y-tree/build-section-title-a11y-tree.js +54 -0
  63. package/dist/collection/components/vega-section-title/slimmers/renderers/vega-section-title-renderer.js +4 -4
  64. package/dist/collection/components/vega-section-title/vega-section-title.js +18 -2
  65. package/dist/collection/helpers/a11y-tree/a11y-node-dto.js +210 -0
  66. package/dist/collection/helpers/a11y-tree/a11y-tree-applier.js +189 -0
  67. package/dist/collection/helpers/a11y-tree/a11y-tree.types.js +48 -0
  68. package/dist/collection/helpers/a11y-tree/strategies/baseline-strategy.js +78 -0
  69. package/dist/collection/helpers/a11y-tree/strategies/firefox-nvda-strategy.js +56 -0
  70. package/dist/collection/helpers/a11y-tree/strategies/webkit-voiceover-strategy.js +140 -0
  71. package/dist/collection/helpers/a11y-tree/strategy-resolver.js +172 -0
  72. package/dist/collection/helpers/slimmers/a11y-tree-slimmer.js +54 -0
  73. package/dist/collection/helpers/slimmers/element-appender/element-appender-slimmer.js +29 -0
  74. package/dist/collection/helpers/slimmers/element-appender/visibility-modifiers/clip-on-scroll-modifier.js +70 -0
  75. package/dist/collection/helpers/slimmers/element-appender/visibility-modifiers/visibility-modifier.interface.js +1 -0
  76. package/dist/collection/helpers/ui/element-appender.js +16 -0
  77. package/dist/esm/{app-globals-eafcc7a1.js → app-globals-d7b651c1.js} +7 -7
  78. package/dist/esm/{code-block-e12588fe.js → code-block-0a88b481.js} +1495 -51
  79. package/dist/esm/{component-value-history-controller-slimmer.abstract-4e8eb313.js → component-value-history-controller-slimmer.abstract-6846edfa.js} +2 -2
  80. package/dist/esm/{content-state-8032467a.js → content-state-79ca99e5.js} +105 -541
  81. package/dist/esm/{element-appender-slimmer-7fcb944b.js → element-appender-slimmer-73ad10ae.js} +115 -0
  82. package/dist/esm/{image-annotation-action-08a20d5e.js → image-annotation-action-bb299ef1.js} +2 -2
  83. package/dist/esm/{image-extension-b6c7e4a7.js → image-extension-48a96f98.js} +2 -2
  84. package/dist/esm/index.js +8 -8
  85. package/dist/esm/{link-extension-97fcb8fb.js → link-extension-09534514.js} +2 -2
  86. package/dist/esm/loader.js +7 -7
  87. package/dist/esm/{public-rules-c06f0d2a.js → public-rules-5eb03ef0.js} +3 -3
  88. package/dist/esm/{range-e999837f.js → range-d4deb7df.js} +1 -1
  89. package/dist/esm/{rich-text-editor-required-rule-71f8ee98.js → rich-text-editor-required-rule-5bbbce23.js} +1 -1
  90. package/dist/esm/{split-cell-operation-359f8082.js → split-cell-operation-7f3058ad.js} +2 -2
  91. package/dist/esm/{token-extension-f5bf9c21.js → token-extension-40c32bcc.js} +30 -6
  92. package/dist/esm/vega-code-block.entry.js +3 -3
  93. package/dist/esm/vega-date-picker_2.entry.js +1 -1
  94. package/dist/esm/vega-dropdown_5.entry.js +27 -4
  95. package/dist/esm/vega-env-manager-8f8dc473.js +2 -2
  96. package/dist/esm/vega-popover_2.entry.js +1 -1
  97. package/dist/esm/vega-rich-text-content.entry.js +58 -9
  98. package/dist/esm/vega-rich-text-editor_4.entry.js +604 -86
  99. package/dist/esm/vega-rich-text-table-properties_3.entry.js +3 -3
  100. package/dist/esm/vega-section-title.entry.js +897 -15
  101. package/dist/esm/vega-time-picker_2.entry.js +1 -1
  102. package/dist/esm/vega-tooltip_2.entry.js +1 -1
  103. package/dist/esm/vega.js +7 -7
  104. package/dist/sri/vega-sri-manifest.json +94 -94
  105. package/dist/types/components/vega-combo-box/vega-combo-box.d.ts +6 -6
  106. package/dist/types/components/vega-dropdown/types.d.ts +2 -2
  107. package/dist/types/components/vega-dropdown/vega-dropdown.d.ts +32 -9
  108. package/dist/types/components/vega-input-select/vega-input-select.d.ts +6 -6
  109. package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-annotation-strategy.abstract.d.ts +36 -0
  110. package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-item-replace-nest-list-strategy.d.ts +14 -2
  111. package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-items-strategy.abstract.d.ts +22 -0
  112. package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-nest-items-strategy.d.ts +21 -0
  113. package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-remove-list-item-strategy.d.ts +14 -0
  114. package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-transform-selection.d.ts +15 -0
  115. package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-transform-to-list-strategy.d.ts +30 -3
  116. package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-transform-to-paragraph-strategy.d.ts +99 -3
  117. package/dist/types/components/vega-rich-text-editor/dto/action-handle-strategies/modify-content-strategies/list-unnest-items-strategy.d.ts +22 -0
  118. package/dist/types/components/vega-rich-text-editor/dto/actions/modify-content-action.abstract.d.ts +2 -0
  119. package/dist/types/components/vega-rich-text-editor/dto/actions/nest-list-items-action.d.ts +11 -0
  120. package/dist/types/components/vega-rich-text-editor/dto/actions/unnest-list-items-action.d.ts +11 -0
  121. package/dist/types/components/vega-rich-text-editor/dto/annotations/list-annotation.d.ts +8 -0
  122. package/dist/types/components/vega-rich-text-editor/dto/blocks/list-block.d.ts +6 -1
  123. package/dist/types/components/vega-rich-text-editor/dto/blocks/list-item-block.d.ts +5 -1
  124. package/dist/types/components/vega-rich-text-editor/dto/content-state.d.ts +2 -2
  125. package/dist/types/components/vega-rich-text-editor/dto/renderers/blocks/list-block-renderer.d.ts +2 -0
  126. package/dist/types/components/vega-rich-text-editor/dto/renderers/blocks/list-item-block-renderer.d.ts +8 -0
  127. package/dist/types/components/vega-rich-text-editor/extensions/table/annotation-handler/table-annotation-handler-base.d.ts +18 -0
  128. package/dist/types/components/vega-rich-text-editor/slimmers/renderers/tools/bullets-numbers/bullets-numbers-toolbar-button-slimmer.d.ts +8 -0
  129. package/dist/types/components/vega-rich-text-editor/slimmers/renderers/tools/bullets-numbers/helper/abstract-list-keyboard-handler.d.ts +99 -0
  130. package/dist/types/components/vega-rich-text-editor/slimmers/renderers/tools/bullets-numbers/helper/list-shift-tab-outdent-handler.d.ts +15 -0
  131. package/dist/types/components/vega-rich-text-editor/slimmers/renderers/tools/bullets-numbers/helper/list-tab-indent-handler.d.ts +15 -0
  132. package/dist/types/components/vega-rich-text-editor/slimmers/renderers/tools/bullets-numbers/list-keyboard-slimmer.d.ts +73 -0
  133. package/dist/types/components/vega-section-title/slimmers/a11y-tree/build-section-title-a11y-tree.d.ts +41 -0
  134. package/dist/types/components/vega-section-title/vega-section-title.d.ts +9 -0
  135. package/dist/types/components.d.ts +10 -10
  136. package/dist/types/helpers/a11y-tree/a11y-node-dto.d.ts +173 -0
  137. package/dist/types/helpers/a11y-tree/a11y-tree-applier.d.ts +28 -0
  138. package/dist/types/helpers/a11y-tree/a11y-tree.types.d.ts +137 -0
  139. package/dist/types/helpers/a11y-tree/strategies/baseline-strategy.d.ts +18 -0
  140. package/dist/types/helpers/a11y-tree/strategies/firefox-nvda-strategy.d.ts +16 -0
  141. package/dist/types/helpers/a11y-tree/strategies/webkit-voiceover-strategy.d.ts +23 -0
  142. package/dist/types/helpers/a11y-tree/strategy-resolver.d.ts +59 -0
  143. package/dist/types/helpers/slimmers/a11y-tree-slimmer.d.ts +49 -0
  144. package/dist/types/helpers/slimmers/element-appender/element-appender-slimmer.d.ts +9 -0
  145. package/dist/types/helpers/slimmers/element-appender/visibility-modifiers/clip-on-scroll-modifier.d.ts +37 -0
  146. package/dist/types/helpers/slimmers/element-appender/visibility-modifiers/visibility-modifier.interface.d.ts +56 -0
  147. package/dist/types/helpers/ui/element-appender.d.ts +7 -0
  148. package/dist/vega/index.esm.js +1 -1
  149. package/dist/vega/{p-9c39f90b.entry.js → p-1dfbc542.entry.js} +1 -1
  150. package/dist/vega/{p-e235020b.entry.js → p-22cc174e.entry.js} +1 -1
  151. package/dist/vega/{p-b187b82d.entry.js → p-2df5d59b.entry.js} +1 -1
  152. package/dist/vega/{p-f7e459cd.js → p-312d8205.js} +1 -1
  153. package/dist/vega/{p-a7209700.js → p-3345d903.js} +1 -1
  154. package/dist/vega/{p-02355de8.js → p-3c23ec90.js} +1 -1
  155. package/dist/vega/p-55e0014a.js +3 -0
  156. package/dist/vega/p-5f377954.js +1 -1
  157. package/dist/vega/p-65fee02f.entry.js +1 -0
  158. package/dist/vega/p-6a51d720.js +1 -0
  159. package/dist/vega/{p-fe24b459.js → p-6c7b6d45.js} +1 -1
  160. package/dist/vega/{p-579cdeae.js → p-84b7a775.js} +1 -1
  161. package/dist/vega/{p-df828d90.entry.js → p-96da7d30.entry.js} +1 -1
  162. package/dist/vega/{p-88be9ec5.js → p-9d3f69cb.js} +1 -1
  163. package/dist/vega/{p-8a001caa.js → p-9f11b579.js} +1 -1
  164. package/dist/vega/{p-ba2b9663.entry.js → p-acaff62d.entry.js} +1 -1
  165. package/dist/vega/p-b63319e9.entry.js +1 -0
  166. package/dist/vega/{p-c079c935.entry.js → p-b660f38c.entry.js} +1 -1
  167. package/dist/vega/p-b8ffa42f.entry.js +1 -0
  168. package/dist/vega/{p-4fe40b76.js → p-c4564904.js} +1 -1
  169. package/dist/vega/p-d9158512.js +1 -0
  170. package/dist/vega/p-e62d41ee.js +1 -0
  171. package/dist/vega/{p-9f7154d2.js → p-ec5dee32.js} +1 -1
  172. package/dist/vega/{p-05d04c07.entry.js → p-f29d9707.entry.js} +1 -1
  173. package/dist/vega/vega.esm.js +1 -1
  174. package/package.json +3 -2
  175. package/dist/vega/p-0be4df0a.js +0 -1
  176. package/dist/vega/p-38c9d782.js +0 -1
  177. package/dist/vega/p-513bc0d9.js +0 -1
  178. package/dist/vega/p-8d4b85e7.entry.js +0 -1
  179. package/dist/vega/p-c5d3b008.entry.js +0 -1
  180. package/dist/vega/p-d25ca0c3.entry.js +0 -1
  181. package/dist/vega/p-f4da615a.js +0 -3
@@ -0,0 +1,140 @@
1
+ import { baselineStrategy } from './baseline-strategy';
2
+ /**
3
+ * WebKit + VoiceOver strategy.
4
+ *
5
+ * Applies on top of the baseline to work around two known VoiceOver quirks:
6
+ *
7
+ * **Quirk #1 — `aria-describedby` on non-focusable containers is skipped.**
8
+ * VoiceOver on Safari often does not read `aria-describedby` on non-focusable
9
+ * `role="group"` (A11yContainerNode) or `role="region"` (A11yLandmarkNode)
10
+ * containers. Workaround: fold the description text directly into the
11
+ * heading's `aria-label` (joined with `. `) so it is read together with the
12
+ * title, and remove the orphaned `aria-describedby` patch.
13
+ *
14
+ * **Quirk #2 — Decorative `<vega-icon>` announced twice.**
15
+ * Safari occasionally announces a decorative icon twice when only
16
+ * `aria-hidden` is set on the host. We additionally set `role="none"` as a
17
+ * belt-and-suspenders guard that suppresses the extra announcement.
18
+ *
19
+ * These adjustments are applied as a *diff* on top of the baseline patch
20
+ * list — the A11y Tree itself is unchanged. Other node types fall back to
21
+ * baseline behaviour.
22
+ */
23
+ export const webkitVoiceOverStrategy = {
24
+ name: 'webkit-voiceover',
25
+ /**
26
+ * Compile ARIA patches, applying the two VoiceOver workarounds.
27
+ *
28
+ * @param {A11yNode} root - Root of the semantic A11y Tree to compile.
29
+ * @returns {AriaPatch[]} ARIA patches adjusted for WebKit + VoiceOver.
30
+ */
31
+ compile(root) {
32
+ var _a;
33
+ const patches = baselineStrategy.compile(root);
34
+ // Quirk #1: fold each described container's description into its heading's
35
+ // aria-label. The non-focusable-container quirk affects both role="group"
36
+ // (A11yContainerNode) and role="region" (A11yLandmarkNode). Generalized to
37
+ // iterate every described container so components with multiple described
38
+ // groups/regions all get folded correctly instead of only the first pair.
39
+ for (const container of collectDescribedContainers(root)) {
40
+ // Use the first heading owned by this container (not crossing nested
41
+ // described-container boundaries), or fall back to the container itself.
42
+ const heading = (_a = findOwnedHeading(container)) !== null && _a !== void 0 ? _a : container;
43
+ const combined = [heading.label, container.description].filter(Boolean).join('. ');
44
+ // Emit an explicit removal patch (value: null) for the container's
45
+ // aria-describedby. VoiceOver double-announces the description when it
46
+ // is both folded into the heading label AND referenced via
47
+ // aria-describedby, so we untrack the attribute declaratively (rather
48
+ // than silently dropping the patch) to keep re-render cleanup correct.
49
+ //
50
+ // When folding onto the container itself (no owned heading found), also
51
+ // update the existing aria-label patch in-place so we do not produce a
52
+ // duplicate patch that would leave the old value visible to consumers
53
+ // using Array.find().
54
+ const foldingOntoContainer = heading.id === container.id;
55
+ for (const p of patches) {
56
+ if (p.targetId === container.id && p.attribute === 'aria-describedby') {
57
+ p.value = null;
58
+ }
59
+ if (foldingOntoContainer && p.targetId === container.id && p.attribute === 'aria-label') {
60
+ p.value = combined;
61
+ }
62
+ }
63
+ if (!foldingOntoContainer) {
64
+ patches.push({ targetId: heading.id, attribute: 'aria-label', value: combined });
65
+ }
66
+ }
67
+ // Quirk #2: harden decorative icons with role="none".
68
+ walkIcons(root, (n) => {
69
+ if (n.decorative) {
70
+ patches.push({ targetId: n.id, attribute: 'role', value: 'none' });
71
+ }
72
+ });
73
+ return patches;
74
+ },
75
+ };
76
+ /**
77
+ * Find the first heading node owned directly by a described container,
78
+ * stopping at nested described-container boundaries.
79
+ *
80
+ * A heading "owned" by a container is one that lives in that container's
81
+ * direct subtree but NOT inside a nested described group/region. Those inner
82
+ * headings belong to the inner container's own fold pass, so crossing their
83
+ * boundary would cause the outer container's description to overwrite the
84
+ * inner heading's aria-label and then be lost when the inner pass runs.
85
+ *
86
+ * If no owned heading is found, the caller falls back to the container itself
87
+ * (the `?? container` in compile()), folding the description onto the
88
+ * container's own aria-label.
89
+ *
90
+ * @param {A11yNode} node - The container to search within.
91
+ * @returns {A11yNode | undefined} First heading owned by this container, if any.
92
+ */
93
+ function findOwnedHeading(node) {
94
+ var _a;
95
+ for (const c of (_a = node.children) !== null && _a !== void 0 ? _a : []) {
96
+ // Stop at nested described-container boundaries — their headings belong
97
+ // to those containers' own fold passes, not this one.
98
+ if ((c.role === 'group' || c.role === 'region') && c.description) {
99
+ continue;
100
+ }
101
+ if (c.role === 'heading')
102
+ return c;
103
+ const hit = findOwnedHeading(c);
104
+ if (hit)
105
+ return hit;
106
+ }
107
+ return undefined;
108
+ }
109
+ /**
110
+ * Visit every image node in the tree, invoking the callback on each.
111
+ *
112
+ * @param {A11yNode} node - Node to walk from.
113
+ * @param {(n: A11yNode) => void} fn - Callback invoked for each image node.
114
+ */
115
+ function walkIcons(node, fn) {
116
+ var _a;
117
+ if (node.role === 'img')
118
+ fn(node);
119
+ (_a = node.children) === null || _a === void 0 ? void 0 : _a.forEach((c) => walkIcons(c, fn));
120
+ }
121
+ /**
122
+ * Collect every `group` or `region` node in the tree that carries a
123
+ * description, in depth-first order. Includes nested described containers.
124
+ *
125
+ * @param {A11yNode} node - Node to search from.
126
+ * @returns {A11yNode[]} All described container nodes, including nested ones.
127
+ */
128
+ function collectDescribedContainers(node) {
129
+ var _a;
130
+ const out = [];
131
+ // Check if this node is a described container
132
+ if ((node.role === 'group' || node.role === 'region') && node.description) {
133
+ out.push(node);
134
+ }
135
+ // Always recurse into children to find nested described containers
136
+ for (const c of (_a = node.children) !== null && _a !== void 0 ? _a : []) {
137
+ out.push(...collectDescribedContainers(c));
138
+ }
139
+ return out;
140
+ }
@@ -0,0 +1,172 @@
1
+ import { baselineStrategy } from './strategies/baseline-strategy';
2
+ import { firefoxNvdaStrategy } from './strategies/firefox-nvda-strategy';
3
+ import { webkitVoiceOverStrategy } from './strategies/webkit-voiceover-strategy';
4
+ /**
5
+ * All registered strategies. The resolver picks from this list; callers that
6
+ * need exhaustive enumeration (e.g. tests, Storybook knobs) can import this
7
+ * constant directly.
8
+ */
9
+ export const ALL_A11Y_STRATEGIES = [
10
+ baselineStrategy,
11
+ webkitVoiceOverStrategy,
12
+ firefoxNvdaStrategy,
13
+ ];
14
+ /**
15
+ * Picks an `A11yTreeStrategy` from the runtime environment and returns the
16
+ * full `A11yStrategyResolution` including confidence and a reason string.
17
+ *
18
+ * ## Browser-engine detection
19
+ *
20
+ * AT cannot be detected from JS (user privacy). We branch on *browser engine*
21
+ * as a coarse proxy for the most likely AT pairing on each platform:
22
+ *
23
+ * | Engine | Assumed AT | Confidence |
24
+ * |-----------|------------------------------|-------------------------|
25
+ * | WebKit | VoiceOver (macOS/iOS) | medium on Apple, low elsewhere |
26
+ * | Gecko | NVDA (Win), Orca (Linux) | medium on Win32, low elsewhere |
27
+ * | Chromium | JAWS / NVDA / TalkBack | high on non-Apple, medium on Apple |
28
+ *
29
+ * An explicit `data-a11y-strategy` attribute on the host element is always
30
+ * treated as `high` confidence (known override). If the override value does
31
+ * not match any registered strategy name, the resolver falls back to baseline
32
+ * with `low` confidence and logs an actionable warning.
33
+ *
34
+ * @param {HTMLElement} [host] - The component host element. When provided, its
35
+ * `data-a11y-strategy` attribute is checked first.
36
+ * @returns {A11yStrategyResolution} The resolved strategy with confidence and reason.
37
+ */
38
+ export function resolveStrategyDetailed(host) {
39
+ var _a, _b;
40
+ // Explicit override takes precedence over UA detection.
41
+ const override = (_a = host === null || host === void 0 ? void 0 : host.getAttribute('data-a11y-strategy')) !== null && _a !== void 0 ? _a : null;
42
+ if (override) {
43
+ const found = ALL_A11Y_STRATEGIES.find((s) => s.name === override);
44
+ if (found) {
45
+ return {
46
+ strategy: found,
47
+ confidence: 'high',
48
+ reason: `explicit override via data-a11y-strategy="${override}"`,
49
+ };
50
+ }
51
+ // Unknown override name — warn and fall back to baseline.
52
+ return {
53
+ strategy: baselineStrategy,
54
+ confidence: 'low',
55
+ reason: `unknown data-a11y-strategy="${override}"; known strategies: ${ALL_A11Y_STRATEGIES.map((s) => s.name).join(', ')}. Falling back to baseline.`,
56
+ };
57
+ }
58
+ // Read the runtime navigator explicitly from `globalThis` (not the bare
59
+ // `navigator` identifier, which build tooling may substitute). Delegate the
60
+ // pure UA→strategy mapping to `resolveStrategyFromEnv` so it can be unit
61
+ // tested deterministically without mocking globals.
62
+ const nav = globalThis.navigator;
63
+ return resolveStrategyFromEnv(nav === null || nav === void 0 ? void 0 : nav.userAgent, (_b = nav === null || nav === void 0 ? void 0 : nav.platform) !== null && _b !== void 0 ? _b : '');
64
+ }
65
+ /**
66
+ * Pure UA→strategy mapping. Separated from `resolveStrategyDetailed` so the
67
+ * browser-engine detection table can be unit tested deterministically by
68
+ * passing explicit `userAgent` / `platform` values instead of mocking the
69
+ * global `navigator` (which build/test tooling may sandbox).
70
+ *
71
+ * @param {string | undefined} userAgent - The `navigator.userAgent` string, or
72
+ * `undefined` for an SSR / non-browser environment.
73
+ * @param {string} platform - The `navigator.platform` string (empty string when
74
+ * unavailable).
75
+ * @returns {A11yStrategyResolution} The resolved strategy with confidence and reason.
76
+ */
77
+ export function resolveStrategyFromEnv(userAgent, platform) {
78
+ // SSR / non-browser environment: no UA available.
79
+ if (userAgent === undefined) {
80
+ return {
81
+ strategy: baselineStrategy,
82
+ confidence: 'medium',
83
+ reason: 'no navigator (SSR or non-browser environment); baseline assumed',
84
+ };
85
+ }
86
+ const ua = userAgent;
87
+ // Order matters: Safari UA contains "Safari" but Chrome UA also does.
88
+ if (/\bFirefox\//.test(ua)) {
89
+ // Firefox + NVDA is the canonical pairing on Windows; on other
90
+ // platforms (macOS VoiceOver, Linux Orca, Windows JAWS) this is a
91
+ // probabilistic guess.
92
+ const isWindows = /Win/i.test(platform);
93
+ return {
94
+ strategy: firefoxNvdaStrategy,
95
+ confidence: isWindows ? 'medium' : 'low',
96
+ reason: isWindows
97
+ ? 'Firefox on Windows — assumed NVDA (most common pairing on Win32)'
98
+ : 'Firefox on non-Windows platform — AT pairing is a guess (may be Orca, VoiceOver, or JAWS)',
99
+ };
100
+ }
101
+ if (/^((?!chrome|android).)*safari/i.test(ua)) {
102
+ const isApple = /Mac|iPhone|iPad|iPod/i.test(platform);
103
+ return {
104
+ strategy: webkitVoiceOverStrategy,
105
+ confidence: isApple ? 'medium' : 'low',
106
+ reason: isApple
107
+ ? 'WebKit on Apple platform — assumed VoiceOver'
108
+ : 'WebKit on non-Apple platform — AT pairing is a guess',
109
+ };
110
+ }
111
+ // Chromium (Edge/Chrome). On macOS, Chromium routes through VoiceOver's
112
+ // accessibility tree; baseline covers most users but VoiceOver quirks may
113
+ // surface. Surfaced as medium confidence so the override path stays
114
+ // discoverable.
115
+ const onApple = /Mac|iPhone|iPad|iPod/i.test(platform);
116
+ return {
117
+ strategy: baselineStrategy,
118
+ confidence: onApple ? 'medium' : 'high',
119
+ reason: onApple
120
+ ? 'Chromium on Apple platform — VoiceOver may diverge from Chromium baseline'
121
+ : 'Chromium on non-Apple platform — baseline is the expected AT mapping',
122
+ };
123
+ }
124
+ /**
125
+ * Convenience wrapper for callers that only need the resolved strategy.
126
+ * Equivalent to `resolveStrategyDetailed(host).strategy` but additionally
127
+ * emits a **dev-mode console warning** for `low`-confidence resolutions,
128
+ * pointing engineers at the `data-a11y-strategy` override mechanism.
129
+ *
130
+ * The warning is rate-limited per `(strategyName, reason)` tuple to avoid
131
+ * log spam on every render cycle.
132
+ *
133
+ * @param {HTMLElement} [host] - The component host element (optional). Used for
134
+ * the `data-a11y-strategy` override check.
135
+ * @returns {A11yTreeStrategy} The resolved strategy.
136
+ */
137
+ export function resolveStrategy(host) {
138
+ const resolution = resolveStrategyDetailed(host);
139
+ if (resolution.confidence === 'low') {
140
+ warnOnce(resolution.strategy.name, resolution.reason);
141
+ }
142
+ return resolution.strategy;
143
+ }
144
+ const warnedKeys = new Set();
145
+ /**
146
+ * Emit a console.warn once per (strategy, reason) tuple. Suppressed in
147
+ * production builds and when `console` is unavailable (SSR).
148
+ *
149
+ * @param {string} strategyName - Name of the resolved strategy.
150
+ * @param {string} reason - Human-readable reason for the resolution.
151
+ * @internal
152
+ */
153
+ function warnOnce(strategyName, reason) {
154
+ var _a, _b;
155
+ if (typeof console === 'undefined')
156
+ return;
157
+ // Only warn in dev mode. Production builds set NODE_ENV=production;
158
+ // the guard below also handles minified bundles where `process` may
159
+ // be undefined.
160
+ const env = (_b = (_a = globalThis.process) === null || _a === void 0 ? void 0 : _a.env) === null || _b === void 0 ? void 0 : _b.NODE_ENV;
161
+ if (env === 'production')
162
+ return;
163
+ const key = `${strategyName}::${reason}`;
164
+ if (warnedKeys.has(key))
165
+ return;
166
+ warnedKeys.add(key);
167
+ console.warn(`[vega a11y-tree] Low-confidence strategy resolution: using "${strategyName}". ` +
168
+ `Reason: ${reason}. ` +
169
+ `Pin via data-a11y-strategy="<strategy-name>" to silence this warning ` +
170
+ `when you know the correct AT pairing. ` +
171
+ `Known strategies: ${ALL_A11Y_STRATEGIES.map((s) => s.name).join(', ')}.`);
172
+ }
@@ -0,0 +1,54 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { MapToComponentField, MapToComponentMethod, VegaSlimmer } from 'vega-slimmer/core';
8
+ import { applyA11yTree } from '../a11y-tree/a11y-tree-applier';
9
+ /**
10
+ * Generic A11y Tree slimmer.
11
+ *
12
+ * Hooks `componentDidRender` and projects the component's semantic A11y
13
+ * Tree onto its shadow DOM using the strategy resolved for the current
14
+ * browser engine.
15
+ *
16
+ * ## Opt-in steps for a component
17
+ *
18
+ * 1. Tag render targets with `data-a11y-id="<stable-id>"` in the renderer.
19
+ * 2. Author a `build<Component>A11yTree(host)` function (see
20
+ * `a11y-node-dto.ts` for the DTO helpers that make this ergonomic).
21
+ * 3. Inject this slimmer with `@InjectVegaSlimmer()`:
22
+ *
23
+ * ```ts
24
+ * @InjectVegaSlimmer()
25
+ * protected a11yTreeSlimmer = new A11yTreeSlimmer<HTMLVegaFooElement>(
26
+ * host => buildFooA11yTree({ title: host.title, description: host.description }),
27
+ * );
28
+ * ```
29
+ *
30
+ * The slimmer handles strategy selection, patch application, and cleanup
31
+ * on every subsequent render.
32
+ *
33
+ * @template T - The concrete `HTMLElement` subtype for the component host.
34
+ */
35
+ export class A11yTreeSlimmer extends VegaSlimmer {
36
+ constructor(buildA11yTree) {
37
+ super();
38
+ this.buildA11yTree = buildA11yTree;
39
+ }
40
+ /**
41
+ * Called by Stencil after each render. Projects the semantic A11y Tree
42
+ * onto the shadow DOM via the resolved browser-engine strategy.
43
+ */
44
+ projectA11yTree() {
45
+ const tree = this.buildA11yTree(this.host);
46
+ applyA11yTree(tree, this.host);
47
+ }
48
+ }
49
+ __decorate([
50
+ MapToComponentField()
51
+ ], A11yTreeSlimmer.prototype, "host", void 0);
52
+ __decorate([
53
+ MapToComponentMethod('componentDidRender')
54
+ ], A11yTreeSlimmer.prototype, "projectA11yTree", null);
@@ -16,10 +16,12 @@ import { HoverTriggerStrategy } from './trigger-strategies/hover-trigger-strateg
16
16
  import { NoneTriggerStrategy } from './trigger-strategies/none-trigger-strategy';
17
17
  import { isEATriggerStrategy } from '../../../types/type-guard';
18
18
  import { tryGetDocument } from '../../../utils/try-get-document';
19
+ import { ClipOnScrollModifier } from './visibility-modifiers/clip-on-scroll-modifier';
19
20
  export class ElementAppenderSlimmer extends VegaSlimmer {
20
21
  constructor(showConfigFactory, getTrigger, isDropdownShowName = 'isDropdownShow', disableInteractiveGetter = () => false) {
21
22
  super();
22
23
  this.hierarchyTreeManager = new ElementAppenderHierarchyTreeManager(this);
24
+ this.visibilityModifiers = [new ClipOnScrollModifier()];
23
25
  /**
24
26
  * It adds event listeners to the target and the appendable element
25
27
  */
@@ -125,6 +127,33 @@ export class ElementAppenderSlimmer extends VegaSlimmer {
125
127
  // itself, so no forced recalculation is needed there.
126
128
  const forceAdjust = !(e instanceof Event) || e.target !== tryGetDocument();
127
129
  (_a = this.elementAppender) === null || _a === void 0 ? void 0 : _a.onScroll(forceAdjust);
130
+ this.executeVisibilityModifiers({ kind: 'scroll', event: e });
131
+ }
132
+ };
133
+ /**
134
+ * Runs every enabled visibility modifier against the current show config and
135
+ * routes their actions to the appender. Modifiers are viewport-level,
136
+ * cross-cutting concerns that run in parallel with (not in place of) the
137
+ * selected trigger strategy — they only affect the appendable's visual
138
+ * clipping, never its logical open state.
139
+ */
140
+ this.executeVisibilityModifiers = (event) => {
141
+ if (!this.showConfig || !this.elementAppender)
142
+ return;
143
+ for (const modifier of this.visibilityModifiers) {
144
+ if (!modifier.isEnabled(this.showConfig))
145
+ continue;
146
+ const result = modifier.evaluate({
147
+ target: this.showConfig.target,
148
+ appendableElement: this.showConfig.appendableElement,
149
+ showConfig: this.showConfig,
150
+ currentState: { isVisible: this.isShowing() },
151
+ event,
152
+ });
153
+ if (result.nextAction === 'clip-hide')
154
+ this.elementAppender.setClipHidden(true);
155
+ else if (result.nextAction === 'clip-show')
156
+ this.elementAppender.setClipHidden(false);
128
157
  }
129
158
  };
130
159
  /* A timer that will hide the dropdown after a certain amount of time. */
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Returns the flattened-tree parent of a node so we can walk from inside a shadow
3
+ * tree up to the top-level document: assigned slot → parent element → shadow
4
+ * host.
5
+ *
6
+ * @param {Node} node - The node whose flattened-tree parent should be returned.
7
+ * @returns {HTMLElement | null} The flattened-tree parent, or null when the walk has reached the top.
8
+ */
9
+ export function flatParent(node) {
10
+ var _a;
11
+ const slot = (_a = node.assignedSlot) !== null && _a !== void 0 ? _a : null;
12
+ if (slot)
13
+ return slot;
14
+ const parent = node.parentElement;
15
+ if (parent)
16
+ return parent;
17
+ const root = node.getRootNode();
18
+ return root.host ? root.host : null;
19
+ }
20
+ /**
21
+ * Returns true when the trigger is clipped out of view by the visual viewport
22
+ * or by any scrollable ancestor.
23
+ *
24
+ * @param {HTMLElement} target - The trigger element to test against the viewport and scrollable ancestors.
25
+ * @returns {boolean} True when the trigger is clipped and the appendable should be hidden.
26
+ */
27
+ export function isTriggerClipped(target) {
28
+ const t = target.getBoundingClientRect();
29
+ const vw = window.innerWidth;
30
+ const vh = window.innerHeight;
31
+ if (t.bottom <= 0 || t.top >= vh || t.right <= 0 || t.left >= vw) {
32
+ return true;
33
+ }
34
+ let node = flatParent(target);
35
+ while (node) {
36
+ const style = getComputedStyle(node);
37
+ if (/(auto|scroll)/.test(style.overflowX + ' ' + style.overflowY)) {
38
+ const r = node.getBoundingClientRect();
39
+ if (t.bottom <= r.top || t.top >= r.bottom || t.right <= r.left || t.left >= r.right) {
40
+ return true;
41
+ }
42
+ }
43
+ node = flatParent(node);
44
+ }
45
+ return false;
46
+ }
47
+ /**
48
+ * Clip-hides an appendable while its trigger is scrolled out of view and
49
+ * restores it when the trigger returns, without touching the popup's logical
50
+ * open state. Applies to every appender consumer.
51
+ */
52
+ export class ClipOnScrollModifier {
53
+ /**
54
+ * @returns {boolean} Always true — geometry alone decides clip vs restore in `evaluate`.
55
+ */
56
+ isEnabled() {
57
+ return true;
58
+ }
59
+ /**
60
+ * Evaluates whether the appendable should be clip-hidden or restored based
61
+ * on the current trigger geometry.
62
+ *
63
+ * @param {VegaEAVisibilityContext} context - Evaluation context.
64
+ * @returns {VegaEAVisibilityResult} The next clip action.
65
+ */
66
+ evaluate(context) {
67
+ const clipped = isTriggerClipped(context.target);
68
+ return { nextAction: clipped ? 'clip-hide' : 'clip-show' };
69
+ }
70
+ }
@@ -111,6 +111,22 @@ export class ElementAppender {
111
111
  this.adjustPosition(true);
112
112
  }
113
113
  }
114
+ /**
115
+ * Toggles the appendable's visibility without changing its logical open
116
+ * state. Used to visually clip the popup when the trigger is out of view.
117
+ *
118
+ * @param {boolean} clipped - true to hide, false to show
119
+ */
120
+ setClipHidden(clipped) {
121
+ if (!this.showConfig)
122
+ return;
123
+ if (clipped) {
124
+ this.hideElementAppender(this.showConfig.appendableElement);
125
+ }
126
+ else {
127
+ this.showElementAppender(this.showConfig.appendableElement);
128
+ }
129
+ }
114
130
  /* istanbul ignore next */
115
131
  /**
116
132
  * It removes the z-index from the appendable element, removes the appendable element from the DOM, and
@@ -1,6 +1,6 @@
1
1
  import { F as FeatureFlag } from './feature-flag-controller-3fd04ea9.js';
2
- import { V as VegaLoader, a as VegaNotify, b as VegaEventManager, c as VegaZIndexManager, w as waitForVega, d as VegaSkeletonLoader, e as VegaTranslation, f as VegaRTETokenExtension, g as VegaRTELanguageExtension, h as VegaRTEDefaultLineHeightOptions, i as VegaRTEFunctionExtension, j as VegaRTETableExtension, k as VegaRTEHorizontalLineExtension, l as VegaRTEBlockquoteExtension, m as VegaRTESpecialCharactersExtension, n as VegaRTEFindReplaceExtension, o as VegaRTESpecialCharactersEssentials, p as VegaRTESpecialCharactersLatin, q as VegaRTESpecialCharactersMathematical, r as VegaRTESpecialCharactersArrows, s as VegaRTESpecialCharactersCurrency, t as VegaRTESpecialCharactersText, u as VegaRTELineHeightExtension, v as VegaRTEPasteExtension, x as VegaRTEFullscreenExtension, y as VegaRTECopyExtension, z as VegaRTECutExtension, A as VegaCalendarPeriodFactory } from './token-extension-f5bf9c21.js';
3
- import { V as VegaThemeManager } from './split-cell-operation-359f8082.js';
2
+ import { V as VegaLoader, a as VegaNotify, b as VegaEventManager, c as VegaZIndexManager, w as waitForVega, d as VegaSkeletonLoader, e as VegaTranslation, f as VegaRTETokenExtension, g as VegaRTELanguageExtension, h as VegaRTEDefaultLineHeightOptions, i as VegaRTEFunctionExtension, j as VegaRTETableExtension, k as VegaRTEHorizontalLineExtension, l as VegaRTEBlockquoteExtension, m as VegaRTESpecialCharactersExtension, n as VegaRTEFindReplaceExtension, o as VegaRTESpecialCharactersEssentials, p as VegaRTESpecialCharactersLatin, q as VegaRTESpecialCharactersMathematical, r as VegaRTESpecialCharactersArrows, s as VegaRTESpecialCharactersCurrency, t as VegaRTESpecialCharactersText, u as VegaRTELineHeightExtension, v as VegaRTEPasteExtension, x as VegaRTEFullscreenExtension, y as VegaRTECopyExtension, z as VegaRTECutExtension, A as VegaCalendarPeriodFactory } from './token-extension-40c32bcc.js';
3
+ import { V as VegaThemeManager } from './split-cell-operation-7f3058ad.js';
4
4
  import { M as MapToComponentMethod, V as VegaSlimmer, s as setVegaLogLevel, G as GlobalSlimmersRegistry } from './global-slimmer-registry-17c4efd4.js';
5
5
  import { V as VegaDialog } from './vega-dialog-controller-726b74f9.js';
6
6
  import { T as TypographyUrls } from './typography-19c3b9be.js';
@@ -12,12 +12,12 @@ import { U as UPDATE_TRANSLATION } from './static-subject-title-1c86e974.js';
12
12
  import { C as ChangeManager } from './change-manager-6a7eb88c.js';
13
13
  import { O as Observer } from './observer-3959f9dd.js';
14
14
  import { f as forceUpdate } from './index-090d31ca.js';
15
- import { V as VegaRTEContent } from './content-state-8032467a.js';
15
+ import { V as VegaRTEContent } from './content-state-79ca99e5.js';
16
16
  import { v as vegaNonceManager, s as setVegaNonce } from './vega-nonce-manager-497e5eb5.js';
17
- import { V as VegaRTEPresetToolbarItems } from './code-block-e12588fe.js';
18
- import { V as VegaRTELinkExtension } from './link-extension-97fcb8fb.js';
17
+ import { V as VegaRTEPresetToolbarItems } from './code-block-0a88b481.js';
18
+ import { V as VegaRTELinkExtension } from './link-extension-09534514.js';
19
19
  import './type-guard-ec5e8628.js';
20
- import { V as VegaRTEImageExtension } from './image-extension-b6c7e4a7.js';
20
+ import { V as VegaRTEImageExtension } from './image-extension-48a96f98.js';
21
21
 
22
22
  var __decorate$2 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
23
23
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -424,7 +424,7 @@ function injectVegaCalendarPeriodFactoryIntoGlobal() {
424
424
  * Inject VegaPublicValidationRules to global as a public api
425
425
  */
426
426
  function injectVegaPublicValidationRules() {
427
- void import('./public-rules-c06f0d2a.js').then((module) => {
427
+ void import('./public-rules-5eb03ef0.js').then((module) => {
428
428
  Object.entries(module).forEach(([name, value]) => {
429
429
  globalThis[name] = value;
430
430
  });