@globalpayments/vega 2.77.0 → 2.77.1

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 (338) hide show
  1. package/dist/cjs/{app-globals-04e7024b.js → app-globals-1021e33e.js} +6 -6
  2. package/dist/cjs/{aria-attributes-value-mapper-f58c73f8.js → aria-attributes-value-mapper-9a41b9cf.js} +10 -3
  3. package/dist/cjs/{code-block-f1480ec3.js → code-block-f9b86a25.js} +1 -1
  4. package/dist/cjs/{component-value-history-controller-slimmer.abstract-a9264cc8.js → component-value-history-controller-slimmer.abstract-6bcff70b.js} +3 -3
  5. package/dist/cjs/{date-required-rule-912469e0.js → date-required-rule-d3c2d088.js} +1 -1
  6. package/dist/cjs/{design-token-c49717c8.js → design-token-b21879b6.js} +2 -2
  7. package/dist/cjs/{dto-renderer-manager-809c947b.js → dto-renderer-manager-e2823eb8.js} +2 -2
  8. package/dist/cjs/{element-appender-slimmer-38583ca9.js → element-appender-slimmer-40d39bba.js} +178 -19
  9. package/dist/cjs/{form-field-controller-slimmer-102f37c7.js → form-field-controller-slimmer-1b3a1388.js} +1 -1
  10. package/dist/cjs/{image-annotation-action-8d9fa20c.js → image-annotation-action-b83283d4.js} +2 -2
  11. package/dist/cjs/index.cjs.js +12 -12
  12. package/dist/cjs/{inject-keyboard-manager-0f5bd568.js → inject-keyboard-manager-ea5c598e.js} +1 -1
  13. package/dist/cjs/{internal-translation-controller-053eb0f1.js → internal-translation-controller-1f84ab0a.js} +15 -0
  14. package/dist/cjs/{keyboard-manager-055e9f67.js → keyboard-manager-16494c34.js} +1 -1
  15. package/dist/cjs/{keyboard-manager-slimmer-0cc0c1c7.js → keyboard-manager-slimmer-5b8fa209.js} +1 -1
  16. package/dist/cjs/loader.cjs.js +8 -8
  17. package/dist/cjs/{month-view-generator-6a6dd527.js → month-view-generator-1a57578d.js} +1 -1
  18. package/dist/cjs/{public-rules-922849f3.js → public-rules-5bd1624d.js} +7 -7
  19. package/dist/cjs/{range-8aa49b08.js → range-7a038973.js} +1 -1
  20. package/dist/cjs/{responsive-format-facade-acc39a40.js → responsive-format-facade-0b65ce4a.js} +1 -1
  21. package/dist/cjs/{rich-text-editor-required-rule-22225840.js → rich-text-editor-required-rule-d984c0b6.js} +1 -1
  22. package/dist/cjs/{string-format-strategy.abstract-f2575647.js → string-format-strategy.abstract-714bfad2.js} +1 -1
  23. package/dist/cjs/{string-input-formatter-slimmer-0a334fc6.js → string-input-formatter-slimmer-9ef2ec7a.js} +1 -1
  24. package/dist/cjs/{string-mask-strategy-dda58395.js → string-mask-strategy-bd2c18df.js} +2 -2
  25. package/dist/cjs/{style-formatter-028af284.js → style-formatter-7a4e9811.js} +2 -2
  26. package/dist/cjs/{time-required-rule-d6fa7aa8.js → time-required-rule-50784b9f.js} +1 -1
  27. package/dist/cjs/{token-extension-ffcaeae0.js → token-extension-5a1c473e.js} +4 -4
  28. package/dist/cjs/{translation-slimmer-4533bd67.js → translation-slimmer-2c207e34.js} +1 -1
  29. package/dist/cjs/{type-guard-407ba0b8.js → type-guard-cd0376d4.js} +36 -1
  30. package/dist/cjs/{valid-credit-card-number-rule-41a8b51b.js → valid-credit-card-number-rule-3f8dc897.js} +1 -1
  31. package/dist/cjs/vega-accordion.cjs.entry.js +4 -4
  32. package/dist/cjs/vega-app-header-button.cjs.entry.js +24 -6
  33. package/dist/cjs/vega-box.cjs.entry.js +5 -5
  34. package/dist/cjs/vega-button-circle.cjs.entry.js +5 -5
  35. package/dist/cjs/vega-button-link.cjs.entry.js +16 -0
  36. package/dist/cjs/vega-button.cjs.entry.js +3 -3
  37. package/dist/cjs/vega-calendar_4.cjs.entry.js +5 -5
  38. package/dist/cjs/vega-card.cjs.entry.js +4 -4
  39. package/dist/cjs/vega-carousel.cjs.entry.js +3 -3
  40. package/dist/cjs/vega-checkbox_2.cjs.entry.js +2 -2
  41. package/dist/cjs/vega-chip.cjs.entry.js +4 -4
  42. package/dist/cjs/vega-code-block.cjs.entry.js +8 -8
  43. package/dist/cjs/vega-color-picker.cjs.entry.js +2 -2
  44. package/dist/cjs/vega-combo-box.cjs.entry.js +5 -5
  45. package/dist/cjs/vega-date-picker_2.cjs.entry.js +103 -22
  46. package/dist/cjs/vega-dialog_2.cjs.entry.js +4 -4
  47. package/dist/cjs/vega-divider.cjs.entry.js +4 -4
  48. package/dist/cjs/vega-dropdown_5.cjs.entry.js +31 -7
  49. package/dist/cjs/vega-env-manager-23b8b23c.js +2 -2
  50. package/dist/cjs/vega-file-uploader.cjs.entry.js +3 -3
  51. package/dist/cjs/vega-flag-icon.cjs.entry.js +4 -4
  52. package/dist/cjs/vega-flex.cjs.entry.js +5 -5
  53. package/dist/cjs/vega-font.cjs.entry.js +4 -4
  54. package/dist/cjs/vega-form.cjs.entry.js +3 -3
  55. package/dist/cjs/vega-grid.cjs.entry.js +4 -4
  56. package/dist/cjs/vega-icon.cjs.entry.js +4 -4
  57. package/dist/cjs/vega-image-uploader.cjs.entry.js +5 -5
  58. package/dist/cjs/vega-input-credit-card.cjs.entry.js +6 -6
  59. package/dist/cjs/vega-input-numeric.cjs.entry.js +5 -5
  60. package/dist/cjs/vega-input-passcode.cjs.entry.js +37 -7
  61. package/dist/cjs/vega-input-phone-number.cjs.entry.js +4 -4
  62. package/dist/cjs/vega-input-range.cjs.entry.js +3 -3
  63. package/dist/cjs/vega-input-select.cjs.entry.js +5 -5
  64. package/dist/cjs/vega-input.cjs.entry.js +220 -125
  65. package/dist/cjs/vega-left-nav_5.cjs.entry.js +6 -7
  66. package/dist/cjs/vega-loader-wrapper_2.cjs.entry.js +3 -3
  67. package/dist/cjs/vega-pagination-page-size-selector-mobile.cjs.entry.js +2 -2
  68. package/dist/cjs/vega-pagination.cjs.entry.js +4 -4
  69. package/dist/cjs/vega-popover_2.cjs.entry.js +8 -8
  70. package/dist/cjs/vega-progress-tracker_2.cjs.entry.js +3 -3
  71. package/dist/cjs/vega-radio_2.cjs.entry.js +5 -5
  72. package/dist/cjs/vega-rich-text-content.cjs.entry.js +12 -6
  73. package/dist/cjs/vega-rich-text-editor_4.cjs.entry.js +127 -29
  74. package/dist/cjs/vega-selection-chip_2.cjs.entry.js +4 -4
  75. package/dist/cjs/vega-selection-tile_2.cjs.entry.js +2 -2
  76. package/dist/cjs/vega-sidenav_3.cjs.entry.js +3 -3
  77. package/dist/cjs/vega-signature-capture.cjs.entry.js +6 -6
  78. package/dist/cjs/vega-stepper.cjs.entry.js +2 -2
  79. package/dist/cjs/vega-table_11.cjs.entry.js +4 -4
  80. package/dist/cjs/vega-textarea.cjs.entry.js +2 -2
  81. package/dist/cjs/vega-time-picker_2.cjs.entry.js +9 -9
  82. package/dist/cjs/vega-toggle-switch.cjs.entry.js +2 -2
  83. package/dist/cjs/vega-tooltip_2.cjs.entry.js +7 -7
  84. package/dist/cjs/vega.cjs.js +8 -8
  85. package/dist/collection/components/vega-app-header-button/vega-app-header-button.js +44 -2
  86. package/dist/collection/components/vega-button-link/vega-button-link.js +16 -1
  87. package/dist/collection/components/vega-calendar/slimmers/common/renderers/vega-calendar-event-preview-popover-renderer.js +1 -1
  88. package/dist/collection/components/vega-date-picker/slimmers/controllers/vega-date-picker-calendar-open-state-controller.js +64 -0
  89. package/dist/collection/components/vega-date-picker/vega-date-picker-calendar/slimmers/controllers/vega-date-picker-calendar-selection-controller.js +3 -0
  90. package/dist/collection/components/vega-date-picker/vega-date-picker-calendar/slimmers/renderers/vega-date-picker-calendar-header-render.js +3 -3
  91. package/dist/collection/components/vega-date-picker/vega-date-picker-calendar/slimmers/renderers/vega-date-picker-calendar-renderer.js +19 -1
  92. package/dist/collection/components/vega-date-picker/vega-date-picker-calendar/slimmers/renderers/vega-date-picker-calendar-year-month-switcher-renderer.js +3 -2
  93. package/dist/collection/components/vega-date-picker/vega-date-picker-calendar/slimmers/renderers/vega-date-picker-month-item-renderer.js +3 -2
  94. package/dist/collection/components/vega-date-picker/vega-date-picker-calendar/vega-date-picker-calendar.css +12 -0
  95. package/dist/collection/components/vega-dropdown/slimmers/controllers/vega-dropdown-appender-controller.js +25 -0
  96. package/dist/collection/components/vega-input/slimmers/controllers/vega-input-render-mode-controller.js +1 -3
  97. package/dist/collection/components/vega-input/slimmers/renderers/vega-input-input-container-renderer.js +1 -5
  98. package/dist/collection/components/vega-input/slimmers/renderers/vega-input-input-renderer.js +1 -4
  99. package/dist/collection/components/vega-input/slimmers/renderers/vega-input-input-suggestions-renderer.js +5 -2
  100. package/dist/collection/components/vega-input/vega-input.js +24 -1
  101. package/dist/collection/components/vega-input-passcode/slimmers/controllers/vega-input-passcode-keyboard-controller.js +2 -0
  102. package/dist/collection/components/vega-input-passcode/slimmers/renderers/vega-input-passcode-renderer.js +30 -2
  103. package/dist/collection/components/vega-nav/vega-left-nav-link/slimmers/renderers/vega-left-nav-link-renderer.js +2 -3
  104. package/dist/collection/components/vega-popover/vega-popover-content-box/vega-popover-content-box.css +5 -0
  105. package/dist/collection/components/vega-rich-text-editor/dto/renderers/nodes/image-node-renderer.js +7 -1
  106. package/dist/collection/components/vega-rich-text-editor/slimmers/controllers/insert-image-controller.js +7 -4
  107. package/dist/collection/components/vega-rich-text-editor/slimmers/renderers/tools/image-toolbar-button-slimmer.js +113 -12
  108. package/dist/collection/components/vega-rich-text-editor/vega-rich-text-image-editor/slimmers/renderers/vega-rich-text-image-editor-renderer.js +1 -1
  109. package/dist/collection/components/vega-tooltip/vega-tooltip-content-box/vega-tooltip-content-box.css +5 -0
  110. package/dist/collection/helpers/calendar/test/utils.test.js +54 -1
  111. package/dist/collection/helpers/calendar/utils.js +35 -0
  112. package/dist/collection/helpers/slimmers/element-appender/element-appender-slimmer.js +27 -0
  113. package/dist/collection/helpers/slimmers/element-appender/test/element-appender-slimmer.test.js +50 -0
  114. package/dist/collection/helpers/slimmers/mutation-observer/aria-attributes-value-mapper.js +10 -3
  115. package/dist/collection/helpers/slimmers/mutation-observer/data-tab-index-value-mapper.js +80 -0
  116. package/dist/collection/helpers/slimmers/mutation-observer/test/aria-attributes-value-mapper.test.js +55 -3
  117. package/dist/collection/helpers/slimmers/mutation-observer/test/data-tab-index-value-mapper.test.js +120 -0
  118. package/dist/collection/helpers/slimmers/position-calculation/base-position-calculation-strategy.js +123 -9
  119. package/dist/collection/helpers/slimmers/position-calculation/position-calculation-controller.js +14 -4
  120. package/dist/collection/helpers/slimmers/position-calculation/screen-position-calculation-strategy.js +13 -4
  121. package/dist/collection/helpers/slimmers/position-calculation/test/body-position-calculation-strategy.test.js +7 -6
  122. package/dist/collection/helpers/slimmers/position-calculation/test/screen-position-calculation-strategy.test.js +162 -7
  123. package/dist/collection/helpers/translation/locales/en.js +15 -0
  124. package/dist/collection/helpers/translation/tests/internal-translation-controller.test.js +15 -0
  125. package/dist/collection/helpers/ui/test/element-appender.test.js +7 -5
  126. package/dist/collection/utils/e2e-utils.js +6 -0
  127. package/dist/esm/{app-globals-32055795.js → app-globals-0b3b7111.js} +6 -6
  128. package/dist/esm/{aria-attributes-value-mapper-d4fef46a.js → aria-attributes-value-mapper-2c632641.js} +10 -3
  129. package/dist/esm/{code-block-b6247a45.js → code-block-2408a812.js} +1 -1
  130. package/dist/esm/{component-value-history-controller-slimmer.abstract-2bb8533d.js → component-value-history-controller-slimmer.abstract-ac40820f.js} +3 -3
  131. package/dist/esm/{date-required-rule-e771e7d9.js → date-required-rule-09d5aa16.js} +1 -1
  132. package/dist/esm/{design-token-5bc034e1.js → design-token-7dec1eab.js} +2 -2
  133. package/dist/esm/{dto-renderer-manager-6fd22ab7.js → dto-renderer-manager-d413de1e.js} +2 -2
  134. package/dist/esm/{element-appender-slimmer-9ea377d0.js → element-appender-slimmer-5d573612.js} +178 -19
  135. package/dist/esm/{form-field-controller-slimmer-5817d14d.js → form-field-controller-slimmer-e1a5a884.js} +1 -1
  136. package/dist/esm/{image-annotation-action-6701b4c9.js → image-annotation-action-54936eaa.js} +2 -2
  137. package/dist/esm/index.js +12 -12
  138. package/dist/esm/{inject-keyboard-manager-78730062.js → inject-keyboard-manager-9339bba8.js} +1 -1
  139. package/dist/esm/{internal-translation-controller-911515f9.js → internal-translation-controller-113a6288.js} +15 -0
  140. package/dist/esm/{keyboard-manager-38934f94.js → keyboard-manager-f9bfa678.js} +1 -1
  141. package/dist/esm/{keyboard-manager-slimmer-9984d922.js → keyboard-manager-slimmer-c8898843.js} +1 -1
  142. package/dist/esm/loader.js +8 -8
  143. package/dist/esm/{month-view-generator-eaf9029c.js → month-view-generator-160a9feb.js} +1 -1
  144. package/dist/esm/{public-rules-25cc3a39.js → public-rules-41561e6e.js} +7 -7
  145. package/dist/esm/{range-663f44dc.js → range-a5d78e69.js} +1 -1
  146. package/dist/esm/{responsive-format-facade-aa705823.js → responsive-format-facade-2a36c54a.js} +1 -1
  147. package/dist/esm/{rich-text-editor-required-rule-a238b862.js → rich-text-editor-required-rule-b09039da.js} +1 -1
  148. package/dist/esm/{string-format-strategy.abstract-713fba36.js → string-format-strategy.abstract-944f759b.js} +1 -1
  149. package/dist/esm/{string-input-formatter-slimmer-5b413ff9.js → string-input-formatter-slimmer-2508d88b.js} +1 -1
  150. package/dist/esm/{string-mask-strategy-6beaf664.js → string-mask-strategy-f9e252a2.js} +2 -2
  151. package/dist/esm/{style-formatter-28138f5c.js → style-formatter-6db1e890.js} +2 -2
  152. package/dist/esm/{time-required-rule-e4138a76.js → time-required-rule-c7cfb257.js} +1 -1
  153. package/dist/esm/{token-extension-73e4460a.js → token-extension-25df8dbb.js} +4 -4
  154. package/dist/esm/{translation-slimmer-2394b173.js → translation-slimmer-9f0339aa.js} +1 -1
  155. package/dist/esm/{type-guard-f50e34d6.js → type-guard-af324dcd.js} +36 -2
  156. package/dist/esm/{valid-credit-card-number-rule-22ce81db.js → valid-credit-card-number-rule-099dba7d.js} +1 -1
  157. package/dist/esm/vega-accordion.entry.js +4 -4
  158. package/dist/esm/vega-app-header-button.entry.js +24 -6
  159. package/dist/esm/vega-box.entry.js +5 -5
  160. package/dist/esm/vega-button-circle.entry.js +5 -5
  161. package/dist/esm/vega-button-link.entry.js +16 -0
  162. package/dist/esm/vega-button.entry.js +3 -3
  163. package/dist/esm/vega-calendar_4.entry.js +5 -5
  164. package/dist/esm/vega-card.entry.js +4 -4
  165. package/dist/esm/vega-carousel.entry.js +3 -3
  166. package/dist/esm/vega-checkbox_2.entry.js +2 -2
  167. package/dist/esm/vega-chip.entry.js +4 -4
  168. package/dist/esm/vega-code-block.entry.js +8 -8
  169. package/dist/esm/vega-color-picker.entry.js +2 -2
  170. package/dist/esm/vega-combo-box.entry.js +5 -5
  171. package/dist/esm/vega-date-picker_2.entry.js +104 -23
  172. package/dist/esm/vega-dialog_2.entry.js +4 -4
  173. package/dist/esm/vega-divider.entry.js +4 -4
  174. package/dist/esm/vega-dropdown_5.entry.js +32 -8
  175. package/dist/esm/vega-env-manager-8f8dc473.js +2 -2
  176. package/dist/esm/vega-file-uploader.entry.js +3 -3
  177. package/dist/esm/vega-flag-icon.entry.js +4 -4
  178. package/dist/esm/vega-flex.entry.js +5 -5
  179. package/dist/esm/vega-font.entry.js +4 -4
  180. package/dist/esm/vega-form.entry.js +3 -3
  181. package/dist/esm/vega-grid.entry.js +4 -4
  182. package/dist/esm/vega-icon.entry.js +4 -4
  183. package/dist/esm/vega-image-uploader.entry.js +5 -5
  184. package/dist/esm/vega-input-credit-card.entry.js +6 -6
  185. package/dist/esm/vega-input-numeric.entry.js +5 -5
  186. package/dist/esm/vega-input-passcode.entry.js +37 -7
  187. package/dist/esm/vega-input-phone-number.entry.js +4 -4
  188. package/dist/esm/vega-input-range.entry.js +3 -3
  189. package/dist/esm/vega-input-select.entry.js +5 -5
  190. package/dist/esm/vega-input.entry.js +220 -125
  191. package/dist/esm/vega-left-nav_5.entry.js +6 -7
  192. package/dist/esm/vega-loader-wrapper_2.entry.js +3 -3
  193. package/dist/esm/vega-pagination-page-size-selector-mobile.entry.js +2 -2
  194. package/dist/esm/vega-pagination.entry.js +4 -4
  195. package/dist/esm/vega-popover_2.entry.js +8 -8
  196. package/dist/esm/vega-progress-tracker_2.entry.js +3 -3
  197. package/dist/esm/vega-radio_2.entry.js +5 -5
  198. package/dist/esm/vega-rich-text-content.entry.js +12 -6
  199. package/dist/esm/vega-rich-text-editor_4.entry.js +128 -30
  200. package/dist/esm/vega-selection-chip_2.entry.js +4 -4
  201. package/dist/esm/vega-selection-tile_2.entry.js +2 -2
  202. package/dist/esm/vega-sidenav_3.entry.js +3 -3
  203. package/dist/esm/vega-signature-capture.entry.js +6 -6
  204. package/dist/esm/vega-stepper.entry.js +2 -2
  205. package/dist/esm/vega-table_11.entry.js +4 -4
  206. package/dist/esm/vega-textarea.entry.js +2 -2
  207. package/dist/esm/vega-time-picker_2.entry.js +9 -9
  208. package/dist/esm/vega-toggle-switch.entry.js +2 -2
  209. package/dist/esm/vega-tooltip_2.entry.js +7 -7
  210. package/dist/esm/vega.js +8 -8
  211. package/dist/sri/vega-sri-manifest.json +281 -281
  212. package/dist/types/components/vega-app-header-button/types.d.ts +18 -0
  213. package/dist/types/components/vega-app-header-button/vega-app-header-button.d.ts +8 -1
  214. package/dist/types/components/vega-button-link/vega-button-link.d.ts +2 -0
  215. package/dist/types/components/vega-date-picker/slimmers/controllers/vega-date-picker-calendar-open-state-controller.d.ts +21 -0
  216. package/dist/types/components/vega-date-picker/vega-date-picker-calendar/slimmers/controllers/vega-date-picker-calendar-selection-controller.d.ts +1 -0
  217. package/dist/types/components/vega-date-picker/vega-date-picker-calendar/slimmers/renderers/vega-date-picker-calendar-renderer.d.ts +7 -0
  218. package/dist/types/components/vega-dropdown/slimmers/controllers/vega-dropdown-appender-controller.d.ts +11 -0
  219. package/dist/types/components/vega-input/slimmers/controllers/vega-input-render-mode-controller.d.ts +0 -1
  220. package/dist/types/components/vega-input/slimmers/renderers/vega-input-input-renderer.d.ts +0 -1
  221. package/dist/types/components/vega-input/vega-input.d.ts +4 -0
  222. package/dist/types/components/vega-input-passcode/slimmers/renderers/vega-input-passcode-renderer.d.ts +14 -0
  223. package/dist/types/components/vega-rich-text-editor/slimmers/controllers/insert-image-controller.d.ts +7 -1
  224. package/dist/types/components/vega-rich-text-editor/slimmers/renderers/tools/image-toolbar-button-slimmer.d.ts +30 -2
  225. package/dist/types/components.d.ts +11 -1
  226. package/dist/types/helpers/calendar/utils.d.ts +17 -0
  227. package/dist/types/helpers/slimmers/element-appender/element-appender-slimmer.d.ts +12 -0
  228. package/dist/types/helpers/slimmers/mutation-observer/aria-attributes-value-mapper.d.ts +2 -1
  229. package/dist/types/helpers/slimmers/mutation-observer/data-tab-index-value-mapper.d.ts +35 -0
  230. package/dist/types/helpers/slimmers/mutation-observer/test/data-tab-index-value-mapper.test.d.ts +1 -0
  231. package/dist/types/helpers/slimmers/position-calculation/base-position-calculation-strategy.d.ts +60 -3
  232. package/dist/types/helpers/slimmers/position-calculation/screen-position-calculation-strategy.d.ts +3 -2
  233. package/dist/types/helpers/slimmers/position-calculation/test/body-position-calculation-strategy.test.d.ts +1 -1
  234. package/dist/types/helpers/translation/interface.d.ts +15 -0
  235. package/dist/types/types/components.type.d.ts +1 -0
  236. package/dist/types/types/ui.type.d.ts +3 -2
  237. package/dist/types/utils/e2e-utils.d.ts +2 -0
  238. package/dist/vega/index.esm.js +1 -1
  239. package/dist/vega/{p-4bffdb28.js → p-051bbce6.js} +1 -1
  240. package/dist/vega/{p-1a3236e7.entry.js → p-0ac9a732.entry.js} +1 -1
  241. package/dist/vega/{p-9fb877c1.entry.js → p-1033e4c4.entry.js} +1 -1
  242. package/dist/vega/{p-0e679d8c.js → p-10e51081.js} +1 -1
  243. package/dist/vega/p-15335b69.entry.js +1 -0
  244. package/dist/vega/{p-592296d7.entry.js → p-19270396.entry.js} +1 -1
  245. package/dist/vega/{p-2d69632d.js → p-1a9b361b.js} +1 -1
  246. package/dist/vega/p-1ccba615.entry.js +1 -0
  247. package/dist/vega/{p-b54dc37c.entry.js → p-22f3d35c.entry.js} +1 -1
  248. package/dist/vega/{p-010ff53d.entry.js → p-23427f6a.entry.js} +1 -1
  249. package/dist/vega/p-2466316a.js +1 -0
  250. package/dist/vega/{p-b1773281.entry.js → p-27b0af38.entry.js} +1 -1
  251. package/dist/vega/{p-03004a05.entry.js → p-2c2193f2.entry.js} +1 -1
  252. package/dist/vega/{p-22056609.entry.js → p-3237be8b.entry.js} +1 -1
  253. package/dist/vega/{p-bff57aa4.js → p-38e850c3.js} +1 -1
  254. package/dist/vega/{p-ffd48e37.entry.js → p-3b9fc697.entry.js} +1 -1
  255. package/dist/vega/{p-1fa0c7da.entry.js → p-41d14339.entry.js} +1 -1
  256. package/dist/vega/{p-a0b66c25.js → p-4c060ba9.js} +1 -1
  257. package/dist/vega/{p-0d4cb1c7.entry.js → p-4d4bf82a.entry.js} +1 -1
  258. package/dist/vega/{p-415ffa35.js → p-4d7d5583.js} +1 -1
  259. package/dist/vega/{p-2a10e2e5.js → p-4f146dae.js} +1 -1
  260. package/dist/vega/p-5f377954.js +1 -1
  261. package/dist/vega/{p-d78f6ede.js → p-600f7d6c.js} +1 -1
  262. package/dist/vega/{p-4ea30592.js → p-6188e783.js} +1 -1
  263. package/dist/vega/p-638d30a5.entry.js +1 -0
  264. package/dist/vega/{p-100b44c3.entry.js → p-67b0ccdc.entry.js} +1 -1
  265. package/dist/vega/p-68846f0d.js +1 -0
  266. package/dist/vega/{p-c165232c.entry.js → p-70444f6f.entry.js} +1 -1
  267. package/dist/vega/{p-e632475e.js → p-7127f966.js} +1 -1
  268. package/dist/vega/{p-49845a91.js → p-718c74ba.js} +1 -1
  269. package/dist/vega/p-77167587.entry.js +1 -0
  270. package/dist/vega/p-78ecfea0.entry.js +1 -0
  271. package/dist/vega/{p-b201f379.js → p-7cde8489.js} +1 -1
  272. package/dist/vega/p-9466619f.entry.js +1 -0
  273. package/dist/vega/p-9863e7a1.entry.js +1 -0
  274. package/dist/vega/p-999950d1.js +1 -0
  275. package/dist/vega/{p-9339c6c4.js → p-9a3a5b9e.js} +1 -1
  276. package/dist/vega/{p-1a011d47.entry.js → p-9adfcd47.entry.js} +1 -1
  277. package/dist/vega/{p-4aa94940.entry.js → p-9e36f7ff.entry.js} +1 -1
  278. package/dist/vega/{p-168bb296.entry.js → p-9f9d9a53.entry.js} +1 -1
  279. package/dist/vega/{p-cfecc1cb.entry.js → p-9feaac4b.entry.js} +1 -1
  280. package/dist/vega/{p-4742feef.entry.js → p-a0e69236.entry.js} +1 -1
  281. package/dist/vega/{p-95528b47.js → p-a17312a6.js} +1 -1
  282. package/dist/vega/{p-f3e6483c.js → p-a79fdf2f.js} +1 -1
  283. package/dist/vega/{p-c2d2faa0.js → p-a800bf6d.js} +1 -1
  284. package/dist/vega/{p-2b142818.entry.js → p-aaf9b39f.entry.js} +1 -1
  285. package/dist/vega/p-acbb96b3.entry.js +1 -0
  286. package/dist/vega/{p-cccd7648.entry.js → p-af2110fc.entry.js} +1 -1
  287. package/dist/vega/{p-560d2f48.entry.js → p-b35bb4a2.entry.js} +1 -1
  288. package/dist/vega/p-b8c10187.js +1 -0
  289. package/dist/vega/p-bdb5180c.js +1 -0
  290. package/dist/vega/{p-50d074ed.entry.js → p-c086529c.entry.js} +1 -1
  291. package/dist/vega/{p-3c05abd9.entry.js → p-c61bcd92.entry.js} +1 -1
  292. package/dist/vega/{p-5833f33b.entry.js → p-c7a9960f.entry.js} +1 -1
  293. package/dist/vega/{p-81b044b9.js → p-c7b9b7c2.js} +1 -1
  294. package/dist/vega/{p-f2b0b58a.js → p-c857e6e2.js} +1 -1
  295. package/dist/vega/{p-857069a5.entry.js → p-c871619c.entry.js} +1 -1
  296. package/dist/vega/{p-1f3cd061.entry.js → p-cbeb47be.entry.js} +1 -1
  297. package/dist/vega/{p-a786259a.js → p-cf6bfac7.js} +1 -1
  298. package/dist/vega/{p-5485c387.entry.js → p-d0975995.entry.js} +1 -1
  299. package/dist/vega/{p-c292ade4.entry.js → p-d2fc470e.entry.js} +1 -1
  300. package/dist/vega/{p-f428086c.entry.js → p-d70e1b75.entry.js} +1 -1
  301. package/dist/vega/{p-3afc025e.entry.js → p-da0fd3dc.entry.js} +1 -1
  302. package/dist/vega/{p-70df91fb.entry.js → p-da552ddf.entry.js} +1 -1
  303. package/dist/vega/{p-4aa52ed2.entry.js → p-ddce3e0e.entry.js} +1 -1
  304. package/dist/vega/{p-aa1174dc.js → p-dfb12762.js} +1 -1
  305. package/dist/vega/{p-daa60a59.entry.js → p-e0fb1f60.entry.js} +1 -1
  306. package/dist/vega/{p-db5fa164.entry.js → p-e1c017d1.entry.js} +1 -1
  307. package/dist/vega/{p-3ce2b05c.entry.js → p-e4c99b72.entry.js} +1 -1
  308. package/dist/vega/{p-d1cfe972.entry.js → p-e841c1fe.entry.js} +1 -1
  309. package/dist/vega/{p-0572c393.entry.js → p-ea96b0f9.entry.js} +1 -1
  310. package/dist/vega/{p-7425cedc.entry.js → p-eab9d999.entry.js} +1 -1
  311. package/dist/vega/{p-e6cf2ace.entry.js → p-ed9ad4fd.entry.js} +1 -1
  312. package/dist/vega/{p-34bcf4ed.entry.js → p-ef603656.entry.js} +1 -1
  313. package/dist/vega/p-f5fcd13e.entry.js +1 -0
  314. package/dist/vega/{p-6d219c44.entry.js → p-f65cb0b6.entry.js} +1 -1
  315. package/dist/vega/p-faa9a3bd.js +1 -0
  316. package/dist/vega/{p-a8792e3d.js → p-fc049028.js} +1 -1
  317. package/dist/vega/p-ff287001.entry.js +1 -0
  318. package/dist/vega/{p-67745549.entry.js → p-ffb3e479.entry.js} +1 -1
  319. package/dist/vega/p-ffd080db.js +1 -0
  320. package/dist/vega/vega.esm.js +1 -1
  321. package/package.json +1 -1
  322. package/dist/vega/p-43ff48c0.entry.js +0 -1
  323. package/dist/vega/p-464559e3.js +0 -1
  324. package/dist/vega/p-4bee4202.entry.js +0 -1
  325. package/dist/vega/p-5cfce62d.entry.js +0 -1
  326. package/dist/vega/p-60f77f5f.entry.js +0 -1
  327. package/dist/vega/p-641cdb5c.entry.js +0 -1
  328. package/dist/vega/p-6b6f0fb4.js +0 -1
  329. package/dist/vega/p-9441f2ba.entry.js +0 -1
  330. package/dist/vega/p-ac82b9f9.entry.js +0 -1
  331. package/dist/vega/p-b597393b.entry.js +0 -1
  332. package/dist/vega/p-b5f18f4b.entry.js +0 -1
  333. package/dist/vega/p-c3d2f316.js +0 -1
  334. package/dist/vega/p-cc5eaa1b.js +0 -1
  335. package/dist/vega/p-dad3ba5f.js +0 -1
  336. package/dist/vega/p-de64f6e6.js +0 -1
  337. package/dist/vega/p-e7fbef97.js +0 -1
  338. package/dist/vega/p-fc9ac6e9.entry.js +0 -1
