@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.mjs CHANGED
@@ -420,7 +420,7 @@ const appGlobalScript = initialize || (() => {});
420
420
  const globalScripts = appGlobalScript;
421
421
 
422
422
  /*
423
- Stencil Hydrate Platform v4.43.5 | MIT Licensed | https://stenciljs.com
423
+ Stencil Hydrate Platform v4.44.1 | MIT Licensed | https://stenciljs.com
424
424
  */
425
425
  var __create = Object.create;
426
426
  var __defProp = Object.defineProperty;
@@ -755,6 +755,8 @@ var DEFAULT_DOC_DATA = {
755
755
  };
756
756
  var SLOT_FB_CSS = "slot-fb{display:contents}slot-fb[hidden]{display:none}";
757
757
  var XLINK_NS = "http://www.w3.org/1999/xlink";
758
+ var MAX_LAZY_LOAD_RETRIES = 3;
759
+ var LAZY_LOAD_RETRY_INTERVAL_MS = 1e3;
758
760
 
759
761
  // src/utils/style.ts
760
762
  function createStyleSheetIfNeededAndSupported(styles2) {
@@ -818,7 +820,7 @@ function getHostSlotNodes(childNodes, hostName, slotName) {
818
820
  slottedNodes.push(childNode);
819
821
  if (typeof slotName !== "undefined") return slottedNodes;
820
822
  }
821
- slottedNodes = [...slottedNodes, ...getHostSlotNodes(childNode.childNodes, hostName, slotName)];
823
+ slottedNodes = [...slottedNodes, ...getHostSlotNodes(internalCall(childNode, "childNodes"), hostName, slotName)];
822
824
  }
823
825
  return slottedNodes;
824
826
  }
