voyager-ionic-core 8.0.0 → 8.1.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 (572) hide show
  1. package/components/checkbox.js +3 -3
  2. package/components/index2.js +119 -1
  3. package/components/input-shims.js +5 -5
  4. package/components/ion-accordion-group.js +2 -2
  5. package/components/ion-content.js +6 -4
  6. package/components/ion-datetime-button.js +2 -2
  7. package/components/ion-datetime.js +17 -14
  8. package/components/ion-fab-button.js +2 -2
  9. package/components/ion-fab-list.js +2 -2
  10. package/components/ion-fab.js +2 -2
  11. package/components/ion-footer.js +2 -2
  12. package/components/ion-grid.js +2 -2
  13. package/components/ion-header.js +2 -2
  14. package/components/ion-img.js +1 -1
  15. package/components/ion-infinite-scroll-content.js +2 -2
  16. package/components/ion-infinite-scroll.js +1 -1
  17. package/components/ion-input-password-toggle.js +3 -3
  18. package/components/ion-input.js +17 -4
  19. package/components/ion-item-divider.js +2 -2
  20. package/components/ion-item-group.js +1 -1
  21. package/components/ion-item-option.js +2 -2
  22. package/components/ion-item-options.js +1 -1
  23. package/components/ion-item-sliding.js +1 -1
  24. package/components/ion-loading.js +2 -2
  25. package/components/ion-menu-button.js +2 -2
  26. package/components/ion-menu-toggle.js +2 -2
  27. package/components/ion-menu.js +2 -2
  28. package/components/ion-modal.js +10 -8
  29. package/components/ion-nav-link.js +1 -1
  30. package/components/ion-nav.js +1 -1
  31. package/components/ion-note.js +2 -2
  32. package/components/ion-picker-legacy.js +2 -2
  33. package/components/ion-progress-bar.js +1 -1
  34. package/components/ion-range.js +3 -3
  35. package/components/ion-refresher-content.js +1 -1
  36. package/components/ion-refresher.js +1 -1
  37. package/components/ion-reorder-group.js +1 -1
  38. package/components/ion-reorder.js +1 -1
  39. package/components/ion-router-link.js +2 -2
  40. package/components/ion-router-outlet.js +1 -1
  41. package/components/ion-row.js +1 -1
  42. package/components/ion-searchbar.js +4 -4
  43. package/components/ion-segment-button.js +3 -3
  44. package/components/ion-segment.js +2 -2
  45. package/components/ion-select-option.js +1 -1
  46. package/components/ion-select.js +2 -2
  47. package/components/ion-skeleton-text.js +2 -2
  48. package/components/ion-split-pane.js +2 -2
  49. package/components/ion-tab-bar.js +2 -2
  50. package/components/ion-tab-button.js +2 -2
  51. package/components/ion-tab.js +2 -2
  52. package/components/ion-tabs.js +1 -1
  53. package/components/ion-text.js +2 -2
  54. package/components/ion-textarea.js +2 -2
  55. package/components/ion-thumbnail.js +1 -1
  56. package/components/ion-title.js +2 -2
  57. package/components/ion-toast.js +2 -2
  58. package/components/ion-toggle.js +3 -3
  59. package/components/ion-toolbar.js +2 -2
  60. package/components/ios.transition.js +94 -67
  61. package/components/label.js +3 -3
  62. package/components/list-header.js +2 -2
  63. package/components/list.js +1 -1
  64. package/components/overlays.js +3 -2
  65. package/components/picker-column-option.js +2 -2
  66. package/components/picker-column.js +156 -4
  67. package/components/picker-column2.js +2 -2
  68. package/components/picker.js +2 -2
  69. package/components/popover.js +6 -4
  70. package/components/radio-group.js +1 -1
  71. package/components/radio.js +3 -3
  72. package/components/ripple-effect.js +1 -1
  73. package/components/select-popover.js +2 -2
  74. package/components/spinner.js +1 -1
  75. package/css/core.css +1 -1
  76. package/css/core.css.map +1 -1
  77. package/css/global.bundle.css.map +1 -1
  78. package/css/ionic.bundle.css +1 -1
  79. package/css/ionic.bundle.css.map +1 -1
  80. package/css/palettes/dark.always.css +1 -1
  81. package/css/palettes/dark.always.css.map +1 -1
  82. package/css/palettes/dark.class.css +1 -1
  83. package/css/palettes/dark.class.css.map +1 -1
  84. package/css/palettes/dark.system.css +1 -1
  85. package/css/palettes/dark.system.css.map +1 -1
  86. package/css/palettes/high-contrast-dark.always.css.map +1 -1
  87. package/css/palettes/high-contrast-dark.class.css.map +1 -1
  88. package/css/palettes/high-contrast-dark.system.css.map +1 -1
  89. package/css/palettes/high-contrast.always.css.map +1 -1
  90. package/css/palettes/high-contrast.class.css.map +1 -1
  91. package/css/palettes/high-contrast.system.css.map +1 -1
  92. package/css/typography.css.map +1 -1
  93. package/dist/cjs/{app-globals-5bfa2d7f.js → app-globals-66b7dc06.js} +1 -1
  94. package/dist/cjs/{button-active-564be49f.js → button-active-9135c809.js} +1 -1
  95. package/dist/cjs/{hardware-back-button-44e7c052.js → hardware-back-button-ed931127.js} +2 -2
  96. package/dist/cjs/index-8709af32.js +2234 -0
  97. package/dist/cjs/{index-6d6ac424.js → index-c0b7f8f4.js} +124 -6
  98. package/dist/cjs/{index-defd575f.js → index-c54654c6.js} +2 -2
  99. package/dist/cjs/index.cjs.js +9 -9
  100. package/dist/cjs/{input-shims-20d639e6.js → input-shims-9e59ef62.js} +5 -5
  101. package/dist/cjs/ion-accordion_2.cjs.entry.js +4 -4
  102. package/dist/cjs/ion-action-sheet.cjs.entry.js +5 -5
  103. package/dist/cjs/ion-alert.cjs.entry.js +5 -5
  104. package/dist/cjs/ion-app_8.cjs.entry.js +21 -20
  105. package/dist/cjs/ion-avatar_3.cjs.entry.js +3 -3
  106. package/dist/cjs/ion-back-button.cjs.entry.js +2 -2
  107. package/dist/cjs/ion-backdrop.cjs.entry.js +2 -2
  108. package/dist/cjs/ion-breadcrumb_2.cjs.entry.js +2 -2
  109. package/dist/cjs/ion-button_2.cjs.entry.js +2 -2
  110. package/dist/cjs/ion-card_5.cjs.entry.js +2 -2
  111. package/dist/cjs/ion-checkbox.cjs.entry.js +5 -5
  112. package/dist/cjs/ion-chip.cjs.entry.js +2 -2
  113. package/dist/cjs/ion-col_3.cjs.entry.js +5 -5
  114. package/dist/cjs/ion-datetime-button.cjs.entry.js +4 -4
  115. package/dist/cjs/ion-datetime_3.cjs.entry.js +25 -22
  116. package/dist/cjs/ion-fab_3.cjs.entry.js +8 -8
  117. package/dist/cjs/ion-img.cjs.entry.js +3 -3
  118. package/dist/cjs/ion-infinite-scroll_2.cjs.entry.js +5 -5
  119. package/dist/cjs/ion-input-password-toggle.cjs.entry.js +5 -5
  120. package/dist/cjs/ion-input.cjs.entry.js +18 -6
  121. package/dist/cjs/ion-item-option_3.cjs.entry.js +6 -6
  122. package/dist/cjs/ion-item_8.cjs.entry.js +15 -15
  123. package/dist/cjs/ion-loading.cjs.entry.js +6 -6
  124. package/dist/cjs/ion-menu_3.cjs.entry.js +11 -11
  125. package/dist/cjs/ion-modal.cjs.entry.js +13 -12
  126. package/dist/cjs/ion-nav_2.cjs.entry.js +6 -5
  127. package/dist/cjs/ion-picker-column-option.cjs.entry.js +4 -4
  128. package/dist/cjs/ion-picker-column.cjs.entry.js +156 -6
  129. package/dist/cjs/ion-picker.cjs.entry.js +3 -3
  130. package/dist/cjs/ion-popover.cjs.entry.js +9 -8
  131. package/dist/cjs/ion-progress-bar.cjs.entry.js +3 -3
  132. package/dist/cjs/ion-radio_2.cjs.entry.js +6 -6
  133. package/dist/cjs/ion-range.cjs.entry.js +5 -5
  134. package/dist/cjs/ion-refresher_2.cjs.entry.js +4 -4
  135. package/dist/cjs/ion-reorder_2.cjs.entry.js +4 -4
  136. package/dist/cjs/ion-ripple-effect.cjs.entry.js +3 -3
  137. package/dist/cjs/ion-route_4.cjs.entry.js +4 -4
  138. package/dist/cjs/ion-searchbar.cjs.entry.js +6 -6
  139. package/dist/cjs/ion-segment_2.cjs.entry.js +7 -7
  140. package/dist/cjs/ion-select_3.cjs.entry.js +9 -9
  141. package/dist/cjs/ion-spinner.cjs.entry.js +3 -3
  142. package/dist/cjs/ion-split-pane.cjs.entry.js +4 -4
  143. package/dist/cjs/ion-tab-bar_2.cjs.entry.js +6 -6
  144. package/dist/cjs/ion-tab_2.cjs.entry.js +4 -4
  145. package/dist/cjs/ion-text.cjs.entry.js +4 -4
  146. package/dist/cjs/ion-textarea.cjs.entry.js +4 -4
  147. package/dist/cjs/ion-toast.cjs.entry.js +6 -6
  148. package/dist/cjs/ion-toggle.cjs.entry.js +5 -5
  149. package/dist/cjs/{ionic-global-62487d02.js → ionic-global-35b86a09.js} +1 -1
  150. package/dist/cjs/ionic.cjs.js +31 -33
  151. package/dist/cjs/{ios.transition-d4f0ca4e.js → ios.transition-5ddf92f1.js} +98 -69
  152. package/dist/cjs/loader.cjs.js +4 -4
  153. package/dist/cjs/{md.transition-857328f3.js → md.transition-047c18c5.js} +4 -2
  154. package/dist/cjs/{overlays-10c452b2.js → overlays-cb04d075.js} +5 -3
  155. package/dist/cjs/{status-tap-81daddfa.js → status-tap-5b2775cd.js} +1 -1
  156. package/dist/collection/collection-manifest.json +2 -2
  157. package/dist/collection/components/accordion-group/accordion-group.js +3 -3
  158. package/dist/collection/components/checkbox/checkbox.js +4 -4
  159. package/dist/collection/components/content/content.js +23 -4
  160. package/dist/collection/components/content/test/content.spec.js +27 -0
  161. package/dist/collection/components/datetime/datetime.js +18 -15
  162. package/dist/collection/components/datetime/test/color/datetime.e2e.js +14 -7
  163. package/dist/collection/components/datetime/test/overlay-roles/datetime.e2e.js +34 -0
  164. package/dist/collection/components/datetime-button/datetime-button.js +2 -2
  165. package/dist/collection/components/fab/fab.js +2 -2
  166. package/dist/collection/components/fab-button/fab-button.js +2 -2
  167. package/dist/collection/components/fab-list/fab-list.js +2 -2
  168. package/dist/collection/components/footer/footer.js +2 -2
  169. package/dist/collection/components/grid/grid.js +2 -2
  170. package/dist/collection/components/header/header.js +2 -2
  171. package/dist/collection/components/img/img.js +1 -1
  172. package/dist/collection/components/infinite-scroll/infinite-scroll.js +1 -1
  173. package/dist/collection/components/infinite-scroll-content/infinite-scroll-content.js +2 -2
  174. package/dist/collection/components/input/input.js +34 -5
  175. package/dist/collection/components/input/test/input.spec.js +13 -0
  176. package/dist/collection/components/input-password-toggle/input-password-toggle.js +3 -3
  177. package/dist/collection/components/item/test/a11y/item.e2e.js +24 -4
  178. package/dist/collection/components/item-divider/item-divider.js +2 -2
  179. package/dist/collection/components/item-group/item-group.js +1 -1
  180. package/dist/collection/components/item-option/item-option.js +2 -2
  181. package/dist/collection/components/item-options/item-options.js +1 -1
  182. package/dist/collection/components/item-sliding/item-sliding.js +1 -1
  183. package/dist/collection/components/label/label.ios.css +1 -1
  184. package/dist/collection/components/label/label.js +2 -2
  185. package/dist/collection/components/list/list.js +1 -1
  186. package/dist/collection/components/list-header/list-header.js +2 -2
  187. package/dist/collection/components/loading/loading.js +2 -2
  188. package/dist/collection/components/menu/menu.js +2 -2
  189. package/dist/collection/components/menu-button/menu-button.js +2 -2
  190. package/dist/collection/components/menu-toggle/menu-toggle.js +2 -2
  191. package/dist/collection/components/modal/gestures/sheet.js +3 -2
  192. package/dist/collection/components/modal/modal.js +25 -6
  193. package/dist/collection/components/modal/test/basic/modal.spec.js +19 -0
  194. package/dist/collection/components/nav/nav.js +1 -1
  195. package/dist/collection/components/nav-link/nav-link.js +1 -1
  196. package/dist/collection/components/note/note.js +2 -2
  197. package/dist/collection/components/picker/picker.js +2 -2
  198. package/dist/collection/components/picker-column/picker-column.css +19 -0
  199. package/dist/collection/components/picker-column/picker-column.js +159 -4
  200. package/dist/collection/components/picker-column/test/picker-column.spec.js +83 -0
  201. package/dist/collection/components/picker-column-option/picker-column-option.js +2 -2
  202. package/dist/collection/components/picker-legacy/picker.js +2 -2
  203. package/dist/collection/components/picker-legacy-column/picker-column.js +2 -2
  204. package/dist/collection/components/popover/popover.js +23 -4
  205. package/dist/collection/components/popover/test/basic/popover.spec.js +19 -0
  206. package/dist/collection/components/progress-bar/progress-bar.js +1 -1
  207. package/dist/collection/components/radio/radio.js +3 -3
  208. package/dist/collection/components/radio-group/radio-group.js +2 -2
  209. package/dist/collection/components/range/range.js +4 -4
  210. package/dist/collection/components/refresher/refresher.js +1 -1
  211. package/dist/collection/components/refresher-content/refresher-content.js +1 -1
  212. package/dist/collection/components/reorder/reorder.js +1 -1
  213. package/dist/collection/components/reorder-group/reorder-group.js +1 -1
  214. package/dist/collection/components/ripple-effect/ripple-effect.js +1 -1
  215. package/dist/collection/components/router-link/router-link.js +2 -2
  216. package/dist/collection/components/router-outlet/router-outlet.js +1 -1
  217. package/dist/collection/components/row/row.js +1 -1
  218. package/dist/collection/components/searchbar/searchbar.js +5 -5
  219. package/dist/collection/components/segment/segment.js +3 -3
  220. package/dist/collection/components/segment-button/segment-button.js +3 -3
  221. package/dist/collection/components/select/select.js +3 -3
  222. package/dist/collection/components/select/test/fill/select.e2e.js +25 -0
  223. package/dist/collection/components/select-option/select-option.js +1 -1
  224. package/dist/collection/components/select-popover/select-popover.js +1 -1
  225. package/dist/collection/components/select-popover/select-popover.md.css +8 -1
  226. package/dist/collection/components/skeleton-text/skeleton-text.js +2 -2
  227. package/dist/collection/components/spinner/spinner.js +1 -1
  228. package/dist/collection/components/split-pane/split-pane.js +2 -2
  229. package/dist/collection/components/tab/tab.js +2 -2
  230. package/dist/collection/components/tab-bar/tab-bar.js +2 -2
  231. package/dist/collection/components/tab-button/tab-button.js +2 -2
  232. package/dist/collection/components/tabs/tabs.js +1 -1
  233. package/dist/collection/components/text/text.js +2 -2
  234. package/dist/collection/components/textarea/textarea.js +3 -3
  235. package/dist/collection/components/thumbnail/thumbnail.js +1 -1
  236. package/dist/collection/components/title/title.js +2 -2
  237. package/dist/collection/components/toast/toast.js +2 -2
  238. package/dist/collection/components/toggle/test/enable-on-off-labels/toggle.e2e.js +51 -31
  239. package/dist/collection/components/toggle/toggle.js +4 -4
  240. package/dist/collection/components/toolbar/toolbar.js +2 -2
  241. package/dist/collection/utils/focus-controller/index.js +112 -0
  242. package/dist/collection/utils/focus-controller/test/generic/focus-controller.e2e.js +52 -0
  243. package/dist/collection/utils/focus-controller/test/ionic/focus-controller.e2e.js +52 -0
  244. package/dist/collection/utils/input-shims/hacks/scroll-assist.js +5 -5
  245. package/dist/collection/utils/overlays.js +2 -1
  246. package/dist/collection/utils/test/playwright/page/utils/goto.js +12 -3
  247. package/dist/collection/utils/transition/index.js +11 -1
  248. package/dist/collection/utils/transition/ios.transition.js +94 -67
  249. package/dist/docs.json +110 -15
  250. package/dist/esm/{app-globals-49873df1.js → app-globals-b99e6d29.js} +1 -1
  251. package/dist/esm/{button-active-46df59c1.js → button-active-920addb8.js} +1 -1
  252. package/dist/esm/{hardware-back-button-ba8f64c2.js → hardware-back-button-2d9760b6.js} +2 -2
  253. package/dist/esm/{index-56d90da9.js → index-7ae7186a.js} +2 -2
  254. package/dist/esm/{index-f0d7371a.js → index-8e6b6a24.js} +122 -4
  255. package/dist/esm/index-9aab3bcf.js +2196 -0
  256. package/dist/esm/index.js +9 -9
  257. package/dist/esm/{input-shims-4530285e.js → input-shims-0314bbe5.js} +5 -5
  258. package/dist/esm/ion-accordion_2.entry.js +4 -4
  259. package/dist/esm/ion-action-sheet.entry.js +5 -5
  260. package/dist/esm/ion-alert.entry.js +5 -5
  261. package/dist/esm/ion-app_8.entry.js +21 -20
  262. package/dist/esm/ion-avatar_3.entry.js +3 -3
  263. package/dist/esm/ion-back-button.entry.js +2 -2
  264. package/dist/esm/ion-backdrop.entry.js +2 -2
  265. package/dist/esm/ion-breadcrumb_2.entry.js +2 -2
  266. package/dist/esm/ion-button_2.entry.js +2 -2
  267. package/dist/esm/ion-card_5.entry.js +2 -2
  268. package/dist/esm/ion-checkbox.entry.js +5 -5
  269. package/dist/esm/ion-chip.entry.js +2 -2
  270. package/dist/esm/ion-col_3.entry.js +5 -5
  271. package/dist/esm/ion-datetime-button.entry.js +4 -4
  272. package/dist/esm/ion-datetime_3.entry.js +25 -22
  273. package/dist/esm/ion-fab_3.entry.js +8 -8
  274. package/dist/esm/ion-img.entry.js +3 -3
  275. package/dist/esm/ion-infinite-scroll_2.entry.js +5 -5
  276. package/dist/esm/ion-input-password-toggle.entry.js +5 -5
  277. package/dist/esm/ion-input.entry.js +18 -6
  278. package/dist/esm/ion-item-option_3.entry.js +6 -6
  279. package/dist/esm/ion-item_8.entry.js +15 -15
  280. package/dist/esm/ion-loading.entry.js +6 -6
  281. package/dist/esm/ion-menu_3.entry.js +11 -11
  282. package/dist/esm/ion-modal.entry.js +13 -12
  283. package/dist/esm/ion-nav_2.entry.js +6 -5
  284. package/dist/esm/ion-picker-column-option.entry.js +4 -4
  285. package/dist/esm/ion-picker-column.entry.js +156 -6
  286. package/dist/esm/ion-picker.entry.js +3 -3
  287. package/dist/esm/ion-popover.entry.js +9 -8
  288. package/dist/esm/ion-progress-bar.entry.js +3 -3
  289. package/dist/esm/ion-radio_2.entry.js +6 -6
  290. package/dist/esm/ion-range.entry.js +5 -5
  291. package/dist/esm/ion-refresher_2.entry.js +4 -4
  292. package/dist/esm/ion-reorder_2.entry.js +4 -4
  293. package/dist/esm/ion-ripple-effect.entry.js +3 -3
  294. package/dist/esm/ion-route_4.entry.js +4 -4
  295. package/dist/esm/ion-searchbar.entry.js +6 -6
  296. package/dist/esm/ion-segment_2.entry.js +7 -7
  297. package/dist/esm/ion-select_3.entry.js +9 -9
  298. package/dist/esm/ion-spinner.entry.js +3 -3
  299. package/dist/esm/ion-split-pane.entry.js +4 -4
  300. package/dist/esm/ion-tab-bar_2.entry.js +6 -6
  301. package/dist/esm/ion-tab_2.entry.js +4 -4
  302. package/dist/esm/ion-text.entry.js +4 -4
  303. package/dist/esm/ion-textarea.entry.js +4 -4
  304. package/dist/esm/ion-toast.entry.js +6 -6
  305. package/dist/esm/ion-toggle.entry.js +5 -5
  306. package/dist/esm/{ionic-global-e6c98cd0.js → ionic-global-4528d288.js} +1 -1
  307. package/dist/esm/ionic.js +32 -34
  308. package/dist/esm/{ios.transition-71bfa932.js → ios.transition-e35d0940.js} +98 -69
  309. package/dist/esm/loader.js +5 -5
  310. package/dist/esm/{md.transition-86aef3c0.js → md.transition-4b90a1f0.js} +4 -2
  311. package/dist/esm/{overlays-6fb4a2f2.js → overlays-df2c06b2.js} +5 -4
  312. package/dist/esm/{status-tap-299361cd.js → status-tap-12c27922.js} +1 -1
  313. package/dist/esm-es5/app-globals-b99e6d29.js +4 -0
  314. package/dist/esm-es5/{button-active-46df59c1.js → button-active-920addb8.js} +1 -1
  315. package/dist/esm-es5/{hardware-back-button-ba8f64c2.js → hardware-back-button-2d9760b6.js} +1 -1
  316. package/dist/esm-es5/{index-56d90da9.js → index-7ae7186a.js} +1 -1
  317. package/dist/esm-es5/index-8e6b6a24.js +4 -0
  318. package/dist/esm-es5/index-9aab3bcf.js +5 -0
  319. package/dist/esm-es5/index.js +1 -1
  320. package/dist/esm-es5/input-shims-0314bbe5.js +4 -0
  321. package/dist/esm-es5/ion-accordion_2.entry.js +1 -1
  322. package/dist/esm-es5/ion-action-sheet.entry.js +1 -1
  323. package/dist/esm-es5/ion-alert.entry.js +1 -1
  324. package/dist/esm-es5/ion-app_8.entry.js +1 -1
  325. package/dist/esm-es5/ion-avatar_3.entry.js +1 -1
  326. package/dist/esm-es5/ion-back-button.entry.js +1 -1
  327. package/dist/esm-es5/ion-backdrop.entry.js +1 -1
  328. package/dist/esm-es5/ion-breadcrumb_2.entry.js +1 -1
  329. package/dist/esm-es5/ion-button_2.entry.js +1 -1
  330. package/dist/esm-es5/ion-card_5.entry.js +1 -1
  331. package/dist/esm-es5/ion-checkbox.entry.js +1 -1
  332. package/dist/esm-es5/ion-chip.entry.js +1 -1
  333. package/dist/esm-es5/ion-col_3.entry.js +1 -1
  334. package/dist/esm-es5/ion-datetime-button.entry.js +1 -1
  335. package/dist/esm-es5/ion-datetime_3.entry.js +1 -1
  336. package/dist/esm-es5/ion-fab_3.entry.js +1 -1
  337. package/dist/esm-es5/ion-img.entry.js +1 -1
  338. package/dist/esm-es5/ion-infinite-scroll_2.entry.js +1 -1
  339. package/dist/esm-es5/ion-input-password-toggle.entry.js +1 -1
  340. package/dist/esm-es5/ion-input.entry.js +1 -1
  341. package/dist/esm-es5/ion-item-option_3.entry.js +1 -1
  342. package/dist/esm-es5/ion-item_8.entry.js +1 -1
  343. package/dist/esm-es5/ion-loading.entry.js +1 -1
  344. package/dist/esm-es5/ion-menu_3.entry.js +1 -1
  345. package/dist/esm-es5/ion-modal.entry.js +1 -1
  346. package/dist/esm-es5/ion-nav_2.entry.js +1 -1
  347. package/dist/esm-es5/ion-picker-column-option.entry.js +1 -1
  348. package/dist/esm-es5/ion-picker-column.entry.js +1 -1
  349. package/dist/esm-es5/ion-picker.entry.js +1 -1
  350. package/dist/esm-es5/ion-popover.entry.js +1 -1
  351. package/dist/esm-es5/ion-progress-bar.entry.js +1 -1
  352. package/dist/esm-es5/ion-radio_2.entry.js +1 -1
  353. package/dist/esm-es5/ion-range.entry.js +1 -1
  354. package/dist/esm-es5/ion-refresher_2.entry.js +1 -1
  355. package/dist/esm-es5/ion-reorder_2.entry.js +1 -1
  356. package/dist/esm-es5/ion-ripple-effect.entry.js +1 -1
  357. package/dist/esm-es5/ion-route_4.entry.js +1 -1
  358. package/dist/esm-es5/ion-searchbar.entry.js +1 -1
  359. package/dist/esm-es5/ion-segment_2.entry.js +1 -1
  360. package/dist/esm-es5/ion-select_3.entry.js +1 -1
  361. package/dist/esm-es5/ion-spinner.entry.js +1 -1
  362. package/dist/esm-es5/ion-split-pane.entry.js +1 -1
  363. package/dist/esm-es5/ion-tab-bar_2.entry.js +1 -1
  364. package/dist/esm-es5/ion-tab_2.entry.js +1 -1
  365. package/dist/esm-es5/ion-text.entry.js +1 -1
  366. package/dist/esm-es5/ion-textarea.entry.js +1 -1
  367. package/dist/esm-es5/ion-toast.entry.js +1 -1
  368. package/dist/esm-es5/ion-toggle.entry.js +1 -1
  369. package/dist/esm-es5/{ionic-global-e6c98cd0.js → ionic-global-4528d288.js} +1 -1
  370. package/dist/esm-es5/ionic.js +1 -1
  371. package/dist/esm-es5/ios.transition-e35d0940.js +4 -0
  372. package/dist/esm-es5/loader.js +1 -1
  373. package/dist/esm-es5/md.transition-4b90a1f0.js +4 -0
  374. package/dist/esm-es5/{overlays-6fb4a2f2.js → overlays-df2c06b2.js} +1 -1
  375. package/dist/esm-es5/{status-tap-299361cd.js → status-tap-12c27922.js} +1 -1
  376. package/dist/html.html-data.json +24 -0
  377. package/dist/ionic/index.esm.js +1 -1
  378. package/dist/ionic/ionic.esm.js +1 -1
  379. package/dist/ionic/ionic.js +1 -1
  380. package/dist/ionic/{p-4f77a080.system.entry.js → p-01a27023.system.entry.js} +1 -1
  381. package/dist/ionic/p-0395be73.entry.js +4 -0
  382. package/dist/ionic/p-03b86a5e.js +4 -0
  383. package/dist/ionic/{p-5ad55625.entry.js → p-049d43bd.entry.js} +1 -1
  384. package/dist/ionic/p-0536574e.entry.js +4 -0
  385. package/dist/ionic/{p-005deca1.system.entry.js → p-08ea3402.system.entry.js} +1 -1
  386. package/dist/ionic/{p-f956e38a.entry.js → p-09538818.entry.js} +1 -1
  387. package/dist/ionic/{p-4a01cec0.entry.js → p-09b4e9ec.entry.js} +1 -1
  388. package/dist/ionic/{p-4809ddae.system.entry.js → p-0a6d801e.system.entry.js} +1 -1
  389. package/dist/ionic/{p-c54b167f.system.entry.js → p-0b007acc.system.entry.js} +1 -1
  390. package/dist/ionic/{p-e292247e.system.entry.js → p-10feef7e.system.entry.js} +1 -1
  391. package/dist/ionic/p-130299c9.entry.js +4 -0
  392. package/dist/ionic/p-15d1ddba.js +4 -0
  393. package/dist/ionic/{p-f8f8c5a8.system.entry.js → p-199f826f.system.entry.js} +1 -1
  394. package/dist/ionic/p-1b435d20.entry.js +4 -0
  395. package/dist/ionic/{p-96a561dd.js → p-1cc0b31f.js} +1 -1
  396. package/dist/ionic/p-1eb63fa4.entry.js +4 -0
  397. package/dist/ionic/{p-1ba197b6.entry.js → p-207e11dc.entry.js} +1 -1
  398. package/dist/ionic/{p-46111310.js → p-2690b1de.js} +1 -1
  399. package/dist/ionic/p-26bb6bb8.entry.js +4 -0
  400. package/dist/ionic/{p-f13dc6bd.system.entry.js → p-279f3bac.system.entry.js} +1 -1
  401. package/dist/ionic/p-29de09dd.entry.js +4 -0
  402. package/dist/ionic/{p-6e4dac1a.entry.js → p-2c588aa2.entry.js} +1 -1
  403. package/dist/ionic/p-2ff0e0aa.system.js +4 -0
  404. package/dist/ionic/p-30baae57.system.js +4 -0
  405. package/dist/ionic/{p-7a7ff5e3.system.js → p-31d27232.system.js} +1 -1
  406. package/dist/ionic/p-33e10509.system.js +4 -0
  407. package/dist/ionic/{p-7f33a6e2.system.entry.js → p-380efbfa.system.entry.js} +2 -2
  408. package/dist/ionic/p-3c27be4a.entry.js +4 -0
  409. package/dist/ionic/p-3d015cdb.system.js +5 -0
  410. package/dist/ionic/{p-1c42ad90.entry.js → p-3f53a0b1.entry.js} +1 -1
  411. package/dist/ionic/p-433157a4.entry.js +4 -0
  412. package/dist/ionic/{p-53d37363.entry.js → p-4824398b.entry.js} +1 -1
  413. package/dist/ionic/p-498eb648.system.entry.js +4 -0
  414. package/dist/ionic/{p-7c93f00b.system.entry.js → p-4d8f408d.system.entry.js} +1 -1
  415. package/dist/ionic/{p-ad2b9596.entry.js → p-5091f63c.entry.js} +1 -1
  416. package/dist/ionic/{p-6ef17d86.system.entry.js → p-509620b8.system.entry.js} +1 -1
  417. package/dist/ionic/{p-48f60474.entry.js → p-5109a566.entry.js} +1 -1
  418. package/dist/ionic/{p-4f6ebc2b.entry.js → p-52ce473d.entry.js} +1 -1
  419. package/dist/ionic/{p-4fadf4b0.entry.js → p-52f53904.entry.js} +1 -1
  420. package/dist/ionic/{p-aa8a2f40.system.entry.js → p-55f99a39.system.entry.js} +1 -1
  421. package/dist/ionic/{p-6ac30fc3.system.js → p-5734ac17.system.js} +1 -1
  422. package/dist/ionic/{p-55bc2a11.system.entry.js → p-57bc32e2.system.entry.js} +1 -1
  423. package/dist/ionic/{p-8f9e2850.js → p-5cc6dcf5.js} +1 -1
  424. package/dist/ionic/p-5dc9f99a.entry.js +4 -0
  425. package/dist/ionic/p-5ec3bb70.system.entry.js +4 -0
  426. package/dist/ionic/{p-b6519a42.entry.js → p-606f069c.entry.js} +1 -1
  427. package/dist/ionic/{p-3de2aab8.system.entry.js → p-628967e3.system.entry.js} +1 -1
  428. package/dist/ionic/{p-c927dbe2.system.entry.js → p-62e44e4a.system.entry.js} +1 -1
  429. package/dist/ionic/p-66ed603b.js +4 -0
  430. package/dist/ionic/{p-e548fedf.system.entry.js → p-670c9f57.system.entry.js} +1 -1
  431. package/dist/ionic/{p-d061515d.system.entry.js → p-6a2cf398.system.entry.js} +1 -1
  432. package/dist/ionic/{p-7492572a.entry.js → p-6c3666d5.entry.js} +1 -1
  433. package/dist/ionic/{p-53d69c70.system.entry.js → p-6df12af0.system.entry.js} +1 -1
  434. package/dist/ionic/p-6ec88301.entry.js +4 -0
  435. package/dist/ionic/p-6f008ad2.js +4 -0
  436. package/dist/ionic/{p-814efd87.system.entry.js → p-700567ab.system.entry.js} +1 -1
  437. package/dist/ionic/p-712d54ae.js +4 -0
  438. package/dist/ionic/{p-e8a713b5.entry.js → p-7349de07.entry.js} +1 -1
  439. package/dist/ionic/p-7402fcdf.entry.js +4 -0
  440. package/dist/ionic/{p-e6d46b5d.system.entry.js → p-77731f19.system.entry.js} +1 -1
  441. package/dist/ionic/{p-90f8498c.entry.js → p-78405458.entry.js} +1 -1
  442. package/dist/ionic/{p-b4a7f856.system.entry.js → p-7d6fd45f.system.entry.js} +1 -1
  443. package/dist/ionic/{p-332aa81e.entry.js → p-7eb47906.entry.js} +1 -1
  444. package/dist/ionic/{p-8a5152e5.entry.js → p-80265a58.entry.js} +1 -1
  445. package/dist/ionic/{p-68afa357.system.entry.js → p-83d748f8.system.entry.js} +2 -2
  446. package/dist/ionic/{p-6c5c1bb5.system.js → p-842c9fca.system.js} +1 -1
  447. package/dist/ionic/{p-e781c893.entry.js → p-8a03fbee.entry.js} +1 -1
  448. package/dist/ionic/{p-cf8101a6.system.entry.js → p-8cb80f83.system.entry.js} +1 -1
  449. package/dist/ionic/{p-9fd3ca09.system.entry.js → p-8d14ee8c.system.entry.js} +2 -2
  450. package/dist/ionic/p-90dfc454.system.entry.js +4 -0
  451. package/dist/ionic/{p-c4eafa12.system.entry.js → p-9213681c.system.entry.js} +1 -1
  452. package/dist/ionic/p-92d7e99d.system.js +4 -0
  453. package/dist/ionic/{p-2b86020c.system.entry.js → p-9664a1a2.system.entry.js} +1 -1
  454. package/dist/ionic/{p-dbc3e90c.entry.js → p-9797f6eb.entry.js} +1 -1
  455. package/dist/ionic/{p-987e38ef.system.entry.js → p-9848d7be.system.entry.js} +1 -1
  456. package/dist/ionic/{p-fea11771.entry.js → p-98f6116f.entry.js} +1 -1
  457. package/dist/ionic/{p-cbd87df6.entry.js → p-99884813.entry.js} +1 -1
  458. package/dist/ionic/{p-904df2ee.system.entry.js → p-99ca9787.system.entry.js} +1 -1
  459. package/dist/ionic/{p-ca5bb110.system.entry.js → p-9bfd7cda.system.entry.js} +1 -1
  460. package/dist/ionic/p-9c6dcf78.system.entry.js +4 -0
  461. package/dist/ionic/p-9da86308.js +4 -0
  462. package/dist/ionic/{p-83b445c3.js → p-9ec42be0.js} +1 -1
  463. package/dist/ionic/{p-5c26fed5.system.entry.js → p-a2e94ade.system.entry.js} +1 -1
  464. package/dist/ionic/{p-7bbcce53.system.js → p-a39d3482.system.js} +1 -1
  465. package/dist/ionic/p-a488b7ab.system.js +4 -0
  466. package/dist/ionic/{p-e1ad8e76.entry.js → p-a4ab7449.entry.js} +1 -1
  467. package/dist/ionic/{p-3d977e09.system.entry.js → p-a50f23bf.system.entry.js} +2 -2
  468. package/dist/ionic/{p-275dd0ba.system.entry.js → p-a76ab3ea.system.entry.js} +1 -1
  469. package/dist/ionic/{p-67f5b57a.js → p-a953ef66.js} +1 -1
  470. package/dist/ionic/p-aaaaaea1.entry.js +4 -0
  471. package/dist/ionic/{p-151e8afd.entry.js → p-b02eda30.entry.js} +1 -1
  472. package/dist/ionic/{p-341b3f37.entry.js → p-b04c27d8.entry.js} +1 -1
  473. package/dist/ionic/{p-6cf780b6.system.entry.js → p-b07affd5.system.entry.js} +1 -1
  474. package/dist/ionic/{p-aa79cc0e.system.entry.js → p-b28d3ccb.system.entry.js} +2 -2
  475. package/dist/ionic/{p-e099a6f3.entry.js → p-b563b6ac.entry.js} +1 -1
  476. package/dist/ionic/p-b62ae60a.system.entry.js +4 -0
  477. package/dist/ionic/p-b9181033.system.entry.js +4 -0
  478. package/dist/ionic/{p-e93cd31c.entry.js → p-ba70039f.entry.js} +1 -1
  479. package/dist/ionic/{p-1fe1f512.entry.js → p-bbbe869e.entry.js} +1 -1
  480. package/dist/ionic/{p-aea5f293.system.entry.js → p-c41435e6.system.entry.js} +1 -1
  481. package/dist/ionic/p-cec8589b.system.js +4 -0
  482. package/dist/ionic/{p-3008ca4e.system.entry.js → p-d69b26d9.system.entry.js} +1 -1
  483. package/dist/ionic/p-d73a16e6.system.entry.js +4 -0
  484. package/dist/ionic/p-dba5cb84.js +5 -0
  485. package/dist/ionic/{p-df0d39c7.system.entry.js → p-dc0d9ff5.system.entry.js} +2 -2
  486. package/dist/ionic/p-dc1e363a.entry.js +4 -0
  487. package/dist/ionic/{p-405fd996.entry.js → p-df517d1f.entry.js} +1 -1
  488. package/dist/ionic/p-dfb78785.system.js +4 -0
  489. package/dist/ionic/{p-98af538a.system.entry.js → p-e0a8ffd0.system.entry.js} +1 -1
  490. package/dist/ionic/{p-50205ef9.system.entry.js → p-e6e197f5.system.entry.js} +1 -1
  491. package/dist/ionic/{p-530207f9.entry.js → p-e6e88ab9.entry.js} +1 -1
  492. package/dist/ionic/{p-ffbc80ae.system.js → p-e81f22e3.system.js} +1 -1
  493. package/dist/ionic/{p-07584ab4.system.js → p-eb3023c9.system.js} +1 -1
  494. package/dist/ionic/p-ecbdbf25.system.entry.js +4 -0
  495. package/dist/ionic/{p-91b568e2.system.entry.js → p-ed5aebaa.system.entry.js} +1 -1
  496. package/dist/ionic/p-f357707e.entry.js +4 -0
  497. package/dist/ionic/{p-ca6decbd.entry.js → p-f53bcebd.entry.js} +1 -1
  498. package/dist/ionic/p-f9baf25c.entry.js +4 -0
  499. package/dist/ionic/{p-1472c130.entry.js → p-fa8f2e62.entry.js} +1 -1
  500. package/dist/ionic/{p-e81c3ca2.system.entry.js → p-fb21fd1c.system.entry.js} +1 -1
  501. package/dist/ionic/{p-bc3d649d.entry.js → p-fcecca8f.entry.js} +1 -1
  502. package/dist/types/components/accordion-group/accordion-group.d.ts +3 -4
  503. package/dist/types/components/checkbox/checkbox.d.ts +3 -4
  504. package/dist/types/components/content/content.d.ts +8 -0
  505. package/dist/types/components/datetime/datetime.d.ts +2 -0
  506. package/dist/types/components/input/input.d.ts +6 -0
  507. package/dist/types/components/modal/modal-interface.d.ts +1 -0
  508. package/dist/types/components/modal/modal.d.ts +18 -0
  509. package/dist/types/components/picker-column/picker-column.d.ts +37 -0
  510. package/dist/types/components/popover/popover-interface.d.ts +1 -0
  511. package/dist/types/components/popover/popover.d.ts +18 -0
  512. package/dist/types/components/radio-group/radio-group.d.ts +2 -0
  513. package/dist/types/components/range/range.d.ts +1 -1
  514. package/dist/types/components/searchbar/searchbar.d.ts +2 -0
  515. package/dist/types/components/segment/segment.d.ts +3 -2
  516. package/dist/types/components/select/select.d.ts +2 -0
  517. package/dist/types/components/textarea/textarea.d.ts +2 -0
  518. package/dist/types/components/toggle/toggle.d.ts +3 -2
  519. package/dist/types/components.d.ts +44 -12
  520. package/dist/types/utils/config.d.ts +9 -0
  521. package/dist/types/utils/focus-controller/index.d.ts +13 -0
  522. package/dist/types/utils/overlays.d.ts +1 -0
  523. package/hydrate/index.d.ts +1 -1
  524. package/hydrate/index.js +44900 -35418
  525. package/package.json +6 -6
  526. package/dist/cjs/index-bbc6c29f.js +0 -3324
  527. package/dist/esm/index-bcd8859b.js +0 -3286
  528. package/dist/esm-es5/app-globals-49873df1.js +0 -4
  529. package/dist/esm-es5/index-bcd8859b.js +0 -5
  530. package/dist/esm-es5/index-f0d7371a.js +0 -4
  531. package/dist/esm-es5/input-shims-4530285e.js +0 -4
  532. package/dist/esm-es5/ios.transition-71bfa932.js +0 -4
  533. package/dist/esm-es5/md.transition-86aef3c0.js +0 -4
  534. package/dist/ionic/p-0bd47555.js +0 -4
  535. package/dist/ionic/p-0e713efe.js +0 -4
  536. package/dist/ionic/p-13cc6ee6.entry.js +0 -4
  537. package/dist/ionic/p-1b0f4e6c.entry.js +0 -4
  538. package/dist/ionic/p-1fa53d02.entry.js +0 -4
  539. package/dist/ionic/p-23fdee0e.entry.js +0 -4
  540. package/dist/ionic/p-2613c305.system.js +0 -4
  541. package/dist/ionic/p-46f407f0.system.js +0 -4
  542. package/dist/ionic/p-495ed1c3.entry.js +0 -4
  543. package/dist/ionic/p-4de53118.js +0 -4
  544. package/dist/ionic/p-4edce583.system.entry.js +0 -4
  545. package/dist/ionic/p-510cb8e6.system.js +0 -4
  546. package/dist/ionic/p-582db405.system.entry.js +0 -4
  547. package/dist/ionic/p-5f28cb75.js +0 -4
  548. package/dist/ionic/p-6dc81903.entry.js +0 -4
  549. package/dist/ionic/p-7372cf23.system.entry.js +0 -4
  550. package/dist/ionic/p-7596e24d.system.js +0 -5
  551. package/dist/ionic/p-76971b4f.entry.js +0 -4
  552. package/dist/ionic/p-91dabef7.system.js +0 -4
  553. package/dist/ionic/p-9ccc8035.system.entry.js +0 -4
  554. package/dist/ionic/p-9fa5ff32.system.js +0 -4
  555. package/dist/ionic/p-a28ea4d8.system.entry.js +0 -4
  556. package/dist/ionic/p-a39a73e3.entry.js +0 -4
  557. package/dist/ionic/p-a90201f2.js +0 -4
  558. package/dist/ionic/p-ac045dad.entry.js +0 -4
  559. package/dist/ionic/p-ae42c907.entry.js +0 -4
  560. package/dist/ionic/p-ba35f07f.entry.js +0 -4
  561. package/dist/ionic/p-c1c77386.js +0 -5
  562. package/dist/ionic/p-c2762c6a.system.entry.js +0 -4
  563. package/dist/ionic/p-c4e495a3.system.js +0 -4
  564. package/dist/ionic/p-cf45a5c7.system.entry.js +0 -4
  565. package/dist/ionic/p-d73f49d0.entry.js +0 -4
  566. package/dist/ionic/p-dc4406d7.system.entry.js +0 -4
  567. package/dist/ionic/p-dec86943.entry.js +0 -4
  568. package/dist/ionic/p-e5a3659f.system.js +0 -4
  569. package/dist/ionic/p-ec178f19.entry.js +0 -4
  570. package/dist/ionic/p-eda2459e.entry.js +0 -4
  571. package/dist/ionic/p-f6ca4d02.js +0 -4
  572. package/dist/ionic/p-f6fec6a0.entry.js +0 -4
