@ionic/core 9.0.1-dev.11787248963.10a00c73 → 9.0.1-dev.11787949960.1e63841c

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 (456) hide show
  1. package/components/index.js +1 -1
  2. package/components/ion-accordion-group.js +1 -1
  3. package/components/ion-accordion.js +1 -1
  4. package/components/ion-action-sheet.js +1 -1
  5. package/components/ion-alert.js +1 -1
  6. package/components/ion-app.js +1 -1
  7. package/components/ion-avatar.js +1 -1
  8. package/components/ion-back-button.js +1 -1
  9. package/components/ion-backdrop.js +1 -1
  10. package/components/ion-badge.js +1 -1
  11. package/components/ion-breadcrumb.js +1 -1
  12. package/components/ion-breadcrumbs.js +1 -1
  13. package/components/ion-button.js +1 -1
  14. package/components/ion-buttons.js +1 -1
  15. package/components/ion-card-content.js +1 -1
  16. package/components/ion-card-header.js +1 -1
  17. package/components/ion-card-subtitle.js +1 -1
  18. package/components/ion-card-title.js +1 -1
  19. package/components/ion-card.js +1 -1
  20. package/components/ion-checkbox.js +1 -1
  21. package/components/ion-chip.js +1 -1
  22. package/components/ion-col.js +1 -1
  23. package/components/ion-content.js +1 -1
  24. package/components/ion-datetime-button.js +1 -1
  25. package/components/ion-datetime.js +1 -1
  26. package/components/ion-fab-button.js +1 -1
  27. package/components/ion-fab-list.js +1 -1
  28. package/components/ion-fab.js +1 -1
  29. package/components/ion-footer.js +1 -1
  30. package/components/ion-grid.js +1 -1
  31. package/components/ion-header.js +1 -1
  32. package/components/ion-icon.js +1 -1
  33. package/components/ion-img.js +1 -1
  34. package/components/ion-infinite-scroll-content.js +1 -1
  35. package/components/ion-infinite-scroll.js +1 -1
  36. package/components/ion-input-otp.js +1 -1
  37. package/components/ion-input-password-toggle.js +1 -1
  38. package/components/ion-input.js +1 -1
  39. package/components/ion-item-divider.js +1 -1
  40. package/components/ion-item-group.js +1 -1
  41. package/components/ion-item-option.js +1 -1
  42. package/components/ion-item-options.js +1 -1
  43. package/components/ion-item-sliding.js +1 -1
  44. package/components/ion-item.js +1 -1
  45. package/components/ion-label.js +1 -1
  46. package/components/ion-list-header.js +1 -1
  47. package/components/ion-list.js +1 -1
  48. package/components/ion-loading.js +1 -1
  49. package/components/ion-menu-button.js +1 -1
  50. package/components/ion-menu-toggle.js +1 -1
  51. package/components/ion-menu.js +1 -1
  52. package/components/ion-modal.js +1 -1
  53. package/components/ion-nav-link.js +1 -1
  54. package/components/ion-nav.js +1 -1
  55. package/components/ion-note.js +1 -1
  56. package/components/ion-picker-column-option.js +1 -1
  57. package/components/ion-picker-column.js +1 -1
  58. package/components/ion-picker.js +1 -1
  59. package/components/ion-popover.js +1 -1
  60. package/components/ion-progress-bar.js +1 -1
  61. package/components/ion-radio-group.js +1 -1
  62. package/components/ion-radio.js +1 -1
  63. package/components/ion-range.js +1 -1
  64. package/components/ion-refresher-content.js +1 -1
  65. package/components/ion-refresher.js +1 -1
  66. package/components/ion-reorder-group.js +1 -1
  67. package/components/ion-reorder.js +1 -1
  68. package/components/ion-ripple-effect.js +1 -1
  69. package/components/ion-route-redirect.js +1 -1
  70. package/components/ion-route.js +1 -1
  71. package/components/ion-router-link.js +1 -1
  72. package/components/ion-router-outlet.js +1 -1
  73. package/components/ion-router.js +1 -1
  74. package/components/ion-row.js +1 -1
  75. package/components/ion-searchbar.js +1 -1
  76. package/components/ion-segment-button.js +1 -1
  77. package/components/ion-segment-content.js +1 -1
  78. package/components/ion-segment-view.js +1 -1
  79. package/components/ion-segment.js +1 -1
  80. package/components/ion-select-modal.js +1 -1
  81. package/components/ion-select-option.js +1 -1
  82. package/components/ion-select-popover.js +1 -1
  83. package/components/ion-select.js +1 -1
  84. package/components/ion-skeleton-text.js +1 -1
  85. package/components/ion-spinner.js +1 -1
  86. package/components/ion-split-pane.js +1 -1
  87. package/components/ion-tab-bar.js +1 -1
  88. package/components/ion-tab-button.js +1 -1
  89. package/components/ion-tab.js +1 -1
  90. package/components/ion-tabs.js +1 -1
  91. package/components/ion-text.js +1 -1
  92. package/components/ion-textarea.js +1 -1
  93. package/components/ion-thumbnail.js +1 -1
  94. package/components/ion-title.js +1 -1
  95. package/components/ion-toast.js +1 -1
  96. package/components/ion-toggle.js +1 -1
  97. package/components/ion-toolbar.js +1 -1
  98. package/components/{p-gFwXiYC_.js → p-5rFO7X8J.js} +1 -1
  99. package/components/{p-BpLt_Ptn.js → p-7qDu1bID.js} +1 -1
  100. package/components/{p-7PNwKFZi.js → p-B2L09UOs.js} +1 -1
  101. package/components/{p-DcOH6-o5.js → p-BAJ7NctL.js} +1 -1
  102. package/components/{p-Kmrg3Fed.js → p-BE9noJ1O.js} +1 -1
  103. package/components/{p-CgvDC7hC.js → p-BFwL2yyK.js} +1 -1
  104. package/components/{p-DysqCsJu.js → p-BWHBdLfY.js} +1 -1
  105. package/components/{p-SR-LLqp_.js → p-Bcm-GVQM.js} +1 -1
  106. package/{dist/ionic/p-9wczfs_v.js → components/p-BcuLPPAE.js} +1 -1
  107. package/components/p-BhlP16sB.js +4 -0
  108. package/components/{p-H1f2qsk4.js → p-BqE7e5gH.js} +1 -1
  109. package/components/{p-BqBDq1Ma.js → p-C12SAK00.js} +1 -1
  110. package/components/p-C8Tp0cQy.js +4 -0
  111. package/components/{p-A8MJRBIY.js → p-C8mPeq0D.js} +1 -1
  112. package/components/{p-Bx2saTHs.js → p-CB06XtlF.js} +1 -1
  113. package/components/{p-BgUIV8NQ.js → p-CBhGZ6rF.js} +1 -1
  114. package/components/{p-B8MQjdvk.js → p-CDKY4TZ_.js} +1 -1
  115. package/components/{p-CWETxTjE.js → p-CEkamjav.js} +1 -1
  116. package/components/p-CFtAWaB6.js +4 -0
  117. package/components/{p-DEW7CnUc.js → p-CJTKYpZv.js} +1 -1
  118. package/components/{p-BA_4ZIEg.js → p-CLZPNP7x.js} +1 -1
  119. package/components/{p-tX3UxCnU.js → p-COxY7PLK.js} +1 -1
  120. package/components/p-CQxPXWNM.js +4 -0
  121. package/components/{p-DDdkefwf.js → p-CRcX0EGs.js} +1 -1
  122. package/components/p-CVNvmbDp.js +4 -0
  123. package/components/p-CXpy69Ei.js +4 -0
  124. package/{dist/ionic/p-BZxjcGRP.js → components/p-CdSLe3Q3.js} +1 -1
  125. package/components/p-CoGD-oMG.js +4 -0
  126. package/components/p-CpYeYl3u.js +4 -0
  127. package/components/{p-CaiZOhfC.js → p-CuS0-WwK.js} +1 -1
  128. package/components/{p-Bnc0m4SW.js → p-CxiXpCtB.js} +1 -1
  129. package/components/{p-BFtL8t1r.js → p-CyKlfXdt.js} +1 -1
  130. package/components/p-D2XJVty5.js +4 -0
  131. package/components/p-DALTMT_o.js +4 -0
  132. package/{dist/ionic/p-D0dfUysx.js → components/p-DG-dUCKp.js} +1 -1
  133. package/{dist/ionic/p-DF_Uqql8.js → components/p-DH0rRXjx.js} +1 -1
  134. package/components/{p-D7ysFE2B.js → p-DMkSsriG.js} +1 -1
  135. package/components/{p-B6x5_b9w.js → p-DkEb3SCT.js} +1 -1
  136. package/components/p-Dr-rBSUW.js +4 -0
  137. package/components/p-MHpJ2A_m.js +4 -0
  138. package/components/p-N6lZFXYR.js +4 -0
  139. package/components/p-QgdyH-Zs.js +4 -0
  140. package/components/{p-BMfgF-Tv.js → p-RRH-7cpd.js} +1 -1
  141. package/components/p-UKksD3f9.js +4 -0
  142. package/components/{p-v2NpoOHp.js → p-VTfnz_8u.js} +1 -1
  143. package/components/p-fP0QF3iG.js +4 -0
  144. package/components/{p-BPDxVIRr.js → p-l-zxxFre.js} +1 -1
  145. package/components/{p-BrFaQbGY.js → p-mXsQnyWB.js} +1 -1
  146. package/components/p-ntAkt4Ra.js +4 -0
  147. package/components/p-ufB0gCSU.js +4 -0
  148. package/components/p-z-BF3clL.js +4 -0
  149. package/css/core.css +1 -1
  150. package/css/core.css.map +1 -1
  151. package/css/ionic.bundle.css +1 -1
  152. package/css/ionic.bundle.css.map +1 -1
  153. package/dist/cjs/{animation-D-OqR4a4.js → animation-ihPP_z2n.js} +1 -1
  154. package/dist/cjs/{app-globals-BzgwARwJ.js → app-globals-BlkzA410.js} +1 -1
  155. package/dist/cjs/{button-active-BlWSD7uK.js → button-active-ItGBjzmO.js} +1 -1
  156. package/dist/cjs/{format-D7ig6Vm0.js → format-CPIqtp4x.js} +1 -1
  157. package/dist/cjs/{framework-delegate-BZUx4TnE.js → framework-delegate-DhyWUPGg.js} +1 -1
  158. package/dist/cjs/{hardware-back-button-JOAEFSzc.js → hardware-back-button-D5f_kASb.js} +1 -1
  159. package/dist/cjs/{helpers-Dj5o76mq.js → helpers-BCLkFTTd.js} +1 -1
  160. package/dist/cjs/{index-C8zH6b3d.js → index-49DTLc_Z.js} +2 -2
  161. package/dist/cjs/{index-CZ6vzt_q.js → index-BcyiqD6R.js} +5 -5
  162. package/dist/cjs/{index-BrVMoqUk.js → index-Bgz6BcKx.js} +50 -16
  163. package/dist/cjs/{index-EJLjthTK.js → index-BocV_y-c.js} +2 -1
  164. package/dist/cjs/{index-2sO-zkZ2.js → index-CldjPPyP.js} +4 -4
  165. package/dist/cjs/{index-Csue6G3m.js → index-xum7jdbq.js} +2 -2
  166. package/dist/cjs/index.cjs.js +12 -12
  167. package/dist/cjs/{input-shims-Bh7bnt2v.js → input-shims-Jisy7U7-.js} +3 -3
  168. package/dist/cjs/{input.utils-Cq3g9uHy.js → input.utils-BDTpGrfn.js} +1 -1
  169. package/dist/cjs/ion-accordion_2.cjs.entry.js +3 -3
  170. package/dist/cjs/ion-action-sheet.cjs.entry.js +45 -29
  171. package/dist/cjs/ion-alert.cjs.entry.js +29 -21
  172. package/dist/cjs/ion-app_8.cjs.entry.js +38 -16
  173. package/dist/cjs/ion-avatar_3.cjs.entry.js +2 -2
  174. package/dist/cjs/ion-back-button.cjs.entry.js +3 -3
  175. package/dist/cjs/ion-backdrop.cjs.entry.js +2 -2
  176. package/dist/cjs/ion-breadcrumb_2.cjs.entry.js +3 -3
  177. package/dist/cjs/ion-button_2.cjs.entry.js +3 -3
  178. package/dist/cjs/ion-card_5.cjs.entry.js +3 -3
  179. package/dist/cjs/ion-checkbox.cjs.entry.js +4 -4
  180. package/dist/cjs/ion-chip.cjs.entry.js +2 -2
  181. package/dist/cjs/ion-col_3.cjs.entry.js +2 -2
  182. package/dist/cjs/ion-datetime-button.cjs.entry.js +4 -4
  183. package/dist/cjs/ion-datetime.cjs.entry.js +32 -24
  184. package/dist/cjs/ion-fab_3.cjs.entry.js +3 -3
  185. package/dist/cjs/ion-img.cjs.entry.js +3 -3
  186. package/dist/cjs/ion-infinite-scroll_2.cjs.entry.js +5 -5
  187. package/dist/cjs/ion-input-otp.cjs.entry.js +3 -3
  188. package/dist/cjs/ion-input-password-toggle.cjs.entry.js +2 -2
  189. package/dist/cjs/ion-input.cjs.entry.js +5 -5
  190. package/dist/cjs/ion-item-option_3.cjs.entry.js +4 -4
  191. package/dist/cjs/ion-item_8.cjs.entry.js +3 -3
  192. package/dist/cjs/ion-loading.cjs.entry.js +14 -10
  193. package/dist/cjs/ion-menu_3.cjs.entry.js +8 -8
  194. package/dist/cjs/ion-modal.cjs.entry.js +85 -32
  195. package/dist/cjs/ion-nav_2.cjs.entry.js +6 -6
  196. package/dist/cjs/ion-picker-column-option.cjs.entry.js +3 -3
  197. package/dist/cjs/ion-picker-column.cjs.entry.js +210 -46
  198. package/dist/cjs/ion-picker.cjs.entry.js +2 -2
  199. package/dist/cjs/ion-popover.cjs.entry.js +23 -10
  200. package/dist/cjs/ion-progress-bar.cjs.entry.js +3 -3
  201. package/dist/cjs/ion-radio_2.cjs.entry.js +4 -4
  202. package/dist/cjs/ion-range.cjs.entry.js +4 -4
  203. package/dist/cjs/ion-refresher_2.cjs.entry.js +6 -6
  204. package/dist/cjs/ion-reorder_2.cjs.entry.js +4 -4
  205. package/dist/cjs/ion-ripple-effect.cjs.entry.js +2 -2
  206. package/dist/cjs/ion-route_4.cjs.entry.js +4 -4
  207. package/dist/cjs/ion-searchbar.cjs.entry.js +3 -3
  208. package/dist/cjs/ion-segment-content.cjs.entry.js +1 -1
  209. package/dist/cjs/ion-segment-view.cjs.entry.js +1 -1
  210. package/dist/cjs/ion-segment_2.cjs.entry.js +3 -3
  211. package/dist/cjs/ion-select-modal.cjs.entry.js +8 -8
  212. package/dist/cjs/ion-select_3.cjs.entry.js +57 -47
  213. package/dist/cjs/ion-spinner.cjs.entry.js +2 -2
  214. package/dist/cjs/ion-split-pane.cjs.entry.js +2 -2
  215. package/dist/cjs/ion-tab-bar_2.cjs.entry.js +3 -3
  216. package/dist/cjs/ion-tab_2.cjs.entry.js +3 -3
  217. package/dist/cjs/ion-text.cjs.entry.js +2 -2
  218. package/dist/cjs/ion-textarea.cjs.entry.js +5 -5
  219. package/dist/cjs/ion-toast.cjs.entry.js +8 -8
  220. package/dist/cjs/ion-toggle.cjs.entry.js +4 -4
  221. package/dist/cjs/{ionic-global-DvgIzM2F.js → ionic-global-BMU-Us1Q.js} +1 -1
  222. package/dist/cjs/ionic.cjs.js +4 -4
  223. package/dist/cjs/{ios.transition-zIgdoSYe.js → ios.transition-OCcCN--B.js} +4 -4
  224. package/dist/cjs/{item-multiple-inputs-DG-ZGm6j.js → item-multiple-inputs-BH9yPC66.js} +1 -1
  225. package/dist/cjs/loader.cjs.js +3 -3
  226. package/dist/cjs/{md.transition-CXeJ9rfh.js → md.transition-D0o2IIbo.js} +4 -4
  227. package/dist/cjs/{overlays-Bg0auTQa.js → overlays-HN9joo1Z.js} +59 -34
  228. package/dist/cjs/{select-option-render-7m1WdFzF.js → select-option-render-BPjGDlsG.js} +2 -2
  229. package/dist/cjs/{slot-mutation-controller-BJEJzx_e.js → slot-mutation-controller-IQ250LoG.js} +1 -1
  230. package/dist/cjs/{status-tap-DxbUM5XX.js → status-tap-Bakl9czs.js} +3 -3
  231. package/dist/cjs/{swipe-back-F_DBt-Aw.js → swipe-back-Cv4OZVJ5.js} +2 -2
  232. package/dist/collection/collection-manifest.json +1 -1
  233. package/dist/collection/components/action-sheet/action-sheet.js +36 -20
  234. package/dist/collection/components/alert/alert.js +20 -12
  235. package/dist/collection/components/content/content.js +26 -4
  236. package/dist/collection/components/datetime/datetime.js +25 -17
  237. package/dist/collection/components/loading/loading.js +7 -3
  238. package/dist/collection/components/modal/modal.ios.css +12 -1
  239. package/dist/collection/components/modal/modal.js +75 -22
  240. package/dist/collection/components/modal/modal.md.css +12 -1
  241. package/dist/collection/components/picker-column/picker-column.js +207 -43
  242. package/dist/collection/components/popover/popover.js +16 -3
  243. package/dist/collection/components/select/select.js +49 -39
  244. package/dist/collection/utils/overlays.js +53 -29
  245. package/dist/collection/utils/test/playwright/detach-reattach.js +23 -0
  246. package/dist/collection/utils/test/playwright/index.js +1 -0
  247. package/dist/docs.json +279 -48
  248. package/dist/esm/{animation-TxGPYeDn.js → animation-B6KGUJwl.js} +1 -1
  249. package/dist/esm/{app-globals-Do8rJest.js → app-globals-BvutUX8P.js} +1 -1
  250. package/dist/esm/{button-active-ChA4D-ml.js → button-active-DRNebs9r.js} +1 -1
  251. package/dist/esm/{format-CVk5e_GP.js → format-BF3btM7P.js} +1 -1
  252. package/dist/esm/{framework-delegate-DaLWnISz.js → framework-delegate-60cEIAgt.js} +1 -1
  253. package/dist/esm/{hardware-back-button-D8W4L0JP.js → hardware-back-button-rhkwRNk2.js} +1 -1
  254. package/dist/esm/{helpers-BIgoInJU.js → helpers-DLLANtRS.js} +1 -1
  255. package/dist/esm/{index-C8Dsa6li.js → index-BZHVn0iF.js} +4 -4
  256. package/dist/esm/{index-DHw2lZxe.js → index-Bl4BUvBL.js} +2 -2
  257. package/dist/esm/{index-BmOR8tCv.js → index-DOrtAUWV.js} +2 -2
  258. package/dist/esm/{index-C5ZdL0qp.js → index-D_7MeuVD.js} +5 -5
  259. package/dist/esm/{index-elneMH8y.js → index-JgU5uTSY.js} +2 -2
  260. package/dist/esm/{index-CKYcsw8f.js → index-h81G-QbJ.js} +50 -16
  261. package/dist/esm/index.js +12 -12
  262. package/dist/esm/{input-shims-09NN97kF.js → input-shims-C2ipc_XX.js} +3 -3
  263. package/dist/esm/{input.utils-BxyH9l1w.js → input.utils-D-qoPjqr.js} +1 -1
  264. package/dist/esm/ion-accordion_2.entry.js +3 -3
  265. package/dist/esm/ion-action-sheet.entry.js +45 -29
  266. package/dist/esm/ion-alert.entry.js +29 -21
  267. package/dist/esm/ion-app_8.entry.js +38 -16
  268. package/dist/esm/ion-avatar_3.entry.js +2 -2
  269. package/dist/esm/ion-back-button.entry.js +3 -3
  270. package/dist/esm/ion-backdrop.entry.js +2 -2
  271. package/dist/esm/ion-breadcrumb_2.entry.js +3 -3
  272. package/dist/esm/ion-button_2.entry.js +3 -3
  273. package/dist/esm/ion-card_5.entry.js +3 -3
  274. package/dist/esm/ion-checkbox.entry.js +4 -4
  275. package/dist/esm/ion-chip.entry.js +2 -2
  276. package/dist/esm/ion-col_3.entry.js +2 -2
  277. package/dist/esm/ion-datetime-button.entry.js +4 -4
  278. package/dist/esm/ion-datetime.entry.js +32 -24
  279. package/dist/esm/ion-fab_3.entry.js +3 -3
  280. package/dist/esm/ion-img.entry.js +3 -3
  281. package/dist/esm/ion-infinite-scroll_2.entry.js +5 -5
  282. package/dist/esm/ion-input-otp.entry.js +3 -3
  283. package/dist/esm/ion-input-password-toggle.entry.js +2 -2
  284. package/dist/esm/ion-input.entry.js +5 -5
  285. package/dist/esm/ion-item-option_3.entry.js +4 -4
  286. package/dist/esm/ion-item_8.entry.js +3 -3
  287. package/dist/esm/ion-loading.entry.js +14 -10
  288. package/dist/esm/ion-menu_3.entry.js +8 -8
  289. package/dist/esm/ion-modal.entry.js +85 -32
  290. package/dist/esm/ion-nav_2.entry.js +6 -6
  291. package/dist/esm/ion-picker-column-option.entry.js +3 -3
  292. package/dist/esm/ion-picker-column.entry.js +211 -47
  293. package/dist/esm/ion-picker.entry.js +2 -2
  294. package/dist/esm/ion-popover.entry.js +23 -10
  295. package/dist/esm/ion-progress-bar.entry.js +3 -3
  296. package/dist/esm/ion-radio_2.entry.js +4 -4
  297. package/dist/esm/ion-range.entry.js +4 -4
  298. package/dist/esm/ion-refresher_2.entry.js +6 -6
  299. package/dist/esm/ion-reorder_2.entry.js +4 -4
  300. package/dist/esm/ion-ripple-effect.entry.js +2 -2
  301. package/dist/esm/ion-route_4.entry.js +4 -4
  302. package/dist/esm/ion-searchbar.entry.js +3 -3
  303. package/dist/esm/ion-segment-content.entry.js +1 -1
  304. package/dist/esm/ion-segment-view.entry.js +1 -1
  305. package/dist/esm/ion-segment_2.entry.js +3 -3
  306. package/dist/esm/ion-select-modal.entry.js +8 -8
  307. package/dist/esm/ion-select_3.entry.js +57 -47
  308. package/dist/esm/ion-spinner.entry.js +2 -2
  309. package/dist/esm/ion-split-pane.entry.js +2 -2
  310. package/dist/esm/ion-tab-bar_2.entry.js +3 -3
  311. package/dist/esm/ion-tab_2.entry.js +3 -3
  312. package/dist/esm/ion-text.entry.js +2 -2
  313. package/dist/esm/ion-textarea.entry.js +5 -5
  314. package/dist/esm/ion-toast.entry.js +8 -8
  315. package/dist/esm/ion-toggle.entry.js +4 -4
  316. package/dist/esm/{ionic-global-lrowsHfi.js → ionic-global-B7I1sdvg.js} +1 -1
  317. package/dist/esm/ionic.js +5 -5
  318. package/dist/esm/{ios.transition-BQhADrk1.js → ios.transition-C-6IaIxe.js} +4 -4
  319. package/dist/esm/{item-multiple-inputs-D_N3fDkD.js → item-multiple-inputs-DI91syHS.js} +1 -1
  320. package/dist/esm/loader.js +4 -4
  321. package/dist/esm/{md.transition-D58NpmRa.js → md.transition-dyqt0t0d.js} +4 -4
  322. package/dist/esm/{overlays-BpnIFlXI.js → overlays-Dz2cGX5q.js} +59 -35
  323. package/dist/esm/{select-option-render-lIuu64EV.js → select-option-render-CUJpruSC.js} +2 -2
  324. package/dist/esm/{slot-mutation-controller-rS_T3FDR.js → slot-mutation-controller-wFuztlVD.js} +1 -1
  325. package/dist/esm/{status-tap-CpFQMLl6.js → status-tap-Dn_42wiy.js} +3 -3
  326. package/dist/esm/{swipe-back-rmc7zeNW.js → swipe-back-CqOqrHW7.js} +2 -2
  327. package/dist/ionic/index.esm.js +1 -1
  328. package/dist/ionic/ionic.esm.js +1 -1
  329. package/dist/ionic/p-010601fe.entry.js +4 -0
  330. package/dist/ionic/{p-05800a02.entry.js → p-025763b2.entry.js} +1 -1
  331. package/dist/ionic/{p-d8deff43.entry.js → p-026e2e4c.entry.js} +1 -1
  332. package/dist/ionic/{p-RzUn7cKs.js → p-06ZcwRF5.js} +1 -1
  333. package/dist/ionic/{p-b62bfce8.entry.js → p-082b8125.entry.js} +1 -1
  334. package/dist/ionic/{p-16e9f542.entry.js → p-0b52d921.entry.js} +1 -1
  335. package/dist/ionic/p-0c2b3555.entry.js +4 -0
  336. package/dist/ionic/{p-485fb218.entry.js → p-1a20571c.entry.js} +1 -1
  337. package/dist/ionic/{p-90ba736e.entry.js → p-1f66c230.entry.js} +1 -1
  338. package/dist/ionic/{p-a0fee899.entry.js → p-2aabd568.entry.js} +1 -1
  339. package/dist/ionic/{p-295ff427.entry.js → p-2ff12c8a.entry.js} +1 -1
  340. package/dist/ionic/{p-5b906fd6.entry.js → p-326e0d05.entry.js} +1 -1
  341. package/dist/ionic/p-392079fa.entry.js +4 -0
  342. package/dist/ionic/{p-6f048604.entry.js → p-43bae3f5.entry.js} +1 -1
  343. package/dist/ionic/p-4778b90f.entry.js +4 -0
  344. package/dist/ionic/{p-d3384a40.entry.js → p-47b8b59a.entry.js} +1 -1
  345. package/dist/ionic/{p-478035a7.entry.js → p-53ba5651.entry.js} +1 -1
  346. package/dist/ionic/{p-bbf6878c.entry.js → p-546b1109.entry.js} +1 -1
  347. package/dist/ionic/{p-8dd4c026.entry.js → p-5dc53bdf.entry.js} +1 -1
  348. package/dist/ionic/{p-1df75f9e.entry.js → p-5ed60413.entry.js} +1 -1
  349. package/dist/ionic/p-639d3b55.entry.js +4 -0
  350. package/dist/ionic/{p-ddfb7e5f.entry.js → p-6d84fa9f.entry.js} +1 -1
  351. package/dist/ionic/{p-72ad7c64.entry.js → p-7c859f42.entry.js} +1 -1
  352. package/dist/ionic/p-7dec112e.entry.js +4 -0
  353. package/dist/ionic/{p-f376876b.entry.js → p-83aa7d47.entry.js} +1 -1
  354. package/dist/ionic/{p-959df5f8.entry.js → p-8d72244b.entry.js} +1 -1
  355. package/dist/ionic/{p-9e455875.entry.js → p-8e388a30.entry.js} +1 -1
  356. package/dist/ionic/{p-75887ee0.entry.js → p-90e06e60.entry.js} +1 -1
  357. package/dist/ionic/{p-b5f37106.entry.js → p-9452849d.entry.js} +1 -1
  358. package/dist/ionic/{p-a54bcd16.entry.js → p-9e688396.entry.js} +1 -1
  359. package/dist/ionic/{p-cad4eccf.entry.js → p-9eba0d8a.entry.js} +1 -1
  360. package/dist/ionic/{p-8e007f11.entry.js → p-9f2d3987.entry.js} +1 -1
  361. package/dist/ionic/p-9fef333a.entry.js +4 -0
  362. package/{components/p-BSARlp49.js → dist/ionic/p-BC17SPKH.js} +1 -1
  363. package/dist/ionic/p-BRa1Jjxr.js +4 -0
  364. package/dist/ionic/{p-De0eY881.js → p-BRc8gq5v.js} +1 -1
  365. package/{components/p-66ogmUZU.js → dist/ionic/p-BpG7jkT9.js} +1 -1
  366. package/dist/ionic/{p-B1Y7LZhV.js → p-C10K-FJg.js} +1 -1
  367. package/dist/ionic/{p-D9yvytgv.js → p-C2BY_4Wp.js} +1 -1
  368. package/dist/ionic/{p-BZVE25Gu.js → p-CH8tk7Pr.js} +1 -1
  369. package/dist/ionic/{p-CDBop-kz.js → p-CTBfxfjC.js} +1 -1
  370. package/dist/ionic/p-Cc-fFNy8.js +4 -0
  371. package/dist/ionic/p-Cc4w3fVf.js +4 -0
  372. package/{components/p-BuPAFTWI.js → dist/ionic/p-CoEa7CiN.js} +1 -1
  373. package/dist/ionic/p-CvRL-Eju.js +4 -0
  374. package/dist/ionic/p-DA88iqXQ.js +4 -0
  375. package/dist/ionic/{p-DXJgZWgi.js → p-DMj-M2c4.js} +1 -1
  376. package/dist/ionic/p-D_IgV7tz.js +4 -0
  377. package/dist/ionic/{p-VquyMbjp.js → p-DoUx_N0R.js} +1 -1
  378. package/dist/ionic/{p-C4IBDDj6.js → p-KJ5pLPiN.js} +1 -1
  379. package/dist/ionic/{p-ByLaqOPm.js → p-Q9w8L_Sw.js} +1 -1
  380. package/dist/ionic/{p-ClrlQU2y.js → p-S1shXW5M.js} +1 -1
  381. package/dist/ionic/{p-1db2afb4.entry.js → p-a2fccdaa.entry.js} +1 -1
  382. package/dist/ionic/{p-fbd83d4c.entry.js → p-ac71362a.entry.js} +1 -1
  383. package/dist/ionic/p-b8cd338d.entry.js +4 -0
  384. package/dist/ionic/{p-873a315a.entry.js → p-bdc01880.entry.js} +1 -1
  385. package/dist/ionic/{p-5f216b79.entry.js → p-ca57763d.entry.js} +1 -1
  386. package/dist/ionic/{p-39a8d4e0.entry.js → p-cc749877.entry.js} +1 -1
  387. package/dist/ionic/{p-56307aea.entry.js → p-d1539609.entry.js} +1 -1
  388. package/dist/ionic/{p-cdc5115e.entry.js → p-d1b888de.entry.js} +1 -1
  389. package/dist/ionic/p-d85e59b1.entry.js +4 -0
  390. package/dist/ionic/p-dad2f3e4.entry.js +4 -0
  391. package/dist/ionic/{p-70ee8888.entry.js → p-dadcb3d2.entry.js} +1 -1
  392. package/dist/ionic/{p-c49165af.entry.js → p-e93cc1e1.entry.js} +1 -1
  393. package/dist/ionic/{p-f7dd1ed9.entry.js → p-eab77a74.entry.js} +1 -1
  394. package/dist/ionic/{p-aebc4d69.entry.js → p-eaeac54e.entry.js} +1 -1
  395. package/dist/ionic/{p-e538f18d.entry.js → p-ecfc9c71.entry.js} +1 -1
  396. package/dist/ionic/{p-5ee2d7b1.entry.js → p-eeb65463.entry.js} +1 -1
  397. package/dist/ionic/{p-881b6954.entry.js → p-f0645c98.entry.js} +1 -1
  398. package/dist/ionic/{p-d8bae128.entry.js → p-f607ad4f.entry.js} +1 -1
  399. package/dist/ionic/{p-61c799d1.entry.js → p-fb4dabbb.entry.js} +1 -1
  400. package/dist/ionic/{p-63bbba8d.entry.js → p-fe80ebb1.entry.js} +1 -1
  401. package/dist/ionic/p-h81G-QbJ.js +6 -0
  402. package/dist/ionic/p-nxFQkv7U.js +4 -0
  403. package/dist/ionic/p-w3KTiug9.js +4 -0
  404. package/{components/p-RFfE9hF6.js → dist/ionic/p-wdSUbx5C.js} +1 -1
  405. package/dist/types/components/action-sheet/action-sheet.d.ts +10 -0
  406. package/dist/types/components/alert/alert.d.ts +7 -0
  407. package/dist/types/components/content/content.d.ts +7 -0
  408. package/dist/types/components/modal/modal.d.ts +8 -0
  409. package/dist/types/components/picker-column/picker-column.d.ts +42 -0
  410. package/dist/types/components.d.ts +1 -1
  411. package/dist/types/stencil-public-runtime.d.ts +12 -0
  412. package/dist/types/utils/overlays.d.ts +9 -0
  413. package/dist/types/utils/test/playwright/detach-reattach.d.ts +13 -0
  414. package/dist/types/utils/test/playwright/index.d.ts +1 -0
  415. package/hydrate/index.js +538 -195
  416. package/hydrate/index.mjs +538 -195
  417. package/loader/index.d.ts +1 -1
  418. package/package.json +2 -2
  419. package/components/p-6Vp915Y7.js +0 -4
  420. package/components/p-AQcCdH2_.js +0 -4
  421. package/components/p-BdwCtX8Y.js +0 -4
  422. package/components/p-Bg4OwDwb.js +0 -4
  423. package/components/p-BxhE2W85.js +0 -4
  424. package/components/p-CHswSpKy.js +0 -4
  425. package/components/p-CQAjyETU.js +0 -4
  426. package/components/p-CR9OgE6N.js +0 -4
  427. package/components/p-CaZeZIL2.js +0 -4
  428. package/components/p-CqyGR9Aq.js +0 -4
  429. package/components/p-DCWfzDM8.js +0 -4
  430. package/components/p-DQ1IPvZO.js +0 -4
  431. package/components/p-DfdYCsov.js +0 -4
  432. package/components/p-DhOoEIAs.js +0 -4
  433. package/components/p-Dl_7b_UJ.js +0 -4
  434. package/components/p-DqAI6tg7.js +0 -4
  435. package/components/p-DrehWDfv.js +0 -4
  436. package/components/p-HVYBAhFx.js +0 -4
  437. package/components/p-eFI3mtEX.js +0 -4
  438. package/dist/ionic/p-0eb50dca.entry.js +0 -4
  439. package/dist/ionic/p-18d532a3.entry.js +0 -4
  440. package/dist/ionic/p-34b9379b.entry.js +0 -4
  441. package/dist/ionic/p-4437015c.entry.js +0 -4
  442. package/dist/ionic/p-48c859fe.entry.js +0 -4
  443. package/dist/ionic/p-49b9d405.entry.js +0 -4
  444. package/dist/ionic/p-68507e70.entry.js +0 -4
  445. package/dist/ionic/p-886d9e66.entry.js +0 -4
  446. package/dist/ionic/p-8f51110d.entry.js +0 -4
  447. package/dist/ionic/p-B5RyLYvl.js +0 -4
  448. package/dist/ionic/p-BQv5i5Kf.js +0 -4
  449. package/dist/ionic/p-BnGA34Pd.js +0 -4
  450. package/dist/ionic/p-C06QNN45.js +0 -4
  451. package/dist/ionic/p-CCVlNZ__.js +0 -4
  452. package/dist/ionic/p-CKYcsw8f.js +0 -5
  453. package/dist/ionic/p-CazSodad.js +0 -4
  454. package/dist/ionic/p-DdhHqKj-.js +0 -4
  455. package/dist/ionic/p-DgUL3JbO.js +0 -4
  456. package/dist/ionic/p-b7a11b58.entry.js +0 -4