@@ -173,6 +173,7 @@ export class ElementAppenderSlimmer extends VegaSlimmer {
173
173
  show() {
174
174
  this.elementAppender && this.elementAppender.show();
175
175
  this[this.isDropdownShowName] = true;
176
+ this.setAriaOwns();
176
177
  }
177
178
  hide() {
178
179
  this.elementAppender && this.elementAppender.hide();
@@ -182,6 +183,7 @@ export class ElementAppenderSlimmer extends VegaSlimmer {
182
183
  });
183
184
  }
184
185
  destroy() {
186
+ this.removeAriaOwns();
185
187
  this.destroyElementAppender();
186
188
  this[this.isDropdownShowName] = false;
187
189
  }
@@ -264,6 +266,31 @@ export class ElementAppenderSlimmer extends VegaSlimmer {
264
266
  return new NoneTriggerStrategy();
265
267
  }
266
268
  }
269
+ /**
270
+ * Sets `ariaOwnsElements` on the target element to reference the appendable element directly.
271
+ * Uses the Element Reflection API which works across shadow DOM boundaries by using
272
+ * direct element references instead of IDREF strings.
273
+ * This ensures screen readers (e.g. VoiceOver) can navigate to the portal-appended
274
+ * content immediately after the trigger, rather than at the end of the document.
275
+ */
276
+ setAriaOwns() {
277
+ if (this.showConfig) {
278
+ const target = this.showConfig.target;
279
+ const appendableElement = this.showConfig.appendableElement;
280
+ if (target && appendableElement) {
281
+ target.ariaOwnsElements = [appendableElement];
282
+ }
283
+ }
284
+ }
285
+ /**
286
+ * Removes `ariaOwnsElements` from the target element when the popup is hidden or destroyed.
287
+ */
288
+ removeAriaOwns() {
289
+ var _a;
290
+ if ((_a = this.showConfig) === null || _a === void 0 ? void 0 : _a.target) {
291
+ this.showConfig.target.ariaOwnsElements = [];
292
+ }
293
+ }
267
294
  }