@@ -8,7 +8,7 @@ import { raf, inheritAttributes, hasLazyBuild } from "../../utils/helpers";
8
8
  import { createLockController } from "../../utils/lock-controller";
9
9
  import { printIonWarning } from "../../utils/logging/index";
10
10
  import { Style as StatusBarStyle, StatusBar } from "../../utils/native/status-bar";
11
- import { GESTURE, BACKDROP, dismiss, eventMethod, prepareOverlay, present, createTriggerController, setOverlayId, } from "../../utils/overlays";
11
+ import { GESTURE, BACKDROP, dismiss, eventMethod, prepareOverlay, present, createTriggerController, setOverlayId, FOCUS_TRAP_DISABLE_CLASS, } from "../../utils/overlays";
12
12
  import { getClassMap } from "../../utils/theme";
13
13
  import { deepReady, waitForMount } from "../../utils/transition/index";
14
14
  import { config } from "../../global/config";
@@ -101,6 +101,7 @@ export class Modal {
101
101
  this.isOpen = false;
102
102
  this.trigger = undefined;
103
103
  this.keepContentsMounted = false;
104
+ this.focusTrap = true;
104
105
  this.canDismiss = true;
105
106
  }
106
107
  onIsOpenChange(newValue, oldValue) {
@@ -557,23 +558,23 @@ export class Modal {
557
558
  return true;
558
559
  }
559
560
  render() {
560
- const { handle, isSheetModal, presentingElement, htmlAttributes, handleBehavior, inheritedAttributes } = this;
561
+ const { handle, isSheetModal, presentingElement, htmlAttributes, handleBehavior, inheritedAttributes, focusTrap } = this;
561
562
  const showHandle = handle !== false && isSheetModal;
562
563
  const mode = getIonMode(this);
563
564
  const isCardModal = presentingElement !== undefined && mode === 'ios';
564
565
  const isHandleCycle = handleBehavior === 'cycle';
565
- return (h(Host, Object.assign({ key: 'bb00efb8cbbdb2d1bbcc5e9c638586e2904882a8', "no-router": true, tabindex: "-1" }, htmlAttributes, { style: {
566
+ return (h(Host, Object.assign({ key: 'fe6fd17cf857127f89d652b9aa3e9473d28c55db', "no-router": true, tabindex: "-1" }, htmlAttributes, { style: {
566
567
  zIndex: `${20000 + this.overlayIndex}`,
567
- }, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, 'overlay-hidden': true }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle }), h("ion-backdrop", { key: 'd2d50f736fdc34b933c00309fe0b67e4aff7ee63', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { key: '5d3523a04da9350ae435a4f3247198095b71f206', class: "modal-shadow" }), h("div", Object.assign({ key: '09b3c4b629155f8c32f5c896cf689ffbe7004de8',
568
+ }, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, 'overlay-hidden': true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle }), h("ion-backdrop", { key: '0f3a31363c2717e5483bc0412c25804897d4aff8', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { key: '0e5ed59162ff08fe0a9f757e06bdacc75f65c0ed', class: "modal-shadow" }), h("div", Object.assign({ key: '35cdbe2238765e5f346ad7be64f7eefa8c78f0c0',
568
569
  /*
569
570
  role and aria-modal must be used on the
570
571
  same element. They must also be set inside the
571
572
  shadow DOM otherwise ion-button will not be highlighted
572
573
  when using VoiceOver: https://bugs.webkit.org/show_bug.cgi?id=247134
573
574
  */
574
- role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: 'e47d90068927f3a518e4144e17f18ac326126712', class: "modal-handle",
575
+ role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: '7a4031eaebf9a098f4c4220a5fe9d1c25cc0ec92', class: "modal-handle",
575
576
  // Prevents the handle from receiving keyboard focus when it does not cycle
576
- tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle" })), h("slot", { key: '5733e94b3ecc4ed9bfb6aec5cd254cd0e43ee8f7' }))));
577
+ tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle" })), h("slot", { key: '534adc8e5bd850199fe2e9e16f0e7c19217d8486' }))));
577
578
  }
578
579
  static get is() { return "ion-modal"; }
579
580
  static get encapsulation() { return "shadow"; }
@@ -1019,6 +1020,24 @@ export class Modal {
1019
1020
  "reflect": false,
1020
1021
  "defaultValue": "false"
1021
1022
  },
1023
+ "focusTrap": {
1024
+ "type": "boolean",
1025
+ "mutable": false,
1026
+ "complexType": {
1027
+ "original": "boolean",
1028
+ "resolved": "boolean",
1029
+ "references": {}
1030
+ },
1031
+ "required": false,
1032
+ "optional": false,
1033
+ "docs": {
1034
+ "tags": [],
1035
+ "text": "If `true`, focus will not be allowed to move outside of this overlay.\nIf `false`, focus will be allowed to move outside of the overlay.\n\nIn most scenarios this property should remain set to `true`. Setting\nthis property to `false` can cause severe accessibility issues as users\nrelying on assistive technologies may be able to move focus into\na confusing state. We recommend only setting this to `false` when\nabsolutely necessary.\n\nDevelopers may want to consider disabling focus trapping if this\noverlay presents a non-Ionic overlay from a 3rd party library.\nDevelopers would disable focus trapping on the Ionic overlay\nwhen presenting the 3rd party overlay and then re-enable\nfocus trapping when dismissing the 3rd party overlay and moving\nfocus back to the Ionic overlay."
1036
+ },
1037
+ "attribute": "focus-trap",
1038
+ "reflect": false,
1039
+ "defaultValue": "true"
1040
+ },
1022
1041
  "canDismiss": {
1023
1042
  "type": "boolean",
1024
1043
  "mutable": false,
@@ -4,6 +4,7 @@
4
4
  import { h } from "@stencil/core";
5
5
  import { newSpecPage } from "@stencil/core/testing";
6
6
  import { Modal } from "../../modal";
7
+ import { FOCUS_TRAP_DISABLE_CLASS } from "../../../../utils/overlays";
7
8
  describe('modal: htmlAttributes inheritance', () => {
8
9
  it('should correctly inherit attributes on host', async () => {
9
10
  const page = await newSpecPage({
@@ -14,3 +15,21 @@ describe('modal: htmlAttributes inheritance', () => {
14
15
  await expect(modal.getAttribute('data-testid')).toBe('basic-modal');
15
16
  });
16
17
  });
18
+ describe('modal: focus trap', () => {
19
+ it('should set the focus trap class when disabled', async () => {
20
+ const page = await newSpecPage({
21
+ components: [Modal],
22
+ template: () => h("ion-modal", { focusTrap: false, overlayIndex: 1 }),
23
+ });
24
+ const modal = page.body.querySelector('ion-modal');
25
+ expect(modal.classList.contains(FOCUS_TRAP_DISABLE_CLASS)).toBe(true);
26
+ });
27
+ it('should not set the focus trap class by default', async () => {
28
+ const page = await newSpecPage({
29
+ components: [Modal],
30
+ template: () => h("ion-modal", { overlayIndex: 1 }),
31
+ });
32
+ const modal = page.body.querySelector('ion-modal');
33
+ expect(modal.classList.contains(FOCUS_TRAP_DISABLE_CLASS)).toBe(false);
34
+ });
35
+ });
@@ -830,7 +830,7 @@ export class Nav {
830
830
  }
831
831
  }
832
832
  render() {
833
- return h("slot", { key: 'dfe98cb6604a2015a49f41beffebdd2da957dfff' });
833
+ return h("slot", { key: 'e9d99a8a0b84f02f9964d8143cd5e647e43334f9' });
834
834
  }
835
835
  static get is() { return "ion-nav"; }
836
836
  static get encapsulation() { return "shadow"; }
@@ -14,7 +14,7 @@ export class NavLink {
14
14
  this.routerAnimation = undefined;
15
15
  }
16
16
  render() {
17
- return h(Host, { key: 'd2f8545b4fbd5aa25ef36eb01dffbc5d35ccfbb9', onClick: this.onClick });
17
+ return h(Host, { key: '42c23dcdec5fdb25defebaf6e8a9fa75754ff8eb', onClick: this.onClick });
18
18
  }
19
19
  static get is() { return "ion-nav-link"; }
20
20
  static get properties() {
@@ -13,9 +13,9 @@ export class Note {
13
13
  }
14
14
  render() {
15
15
  const mode = getIonMode(this);
16
- return (h(Host, { key: '10a3495bc21166176986441479f8f7539029d161', class: createColorClasses(this.color, {
16
+ return (h(Host, { key: '90ec2fe8c9487608ed8c0bdc32c2e80a6a0890b3', class: createColorClasses(this.color, {
17
17
  [mode]: true,
18
- }) }, h("slot", { key: 'b6a9459e1b85f608fafd060a4bfeb11637ebe873' })));
18
+ }) }, h("slot", { key: '115ee3f79e6c526b0644443aad468e99385d0eda' })));
19
19
  }
20
20
  static get is() { return "ion-note"; }
21
21
  static get encapsulation() { return "shadow"; }
@@ -474,7 +474,7 @@ export class Picker {
474
474
  this.emitInputModeChange();
475
475
  }
476
476
  render() {
477
- return (h(Host, { key: 'f92214a09dc85b65873676f40fde2b802960e704', onPointerDown: (ev) => this.onPointerDown(ev), onClick: () => this.onClick() }, h("input", { key: '6da37f75aca4ea1c9cb3bc733ebda2116279f313', "aria-hidden": "true", tabindex: -1, inputmode: "numeric", type: "number", onKeyDown: (ev) => {
477
+ return (h(Host, { key: '02b0687b1f80ba295a965dfba76dd59e2d1de5d3', onPointerDown: (ev) => this.onPointerDown(ev), onClick: () => this.onClick() }, h("input", { key: 'f83ed84bcf9e02539c00d8a4e63e6a0d7fc4ac71', "aria-hidden": "true", tabindex: -1, inputmode: "numeric", type: "number", onKeyDown: (ev) => {
478
478
  var _a;
479
479
  /**
480
480
  * The "Enter" key represents
@@ -489,7 +489,7 @@ export class Picker {
489
489
  if (ev.key === 'Enter') {
490
490
  (_a = this.inputEl) === null || _a === void 0 ? void 0 : _a.blur();
491
491
  }
492
- }, ref: (el) => (this.inputEl = el), onInput: () => this.onInputChange(), onBlur: () => this.exitInputMode() }), h("div", { key: '298e99d83dd3f5bf2798150bab0bb4024af472fa', class: "picker-before" }), h("div", { key: 'ea578f04eb562a4dc6d6cc92de133dcb9fb7f42a', class: "picker-after" }), h("div", { key: '84567824956dfe967992a629904836ba8b75b3ec', class: "picker-highlight", ref: (el) => (this.highlightEl = el) }), h("slot", { key: 'df81f8fb90e1f649b608328034528f5c31c70c3b' })));
492
+ }, ref: (el) => (this.inputEl = el), onInput: () => this.onInputChange(), onBlur: () => this.exitInputMode() }), h("div", { key: '45b07fb0617d8e006712776bf78302288edb3ff4', class: "picker-before" }), h("div", { key: '73009229368e0d62b09c913aacade26f068a7aa9', class: "picker-after" }), h("div", { key: 'b73da00e446cd1cfd511c39212e14a00d355752e', class: "picker-highlight", ref: (el) => (this.highlightEl = el) }), h("slot", { key: 'd969f5efc5ddb9eda6c4828702efd1ceeb69f767' })));
493
493
  }
494
494
  static get is() { return "ion-picker"; }
495
495
  static get encapsulation() { return "shadow"; }
@@ -55,6 +55,7 @@
55
55
  */
56
56
  :host {
57
57
  display: flex;
58
+ position: relative;
58
59
  align-items: center;
59
60
  justify-content: center;
60
61
  max-width: 100%;
@@ -63,6 +64,24 @@
63
64
  text-align: center;
64
65
  }
65
66
 
67
+ /**
68
+ * Renders an invisible element on top of the column that receives focus
69
+ * events. This allows screen readers to navigate the column.
70
+ */
71
+ .assistive-focusable {
72
+ left: 0;
73
+ right: 0;
74
+ top: 0;
75
+ bottom: 0;
76
+ position: absolute;
77
+ z-index: 1;
78
+ pointer-events: none;
79
+ }
80
+
81
+ .assistive-focusable:focus {
82
+ outline: none;
83
+ }
84
+
66
85
  .picker-opts {
67
86
  /**
68
87
  * This padding must be set here and not on the
@@ -19,6 +19,7 @@ export class PickerColumn {
19
19
  this.isScrolling = false;
20
20
  this.isColumnVisible = false;
21
21
  this.canExitInputMode = true;
22
+ this.updateValueTextOnScroll = false;
22
23
  this.centerPickerItemInView = (target, smooth = true, canExitInputMode = true) => {
23
24
  const { isColumnVisible, scrollEl } = this;
24
25
  if (isColumnVisible && scrollEl) {
@@ -33,6 +34,7 @@ export class PickerColumn {
33
34
  * of these can cause a scroll to occur.
34
35
  */
35
36
  this.canExitInputMode = canExitInputMode;
37
+ this.updateValueTextOnScroll = false;
36
38
  scrollEl.scroll({
37
39
  top,
38
40
  left: 0,
@@ -105,6 +107,7 @@ export class PickerColumn {
105
107
  let activeEl = this.activeItem;
106
108
  const scrollCallback = () => {
107
109
  raf(() => {
110
+ var _a;
108
111
  if (!scrollEl)
109
112
  return;
110
113
  if (timeout) {
@@ -185,8 +188,23 @@ export class PickerColumn {
185
188
  }
186
189
  activeEl = newActiveElement;
187
190
  this.setPickerItemActiveState(newActiveElement, true);
191
+ /**
192
+ * Set the aria-valuetext even though the value prop has not been updated yet.
193
+ * This enables some screen readers to announce the value as the users drag
194
+ * as opposed to when their release their pointer from the screen.
195
+ *
196
+ * When the value is programmatically updated, we will smoothly scroll
197
+ * to the new option. However, we do not want to update aria-valuetext mid-scroll
198
+ * as that can cause the old value to be briefly set before being set to the
199
+ * correct option. This will cause some screen readers to announce the old value
200
+ * again before announcing the new value. The correct valuetext will be set on render.
201
+ */
202
+ if (this.updateValueTextOnScroll) {
203
+ (_a = this.assistiveFocusable) === null || _a === void 0 ? void 0 : _a.setAttribute('aria-valuetext', this.getOptionValueText(newActiveElement));
204
+ }
188
205
  timeout = setTimeout(() => {
189
206
  this.isScrolling = false;
207
+ this.updateValueTextOnScroll = true;
190
208
  enableHaptics && hapticSelectionEnd();
191
209
  /**
192
210
  * Certain tasks (such as those that
@@ -245,12 +263,141 @@ export class PickerColumn {
245
263
  */
246
264
  this.el.classList.remove('picker-column-active');
247
265
  };
266
+ /**
267
+ * Find the next enabled option after the active option.
268
+ * @param stride - How many options to "jump" over in order to select the next option.
269
+ * This can be used to implement PageUp/PageDown behaviors where pressing these keys
270
+ * scrolls the picker by more than 1 option. For example, a stride of 5 means select
271
+ * the enabled option 5 options after the active one. Note that the actual option selected
272
+ * may be past the stride if the option at the stride is disabled.
273
+ */
274
+ this.findNextOption = (stride = 1) => {
275
+ const { activeItem } = this;
276
+ if (!activeItem)
277
+ return null;
278
+ let prevNode = activeItem;
279
+ let node = activeItem.nextElementSibling;
280
+ while (node != null) {
281
+ if (stride > 0) {
282
+ stride--;
283
+ }
284
+ if (node.tagName === 'ION-PICKER-COLUMN-OPTION' && !node.disabled && stride === 0) {
285
+ return node;
286
+ }
287
+ prevNode = node;
288
+ // Use nextElementSibling instead of nextSibling to avoid text/comment nodes
289
+ node = node.nextElementSibling;
290
+ }
291
+ return prevNode;
292
+ };
293
+ /**
294
+ * Find the next enabled option after the active option.
295
+ * @param stride - How many options to "jump" over in order to select the next option.
296
+ * This can be used to implement PageUp/PageDown behaviors where pressing these keys
297
+ * scrolls the picker by more than 1 option. For example, a stride of 5 means select
298
+ * the enabled option 5 options before the active one. Note that the actual option selected
299
+ * may be past the stride if the option at the stride is disabled.
300
+ */
301
+ this.findPreviousOption = (stride = 1) => {
302
+ const { activeItem } = this;
303
+ if (!activeItem)
304
+ return null;
305
+ let nextNode = activeItem;
306
+ let node = activeItem.previousElementSibling;
307
+ while (node != null) {
308
+ if (stride > 0) {
309
+ stride--;
310
+ }
311
+ if (node.tagName === 'ION-PICKER-COLUMN-OPTION' && !node.disabled && stride === 0) {
312
+ return node;
313
+ }
314
+ nextNode = node;
315
+ // Use previousElementSibling instead of previousSibling to avoid text/comment nodes
316
+ node = node.previousElementSibling;
317
+ }
318
+ return nextNode;
319
+ };
320
+ this.onKeyDown = (ev) => {
321
+ /**
322
+ * The below operations should be inverted when running on a mobile device.
323
+ * For example, swiping up will dispatch an "ArrowUp" event. On desktop,
324
+ * this should cause the previous option to be selected. On mobile, swiping
325
+ * up causes a view to scroll down. As a result, swiping up on mobile should
326
+ * cause the next option to be selected. The Home/End operations remain
327
+ * unchanged because those always represent the first/last options, respectively.
328
+ */
329
+ const mobile = isPlatform('mobile');
330
+ let newOption = null;
331
+ switch (ev.key) {
332
+ case 'ArrowDown':
333
+ newOption = mobile ? this.findPreviousOption() : this.findNextOption();
334
+ break;
335
+ case 'ArrowUp':
336
+ newOption = mobile ? this.findNextOption() : this.findPreviousOption();
337
+ break;
338
+ case 'PageUp':
339
+ newOption = mobile ? this.findNextOption(5) : this.findPreviousOption(5);
340
+ break;
341
+ case 'PageDown':
342
+ newOption = mobile ? this.findPreviousOption(5) : this.findNextOption(5);
343
+ break;
344
+ case 'Home':
345
+ /**
346
+ * There is no guarantee that the first child will be an ion-picker-column-option,
347
+ * so we do not use firstElementChild.
348
+ */
349
+ newOption = this.el.querySelector('ion-picker-column-option:first-of-type');
350
+ break;
351
+ case 'End':
352
+ /**
353
+ * There is no guarantee that the last child will be an ion-picker-column-option,
354
+ * so we do not use lastElementChild.
355
+ */
356
+ newOption = this.el.querySelector('ion-picker-column-option:last-of-type');
357
+ break;
358
+ default:
359
+ break;
360
+ }
361
+ if (newOption !== null) {
362
+ this.value = newOption.value;
363
+ // This stops any default browser behavior such as scrolling
364
+ ev.preventDefault();
365
+ }
366
+ };
367
+ /**
368
+ * Utility to generate the correct text for aria-valuetext.
369
+ */
370
+ this.getOptionValueText = (el) => {
371
+ var _a;
372
+ return el ? (_a = el.getAttribute('aria-label')) !== null && _a !== void 0 ? _a : el.innerText : '';
373
+ };
374
+ /**
375
+ * Render an element that overlays the column. This element is for assistive
376
+ * tech to allow users to navigate the column up/down. This element should receive
377
+ * focus as it listens for synthesized keyboard events as required by the
378
+ * slider role: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/slider_role
379
+ */
380
+ this.renderAssistiveFocusable = () => {
381
+ const { activeItem } = this;
382
+ const valueText = this.getOptionValueText(activeItem);
383
+ /**
384
+ * When using the picker, the valuetext provides important context that valuenow
385
+ * does not. Additionally, using non-zero valuemin/valuemax values can cause
386
+ * WebKit to incorrectly announce numeric valuetext values (such as a year
387
+ * like "2024") as percentages: https://bugs.webkit.org/show_bug.cgi?id=273126
388
+ */
389
+ return (h("div", { ref: (el) => (this.assistiveFocusable = el), class: "assistive-focusable", role: "slider", tabindex: this.disabled ? undefined : 0, "aria-label": this.ariaLabel, "aria-valuemin": 0, "aria-valuemax": 0, "aria-valuenow": 0, "aria-valuetext": valueText, "aria-orientation": "vertical", onKeyDown: (ev) => this.onKeyDown(ev) }));
390
+ };
391
+ this.ariaLabel = null;
248
392
  this.isActive = false;
249
393
  this.disabled = false;
250
394
  this.value = undefined;
251
395
  this.color = 'primary';
252
396
  this.numericInput = false;
253
397
  }
398
+ ariaLabelChanged(newValue) {
399
+ this.ariaLabel = newValue;
400
+ }
254
401
  valueChange() {
255
402
  if (this.isColumnVisible) {
256
403
  /**
@@ -366,6 +513,10 @@ export class PickerColumn {
366
513
  this.scrollEl.focus();
367
514
  }
368
515
  }
516
+ connectedCallback() {
517
+ var _a;
518
+ this.ariaLabel = (_a = this.el.getAttribute('aria-label')) !== null && _a !== void 0 ? _a : 'Select a value';
519
+ }
369
520
  get activeItem() {
370
521
  const { value } = this;
371
522
  const options = Array.from(this.el.querySelectorAll('ion-picker-column-option'));
@@ -383,14 +534,14 @@ export class PickerColumn {
383
534
  render() {
384
535
  const { color, disabled, isActive, numericInput } = this;
385
536
  const mode = getIonMode(this);
386
- return (h(Host, { key: '59648ef23cef1ab6d30955bb95bc23e670ec7256', class: createColorClasses(color, {
537
+ return (h(Host, { key: 'ced35afc6326a20dbac68193921a807a9c10bb99', class: createColorClasses(color, {
387
538
  [mode]: true,
388
539
  ['picker-column-active']: isActive,
389
540
  ['picker-column-numeric-input']: numericInput,
390
541
  ['picker-column-disabled']: disabled,
391
- }) }, h("slot", { key: 'fd93192d4945b2c33e0fe93cc90b505f2cec12fc', name: "prefix" }), h("div", { key: '99e49c6d58badd2fe5e75f0ebcd4bc00eb50aa58', class: "picker-opts", tabindex: disabled ? undefined : 0, ref: (el) => {
542
+ }) }, this.renderAssistiveFocusable(), h("slot", { key: '41e290dcc44dacb4237eb674ce2dedc7db66eb7d', name: "prefix" }), h("div", { key: '1fd869b063900103deadefc40929a1e8f02ec084', "aria-hidden": "true", class: "picker-opts", ref: (el) => {
392
543
  this.scrollEl = el;
393
- } }, h("div", { key: 'bb44892ef179b25373e45e4b4bc4d1fa617b1ea1', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: '9ee7aeb8468bbb03f7192d56849dae089b7a0250', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: '0baa4bda4bf02a8d06dbf3392b1516ca8ea8d26a', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("slot", { key: 'ff4cad20fd82ab66599473f60d10c18dc1dc76d8' }), h("div", { key: '04dcb0390209081e6223b90e45b8f2ef0fdf94bd', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: '734e3b431a30ce93957e1452516efc86e29ff9c9', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: '1c68dcf9a029e607bb6bc9c19cd02214914eb6d7', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0")), h("slot", { key: 'd85210cc99c8c1bf83eb1cd51540ebe875d4adeb', name: "suffix" })));
544
+ } }, h("div", { key: '0d2087f775b240c9b2534650eb27f3d99e7690a9', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: '1245b2bb2b6314c3ec4e0ab3ece4e42beb360fc9', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: '503b08f6bbe27fa7d34c165a93ec38ce7f1ad590', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("slot", { key: 'ec401a2b2d56546fb3f10239b71320ce7dc6a77d' }), h("div", { key: '97a234018291c5a6ca7a56bb1a9a417cac0b3e6f', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: '0197711f71486a8fa3c184b593cebe1c1e54c585', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: '961304f0a2a10afb3502ce4c5fbdceef0aa933cf', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0")), h("slot", { key: 'f38b83d26c3c2ba8ef00da7caf7f0be518b2007d', name: "suffix" })));
394
545
  }
395
546
  static get is() { return "ion-picker-column"; }
396
547
  static get encapsulation() { return "shadow"; }
@@ -490,6 +641,7 @@ export class PickerColumn {
490
641
  }
491
642
  static get states() {
492
643
  return {
644
+ "ariaLabel": {},
493
645
  "isActive": {}
494
646
  };
495
647
  }
@@ -502,7 +654,7 @@ export class PickerColumn {
502
654
  "composed": true,
503
655
  "docs": {
504
656
  "tags": [],
505
- "text": "Emitted when the value has changed."
657
+ "text": "Emitted when the value has changed.\n\nThis event will not emit when programmatically setting the `value` property."
506
658
  },
507
659
  "complexType": {
508
660
  "original": "PickerColumnChangeEventDetail",
@@ -594,6 +746,9 @@ export class PickerColumn {
594
746
  static get elementRef() { return "el"; }
595
747
  static get watchers() {
596
748
  return [{
749
+ "propName": "aria-label",
750
+ "methodName": "ariaLabelChanged"
751
+ }, {
597
752
  "propName": "value",
598
753
  "methodName": "valueChange"
599
754
  }];
@@ -0,0 +1,83 @@
1
+ /*!
2
+ * (C) Ionic http://ionicframework.com - MIT License
3
+ */
4
+ import { h } from "@stencil/core";
5
+ import { newSpecPage } from "@stencil/core/testing";
6
+ import { PickerColumn } from "../picker-column";
7
+ import { PickerColumnOption } from "../../picker-column-option/picker-column-option";
8
+ describe('picker-column: assistive element', () => {
9
+ beforeEach(() => {
10
+ const mockIntersectionObserver = jest.fn();
11
+ mockIntersectionObserver.mockReturnValue({
12
+ observe: () => null,
13
+ unobserve: () => null,
14
+ disconnect: () => null,
15
+ });
16
+ global.IntersectionObserver = mockIntersectionObserver;
17
+ });
18
+ it('should have a default label', async () => {
19
+ const page = await newSpecPage({
20
+ components: [PickerColumn],
21
+ template: () => h("ion-picker-column", null),
22
+ });
23
+ const pickerCol = page.body.querySelector('ion-picker-column');
24
+ const assistiveFocusable = pickerCol.shadowRoot.querySelector('.assistive-focusable');
25
+ expect(assistiveFocusable.getAttribute('aria-label')).not.toBe(null);
26
+ });
27
+ it('should have a custom label', async () => {
28
+ const page = await newSpecPage({
29
+ components: [PickerColumn],
30
+ template: () => h("ion-picker-column", { "aria-label": "my label" }),
31
+ });
32
+ const pickerCol = page.body.querySelector('ion-picker-column');
33
+ const assistiveFocusable = pickerCol.shadowRoot.querySelector('.assistive-focusable');
34
+ expect(assistiveFocusable.getAttribute('aria-label')).toBe('my label');
35
+ });
36
+ it('should update a custom label', async () => {
37
+ const page = await newSpecPage({
38
+ components: [PickerColumn],
39
+ template: () => h("ion-picker-column", null),
40
+ });
41
+ const pickerCol = page.body.querySelector('ion-picker-column');
42
+ const assistiveFocusable = pickerCol.shadowRoot.querySelector('.assistive-focusable');
43
+ pickerCol.setAttribute('aria-label', 'my label');
44
+ await page.waitForChanges();
45
+ expect(assistiveFocusable.getAttribute('aria-label')).toBe('my label');
46
+ });
47
+ it('should receive keyboard focus when enabled', async () => {
48
+ const page = await newSpecPage({
49
+ components: [PickerColumn],
50
+ template: () => h("ion-picker-column", null),
51
+ });
52
+ const pickerCol = page.body.querySelector('ion-picker-column');
53
+ const assistiveFocusable = pickerCol.shadowRoot.querySelector('.assistive-focusable');
54
+ expect(assistiveFocusable.tabIndex).toBe(0);
55
+ });
56
+ it('should not receive keyboard focus when disabled', async () => {
57
+ const page = await newSpecPage({
58
+ components: [PickerColumn],
59
+ template: () => h("ion-picker-column", { disabled: true }),
60
+ });
61
+ const pickerCol = page.body.querySelector('ion-picker-column');
62
+ const assistiveFocusable = pickerCol.shadowRoot.querySelector('.assistive-focusable');
63
+ expect(assistiveFocusable.tabIndex).toBe(-1);
64
+ });
65
+ it('should use option aria-label as assistive element aria-valuetext', async () => {
66
+ const page = await newSpecPage({
67
+ components: [PickerColumn, PickerColumnOption],
68
+ template: () => (h("ion-picker-column", { value: 1 }, h("ion-picker-column-option", { value: 1, "aria-label": "My Label" }, "My Text"))),
69
+ });
70
+ const pickerCol = page.body.querySelector('ion-picker-column');
71
+ const assistiveFocusable = pickerCol.shadowRoot.querySelector('.assistive-focusable');
72
+ expect(assistiveFocusable.getAttribute('aria-valuetext')).toBe('My Label');
73
+ });
74
+ it('should use option text as assistive element aria-valuetext when no label provided', async () => {
75
+ const page = await newSpecPage({
76
+ components: [PickerColumn, PickerColumnOption],
77
+ template: () => (h("ion-picker-column", { value: 1 }, h("ion-picker-column-option", { value: 1 }, "My Text"))),
78
+ });
79
+ const pickerCol = page.body.querySelector('ion-picker-column');
80
+ const assistiveFocusable = pickerCol.shadowRoot.querySelector('.assistive-focusable');
81
+ expect(assistiveFocusable.getAttribute('aria-valuetext')).toBe('My Text');
82
+ });
83
+ });
@@ -76,10 +76,10 @@ export class PickerColumnOption {
76
76
  render() {
77
77
  const { color, disabled, ariaLabel } = this;
78
78
  const mode = getIonMode(this);
79
- return (h(Host, { key: 'c743c6ef44bb9f765cc15b3b5d2864de6520203a', class: createColorClasses(color, {
79
+ return (h(Host, { key: 'cc4435a0ce0e55be1321bcabaf342ed68cf5ba1e', class: createColorClasses(color, {
80
80
  [mode]: true,
81
81
  ['option-disabled']: disabled,
82
- }) }, h("button", { key: '4c3d9eb245c52b2c007f727e145cfb55759bd7a9', tabindex: "-1", "aria-label": ariaLabel, disabled: disabled, onClick: () => this.onClick() }, h("slot", { key: '4c907d2187cbe9d5941e27f2b12578e2b7271461' }))));
82
+ }) }, h("button", { key: '0187fb967771e0787807a8538dce4e59f6a98565', tabindex: "-1", "aria-label": ariaLabel, disabled: disabled, onClick: () => this.onClick() }, h("slot", { key: 'dbe52552f3f27332816748c12d929cc81060841d' }))));
83
83
  }
84
84
  static get is() { return "ion-picker-column-option"; }
85
85
  static get encapsulation() { return "shadow"; }
@@ -182,11 +182,11 @@ export class Picker {
182
182
  render() {
183
183
  const { htmlAttributes } = this;
184
184
  const mode = getIonMode(this);
185
- return (h(Host, Object.assign({ key: 'cb1495acc8842c00e9f51ae792a01f769e36b0c6', "aria-modal": "true", tabindex: "-1" }, htmlAttributes, { style: {
185
+ return (h(Host, Object.assign({ key: '26e3144adcdf01605271d01e468bb4a75ce854b1', "aria-modal": "true", tabindex: "-1" }, htmlAttributes, { style: {
186
186
  zIndex: `${20000 + this.overlayIndex}`,
187
187
  }, class: Object.assign({ [mode]: true,
188
188
  // Used internally for styling
189
- [`picker-${mode}`]: true, 'overlay-hidden': true }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonPickerWillDismiss: this.dispatchCancelHandler }), h("ion-backdrop", { key: 'eecbcdfd474f5ab2f9962a030b1dcbf7714fe938', visible: this.showBackdrop, tappable: this.backdropDismiss }), h("div", { key: '262e1d3bc916b30068f7be1edbc73283a815fc0f', tabindex: "0" }), h("div", { key: 'a036cf789ab768428aae26a19dbd0c5cb696188c', class: "picker-wrapper ion-overlay-wrapper", role: "dialog" }, h("div", { key: '6be7a8986976ead39611ce398ed6ad71f3b7427e', class: "picker-toolbar" }, this.buttons.map((b) => (h("div", { class: buttonWrapperClass(b) }, h("button", { type: "button", onClick: () => this.buttonClick(b), class: buttonClass(b) }, b.text))))), h("div", { key: '66a1d99aebf48219cab4177d06d893fe1d458a1f', class: "picker-columns" }, h("div", { key: 'ed7fd940c5f54453587e13ab52cbfd4122a397c6', class: "picker-above-highlight" }), this.presented && this.columns.map((c) => h("ion-picker-legacy-column", { col: c })), h("div", { key: '21c491c08bce126dde03196b21e28d903e157e1f', class: "picker-below-highlight" }))), h("div", { key: 'bd892f74b886ae1bfd010d687a2b9741213b246c', tabindex: "0" })));
189
+ [`picker-${mode}`]: true, 'overlay-hidden': true }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonPickerWillDismiss: this.dispatchCancelHandler }), h("ion-backdrop", { key: 'fa212d21406606186cd95f8c7a4f119696ac8d4a', visible: this.showBackdrop, tappable: this.backdropDismiss }), h("div", { key: '19ea889f65cb6a68a9db26cf9f83c6587cfcf07e', tabindex: "0" }), h("div", { key: '5fc0f5d26915ba353b9f0335946f94b6fda95e1e', class: "picker-wrapper ion-overlay-wrapper", role: "dialog" }, h("div", { key: '3fa5bff4ac0013ef31845482a27a14caebbdcd2f', class: "picker-toolbar" }, this.buttons.map((b) => (h("div", { class: buttonWrapperClass(b) }, h("button", { type: "button", onClick: () => this.buttonClick(b), class: buttonClass(b) }, b.text))))), h("div", { key: '2ff6376956d01dcd9ec01b8d6972dd4b37ffb1a1', class: "picker-columns" }, h("div", { key: '4adcef77429f10a3faa50b41d1eaf3404387997c', class: "picker-above-highlight" }), this.presented && this.columns.map((c) => h("ion-picker-legacy-column", { col: c })), h("div", { key: 'e0f37d3e9896eb2bc0f0aef4762a897130851963', class: "picker-below-highlight" }))), h("div", { key: '671bb7d0f487b0d7c7fa70388f8fa1de77448b9f', tabindex: "0" })));
190
190
  }
191
191
  static get is() { return "ion-picker-legacy"; }
192
192
  static get encapsulation() { return "scoped"; }
@@ -336,9 +336,9 @@ export class PickerColumnCmp {
336
336
  render() {
337
337
  const col = this.col;
338
338
  const mode = getIonMode(this);
339
- return (h(Host, { key: 'c015eb8bc01b3287cbd1d71af0aa311b6be89d36', class: Object.assign({ [mode]: true, 'picker-col': true, 'picker-opts-left': this.col.align === 'left', 'picker-opts-right': this.col.align === 'right' }, getClassMap(col.cssClass)), style: {
339
+ return (h(Host, { key: '56289a294e5c580f3e7fe5fc12777aa7f80ad19b', class: Object.assign({ [mode]: true, 'picker-col': true, 'picker-opts-left': this.col.align === 'left', 'picker-opts-right': this.col.align === 'right' }, getClassMap(col.cssClass)), style: {
340
340
  'max-width': this.col.columnWidth,
341
- } }, col.prefix && (h("div", { key: 'f9de3fe2f5c7ad3256d6e5f44b6d03a2b1f96ffb', class: "picker-prefix", style: { width: col.prefixWidth } }, col.prefix)), h("div", { key: '10f9c12aa174f96c7cf9adc30efbb26695c0aa64', class: "picker-opts", style: { maxWidth: col.optionsWidth }, ref: (el) => (this.optsEl = el) }, col.options.map((o, index) => (h("button", { "aria-label": o.ariaLabel, class: { 'picker-opt': true, 'picker-opt-disabled': !!o.disabled }, "opt-index": index }, o.text)))), col.suffix && (h("div", { key: '1d9c0892ce56e0da9044c79eb953827166f5190b', class: "picker-suffix", style: { width: col.suffixWidth } }, col.suffix))));
341
+ } }, col.prefix && (h("div", { key: 'd21f44667b5df567d6879723fe643ea7c2c60bef', class: "picker-prefix", style: { width: col.prefixWidth } }, col.prefix)), h("div", { key: 'bb427e5f24fd832703926e0e847ad05567597262', class: "picker-opts", style: { maxWidth: col.optionsWidth }, ref: (el) => (this.optsEl = el) }, col.options.map((o, index) => (h("button", { "aria-label": o.ariaLabel, class: { 'picker-opt': true, 'picker-opt-disabled': !!o.disabled }, "opt-index": index }, o.text)))), col.suffix && (h("div", { key: '0413f7c074b6534b8967387ecb9957a79a267aff', class: "picker-suffix", style: { width: col.suffixWidth } }, col.suffix))));
342
342
  }
343
343
  static get is() { return "ion-picker-legacy-column"; }
344
344
  static get originalStyleUrls() {
@@ -7,7 +7,7 @@ import { CoreDelegate, attachComponent, detachComponent } from "../../utils/fram
7
7
  import { addEventListener, raf, hasLazyBuild } from "../../utils/helpers";
8
8
  import { createLockController } from "../../utils/lock-controller";
9
9
  import { printIonWarning } from "../../utils/logging/index";
10
- import { BACKDROP, dismiss, eventMethod, prepareOverlay, present, setOverlayId } from "../../utils/overlays";
10
+ import { BACKDROP, dismiss, eventMethod, prepareOverlay, present, setOverlayId, FOCUS_TRAP_DISABLE_CLASS, } from "../../utils/overlays";
11
11
  import { isPlatform } from "../../utils/platform";
12
12
  import { getClassMap } from "../../utils/theme";
13
13
  import { deepReady, waitForMount } from "../../utils/transition/index";
@@ -107,6 +107,7 @@ export class Popover {
107
107
  this.arrow = true;
108
108
  this.isOpen = false;
109
109
  this.keyboardEvents = false;
110
+ this.focusTrap = true;
110
111
  this.keepContentsMounted = false;
111
112
  }
112
113
  onTriggerChange() {
@@ -333,12 +334,12 @@ export class Popover {
333
334
  }
334
335
  render() {
335
336
  const mode = getIonMode(this);
336
- const { onLifecycle, parentPopover, dismissOnSelect, side, arrow, htmlAttributes } = this;
337
+ const { onLifecycle, parentPopover, dismissOnSelect, side, arrow, htmlAttributes, focusTrap } = this;
337
338
  const desktop = isPlatform('desktop');
338
339
  const enableArrow = arrow && !parentPopover;
339
- return (h(Host, Object.assign({ key: '4bccccf57df72e1196c6a28e803831c0520aef53', "aria-modal": "true", "no-router": true, tabindex: "-1" }, htmlAttributes, { style: {
340
+ return (h(Host, Object.assign({ key: '17e5e8b3e7ba5e251665fb9d0ade10c781f82f0e', "aria-modal": "true", "no-router": true, tabindex: "-1" }, htmlAttributes, { style: {
340
341
  zIndex: `${20000 + this.overlayIndex}`,
341
- }, class: Object.assign(Object.assign({}, getClassMap(this.cssClass)), { [mode]: true, 'popover-translucent': this.translucent, 'overlay-hidden': true, 'popover-desktop': desktop, [`popover-side-${side}`]: true, 'popover-nested': !!parentPopover }), onIonPopoverDidPresent: onLifecycle, onIonPopoverWillPresent: onLifecycle, onIonPopoverWillDismiss: onLifecycle, onIonPopoverDidDismiss: onLifecycle, onIonBackdropTap: this.onBackdropTap }), !parentPopover && h("ion-backdrop", { key: 'e42f4f61150b7b41093d37d187d1b7bb4187a00e', tappable: this.backdropDismiss, visible: this.showBackdrop, part: "backdrop" }), h("div", { key: '386ac3247b0f82566aae07b6dbf5e97d243ce367', class: "popover-wrapper ion-overlay-wrapper", onClick: dismissOnSelect ? () => this.dismiss() : undefined }, enableArrow && h("div", { key: '28f0e5ea2fa099b808ffb77a9a0d78b8b46c1513', class: "popover-arrow", part: "arrow" }), h("div", { key: '7ba2e3dee529015c4e07ce78ec10dc59985ec6a2', class: "popover-content", part: "content" }, h("slot", { key: '915cdc8e389fda210f83aec8b7bbbfa6f830a884' })))));
342
+ }, class: Object.assign(Object.assign({}, getClassMap(this.cssClass)), { [mode]: true, 'popover-translucent': this.translucent, 'overlay-hidden': true, 'popover-desktop': desktop, [`popover-side-${side}`]: true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false, 'popover-nested': !!parentPopover }), onIonPopoverDidPresent: onLifecycle, onIonPopoverWillPresent: onLifecycle, onIonPopoverWillDismiss: onLifecycle, onIonPopoverDidDismiss: onLifecycle, onIonBackdropTap: this.onBackdropTap }), !parentPopover && h("ion-backdrop", { key: 'c12fb94b375d7e88a0c5d715440c0f66ad7ee817', tappable: this.backdropDismiss, visible: this.showBackdrop, part: "backdrop" }), h("div", { key: '478b388cc9a5a382003a2863e968e77a174914ab', class: "popover-wrapper ion-overlay-wrapper", onClick: dismissOnSelect ? () => this.dismiss() : undefined }, enableArrow && h("div", { key: 'f1c63a0079f197a8d4577e7c00a654871fb9d816', class: "popover-arrow", part: "arrow" }), h("div", { key: '08b62a321c09ad4b0f90460468ecbc1d56320bf1', class: "popover-content", part: "content" }, h("slot", { key: '55645ff597f64d434219caa28015cf2a4ceb0ee5' })))));
342
343
  }
343
344
  static get is() { return "ion-popover"; }
344
345
  static get encapsulation() { return "shadow"; }
@@ -860,6 +861,24 @@ export class Popover {
860
861
  "reflect": false,
861
862
  "defaultValue": "false"
862
863
  },
864
+ "focusTrap": {
865
+ "type": "boolean",
866
+ "mutable": false,
867
+ "complexType": {
868
+ "original": "boolean",
869
+ "resolved": "boolean",
870
+ "references": {}
871
+ },
872
+ "required": false,
873
+ "optional": false,
874
+ "docs": {
875
+ "tags": [],
876
+ "text": "If `true`, focus will not be allowed to move outside of this overlay.\nIf `false`, focus will be allowed to move outside of the overlay.\n\nIn most scenarios this property should remain set to `true`. Setting\nthis property to `false` can cause severe accessibility issues as users\nrelying on assistive technologies may be able to move focus into\na confusing state. We recommend only setting this to `false` when\nabsolutely necessary.\n\nDevelopers may want to consider disabling focus trapping if this\noverlay presents a non-Ionic overlay from a 3rd party library.\nDevelopers would disable focus trapping on the Ionic overlay\nwhen presenting the 3rd party overlay and then re-enable\nfocus trapping when dismissing the 3rd party overlay and moving\nfocus back to the Ionic overlay."
877
+ },
878
+ "attribute": "focus-trap",
879
+ "reflect": false,
880
+ "defaultValue": "true"
881
+ },
863
882
  "keepContentsMounted": {
864
883
  "type": "boolean",
865
884
  "mutable": false,