package/hydrate/index.js CHANGED
@@ -422,7 +422,7 @@ const appGlobalScript = initialize || (() => {});
422
422
  const globalScripts = appGlobalScript;
423
423
 
424
424
  /*
425
- Stencil Hydrate Platform v4.43.5 | MIT Licensed | https://stenciljs.com
425
+ Stencil Hydrate Platform v4.44.1 | MIT Licensed | https://stenciljs.com
426
426
  */
427
427
  var __create = Object.create;
428
428
  var __defProp = Object.defineProperty;
@@ -757,6 +757,8 @@ var DEFAULT_DOC_DATA = {
757
757
  };
758
758
  var SLOT_FB_CSS = "slot-fb{display:contents}slot-fb[hidden]{display:none}";
759
759
  var XLINK_NS = "http://www.w3.org/1999/xlink";
760
+ var MAX_LAZY_LOAD_RETRIES = 3;
761
+ var LAZY_LOAD_RETRY_INTERVAL_MS = 1e3;
760
762
 
761
763
  // src/utils/style.ts
762
764
  function createStyleSheetIfNeededAndSupported(styles2) {
@@ -820,7 +822,7 @@ function getHostSlotNodes(childNodes, hostName, slotName) {
820
822
  slottedNodes.push(childNode);
821
823
  if (typeof slotName !== "undefined") return slottedNodes;
822
824
  }
823
- slottedNodes = [...slottedNodes, ...getHostSlotNodes(childNode.childNodes, hostName, slotName)];
825
+ slottedNodes = [...slottedNodes, ...getHostSlotNodes(internalCall(childNode, "childNodes"), hostName, slotName)];
824
826
  }