@@ -1062,6 +1064,11 @@ var h = (nodeName, vnodeData, ...children) => {
1062
1064
  } else if (child != null && typeof child !== "boolean") {
1063
1065
  if (simple = typeof nodeName !== "function" && !isComplexType(child)) {
1064
1066
  child = String(child);
1067
+ } else if (typeof nodeName !== "function" && child.$flags$ === void 0) {
1068
+ {
1069
+ consoleError("Invalid vNode child");
1070
+ }
1071
+ continue;
1065
1072
  }
1066
1073
  if (simple && lastSimple) {
1067
1074
  vNodeChildren[vNodeChildren.length - 1].$text$ += child;
@@ -2297,7 +2304,7 @@ var setAccessor = (elm, memberName, oldValue, newValue, isSvg, flags, initialRen
2297
2304
  }
2298
2305
  }
2299
2306
  if (newValue == null || newValue === false) {
2300
- if (newValue !== false || elm.getAttribute(memberName) === "") {
2307
+ if (newValue !== false || elm.getAttribute(memberName) === "" || flags & 4 /* isHost */ && !isEnumeratedAttribute(memberName)) {
2301
2308
  if (xlink) {
2302
2309
  elm.removeAttributeNS(XLINK_NS, memberName);
2303
2310
  } else {
@@ -2314,6 +2321,8 @@ var setAccessor = (elm, memberName, oldValue, newValue, isSvg, flags, initialRen
2314
2321
  }
2315
2322
  }
2316
2323
  };
2324
+ var ENUMERATED_ATTRIBUTES = /* @__PURE__ */ new Set(["draggable", "contenteditable", "spellcheck"]);
2325
+ var isEnumeratedAttribute = (attrName) => ENUMERATED_ATTRIBUTES.has(attrName) || attrName.startsWith("aria-");
2317
2326
  var parseClassListRegex = /\s/;
2318
2327
  var parseClassList = (value) => {
2319
2328
  if (typeof value === "object" && value && "baseVal" in value) {
@@ -2716,7 +2725,10 @@ var markSlotContentForRelocation = (elm) => {
2716
2725
  const slotName = childNode["s-sn"];
2717
2726
  for (j = hostContentNodes.length - 1; j >= 0; j--) {
2718
2727
  node = hostContentNodes[j];
2719
- if (!node["s-cn"] && !node["s-nr"] && node["s-hn"] !== childNode["s-hn"] && (!node["s-sh"] || node["s-sh"] !== childNode["s-hn"])) {
2728
+ 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
2729
+ // `slotName === ''` itself - a matched default node's cached `s-sn` is `''` too, which
2730
+ // would trivially "match" on every re-render and force pointless re-insertion.
2731
+ (!node["s-sh"] || node["s-sh"] !== childNode["s-hn"] || slotName !== "" && getSlotName(node) === slotName)) {
2720
2732
  if (isNodeLocatedInSlot(node, slotName)) {
2721
2733
  let relocateNodeData = relocateNodes.find((r) => r.$nodeToRelocate$ === node);
2722
2734
  checkSlotFallbackVisibility = true;
@@ -2786,7 +2798,7 @@ var insertBefore = (parent, newNode, reference, isInitialLoad) => {
2786
2798
  return newNode;
2787
2799
  }
2788
2800
  }
2789
- if (parent.__insertBefore) {
2801
+ if ((parent == null ? void 0 : parent.__insertBefore)) {
2790
2802
  return parent.__insertBefore(newNode, reference);
2791
2803
  } else {
2792
2804
  return parent == null ? void 0 : parent.insertBefore(newNode, reference);
@@ -3291,10 +3303,12 @@ var proxyComponent = (Cstr, cmpMeta, flags) => {
3291
3303
 
3292
3304
  // src/runtime/initialize-component.ts
3293
3305
  var initializeComponent = async (elm, hostRef, cmpMeta, hmrVersionId) => {
3306
+ var _a2;
3294
3307
  let Cstr;
3295
3308
  try {
3296
3309
  if ((hostRef.$flags$ & 32 /* hasInitializedComponent */) === 0) {
3297
3310
  hostRef.$flags$ |= 32 /* hasInitializedComponent */;
3311
+ hostRef.$flags$ &= -1025 /* hasFailedLoad */;
3298
3312
  const bundleId = cmpMeta.$lazyBundleId$;
3299
3313
  if (bundleId) {
3300
3314
  const CstrImport = loadModule(cmpMeta);
@@ -3306,6 +3320,11 @@ var initializeComponent = async (elm, hostRef, cmpMeta, hmrVersionId) => {
3306
3320
  Cstr = CstrImport;
3307
3321
  }
3308
3322
  if (!Cstr) {
3323
+ hostRef.$flags$ &= -33 /* hasInitializedComponent */;
3324
+ hostRef.$loadRetryCount$ = ((_a2 = hostRef.$loadRetryCount$) != null ? _a2 : 0) + 1;
3325
+ if (hostRef.$loadRetryCount$ < MAX_LAZY_LOAD_RETRIES) {
3326
+ hostRef.$flags$ |= 1024 /* hasFailedLoad */;
3327
+ }
3309
3328
  throw new Error(`Constructor for "${cmpMeta.$tagName$}#${hostRef.$modeName$}" was not found`);
3310
3329
  }
3311
3330
  if (!Cstr.isProxied) {
@@ -3385,7 +3404,7 @@ var initializeComponent = async (elm, hostRef, cmpMeta, hmrVersionId) => {
3385
3404
  hostRef.$onRenderResolve$();
3386
3405
  hostRef.$onRenderResolve$ = void 0;
3387
3406
  }
3388
- if (hostRef.$onReadyResolve$) {
3407
+ if (hostRef.$onReadyResolve$ && !(hostRef.$flags$ & 1024 /* hasFailedLoad */)) {
3389
3408
  hostRef.$onReadyResolve$(elm);
3390
3409
  }
3391
3410
  }
@@ -3444,6 +3463,8 @@ var connectedCallback = (elm) => {
3444
3463
  addHostEventListeners(elm, hostRef, cmpMeta.$listeners$);
3445
3464
  if (hostRef == null ? void 0 : hostRef.$lazyInstance$) {
3446
3465
  fireConnectedCallback(hostRef.$lazyInstance$, elm);
3466
+ } else if (hostRef.$flags$ & 1024 /* hasFailedLoad */) {
3467
+ setTimeout(() => initializeComponent(elm, hostRef, cmpMeta), LAZY_LOAD_RETRY_INTERVAL_MS);
3447
3468
  } else if (hostRef == null ? void 0 : hostRef.$onReadyPromise$) {
3448
3469
  hostRef.$onReadyPromise$.then(() => fireConnectedCallback(hostRef.$lazyInstance$, elm));
3449
3470
  }
@@ -7959,6 +7980,15 @@ const activeAnimations = new WeakMap();
7959
7980
  const isBackdropAlwaysBlocking = (el) => {
7960
7981
  return el.showBackdrop !== false && !((el.backdropBreakpoint ?? 0) > 0);
7961
7982
  };
7983
+ /**
7984
+ * Whether the overlay takes the app root out of the accessibility tree and
7985
+ * blocks body scroll while presented. Toasts never do, modal and popover can
7986
+ * opt out with `focusTrap={false}`, and a backdrop that does not block
7987
+ * (`showBackdrop={false}`, or a `backdropBreakpoint` above 0) is excluded.
7988
+ */
7989
+ const locksAppRoot = (el) => {
7990
+ return el.tagName !== 'ION-TOAST' && el.focusTrap !== false && isBackdropAlwaysBlocking(el);
7991
+ };
7962
7992
  const createController = (tagName) => {
7963
7993
  return {
7964
7994
  create(options) {
@@ -8327,6 +8357,13 @@ const getPresentedOverlay = (doc, overlayTag, id) => {
8327
8357
  // Otherwise, return the last overlay with the given id
8328
8358
  return (id === undefined ? overlays : overlays.filter((o) => o.id === id)).slice(-1)[0];
8329
8359
  };
8360
+ /**
8361
+ * The element an app nests its views under. Overlays hide this rather than the
8362
+ * whole root, so the overlay itself (a sibling) stays reachable.
8363
+ */
8364
+ const getViewContainer = () => {
8365
+ return getAppRoot(document).querySelector('ion-router-outlet, #ion-view-container-root');
8366
+ };
8330
8367
  /**
8331
8368
  * When an overlay is presented, the main
8332
8369
  * focus is the overlay not the page content.
@@ -8350,8 +8387,7 @@ const getPresentedOverlay = (doc, overlayTag, id) => {
8350
8387
  * for main content.
8351
8388
  */
8352
8389
  const setRootAriaHidden = (hidden = false) => {
8353
- const root = getAppRoot(document);
8354
- const viewContainer = root.querySelector('ion-router-outlet, #ion-view-container-root');
8390
+ const viewContainer = getViewContainer();
8355
8391
  if (!viewContainer) {
8356
8392
  return;
8357
8393
  }
@@ -8376,15 +8412,42 @@ const cleanupRootFocusTrapAccessibility = () => {
8376
8412
  return;
8377
8413
  }
8378
8414
  const remainingOverlays = getPresentedOverlays(document);
8379
- const hasRemainingLocking = remainingOverlays.some((o) => {
8380
- const el = o;
8381
- return el.tagName !== 'ION-TOAST' && el.focusTrap !== false && isBackdropAlwaysBlocking(el);
8382
- });
8415
+ const hasRemainingLocking = remainingOverlays.some((o) => locksAppRoot(o));
8383
8416
  if (!hasRemainingLocking) {
8384
8417
  setRootAriaHidden(false);
8385
8418
  document.body.classList.remove(BACKDROP_NO_SCROLL);
8386
8419
  }
8387
8420
  };
8421
+ /**
8422
+ * Applies the root lock itself: `aria-hidden` on the view container, and
8423
+ * `backdrop-no-scroll` on the body. Shared by `present()` and the restore
8424
+ * below, which have to stay in lockstep.
8425
+ */
8426
+ const applyRootLock = (el) => {
8427
+ // Hiding the container the overlay now sits in would hide the overlay too.
8428
+ if (!getViewContainer()?.contains(el)) {
8429
+ setRootAriaHidden(true);
8430
+ }
8431
+ document.body.classList.add(BACKDROP_NO_SCROLL);
8432
+ };
8433
+ /**
8434
+ * Re-applies the root lock that `cleanupRootFocusTrapAccessibility()` released.
8435
+ * Call from `connectedCallback` when the overlay is still presented.
8436
+ *
8437
+ * A synchronous move keeps the overlay connected, so the lock survives. A
8438
+ * detach with a re-insert in a later task releases it, which is the shape a
8439
+ * framework produces when it takes a subtree out and puts it back.
8440
+ */
8441
+ const restoreRootFocusTrapAccessibility = (overlayEl) => {
8442
+ if (typeof document === 'undefined') {
8443
+ return;
8444
+ }
8445
+ const el = overlayEl;
8446
+ if (!locksAppRoot(el)) {
8447
+ return;
8448
+ }
8449
+ applyRootLock(el);
8450
+ };
8388
8451
  const present = async (overlay, name, iosEnterAnimation, mdEnterAnimation, opts) => {
8389
8452
  if (overlay.presented) {
8390
8453
  return;
@@ -8401,15 +8464,7 @@ const present = async (overlay, name, iosEnterAnimation, mdEnterAnimation, opts)
8401
8464
  restoreElementFocus(overlay.el);
8402
8465
  }
8403
8466
  /**
8404
- * Due to accessibility guidelines, toasts do not have
8405
- * focus traps.
8406
- *
8407
- * All other overlays should have focus traps to prevent
8408
- * the keyboard focus from leaving the overlay unless
8409
- * developers explicitly opt out (for example, sheet
8410
- * modals that should permit background interaction).
8411
- *
8412
- * Note: Some apps move inline overlays to a specific container
8467
+ * Some apps move inline overlays to a specific container
8413
8468
  * during the willPresent lifecycle (e.g., React portals via
8414
8469
  * onWillPresent). Defer applying aria-hidden/inert to the app
8415
8470
  * root until after willPresent so we can detect where the
@@ -8418,18 +8473,11 @@ const present = async (overlay, name, iosEnterAnimation, mdEnterAnimation, opts)
8418
8473
  * to avoid disabling the overlay.
8419
8474
  */
8420
8475
  const overlayEl = overlay.el;
8421
- const shouldTrapFocus = overlayEl.tagName !== 'ION-TOAST' && overlayEl.focusTrap !== false;
8422
- const shouldLockRoot = shouldTrapFocus && isBackdropAlwaysBlocking(overlayEl);
8476
+ const shouldLockRoot = locksAppRoot(overlayEl);
8423
8477
  overlay.presented = true;
8424
8478
  overlay.willPresent.emit();
8425
8479
  if (shouldLockRoot) {
8426
- const root = getAppRoot(document);
8427
- const viewContainer = root.querySelector('ion-router-outlet, #ion-view-container-root');
8428
- const overlayInsideViewContainer = viewContainer ? viewContainer.contains(overlayEl) : false;
8429
- if (!overlayInsideViewContainer) {
8430
- setRootAriaHidden(true);
8431
- }
8432
- document.body.classList.add(BACKDROP_NO_SCROLL);
8480
+ applyRootLock(overlayEl);
8433
8481
  }
8434
8482
  overlay.willPresentShorthand?.emit();
8435
8483
  const mode = getIonMode$1(overlay);
@@ -8555,12 +8603,9 @@ const dismiss = async (overlay, data, role, name, iosLeaveAnimation, mdLeaveAnim
8555
8603
  * from the root element when the last focus-trapping overlay
8556
8604
  * is dismissed.
8557
8605
  */
8558
- const overlaysLockingRoot = presentedOverlays.filter((o) => {
8559
- const el = o;
8560
- return el.tagName !== 'ION-TOAST' && el.focusTrap !== false && isBackdropAlwaysBlocking(el);
8561
- });
8606
+ const overlaysLockingRoot = presentedOverlays.filter((o) => locksAppRoot(o));
8562
8607
  const overlayEl = overlay.el;
8563
- const locksRoot = overlayEl.tagName !== 'ION-TOAST' && overlayEl.focusTrap !== false && isBackdropAlwaysBlocking(overlayEl);
8608
+ const locksRoot = locksAppRoot(overlayEl);
8564
8609
  /**
8565
8610
  * If this is the last visible overlay that is trapping focus
8566
8611
  * then we want to re-add the root to the accessibility tree.
@@ -10556,6 +10601,13 @@ class ActionSheet {
10556
10601
  connectedCallback() {
10557
10602
  prepareOverlay(this.el);
10558
10603
  this.triggerChanged();
10604
+ // `componentDidLoad` only fires once per instance, so a reconnect has to
10605
+ // rebuild the gesture its disconnect destroyed.
10606
+ this.setupButtonActiveGesture();
10607
+ // Re-apply the root lock if moved without dismiss() being called
10608
+ if (this.presented) {
10609
+ restoreRootFocusTrapAccessibility(this.el);
10610
+ }
10559
10611
  }
10560
10612
  disconnectedCallback() {
10561
10613
  if (this.gesture) {
@@ -10575,24 +10627,33 @@ class ActionSheet {
10575
10627
  // Initialize activeRadioId for radio buttons
10576
10628
  this.buttonsChanged();
10577
10629
  }
10578
- componentDidLoad() {
10579
- /**
10580
- * Only create gesture if:
10581
- * 1. A gesture does not already exist
10582
- * 2. App is running in iOS mode
10583
- * 3. A wrapper ref exists
10584
- * 4. A group ref exists
10585
- */
10630
+ /**
10631
+ * Only create gesture if:
10632
+ * 1. A gesture does not already exist
10633
+ * 2. App is running in iOS mode
10634
+ * 3. A wrapper ref exists
10635
+ * 4. A group ref exists
10636
+ * 5. The host is still connected, since a reconnect can schedule this and
10637
+ * disconnect again before the task runs
10638
+ */
10639
+ setupButtonActiveGesture() {
10586
10640
  const { groupEl, wrapperEl } = this;
10587
- if (!this.gesture && getIonMode$1(this) === 'ios' && wrapperEl && groupEl) {
10588
- readTask(() => {
10589
- const isScrollable = groupEl.scrollHeight > groupEl.clientHeight;
10590
- if (!isScrollable) {
10591
- this.gesture = createButtonActiveGesture(wrapperEl, (refEl) => refEl.classList.contains('action-sheet-button'));
10592
- this.gesture.enable(true);
10593
- }
10594
- });
10641
+ if (getIonMode$1(this) !== 'ios' || !wrapperEl || !groupEl) {
10642
+ return;
10595
10643
  }
10644
+ readTask(() => {
10645
+ // Bail if a call queued ahead of this one already built the gesture
10646
+ // (a second would orphan the first with its listeners still bound), if
10647
+ // the host disconnected while this task waited, or if the group scrolls.
10648
+ if (this.gesture || !this.el.isConnected || groupEl.scrollHeight > groupEl.clientHeight) {
10649
+ return;
10650
+ }
10651
+ this.gesture = createButtonActiveGesture(wrapperEl, (refEl) => refEl.classList.contains('action-sheet-button'));
10652
+ this.gesture.enable(true);
10653
+ });
10654
+ }
10655
+ componentDidLoad() {
10656
+ this.setupButtonActiveGesture();
10596
10657
  /**
10597
10658
  * If action sheet was rendered with isOpen="true"
10598
10659
  * then we should open action sheet immediately.
@@ -10685,17 +10746,17 @@ class ActionSheet {
10685
10746
  const cancelButton = allButtons.find((b) => b.role === 'cancel');
10686
10747
  const buttons = allButtons.filter((b) => b.role !== 'cancel');
10687
10748
  const headerID = `action-sheet-${overlayIndex}-header`;
10688
- return (hAsync(Host, { key: '7685831da9a78b73473246a2cea95cefa79a53c3', role: "dialog", "aria-modal": "true", "aria-labelledby": header !== undefined ? headerID : null, tabindex: "-1", ...htmlAttributes, style: {
10749
+ return (hAsync(Host, { key: '83b47ea6b81d4eec6582c1dcaae6f267c78ba634', role: "dialog", "aria-modal": "true", "aria-labelledby": header !== undefined ? headerID : null, tabindex: "-1", ...htmlAttributes, style: {
10689
10750
  zIndex: `${20000 + this.overlayIndex}`,
10690
10751
  }, class: {
10691
10752
  [mode]: true,
10692
10753
  ...getClassMap(this.cssClass),
10693
10754
  'overlay-hidden': true,
10694
10755
  'action-sheet-translucent': this.translucent,
10695
- }, 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: {
10756
+ }, 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: {
10696
10757
  'action-sheet-title': true,
10697
10758
  'action-sheet-has-sub-title': this.subHeader !== undefined,
10698
- } }, 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" })));
10759
+ } }, 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" })));
10699
10760
  }
10700
10761
  get el() { return getElement(this); }
10701
10762
  static get watchers() { return {
@@ -11077,10 +11138,15 @@ class Alert {
11077
11138
  this.triggerChanged();
11078
11139
  /**
11079
11140
  * If the alert was previously connected and is being reattached, the
11080
- * ResizeObserver was disconnected. componentDidLoad only fires once per
11081
- * instance, so re-establish the observer here on reconnect.
11141
+ * `ResizeObserver` and the button gesture were torn down. `componentDidLoad`
11142
+ * only fires once per instance, so re-establish both here on reconnect.
11082
11143
  */
11083
11144
  this.setupButtonGroupResizeObserver();
11145
+ this.setupButtonActiveGesture();
11146
+ // Re-apply the root lock if moved without dismiss() being called
11147
+ if (this.presented) {
11148
+ restoreRootFocusTrapAccessibility(this.el);
11149
+ }
11084
11150
  }
11085
11151
  componentWillLoad() {
11086
11152
  if (!this.htmlAttributes?.id) {
@@ -11102,17 +11168,20 @@ class Alert {
11102
11168
  this.buttonGroupResizeObserver?.disconnect();
11103
11169
  this.buttonGroupResizeObserver = undefined;
11104
11170
  }
11105
- componentDidLoad() {
11106
- /**
11107
- * Only create gesture if:
11108
- * 1. A gesture does not already exist
11109
- * 2. App is running in iOS mode
11110
- * 3. A wrapper ref exists
11111
- */
11171
+ /**
11172
+ * Only create gesture if:
11173
+ * 1. A gesture does not already exist
11174
+ * 2. App is running in iOS mode
11175
+ * 3. A wrapper ref exists
11176
+ */
11177
+ setupButtonActiveGesture() {
11112
11178
  if (!this.gesture && getIonMode$1(this) === 'ios' && this.wrapperEl) {
11113
11179
  this.gesture = createButtonActiveGesture(this.wrapperEl, (refEl) => refEl.classList.contains('alert-button'));
11114
11180
  this.gesture.enable(true);
11115
11181
  }
11182
+ }
11183
+ componentDidLoad() {
11184
+ this.setupButtonActiveGesture();
11116
11185
  this.setupButtonGroupResizeObserver();
11117
11186
  /**
11118
11187
  * If alert was rendered with isOpen="true"
@@ -11433,14 +11502,14 @@ class Alert {
11433
11502
  * If neither are defined, do not set aria-labelledby.
11434
11503
  */
11435
11504
  const ariaLabelledBy = header && subHeader ? `${hdrId} ${subHdrId}` : header ? hdrId : subHeader ? subHdrId : null;
11436
- return (hAsync(Host, { key: '022f3463b8e6c52064b90ec304c524847c3d5ad3', tabindex: "-1", style: {
11505
+ return (hAsync(Host, { key: '083b5250dc4c76e85240e0225abcb7ca2b66de2f', tabindex: "-1", style: {
11437
11506
  zIndex: `${20000 + overlayIndex}`,
11438
11507
  }, class: {
11439
11508
  ...getClassMap(this.cssClass),
11440
11509
  [mode]: true,
11441
11510
  'overlay-hidden': true,
11442
11511
  'alert-translucent': this.translucent,
11443
- }, 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" })));
11512
+ }, 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" })));
11444
11513
  }
11445
11514
  get el() { return getElement(this); }
11446
11515
  static get watchers() { return {
@@ -13619,6 +13688,23 @@ class Content {
13619
13688
  const mode = getIonMode$1(this);
13620
13689
  return forceOverscroll === undefined ? mode === 'ios' && isPlatform('ios') : forceOverscroll;
13621
13690
  }
13691
+ /**
13692
+ * Whether this component should size itself to its contents height, which
13693
+ * is the case inside any popover and inside a modal whose `--height` is a
13694
+ * content-based value. Those overlays give the content no definite height
13695
+ * to fill.
13696
+ */
13697
+ shouldSizeToContent() {
13698
+ if (hostContext('ion-popover', this.el)) {
13699
+ return true;
13700
+ }
13701
+ const modal = this.el.closest('ion-modal');
13702
+ if (modal === null) {
13703
+ return false;
13704
+ }
13705
+ const height = getComputedStyle(modal).getPropertyValue('--height').trim();
13706
+ return CONTENT_SIZED_HEIGHTS.includes(height);
13707
+ }
13622
13708
  resize() {
13623
13709
  }
13624
13710
  /**
@@ -13798,21 +13884,21 @@ class Content {
13798
13884
  const forceOverscroll = this.shouldForceOverscroll();
13799
13885
  const transitionShadow = mode === 'ios';
13800
13886
  this.resize();
13801
- return (hAsync(Host, { key: '9551c759df407b10d809171641fc6e8f14d92219', role: isMainContent ? 'main' : undefined, class: createColorClasses$1(this.color, {
13887
+ return (hAsync(Host, { key: 'd6ea57ec1f5def0bfd22f52ec5a5bbe6aa2f8e8e', role: isMainContent ? 'main' : undefined, class: createColorClasses$1(this.color, {
13802
13888
  [mode]: true,
13803
13889
  'content-fullscreen': this.fullscreen,
13804
- 'content-sizing': hostContext('ion-popover', this.el),
13890
+ 'content-sizing': this.shouldSizeToContent(),
13805
13891
  overscroll: forceOverscroll,
13806
13892
  [`content-${rtl}`]: true,
13807
13893
  }), style: {
13808
13894
  '--offset-top': `${this.cTop}px`,
13809
13895
  '--offset-bottom': `${this.cBottom}px`,
13810
- }, ...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: {
13896
+ }, ...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: {
13811
13897
  'inner-scroll': true,
13812
13898
  'scroll-x': scrollX,
13813
13899
  'scroll-y': scrollY,
13814
13900
  overscroll: (scrollX || scrollY) && forceOverscroll,
13815
- }, 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));
13901
+ }, 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));
13816
13902
  }
13817
13903
  get el() { return getElement(this); }
13818
13904
  static get watchers() { return {
@@ -13845,6 +13931,11 @@ class Content {
13845
13931
  "$attrsToReflect$": [["color", "color"]]
13846
13932
  }; }
13847
13933
  }
13934
+ /**
13935
+ * `ion-modal` `--height` values that size the modal to its contents, leaving
13936
+ * children an indefinite height to resolve against.
13937
+ */
13938
+ const CONTENT_SIZED_HEIGHTS = ['auto', 'fit-content', 'min-content', 'max-content'];
13848
13939
  const getParentElement = (el) => {
13849
13940
  if (el.parentElement) {
13850
13941
  // normal element with a parent element
@@ -17026,7 +17117,6 @@ class Datetime {
17026
17117
  }
17027
17118
  renderCombinedDatePickerColumn() {
17028
17119
  const { defaultParts, disabled, workingParts, locale, minParts, maxParts, todayParts, isDateEnabled } = this;
17029
- const activePart = this.getActivePartsWithFallback();
17030
17120
  /**
17031
17121
  * By default, generate a range of 3 months:
17032
17122
  * Previous month, current month, and next month
@@ -17082,8 +17172,10 @@ class Datetime {
17082
17172
  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) => {
17083
17173
  const { value } = ev.detail;
17084
17174
  const findPart = parts.find(({ month, day, year }) => value === `${year}-${month}-${day}`);
17175
+ // Read live so parts a sibling column just committed are included.
17176
+ const activePart = this.getActivePartsWithFallback();
17085
17177
  this.setWorkingParts({
17086
- ...workingParts,
17178
+ ...this.workingParts,
17087
17179
  ...findPart,
17088
17180
  });
17089
17181
  this.setActiveParts({
@@ -17160,11 +17252,12 @@ class Datetime {
17160
17252
  return [];
17161
17253
  }
17162
17254
  const { disabled, workingParts } = this;
17163
- const activePart = this.getActivePartsWithFallback();
17164
17255
  const pickerColumnValue = (workingParts.day !== null ? workingParts.day : this.defaultParts.day) ?? undefined;
17165
17256
  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) => {
17257
+ // Read live so parts a sibling column just committed are included.
17258
+ const activePart = this.getActivePartsWithFallback();
17166
17259
  this.setWorkingParts({
17167
- ...workingParts,
17260
+ ...this.workingParts,
17168
17261
  day: ev.detail.value,
17169
17262
  });
17170
17263
  this.setActiveParts({
@@ -17179,10 +17272,11 @@ class Datetime {
17179
17272
  return [];
17180
17273
  }
17181
17274
  const { disabled, workingParts } = this;
17182
- const activePart = this.getActivePartsWithFallback();
17183
17275
  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) => {
17276
+ // Read live so parts a sibling column just committed are included.
17277
+ const activePart = this.getActivePartsWithFallback();
17184
17278
  this.setWorkingParts({
17185
- ...workingParts,
17279
+ ...this.workingParts,
17186
17280
  month: ev.detail.value,
17187
17281
  });
17188
17282
  // Month wheel is navigation-only in multi-select mode as a fix for https://github.com/ionic-team/ionic-framework/issues/29673
@@ -17200,10 +17294,11 @@ class Datetime {
17200
17294
  return [];
17201
17295
  }
17202
17296
  const { disabled, workingParts } = this;
17203
- const activePart = this.getActivePartsWithFallback();
17204
17297
  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) => {
17298
+ // Read live so parts a sibling column just committed are included.
17299
+ const activePart = this.getActivePartsWithFallback();
17205
17300
  this.setWorkingParts({
17206
- ...workingParts,
17301
+ ...this.workingParts,
17207
17302
  year: ev.detail.value,
17208
17303
  });
17209
17304
  // Year wheel is navigation-only in multi-select mode as a fix for https://github.com/ionic-team/ionic-framework/issues/29673
@@ -17239,13 +17334,14 @@ class Datetime {
17239
17334
  ];
17240
17335
  }
17241
17336
  renderHourPickerColumn(hoursData) {
17242
- const { disabled, workingParts } = this;
17337
+ const { disabled } = this;
17243
17338
  if (hoursData.length === 0)
17244
17339
  return [];
17245
17340
  const activePart = this.getActivePartsWithFallback();
17246
17341
  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) => {
17342
+ // Read live so parts a sibling column just committed are included.
17247
17343
  this.setWorkingParts({
17248
- ...workingParts,
17344
+ ...this.workingParts,
17249
17345
  hour: ev.detail.value,
17250
17346
  });
17251
17347
  this.setActiveParts({
@@ -17256,13 +17352,14 @@ class Datetime {
17256
17352
  } }, 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)))));
17257
17353
  }
17258
17354
  renderMinutePickerColumn(minutesData) {
17259
- const { disabled, workingParts } = this;
17355
+ const { disabled } = this;
17260
17356
  if (minutesData.length === 0)
17261
17357
  return [];
17262
17358
  const activePart = this.getActivePartsWithFallback();
17263
17359
  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) => {
17360
+ // Read live so parts a sibling column just committed are included.
17264
17361
  this.setWorkingParts({
17265
- ...workingParts,
17362
+ ...this.workingParts,
17266
17363
  minute: ev.detail.value,
17267
17364
  });
17268
17365
  this.setActiveParts({
@@ -17273,16 +17370,18 @@ class Datetime {
17273
17370
  } }, 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)))));
17274
17371
  }
17275
17372
  renderDayPeriodPickerColumn(dayPeriodData) {
17276
- const { disabled, workingParts } = this;
17373
+ const { disabled } = this;
17277
17374
  if (dayPeriodData.length === 0) {
17278
17375
  return [];
17279
17376
  }
17280
17377
  const activePart = this.getActivePartsWithFallback();
17281
17378
  const isDayPeriodRTL = isLocaleDayPeriodRTL(this.locale);
17282
17379
  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) => {
17283
- const hour = calculateHourFromAMPM(workingParts, ev.detail.value);
17380
+ // Read live so parts a sibling column just committed are included.
17381
+ const currentParts = this.workingParts;
17382
+ const hour = calculateHourFromAMPM(currentParts, ev.detail.value);
17284
17383
  this.setWorkingParts({
17285
- ...workingParts,
17384
+ ...currentParts,
17286
17385
  ampm: ev.detail.value,
17287
17386
  hour,
17288
17387
  });
@@ -17634,7 +17733,7 @@ class Datetime {
17634
17733
  const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
17635
17734
  const hasWheelVariant = hasDatePresentation && preferWheel;
17636
17735
  renderHiddenInput(true, el, name, formatValue(value), disabled);
17637
- return (hAsync(Host, { key: 'd8e6dfe5e3bffb1c38a3e37b63b3aec099f40d29', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: {
17736
+ return (hAsync(Host, { key: '4e0b529a70924b065bcc6191e08550428b5a52a0', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: {
17638
17737
  ...createColorClasses$1(color, {
17639
17738
  [mode]: true,
17640
17739
  ['datetime-readonly']: readonly,
@@ -17646,7 +17745,7 @@ class Datetime {
17646
17745
  [`datetime-prefer-wheel`]: hasWheelVariant,
17647
17746
  [`datetime-grid`]: isGridStyle,
17648
17747
  }),
17649
- } }, hAsync("div", { key: '20889d3c68dd5109633c0e214411a63d6f3025bb', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
17748
+ } }, hAsync("div", { key: 'cc9d1b92f960984cb0466d0003a240ace67da243', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
17650
17749
  }
17651
17750
  get el() { return getElement(this); }
17652
17751
  static get watchers() { return {
@@ -22950,6 +23049,10 @@ class Loading {
22950
23049
  connectedCallback() {
22951
23050
  prepareOverlay(this.el);
22952
23051
  this.triggerChanged();
23052
+ // Re-apply the root lock if moved without dismiss() being called
23053
+ if (this.presented) {
23054
+ restoreRootFocusTrapAccessibility(this.el);
23055
+ }
22953
23056
  }
22954
23057
  componentWillLoad() {
22955
23058
  if (this.spinner === undefined) {
@@ -23050,14 +23153,14 @@ class Loading {
23050
23153
  * Otherwise, don't set aria-labelledby.
23051
23154
  */
23052
23155
  const ariaLabelledBy = message !== undefined ? msgId : null;
23053
- return (hAsync(Host, { key: '2d14122ff3081de73631a7fdd4affdd5c73b8618', role: "dialog", "aria-modal": "true", "aria-labelledby": ariaLabelledBy, tabindex: "-1", ...htmlAttributes, style: {
23156
+ return (hAsync(Host, { key: 'b4430bc66aedeca19d5645667cba73c169c4bd76', role: "dialog", "aria-modal": "true", "aria-labelledby": ariaLabelledBy, tabindex: "-1", ...htmlAttributes, style: {
23054
23157
  zIndex: `${40000 + this.overlayIndex}`,
23055
23158
  }, onIonBackdropTap: this.onBackdropTap, class: {
23056
23159
  ...getClassMap(this.cssClass),
23057
23160
  [mode]: true,
23058
23161
  'overlay-hidden': true,
23059
23162
  'loading-translucent': this.translucent,
23060
- } }, 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" })));
23163
+ } }, 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" })));
23061
23164
  }
23062
23165
  get el() { return getElement(this); }
23063
23166
  static get watchers() { return {
@@ -26578,9 +26681,9 @@ const clearSafeAreaOverrides = (hostEl) => {
26578
26681
  hostEl.style.removeProperty('--ion-safe-area-right');
26579
26682
  };
26580
26683
 
26581
- 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}`;
26684
+ 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}`;
26582
26685
 
26583
- 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}`;
26686
+ 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}`;
26584
26687
 
26585
26688
  // TODO(FW-2832): types
26586
26689
  /**
@@ -26616,6 +26719,9 @@ class Modal {
26616
26719
  this.inline = false;
26617
26720
  // Whether or not modal is being dismissed via gesture
26618
26721
  this.gestureAnimationDismissing = false;
26722
+ // True from the first safe-area write in `present()` until the enter
26723
+ // animation settles. A position-based read in that window is not the rest position.
26724
+ this.isPresenting = false;
26619
26725
  this.presented = false;
26620
26726
  /** @internal */
26621
26727
  this.hasController = false;
@@ -26852,6 +26958,17 @@ class Modal {
26852
26958
  const { el } = this;
26853
26959
  prepareOverlay(el);
26854
26960
  this.triggerChanged();
26961
+ // A disconnect tears down state this presentation still needs and cannot
26962
+ // tell a re-insert from a removal, so put it back.
26963
+ if (this.presented || this.isPresenting) {
26964
+ this.restoreSafeAreaOverrides();
26965
+ }
26966
+ // A relocation from `willPresent` reaches these before `present()` has
26967
+ // applied the lock, so they apply it instead. Both are idempotent.
26968
+ if (this.presented) {
26969
+ restoreRootFocusTrapAccessibility(el);
26970
+ this.initParentRemovalObserver();
26971
+ }
26855
26972
  }
26856
26973
  disconnectedCallback() {
26857
26974
  this.triggerController.removeClickListener();
@@ -27029,25 +27146,33 @@ class Modal {
27029
27146
  // Recalculate isSheetModal before safe-area setup because framework
27030
27147
  // bindings (e.g., Angular) may not have been applied when componentWillLoad ran.
27031
27148
  this.isSheetModal = this.breakpoints !== undefined && this.initialBreakpoint !== undefined;
27032
- // Set initial safe-area overrides before animation
27033
- this.setInitialSafeAreaOverrides();
27149
+ this.isPresenting = true;
27034
27150
  const hasCardModal = presentingElement !== undefined;
27035
- /**
27036
- * We need to change the status bar at the
27037
- * start of the animation so that it completes
27038
- * by the time the card animation is done.
27039
- */
27040
- if (hasCardModal && getIonMode$1(this) === 'ios') {
27041
- // Cache the original status bar color before the modal is presented
27042
- this.statusBarStyle = await StatusBar.getStyle();
27043
- setCardStatusBarDark();
27151
+ // Wrapped so a throw cannot strand `isPresenting`, which would suppress
27152
+ // the position-based correction for the life of this instance.
27153
+ try {
27154
+ // Set initial safe-area overrides before animation
27155
+ this.setInitialSafeAreaOverrides();
27156
+ /**
27157
+ * We need to change the status bar at the
27158
+ * start of the animation so that it completes
27159
+ * by the time the card animation is done.
27160
+ */
27161
+ if (hasCardModal && getIonMode$1(this) === 'ios') {
27162
+ // Cache the original status bar color before the modal is presented
27163
+ this.statusBarStyle = await StatusBar.getStyle();
27164
+ setCardStatusBarDark();
27165
+ }
27166
+ await present(this, 'modalEnter', iosEnterAnimation$2, mdEnterAnimation$2, {
27167
+ presentingEl: presentingElement,
27168
+ currentBreakpoint: this.initialBreakpoint,
27169
+ backdropBreakpoint: this.backdropBreakpoint,
27170
+ expandToScroll: this.expandToScroll,
27171
+ });
27172
+ }
27173
+ finally {
27174
+ this.isPresenting = false;
27044
27175
  }
27045
- await present(this, 'modalEnter', iosEnterAnimation$2, mdEnterAnimation$2, {
27046
- presentingEl: presentingElement,
27047
- currentBreakpoint: this.initialBreakpoint,
27048
- backdropBreakpoint: this.backdropBreakpoint,
27049
- expandToScroll: this.expandToScroll,
27050
- });
27051
27176
  // Update safe-area based on actual position after animation
27052
27177
  this.updateSafeAreaOverrides();
27053
27178
  // Apply fullscreen safe-area padding if needed
@@ -27549,6 +27674,9 @@ class Modal {
27549
27674
  this.cachedOriginalParent.tagName === 'ION-APP') {
27550
27675
  return;
27551
27676
  }
27677
+ // Both `present()` and a reconnect call this, so drop any existing
27678
+ // observer. Below the guards, so a call that bails cannot leave none.
27679
+ this.cleanupParentRemovalObserver();
27552
27680
  this.parentRemovalObserver = new MutationObserver((mutations) => {
27553
27681
  mutations.forEach((mutation) => {
27554
27682
  if (mutation.type === 'childList' && mutation.removedNodes.length > 0) {
@@ -27627,6 +27755,9 @@ class Modal {
27627
27755
  // Set the internal offset property with the resolved root safe-area-top value
27628
27756
  if (context.isSheetModal) {
27629
27757
  this.updateSheetOffsetTop();
27758
+ // A restore after a DOM move runs this a second time for the same
27759
+ // modal, so drop the previous subscription rather than stacking one.
27760
+ this.unsubscribeRootSafeAreaTop?.();
27630
27761
  this.unsubscribeRootSafeAreaTop = onRootSafeAreaTopChange((safeAreaTop) => this.updateSheetOffsetTop(safeAreaTop));
27631
27762
  }
27632
27763
  }
@@ -27745,6 +27876,31 @@ class Modal {
27745
27876
  const { contentEl } = this.findContentAndFooter();
27746
27877
  this.clearContentSafeAreaPadding(contentEl);
27747
27878
  }
27879
+ /**
27880
+ * Re-applies what `cleanupSafeAreaOverrides()` removed for a modal moved
27881
+ * while presented. Anything needing no measurement goes on synchronously so
27882
+ * the modal is never painted without safe-area. The position-based
27883
+ * correction waits a frame for the layout pass it reads.
27884
+ */
27885
+ restoreSafeAreaOverrides() {
27886
+ this.setInitialSafeAreaOverrides();
27887
+ this.applyFullscreenSafeArea();
27888
+ raf(() => {
27889
+ // A dismiss or another move can land first, and a read before the enter
27890
+ // animation settles is not the rest position. `present()` redoes it.
27891
+ if (!this.presented || !this.el.isConnected || this.isPresenting) {
27892
+ return;
27893
+ }
27894
+ // A hidden subtree carries `display: none`, so there is no box and the
27895
+ // read would write the safe-area for a modal touching no edge. The
27896
+ // prediction applied above holds until the modal is shown again.
27897
+ const { width, height } = this.el.getBoundingClientRect();
27898
+ if (width === 0 && height === 0) {
27899
+ return;
27900
+ }
27901
+ this.updateSafeAreaOverrides();
27902
+ });
27903
+ }
27748
27904
  render() {
27749
27905
  const { handle, isSheetModal, presentingElement, htmlAttributes, handleBehavior, inheritedAttributes, focusTrap, expandToScroll, } = this;
27750
27906
  const showHandle = handle !== false && isSheetModal;
@@ -27752,7 +27908,7 @@ class Modal {
27752
27908
  const isCardModal = presentingElement !== undefined && mode === 'ios';
27753
27909
  const isHandleCycle = handleBehavior === 'cycle';
27754
27910
  const isSheetModalWithHandle = isSheetModal && showHandle;
27755
- return (hAsync(Host, { key: 'a471c293319cb6ee5ffb7ffafec0b8413e4289de', "no-router": true,
27911
+ return (hAsync(Host, { key: '7c9c736052c5a788cf31040b6b2386dd9ea7454b', "no-router": true,
27756
27912
  // Allow the modal to be navigable when the handle is focusable
27757
27913
  tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1, ...htmlAttributes, style: {
27758
27914
  zIndex: `${20000 + this.overlayIndex}`,
@@ -27765,7 +27921,7 @@ class Modal {
27765
27921
  'overlay-hidden': true,
27766
27922
  [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false,
27767
27923
  ...getClassMap(this.cssClass),
27768
- }, 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',
27924
+ }, 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',
27769
27925
  /*
27770
27926
  role and aria-modal must be used on the
27771
27927
  same element. They must also be set inside the
@@ -27778,9 +27934,9 @@ class Modal {
27778
27934
  without the tabindex focus() would be a no-op and screen readers
27779
27935
  may not properly announce the dialog and its content when it opens.
27780
27936
  */
27781
- 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",
27937
+ 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",
27782
27938
  // Prevents the handle from receiving keyboard focus when it does not cycle
27783
- 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 }))));
27939
+ 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 }))));
27784
27940
  }
27785
27941
  get el() { return getElement(this); }
27786
27942
  static get watchers() { return {
@@ -29255,6 +29411,12 @@ class PickerColumn {
29255
29411
  this.isColumnVisible = false;
29256
29412
  this.canExitInputMode = true;
29257
29413
  this.updateValueTextOnScroll = false;
29414
+ this.isUserScroll = false;
29415
+ /**
29416
+ * The haptics for the wheel picker are an iOS-only feature. As a result,
29417
+ * they should be disabled on Android.
29418
+ */
29419
+ this.enableHaptics = false;
29258
29420
  this.ariaLabel = null;
29259
29421
  this.isActive = false;
29260
29422
  /**
@@ -29286,6 +29448,12 @@ class PickerColumn {
29286
29448
  */
29287
29449
  this.canExitInputMode = canExitInputMode;
29288
29450
  this.updateValueTextOnScroll = false;
29451
+ /**
29452
+ * This scroll takes over from whatever the user was doing, so an outside
29453
+ * press must not commit an option the column is only passing through.
29454
+ */
29455
+ this.isUserScroll = false;
29456
+ this.stopWatchingForOutsidePress();
29289
29457
  scrollEl.scroll({
29290
29458
  top,
29291
29459
  left: 0,
@@ -29340,6 +29508,117 @@ class PickerColumn {
29340
29508
  }
29341
29509
  this.isActive = state;
29342
29510
  };
29511
+ this.clearScrollEndTimeout = () => {
29512
+ if (this.scrollEndTimeout) {
29513
+ clearTimeout(this.scrollEndTimeout);
29514
+ this.scrollEndTimeout = undefined;
29515
+ }
29516
+ };
29517
+ /**
29518
+ * Resets the idle timer that commits the centered option.
29519
+ */
29520
+ this.resetScrollEndTimeout = () => {
29521
+ this.clearScrollEndTimeout();
29522
+ this.scrollEndTimeout = setTimeout(this.settle, SCROLL_END_DELAY);
29523
+ };
29524
+ /**
29525
+ * Capture so the column still commits if an application's own pointerdown
29526
+ * handler stops the event before it reaches the document.
29527
+ */
29528
+ this.watchForOutsidePress = () => {
29529
+ doc?.addEventListener('pointerdown', this.onPointerDownOutside, { capture: true });
29530
+ };
29531
+ this.stopWatchingForOutsidePress = () => {
29532
+ doc?.removeEventListener('pointerdown', this.onPointerDownOutside, { capture: true });
29533
+ };
29534
+ /**
29535
+ * Resets everything the current scroll interaction is holding, so nothing
29536
+ * pending on it can commit later.
29537
+ */
29538
+ this.discardScroll = () => {
29539
+ this.stopWatchingForOutsidePress();
29540
+ this.clearScrollEndTimeout();
29541
+ this.scrollEndCallback = undefined;
29542
+ this.centeredOption = undefined;
29543
+ this.haltedAtScrollTop = undefined;
29544
+ this.isScrolling = false;
29545
+ this.isUserScroll = false;
29546
+ this.canExitInputMode = true;
29547
+ };
29548
+ /**
29549
+ * Commits the option that is currently centered under the highlight and ends
29550
+ * the scroll interaction.
29551
+ */
29552
+ this.settle = () => {
29553
+ const { centeredOption } = this;
29554
+ this.clearScrollEndTimeout();
29555
+ this.stopWatchingForOutsidePress();
29556
+ this.isUserScroll = false;
29557
+ this.isScrolling = false;
29558
+ this.updateValueTextOnScroll = true;
29559
+ this.enableHaptics && hapticSelectionEnd();
29560
+ /**
29561
+ * Certain tasks (such as those that
29562
+ * cause re-renders) should only be done
29563
+ * once scrolling has finished, otherwise
29564
+ * flickering may occur.
29565
+ */
29566
+ const { scrollEndCallback } = this;
29567
+ if (scrollEndCallback) {
29568
+ scrollEndCallback();
29569
+ this.scrollEndCallback = undefined;
29570
+ }
29571
+ /**
29572
+ * Reset this flag as the
29573
+ * next scroll interaction could
29574
+ * be a scroll from the user. In this
29575
+ * case, we should exit input mode.
29576
+ */
29577
+ this.canExitInputMode = true;
29578
+ if (centeredOption !== undefined) {
29579
+ // Cleared here so a later scroll that centers nothing cannot fall back on it.
29580
+ this.centeredOption = undefined;
29581
+ if (centeredOption.isConnected) {
29582
+ this.setValue(centeredOption.value);
29583
+ }
29584
+ }
29585
+ };
29586
+ /**
29587
+ * Commits the option the user can see when they press anything outside of the
29588
+ * column during a scroll they started. This runs on pointerdown rather than
29589
+ * click so the value is up to date by the time an application's own click
29590
+ * handler (a Save button, for example) reads it.
29591
+ */
29592
+ this.onPointerDownOutside = (ev) => {
29593
+ const { centeredOption, parentEl, scrollEl } = this;
29594
+ if (!this.isScrolling) {
29595
+ return;
29596
+ }
29597
+ /**
29598
+ * The column can live in another component's Shadow DOM, where a document
29599
+ * listener sees the target retargeted to the outer host. The composed path
29600
+ * is the only reliable way to tell a press on the column apart.
29601
+ */
29602
+ const path = ev.composedPath();
29603
+ /**
29604
+ * A press anywhere in the parent picker counts as inside, so reaching for a
29605
+ * sibling wheel leaves this column coasting.
29606
+ */
29607
+ if (path.includes(this.el) || (parentEl != null && path.includes(parentEl))) {
29608
+ return;
29609
+ }
29610
+ /**
29611
+ * Landing on the centered option halts the in-flight momentum scroll, so the
29612
+ * committed value and the option the user is left looking at agree. The
29613
+ * option list can be replaced mid-scroll, and a detached option has no
29614
+ * offset to center on.
29615
+ */
29616
+ if (centeredOption !== undefined && centeredOption.isConnected) {
29617
+ this.centerPickerItemInView(centeredOption, false, false);
29618
+ this.haltedAtScrollTop = scrollEl?.scrollTop;
29619
+ }
29620
+ this.settle();
29621
+ };
29343
29622
  /**
29344
29623
  * When the column scrolls, the component
29345
29624
  * needs to determine which item is centered
@@ -29347,27 +29626,42 @@ class PickerColumn {
29347
29626
  * the item object.
29348
29627
  */
29349
29628
  this.initializeScrollListener = () => {
29350
- /**
29351
- * The haptics for the wheel picker are
29352
- * an iOS-only feature. As a result, they should
29353
- * be disabled on Android.
29354
- */
29355
- const enableHaptics = isPlatform('ios');
29629
+ this.enableHaptics = isPlatform('ios');
29356
29630
  const { el, scrollEl } = this;
29357
- let timeout;
29358
29631
  let activeEl = this.activeItem;
29359
29632
  const scrollCallback = () => {
29360
29633
  raf(() => {
29361
- if (!scrollEl)
29634
+ /**
29635
+ * This frame cannot be cancelled, and moving the column disconnects it
29636
+ * without the observer reporting a change, so this checks live state.
29637
+ */
29638
+ if (!this.el.isConnected || !this.isColumnVisible || !scrollEl)
29362
29639
  return;
29363
- if (timeout) {
29364
- clearTimeout(timeout);
29365
- timeout = undefined;
29640
+ const { haltedAtScrollTop } = this;
29641
+ if (haltedAtScrollTop !== undefined) {
29642
+ /**
29643
+ * Still at the halted position, so this frame is the halt landing
29644
+ * rather than the wheel moving, and re-arming would start a second
29645
+ * commit cycle.
29646
+ */
29647
+ if (Math.abs(scrollEl.scrollTop - haltedAtScrollTop) <= HALT_TOLERANCE)
29648
+ return;
29649
+ this.haltedAtScrollTop = undefined;
29366
29650
  }
29651
+ // Armed before the early returns below, so a scroll never ends uncommitted.
29652
+ this.resetScrollEndTimeout();
29367
29653
  if (!this.isScrolling) {
29368
- enableHaptics && hapticSelectionStart();
29654
+ this.enableHaptics && hapticSelectionStart();
29369
29655
  this.isScrolling = true;
29370
29656
  }
29657
+ /**
29658
+ * Only a user-driven scroll holds an uncommitted selection. Checked every
29659
+ * frame because the user can take hold of the wheel mid-scroll, and
29660
+ * re-adding the same listener is a no-op.
29661
+ */
29662
+ if (this.isUserScroll) {
29663
+ this.watchForOutsidePress();
29664
+ }
29371
29665
  /**
29372
29666
  * Select item in the center of the column
29373
29667
  * which is the month/year that we want to select
@@ -29427,18 +29721,23 @@ class PickerColumn {
29427
29721
  newActiveElement = fallbackActiveElement;
29428
29722
  }
29429
29723
  }
29430
- if (activeEl !== undefined) {
29431
- this.setPickerItemActiveState(activeEl, false);
29432
- }
29724
+ /**
29725
+ * A scroll can land with no selectable option centered, such as an
29726
+ * overscroll bounce briefly centering the empty padding rows. Keep the
29727
+ * current selection until an option is centered again.
29728
+ */
29433
29729
  if (newActiveElement === undefined || newActiveElement.disabled) {
29434
29730
  return;
29435
29731
  }
29732
+ if (activeEl !== undefined) {
29733
+ this.setPickerItemActiveState(activeEl, false);
29734
+ }
29436
29735
  /**
29437
29736
  * If we are selecting a new value,
29438
29737
  * we need to run haptics again.
29439
29738
  */
29440
29739
  if (newActiveElement !== activeEl) {
29441
- enableHaptics && hapticSelectionChanged();
29740
+ this.enableHaptics && hapticSelectionChanged();
29442
29741
  if (this.canExitInputMode) {
29443
29742
  /**
29444
29743
  * The native iOS wheel picker
@@ -29470,32 +29769,14 @@ class PickerColumn {
29470
29769
  if (this.updateValueTextOnScroll) {
29471
29770
  this.assistiveFocusable?.setAttribute('aria-valuetext', this.getOptionValueText(newActiveElement));
29472
29771
  }
29473
- timeout = setTimeout(() => {
29474
- this.isScrolling = false;
29475
- this.updateValueTextOnScroll = true;
29476
- enableHaptics && hapticSelectionEnd();
29477
- /**
29478
- * Certain tasks (such as those that
29479
- * cause re-renders) should only be done
29480
- * once scrolling has finished, otherwise
29481
- * flickering may occur.
29482
- */
29483
- const { scrollEndCallback } = this;
29484
- if (scrollEndCallback) {
29485
- scrollEndCallback();
29486
- this.scrollEndCallback = undefined;
29487
- }
29488
- /**
29489
- * Reset this flag as the
29490
- * next scroll interaction could
29491
- * be a scroll from the user. In this
29492
- * case, we should exit input mode.
29493
- */
29494
- this.canExitInputMode = true;
29495
- this.setValue(newActiveElement.value);
29496
- }, 250);
29772
+ this.centeredOption = newActiveElement;
29497
29773
  });
29498
29774
  };
29775
+ const userScrollCallback = () => {
29776
+ this.isUserScroll = true;
29777
+ // Taking hold of the wheel ends the halt even if it has not moved yet.
29778
+ this.haltedAtScrollTop = undefined;
29779
+ };
29499
29780
  /**
29500
29781
  * Wrap this in an raf so that the scroll callback
29501
29782
  * does not fire when component is initially shown.
@@ -29504,8 +29785,19 @@ class PickerColumn {
29504
29785
  if (!scrollEl)
29505
29786
  return;
29506
29787
  scrollEl.addEventListener('scroll', scrollCallback);
29788
+ scrollEl.addEventListener('pointerdown', userScrollCallback);
29789
+ scrollEl.addEventListener('wheel', userScrollCallback, { passive: true });
29790
+ /**
29791
+ * A `pointerdown` fires once per touch, so a drag that pauses long enough
29792
+ * to commit would look like a scroll the column started. A `touchmove`
29793
+ * keeps arriving while the finger moves.
29794
+ */
29795
+ scrollEl.addEventListener('touchmove', userScrollCallback, { passive: true });
29507
29796
  this.destroyScrollListener = () => {
29508
29797
  scrollEl.removeEventListener('scroll', scrollCallback);
29798
+ scrollEl.removeEventListener('pointerdown', userScrollCallback);
29799
+ scrollEl.removeEventListener('wheel', userScrollCallback);
29800
+ scrollEl.removeEventListener('touchmove', userScrollCallback);
29509
29801
  };
29510
29802
  });
29511
29803
  };
@@ -29688,6 +29980,14 @@ class PickerColumn {
29688
29980
  }
29689
29981
  else {
29690
29982
  this.isColumnVisible = false;
29983
+ /**
29984
+ * The pending timer still runs so it resets the scroll state, but the
29985
+ * option it would have committed is dropped. A column the user cannot
29986
+ * see should not change its value.
29987
+ */
29988
+ this.stopWatchingForOutsidePress();
29989
+ this.centeredOption = undefined;
29990
+ this.haltedAtScrollTop = undefined;
29691
29991
  if (this.destroyScrollListener) {
29692
29992
  this.destroyScrollListener();
29693
29993
  this.destroyScrollListener = undefined;
@@ -29758,6 +30058,13 @@ class PickerColumn {
29758
30058
  connectedCallback() {
29759
30059
  this.ariaLabel = this.el.getAttribute('aria-label') ?? 'Select a value';
29760
30060
  }
30061
+ disconnectedCallback() {
30062
+ /**
30063
+ * A pending settle would otherwise commit a value on a column that is no
30064
+ * longer in the DOM.
30065
+ */
30066
+ this.discardScroll();
30067
+ }
29761
30068
  get activeItem() {
29762
30069
  const { value } = this;
29763
30070
  const options = Array.from(this.el.querySelectorAll('ion-picker-column-option'));
@@ -29775,14 +30082,14 @@ class PickerColumn {
29775
30082
  render() {
29776
30083
  const { color, disabled, isActive, numericInput } = this;
29777
30084
  const mode = getIonMode$1(this);
29778
- return (hAsync(Host, { key: '78b46ad10d88ea1bb43ca8c36748767912f03224', class: createColorClasses$1(color, {
30085
+ return (hAsync(Host, { key: '60a893619d0b01fba53fbccef67a10d533a22657', class: createColorClasses$1(color, {
29779
30086
  [mode]: true,
29780
30087
  ['picker-column-active']: isActive,
29781
30088
  ['picker-column-numeric-input']: numericInput,
29782
30089
  ['picker-column-disabled']: disabled,
29783
- }) }, hAsync("slot", { key: '761e501df77f7de896ffb3ebb99ebf88c5c3bf70', name: "prefix" }), hAsync("div", { key: '9f4caaeef8ab704522a85f30876d371712f47c5c', class: "picker-opts", ref: (el) => {
30090
+ }) }, hAsync("slot", { key: '79f1e047f89c5ec916ed02efaac56ef3f73b8969', name: "prefix" }), hAsync("div", { key: 'c45c86e88353a196ff38159f40f390bc27852c9e', class: "picker-opts", ref: (el) => {
29784
30091
  this.scrollEl = el;
29785
- }, 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" })));
30092
+ }, 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" })));
29786
30093
  }
29787
30094
  get el() { return getElement(this); }
29788
30095
  static get watchers() { return {
@@ -29814,6 +30121,19 @@ class PickerColumn {
29814
30121
  }; }
29815
30122
  }
29816
30123
  const PICKER_ITEM_ACTIVE_CLASS = 'option-active';
30124
+ /**
30125
+ * How long the column must be idle before the centered option is treated as
30126
+ * the user's selection. Replaceable by the `scrollend` event once that is
30127
+ * supported everywhere (https://caniuse.com/?search=scrollend).
30128
+ */
30129
+ const SCROLL_END_DELAY = 250;
30130
+ /**
30131
+ * How far, in pixels, the column may report from where it was halted and still
30132
+ * count as having stayed there. Centering targets a position between two snap
30133
+ * points, so mandatory snapping corrects it by half the column height less
30134
+ * three option heights: 2px at the default sizes.
30135
+ */
30136
+ const HALT_TOLERANCE = 2;
29817
30137
 
29818
30138
  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}`;
29819
30139
 
@@ -31216,6 +31536,13 @@ class Popover {
31216
31536
  const { configureTriggerInteraction, el } = this;
31217
31537
  prepareOverlay(el);
31218
31538
  configureTriggerInteraction();
31539
+ // Re-apply the root lock if moved without dismiss() being called
31540
+ if (this.presented) {
31541
+ restoreRootFocusTrapAccessibility(el);
31542
+ // The disconnect tore down the header observer, and `present()` is its
31543
+ // only other caller, so a move mid-layout would lose the recalculation.
31544
+ this.recalculateContentOnHeaderReady();
31545
+ }
31219
31546
  }
31220
31547
  disconnectedCallback() {
31221
31548
  const { destroyTriggerInteraction } = this;
@@ -31393,6 +31720,12 @@ class Popover {
31393
31720
  if (!header || contentElements.length === 0) {
31394
31721
  return;
31395
31722
  }
31723
+ // Both `present()` and a reconnect call this, so drop any existing
31724
+ // observer. Below the guards, so a call that bails cannot leave none.
31725
+ if (this.headerResizeObserver) {
31726
+ this.headerResizeObserver.disconnect();
31727
+ this.headerResizeObserver = undefined;
31728
+ }
31396
31729
  this.headerResizeObserver = new ResizeObserver(async () => {
31397
31730
  if (header.offsetHeight > 0) {
31398
31731
  this.headerResizeObserver?.disconnect();
@@ -31465,7 +31798,7 @@ class Popover {
31465
31798
  const { onLifecycle, parentPopover, dismissOnSelect, side, arrow, htmlAttributes, focusTrap } = this;
31466
31799
  const desktop = isPlatform('desktop');
31467
31800
  const enableArrow = arrow && !parentPopover;
31468
- return (hAsync(Host, { key: '52ffc7116969ae1b8b927e67f2acbfe5f5434f70', "aria-modal": "true", "no-router": true, tabindex: "-1", ...htmlAttributes, style: {
31801
+ return (hAsync(Host, { key: 'b5e9c788f58397203976d5f8302dfb89e916efe1', "aria-modal": "true", "no-router": true, tabindex: "-1", ...htmlAttributes, style: {
31469
31802
  zIndex: `${20000 + this.overlayIndex}`,
31470
31803
  }, class: {
31471
31804
  ...getClassMap(this.cssClass),
@@ -31476,7 +31809,7 @@ class Popover {
31476
31809
  [`popover-side-${side}`]: true,
31477
31810
  [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false,
31478
31811
  'popover-nested': !!parentPopover,
31479
- }, 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' })))));
31812
+ }, 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' })))));
31480
31813
  }
31481
31814
  get el() { return getElement(this); }
31482
31815
  static get watchers() { return {
@@ -38390,7 +38723,7 @@ class Select {
38390
38723
  const hasOutlineFill = mode === 'md' && fill === 'outline';
38391
38724
  renderHiddenInput(true, el, name, parseValue(value), disabled);
38392
38725
  const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || isExpanded));
38393
- return (hAsync(Host, { key: '5d1e5bf46d0f204efdcb55cc42cfde52e6db304b', onClick: this.onClick, class: createColorClasses$1(this.color, {
38726
+ return (hAsync(Host, { key: 'b2f161e3706e139e61440cd13e162714b1b75d72', onClick: this.onClick, class: createColorClasses$1(this.color, {
38394
38727
  [mode]: true,
38395
38728
  'in-item': inItem,
38396
38729
  'in-item-color': hostContext('ion-item.ion-color', el),
@@ -38408,7 +38741,7 @@ class Select {
38408
38741
  [`select-justify-${justify}`]: justifyEnabled,
38409
38742
  [`select-shape-${shape}`]: shape !== undefined,
38410
38743
  [`select-label-placement-${labelPlacement}`]: true,
38411
- }) }, 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()));
38744
+ }) }, 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()));
38412
38745
  }
38413
38746
  get el() { return getElement(this); }
38414
38747
  static get watchers() { return {
@@ -38517,29 +38850,14 @@ const textForValue = (opts, value, compareWith, useHTML = false) => {
38517
38850
  return getOptionContent(selectOpt, undefined, true);
38518
38851
  }
38519
38852
  /**
38520
- * When custom HTML is enabled, extract only the default slot content.
38521
- * This ensures aria-label and other text-only contexts read only
38522
- * the relevant option text.
38853
+ * Every text-only context reads only the default slot, so the start
38854
+ * and end slots stay out of the `aria-label` and the overlay labels.
38855
+ * Both config paths derive that text through the same helper, so they
38856
+ * cannot disagree about what an option's text is. `null` marks an
38857
+ * option with no text, which is dropped from the joined text of a
38858
+ * `multiple` select rather than joined in as an empty entry.
38523
38859
  */
38524
- if (customHTMLEnabled) {
38525
- const content = getOptionContent(selectOpt);
38526
- if (typeof content === 'string') {
38527
- return content;
38528
- }
38529
- /**
38530
- * Elements were found in the default slot, extract and concatenate
38531
- * their text content while trimming whitespace.
38532
- */
38533
- if (content) {
38534
- const texts = Array.from(content.childNodes)
38535
- .map((n) => n.textContent?.trim())
38536
- .filter((t) => t);
38537
- return texts.join(' ') || null;
38538
- }
38539
- // Empty option
38540
- return null;
38541
- }
38542
- return getDefaultSlotPlainText(selectOpt);
38860
+ return getDefaultSlotPlainText(selectOpt) || null;
38543
38861
  };
38544
38862
  /**
38545
38863
  * Trims whitespace from all text nodes within a DOM tree.
@@ -38595,9 +38913,13 @@ const getOptionContent = (option, slotName, useHTML = false) => {
38595
38913
  if (nodes.length === 0) {
38596
38914
  return null;
38597
38915
  }
38598
- // Return plain text if no elements are found
38916
+ /**
38917
+ * Return plain text if no elements are found. This reads the option the
38918
+ * same way the non-custom-HTML path does, so the two do not disagree
38919
+ * about what an option's text is.
38920
+ */
38599
38921
  if (!slotName && nodes.every((n) => n.nodeType === Node.TEXT_NODE)) {
38600
- return nodes.map((n) => n.textContent?.trim()).join(' ') || null;
38922
+ return getDefaultSlotPlainText(option) || null;
38601
38923
  }
38602
38924
  /**
38603
38925
  * Mirror known custom-element properties (e.g. ion-icon's `icon`)
@@ -38653,22 +38975,43 @@ const getOptionDefaultSlot = (option) => {
38653
38975
  }
38654
38976
  return defaultSlotNodes;
38655
38977
  };
38978
+ /**
38979
+ * Concatenates the text a node renders, skipping the subtrees of tags
38980
+ * whose contents the browser never paints (`script`, `style`, and the
38981
+ * rest of `blockedTags`). `textContent` includes those, so reading it
38982
+ * directly would put stylesheet or script source into the select text
38983
+ * and the `aria-label`.
38984
+ *
38985
+ * @param node - The node to read text from.
38986
+ * @returns The node's rendered text.
38987
+ */
38988
+ const getRenderedTextContent = (node) => {
38989
+ if (node.nodeType === Node.TEXT_NODE) {
38990
+ return node.textContent ?? '';
38991
+ }
38992
+ if (node.nodeType !== Node.ELEMENT_NODE) {
38993
+ return '';
38994
+ }
38995
+ if (blockedTags.includes(node.tagName.toLowerCase())) {
38996
+ return '';
38997
+ }
38998
+ return Array.from(node.childNodes)
38999
+ .map((child) => getRenderedTextContent(child))
39000
+ .join('');
39001
+ };
38656
39002
  /**
38657
39003
  * Extracts plain text from only the default slot of an option,
38658
- * excluding content assigned to named slots (start/end).
39004
+ * excluding content assigned to named slots (start/end). Text is
39005
+ * concatenated with no separator and collapsible whitespace is
39006
+ * collapsed, approximating how the browser renders the option.
39007
+ * NBSP is not collapsible, so it is preserved.
39008
+ *
39009
+ * @param option - The `ion-select-option` element to read text from.
39010
+ * @returns The option's default slot text.
38659
39011
  */
38660
39012
  const getDefaultSlotPlainText = (option) => {
38661
- const texts = Array.from(option.childNodes)
38662
- .filter((node) => {
38663
- if (node.nodeType === Node.ELEMENT_NODE) {
38664
- return !node.hasAttribute('slot');
38665
- }
38666
- return node.nodeType === Node.TEXT_NODE;
38667
- })
38668
- .filter((node) => node.nodeType === Node.TEXT_NODE)
38669
- .map((n) => n.textContent?.trim())
38670
- .filter((t) => t);
38671
- return texts.join(' ');
39013
+ const text = (getOptionDefaultSlot(option) ?? []).map((node) => getRenderedTextContent(node)).join('');
39014
+ return text.replace(/[ \t\n\r\f]+/g, ' ').replace(/^[ \t\n\r\f]+|[ \t\n\r\f]+$/g, '');
38672
39015
  };
38673
39016
  /**
38674
39017
  * Extracts the rich content from an `ion-select-option`.
@@ -42744,7 +43087,7 @@ var NAMESPACE = (
42744
43087
  );
42745
43088
 
42746
43089
  /*
42747
- Stencil Hydrate Runner v4.43.5 | MIT Licensed | https://stenciljs.com
43090
+ Stencil Hydrate Runner v4.44.1 | MIT Licensed | https://stenciljs.com
42748
43091
  */
42749
43092
  var __create = Object.create;
42750
43093
  var __defProp = Object.defineProperty;