268
295
  ElementAppenderSlimmer.DELAY_HIDE_TIME = 100;
269
296
  __decorate([
@@ -568,4 +568,54 @@ describe('ElementAppender slimmer test suite', () => {
568
568
  expect(child2.appendableElement).toHaveClass('vega-force-hidden');
569
569
  });
570
570
  });
571
+ describe('AriaOwns management', () => {
572
+ test('should set ariaOwnsElements on target when show is called', () => {
573
+ const mockedComponent = new MockedComponent();
574
+ const target = new MockHTMLElement('body', 'div');
575
+ const appendableElement = new MockHTMLElement('body', 'div');
576
+ appendableElement.classList.add('vega-force-hidden');
577
+ mockedComponent.target = target;
578
+ mockedComponent.appendableElement = appendableElement;
579
+ mockedComponent.componentDidLoad();
580
+ mockedComponent.show();
581
+ expect(target.ariaOwnsElements).toEqual([
582
+ appendableElement,
583
+ ]);
584
+ });
585
+ test('should remove ariaOwnsElements from target when destroy is called', () => {
586
+ const mockedComponent = new MockedComponent();
587
+ const target = new MockHTMLElement('body', 'div');
588
+ const appendableElement = new MockHTMLElement('body', 'div');
589
+ appendableElement.classList.add('vega-force-hidden');
590
+ mockedComponent.target = target;
591
+ mockedComponent.appendableElement = appendableElement;
592
+ mockedComponent.componentDidLoad();
593
+ mockedComponent.show();
594
+ expect(target.ariaOwnsElements).toEqual([
595
+ appendableElement,
596
+ ]);
597
+ mockedComponent.destroy();
598
+ expect(target.ariaOwnsElements).toEqual([]);
599
+ });
600
+ test('should not throw when show is called without showConfig', () => {
601
+ const mockedComponent = new MockedComponent();
602
+ mockedComponent.target = null;
603
+ mockedComponent.appendableElement = null;
604
+ spyOn(LogUtility, 'error');
605
+ mockedComponent.componentDidLoad();
606
+ expect(() => mockedComponent.show()).not.toThrow();
607
+ });
608
+ test('should not throw when destroy is called without target', () => {
609
+ const mockedComponent = new MockedComponent();
610
+ mockedComponent.target = null;
611
+ mockedComponent.appendableElement = null;
612
+ spyOn(LogUtility, 'error');
613
+ mockedComponent.componentDidLoad();
614
+ expect(() => mockedComponent.destroy()).not.toThrow();
615
+ });
616
+ test('should not throw when destroy is called before componentDidLoad', () => {
617
+ const mockedComponent = new MockedComponent();
618
+ expect(() => mockedComponent.destroy()).not.toThrow();
619
+ });
620
+ });
571
621
  });