825
827
  return slottedNodes;
826
828
  }
@@ -1064,6 +1066,11 @@ var h = (nodeName, vnodeData, ...children) => {
1064
1066
  } else if (child != null && typeof child !== "boolean") {
1065
1067
  if (simple = typeof nodeName !== "function" && !isComplexType(child)) {
1066
1068
  child = String(child);
1069
+ } else if (typeof nodeName !== "function" && child.$flags$ === void 0) {
1070
+ {
1071
+ consoleError("Invalid vNode child");
1072
+ }
1073
+ continue;
1067
1074
  }
1068
1075
  if (simple && lastSimple) {
1069
1076
  vNodeChildren[vNodeChildren.length - 1].$text$ += child;
@@ -2299,7 +2306,7 @@ var setAccessor = (elm, memberName, oldValue, newValue, isSvg, flags, initialRen
2299
2306
  }
2300
2307
  }
2301
2308
  if (newValue == null || newValue === false) {
2302
- if (newValue !== false || elm.getAttribute(memberName) === "") {
2309
+ if (newValue !== false || elm.getAttribute(memberName) === "" || flags & 4 /* isHost */ && !isEnumeratedAttribute(memberName)) {
2303
2310
  if (xlink) {
2304
2311
  elm.removeAttributeNS(XLINK_NS, memberName);
2305
2312
  } else {
@@ -2316,6 +2323,8 @@ var setAccessor = (elm, memberName, oldValue, newValue, isSvg, flags, initialRen
2316
2323
  }
2317
2324
  }
2318
2325
  };
2326
+ var ENUMERATED_ATTRIBUTES = /* @__PURE__ */ new Set(["draggable", "contenteditable", "spellcheck"]);
2327
+ var isEnumeratedAttribute = (attrName) => ENUMERATED_ATTRIBUTES.has(attrName) || attrName.startsWith("aria-");
2319
2328
  var parseClassListRegex = /\s/;
2320
2329
  var parseClassList = (value) => {
2321
2330
  if (typeof value === "object" && value && "baseVal" in value) {
@@ -2718,7 +2727,10 @@ var markSlotContentForRelocation = (elm) => {
2718
2727
  const slotName = childNode["s-sn"];
2719
2728
  for (j = hostContentNodes.length - 1; j >= 0; j--) {
2720
2729
  node = hostContentNodes[j];
2721
- if (!node["s-cn"] && !node["s-nr"] && node["s-hn"] !== childNode["s-hn"] && (!node["s-sh"] || node["s-sh"] !== childNode["s-hn"])) {
2730
+ if (!node["s-cn"] && !node["s-nr"] && node["s-hn"] !== childNode["s-hn"] && // let an exact named-slot match override a stale default-slot claim. Skip this for
2731
+ // `slotName === ''` itself - a matched default node's cached `s-sn` is `''` too, which
2732
+ // would trivially "match" on every re-render and force pointless re-insertion.
2733
+ (!node["s-sh"] || node["s-sh"] !== childNode["s-hn"] || slotName !== "" && getSlotName(node) === slotName)) {
2722
2734
  if (isNodeLocatedInSlot(node, slotName)) {
2723
2735
  let relocateNodeData = relocateNodes.find((r) => r.$nodeToRelocate$ === node);
2724
2736
  checkSlotFallbackVisibility = true;
@@ -2788,7 +2800,7 @@ var insertBefore = (parent, newNode, reference, isInitialLoad) => {
2788
2800
  return newNode;
2789
2801
  }
2790
2802
  }
2791
- if (parent.__insertBefore) {
2803
+ if ((parent == null ? void 0 : parent.__insertBefore)) {
2792
2804
  return parent.__insertBefore(newNode, reference);
2793
2805
  } else {
2794
2806
  return parent == null ? void 0 : parent.insertBefore(newNode, reference);
@@ -3293,10 +3305,12 @@ var proxyComponent = (Cstr, cmpMeta, flags) => {
3293
3305
 
3294
3306
  // src/runtime/initialize-component.ts
3295
3307
  var initializeComponent = async (elm, hostRef, cmpMeta, hmrVersionId) => {
3308
+ var _a2;
3296
3309
  let Cstr;
3297
3310
  try {
3298
3311
  if ((hostRef.$flags$ & 32 /* hasInitializedComponent */) === 0) {
3299
3312
  hostRef.$flags$ |= 32 /* hasInitializedComponent */;
3313
+ hostRef.$flags$ &= -1025 /* hasFailedLoad */;
3300
3314
  const bundleId = cmpMeta.$lazyBundleId$;
3301
3315
  if (bundleId) {
3302
3316
  const CstrImport = loadModule(cmpMeta);
@@ -3308,6 +3322,11 @@ var initializeComponent = async (elm, hostRef, cmpMeta, hmrVersionId) => {
3308
3322
  Cstr = CstrImport;
3309
3323
  }
3310
3324
  if (!Cstr) {
3325
+ hostRef.$flags$ &= -33 /* hasInitializedComponent */;
3326
+ hostRef.$loadRetryCount$ = ((_a2 = hostRef.$loadRetryCount$) != null ? _a2 : 0) + 1;
3327
+ if (hostRef.$loadRetryCount$ < MAX_LAZY_LOAD_RETRIES) {
3328
+ hostRef.$flags$ |= 1024 /* hasFailedLoad */;
3329
+ }
3311
3330
  throw new Error(`Constructor for "${cmpMeta.$tagName$}#${hostRef.$modeName$}" was not found`);
3312
3331
  }
3313
3332
  if (!Cstr.isProxied) {
@@ -3387,7 +3406,7 @@ var initializeComponent = async (elm, hostRef, cmpMeta, hmrVersionId) => {
3387
3406
  hostRef.$onRenderResolve$();
3388
3407
  hostRef.$onRenderResolve$ = void 0;
3389
3408
  }
3390
- if (hostRef.$onReadyResolve$) {
3409
+ if (hostRef.$onReadyResolve$ && !(hostRef.$flags$ & 1024 /* hasFailedLoad */)) {
3391
3410
  hostRef.$onReadyResolve$(elm);
3392
3411
  }
3393
3412
  }
@@ -3446,6 +3465,8 @@ var connectedCallback = (elm) => {
3446
3465
  addHostEventListeners(elm, hostRef, cmpMeta.$listeners$);
3447
3466
  if (hostRef == null ? void 0 : hostRef.$lazyInstance$) {
3448
3467
  fireConnectedCallback(hostRef.$lazyInstance$, elm);
3468
+ } else if (hostRef.$flags$ & 1024 /* hasFailedLoad */) {
3469
+ setTimeout(() => initializeComponent(elm, hostRef, cmpMeta), LAZY_LOAD_RETRY_INTERVAL_MS);
3449
3470
  } else if (hostRef == null ? void 0 : hostRef.$onReadyPromise$) {
3450
3471
  hostRef.$onReadyPromise$.then(() => fireConnectedCallback(hostRef.$lazyInstance$, elm));
3451
3472
  }
@@ -7961,6 +7982,15 @@ const activeAnimations = new WeakMap();
7961
7982
  const isBackdropAlwaysBlocking = (el) => {
7962
7983
  return el.showBackdrop !== false && !((el.backdropBreakpoint ?? 0) > 0);
7963
7984
  };
7985
+ /**
7986
+ * Whether the overlay takes the app root out of the accessibility tree and
7987
+ * blocks body scroll while presented. Toasts never do, modal and popover can
7988
+ * opt out with `focusTrap={false}`, and a backdrop that does not block
7989
+ * (`showBackdrop={false}`, or a `backdropBreakpoint` above 0) is excluded.
7990
+ */
7991
+ const locksAppRoot = (el) => {
7992
+ return el.tagName !== 'ION-TOAST' && el.focusTrap !== false && isBackdropAlwaysBlocking(el);
7993
+ };
7964
7994
  const createController = (tagName) => {
7965
7995
  return {
7966
7996
  create(options) {
@@ -8329,6 +8359,13 @@ const getPresentedOverlay = (doc, overlayTag, id) => {
8329
8359
  // Otherwise, return the last overlay with the given id
8330
8360
  return (id === undefined ? overlays : overlays.filter((o) => o.id === id)).slice(-1)[0];
8331
8361
  };
8362
+ /**
8363
+ * The element an app nests its views under. Overlays hide this rather than the
8364
+ * whole root, so the overlay itself (a sibling) stays reachable.
8365
+ */
8366
+ const getViewContainer = () => {
8367
+ return getAppRoot(document).querySelector('ion-router-outlet, #ion-view-container-root');
8368
+ };
8332
8369
  /**
8333
8370
  * When an overlay is presented, the main
8334
8371
  * focus is the overlay not the page content.
@@ -8352,8 +8389,7 @@ const getPresentedOverlay = (doc, overlayTag, id) => {
8352
8389
  * for main content.
8353
8390
  */
8354
8391
  const setRootAriaHidden = (hidden = false) => {
8355
- const root = getAppRoot(document);
8356
- const viewContainer = root.querySelector('ion-router-outlet, #ion-view-container-root');
8392
+ const viewContainer = getViewContainer();
8357
8393
  if (!viewContainer) {
8358
8394
  return;
8359
8395
  }
@@ -8378,15 +8414,42 @@ const cleanupRootFocusTrapAccessibility = () => {
8378
8414
  return;
8379
8415
  }
8380
8416
  const remainingOverlays = getPresentedOverlays(document);
8381
- const hasRemainingLocking = remainingOverlays.some((o) => {
8382
- const el = o;
8383
- return el.tagName !== 'ION-TOAST' && el.focusTrap !== false && isBackdropAlwaysBlocking(el);
8384
- });
8417
+ const hasRemainingLocking = remainingOverlays.some((o) => locksAppRoot(o));
8385
8418
  if (!hasRemainingLocking) {
8386
8419
  setRootAriaHidden(false);
8387
8420
  document.body.classList.remove(BACKDROP_NO_SCROLL);
8388
8421
  }
8389
8422
  };
8423
+ /**
8424
+ * Applies the root lock itself: `aria-hidden` on the view container, and
8425
+ * `backdrop-no-scroll` on the body. Shared by `present()` and the restore
8426
+ * below, which have to stay in lockstep.
8427
+ */
8428
+ const applyRootLock = (el) => {
8429
+ // Hiding the container the overlay now sits in would hide the overlay too.
8430
+ if (!getViewContainer()?.contains(el)) {
8431
+ setRootAriaHidden(true);
8432
+ }
8433
+ document.body.classList.add(BACKDROP_NO_SCROLL);
8434
+ };
8435
+ /**
8436
+ * Re-applies the root lock that `cleanupRootFocusTrapAccessibility()` released.
8437
+ * Call from `connectedCallback` when the overlay is still presented.
8438
+ *
8439
+ * A synchronous move keeps the overlay connected, so the lock survives. A
8440
+ * detach with a re-insert in a later task releases it, which is the shape a
8441
+ * framework produces when it takes a subtree out and puts it back.
8442
+ */
8443
+ const restoreRootFocusTrapAccessibility = (overlayEl) => {
8444
+ if (typeof document === 'undefined') {
8445
+ return;
8446
+ }
8447
+ const el = overlayEl;
8448
+ if (!locksAppRoot(el)) {
8449
+ return;
8450
+ }
8451
+ applyRootLock(el);
8452
+ };
8390
8453
  const present = async (overlay, name, iosEnterAnimation, mdEnterAnimation, opts) => {
8391
8454
  if (overlay.presented) {
8392
8455
  return;
@@ -8403,15 +8466,7 @@ const present = async (overlay, name, iosEnterAnimation, mdEnterAnimation, opts)
8403
8466
  restoreElementFocus(overlay.el);
8404
8467
  }
8405
8468
  /**
8406
- * Due to accessibility guidelines, toasts do not have
8407
- * focus traps.
8408
- *
8409
- * All other overlays should have focus traps to prevent
8410
- * the keyboard focus from leaving the overlay unless
8411
- * developers explicitly opt out (for example, sheet
8412
- * modals that should permit background interaction).
8413
- *
8414
- * Note: Some apps move inline overlays to a specific container
8469
+ * Some apps move inline overlays to a specific container
8415
8470
  * during the willPresent lifecycle (e.g., React portals via
8416
8471
  * onWillPresent). Defer applying aria-hidden/inert to the app
8417
8472
  * root until after willPresent so we can detect where the
@@ -8420,18 +8475,11 @@ const present = async (overlay, name, iosEnterAnimation, mdEnterAnimation, opts)
8420
8475
  * to avoid disabling the overlay.
8421
8476
  */
8422
8477
  const overlayEl = overlay.el;
8423
- const shouldTrapFocus = overlayEl.tagName !== 'ION-TOAST' && overlayEl.focusTrap !== false;
8424
- const shouldLockRoot = shouldTrapFocus && isBackdropAlwaysBlocking(overlayEl);
8478
+ const shouldLockRoot = locksAppRoot(overlayEl);
8425
8479
  overlay.presented = true;
8426
8480
  overlay.willPresent.emit();
8427
8481
  if (shouldLockRoot) {
8428
- const root = getAppRoot(document);
8429
- const viewContainer = root.querySelector('ion-router-outlet, #ion-view-container-root');
8430
- const overlayInsideViewContainer = viewContainer ? viewContainer.contains(overlayEl) : false;
8431
- if (!overlayInsideViewContainer) {
8432
- setRootAriaHidden(true);
8433
- }
8434
- document.body.classList.add(BACKDROP_NO_SCROLL);
8482
+ applyRootLock(overlayEl);
8435
8483
  }
8436
8484
  overlay.willPresentShorthand?.emit();
8437
8485
  const mode = getIonMode$1(overlay);
@@ -8557,12 +8605,9 @@ const dismiss = async (overlay, data, role, name, iosLeaveAnimation, mdLeaveAnim
8557
8605
  * from the root element when the last focus-trapping overlay
8558
8606
  * is dismissed.
8559
8607
  */
8560
- const overlaysLockingRoot = presentedOverlays.filter((o) => {
8561
- const el = o;
8562
- return el.tagName !== 'ION-TOAST' && el.focusTrap !== false && isBackdropAlwaysBlocking(el);
8563
- });
8608
+ const overlaysLockingRoot = presentedOverlays.filter((o) => locksAppRoot(o));
8564
8609
  const overlayEl = overlay.el;
8565
- const locksRoot = overlayEl.tagName !== 'ION-TOAST' && overlayEl.focusTrap !== false && isBackdropAlwaysBlocking(overlayEl);
8610
+ const locksRoot = locksAppRoot(overlayEl);
8566
8611
  /**
8567
8612
  * If this is the last visible overlay that is trapping focus
8568
8613
  * then we want to re-add the root to the accessibility tree.
@@ -10558,6 +10603,13 @@ class ActionSheet {
10558
10603
  connectedCallback() {
10559
10604
  prepareOverlay(this.el);
10560
10605
  this.triggerChanged();
10606
+ // `componentDidLoad` only fires once per instance, so a reconnect has to
10607
+ // rebuild the gesture its disconnect destroyed.
10608
+ this.setupButtonActiveGesture();
10609
+ // Re-apply the root lock if moved without dismiss() being called
10610
+ if (this.presented) {
10611
+ restoreRootFocusTrapAccessibility(this.el);
10612
+ }
10561
10613
  }
10562
10614
  disconnectedCallback() {
10563
10615
  if (this.gesture) {
@@ -10577,24 +10629,33 @@ class ActionSheet {
10577
10629
  // Initialize activeRadioId for radio buttons
10578
10630
  this.buttonsChanged();
10579
10631
  }
10580
- componentDidLoad() {
10581
- /**
10582
- * Only create gesture if:
10583
- * 1. A gesture does not already exist
10584
- * 2. App is running in iOS mode
10585
- * 3. A wrapper ref exists
10586
- * 4. A group ref exists
10587
- */
10632
+ /**
10633
+ * Only create gesture if:
10634
+ * 1. A gesture does not already exist
10635
+ * 2. App is running in iOS mode
10636
+ * 3. A wrapper ref exists
10637
+ * 4. A group ref exists
10638
+ * 5. The host is still connected, since a reconnect can schedule this and
10639
+ * disconnect again before the task runs
10640
+ */
10641
+ setupButtonActiveGesture() {
10588
10642
  const { groupEl, wrapperEl } = this;
10589
- if (!this.gesture && getIonMode$1(this) === 'ios' && wrapperEl && groupEl) {
10590
- readTask(() => {
10591
- const isScrollable = groupEl.scrollHeight > groupEl.clientHeight;
10592
- if (!isScrollable) {
10593
- this.gesture = createButtonActiveGesture(wrapperEl, (refEl) => refEl.classList.contains('action-sheet-button'));
10594
- this.gesture.enable(true);
10595
- }
10596
- });
10643
+ if (getIonMode$1(this) !== 'ios' || !wrapperEl || !groupEl) {
10644
+ return;
10597
10645
  }
10646
+ readTask(() => {
10647
+ // Bail if a call queued ahead of this one already built the gesture
10648
+ // (a second would orphan the first with its listeners still bound), if
10649
+ // the host disconnected while this task waited, or if the group scrolls.
10650
+ if (this.gesture || !this.el.isConnected || groupEl.scrollHeight > groupEl.clientHeight) {
10651
+ return;
10652
+ }
10653
+ this.gesture = createButtonActiveGesture(wrapperEl, (refEl) => refEl.classList.contains('action-sheet-button'));
10654
+ this.gesture.enable(true);
10655
+ });
10656
+ }
10657
+ componentDidLoad() {
10658
+ this.setupButtonActiveGesture();
10598
10659
  /**
10599
10660
  * If action sheet was rendered with isOpen="true"
10600
10661
  * then we should open action sheet immediately.
@@ -10687,17 +10748,17 @@ class ActionSheet {
10687
10748
  const cancelButton = allButtons.find((b) => b.role === 'cancel');
10688
10749
  const buttons = allButtons.filter((b) => b.role !== 'cancel');
10689
10750
  const headerID = `action-sheet-${overlayIndex}-header`;
10690
- return (hAsync(Host, { key: '7685831da9a78b73473246a2cea95cefa79a53c3', role: "dialog", "aria-modal": "true", "aria-labelledby": header !== undefined ? headerID : null, tabindex: "-1", ...htmlAttributes, style: {
10751
+ return (hAsync(Host, { key: '83b47ea6b81d4eec6582c1dcaae6f267c78ba634', role: "dialog", "aria-modal": "true", "aria-labelledby": header !== undefined ? headerID : null, tabindex: "-1", ...htmlAttributes, style: {
10691
10752
  zIndex: `${20000 + this.overlayIndex}`,
10692
10753
  }, class: {
10693
10754
  [mode]: true,
10694
10755
  ...getClassMap(this.cssClass),
10695
10756
  'overlay-hidden': true,
10696
10757
  'action-sheet-translucent': this.translucent,
10697
- }, onIonActionSheetWillDismiss: this.dispatchCancelHandler, onIonBackdropTap: this.onBackdropTap }, hAsync("ion-backdrop", { key: 'c70f00e401cac99b89412d1adb867f35bc855d57', tappable: this.backdropDismiss }), hAsync("div", { key: '3332893ce3098f1435875480b1269b2821d41660', tabindex: "0", "aria-hidden": "true" }), hAsync("div", { key: 'eb406b0a9e303d6f94c5c7aa99c6f4c089bfbd41', class: "action-sheet-wrapper ion-overlay-wrapper", ref: (el) => (this.wrapperEl = el) }, hAsync("div", { key: '92ec855379f10e1e0bfce6ff68b45d3cda0c137c', class: "action-sheet-container" }, hAsync("div", { key: 'bc88a396d75396f574961471bf7e6c4edb513353', class: "action-sheet-group", ref: (el) => (this.groupEl = el), role: hasRadioButtons ? 'radiogroup' : undefined }, header !== undefined && (hAsync("div", { key: '33329e0193818888bdcaa443ff5ea301802e0787', id: headerID, class: {
10758
+ }, onIonActionSheetWillDismiss: this.dispatchCancelHandler, onIonBackdropTap: this.onBackdropTap }, hAsync("ion-backdrop", { key: '3652793ec76adcfb87b814eb65d1260ae26f6910', tappable: this.backdropDismiss }), hAsync("div", { key: '7de3a51daf95b50e02734a2cc8eec6f55b1473f3', tabindex: "0", "aria-hidden": "true" }), hAsync("div", { key: '9b76bbf12901b956f7ee6d984f7f71e169bb5939', class: "action-sheet-wrapper ion-overlay-wrapper", ref: (el) => (this.wrapperEl = el) }, hAsync("div", { key: 'cb52c905275a46ff27810fb1b4748ab533a78c45', class: "action-sheet-container" }, hAsync("div", { key: '578c7194cfbcb65c1e41e15c390af41f179a2686', class: "action-sheet-group", ref: (el) => (this.groupEl = el), role: hasRadioButtons ? 'radiogroup' : undefined }, header !== undefined && (hAsync("div", { key: 'ee961307c25cb1fcb0c6bbf667a8ed76ab717860', id: headerID, class: {
10698
10759
  'action-sheet-title': true,
10699
10760
  'action-sheet-has-sub-title': this.subHeader !== undefined,
10700
- } }, header, this.subHeader && hAsync("div", { key: '92ac5a9217a12b7417f7aca9c4fdb7bf6b051364', class: "action-sheet-sub-title" }, this.subHeader))), this.renderActionSheetButtons(buttons)), cancelButton && (hAsync("div", { key: '020463b830fa48fc3ae647ea64f2aaa4d0969305', class: "action-sheet-group action-sheet-group-cancel" }, hAsync("button", { key: 'cefa9c70a2233f6652a81b1a2eae6e717712144d', ...cancelButton.htmlAttributes, type: "button", class: buttonClass$2(cancelButton), onClick: () => this.buttonClick(cancelButton) }, hAsync("span", { key: '56d7e2f8bfb3644e4476895164d334445fda9b2f', class: "action-sheet-button-inner" }, cancelButton.icon && (hAsync("ion-icon", { key: '6a4a49254ec5cd96f4e0dce9447f90d8cac81913', icon: cancelButton.icon, "aria-hidden": "true", lazy: false, class: "action-sheet-icon" })), cancelButton.text), mode === 'md' && hAsync("ion-ripple-effect", { key: '7d3c6e8d70b0922ea0f75520856285ce1005c891' })))))), hAsync("div", { key: '958fc43e603c6a7f5d1e649d3326fce0f163b5d0', tabindex: "0", "aria-hidden": "true" })));
10761
+ } }, header, this.subHeader && hAsync("div", { key: '82d4016010db14d3f3b9911c276cb9a63b960ef4', class: "action-sheet-sub-title" }, this.subHeader))), this.renderActionSheetButtons(buttons)), cancelButton && (hAsync("div", { key: 'a88fbfab194e13c6642a65f2e19a12299dd4ac23', class: "action-sheet-group action-sheet-group-cancel" }, hAsync("button", { key: 'a232b8d23f1fc2efb7b37a605102b6994761a2f6', ...cancelButton.htmlAttributes, type: "button", class: buttonClass$2(cancelButton), onClick: () => this.buttonClick(cancelButton) }, hAsync("span", { key: '19a7d95d3428d78a56b7dacabdec8fc0b722d8c2', class: "action-sheet-button-inner" }, cancelButton.icon && (hAsync("ion-icon", { key: '5f3f3cb996a48e6365a3a09ea72ddc68ac9ccb78', icon: cancelButton.icon, "aria-hidden": "true", lazy: false, class: "action-sheet-icon" })), cancelButton.text), mode === 'md' && hAsync("ion-ripple-effect", { key: '6e8fcb5f103ac19aa4b0682f19791cef0a147001' })))))), hAsync("div", { key: '36f63ab77949c88f662e2cf6bb18510cb9de6a9f', tabindex: "0", "aria-hidden": "true" })));
10701
10762
  }
10702
10763
  get el() { return getElement(this); }
10703
10764
  static get watchers() { return {
@@ -11079,10 +11140,15 @@ class Alert {
11079
11140
  this.triggerChanged();
11080
11141
  /**
11081
11142
  * If the alert was previously connected and is being reattached, the
11082
- * ResizeObserver was disconnected. componentDidLoad only fires once per
11083
- * instance, so re-establish the observer here on reconnect.
11143
+ * `ResizeObserver` and the button gesture were torn down. `componentDidLoad`
11144
+ * only fires once per instance, so re-establish both here on reconnect.
11084
11145
  */
11085
11146
  this.setupButtonGroupResizeObserver();
11147
+ this.setupButtonActiveGesture();
11148
+ // Re-apply the root lock if moved without dismiss() being called
11149
+ if (this.presented) {
11150
+ restoreRootFocusTrapAccessibility(this.el);
11151
+ }
11086
11152
  }
11087
11153
  componentWillLoad() {
11088
11154
  if (!this.htmlAttributes?.id) {
@@ -11104,17 +11170,20 @@ class Alert {
11104
11170
  this.buttonGroupResizeObserver?.disconnect();
11105
11171
  this.buttonGroupResizeObserver = undefined;
11106
11172
  }
11107
- componentDidLoad() {
11108
- /**
11109
- * Only create gesture if:
11110
- * 1. A gesture does not already exist
11111
- * 2. App is running in iOS mode
11112
- * 3. A wrapper ref exists
11113
- */
11173
+ /**
11174
+ * Only create gesture if:
11175
+ * 1. A gesture does not already exist
11176
+ * 2. App is running in iOS mode
11177
+ * 3. A wrapper ref exists
11178
+ */
11179
+ setupButtonActiveGesture() {
11114
11180
  if (!this.gesture && getIonMode$1(this) === 'ios' && this.wrapperEl) {
11115
11181
  this.gesture = createButtonActiveGesture(this.wrapperEl, (refEl) => refEl.classList.contains('alert-button'));
11116
11182
  this.gesture.enable(true);
11117
11183
  }
11184
+ }
11185
+ componentDidLoad() {
11186
+ this.setupButtonActiveGesture();
11118
11187
  this.setupButtonGroupResizeObserver();
11119
11188
  /**
11120
11189
  * If alert was rendered with isOpen="true"
@@ -11435,14 +11504,14 @@ class Alert {
11435
11504
  * If neither are defined, do not set aria-labelledby.
11436
11505
  */
11437
11506
  const ariaLabelledBy = header && subHeader ? `${hdrId} ${subHdrId}` : header ? hdrId : subHeader ? subHdrId : null;
11438
- return (hAsync(Host, { key: '022f3463b8e6c52064b90ec304c524847c3d5ad3', tabindex: "-1", style: {
11507
+ return (hAsync(Host, { key: '083b5250dc4c76e85240e0225abcb7ca2b66de2f', tabindex: "-1", style: {
11439
11508
  zIndex: `${20000 + overlayIndex}`,
11440
11509
  }, class: {
11441
11510
  ...getClassMap(this.cssClass),
11442
11511
  [mode]: true,
11443
11512
  'overlay-hidden': true,
11444
11513
  'alert-translucent': this.translucent,
11445
- }, onIonAlertWillDismiss: this.dispatchCancelHandler, onIonBackdropTap: this.onBackdropTap }, hAsync("ion-backdrop", { key: 'c3cd05738bc2834f54707edeb2fae06ec10d6fd2', tappable: this.backdropDismiss }), hAsync("div", { key: 'b44fadd9ba7ddf073854c5035538d11ae8e66bc2', tabindex: "0", "aria-hidden": "true" }), hAsync("div", { key: 'fafea048141a6c7957e62aef31faa8041dd610c1', class: "alert-wrapper ion-overlay-wrapper", role: role, "aria-modal": "true", "aria-labelledby": ariaLabelledBy, "aria-describedby": message !== undefined ? msgId : null, tabindex: "0", ref: (el) => (this.wrapperEl = el), ...htmlAttributes }, hAsync("div", { key: '3ad9d2d4b7cf425eab8293ddc12eff0fe8df1517', class: "alert-head" }, header && (hAsync("h2", { key: '7d9154f5ee595b7e4da6ecf3a20871f104c1256e', id: hdrId, class: "alert-title" }, header)), subHeader && !header && (hAsync("h2", { key: '1f891f38004be6964e9406b84dd580145c42516a', id: subHdrId, class: "alert-sub-title" }, subHeader)), subHeader && header && (hAsync("h3", { key: '2ab4d344ecb7e384e8f6d3d3e59ee5a1bbcc832c', id: subHdrId, class: "alert-sub-title" }, subHeader))), this.renderAlertMessage(msgId), this.renderAlertInputs(), this.renderAlertButtons()), hAsync("div", { key: '78a4ff09aa3aaafcd0dc2a42d036767d83b3cfa2', tabindex: "0", "aria-hidden": "true" })));
11514
+ }, onIonAlertWillDismiss: this.dispatchCancelHandler, onIonBackdropTap: this.onBackdropTap }, hAsync("ion-backdrop", { key: '65c92a956d998ae9016396dd2a29c42ab7376d0e', tappable: this.backdropDismiss }), hAsync("div", { key: 'f2288fa0b7ef9d0bf031c168fe78c48422cf91c8', tabindex: "0", "aria-hidden": "true" }), hAsync("div", { key: 'dbb109435c378f77c6b0231e58756f8a0467732d', class: "alert-wrapper ion-overlay-wrapper", role: role, "aria-modal": "true", "aria-labelledby": ariaLabelledBy, "aria-describedby": message !== undefined ? msgId : null, tabindex: "0", ref: (el) => (this.wrapperEl = el), ...htmlAttributes }, hAsync("div", { key: '075597f94719673cf1f894a8566e1036849afa75', class: "alert-head" }, header && (hAsync("h2", { key: 'f96f4b1db8473c62040beed6e96108c733978d73', id: hdrId, class: "alert-title" }, header)), subHeader && !header && (hAsync("h2", { key: 'dbd824ef19a07bddde4eb928f11de7c7cadf98b8', id: subHdrId, class: "alert-sub-title" }, subHeader)), subHeader && header && (hAsync("h3", { key: '4774fa13700dd23aec7930492acae80de3bdf5d1', id: subHdrId, class: "alert-sub-title" }, subHeader))), this.renderAlertMessage(msgId), this.renderAlertInputs(), this.renderAlertButtons()), hAsync("div", { key: '5c728b7457e231f64294bbec821bdb547c6437dd', tabindex: "0", "aria-hidden": "true" })));
11446
11515
  }
11447
11516
  get el() { return getElement(this); }
11448
11517
  static get watchers() { return {
@@ -13621,6 +13690,23 @@ class Content {
13621
13690
  const mode = getIonMode$1(this);
13622
13691
  return forceOverscroll === undefined ? mode === 'ios' && isPlatform('ios') : forceOverscroll;
13623
13692
  }
13693
+ /**
13694
+ * Whether this component should size itself to its contents height, which
13695
+ * is the case inside any popover and inside a modal whose `--height` is a
13696
+ * content-based value. Those overlays give the content no definite height
13697
+ * to fill.
13698
+ */
13699
+ shouldSizeToContent() {
13700
+ if (hostContext('ion-popover', this.el)) {
13701
+ return true;
13702
+ }
13703
+ const modal = this.el.closest('ion-modal');
13704
+ if (modal === null) {
13705
+ return false;
13706
+ }
13707
+ const height = getComputedStyle(modal).getPropertyValue('--height').trim();
13708
+ return CONTENT_SIZED_HEIGHTS.includes(height);
13709
+ }
13624
13710
  resize() {
13625
13711
  }
13626
13712
  /**
@@ -13800,21 +13886,21 @@ class Content {
13800
13886
  const forceOverscroll = this.shouldForceOverscroll();
13801
13887
  const transitionShadow = mode === 'ios';
13802
13888
  this.resize();
13803
- return (hAsync(Host, { key: '9551c759df407b10d809171641fc6e8f14d92219', role: isMainContent ? 'main' : undefined, class: createColorClasses$1(this.color, {
13889
+ return (hAsync(Host, { key: 'd6ea57ec1f5def0bfd22f52ec5a5bbe6aa2f8e8e', role: isMainContent ? 'main' : undefined, class: createColorClasses$1(this.color, {
13804
13890
  [mode]: true,
13805
13891
  'content-fullscreen': this.fullscreen,
13806
- 'content-sizing': hostContext('ion-popover', this.el),
13892
+ 'content-sizing': this.shouldSizeToContent(),
13807
13893
  overscroll: forceOverscroll,
13808
13894
  [`content-${rtl}`]: true,
13809
13895
  }), style: {
13810
13896
  '--offset-top': `${this.cTop}px`,
13811
13897
  '--offset-bottom': `${this.cBottom}px`,
13812
- }, ...inheritedAttributes }, hAsync("div", { key: 'c6de8fd226f0d10a534eb107fe032ac155fbe68e', ref: (el) => (this.backgroundContentEl = el), id: "background-content", part: "background" }), fixedSlotPlacement === 'before' ? hAsync("slot", { name: "fixed" }) : null, hAsync("div", { key: '082fc2936061360060b48221ecb1c864a3711fa0', class: {
13898
+ }, ...inheritedAttributes }, hAsync("div", { key: '3ea7145f051ac3870ffb2b0c1fd83c20ce42d431', ref: (el) => (this.backgroundContentEl = el), id: "background-content", part: "background" }), fixedSlotPlacement === 'before' ? hAsync("slot", { name: "fixed" }) : null, hAsync("div", { key: 'af112b5f681fd40417c82bee085263c85755dad5', class: {
13813
13899
  'inner-scroll': true,
13814
13900
  'scroll-x': scrollX,
13815
13901
  'scroll-y': scrollY,
13816
13902
  overscroll: (scrollX || scrollY) && forceOverscroll,
13817
- }, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, hAsync("slot", { key: '0d2286206facb22696a9ca7e74a3f6b7d2397aab' })), transitionShadow ? (hAsync("div", { class: "transition-effect" }, hAsync("div", { class: "transition-cover" }), hAsync("div", { class: "transition-shadow" }))) : null, fixedSlotPlacement === 'after' ? hAsync("slot", { name: "fixed" }) : null));
13903
+ }, ref: (scrollEl) => (this.scrollEl = scrollEl), onScroll: this.scrollEvents ? (ev) => this.onScroll(ev) : undefined, part: "scroll" }, hAsync("slot", { key: '1b130c5713874fe457934359a1a1709a8cdb257a' })), transitionShadow ? (hAsync("div", { class: "transition-effect" }, hAsync("div", { class: "transition-cover" }), hAsync("div", { class: "transition-shadow" }))) : null, fixedSlotPlacement === 'after' ? hAsync("slot", { name: "fixed" }) : null));
13818
13904
  }
13819
13905
  get el() { return getElement(this); }
13820
13906
  static get watchers() { return {
@@ -13847,6 +13933,11 @@ class Content {
13847
13933
  "$attrsToReflect$": [["color", "color"]]
13848
13934
  }; }
13849
13935
  }
13936
+ /**
13937
+ * `ion-modal` `--height` values that size the modal to its contents, leaving
13938
+ * children an indefinite height to resolve against.
13939
+ */
13940
+ const CONTENT_SIZED_HEIGHTS = ['auto', 'fit-content', 'min-content', 'max-content'];
13850
13941
  const getParentElement = (el) => {
13851
13942
  if (el.parentElement) {
13852
13943
  // normal element with a parent element
@@ -17028,7 +17119,6 @@ class Datetime {
17028
17119
  }
17029
17120
  renderCombinedDatePickerColumn() {
17030
17121
  const { defaultParts, disabled, workingParts, locale, minParts, maxParts, todayParts, isDateEnabled } = this;
17031
- const activePart = this.getActivePartsWithFallback();
17032
17122
  /**
17033
17123
  * By default, generate a range of 3 months:
17034
17124
  * Previous month, current month, and next month
@@ -17084,8 +17174,10 @@ class Datetime {
17084
17174
  return (hAsync("ion-picker-column", { part: WHEEL_PART, "aria-label": "Select a date", class: "date-column", color: this.color, disabled: disabled, value: todayString, onIonChange: (ev) => {
17085
17175
  const { value } = ev.detail;
17086
17176
  const findPart = parts.find(({ month, day, year }) => value === `${year}-${month}-${day}`);
17177
+ // Read live so parts a sibling column just committed are included.
17178
+ const activePart = this.getActivePartsWithFallback();
17087
17179
  this.setWorkingParts({
17088
- ...workingParts,
17180
+ ...this.workingParts,
17089
17181
  ...findPart,
17090
17182
  });
17091
17183
  this.setActiveParts({
@@ -17162,11 +17254,12 @@ class Datetime {
17162
17254
  return [];
17163
17255
  }
17164
17256
  const { disabled, workingParts } = this;
17165
- const activePart = this.getActivePartsWithFallback();
17166
17257
  const pickerColumnValue = (workingParts.day !== null ? workingParts.day : this.defaultParts.day) ?? undefined;
17167
17258
  return (hAsync("ion-picker-column", { part: WHEEL_PART, "aria-label": "Select a day", class: "day-column", color: this.color, disabled: disabled, value: pickerColumnValue, onIonChange: (ev) => {
17259
+ // Read live so parts a sibling column just committed are included.
17260
+ const activePart = this.getActivePartsWithFallback();
17168
17261
  this.setWorkingParts({
17169
- ...workingParts,
17262
+ ...this.workingParts,
17170
17263
  day: ev.detail.value,
17171
17264
  });
17172
17265
  this.setActiveParts({
@@ -17181,10 +17274,11 @@ class Datetime {
17181
17274
  return [];
17182
17275
  }
17183
17276
  const { disabled, workingParts } = this;
17184
- const activePart = this.getActivePartsWithFallback();
17185
17277
  return (hAsync("ion-picker-column", { part: WHEEL_PART, "aria-label": "Select a month", class: "month-column", color: this.color, disabled: disabled, value: workingParts.month, onIonChange: (ev) => {
17278
+ // Read live so parts a sibling column just committed are included.
17279
+ const activePart = this.getActivePartsWithFallback();
17186
17280
  this.setWorkingParts({
17187
- ...workingParts,
17281
+ ...this.workingParts,
17188
17282
  month: ev.detail.value,
17189
17283
  });
17190
17284
  // Month wheel is navigation-only in multi-select mode as a fix for https://github.com/ionic-team/ionic-framework/issues/29673
@@ -17202,10 +17296,11 @@ class Datetime {
17202
17296
  return [];
17203
17297
  }
17204
17298
  const { disabled, workingParts } = this;
17205
- const activePart = this.getActivePartsWithFallback();
17206
17299
  return (hAsync("ion-picker-column", { part: WHEEL_PART, "aria-label": "Select a year", class: "year-column", color: this.color, disabled: disabled, value: workingParts.year, onIonChange: (ev) => {
17300
+ // Read live so parts a sibling column just committed are included.
17301
+ const activePart = this.getActivePartsWithFallback();
17207
17302
  this.setWorkingParts({
17208
- ...workingParts,
17303
+ ...this.workingParts,
17209
17304
  year: ev.detail.value,
17210
17305
  });
17211
17306
  // Year wheel is navigation-only in multi-select mode as a fix for https://github.com/ionic-team/ionic-framework/issues/29673
@@ -17241,13 +17336,14 @@ class Datetime {
17241
17336
  ];
17242
17337
  }
17243
17338
  renderHourPickerColumn(hoursData) {
17244
- const { disabled, workingParts } = this;
17339
+ const { disabled } = this;
17245
17340
  if (hoursData.length === 0)
17246
17341
  return [];
17247
17342
  const activePart = this.getActivePartsWithFallback();
17248
17343
  return (hAsync("ion-picker-column", { part: WHEEL_PART, "aria-label": "Select an hour", color: this.color, disabled: disabled, value: activePart.hour, numericInput: true, onIonChange: (ev) => {
17344
+ // Read live so parts a sibling column just committed are included.
17249
17345
  this.setWorkingParts({
17250
- ...workingParts,
17346
+ ...this.workingParts,
17251
17347
  hour: ev.detail.value,
17252
17348
  });
17253
17349
  this.setActiveParts({
@@ -17258,13 +17354,14 @@ class Datetime {
17258
17354
  } }, hoursData.map((hour) => (hAsync("ion-picker-column-option", { color: this.color, part: hour.value === activePart.hour ? `${WHEEL_ITEM_PART} ${WHEEL_ITEM_ACTIVE_PART}` : WHEEL_ITEM_PART, key: hour.value, disabled: hour.disabled, value: hour.value }, hour.text)))));
17259
17355
  }
17260
17356
  renderMinutePickerColumn(minutesData) {
17261
- const { disabled, workingParts } = this;
17357
+ const { disabled } = this;
17262
17358
  if (minutesData.length === 0)
17263
17359
  return [];
17264
17360
  const activePart = this.getActivePartsWithFallback();
17265
17361
  return (hAsync("ion-picker-column", { part: WHEEL_PART, "aria-label": "Select a minute", color: this.color, disabled: disabled, value: activePart.minute, numericInput: true, onIonChange: (ev) => {
17362
+ // Read live so parts a sibling column just committed are included.
17266
17363
  this.setWorkingParts({
17267
- ...workingParts,
17364
+ ...this.workingParts,
17268
17365
  minute: ev.detail.value,
17269
17366
  });
17270
17367
  this.setActiveParts({
@@ -17275,16 +17372,18 @@ class Datetime {
17275
17372
  } }, minutesData.map((minute) => (hAsync("ion-picker-column-option", { color: this.color, part: minute.value === activePart.minute ? `${WHEEL_ITEM_PART} ${WHEEL_ITEM_ACTIVE_PART}` : WHEEL_ITEM_PART, key: minute.value, disabled: minute.disabled, value: minute.value }, minute.text)))));
17276
17373
  }
17277
17374
  renderDayPeriodPickerColumn(dayPeriodData) {
17278
- const { disabled, workingParts } = this;
17375
+ const { disabled } = this;
17279
17376
  if (dayPeriodData.length === 0) {
17280
17377
  return [];
17281
17378
  }
17282
17379
  const activePart = this.getActivePartsWithFallback();
17283
17380
  const isDayPeriodRTL = isLocaleDayPeriodRTL(this.locale);
17284
17381
  return (hAsync("ion-picker-column", { part: WHEEL_PART, "aria-label": "Select a day period", style: isDayPeriodRTL ? { order: '-1' } : {}, color: this.color, disabled: disabled, value: activePart.ampm, onIonChange: (ev) => {
17285
- const hour = calculateHourFromAMPM(workingParts, ev.detail.value);
17382
+ // Read live so parts a sibling column just committed are included.
17383
+ const currentParts = this.workingParts;
17384
+ const hour = calculateHourFromAMPM(currentParts, ev.detail.value);
17286
17385
  this.setWorkingParts({
17287
- ...workingParts,
17386
+ ...currentParts,
17288
17387
  ampm: ev.detail.value,
17289
17388
  hour,
17290
17389
  });
@@ -17636,7 +17735,7 @@ class Datetime {
17636
17735
  const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
17637
17736
  const hasWheelVariant = hasDatePresentation && preferWheel;
17638
17737
  renderHiddenInput(true, el, name, formatValue(value), disabled);
17639
- return (hAsync(Host, { key: 'd8e6dfe5e3bffb1c38a3e37b63b3aec099f40d29', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: {
17738
+ return (hAsync(Host, { key: '4e0b529a70924b065bcc6191e08550428b5a52a0', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: {
17640
17739
  ...createColorClasses$1(color, {
17641
17740
  [mode]: true,
17642
17741
  ['datetime-readonly']: readonly,
@@ -17648,7 +17747,7 @@ class Datetime {
17648
17747
  [`datetime-prefer-wheel`]: hasWheelVariant,
17649
17748
  [`datetime-grid`]: isGridStyle,
17650
17749
  }),
17651
- } }, hAsync("div", { key: '20889d3c68dd5109633c0e214411a63d6f3025bb', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
17750
+ } }, hAsync("div", { key: 'cc9d1b92f960984cb0466d0003a240ace67da243', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
17652
17751
  }
17653
17752
  get el() { return getElement(this); }
17654
17753
  static get watchers() { return {
@@ -22952,6 +23051,10 @@ class Loading {
22952
23051
  connectedCallback() {
22953
23052
  prepareOverlay(this.el);
22954
23053
  this.triggerChanged();
23054
+ // Re-apply the root lock if moved without dismiss() being called
23055
+ if (this.presented) {
23056
+ restoreRootFocusTrapAccessibility(this.el);
23057
+ }
22955
23058
  }
22956
23059
  componentWillLoad() {
22957
23060
  if (this.spinner === undefined) {
@@ -23052,14 +23155,14 @@ class Loading {
23052
23155
  * Otherwise, don't set aria-labelledby.
23053
23156
  */
23054
23157
  const ariaLabelledBy = message !== undefined ? msgId : null;
23055
- return (hAsync(Host, { key: '2d14122ff3081de73631a7fdd4affdd5c73b8618', role: "dialog", "aria-modal": "true", "aria-labelledby": ariaLabelledBy, tabindex: "-1", ...htmlAttributes, style: {
23158
+ return (hAsync(Host, { key: 'b4430bc66aedeca19d5645667cba73c169c4bd76', role: "dialog", "aria-modal": "true", "aria-labelledby": ariaLabelledBy, tabindex: "-1", ...htmlAttributes, style: {
23056
23159
  zIndex: `${40000 + this.overlayIndex}`,
23057
23160
  }, onIonBackdropTap: this.onBackdropTap, class: {
23058
23161
  ...getClassMap(this.cssClass),
23059
23162
  [mode]: true,
23060
23163
  'overlay-hidden': true,
23061
23164
  'loading-translucent': this.translucent,
23062
- } }, hAsync("ion-backdrop", { key: 'b7d5bb0d670a20c159d7f67327bf3b1489449188', visible: this.showBackdrop, tappable: this.backdropDismiss }), hAsync("div", { key: '085ce92bd2004d323ab47eb472b83826e48dc619', tabindex: "0", "aria-hidden": "true" }), hAsync("div", { key: '4ecd5bfc0bbd3da434d32f0f319f867a44c5e1f1', class: "loading-wrapper ion-overlay-wrapper" }, spinner && (hAsync("div", { key: '5a4498e1421e09d01c0ee4312eae5272e95c3127', class: "loading-spinner" }, hAsync("ion-spinner", { key: '1b3bc7d45d775195657ead3535f65e6b79f37e84', name: spinner, "aria-hidden": "true" }))), message !== undefined && this.renderLoadingMessage(msgId)), hAsync("div", { key: 'bc7c5467b9f1c6ab957f79934e97acc713bdec37', tabindex: "0", "aria-hidden": "true" })));
23165
+ } }, hAsync("ion-backdrop", { key: 'dec0df942ae778c99ebd4dbf08d6c2a0a992639d', visible: this.showBackdrop, tappable: this.backdropDismiss }), hAsync("div", { key: '71b2d5fc259666225047fc901648ada1efcd5d4b', tabindex: "0", "aria-hidden": "true" }), hAsync("div", { key: '1d83dc3b57ee70c9e8c0f006c6fa576bd96ecded', class: "loading-wrapper ion-overlay-wrapper" }, spinner && (hAsync("div", { key: 'd1cd127e044b8831e396b53122322c1db7e89904', class: "loading-spinner" }, hAsync("ion-spinner", { key: '38c2580cf5659da612872f01801a5fbdc2c023ba', name: spinner, "aria-hidden": "true" }))), message !== undefined && this.renderLoadingMessage(msgId)), hAsync("div", { key: '90e5e32ffe0df2c691f364149f43374e676bfaa3', tabindex: "0", "aria-hidden": "true" })));
23063
23166
  }
23064
23167
  get el() { return getElement(this); }
23065
23168
  static get watchers() { return {
@@ -26580,9 +26683,9 @@ const clearSafeAreaOverrides = (hostEl) => {
26580
26683
  hostEl.style.removeProperty('--ion-safe-area-right');
26581
26684
  };
26582
26685
 
26583
- const modalIosCss = () => `:host{--width:100%;--min-width:auto;--max-width:auto;--height:100%;--min-height:auto;--max-height:auto;--overflow:hidden;--border-radius:0;--border-width:0;--border-style:none;--border-color:transparent;--background:var(--ion-background-color, #fff);--box-shadow:none;--backdrop-opacity:0;left:0;right:0;top:0;bottom:0;display:-ms-flexbox;display:flex;position:absolute;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;outline:none;color:var(--ion-text-color, #000);contain:strict}.modal-wrapper,ion-backdrop{pointer-events:auto}:host(.overlay-hidden){display:none}.modal-wrapper,.modal-shadow{border-radius:var(--border-radius);width:var(--width);min-width:var(--min-width);max-width:var(--max-width);height:var(--height);min-height:var(--min-height);max-height:var(--max-height);border-width:var(--border-width);border-style:var(--border-style);border-color:var(--border-color);background:var(--background);-webkit-box-shadow:var(--box-shadow);box-shadow:var(--box-shadow);overflow:var(--overflow);z-index:10}.modal-wrapper{outline:none}.modal-shadow{position:absolute;background:transparent}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--width:600px;--height:500px}}@media only screen and (min-width: 768px) and (min-height: 768px){:host{--width:600px;--height:600px}}.modal-handle{left:0px;right:0px;top:5px;border-radius:8px;-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto;position:absolute;width:36px;height:5px;-webkit-transform:translateZ(0);transform:translateZ(0);border:0;background:var(--ion-color-step-350, var(--ion-background-color-step-350, #c0c0be));cursor:pointer;z-index:11}.modal-handle::before{-webkit-padding-start:4px;padding-inline-start:4px;-webkit-padding-end:4px;padding-inline-end:4px;padding-top:4px;padding-bottom:4px;position:absolute;width:36px;height:5px;-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%);content:""}:host(.modal-sheet){--height:calc(100% - (var(--ion-modal-offset-top, 0px) + 10px))}:host(.modal-sheet) .modal-wrapper,:host(.modal-sheet) .modal-shadow{position:absolute;bottom:0}:host(.modal-sheet.modal-no-expand-scroll) ion-footer{position:absolute;bottom:0;width:var(--width)}:host{--backdrop-opacity:var(--ion-backdrop-opacity, 0.4)}:host(.modal-card),:host(.modal-sheet){--border-radius:10px}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--border-radius:10px}}.modal-wrapper{-webkit-transform:translate3d(0, 100%, 0);transform:translate3d(0, 100%, 0)}@media screen and (max-width: 767px){@supports (width: max(0px, 1px)){:host(.modal-card){--height:calc(100% - max(30px, var(--ion-safe-area-top)) - 10px)}}@supports not (width: max(0px, 1px)){:host(.modal-card){--height:calc(100% - 40px)}}:host(.modal-card) .modal-wrapper{border-start-start-radius:var(--border-radius);border-start-end-radius:var(--border-radius);border-end-end-radius:0;border-end-start-radius:0}:host(.modal-card){--backdrop-opacity:0;--width:100%;-ms-flex-align:end;align-items:flex-end}:host(.modal-card) .modal-shadow{display:none}:host(.modal-card) ion-backdrop{pointer-events:none}}@media screen and (min-width: 768px){:host(.modal-card){--width:calc(100% - 120px);--height:calc(100% - (120px + var(--ion-safe-area-top) + var(--ion-safe-area-bottom)));--max-width:720px;--max-height:1000px;--backdrop-opacity:0;--box-shadow:0px 0px 30px 10px rgba(0, 0, 0, 0.1);-webkit-transition:all 0.5s ease-in-out;transition:all 0.5s ease-in-out}:host(.modal-card) .modal-wrapper{-webkit-box-shadow:none;box-shadow:none}:host(.modal-card) .modal-shadow{-webkit-box-shadow:var(--box-shadow);box-shadow:var(--box-shadow)}}:host(.modal-sheet) .modal-wrapper{border-start-start-radius:var(--border-radius);border-start-end-radius:var(--border-radius);border-end-end-radius:0;border-end-start-radius:0}`;
26686
+ const modalIosCss = () => `:host{--width:100%;--min-width:auto;--max-width:auto;--height:100%;--min-height:auto;--max-height:100%;--overflow:hidden;--border-radius:0;--border-width:0;--border-style:none;--border-color:transparent;--background:var(--ion-background-color, #fff);--box-shadow:none;--backdrop-opacity:0;left:0;right:0;top:0;bottom:0;display:-ms-flexbox;display:flex;position:absolute;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;outline:none;color:var(--ion-text-color, #000);contain:strict}.modal-wrapper,ion-backdrop{pointer-events:auto}:host(.overlay-hidden){display:none}.modal-wrapper,.modal-shadow{border-radius:var(--border-radius);width:var(--width);min-width:var(--min-width);max-width:var(--max-width);height:var(--height);min-height:var(--min-height);max-height:var(--max-height);border-width:var(--border-width);border-style:var(--border-style);border-color:var(--border-color);background:var(--background);-webkit-box-shadow:var(--box-shadow);box-shadow:var(--box-shadow);overflow:var(--overflow);z-index:10}.modal-wrapper{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;outline:none}.modal-shadow{position:absolute;background:transparent}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--width:600px;--height:500px}}@media only screen and (min-width: 768px) and (min-height: 768px){:host{--width:600px;--height:600px}}.modal-handle{left:0px;right:0px;top:5px;border-radius:8px;-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto;position:absolute;width:36px;height:5px;-webkit-transform:translateZ(0);transform:translateZ(0);border:0;background:var(--ion-color-step-350, var(--ion-background-color-step-350, #c0c0be));cursor:pointer;z-index:11}.modal-handle::before{-webkit-padding-start:4px;padding-inline-start:4px;-webkit-padding-end:4px;padding-inline-end:4px;padding-top:4px;padding-bottom:4px;position:absolute;width:36px;height:5px;-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%);content:""}:host(.modal-sheet){--height:calc(100% - (var(--ion-modal-offset-top, 0px) + 10px))}:host(.modal-sheet) .modal-wrapper,:host(.modal-sheet) .modal-shadow{position:absolute;bottom:0}:host(.modal-sheet.modal-no-expand-scroll) ion-footer{position:absolute;bottom:0;width:var(--width)}:host{--backdrop-opacity:var(--ion-backdrop-opacity, 0.4)}:host(.modal-card),:host(.modal-sheet){--border-radius:10px}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--border-radius:10px}}.modal-wrapper{-webkit-transform:translate3d(0, 100%, 0);transform:translate3d(0, 100%, 0)}@media screen and (max-width: 767px){@supports (width: max(0px, 1px)){:host(.modal-card){--height:calc(100% - max(30px, var(--ion-safe-area-top)) - 10px)}}@supports not (width: max(0px, 1px)){:host(.modal-card){--height:calc(100% - 40px)}}:host(.modal-card) .modal-wrapper{border-start-start-radius:var(--border-radius);border-start-end-radius:var(--border-radius);border-end-end-radius:0;border-end-start-radius:0}:host(.modal-card){--backdrop-opacity:0;--width:100%;-ms-flex-align:end;align-items:flex-end}:host(.modal-card) .modal-shadow{display:none}:host(.modal-card) ion-backdrop{pointer-events:none}}@media screen and (min-width: 768px){:host(.modal-card){--width:calc(100% - 120px);--height:calc(100% - (120px + var(--ion-safe-area-top) + var(--ion-safe-area-bottom)));--max-width:720px;--max-height:1000px;--backdrop-opacity:0;--box-shadow:0px 0px 30px 10px rgba(0, 0, 0, 0.1);-webkit-transition:all 0.5s ease-in-out;transition:all 0.5s ease-in-out}:host(.modal-card) .modal-wrapper{-webkit-box-shadow:none;box-shadow:none}:host(.modal-card) .modal-shadow{-webkit-box-shadow:var(--box-shadow);box-shadow:var(--box-shadow)}}:host(.modal-sheet) .modal-wrapper{border-start-start-radius:var(--border-radius);border-start-end-radius:var(--border-radius);border-end-end-radius:0;border-end-start-radius:0}`;
26584
26687
 
26585
- const modalMdCss = () => `:host{--width:100%;--min-width:auto;--max-width:auto;--height:100%;--min-height:auto;--max-height:auto;--overflow:hidden;--border-radius:0;--border-width:0;--border-style:none;--border-color:transparent;--background:var(--ion-background-color, #fff);--box-shadow:none;--backdrop-opacity:0;left:0;right:0;top:0;bottom:0;display:-ms-flexbox;display:flex;position:absolute;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;outline:none;color:var(--ion-text-color, #000);contain:strict}.modal-wrapper,ion-backdrop{pointer-events:auto}:host(.overlay-hidden){display:none}.modal-wrapper,.modal-shadow{border-radius:var(--border-radius);width:var(--width);min-width:var(--min-width);max-width:var(--max-width);height:var(--height);min-height:var(--min-height);max-height:var(--max-height);border-width:var(--border-width);border-style:var(--border-style);border-color:var(--border-color);background:var(--background);-webkit-box-shadow:var(--box-shadow);box-shadow:var(--box-shadow);overflow:var(--overflow);z-index:10}.modal-wrapper{outline:none}.modal-shadow{position:absolute;background:transparent}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--width:600px;--height:500px}}@media only screen and (min-width: 768px) and (min-height: 768px){:host{--width:600px;--height:600px}}.modal-handle{left:0px;right:0px;top:5px;border-radius:8px;-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto;position:absolute;width:36px;height:5px;-webkit-transform:translateZ(0);transform:translateZ(0);border:0;background:var(--ion-color-step-350, var(--ion-background-color-step-350, #c0c0be));cursor:pointer;z-index:11}.modal-handle::before{-webkit-padding-start:4px;padding-inline-start:4px;-webkit-padding-end:4px;padding-inline-end:4px;padding-top:4px;padding-bottom:4px;position:absolute;width:36px;height:5px;-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%);content:""}:host(.modal-sheet){--height:calc(100% - (var(--ion-modal-offset-top, 0px) + 10px))}:host(.modal-sheet) .modal-wrapper,:host(.modal-sheet) .modal-shadow{position:absolute;bottom:0}:host(.modal-sheet.modal-no-expand-scroll) ion-footer{position:absolute;bottom:0;width:var(--width)}:host{--backdrop-opacity:var(--ion-backdrop-opacity, 0.32)}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--border-radius:2px;--box-shadow:0 28px 48px rgba(0, 0, 0, 0.4)}}.modal-wrapper{-webkit-transform:translate3d(0, 40px, 0);transform:translate3d(0, 40px, 0);opacity:0.01}`;
26688
+ const modalMdCss = () => `:host{--width:100%;--min-width:auto;--max-width:auto;--height:100%;--min-height:auto;--max-height:100%;--overflow:hidden;--border-radius:0;--border-width:0;--border-style:none;--border-color:transparent;--background:var(--ion-background-color, #fff);--box-shadow:none;--backdrop-opacity:0;left:0;right:0;top:0;bottom:0;display:-ms-flexbox;display:flex;position:absolute;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;outline:none;color:var(--ion-text-color, #000);contain:strict}.modal-wrapper,ion-backdrop{pointer-events:auto}:host(.overlay-hidden){display:none}.modal-wrapper,.modal-shadow{border-radius:var(--border-radius);width:var(--width);min-width:var(--min-width);max-width:var(--max-width);height:var(--height);min-height:var(--min-height);max-height:var(--max-height);border-width:var(--border-width);border-style:var(--border-style);border-color:var(--border-color);background:var(--background);-webkit-box-shadow:var(--box-shadow);box-shadow:var(--box-shadow);overflow:var(--overflow);z-index:10}.modal-wrapper{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;outline:none}.modal-shadow{position:absolute;background:transparent}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--width:600px;--height:500px}}@media only screen and (min-width: 768px) and (min-height: 768px){:host{--width:600px;--height:600px}}.modal-handle{left:0px;right:0px;top:5px;border-radius:8px;-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto;position:absolute;width:36px;height:5px;-webkit-transform:translateZ(0);transform:translateZ(0);border:0;background:var(--ion-color-step-350, var(--ion-background-color-step-350, #c0c0be));cursor:pointer;z-index:11}.modal-handle::before{-webkit-padding-start:4px;padding-inline-start:4px;-webkit-padding-end:4px;padding-inline-end:4px;padding-top:4px;padding-bottom:4px;position:absolute;width:36px;height:5px;-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%);content:""}:host(.modal-sheet){--height:calc(100% - (var(--ion-modal-offset-top, 0px) + 10px))}:host(.modal-sheet) .modal-wrapper,:host(.modal-sheet) .modal-shadow{position:absolute;bottom:0}:host(.modal-sheet.modal-no-expand-scroll) ion-footer{position:absolute;bottom:0;width:var(--width)}:host{--backdrop-opacity:var(--ion-backdrop-opacity, 0.32)}@media only screen and (min-width: 768px) and (min-height: 600px){:host{--border-radius:2px;--box-shadow:0 28px 48px rgba(0, 0, 0, 0.4)}}.modal-wrapper{-webkit-transform:translate3d(0, 40px, 0);transform:translate3d(0, 40px, 0);opacity:0.01}`;
26586
26689
 
26587
26690
  // TODO(FW-2832): types
26588
26691
  /**
@@ -26618,6 +26721,9 @@ class Modal {
26618
26721
  this.inline = false;
26619
26722
  // Whether or not modal is being dismissed via gesture
26620
26723
  this.gestureAnimationDismissing = false;
26724
+ // True from the first safe-area write in `present()` until the enter
26725
+ // animation settles. A position-based read in that window is not the rest position.
26726
+ this.isPresenting = false;
26621
26727
  this.presented = false;
26622
26728
  /** @internal */
26623
26729
  this.hasController = false;
@@ -26854,6 +26960,17 @@ class Modal {
26854
26960
  const { el } = this;
26855
26961
  prepareOverlay(el);
26856
26962
  this.triggerChanged();
26963
+ // A disconnect tears down state this presentation still needs and cannot
26964
+ // tell a re-insert from a removal, so put it back.
26965
+ if (this.presented || this.isPresenting) {
26966
+ this.restoreSafeAreaOverrides();
26967
+ }
26968
+ // A relocation from `willPresent` reaches these before `present()` has
26969
+ // applied the lock, so they apply it instead. Both are idempotent.
26970
+ if (this.presented) {
26971
+ restoreRootFocusTrapAccessibility(el);
26972
+ this.initParentRemovalObserver();
26973
+ }
26857
26974
  }
26858
26975
  disconnectedCallback() {
26859
26976
  this.triggerController.removeClickListener();
@@ -27031,25 +27148,33 @@ class Modal {
27031
27148
  // Recalculate isSheetModal before safe-area setup because framework
27032
27149
  // bindings (e.g., Angular) may not have been applied when componentWillLoad ran.
27033
27150
  this.isSheetModal = this.breakpoints !== undefined && this.initialBreakpoint !== undefined;
27034
- // Set initial safe-area overrides before animation
27035
- this.setInitialSafeAreaOverrides();
27151
+ this.isPresenting = true;
27036
27152
  const hasCardModal = presentingElement !== undefined;
27037
- /**
27038
- * We need to change the status bar at the
27039
- * start of the animation so that it completes
27040
- * by the time the card animation is done.
27041
- */
27042
- if (hasCardModal && getIonMode$1(this) === 'ios') {
27043
- // Cache the original status bar color before the modal is presented
27044
- this.statusBarStyle = await StatusBar.getStyle();
27045
- setCardStatusBarDark();
27153
+ // Wrapped so a throw cannot strand `isPresenting`, which would suppress
27154
+ // the position-based correction for the life of this instance.
27155
+ try {
27156
+ // Set initial safe-area overrides before animation
27157
+ this.setInitialSafeAreaOverrides();
27158
+ /**
27159
+ * We need to change the status bar at the
27160
+ * start of the animation so that it completes
27161
+ * by the time the card animation is done.
27162
+ */
27163
+ if (hasCardModal && getIonMode$1(this) === 'ios') {
27164
+ // Cache the original status bar color before the modal is presented
27165
+ this.statusBarStyle = await StatusBar.getStyle();
27166
+ setCardStatusBarDark();
27167
+ }
27168
+ await present(this, 'modalEnter', iosEnterAnimation$2, mdEnterAnimation$2, {
27169
+ presentingEl: presentingElement,
27170
+ currentBreakpoint: this.initialBreakpoint,
27171
+ backdropBreakpoint: this.backdropBreakpoint,
27172
+ expandToScroll: this.expandToScroll,
27173
+ });
27174
+ }
27175
+ finally {
27176
+ this.isPresenting = false;
27046
27177
  }
27047
- await present(this, 'modalEnter', iosEnterAnimation$2, mdEnterAnimation$2, {
27048
- presentingEl: presentingElement,
27049
- currentBreakpoint: this.initialBreakpoint,
27050
- backdropBreakpoint: this.backdropBreakpoint,
27051
- expandToScroll: this.expandToScroll,
27052
- });
27053
27178
  // Update safe-area based on actual position after animation
27054
27179
  this.updateSafeAreaOverrides();
27055
27180
  // Apply fullscreen safe-area padding if needed
@@ -27551,6 +27676,9 @@ class Modal {
27551
27676
  this.cachedOriginalParent.tagName === 'ION-APP') {
27552
27677
  return;
27553
27678
  }
27679
+ // Both `present()` and a reconnect call this, so drop any existing
27680
+ // observer. Below the guards, so a call that bails cannot leave none.
27681
+ this.cleanupParentRemovalObserver();
27554
27682
  this.parentRemovalObserver = new MutationObserver((mutations) => {
27555
27683
  mutations.forEach((mutation) => {
27556
27684
  if (mutation.type === 'childList' && mutation.removedNodes.length > 0) {
@@ -27629,6 +27757,9 @@ class Modal {
27629
27757
  // Set the internal offset property with the resolved root safe-area-top value
27630
27758
  if (context.isSheetModal) {
27631
27759
  this.updateSheetOffsetTop();
27760
+ // A restore after a DOM move runs this a second time for the same
27761
+ // modal, so drop the previous subscription rather than stacking one.
27762
+ this.unsubscribeRootSafeAreaTop?.();
27632
27763
  this.unsubscribeRootSafeAreaTop = onRootSafeAreaTopChange((safeAreaTop) => this.updateSheetOffsetTop(safeAreaTop));
27633
27764
  }
27634
27765
  }
@@ -27747,6 +27878,31 @@ class Modal {
27747
27878
  const { contentEl } = this.findContentAndFooter();
27748
27879
  this.clearContentSafeAreaPadding(contentEl);
27749
27880
  }
27881
+ /**
27882
+ * Re-applies what `cleanupSafeAreaOverrides()` removed for a modal moved
27883
+ * while presented. Anything needing no measurement goes on synchronously so
27884
+ * the modal is never painted without safe-area. The position-based
27885
+ * correction waits a frame for the layout pass it reads.
27886
+ */
27887
+ restoreSafeAreaOverrides() {
27888
+ this.setInitialSafeAreaOverrides();
27889
+ this.applyFullscreenSafeArea();
27890
+ raf(() => {
27891
+ // A dismiss or another move can land first, and a read before the enter
27892
+ // animation settles is not the rest position. `present()` redoes it.
27893
+ if (!this.presented || !this.el.isConnected || this.isPresenting) {
27894
+ return;
27895
+ }
27896
+ // A hidden subtree carries `display: none`, so there is no box and the
27897
+ // read would write the safe-area for a modal touching no edge. The
27898
+ // prediction applied above holds until the modal is shown again.
27899
+ const { width, height } = this.el.getBoundingClientRect();
27900
+ if (width === 0 && height === 0) {
27901
+ return;
27902
+ }
27903
+ this.updateSafeAreaOverrides();
27904
+ });
27905
+ }
27750
27906
  render() {
27751
27907
  const { handle, isSheetModal, presentingElement, htmlAttributes, handleBehavior, inheritedAttributes, focusTrap, expandToScroll, } = this;
27752
27908
  const showHandle = handle !== false && isSheetModal;
@@ -27754,7 +27910,7 @@ class Modal {
27754
27910
  const isCardModal = presentingElement !== undefined && mode === 'ios';
27755
27911
  const isHandleCycle = handleBehavior === 'cycle';
27756
27912
  const isSheetModalWithHandle = isSheetModal && showHandle;
27757
- return (hAsync(Host, { key: 'a471c293319cb6ee5ffb7ffafec0b8413e4289de', "no-router": true,
27913
+ return (hAsync(Host, { key: '7c9c736052c5a788cf31040b6b2386dd9ea7454b', "no-router": true,
27758
27914
  // Allow the modal to be navigable when the handle is focusable
27759
27915
  tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1, ...htmlAttributes, style: {
27760
27916
  zIndex: `${20000 + this.overlayIndex}`,
@@ -27767,7 +27923,7 @@ class Modal {
27767
27923
  'overlay-hidden': true,
27768
27924
  [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false,
27769
27925
  ...getClassMap(this.cssClass),
27770
- }, onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }, hAsync("ion-backdrop", { key: 'f67934afd4ddad64623856fb641cb6db846df428', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && hAsync("div", { key: 'a23f5cb6cf60c8f717c1dd556bce375829c80a43', class: "modal-shadow" }), hAsync("div", { key: '51eb6cd1070e4b7e49840a78dc7437238c867a01',
27926
+ }, onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }, hAsync("ion-backdrop", { key: '01b5b5765fb3a32393c736065c824bf760728823', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && hAsync("div", { key: '40fa7727a0923f7d7461dd027f1511a6a148d84a', class: "modal-shadow" }), hAsync("div", { key: '9af934b607f60795bd5bff7bee6eacfc9b14fa35',
27771
27927
  /*
27772
27928
  role and aria-modal must be used on the
27773
27929
  same element. They must also be set inside the
@@ -27780,9 +27936,9 @@ class Modal {
27780
27936
  without the tabindex focus() would be a no-op and screen readers
27781
27937
  may not properly announce the dialog and its content when it opens.
27782
27938
  */
27783
- role: "dialog", ...inheritedAttributes, "aria-modal": "true", tabIndex: -1, class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }, showHandle && (hAsync("button", { key: 'f49a144642b5c227c0c2b00b33f4c7e37a2bf088', class: "modal-handle",
27939
+ role: "dialog", ...inheritedAttributes, "aria-modal": "true", tabIndex: -1, class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }, showHandle && (hAsync("button", { key: 'df84a6806413b13efc5b03c862edde83151579a7', class: "modal-handle",
27784
27940
  // Prevents the handle from receiving keyboard focus when it does not cycle
27785
- tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), hAsync("slot", { key: 'e781c0d5881762c6b61aa432721a38b49580ff64', onSlotchange: this.onSlotChange }))));
27941
+ tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), hAsync("slot", { key: '072d3929ec6f25481946b184d8ac24219011e783', onSlotchange: this.onSlotChange }))));
27786
27942
  }
27787
27943
  get el() { return getElement(this); }
27788
27944
  static get watchers() { return {
@@ -29257,6 +29413,12 @@ class PickerColumn {
29257
29413
  this.isColumnVisible = false;
29258
29414
  this.canExitInputMode = true;
29259
29415
  this.updateValueTextOnScroll = false;
29416
+ this.isUserScroll = false;
29417
+ /**
29418
+ * The haptics for the wheel picker are an iOS-only feature. As a result,
29419
+ * they should be disabled on Android.
29420
+ */
29421
+ this.enableHaptics = false;
29260
29422
  this.ariaLabel = null;
29261
29423
  this.isActive = false;
29262
29424
  /**
@@ -29288,6 +29450,12 @@ class PickerColumn {
29288
29450
  */
29289
29451
  this.canExitInputMode = canExitInputMode;
29290
29452
  this.updateValueTextOnScroll = false;
29453
+ /**
29454
+ * This scroll takes over from whatever the user was doing, so an outside
29455
+ * press must not commit an option the column is only passing through.
29456
+ */
29457
+ this.isUserScroll = false;
29458
+ this.stopWatchingForOutsidePress();
29291
29459
  scrollEl.scroll({
29292
29460
  top,
29293
29461
  left: 0,
@@ -29342,6 +29510,117 @@ class PickerColumn {
29342
29510
  }
29343
29511
  this.isActive = state;
29344
29512
  };
29513
+ this.clearScrollEndTimeout = () => {
29514
+ if (this.scrollEndTimeout) {
29515
+ clearTimeout(this.scrollEndTimeout);
29516
+ this.scrollEndTimeout = undefined;
29517
+ }
29518
+ };
29519
+ /**
29520
+ * Resets the idle timer that commits the centered option.
29521
+ */
29522
+ this.resetScrollEndTimeout = () => {
29523
+ this.clearScrollEndTimeout();
29524
+ this.scrollEndTimeout = setTimeout(this.settle, SCROLL_END_DELAY);
29525
+ };
29526
+ /**
29527
+ * Capture so the column still commits if an application's own pointerdown
29528
+ * handler stops the event before it reaches the document.
29529
+ */
29530
+ this.watchForOutsidePress = () => {
29531
+ doc?.addEventListener('pointerdown', this.onPointerDownOutside, { capture: true });
29532
+ };
29533
+ this.stopWatchingForOutsidePress = () => {
29534
+ doc?.removeEventListener('pointerdown', this.onPointerDownOutside, { capture: true });
29535
+ };
29536
+ /**
29537
+ * Resets everything the current scroll interaction is holding, so nothing
29538
+ * pending on it can commit later.
29539
+ */
29540
+ this.discardScroll = () => {
29541
+ this.stopWatchingForOutsidePress();
29542
+ this.clearScrollEndTimeout();
29543
+ this.scrollEndCallback = undefined;
29544
+ this.centeredOption = undefined;
29545
+ this.haltedAtScrollTop = undefined;
29546
+ this.isScrolling = false;
29547
+ this.isUserScroll = false;
29548
+ this.canExitInputMode = true;
29549
+ };
29550
+ /**
29551
+ * Commits the option that is currently centered under the highlight and ends
29552
+ * the scroll interaction.
29553
+ */
29554
+ this.settle = () => {
29555
+ const { centeredOption } = this;
29556
+ this.clearScrollEndTimeout();
29557
+ this.stopWatchingForOutsidePress();
29558
+ this.isUserScroll = false;
29559
+ this.isScrolling = false;
29560
+ this.updateValueTextOnScroll = true;
29561
+ this.enableHaptics && hapticSelectionEnd();
29562
+ /**
29563
+ * Certain tasks (such as those that
29564
+ * cause re-renders) should only be done
29565
+ * once scrolling has finished, otherwise
29566
+ * flickering may occur.
29567
+ */
29568
+ const { scrollEndCallback } = this;
29569
+ if (scrollEndCallback) {
29570
+ scrollEndCallback();
29571
+ this.scrollEndCallback = undefined;
29572
+ }
29573
+ /**
29574
+ * Reset this flag as the
29575
+ * next scroll interaction could
29576
+ * be a scroll from the user. In this
29577
+ * case, we should exit input mode.
29578
+ */
29579
+ this.canExitInputMode = true;
29580
+ if (centeredOption !== undefined) {
29581
+ // Cleared here so a later scroll that centers nothing cannot fall back on it.
29582
+ this.centeredOption = undefined;
29583
+ if (centeredOption.isConnected) {
29584
+ this.setValue(centeredOption.value);
29585
+ }
29586
+ }
29587
+ };
29588
+ /**
29589
+ * Commits the option the user can see when they press anything outside of the
29590
+ * column during a scroll they started. This runs on pointerdown rather than
29591
+ * click so the value is up to date by the time an application's own click
29592
+ * handler (a Save button, for example) reads it.
29593
+ */
29594
+ this.onPointerDownOutside = (ev) => {
29595
+ const { centeredOption, parentEl, scrollEl } = this;
29596
+ if (!this.isScrolling) {
29597
+ return;
29598
+ }
29599
+ /**
29600
+ * The column can live in another component's Shadow DOM, where a document
29601
+ * listener sees the target retargeted to the outer host. The composed path
29602
+ * is the only reliable way to tell a press on the column apart.
29603
+ */
29604
+ const path = ev.composedPath();
29605
+ /**
29606
+ * A press anywhere in the parent picker counts as inside, so reaching for a
29607
+ * sibling wheel leaves this column coasting.
29608
+ */
29609
+ if (path.includes(this.el) || (parentEl != null && path.includes(parentEl))) {
29610
+ return;
29611
+ }
29612
+ /**
29613
+ * Landing on the centered option halts the in-flight momentum scroll, so the
29614
+ * committed value and the option the user is left looking at agree. The
29615
+ * option list can be replaced mid-scroll, and a detached option has no
29616
+ * offset to center on.
29617
+ */
29618
+ if (centeredOption !== undefined && centeredOption.isConnected) {
29619
+ this.centerPickerItemInView(centeredOption, false, false);
29620
+ this.haltedAtScrollTop = scrollEl?.scrollTop;
29621
+ }
29622
+ this.settle();
29623
+ };
29345
29624
  /**
29346
29625
  * When the column scrolls, the component
29347
29626
  * needs to determine which item is centered
@@ -29349,27 +29628,42 @@ class PickerColumn {
29349
29628
  * the item object.
29350
29629
  */
29351
29630
  this.initializeScrollListener = () => {
29352
- /**
29353
- * The haptics for the wheel picker are
29354
- * an iOS-only feature. As a result, they should
29355
- * be disabled on Android.
29356
- */
29357
- const enableHaptics = isPlatform('ios');
29631
+ this.enableHaptics = isPlatform('ios');
29358
29632
  const { el, scrollEl } = this;
29359
- let timeout;
29360
29633
  let activeEl = this.activeItem;
29361
29634
  const scrollCallback = () => {
29362
29635
  raf(() => {
29363
- if (!scrollEl)
29636
+ /**
29637
+ * This frame cannot be cancelled, and moving the column disconnects it
29638
+ * without the observer reporting a change, so this checks live state.
29639
+ */
29640
+ if (!this.el.isConnected || !this.isColumnVisible || !scrollEl)
29364
29641
  return;
29365
- if (timeout) {
29366
- clearTimeout(timeout);
29367
- timeout = undefined;
29642
+ const { haltedAtScrollTop } = this;
29643
+ if (haltedAtScrollTop !== undefined) {
29644
+ /**
29645
+ * Still at the halted position, so this frame is the halt landing
29646
+ * rather than the wheel moving, and re-arming would start a second
29647
+ * commit cycle.
29648
+ */
29649
+ if (Math.abs(scrollEl.scrollTop - haltedAtScrollTop) <= HALT_TOLERANCE)
29650
+ return;
29651
+ this.haltedAtScrollTop = undefined;
29368
29652
  }
29653
+ // Armed before the early returns below, so a scroll never ends uncommitted.
29654
+ this.resetScrollEndTimeout();
29369
29655
  if (!this.isScrolling) {
29370
- enableHaptics && hapticSelectionStart();
29656
+ this.enableHaptics && hapticSelectionStart();
29371
29657
  this.isScrolling = true;
29372
29658
  }
29659
+ /**
29660
+ * Only a user-driven scroll holds an uncommitted selection. Checked every
29661
+ * frame because the user can take hold of the wheel mid-scroll, and
29662
+ * re-adding the same listener is a no-op.
29663
+ */
29664
+ if (this.isUserScroll) {
29665
+ this.watchForOutsidePress();
29666
+ }
29373
29667
  /**
29374
29668
  * Select item in the center of the column
29375
29669
  * which is the month/year that we want to select
@@ -29429,18 +29723,23 @@ class PickerColumn {
29429
29723
  newActiveElement = fallbackActiveElement;
29430
29724
  }
29431
29725
  }
29432
- if (activeEl !== undefined) {
29433
- this.setPickerItemActiveState(activeEl, false);
29434
- }
29726
+ /**
29727
+ * A scroll can land with no selectable option centered, such as an
29728
+ * overscroll bounce briefly centering the empty padding rows. Keep the
29729
+ * current selection until an option is centered again.
29730
+ */
29435
29731
  if (newActiveElement === undefined || newActiveElement.disabled) {
29436
29732
  return;
29437
29733
  }
29734
+ if (activeEl !== undefined) {
29735
+ this.setPickerItemActiveState(activeEl, false);
29736
+ }
29438
29737
  /**
29439
29738
  * If we are selecting a new value,
29440
29739
  * we need to run haptics again.
29441
29740
  */
29442
29741
  if (newActiveElement !== activeEl) {
29443
- enableHaptics && hapticSelectionChanged();
29742
+ this.enableHaptics && hapticSelectionChanged();
29444
29743
  if (this.canExitInputMode) {
29445
29744
  /**
29446
29745
  * The native iOS wheel picker
@@ -29472,32 +29771,14 @@ class PickerColumn {
29472
29771
  if (this.updateValueTextOnScroll) {
29473
29772
  this.assistiveFocusable?.setAttribute('aria-valuetext', this.getOptionValueText(newActiveElement));
29474
29773
  }
29475
- timeout = setTimeout(() => {
29476
- this.isScrolling = false;
29477
- this.updateValueTextOnScroll = true;
29478
- enableHaptics && hapticSelectionEnd();
29479
- /**
29480
- * Certain tasks (such as those that
29481
- * cause re-renders) should only be done
29482
- * once scrolling has finished, otherwise
29483
- * flickering may occur.
29484
- */
29485
- const { scrollEndCallback } = this;
29486
- if (scrollEndCallback) {
29487
- scrollEndCallback();
29488
- this.scrollEndCallback = undefined;
29489
- }
29490
- /**
29491
- * Reset this flag as the
29492
- * next scroll interaction could
29493
- * be a scroll from the user. In this
29494
- * case, we should exit input mode.
29495
- */
29496
- this.canExitInputMode = true;
29497
- this.setValue(newActiveElement.value);
29498
- }, 250);
29774
+ this.centeredOption = newActiveElement;
29499
29775
  });
29500
29776
  };
29777
+ const userScrollCallback = () => {
29778
+ this.isUserScroll = true;
29779
+ // Taking hold of the wheel ends the halt even if it has not moved yet.
29780
+ this.haltedAtScrollTop = undefined;
29781
+ };
29501
29782
  /**
29502
29783
  * Wrap this in an raf so that the scroll callback
29503
29784
  * does not fire when component is initially shown.
@@ -29506,8 +29787,19 @@ class PickerColumn {
29506
29787
  if (!scrollEl)
29507
29788
  return;
29508
29789
  scrollEl.addEventListener('scroll', scrollCallback);
29790
+ scrollEl.addEventListener('pointerdown', userScrollCallback);
29791
+ scrollEl.addEventListener('wheel', userScrollCallback, { passive: true });
29792
+ /**
29793
+ * A `pointerdown` fires once per touch, so a drag that pauses long enough
29794
+ * to commit would look like a scroll the column started. A `touchmove`
29795
+ * keeps arriving while the finger moves.
29796
+ */
29797
+ scrollEl.addEventListener('touchmove', userScrollCallback, { passive: true });
29509
29798
  this.destroyScrollListener = () => {
29510
29799
  scrollEl.removeEventListener('scroll', scrollCallback);
29800
+ scrollEl.removeEventListener('pointerdown', userScrollCallback);
29801
+ scrollEl.removeEventListener('wheel', userScrollCallback);
29802
+ scrollEl.removeEventListener('touchmove', userScrollCallback);
29511
29803
  };
29512
29804
  });
29513
29805
  };
@@ -29690,6 +29982,14 @@ class PickerColumn {
29690
29982
  }
29691
29983
  else {
29692
29984
  this.isColumnVisible = false;
29985
+ /**
29986
+ * The pending timer still runs so it resets the scroll state, but the
29987
+ * option it would have committed is dropped. A column the user cannot
29988
+ * see should not change its value.
29989
+ */
29990
+ this.stopWatchingForOutsidePress();
29991
+ this.centeredOption = undefined;
29992
+ this.haltedAtScrollTop = undefined;
29693
29993
  if (this.destroyScrollListener) {
29694
29994
  this.destroyScrollListener();
29695
29995
  this.destroyScrollListener = undefined;
@@ -29760,6 +30060,13 @@ class PickerColumn {
29760
30060
  connectedCallback() {
29761
30061
  this.ariaLabel = this.el.getAttribute('aria-label') ?? 'Select a value';
29762
30062
  }
30063
+ disconnectedCallback() {
30064
+ /**
30065
+ * A pending settle would otherwise commit a value on a column that is no
30066
+ * longer in the DOM.
30067
+ */
30068
+ this.discardScroll();
30069
+ }
29763
30070
  get activeItem() {
29764
30071
  const { value } = this;
29765
30072
  const options = Array.from(this.el.querySelectorAll('ion-picker-column-option'));
@@ -29777,14 +30084,14 @@ class PickerColumn {
29777
30084
  render() {
29778
30085
  const { color, disabled, isActive, numericInput } = this;
29779
30086
  const mode = getIonMode$1(this);
29780
- return (hAsync(Host, { key: '78b46ad10d88ea1bb43ca8c36748767912f03224', class: createColorClasses$1(color, {
30087
+ return (hAsync(Host, { key: '60a893619d0b01fba53fbccef67a10d533a22657', class: createColorClasses$1(color, {
29781
30088
  [mode]: true,
29782
30089
  ['picker-column-active']: isActive,
29783
30090
  ['picker-column-numeric-input']: numericInput,
29784
30091
  ['picker-column-disabled']: disabled,
29785
- }) }, hAsync("slot", { key: '761e501df77f7de896ffb3ebb99ebf88c5c3bf70', name: "prefix" }), hAsync("div", { key: '9f4caaeef8ab704522a85f30876d371712f47c5c', class: "picker-opts", ref: (el) => {
30092
+ }) }, hAsync("slot", { key: '79f1e047f89c5ec916ed02efaac56ef3f73b8969', name: "prefix" }), hAsync("div", { key: 'c45c86e88353a196ff38159f40f390bc27852c9e', class: "picker-opts", ref: (el) => {
29786
30093
  this.scrollEl = el;
29787
- }, role: "slider", tabindex: this.disabled ? undefined : 0, "aria-label": this.ariaLabel, "aria-valuemin": 0, "aria-valuemax": 0, "aria-valuenow": 0, "aria-valuetext": this.getOptionValueText(this.activeItem), "aria-orientation": "vertical", onKeyDown: (ev) => this.onKeyDown(ev) }, hAsync("div", { key: '9d3533436aba6c61c93f65f84a077fba832194a0', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: '3f18d3a47361f06f55321b65fdf5742a61722b26', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: 'eac0d20ab8c533ef829875e323e93e1ee2067d6d', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("slot", { key: '92e25989ef41cf6f910c73238e1a0a5ac03f1c1f' }), hAsync("div", { key: '33a84644ebdc84108b44a8e3a129b54e824939c8', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: '128ad61a3a68c7ff2d2e44a6e968424fcc608a15', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: '6e4d59a4f75befcbbf47279a263f28a69b12dbbd', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0")), hAsync("slot", { key: '3c6621b64438792a3024c90e3d9916a0a3614506', name: "suffix" })));
30094
+ }, role: "slider", tabindex: this.disabled ? undefined : 0, "aria-label": this.ariaLabel, "aria-valuemin": 0, "aria-valuemax": 0, "aria-valuenow": 0, "aria-valuetext": this.getOptionValueText(this.activeItem), "aria-orientation": "vertical", onKeyDown: (ev) => this.onKeyDown(ev) }, hAsync("div", { key: 'e02d76752f5d3dd4cd2846fbc28645f1508a4b49', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: 'd577bcbadc530970b2781692b050811633625c5a', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: 'c89e78c3a896bc1f55b922d01df16fdbb1259bdd', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("slot", { key: '6c597ff899692597432ee2aa0b42de53b86deed4' }), hAsync("div", { key: '91686ed94f14c47647836ed4d63e54b5c54ee3b9', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: '2ff058c6d0e8cef4e143c2d848f9a52684579af1', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), hAsync("div", { key: 'bc7386bec6fced36e44084a7a137b3fe6506c996', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0")), hAsync("slot", { key: '8835fd3f4e025bce964e6f05984c9aaadc20d7fb', name: "suffix" })));
29788
30095
  }
29789
30096
  get el() { return getElement(this); }
29790
30097
  static get watchers() { return {
@@ -29816,6 +30123,19 @@ class PickerColumn {
29816
30123
  }; }
29817
30124
  }
29818
30125
  const PICKER_ITEM_ACTIVE_CLASS = 'option-active';
30126
+ /**
30127
+ * How long the column must be idle before the centered option is treated as
30128
+ * the user's selection. Replaceable by the `scrollend` event once that is
30129
+ * supported everywhere (https://caniuse.com/?search=scrollend).
30130
+ */
30131
+ const SCROLL_END_DELAY = 250;
30132
+ /**
30133
+ * How far, in pixels, the column may report from where it was halted and still
30134
+ * count as having stayed there. Centering targets a position between two snap
30135
+ * points, so mandatory snapping corrects it by half the column height less
30136
+ * three option heights: 2px at the default sizes.
30137
+ */
30138
+ const HALT_TOLERANCE = 2;
29819
30139
 
29820
30140
  const pickerColumnOptionIosCss = () => `.picker-column-option-button{padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;width:100%;height:34px;border:0px;outline:none;background:transparent;color:inherit;font-family:var(--ion-font-family, inherit);font-size:inherit;line-height:34px;text-align:inherit;text-overflow:ellipsis;white-space:nowrap;cursor:pointer;overflow:hidden}:host(.option-disabled){opacity:0.4}:host(.option-disabled) .picker-column-option-button{cursor:default}`;
29821
30141
 
@@ -31218,6 +31538,13 @@ class Popover {
31218
31538
  const { configureTriggerInteraction, el } = this;
31219
31539
  prepareOverlay(el);
31220
31540
  configureTriggerInteraction();
31541
+ // Re-apply the root lock if moved without dismiss() being called
31542
+ if (this.presented) {
31543
+ restoreRootFocusTrapAccessibility(el);
31544
+ // The disconnect tore down the header observer, and `present()` is its
31545
+ // only other caller, so a move mid-layout would lose the recalculation.
31546
+ this.recalculateContentOnHeaderReady();
31547
+ }
31221
31548
  }
31222
31549
  disconnectedCallback() {
31223
31550
  const { destroyTriggerInteraction } = this;
@@ -31395,6 +31722,12 @@ class Popover {
31395
31722
  if (!header || contentElements.length === 0) {
31396
31723
  return;
31397
31724
  }
31725
+ // Both `present()` and a reconnect call this, so drop any existing
31726
+ // observer. Below the guards, so a call that bails cannot leave none.
31727
+ if (this.headerResizeObserver) {
31728
+ this.headerResizeObserver.disconnect();
31729
+ this.headerResizeObserver = undefined;
31730
+ }
31398
31731
  this.headerResizeObserver = new ResizeObserver(async () => {
31399
31732
  if (header.offsetHeight > 0) {
31400
31733
  this.headerResizeObserver?.disconnect();
@@ -31467,7 +31800,7 @@ class Popover {
31467
31800
  const { onLifecycle, parentPopover, dismissOnSelect, side, arrow, htmlAttributes, focusTrap } = this;
31468
31801
  const desktop = isPlatform('desktop');
31469
31802
  const enableArrow = arrow && !parentPopover;
31470
- return (hAsync(Host, { key: '52ffc7116969ae1b8b927e67f2acbfe5f5434f70', "aria-modal": "true", "no-router": true, tabindex: "-1", ...htmlAttributes, style: {
31803
+ return (hAsync(Host, { key: 'b5e9c788f58397203976d5f8302dfb89e916efe1', "aria-modal": "true", "no-router": true, tabindex: "-1", ...htmlAttributes, style: {
31471
31804
  zIndex: `${20000 + this.overlayIndex}`,
31472
31805
  }, class: {
31473
31806
  ...getClassMap(this.cssClass),
@@ -31478,7 +31811,7 @@ class Popover {
31478
31811
  [`popover-side-${side}`]: true,
31479
31812
  [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false,
31480
31813
  'popover-nested': !!parentPopover,
31481
- }, onIonPopoverDidPresent: onLifecycle, onIonPopoverWillPresent: onLifecycle, onIonPopoverWillDismiss: onLifecycle, onIonPopoverDidDismiss: onLifecycle, onIonBackdropTap: this.onBackdropTap }, !parentPopover && hAsync("ion-backdrop", { key: '79a8e851dbd22119e21ffb2f4709c555251045c8', tappable: this.backdropDismiss, visible: this.showBackdrop, part: "backdrop" }), hAsync("div", { key: 'c46c9f62c3ef3f902e23f27404eaa446a5d8cf88', class: "popover-wrapper ion-overlay-wrapper", onClick: dismissOnSelect ? () => this.dismiss() : undefined }, enableArrow && hAsync("div", { key: '9fdcbbc4ea6c7bde74f646d48eb77296b2c9dd83', class: "popover-arrow", part: "arrow" }), hAsync("div", { key: '138e56bb83462ebb0908edb522b45ecf94b82aeb', class: "popover-content", part: "content" }, hAsync("slot", { key: 'daeefcf002e8d89e91d6e0faf7f63f75b68a2dbe' })))));
31814
+ }, onIonPopoverDidPresent: onLifecycle, onIonPopoverWillPresent: onLifecycle, onIonPopoverWillDismiss: onLifecycle, onIonPopoverDidDismiss: onLifecycle, onIonBackdropTap: this.onBackdropTap }, !parentPopover && hAsync("ion-backdrop", { key: 'f3977833c5b2c0087c286ee54363b478d69eb115', tappable: this.backdropDismiss, visible: this.showBackdrop, part: "backdrop" }), hAsync("div", { key: '1059893d6fd2932ca8adcdf8d45a5d66f4794727', class: "popover-wrapper ion-overlay-wrapper", onClick: dismissOnSelect ? () => this.dismiss() : undefined }, enableArrow && hAsync("div", { key: '24d7988bdd95882ad77fcaa7112aeda55878bee4', class: "popover-arrow", part: "arrow" }), hAsync("div", { key: '4d6992e0a9d629f11763045f9199f9a77fa521ab', class: "popover-content", part: "content" }, hAsync("slot", { key: 'b29747419620a01a6c34e9e846cd529b0b210145' })))));
31482
31815
  }
31483
31816
  get el() { return getElement(this); }
31484
31817
  static get watchers() { return {
@@ -38392,7 +38725,7 @@ class Select {
38392
38725
  const hasOutlineFill = mode === 'md' && fill === 'outline';
38393
38726
  renderHiddenInput(true, el, name, parseValue(value), disabled);
38394
38727
  const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || isExpanded));
38395
- return (hAsync(Host, { key: '5d1e5bf46d0f204efdcb55cc42cfde52e6db304b', onClick: this.onClick, class: createColorClasses$1(this.color, {
38728
+ return (hAsync(Host, { key: 'b2f161e3706e139e61440cd13e162714b1b75d72', onClick: this.onClick, class: createColorClasses$1(this.color, {
38396
38729
  [mode]: true,
38397
38730
  'in-item': inItem,
38398
38731
  'in-item-color': hostContext('ion-item.ion-color', el),
@@ -38410,7 +38743,7 @@ class Select {
38410
38743
  [`select-justify-${justify}`]: justifyEnabled,
38411
38744
  [`select-shape-${shape}`]: shape !== undefined,
38412
38745
  [`select-label-placement-${labelPlacement}`]: true,
38413
- }) }, hAsync("label", { key: '15fd1f8e06510ae8472c621cf8cf90e51172e0be', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick, part: "wrapper" }, hasOutlineFill && this.renderOutlineContainer(), hAsync("div", { key: '7964e3d9351671899793b117896acdda25ec24c4', class: "select-start", part: "start", ref: (el) => (this.startContainerEl = el) }, hAsync("slot", { key: 'aa309ef155c4025acfd7ed5739b5221c85097b36', name: "start" })), hAsync("div", { key: '23d5a9dfea64a9d81b0b36d9426b15bed98901b9', class: "select-control", part: "control" }, this.renderLabel(), hAsync("div", { key: '810da9fbfa8771e09b5fb768d64e5f04858b5833', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox(), !hasFloatingOrStackedLabel && this.renderSelectIcon())), hAsync("div", { key: 'bf1c04704326ecfa14cf2e49bb76d3fb45beb08d', class: "select-end", part: "end" }, hasFloatingOrStackedLabel && this.renderSelectIcon(), hAsync("slot", { key: '76a8bcaeefdcaa908aebd820d93171b08165cee3', name: "end" })), shouldRenderHighlight && hAsync("div", { key: '55a9c417a82323a44e16328fd62a634d9d7c558b', class: "select-highlight" })), this.renderBottomContent()));
38746
+ }) }, hAsync("label", { key: '944a2eb468154a21260d181fdaf67828a71eb902', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick, part: "wrapper" }, hasOutlineFill && this.renderOutlineContainer(), hAsync("div", { key: '927200c53548b1bb4f52d6a167605b724a7b7d0d', class: "select-start", part: "start", ref: (el) => (this.startContainerEl = el) }, hAsync("slot", { key: '6e14b95e9b95c116b16744d630600e90977782bc', name: "start" })), hAsync("div", { key: '8451ed4300ac005963075be36a04ea8763bc0fdd', class: "select-control", part: "control" }, this.renderLabel(), hAsync("div", { key: '207e7b63f3224a4870579365ac992da6784fb31f', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox(), !hasFloatingOrStackedLabel && this.renderSelectIcon())), hAsync("div", { key: '5c17367d488db4d570f31b25e33560efa9011500', class: "select-end", part: "end" }, hasFloatingOrStackedLabel && this.renderSelectIcon(), hAsync("slot", { key: '21fd8c0d9bee8cffef9ef6984cacd31e8f38211c', name: "end" })), shouldRenderHighlight && hAsync("div", { key: '1fff767db9a1ec07b274ef65ff7ae8fb976e6ad2', class: "select-highlight" })), this.renderBottomContent()));
38414
38747
  }
38415
38748
  get el() { return getElement(this); }
38416
38749
  static get watchers() { return {
@@ -38519,29 +38852,14 @@ const textForValue = (opts, value, compareWith, useHTML = false) => {
38519
38852
  return getOptionContent(selectOpt, undefined, true);
38520
38853
  }
38521
38854
  /**
38522
- * When custom HTML is enabled, extract only the default slot content.
38523
- * This ensures aria-label and other text-only contexts read only
38524
- * the relevant option text.
38855
+ * Every text-only context reads only the default slot, so the start
38856
+ * and end slots stay out of the `aria-label` and the overlay labels.
38857
+ * Both config paths derive that text through the same helper, so they
38858
+ * cannot disagree about what an option's text is. `null` marks an
38859
+ * option with no text, which is dropped from the joined text of a
38860
+ * `multiple` select rather than joined in as an empty entry.
38525
38861
  */
38526
- if (customHTMLEnabled) {
38527
- const content = getOptionContent(selectOpt);
38528
- if (typeof content === 'string') {
38529
- return content;
38530
- }
38531
- /**
38532
- * Elements were found in the default slot, extract and concatenate
38533
- * their text content while trimming whitespace.
38534
- */
38535
- if (content) {
38536
- const texts = Array.from(content.childNodes)
38537
- .map((n) => n.textContent?.trim())
38538
- .filter((t) => t);
38539
- return texts.join(' ') || null;
38540
- }
38541
- // Empty option
38542
- return null;
38543
- }
38544
- return getDefaultSlotPlainText(selectOpt);
38862
+ return getDefaultSlotPlainText(selectOpt) || null;
38545
38863
  };
38546
38864
  /**
38547
38865
  * Trims whitespace from all text nodes within a DOM tree.
@@ -38597,9 +38915,13 @@ const getOptionContent = (option, slotName, useHTML = false) => {
38597
38915
  if (nodes.length === 0) {
38598
38916
  return null;
38599
38917
  }
38600
- // Return plain text if no elements are found
38918
+ /**
38919
+ * Return plain text if no elements are found. This reads the option the
38920
+ * same way the non-custom-HTML path does, so the two do not disagree
38921
+ * about what an option's text is.
38922
+ */
38601
38923
  if (!slotName && nodes.every((n) => n.nodeType === Node.TEXT_NODE)) {
38602
- return nodes.map((n) => n.textContent?.trim()).join(' ') || null;
38924
+ return getDefaultSlotPlainText(option) || null;
38603
38925
  }
38604
38926
  /**
38605
38927
  * Mirror known custom-element properties (e.g. ion-icon's `icon`)
@@ -38655,22 +38977,43 @@ const getOptionDefaultSlot = (option) => {
38655
38977
  }
38656
38978
  return defaultSlotNodes;
38657
38979
  };
38980
+ /**
38981
+ * Concatenates the text a node renders, skipping the subtrees of tags
38982
+ * whose contents the browser never paints (`script`, `style`, and the
38983
+ * rest of `blockedTags`). `textContent` includes those, so reading it
38984
+ * directly would put stylesheet or script source into the select text
38985
+ * and the `aria-label`.
38986
+ *
38987
+ * @param node - The node to read text from.
38988
+ * @returns The node's rendered text.
38989
+ */
38990
+ const getRenderedTextContent = (node) => {
38991
+ if (node.nodeType === Node.TEXT_NODE) {
38992
+ return node.textContent ?? '';
38993
+ }
38994
+ if (node.nodeType !== Node.ELEMENT_NODE) {
38995
+ return '';
38996
+ }
38997
+ if (blockedTags.includes(node.tagName.toLowerCase())) {
38998
+ return '';
38999
+ }
39000
+ return Array.from(node.childNodes)
39001
+ .map((child) => getRenderedTextContent(child))
39002
+ .join('');
39003
+ };
38658
39004
  /**
38659
39005
  * Extracts plain text from only the default slot of an option,
38660
- * excluding content assigned to named slots (start/end).
39006
+ * excluding content assigned to named slots (start/end). Text is
39007
+ * concatenated with no separator and collapsible whitespace is
39008
+ * collapsed, approximating how the browser renders the option.
39009
+ * NBSP is not collapsible, so it is preserved.
39010
+ *
39011
+ * @param option - The `ion-select-option` element to read text from.
39012
+ * @returns The option's default slot text.
38661
39013
  */
38662
39014
  const getDefaultSlotPlainText = (option) => {
38663
- const texts = Array.from(option.childNodes)
38664
- .filter((node) => {
38665
- if (node.nodeType === Node.ELEMENT_NODE) {
38666
- return !node.hasAttribute('slot');
38667
- }
38668
- return node.nodeType === Node.TEXT_NODE;
38669
- })
38670
- .filter((node) => node.nodeType === Node.TEXT_NODE)
38671
- .map((n) => n.textContent?.trim())
38672
- .filter((t) => t);
38673
- return texts.join(' ');
39015
+ const text = (getOptionDefaultSlot(option) ?? []).map((node) => getRenderedTextContent(node)).join('');
39016
+ return text.replace(/[ \t\n\r\f]+/g, ' ').replace(/^[ \t\n\r\f]+|[ \t\n\r\f]+$/g, '');
38674
39017
  };
38675
39018
  /**
38676
39019
  * Extracts the rich content from an `ion-select-option`.
@@ -42746,7 +43089,7 @@ var NAMESPACE = (
42746
43089
  );
42747
43090
 
42748
43091
  /*
42749
- Stencil Hydrate Runner v4.43.5 | MIT Licensed | https://stenciljs.com
43092
+ Stencil Hydrate Runner v4.44.1 | MIT Licensed | https://stenciljs.com
42750
43093
  */
42751
43094
  var __create = Object.create;
42752
43095
  var __defProp = Object.defineProperty;