@@ -102,7 +102,7 @@ export class AriaAttributesValueMapper extends MutationObserverSlimmer {
102
102
  }
103
103
  }
104
104
  if (finalValue === null || finalValue === undefined || String(finalValue).trim() === '') {
105
- finalValue = defaultValue !== null && defaultValue !== void 0 ? defaultValue : '';
105
+ finalValue = defaultValue;
106
106
  }
107
107
  try {
108
108
  if (String(finalValue).trim() === '') {
@@ -110,8 +110,15 @@ export class AriaAttributesValueMapper extends MutationObserverSlimmer {
110
110
  return;
111
111
  }
112
112
  const existing = target.getAttribute(ariaAttr);
113
- if (existing !== finalValue) {
114
- target.setAttribute(ariaAttr, finalValue);
113
+ if (finalValue === null || finalValue === undefined) {
114
+ if (existing !== null) {
115
+ target.removeAttribute(ariaAttr);
116
+ }
117
+ return;
118
+ }
119
+ const stringValue = String(finalValue);
120
+ if (existing !== stringValue) {
121
+ target.setAttribute(ariaAttr, stringValue);
115
122
  }
116
123
  }
117
124
  catch (e) {
@@ -0,0 +1,80 @@
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 { MapToComponentMethod } from 'vega-slimmer/core';
8
+ import { MutationObserverSlimmer } from './mutation-observer-slimmer';
9
+ /**
10
+ * Maps host data-tabindex to inner native input tabindex.
11
+ */
12
+ export class DataTabIndexValueMapper extends MutationObserverSlimmer {
13
+ /**
14
+ * Constructor for DataTabIndexValueMapper
15
+ *
16
+ * @param {() => HTMLElement} targetGetter - Function to get the target HTMLElement
17
+ */
18
+ constructor(targetGetter) {
19
+ super({
20
+ options: { attributes: true, attributeFilter: [DataTabIndexValueMapper.OBSERVED_ATTRIBUTE] },
21
+ // eslint-disable-next-line jsdoc/require-jsdoc
22
+ callback: () => {
23
+ this.performMapping();
24
+ },
25
+ });
26
+ this.targetGetter = targetGetter;
27
+ }
28
+ /**
29
+ * Component lifecycle - [componentDidLoad]
30
+ */
31
+ componentDidLoad() {
32
+ this.performMapping();
33
+ super.componentDidLoad && super.componentDidLoad();
34
+ }
35
+ /**
36
+ * Component lifecycle - [componentDidRender]
37
+ */
38
+ componentDidRender() {
39
+ this.performMapping();
40
+ }
41
+ /**
42
+ * Performs the mapping of host data-tabindex to target element's tabindex.
43
+ * If the host attribute value is null, undefined, or empty string, it removes the tabindex attribute from the target.
44
+ * Otherwise, it sets the target's tabindex to the host attribute value.
45
+ */
46
+ performMapping() {
47
+ const target = this.targetGetter ? this.targetGetter() : null;
48
+ if (!target)
49
+ return;
50
+ const hostValue = this.host.getAttribute(DataTabIndexValueMapper.OBSERVED_ATTRIBUTE);
51
+ if (this.shouldRemoveTabIndex(hostValue)) {
52
+ target.removeAttribute('tabindex');
53
+ return;
54
+ }
55
+ const tabIndexValue = String(hostValue);
56
+ if (target.getAttribute('tabindex') !== tabIndexValue) {
57
+ target.setAttribute('tabindex', tabIndexValue);
58
+ }
59
+ }
60
+ /**
61
+ * Determines whether the tabindex attribute should be removed from the target element.
62
+ *
63
+ * @param {string | null} hostValue - The value of the host element's data-tabindex attribute
64
+ * @returns {boolean} True if the tabindex should be removed, false otherwise
65
+ */
66
+ shouldRemoveTabIndex(hostValue) {
67
+ if (hostValue === null || hostValue === undefined) {
68
+ return true;
69
+ }
70
+ const normalizedValue = String(hostValue).trim().toLowerCase();
71
+ return normalizedValue === '' || normalizedValue === 'null' || normalizedValue === 'undefined';
72
+ }
73
+ }
74
+ DataTabIndexValueMapper.OBSERVED_ATTRIBUTE = 'data-tabindex';
75
+ __decorate([
76
+ MapToComponentMethod('componentDidLoad')
77
+ ], DataTabIndexValueMapper.prototype, "componentDidLoad", null);
78
+ __decorate([
79
+ MapToComponentMethod('componentDidRender')
80
+ ], DataTabIndexValueMapper.prototype, "componentDidRender", null);
@@ -168,7 +168,7 @@ describe('AriaAttributesValueMapper', () => {
168
168
  comp.componentDidLoad();
169
169
  }).not.toThrow();
170
170
  });
171
- it('should set empty string when no defaultValue provided', () => {
171
+ it('should omit aria attribute when no defaultValue provided', () => {
172
172
  const comp = new MockedComponent();
173
173
  const button = document.createElement('button');
174
174
  // no dependencies present on host and no defaultValue in map
@@ -177,8 +177,47 @@ describe('AriaAttributesValueMapper', () => {
177
177
  }));
178
178
  comp.connectedCallback();
179
179
  comp.componentDidLoad();
180
- // should set attribute to empty string when no defaultValue provided
181
- expect(button.getAttribute('aria-label')).toBe(null);
180
+ expect(button.hasAttribute('aria-label')).toBeFalsy();
181
+ });
182
+ it('should omit aria attribute when defaultValue is null', () => {
183
+ const comp = new MockedComponent();
184
+ const button = document.createElement('button');
185
+ comp.setMapper(new AriaAttributesValueMapper(() => button, {
186
+ 'aria-label': {
187
+ dependency: ['data-aria-label', 'label'],
188
+ defaultValue: null,
189
+ },
190
+ }));
191
+ comp.connectedCallback();
192
+ comp.componentDidLoad();
193
+ expect(button.hasAttribute('aria-label')).toBeFalsy();
194
+ });
195
+ it('should omit aria attribute when defaultValue is undefined', () => {
196
+ const comp = new MockedComponent();
197
+ const button = document.createElement('button');
198
+ comp.setMapper(new AriaAttributesValueMapper(() => button, {
199
+ 'aria-label': {
200
+ dependency: ['data-aria-label', 'label'],
201
+ defaultValue: undefined,
202
+ },
203
+ }));
204
+ comp.connectedCallback();
205
+ comp.componentDidLoad();
206
+ expect(button.hasAttribute('aria-label')).toBeFalsy();
207
+ });
208
+ it('should remove existing aria attribute when resolved value is undefined', () => {
209
+ const comp = new MockedComponent();
210
+ const button = document.createElement('button');
211
+ button.setAttribute('aria-label', 'legacy-value');
212
+ comp.setMapper(new AriaAttributesValueMapper(() => button, {
213
+ 'aria-label': {
214
+ dependency: ['data-aria-label', 'label'],
215
+ defaultValue: undefined,
216
+ },
217
+ }));
218
+ comp.connectedCallback();
219
+ comp.componentDidLoad();
220
+ expect(button.hasAttribute('aria-label')).toBeFalsy();
182
221
  });
183
222
  it('should handle empty mutations array (pass undefined to performMapping)', () => {
184
223
  const comp = new MockedComponent();
@@ -193,4 +232,17 @@ describe('AriaAttributesValueMapper', () => {
193
232
  MockedMutationObserver.mock.instances[0].trigger([]);
194
233
  expect(button.getAttribute('aria-label')).toBe('test');
195
234
  });
235
+ it('should be null for aria attribute when defaultValue is empty string', () => {
236
+ const comp = new MockedComponent();
237
+ const button = document.createElement('button');
238
+ comp.setMapper(new AriaAttributesValueMapper(() => button, {
239
+ 'aria-label': {
240
+ dependency: ['data-aria-label', 'label'],
241
+ defaultValue: '',
242
+ },
243
+ }));
244
+ comp.connectedCallback();
245
+ comp.componentDidLoad();
246
+ expect(button.getAttribute('aria-label')).toBe(null);
247
+ });
196
248
  });
@@ -0,0 +1,120 @@
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 { MockHTMLElement } from '@stencil/core/mock-doc';
8
+ import { InjectVegaSlimmer } from 'vega-slimmer/core';
9
+ import { MockedMutationObserver } from '../../../../utils/spec-utils';
10
+ import { DataTabIndexValueMapper } from '../data-tab-index-value-mapper';
11
+ describe('DataTabIndexValueMapper', () => {
12
+ beforeEach(() => {
13
+ global.MutationObserver = MockedMutationObserver;
14
+ MockedMutationObserver.mockClear();
15
+ });
16
+ class MockedComponent {
17
+ constructor() {
18
+ this.host = new MockHTMLElement('body', 'mocked-component');
19
+ }
20
+ connectedCallback() {
21
+ return;
22
+ }
23
+ componentDidLoad() {
24
+ return;
25
+ }
26
+ setMapper(mapper) {
27
+ this.dataTabIndexValueMapper = mapper;
28
+ }
29
+ }
30
+ __decorate([
31
+ InjectVegaSlimmer()
32
+ ], MockedComponent.prototype, "dataTabIndexValueMapper", void 0);
33
+ it('should map host data-tabindex to native input tabindex on load', () => {
34
+ const comp = new MockedComponent();
35
+ const input = document.createElement('input');
36
+ comp.host.setAttribute('data-tabindex', '-1');
37
+ comp.setMapper(new DataTabIndexValueMapper(() => input));
38
+ comp.connectedCallback();
39
+ comp.componentDidLoad();
40
+ expect(input.getAttribute('tabindex')).toBe('-1');
41
+ expect(MockedMutationObserver.mock.instances[0].observe).toHaveBeenCalledWith(comp.host, {
42
+ attributes: true,
43
+ attributeFilter: ['data-tabindex'],
44
+ });
45
+ });
46
+ it('should update native input tabindex when host data-tabindex changes', () => {
47
+ const comp = new MockedComponent();
48
+ const input = document.createElement('input');
49
+ comp.host.setAttribute('data-tabindex', '0');
50
+ comp.setMapper(new DataTabIndexValueMapper(() => input));
51
+ comp.connectedCallback();
52
+ comp.componentDidLoad();
53
+ expect(input.getAttribute('tabindex')).toBe('0');
54
+ comp.host.setAttribute('data-tabindex', '-1');
55
+ MockedMutationObserver.mock.instances[0].trigger([{ attributeName: 'data-tabindex', oldValue: '0' }]);
56
+ expect(input.getAttribute('tabindex')).toBe('-1');
57
+ });
58
+ it('should remove native input tabindex when host data-tabindex is empty or missing', () => {
59
+ const comp = new MockedComponent();
60
+ const input = document.createElement('input');
61
+ comp.host.setAttribute('data-tabindex', '0');
62
+ comp.setMapper(new DataTabIndexValueMapper(() => input));
63
+ comp.connectedCallback();
64
+ comp.componentDidLoad();
65
+ expect(input.getAttribute('tabindex')).toBe('0');
66
+ comp.host.setAttribute('data-tabindex', '');
67
+ MockedMutationObserver.mock.instances[0].trigger([{ attributeName: 'data-tabindex', oldValue: '0' }]);
68
+ expect(input.hasAttribute('tabindex')).toBeFalsy();
69
+ comp.host.removeAttribute('data-tabindex');
70
+ MockedMutationObserver.mock.instances[0].trigger([{ attributeName: 'data-tabindex', oldValue: '' }]);
71
+ expect(input.hasAttribute('tabindex')).toBeFalsy();
72
+ });
73
+ it('should remove native input tabindex when host data-tabindex is "null" or "undefined" string', () => {
74
+ const comp = new MockedComponent();
75
+ const input = document.createElement('input');
76
+ comp.host.setAttribute('data-tabindex', '0');
77
+ comp.setMapper(new DataTabIndexValueMapper(() => input));
78
+ comp.connectedCallback();
79
+ comp.componentDidLoad();
80
+ expect(input.getAttribute('tabindex')).toBe('0');
81
+ comp.host.setAttribute('data-tabindex', 'null');
82
+ MockedMutationObserver.mock.instances[0].trigger([{ attributeName: 'data-tabindex', oldValue: '0' }]);
83
+ expect(input.hasAttribute('tabindex')).toBeFalsy();
84
+ comp.host.setAttribute('data-tabindex', 'undefined');
85
+ MockedMutationObserver.mock.instances[0].trigger([
86
+ { attributeName: 'data-tabindex', oldValue: 'null' },
87
+ ]);
88
+ expect(input.hasAttribute('tabindex')).toBeFalsy();
89
+ });
90
+ it('should return early when targetGetter returns null', () => {
91
+ const comp = new MockedComponent();
92
+ comp.host.setAttribute('data-tabindex', '0');
93
+ comp.setMapper(new DataTabIndexValueMapper(() => null));
94
+ expect(() => {
95
+ comp.connectedCallback();
96
+ comp.componentDidLoad();
97
+ MockedMutationObserver.mock.instances[0].trigger([
98
+ { attributeName: 'data-tabindex', oldValue: null },
99
+ ]);
100
+ }).not.toThrow();
101
+ });
102
+ it('should return early when targetGetter field is null', () => {
103
+ const comp = new MockedComponent();
104
+ const input = document.createElement('input');
105
+ comp.host.setAttribute('data-tabindex', '1');
106
+ const mapper = new DataTabIndexValueMapper(() => input);
107
+ // force the private readonly field to null so ternary fallback branch is executed
108
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
109
+ mapper.targetGetter = null;
110
+ comp.setMapper(mapper);
111
+ expect(() => {
112
+ comp.connectedCallback();
113
+ comp.componentDidLoad();
114
+ MockedMutationObserver.mock.instances[0].trigger([
115
+ { attributeName: 'data-tabindex', oldValue: null },
116
+ ]);
117
+ }).not.toThrow();
118
+ expect(input.hasAttribute('tabindex')).toBeFalsy();
119
+ });
120
+ });
@@ -27,19 +27,24 @@ export class BasePositionCalculationStrategy extends VegaSlimmer {
27
27
  * returns an ElementPositionBox.
28
28
  */
29
29
  getPositionBox(placement, alignment) {
30
- const placements = placement || this.getPlacements();
31
- const alignments = alignment || this.getAlignments();
30
+ const placements = placement && placement.length > 0 ? placement : this.getPlacements();
31
+ const alignments = alignment && alignment.length > 0 ? alignment : this.getAlignments();
32
32
  const targetBox = this.getTargetBoundBox();
33
33
  const elementBox = this.getElementBoundBox();
34
34
  const containerBox = this.getElementScrollDimension();
35
35
  const suitablePlacement = this.getSuitablePlacement(containerBox, elementBox, targetBox, placements);
36
- const suitableAlignment = this.getSuitableAlignment(containerBox, elementBox, targetBox, suitablePlacement, alignments);
37
- const positionBox = this.calculatePosition(elementBox, targetBox, suitablePlacement, suitableAlignment);
38
- const translocationBox = this.getTranslocationBox(suitablePlacement);
36
+ const activePlacement = suitablePlacement || placements[0];
37
+ const suitableAlignment = this.getSuitableAlignment(containerBox, elementBox, targetBox, activePlacement, alignments);
38
+ const activeAlignment = suitableAlignment || alignments[0];
39
+ const positionBox = this.calculatePosition(elementBox, targetBox, activePlacement, activeAlignment);
40
+ const translocationBox = this.getTranslocationBox(activePlacement);
39
41
  positionBox.placement = suitablePlacement;
40
42
  positionBox.alignment = suitableAlignment;
41
43
  positionBox.left += translocationBox.X;
42
44
  positionBox.top += translocationBox.Y;
45
+ if (!this.showConfig.positionRelativeTo) {
46
+ this.adjustPositionForViewport(positionBox, elementBox, targetBox, activePlacement);
47
+ }
43
48
  return positionBox;
44
49
  }
45
50
  /**
@@ -178,7 +183,7 @@ export class BasePositionCalculationStrategy extends VegaSlimmer {
178
183
  * @param {ElementBoundBox} elementBox - The box of the element to be placed.
179
184
  * @param {ElementBoundBox} targetBox - The box of the target element.
180
185
  * @param {PlacementType[]} placements - The placements that we want to try.
181
- * @returns {PlacementType} A function that takes in a containerBox, elementBox, targetBox, placements, and element.
186
+ * @returns {Nullable<PlacementType>} A function that takes in a containerBox, elementBox, targetBox, placements, and element.
182
187
  */
183
188
  getSuitablePlacement(containerBox, elementBox, targetBox, placements) {
184
189
  const defaultPlacement = placements[0];
@@ -191,7 +196,7 @@ export class BasePositionCalculationStrategy extends VegaSlimmer {
191
196
  No enough space found for placing element and we will keep using the defined placement:
192
197
  ${defaultPlacement}
193
198
  `);
194
- return defaultPlacement;
199
+ return null;
195
200
  }
196
201
  }
197
202
  /**
@@ -257,6 +262,115 @@ export class BasePositionCalculationStrategy extends VegaSlimmer {
257
262
  left: this.calculateLeft(elementBox, targetBox, placement, alignment),
258
263
  };
259
264
  }
265
+ /**
266
+ * Keeps the vertical position within the visible viewport
267
+ *
268
+ * @param {number} top - The calculated top position.
269
+ * @param {number} elementHeight - The height of the element.
270
+ * @returns {number} The top position constrained to the viewport.
271
+ */
272
+ keepVerticallyInView(top, elementHeight) {
273
+ return Math.max(0, Math.min(top, window.innerHeight - elementHeight));
274
+ }
275
+ /**
276
+ * Keeps the horizontal position within the visible viewport
277
+ *
278
+ * @param {number} left - The calculated left position.
279
+ * @param {number} elementWidth - The width of the element.
280
+ * @returns {number} The left position constrained to the viewport.
281
+ */
282
+ keepHorizontallyInView(left, elementWidth) {
283
+ return Math.max(0, Math.min(left, window.innerWidth - elementWidth));
284
+ }
285
+ /**
286
+ * Checks if the target element is visible in the viewport
287
+ *
288
+ * @param {ElementBoundBox} targetBox - The bounding box of the target element.
289
+ * @returns {boolean} True if target is visible in viewport.
290
+ */
291
+ isTargetInView(targetBox) {
292
+ const innerHeight = window.innerHeight;
293
+ const innerWidth = window.innerWidth;
294
+ const targetBottom = targetBox.top + targetBox.height;
295
+ const targetRight = targetBox.left + targetBox.width;
296
+ return (targetBox.top <= innerHeight &&
297
+ targetBottom >= 0 &&
298
+ targetBox.left <= innerWidth &&
299
+ targetRight >= 0);
300
+ }
301
+ /**
302
+ * Corrects `positionBox` so the element stays within the viewport after translocation.
303
+ * Only runs when the target is visible; skips correction entirely if the target has
304
+ * scrolled out of view so the element simply follows it.
305
+ *
306
+ * @param {ElementPositionBox} positionBox - The final position box to adjust (mutated in place).
307
+ * @param {ElementBoundBox} elementBox - Dimensions of the positioned element.
308
+ * @param {ElementBoundBox} targetBox - Bounding box of the target element.
309
+ * @param {PlacementType} placement - Active placement used to select the correction axis.
310
+ */
311
+ adjustPositionForViewport(positionBox, elementBox, targetBox, placement) {
312
+ if (!this.isTargetInView(targetBox)) {
313
+ return;
314
+ }
315
+ if (placement === 'top' || placement === 'bottom') {
316
+ positionBox.top = this.adjustForVerticalOverflow(positionBox.top, elementBox.height, targetBox.height);
317
+ }
318
+ else if (placement === 'left' || placement === 'right') {
319
+ positionBox.left = this.adjustForHorizontalOverflow(positionBox.left, elementBox.width, targetBox.width);
320
+ }
321
+ positionBox.top = this.keepVerticallyInView(positionBox.top, elementBox.height);
322
+ positionBox.left = this.keepHorizontallyInView(positionBox.left, elementBox.width);
323
+ }
324
+ /**
325
+ * Nudges `top` so the element stays within the viewport vertically.
326
+ * Only corrects when the overflow is less than `targetHeight` to keep the element
327
+ * visually anchored to its target; larger overflows are handled by `keepVerticallyInView`.
328
+ *
329
+ * @param {number} top - The calculated top position.
330
+ * @param {number} elementHeight - Height of the positioned element.
331
+ * @param {number} targetHeight - Height of the target, used as the max correctable overflow.
332
+ * @returns {number} The adjusted top position.
333
+ */
334
+ adjustForVerticalOverflow(top, elementHeight, targetHeight) {
335
+ // Pixels the element bleeds past the bottom of the viewport (positive = overflow).
336
+ const overflowBottom = top + elementHeight - window.innerHeight;
337
+ // Pixels the element bleeds past the top of the viewport (positive = overflow).
338
+ const overflowTop = -top;
339
+ // Only nudge when overflow is smaller than targetHeight; larger overflows are left to
340
+ // keepVerticallyInView to hard-clamp, since nudging that far would detach from the target.
341
+ if (overflowBottom > 0 && overflowBottom < targetHeight) {
342
+ return top - overflowBottom; // shift up until bottom edge is flush with viewport bottom
343
+ }
344
+ if (overflowTop > 0 && overflowTop < targetHeight) {
345
+ return top + overflowTop; // shift down until top edge is flush with viewport top
346
+ }
347
+ return top;
348
+ }
349
+ /**
350
+ * Nudges `left` so the element stays within the viewport horizontally.
351
+ * Only corrects when the overflow is less than `targetWidth` to keep the element
352
+ * visually anchored to its target; larger overflows are handled by `keepHorizontallyInView`.
353
+ *
354
+ * @param {number} left - The calculated left position.
355
+ * @param {number} elementWidth - Width of the positioned element.
356
+ * @param {number} targetWidth - Width of the target, used as the max correctable overflow.
357
+ * @returns {number} The adjusted left position.
358
+ */
359
+ adjustForHorizontalOverflow(left, elementWidth, targetWidth) {
360
+ // Pixels the element bleeds past the right edge of the viewport (positive = overflow).
361
+ const overflowRight = left + elementWidth - window.innerWidth;
362
+ // Pixels the element bleeds past the left edge of the viewport (positive = overflow).
363
+ const overflowLeft = -left;
364
+ // Only nudge when overflow is smaller than targetWidth; larger overflows are left to
365
+ // keepHorizontallyInView to hard-clamp, since nudging that far would detach from the target.
366
+ if (overflowRight > 0 && overflowRight < targetWidth) {
367
+ return left - overflowRight; // shift left until right edge is flush with viewport right
368
+ }
369
+ if (overflowLeft > 0 && overflowLeft < targetWidth) {
370
+ return left + overflowLeft; // shift right until left edge is flush with viewport left
371
+ }
372
+ return left;
373
+ }
260
374
  /**
261
375
  * It returns the translocation of the element relative to the target element
262
376
  *
@@ -301,7 +415,7 @@ export class BasePositionCalculationStrategy extends VegaSlimmer {
301
415
  * @param {ElementBoundBox} targetBox - The box of the element that the element to be positioned is aligned to.
302
416
  * @param {PlacementType} placement - The placement of the element relative to the target.
303
417
  * @param {PositionAlignmentType[]} alignments - An array of alignments to try.
304
- * @returns {PositionAlignmentType} the alignment that is suitable for the element.
418
+ * @returns {Nullable<PositionAlignmentType>} the alignment that is suitable for the element.
305
419
  */
306
420
  getSuitableAlignment(containerBox, elementBox, targetBox, placement, alignments) {
307
421
  const defaultAlignment = alignments[0];
@@ -314,7 +428,7 @@ export class BasePositionCalculationStrategy extends VegaSlimmer {
314
428
  No enough space found for placing element and we will keep using the defined alignment:
315
429
  ${defaultAlignment}
316
430
  `);
317
- return defaultAlignment;
431
+ return null;
318
432
  }
319
433
  }
320
434
  /**
@@ -63,10 +63,20 @@ export class PositionCalculationController extends VegaSlimmer {
63
63
  }
64
64
  appendableElement.style.left = `${positionBox.left}px`;
65
65
  appendableElement.style.top = `${positionBox.top}px`;
66
- appendableElement.classList.remove('vega-placement-left', 'vega-placement-right', 'vega-placement-top', 'vega-placement-bottom');
67
- appendableElement.classList.remove('vega-alignment-start', 'vega-alignment-center', 'vega-alignment-end');
68
- appendableElement.classList.add(`vega-placement-${positionBox.placement}`);
69
- appendableElement.classList.add(`vega-alignment-${positionBox.alignment}`);
66
+ appendableElement.classList.remove('vega-placement-left', 'vega-placement-right', 'vega-placement-top', 'vega-placement-bottom', 'vega-no-suitable-placement');
67
+ appendableElement.classList.remove('vega-alignment-start', 'vega-alignment-center', 'vega-alignment-end', 'vega-no-suitable-alignment');
68
+ if (positionBox.placement) {
69
+ appendableElement.classList.add(`vega-placement-${positionBox.placement}`);
70
+ }
71
+ else {
72
+ appendableElement.classList.add(`vega-no-suitable-placement`);
73
+ }
74
+ if (positionBox.alignment) {
75
+ appendableElement.classList.add(`vega-alignment-${positionBox.alignment}`);
76
+ }
77
+ else {
78
+ appendableElement.classList.add(`vega-no-suitable-alignment`);
79
+ }
70
80
  }
71
81
  /**
72
82
  * It sets the width of the appendable element to the width of the target element if the
@@ -9,6 +9,7 @@ import { BasePositionCalculationStrategy } from './base-position-calculation-str
9
9
  import { ScreenScrollPositionUpdate } from './screen-scroll-position-update';
10
10
  import { tryGetDocument } from '../../../utils/try-get-document';
11
11
  import { FeatureFlag } from '../../feature-control/feature-flag-controller';
12
+ import { isNonNullable } from '../../../types/type-guard';
12
13
  /**
13
14
  * calculate position by screen container
14
15
  */
@@ -93,9 +94,17 @@ export class ScreenPositionCalculationStrategy extends BasePositionCalculationSt
93
94
  */
94
95
  getPosition(usePreviousPlacement) {
95
96
  const stayPlacement = usePreviousPlacement ? this.usePreviousPlacement : false;
96
- const positionBox = stayPlacement
97
- ? this.getPositionBox([this.previousPositionBox.placement], [this.previousPositionBox.alignment])
98
- : this.getPositionBox();
97
+ let positionBox;
98
+ if (stayPlacement) {
99
+ positionBox = this.getPositionBox([this.previousPositionBox.placement].filter(isNonNullable), [this.previousPositionBox.alignment].filter(isNonNullable));
100
+ if (!FeatureFlag.isEnabled('VEGA_ELEMENT_APPENDER.AUTO_PLACEMENT')) {
101
+ positionBox.placement = this.previousPositionBox.placement;
102
+ positionBox.alignment = this.previousPositionBox.alignment;
103
+ }
104
+ }
105
+ else {
106
+ positionBox = this.getPositionBox();
107
+ }
99
108
  this.previousPositionBox = positionBox;
100
109
  return positionBox;
101
110
  }
@@ -154,7 +163,7 @@ export class ScreenPositionCalculationStrategy extends BasePositionCalculationSt
154
163
  * @param {ElementBoundBox} elementBox - The box of the element to place.
155
164
  * @param {ElementBoundBox} targetBox - The box of the target element.
156
165
  * @param {PlacementType[]} placements - Ordered list of placements to try.
157
- * @returns {PlacementType} The chosen placement.
166
+ * @returns {Nullable<PlacementType>} The chosen placement.
158
167
  */
159
168
  getSuitablePlacement(containerBox, elementBox, targetBox, placements) {
160
169
  const alignments = this.getAlignments();