voyager-ionic-core 9.0.3 → 9.0.6

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 (527) 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-Hp8t4RMX.js → p-6sKRBFnK.js} +1 -1
  99. package/components/{p-qAXsfUff.js → p-B8HBLiYi.js} +1 -1
  100. package/{dist/ionic/p-Do3zTvCA.js → components/p-BEiYs-sz.js} +1 -1
  101. package/components/p-BKeulLTJ.js +4 -0
  102. package/components/{p-5ldEpNdG.js → p-BKxLivx4.js} +1 -1
  103. package/components/{p-BYJRZKHa.js → p-BLjEwM6v.js} +1 -1
  104. package/components/{p-Cd1WaN-0.js → p-BNnmwjuy.js} +1 -1
  105. package/components/{p-COO0eJOA.js → p-BSJriPuC.js} +1 -1
  106. package/components/p-BUVGbkSc.js +4 -0
  107. package/components/{p-DL13ieTa.js → p-B_tZQKpS.js} +1 -1
  108. package/components/p-BexLz2XV.js +4 -0
  109. package/components/p-BinR4_P7.js +4 -0
  110. package/components/{p-DxhHlJln.js → p-BrOSQhkA.js} +1 -1
  111. package/components/p-BriaEJK8.js +4 -0
  112. package/components/p-BsLM9eQu.js +4 -0
  113. package/components/{p-DhNuxvJH.js → p-Bu6O-veK.js} +1 -1
  114. package/{dist/ionic/p-BMiZX1LT.js → components/p-C7rB-0-1.js} +1 -1
  115. package/components/{p-6ZLn6K5e.js → p-C9ioHZq-.js} +1 -1
  116. package/components/p-CAQG0btC.js +4 -0
  117. package/components/{p-DMBiAyOR.js → p-CHHkdXfP.js} +1 -1
  118. package/components/p-CJgshb3W.js +4 -0
  119. package/components/p-CQjNc-Pz.js +4 -0
  120. package/components/{p-CJgnoKcN.js → p-CTUMJM0R.js} +1 -1
  121. package/components/{p-C4VpVfrJ.js → p-CVVUo4J1.js} +1 -1
  122. package/components/{p-B4lxwJ8N.js → p-CXy2v7GI.js} +1 -1
  123. package/components/{p-BQyuFxYc.js → p-C_NQIzjP.js} +1 -1
  124. package/components/{p-D7wDJdFn.js → p-Canp1qah.js} +1 -1
  125. package/components/p-CcQQ8oRo.js +4 -0
  126. package/components/{p-GGbIHyEF.js → p-CiFFeRH9.js} +1 -1
  127. package/components/p-CiXOsJF2.js +4 -0
  128. package/components/p-Ctw69DyZ.js +4 -0
  129. package/components/{p-C8Ck7_Eo.js → p-CvzE7FFp.js} +1 -1
  130. package/components/{p-TWw4e4sO.js → p-CzykzqAO.js} +1 -1
  131. package/components/p-D0jSx7rE.js +4 -0
  132. package/components/{p-C-NbvXu4.js → p-D4NOsSCE.js} +1 -1
  133. package/components/{p-cEN43Ahr.js → p-DGUed0uX.js} +1 -1
  134. package/components/p-DM2jMsSO.js +4 -0
  135. package/components/p-DPyjiKOq.js +4 -0
  136. package/components/{p-BF48Oc0v.js → p-DSmHJ2DH.js} +1 -1
  137. package/components/{p-Fl7ZFU74.js → p-DWGgvN5e.js} +1 -1
  138. package/components/p-DlUdjUlf.js +4 -0
  139. package/components/{p-DM1gJSMP.js → p-Dlr7b3_2.js} +1 -1
  140. package/components/p-F1rV0pyK.js +4 -0
  141. package/components/{p-DFLJvuRK.js → p-LH1I_Zhd.js} +1 -1
  142. package/components/p-PPagT42x.js +4 -0
  143. package/components/{p-CqbGBmqb.js → p-RJT5zTbD.js} +1 -1
  144. package/components/p-T2dnrBya.js +4 -0
  145. package/components/p-WMQuK_Tj.js +4 -0
  146. package/components/p-eJpG4UbM.js +4 -0
  147. package/components/p-fFx6WCTj.js +4 -0
  148. package/{dist/ionic/p-BgOvhHy_.js → components/p-q2WJ5Igc.js} +1 -1
  149. package/components/{p-D5w_FlVa.js → p-y7Nhe3de.js} +1 -1
  150. package/css/core.css +1 -1
  151. package/css/core.css.map +1 -1
  152. package/css/ionic.bundle.css +1 -1
  153. package/css/ionic.bundle.css.map +1 -1
  154. package/dist/cjs/{animation-Kd1N7WTN.js → animation-BFKyYY11.js} +3 -3
  155. package/dist/cjs/{app-globals-b1G4t26O.js → app-globals-BLTzqkrC.js} +1 -1
  156. package/dist/cjs/attribute-controller-CXIeB0Mn.js +131 -0
  157. package/dist/cjs/{button-active-CQCFubJJ.js → button-active-CEQaiV9N.js} +2 -2
  158. package/dist/cjs/{capacitor-DmA66EwP.js → capacitor-BMzmHhwe.js} +3 -3
  159. package/dist/cjs/{format-bHU8N1g5.js → format-CdRlDqPs.js} +1 -1
  160. package/dist/cjs/{framework-delegate-d-fWfeI6.js → framework-delegate-DTLbqaaO.js} +1 -1
  161. package/dist/cjs/{haptic-Ch-X4gRx.js → haptic-CJVUv_GB.js} +1 -1
  162. package/dist/cjs/{helpers-7wzdhdeg.js → helpers-Crluoxqu.js} +50 -3
  163. package/dist/cjs/{index-DtvKGwdh.js → index-BAM4223M.js} +2 -2
  164. package/dist/cjs/{index-C74Q3t6a.js → index-BKpybYNI.js} +7 -8
  165. package/dist/cjs/{index-KiSZqhYS.js → index-BSD7toMO.js} +1 -1
  166. package/dist/cjs/{index-DFNrCX7M.js → index-CElfU-dK.js} +8 -9
  167. package/dist/cjs/{index-CQfEIyLK.js → index-CgXTRA_-.js} +4 -4
  168. package/dist/cjs/{index-DXoo08JC.js → index-SAR1xwtW.js} +25 -12
  169. package/dist/cjs/index.cjs.js +19 -19
  170. package/dist/cjs/{input-shims-VJIiKBKv.js → input-shims-CHghGZe-.js} +16 -17
  171. package/dist/cjs/{input.utils-EHVE2RK_.js → input.utils-BBZr0wjw.js} +1 -1
  172. package/dist/cjs/ion-accordion_2.cjs.entry.js +3 -3
  173. package/dist/cjs/ion-action-sheet.cjs.entry.js +26 -28
  174. package/dist/cjs/ion-alert.cjs.entry.js +27 -29
  175. package/dist/cjs/ion-app_8.cjs.entry.js +72 -24
  176. package/dist/cjs/ion-avatar_3.cjs.entry.js +2 -2
  177. package/dist/cjs/ion-back-button.cjs.entry.js +3 -3
  178. package/dist/cjs/ion-backdrop.cjs.entry.js +2 -2
  179. package/dist/cjs/ion-breadcrumb_2.cjs.entry.js +3 -3
  180. package/dist/cjs/ion-button_2.cjs.entry.js +23 -34
  181. package/dist/cjs/ion-card_5.cjs.entry.js +19 -7
  182. package/dist/cjs/ion-checkbox.cjs.entry.js +4 -4
  183. package/dist/cjs/ion-chip.cjs.entry.js +2 -2
  184. package/dist/cjs/ion-col_3.cjs.entry.js +2 -2
  185. package/dist/cjs/ion-datetime-button.cjs.entry.js +4 -4
  186. package/dist/cjs/ion-datetime.cjs.entry.js +34 -29
  187. package/dist/cjs/ion-fab_3.cjs.entry.js +3 -3
  188. package/dist/cjs/ion-img.cjs.entry.js +3 -3
  189. package/dist/cjs/ion-infinite-scroll_2.cjs.entry.js +5 -5
  190. package/dist/cjs/ion-input-otp.cjs.entry.js +3 -3
  191. package/dist/cjs/ion-input-password-toggle.cjs.entry.js +2 -2
  192. package/dist/cjs/ion-input.cjs.entry.js +12 -16
  193. package/dist/cjs/ion-item-option_3.cjs.entry.js +4 -4
  194. package/dist/cjs/ion-item_8.cjs.entry.js +17 -8
  195. package/dist/cjs/ion-loading.cjs.entry.js +18 -20
  196. package/dist/cjs/ion-menu_3.cjs.entry.js +15 -17
  197. package/dist/cjs/ion-modal.cjs.entry.js +177 -172
  198. package/dist/cjs/ion-nav_2.cjs.entry.js +6 -6
  199. package/dist/cjs/ion-picker-column-option.cjs.entry.js +3 -3
  200. package/dist/cjs/ion-picker-column.cjs.entry.js +8 -9
  201. package/dist/cjs/ion-picker.cjs.entry.js +2 -2
  202. package/dist/cjs/ion-popover.cjs.entry.js +119 -42
  203. package/dist/cjs/ion-progress-bar.cjs.entry.js +3 -3
  204. package/dist/cjs/ion-radio_2.cjs.entry.js +4 -4
  205. package/dist/cjs/ion-range.cjs.entry.js +4 -4
  206. package/dist/cjs/ion-refresher_2.cjs.entry.js +8 -9
  207. package/dist/cjs/ion-reorder_2.cjs.entry.js +6 -7
  208. package/dist/cjs/ion-ripple-effect.cjs.entry.js +2 -2
  209. package/dist/cjs/ion-route_4.cjs.entry.js +4 -4
  210. package/dist/cjs/ion-searchbar.cjs.entry.js +3 -3
  211. package/dist/cjs/ion-segment-content.cjs.entry.js +1 -1
  212. package/dist/cjs/ion-segment-view.cjs.entry.js +1 -1
  213. package/dist/cjs/ion-segment_2.cjs.entry.js +3 -3
  214. package/dist/cjs/ion-select-modal.cjs.entry.js +8 -10
  215. package/dist/cjs/ion-select_3.cjs.entry.js +71 -53
  216. package/dist/cjs/ion-spinner.cjs.entry.js +2 -2
  217. package/dist/cjs/ion-split-pane.cjs.entry.js +2 -2
  218. package/dist/cjs/ion-tab-bar_2.cjs.entry.js +6 -7
  219. package/dist/cjs/ion-tab_2.cjs.entry.js +3 -3
  220. package/dist/cjs/ion-text.cjs.entry.js +2 -2
  221. package/dist/cjs/ion-textarea.cjs.entry.js +11 -15
  222. package/dist/cjs/ion-toast.cjs.entry.js +49 -51
  223. package/dist/cjs/ion-toggle.cjs.entry.js +6 -7
  224. package/dist/cjs/{ionic-global-CYJNT-2P.js → ionic-global-C1h8Yi_K.js} +1 -1
  225. package/dist/cjs/ionic.cjs.js +5 -5
  226. package/dist/cjs/{ios.transition-DYGiD6gM.js → ios.transition-YFSxiyP_.js} +4 -5
  227. package/dist/cjs/{item-multiple-inputs-Dv6qrMhm.js → item-multiple-inputs-h2PyAFzG.js} +1 -1
  228. package/dist/cjs/{keyboard-cHxZlTyz.js → keyboard-C-C7xMKk.js} +1 -1
  229. package/dist/cjs/{keyboard-Cix5TVkD.js → keyboard-Cv-LNReK.js} +5 -3
  230. package/dist/cjs/{keyboard-controller-PtZoN2GS.js → keyboard-controller-CLcFxSnb.js} +9 -9
  231. package/dist/cjs/loader.cjs.js +4 -4
  232. package/dist/cjs/{md.transition-CrSkaoz6.js → md.transition-Cm8yg0UK.js} +4 -5
  233. package/dist/cjs/{overlays-BR21NUIG.js → overlays-C68wNDWY.js} +162 -9
  234. package/dist/cjs/{select-option-render-D8ZEjYji.js → select-option-render-C-Yh9yZG.js} +2 -2
  235. package/dist/cjs/{slot-mutation-controller-D6IjSEIh.js → slot-mutation-controller-zixZ5LyH.js} +73 -5
  236. package/dist/cjs/{status-tap-CNP5eD1R.js → status-tap-C3frTJ4c.js} +3 -3
  237. package/dist/cjs/{swipe-back-CSIJQfu5.js → swipe-back-ChrfFzIe.js} +2 -2
  238. package/dist/collection/collection-manifest.json +1 -1
  239. package/dist/collection/components/button/button.js +21 -32
  240. package/dist/collection/components/card/card.js +17 -6
  241. package/dist/collection/components/content/content.js +62 -8
  242. package/dist/collection/components/datetime/datetime.js +27 -20
  243. package/dist/collection/components/input/input.ios.css +6 -0
  244. package/dist/collection/components/input/input.js +6 -9
  245. package/dist/collection/components/input/input.md.css +6 -0
  246. package/dist/collection/components/item/item.js +15 -6
  247. package/dist/collection/components/modal/modal.ios.css +12 -1
  248. package/dist/collection/components/modal/modal.js +31 -8
  249. package/dist/collection/components/modal/modal.md.css +12 -1
  250. package/dist/collection/components/modal/safe-area-utils.js +69 -90
  251. package/dist/collection/components/modal/utils.js +7 -0
  252. package/dist/collection/components/popover/animations/ios.enter.js +20 -6
  253. package/dist/collection/components/popover/animations/md.enter.js +19 -5
  254. package/dist/collection/components/popover/utils.js +64 -13
  255. package/dist/collection/components/select/select.ios.css +1 -1
  256. package/dist/collection/components/select/select.js +67 -38
  257. package/dist/collection/components/select/select.md.css +1 -1
  258. package/dist/collection/components/textarea/textarea.ios.css +15 -1
  259. package/dist/collection/components/textarea/textarea.js +5 -8
  260. package/dist/collection/components/textarea/textarea.md.css +15 -1
  261. package/dist/collection/index.js +1 -1
  262. package/dist/collection/utils/attribute-controller.js +126 -0
  263. package/dist/collection/utils/forms/click-controller.js +70 -0
  264. package/dist/collection/utils/forms/index.js +1 -0
  265. package/dist/collection/utils/helpers.js +44 -3
  266. package/dist/collection/utils/logging/index.js +4 -0
  267. package/dist/collection/utils/overlays.js +34 -0
  268. package/dist/docs.json +9 -3
  269. package/dist/esm/{animation-BFNVlYum.js → animation-CFd8Olt3.js} +2 -2
  270. package/dist/esm/{app-globals-BgX0BGL1.js → app-globals-7GHLBkwd.js} +1 -1
  271. package/dist/esm/attribute-controller-Cn665x42.js +128 -0
  272. package/dist/esm/{button-active-BfOvDr3b.js → button-active-DMuYeDQN.js} +2 -2
  273. package/dist/esm/{capacitor-CFERIeaU.js → capacitor-CoEgIpR9.js} +1 -1
  274. package/dist/esm/{format-DDFE9jM5.js → format-C9zPmwKU.js} +1 -1
  275. package/dist/esm/{framework-delegate-BwNhx9NR.js → framework-delegate-DeT5pmPB.js} +1 -1
  276. package/dist/esm/{haptic-Cq4UAeka.js → haptic-Dxm7ZmT5.js} +1 -1
  277. package/dist/esm/{helpers-BSmc0nst.js → helpers-B54ynME_.js} +47 -4
  278. package/dist/esm/{index-C1b9CLFg.js → index--21qeSt0.js} +2 -2
  279. package/dist/esm/{index-DnA_7Bnx.js → index-B8iieOdw.js} +4 -4
  280. package/dist/esm/{index-BuPaALjU.js → index-B9jhwvmO.js} +5 -6
  281. package/dist/esm/{index-D76bbuoi.js → index-D4ZMZz_3.js} +1 -1
  282. package/dist/esm/{index-C23AVPx9.js → index-D9OR05yj.js} +26 -13
  283. package/dist/esm/{index-CJln0gS3.js → index-D_xZtbw6.js} +2 -3
  284. package/dist/esm/index.js +11 -13
  285. package/dist/esm/{input-shims-Dqk-Ou25.js → input-shims-MCrhq67U.js} +5 -6
  286. package/dist/esm/{input.utils-rqoH22pW.js → input.utils-B-IIWrwT.js} +1 -1
  287. package/dist/esm/ion-accordion_2.entry.js +3 -3
  288. package/dist/esm/ion-action-sheet.entry.js +11 -13
  289. package/dist/esm/ion-alert.entry.js +11 -13
  290. package/dist/esm/ion-app_8.entry.js +72 -24
  291. package/dist/esm/ion-avatar_3.entry.js +2 -2
  292. package/dist/esm/ion-back-button.entry.js +3 -3
  293. package/dist/esm/ion-backdrop.entry.js +2 -2
  294. package/dist/esm/ion-breadcrumb_2.entry.js +3 -3
  295. package/dist/esm/ion-button_2.entry.js +23 -34
  296. package/dist/esm/ion-card_5.entry.js +19 -7
  297. package/dist/esm/ion-checkbox.entry.js +4 -4
  298. package/dist/esm/ion-chip.entry.js +2 -2
  299. package/dist/esm/ion-col_3.entry.js +2 -2
  300. package/dist/esm/ion-datetime-button.entry.js +4 -4
  301. package/dist/esm/ion-datetime.entry.js +33 -28
  302. package/dist/esm/ion-fab_3.entry.js +3 -3
  303. package/dist/esm/ion-img.entry.js +3 -3
  304. package/dist/esm/ion-infinite-scroll_2.entry.js +5 -5
  305. package/dist/esm/ion-input-otp.entry.js +3 -3
  306. package/dist/esm/ion-input-password-toggle.entry.js +2 -2
  307. package/dist/esm/ion-input.entry.js +12 -16
  308. package/dist/esm/ion-item-option_3.entry.js +4 -4
  309. package/dist/esm/ion-item_8.entry.js +17 -8
  310. package/dist/esm/ion-loading.entry.js +7 -9
  311. package/dist/esm/ion-menu_3.entry.js +7 -9
  312. package/dist/esm/ion-modal.entry.js +115 -110
  313. package/dist/esm/ion-nav_2.entry.js +6 -6
  314. package/dist/esm/ion-picker-column-option.entry.js +3 -3
  315. package/dist/esm/ion-picker-column.entry.js +5 -6
  316. package/dist/esm/ion-picker.entry.js +2 -2
  317. package/dist/esm/ion-popover.entry.js +108 -31
  318. package/dist/esm/ion-progress-bar.entry.js +3 -3
  319. package/dist/esm/ion-radio_2.entry.js +4 -4
  320. package/dist/esm/ion-range.entry.js +4 -4
  321. package/dist/esm/ion-refresher_2.entry.js +8 -9
  322. package/dist/esm/ion-reorder_2.entry.js +6 -7
  323. package/dist/esm/ion-ripple-effect.entry.js +2 -2
  324. package/dist/esm/ion-route_4.entry.js +4 -4
  325. package/dist/esm/ion-searchbar.entry.js +3 -3
  326. package/dist/esm/ion-segment-content.entry.js +1 -1
  327. package/dist/esm/ion-segment-view.entry.js +1 -1
  328. package/dist/esm/ion-segment_2.entry.js +3 -3
  329. package/dist/esm/ion-select-modal.entry.js +7 -9
  330. package/dist/esm/ion-select_3.entry.js +66 -48
  331. package/dist/esm/ion-spinner.entry.js +2 -2
  332. package/dist/esm/ion-split-pane.entry.js +2 -2
  333. package/dist/esm/ion-tab-bar_2.entry.js +6 -7
  334. package/dist/esm/ion-tab_2.entry.js +3 -3
  335. package/dist/esm/ion-text.entry.js +2 -2
  336. package/dist/esm/ion-textarea.entry.js +11 -15
  337. package/dist/esm/ion-toast.entry.js +7 -9
  338. package/dist/esm/ion-toggle.entry.js +6 -7
  339. package/dist/esm/{ionic-global-ZXjCXKH0.js → ionic-global-B-G43ddm.js} +1 -1
  340. package/dist/esm/ionic.js +6 -6
  341. package/dist/esm/{ios.transition-CWAgfQ1r.js → ios.transition-CRfGj4Mo.js} +4 -5
  342. package/dist/esm/{item-multiple-inputs-DZnIiOO_.js → item-multiple-inputs-BSD9wGHO.js} +1 -1
  343. package/dist/esm/{keyboard-Cj8mLJeq.js → keyboard-DDw62P0D.js} +5 -3
  344. package/dist/esm/{keyboard-controller-DEwoa1ev.js → keyboard-controller-Dzjet5wD.js} +2 -2
  345. package/dist/esm/{keyboard-DAF8GNJ9.js → keyboard-ly3M0GO7.js} +1 -1
  346. package/dist/esm/loader.js +5 -5
  347. package/dist/esm/{md.transition-ZuqDDdDW.js → md.transition-wqThNy_C.js} +4 -5
  348. package/dist/esm/{overlays-DKE0DgvE.js → overlays-BQnV0HAU.js} +156 -7
  349. package/dist/esm/{select-option-render-CRP_teb1.js → select-option-render-CGxPejmz.js} +2 -2
  350. package/dist/esm/{slot-mutation-controller-B5NpUZ-N.js → slot-mutation-controller-C3s4-_YN.js} +69 -3
  351. package/dist/esm/{status-tap-Cv9gb3ja.js → status-tap-DRx9wSD_.js} +3 -3
  352. package/dist/esm/{swipe-back-De5HlmeM.js → swipe-back-CXmdi75W.js} +2 -2
  353. package/dist/ionic/index.esm.js +1 -1
  354. package/dist/ionic/ionic.esm.js +1 -1
  355. package/dist/ionic/{p-8b80d9f9.entry.js → p-0517aec4.entry.js} +1 -1
  356. package/dist/ionic/{p-ee09ac9d.entry.js → p-083b1119.entry.js} +1 -1
  357. package/dist/ionic/p-0ab133d6.entry.js +4 -0
  358. package/dist/ionic/{p-271c3640.entry.js → p-1110da0d.entry.js} +1 -1
  359. package/dist/ionic/p-1213b719.entry.js +4 -0
  360. package/dist/ionic/p-150f350e.entry.js +4 -0
  361. package/dist/ionic/{p-38b9375b.entry.js → p-20d1ac29.entry.js} +1 -1
  362. package/dist/ionic/p-24b0a961.entry.js +4 -0
  363. package/dist/ionic/{p-f0fb23c1.entry.js → p-2e6e933d.entry.js} +1 -1
  364. package/dist/ionic/p-30dcf43b.entry.js +4 -0
  365. package/dist/ionic/p-336ea4b8.entry.js +4 -0
  366. package/dist/ionic/{p-b9b4e85d.entry.js → p-378341d1.entry.js} +1 -1
  367. package/dist/ionic/{p-191a651e.entry.js → p-37f46670.entry.js} +1 -1
  368. package/dist/ionic/p-3a5faaa8.entry.js +4 -0
  369. package/dist/ionic/{p-efc0cf82.entry.js → p-3c4b0ba7.entry.js} +1 -1
  370. package/dist/ionic/p-42b2a992.entry.js +4 -0
  371. package/dist/ionic/p-49a16200.entry.js +4 -0
  372. package/dist/ionic/{p-837db1b9.entry.js → p-4dbb2f4f.entry.js} +1 -1
  373. package/dist/ionic/p-52dc3309.entry.js +4 -0
  374. package/dist/ionic/{p-85599fe3.entry.js → p-58f914ee.entry.js} +1 -1
  375. package/dist/ionic/{p-561af487.entry.js → p-5b9666be.entry.js} +1 -1
  376. package/dist/ionic/p-5c19330c.entry.js +4 -0
  377. package/dist/ionic/{p-3bba83ee.entry.js → p-61b304c8.entry.js} +1 -1
  378. package/dist/ionic/p-624f2fa8.entry.js +4 -0
  379. package/dist/ionic/p-636349e2.entry.js +4 -0
  380. package/dist/ionic/{p-d8c138d9.entry.js → p-6865f0e1.entry.js} +1 -1
  381. package/dist/ionic/p-7441ed2b.entry.js +4 -0
  382. package/dist/ionic/p-76309bab.entry.js +4 -0
  383. package/dist/ionic/p-83448626.entry.js +4 -0
  384. package/dist/ionic/{p-5d9094ac.entry.js → p-834afcf7.entry.js} +1 -1
  385. package/dist/ionic/{p-099b7f9f.entry.js → p-93cd738b.entry.js} +1 -1
  386. package/dist/ionic/{p-d6755739.entry.js → p-9b78fedf.entry.js} +1 -1
  387. package/dist/ionic/p-9dd9788c.entry.js +4 -0
  388. package/dist/ionic/{p-DYUjHcuH.js → p-B4ELlbJE.js} +1 -1
  389. package/dist/ionic/p-B4wzg4z4.js +4 -0
  390. package/dist/ionic/p-B4xjg_Qu.js +4 -0
  391. package/dist/ionic/{p-T71k3C35.js → p-BCgqWm-V.js} +1 -1
  392. package/dist/ionic/p-BChRVdVv.js +4 -0
  393. package/dist/ionic/{p-DTxBioUO.js → p-BUB5OrpU.js} +1 -1
  394. package/dist/ionic/p-BVEsh7-M.js +4 -0
  395. package/dist/ionic/p-Ba6ZV-qU.js +4 -0
  396. package/dist/ionic/{p-D7jHfs0Y.js → p-BhMQahM6.js} +1 -1
  397. package/dist/ionic/p-BtHAx8im.js +4 -0
  398. package/dist/ionic/{p-DZ6Hmc-8.js → p-Bv-6401R.js} +1 -1
  399. package/dist/ionic/{p-C8XilMh0.js → p-CCik51Nv.js} +1 -1
  400. package/dist/ionic/p-CTmJSZcs.js +4 -0
  401. package/dist/ionic/{p-BaeKWZ-a.js → p-CVwXN07G.js} +1 -1
  402. package/dist/ionic/p-CgQdInM0.js +4 -0
  403. package/{components/p-BJr2B5hZ.js → dist/ionic/p-CrAPHbJ3.js} +1 -1
  404. package/dist/ionic/p-CsWrz1c2.js +4 -0
  405. package/dist/ionic/p-D5akOqD0.js +4 -0
  406. package/dist/ionic/{p-C23AVPx9.js → p-D9OR05yj.js} +2 -2
  407. package/dist/ionic/p-DHf9V6zI.js +4 -0
  408. package/dist/ionic/{p-Bd72UYI2.js → p-DNxEB9-T.js} +1 -1
  409. package/dist/ionic/p-DZUqAr_6.js +4 -0
  410. package/dist/ionic/{p-CM5OBjTW.js → p-DffXRKHu.js} +1 -1
  411. package/dist/ionic/{p-BMPN55of.js → p-DxvRP6ld.js} +1 -1
  412. package/dist/ionic/p-Dzew6Qv7.js +4 -0
  413. package/dist/ionic/p-PkaVMJga.js +4 -0
  414. package/dist/ionic/{p-4712a8a9.entry.js → p-b0a3dd1a.entry.js} +1 -1
  415. package/dist/ionic/p-b1164028.entry.js +4 -0
  416. package/dist/ionic/{p-ca1b8865.entry.js → p-b710b4b8.entry.js} +1 -1
  417. package/dist/ionic/{p-6e386853.entry.js → p-b9659d21.entry.js} +1 -1
  418. package/dist/ionic/{p-68cc89a6.entry.js → p-ba7bd621.entry.js} +1 -1
  419. package/dist/ionic/{p-db449915.entry.js → p-c2a23101.entry.js} +1 -1
  420. package/dist/ionic/p-daaecea3.entry.js +4 -0
  421. package/dist/ionic/p-e05073f6.entry.js +4 -0
  422. package/dist/ionic/{p-90f50a65.entry.js → p-e137f724.entry.js} +1 -1
  423. package/dist/ionic/p-e1969fd1.entry.js +4 -0
  424. package/dist/ionic/{p-7fbb3319.entry.js → p-e338693a.entry.js} +1 -1
  425. package/dist/ionic/p-e4c3f17f.entry.js +4 -0
  426. package/dist/ionic/p-e7414c33.entry.js +4 -0
  427. package/dist/ionic/{p-dd01be0a.entry.js → p-eb762f80.entry.js} +1 -1
  428. package/dist/ionic/{p-ec00fd0d.entry.js → p-edcb63e5.entry.js} +1 -1
  429. package/dist/ionic/p-f19e50f8.entry.js +4 -0
  430. package/dist/ionic/p-f9057f70.entry.js +4 -0
  431. package/dist/ionic/{p-9c5f2691.entry.js → p-f99cf5aa.entry.js} +1 -1
  432. package/dist/ionic/{p-54cbb0a7.entry.js → p-fee863dc.entry.js} +1 -1
  433. package/dist/ionic/p-kKvGoaEe.js +4 -0
  434. package/dist/ionic/p-tXpzvta8.js +4 -0
  435. package/dist/ionic/p-vPo3vRFc.js +4 -0
  436. package/dist/types/components/button/button.d.ts +3 -12
  437. package/dist/types/components/card/card.d.ts +3 -1
  438. package/dist/types/components/content/content.d.ts +28 -3
  439. package/dist/types/components/datetime/datetime.d.ts +5 -10
  440. package/dist/types/components/input/input.d.ts +1 -0
  441. package/dist/types/components/item/item.d.ts +1 -1
  442. package/dist/types/components/modal/modal.d.ts +9 -1
  443. package/dist/types/components/modal/safe-area-utils.d.ts +28 -14
  444. package/dist/types/components/modal/utils.d.ts +4 -0
  445. package/dist/types/components/popover/utils.d.ts +16 -3
  446. package/dist/types/components/select/select.d.ts +11 -0
  447. package/dist/types/components/textarea/textarea.d.ts +1 -0
  448. package/dist/types/components.d.ts +1 -1
  449. package/dist/types/index.d.ts +1 -1
  450. package/dist/types/stencil-public-runtime.d.ts +61 -55
  451. package/dist/types/utils/attribute-controller.d.ts +56 -0
  452. package/dist/types/utils/forms/click-controller.d.ts +36 -0
  453. package/dist/types/utils/forms/index.d.ts +1 -0
  454. package/dist/types/utils/helpers.d.ts +27 -2
  455. package/dist/types/utils/logging/index.d.ts +4 -0
  456. package/dist/types/utils/overlays.d.ts +15 -0
  457. package/hydrate/index.js +808 -292
  458. package/hydrate/index.mjs +808 -292
  459. package/package.json +3 -3
  460. package/components/p-1sJ0ZDPe.js +0 -4
  461. package/components/p-B1_TL6RQ.js +0 -4
  462. package/components/p-BT9-hMMz.js +0 -4
  463. package/components/p-BU8a2IhR.js +0 -4
  464. package/components/p-BW_SlU2D.js +0 -4
  465. package/components/p-BWoa-cki.js +0 -4
  466. package/components/p-BgkOsq-d.js +0 -4
  467. package/components/p-Bi-it1EH.js +0 -4
  468. package/components/p-C09TXohi.js +0 -4
  469. package/components/p-CG_zZq_I.js +0 -4
  470. package/components/p-CMRYD_yR.js +0 -4
  471. package/components/p-CNLioZ3B.js +0 -4
  472. package/components/p-CWAks_S_.js +0 -4
  473. package/components/p-CrAKlX71.js +0 -4
  474. package/components/p-Ctop2IWW.js +0 -4
  475. package/components/p-Cw6WocLJ.js +0 -4
  476. package/components/p-DZRZic9C.js +0 -4
  477. package/components/p-DiuOa1vw.js +0 -4
  478. package/components/p-Djmz-ssp.js +0 -4
  479. package/components/p-DnBNYc7u.js +0 -4
  480. package/components/p-DwSXbQSz.js +0 -4
  481. package/components/p-M34T2gyX.js +0 -4
  482. package/components/p-YjMkHuvH.js +0 -4
  483. package/dist/cjs/hardware-back-button-Bu4Dzw8l.js +0 -121
  484. package/dist/cjs/index-DkNv4J_i.js +0 -10
  485. package/dist/esm/hardware-back-button-DmkiRgOT.js +0 -115
  486. package/dist/esm/index-ZjP4CjeZ.js +0 -7
  487. package/dist/ionic/p-0dcb7bb6.entry.js +0 -4
  488. package/dist/ionic/p-1347880c.entry.js +0 -4
  489. package/dist/ionic/p-1f24cb24.entry.js +0 -4
  490. package/dist/ionic/p-2ea4bb36.entry.js +0 -4
  491. package/dist/ionic/p-338a02e0.entry.js +0 -4
  492. package/dist/ionic/p-3e01c744.entry.js +0 -4
  493. package/dist/ionic/p-458715a9.entry.js +0 -4
  494. package/dist/ionic/p-4c3e50f8.entry.js +0 -4
  495. package/dist/ionic/p-5906ea6f.entry.js +0 -4
  496. package/dist/ionic/p-5cc09b40.entry.js +0 -4
  497. package/dist/ionic/p-612ea3b1.entry.js +0 -4
  498. package/dist/ionic/p-77c96e08.entry.js +0 -4
  499. package/dist/ionic/p-7bfeccb3.entry.js +0 -4
  500. package/dist/ionic/p-7e394cc3.entry.js +0 -4
  501. package/dist/ionic/p-803059b6.entry.js +0 -4
  502. package/dist/ionic/p-9595e305.entry.js +0 -4
  503. package/dist/ionic/p-9ee9c5b6.entry.js +0 -4
  504. package/dist/ionic/p-BY6BzzPF.js +0 -4
  505. package/dist/ionic/p-BhamHSw3.js +0 -4
  506. package/dist/ionic/p-BijjLYjT.js +0 -4
  507. package/dist/ionic/p-CER8qW8Y.js +0 -4
  508. package/dist/ionic/p-CFuOr1Tu.js +0 -4
  509. package/dist/ionic/p-CIGNaXM1.js +0 -4
  510. package/dist/ionic/p-CMZYmFb4.js +0 -4
  511. package/dist/ionic/p-CkxVYPtX.js +0 -4
  512. package/dist/ionic/p-CmXuiRT6.js +0 -4
  513. package/dist/ionic/p-D5t_-oMk.js +0 -4
  514. package/dist/ionic/p-D6rHcCvc.js +0 -4
  515. package/dist/ionic/p-DLM95R4x.js +0 -4
  516. package/dist/ionic/p-D_gb-kdd.js +0 -4
  517. package/dist/ionic/p-DajLgJ4d.js +0 -4
  518. package/dist/ionic/p-ZjP4CjeZ.js +0 -4
  519. package/dist/ionic/p-a8df96c8.entry.js +0 -4
  520. package/dist/ionic/p-a8ff2489.entry.js +0 -4
  521. package/dist/ionic/p-aff52029.entry.js +0 -4
  522. package/dist/ionic/p-b3532b8d.entry.js +0 -4
  523. package/dist/ionic/p-cc4320d3.entry.js +0 -4
  524. package/dist/ionic/p-d526798a.entry.js +0 -4
  525. package/dist/ionic/p-f83b3e0c.entry.js +0 -4
  526. package/dist/ionic/p-fa50d493.entry.js +0 -4
  527. package/dist/ionic/p-zWf7R2xV.js +0 -4
@@ -2,41 +2,14 @@
2
2
  * (C) Ionic http://ionicframework.com - MIT License
3
3
  */
4
4
  import { win } from "../../utils/browser/index";
5
- import { raf } from "../../utils/helpers";
6
- /**
7
- * These thresholds match the SCSS media query breakpoints in modal.vars.scss
8
- * that trigger the centered dialog layout (non-fullscreen modal).
9
- *
10
- * SCSS defines two height breakpoints: $modal-inset-min-height-small (600px)
11
- * and $modal-inset-min-height-large (768px). We use the smaller one because
12
- * that's the threshold where the modal transitions from fullscreen to centered
13
- * dialog — the larger breakpoint only increases the dialog's height.
14
- */
15
- const MODAL_INSET_MIN_WIDTH = 768;
16
- const MODAL_INSET_MIN_HEIGHT = 600;
5
+ import { onCustomPropertyChange, raf } from "../../utils/helpers";
6
+ import { getOverlaySizeType } from "../../utils/overlays";
17
7
  const EDGE_THRESHOLD = 5;
18
- /**
19
- * CSS values for `--width` / `--height` that are treated as fullscreen
20
- * (modal touches the corresponding screen edges). Empty string means the
21
- * property was not overridden. See `hasCustomModalDimensions()`.
22
- */
23
- const FULLSCREEN_SIZE_VALUES = new Set(['', '100%', '100vw', '100vh', '100dvw', '100dvh', '100svw', '100svh']);
24
8
  /**
25
9
  * Cache for resolved root safe-area-top value, invalidated once per frame.
26
10
  */
27
11
  let cachedRootSafeAreaTop = null;
28
12
  let cacheInvalidationScheduled = false;
29
- /**
30
- * Determines if the current viewport meets the CSS media query conditions
31
- * that cause regular modals to render as centered dialogs instead of fullscreen.
32
- * Matches: @media (min-width: 768px) and (min-height: 600px)
33
- */
34
- const isCenteredDialogViewport = () => {
35
- if (!win)
36
- return false;
37
- return win.matchMedia(`(min-width: ${MODAL_INSET_MIN_WIDTH}px) and (min-height: ${MODAL_INSET_MIN_HEIGHT}px)`)
38
- .matches;
39
- };
40
13
  /**
41
14
  * Resolves the current root --ion-safe-area-top value to pixels.
42
15
  * Uses a temporary element because getComputedStyle on :root returns
@@ -70,55 +43,64 @@ export const getRootSafeAreaTop = () => {
70
43
  return value;
71
44
  };
72
45
  /**
73
- * Calls back when the resolved root `--ion-safe-area-top` changes, which no
74
- * event and no window resize covers. The probe's height tracks the variable, so
75
- * a change to it becomes a size change the observer can see.
46
+ * Calls back when the resolved root `--ion-safe-area-top` changes. The value
47
+ * the caller already applied is passed as the baseline, so a change between
48
+ * that read and the observer starting is still reported.
76
49
  */
77
50
  export const onRootSafeAreaTopChange = (callback) => {
78
- const doc = win?.document;
79
- if (!doc?.body || typeof ResizeObserver === 'undefined') {
80
- return () => undefined;
81
- }
82
- const probe = doc.createElement('div');
83
- probe.style.cssText =
84
- 'position:fixed;visibility:hidden;pointer-events:none;top:0;left:0;width:0;' +
85
- 'height:var(--ion-safe-area-top,0px);';
86
- doc.body.appendChild(probe);
87
- /**
88
- * Seeded with the value the caller has already applied, so a change that
89
- * lands before the observer's first delivery still gets reported. Comparing
90
- * against an unset value instead would consume that first delivery and treat
91
- * the new inset as the baseline.
92
- */
93
- let lastHeight = getRootSafeAreaTop();
94
- const observer = new ResizeObserver((entries) => {
95
- const { height } = entries[0].contentRect;
96
- if (height !== lastHeight) {
97
- lastHeight = height;
98
- callback(height);
99
- }
100
- });
101
- observer.observe(probe);
102
- return () => {
103
- observer.disconnect();
104
- probe.remove();
105
- };
51
+ return onCustomPropertyChange(win?.document?.body, '--ion-safe-area-top', callback, getRootSafeAreaTop());
106
52
  };
107
53
  /**
108
- * True when the modal host declares BOTH a non-fullscreen `--width` AND a
109
- * non-fullscreen `--height` (i.e. a centered-dialog-like modal that doesn't
110
- * touch any screen edge).
54
+ * Determines which viewport axes the modal spans so safe-area requirements
55
+ * can be predicted independently for each axis.
111
56
  *
112
- * The conservative "both axes" check avoids mis-zeroing safe-area for
113
- * partial-custom modals where the modal still touches top/bottom edges
114
- * (e.g. only `--width` overridden). Partial cases fall through to the
115
- * existing position-based post-animation correction.
57
+ * A modal that spans an axis reaches both edges on that axis and needs the
58
+ * corresponding safe-area insets. A modal that does not span an axis reaches
59
+ * neither edge on that axis.
60
+ *
61
+ * When both `--width` and `--height` are `fullscreen`, coverage can be
62
+ * determined directly. Otherwise, coverage is based on the rendered wrapper,
63
+ * including cases where content sizing or `--max-height` causes the modal
64
+ * to reach the viewport.
116
65
  */
117
- export const hasCustomModalDimensions = (hostEl) => {
66
+ export const getModalCoveredAxes = (hostEl) => {
118
67
  const styles = getComputedStyle(hostEl);
119
- const width = styles.getPropertyValue('--width').trim();
120
- const height = styles.getPropertyValue('--height').trim();
121
- return !FULLSCREEN_SIZE_VALUES.has(width) && !FULLSCREEN_SIZE_VALUES.has(height);
68
+ const width = getOverlaySizeType(styles.getPropertyValue('--width'));
69
+ const height = getOverlaySizeType(styles.getPropertyValue('--height'));
70
+ if (width === 'fullscreen' && height === 'fullscreen') {
71
+ return { vertical: true, horizontal: true };
72
+ }
73
+ return measureCoveredAxes(hostEl);
74
+ };
75
+ /**
76
+ * Measures the modal wrapper to determine whether it spans the viewport
77
+ * on each axis.
78
+ *
79
+ * The wrapper has no box while the modal is hidden, so `overlay-hidden`
80
+ * is temporarily removed to allow the wrapper to be measured. The class
81
+ * is restored in the same task before the browser can paint.
82
+ *
83
+ * Only the wrapper's size is measured. Its position is affected by the
84
+ * enter animation, which initially translates it by its own height, while
85
+ * the translation does not affect its measured size.
86
+ */
87
+ const measureCoveredAxes = (hostEl) => {
88
+ const wrapperEl = hostEl.shadowRoot?.querySelector('.modal-wrapper');
89
+ if (wrapperEl == null || win === undefined) {
90
+ return { vertical: false, horizontal: false };
91
+ }
92
+ const wasHidden = hostEl.classList.contains('overlay-hidden');
93
+ if (wasHidden) {
94
+ hostEl.classList.remove('overlay-hidden');
95
+ }
96
+ const { width, height } = wrapperEl.getBoundingClientRect();
97
+ if (wasHidden) {
98
+ hostEl.classList.add('overlay-hidden');
99
+ }
100
+ return {
101
+ vertical: height >= win.innerHeight - EDGE_THRESHOLD,
102
+ horizontal: width >= win.innerWidth - EDGE_THRESHOLD,
103
+ };
122
104
  };
123
105
  /**
124
106
  * Returns the initial safe-area configuration based on modal type.
@@ -152,26 +134,23 @@ export const getInitialSafeAreaConfig = (context) => {
152
134
  right: '0px',
153
135
  };
154
136
  }
155
- // On viewports that meet the centered dialog media query breakpoints,
156
- // regular modals render as centered dialogs (not fullscreen), so they
157
- // don't touch any screen edges and don't need safe-area insets. Also
158
- // applies to phone viewports when the modal declares custom --width and
159
- // --height; these don't touch screen edges either, so the initial
160
- // prediction must be zero to avoid a post-animation correction flash.
161
- if (isCenteredDialogViewport() || context.hasCustomDimensions) {
162
- return {
163
- top: '0px',
164
- bottom: '0px',
165
- left: '0px',
166
- right: '0px',
167
- };
168
- }
169
- // Fullscreen modals on phone - inherit all safe areas
137
+ /**
138
+ * Each axis is evaluated independently because a modal can span one axis
139
+ * without spanning the other. This allows the initial safe-area configuration
140
+ * to match the modal's expected dimensions and avoids correcting an incorrect
141
+ * pair of insets after presentation.
142
+ *
143
+ * A modal can span the horizontal axis while remaining inset vertically, or
144
+ * span the vertical axis while remaining inset horizontally. Wide viewports
145
+ * can also render regular modals as centered dialogs, while content-sized
146
+ * modals may still be clamped to the viewport.
147
+ */
148
+ const { vertical, horizontal } = context.coveredAxes ?? { vertical: true, horizontal: true };
170
149
  return {
171
- top: 'inherit',
172
- bottom: 'inherit',
173
- left: 'inherit',
174
- right: 'inherit',
150
+ top: vertical ? 'inherit' : '0px',
151
+ bottom: vertical ? 'inherit' : '0px',
152
+ left: horizontal ? 'inherit' : '0px',
153
+ right: horizontal ? 'inherit' : '0px',
175
154
  };
176
155
  };
177
156
  /**
@@ -2,6 +2,7 @@
2
2
  * (C) Ionic http://ionicframework.com - MIT License
3
3
  */
4
4
  import { win } from "../../utils/browser/index";
5
+ import { onCustomPropertyChange } from "../../utils/helpers";
5
6
  import { StatusBar, Style } from "../../utils/native/status-bar";
6
7
  /**
7
8
  * Use y = mx + b to
@@ -78,3 +79,9 @@ export const setCardStatusBarDefault = (defaultStyle = Style.Default) => {
78
79
  }
79
80
  StatusBar.setStyle({ style: defaultStyle });
80
81
  };
82
+ /**
83
+ * Calls back when the modal's resolved `--height` changes.
84
+ */
85
+ export const onModalHeightChange = (hostEl, callback) => {
86
+ return onCustomPropertyChange(hostEl, '--height', () => callback());
87
+ };
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import { createAnimation } from "../../../utils/animation/animation";
5
5
  import { getElementRoot } from "../../../utils/helpers";
6
- import { calculateWindowAdjustment, getArrowDimensions, getPopoverDimensions, getPopoverPosition, getSafeAreaInsets, shouldShowArrow, } from "../utils";
6
+ import { calculateWindowAdjustment, getArrowDimensions, getElementCSSZoom, getPopoverDimensions, getPopoverPosition, getSafeAreaInsets, shouldShowArrow, } from "../utils";
7
7
  const POPOVER_IOS_BODY_PADDING = 5;
8
8
  /**
9
9
  * Minimum edge margin for iOS popovers ensures visual spacing from screen
@@ -22,21 +22,35 @@ export const iosEnterAnimation = (baseEl, opts) => {
22
22
  const { event: ev, size, trigger, reference, side, align } = opts;
23
23
  const doc = baseEl.ownerDocument;
24
24
  const isRTL = doc.dir === 'rtl';
25
- const bodyWidth = doc.defaultView.innerWidth;
26
- const bodyHeight = doc.defaultView.innerHeight;
27
25
  const root = getElementRoot(baseEl);
28
26
  const contentEl = root.querySelector('.popover-content');
29
27
  const arrowEl = root.querySelector('.popover-arrow');
28
+ /**
29
+ * A CSS `zoom` other than 1 on an ancestor (e.g. the `html` element) causes
30
+ * geometry APIs like `getBoundingClientRect()` to report zoomed values while
31
+ * inline `top`/`left`/`--width` styles are interpreted in the unzoomed layout
32
+ * space. Normalize all rect-derived measurements by this factor so the
33
+ * popover is positioned and sized correctly.
34
+ */
35
+ const zoom = getElementCSSZoom(contentEl);
36
+ /**
37
+ * `innerWidth`/`innerHeight` are not affected by CSS `zoom`, so they must be
38
+ * scaled down to the same layout space as the normalized measurements above.
39
+ * Otherwise the popover would be clamped against a viewport that is larger
40
+ * than the space actually available to it.
41
+ */
42
+ const bodyWidth = doc.defaultView.innerWidth / zoom;
43
+ const bodyHeight = doc.defaultView.innerHeight / zoom;
30
44
  const referenceSizeEl = trigger || ev?.detail?.ionShadowTarget || ev?.target;
31
- const { contentWidth, contentHeight } = getPopoverDimensions(size, contentEl, referenceSizeEl);
32
- const { arrowWidth, arrowHeight } = getArrowDimensions(arrowEl);
45
+ const { contentWidth, contentHeight } = getPopoverDimensions(size, contentEl, referenceSizeEl, zoom);
46
+ const { arrowWidth, arrowHeight } = getArrowDimensions(arrowEl, zoom);
33
47
  const defaultPosition = {
34
48
  top: bodyHeight / 2 - contentHeight / 2,
35
49
  left: bodyWidth / 2 - contentWidth / 2,
36
50
  originX: isRTL ? 'right' : 'left',
37
51
  originY: 'top',
38
52
  };
39
- const results = getPopoverPosition(isRTL, contentWidth, contentHeight, arrowWidth, arrowHeight, reference, side, align, defaultPosition, trigger, ev);
53
+ const results = getPopoverPosition(isRTL, contentWidth, contentHeight, arrowWidth, arrowHeight, reference, side, align, defaultPosition, trigger, ev, zoom);
40
54
  const padding = size === 'cover' ? 0 : POPOVER_IOS_BODY_PADDING;
41
55
  const rawSafeArea = getSafeAreaInsets(doc);
42
56
  const safeArea = size === 'cover'
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import { createAnimation } from "../../../utils/animation/animation";
5
5
  import { getElementRoot } from "../../../utils/helpers";
6
- import { calculateWindowAdjustment, getPopoverDimensions, getPopoverPosition, getSafeAreaInsets } from "../utils";
6
+ import { calculateWindowAdjustment, getElementCSSZoom, getPopoverDimensions, getPopoverPosition, getSafeAreaInsets, } from "../utils";
7
7
  const POPOVER_MD_BODY_PADDING = 12;
8
8
  /**
9
9
  * Md Popover Enter Animation
@@ -13,19 +13,33 @@ export const mdEnterAnimation = (baseEl, opts) => {
13
13
  const { event: ev, size, trigger, reference, side, align } = opts;
14
14
  const doc = baseEl.ownerDocument;
15
15
  const isRTL = doc.dir === 'rtl';
16
- const bodyWidth = doc.defaultView.innerWidth;
17
- const bodyHeight = doc.defaultView.innerHeight;
18
16
  const root = getElementRoot(baseEl);
19
17
  const contentEl = root.querySelector('.popover-content');
18
+ /**
19
+ * A CSS `zoom` other than 1 on an ancestor (e.g. the `html` element) causes
20
+ * geometry APIs like `getBoundingClientRect()` to report zoomed values while
21
+ * inline `top`/`left`/`--width` styles are interpreted in the unzoomed layout
22
+ * space. Normalize all rect-derived measurements by this factor so the
23
+ * popover is positioned and sized correctly.
24
+ */
25
+ const zoom = getElementCSSZoom(contentEl);
26
+ /**
27
+ * `innerWidth`/`innerHeight` are not affected by CSS `zoom`, so they must be
28
+ * scaled down to the same layout space as the normalized measurements above.
29
+ * Otherwise the popover would be clamped against a viewport that is larger
30
+ * than the space actually available to it.
31
+ */
32
+ const bodyWidth = doc.defaultView.innerWidth / zoom;
33
+ const bodyHeight = doc.defaultView.innerHeight / zoom;
20
34
  const referenceSizeEl = trigger || ev?.detail?.ionShadowTarget || ev?.target;
21
- const { contentWidth, contentHeight } = getPopoverDimensions(size, contentEl, referenceSizeEl);
35
+ const { contentWidth, contentHeight } = getPopoverDimensions(size, contentEl, referenceSizeEl, zoom);
22
36
  const defaultPosition = {
23
37
  top: bodyHeight / 2 - contentHeight / 2,
24
38
  left: bodyWidth / 2 - contentWidth / 2,
25
39
  originX: isRTL ? 'right' : 'left',
26
40
  originY: 'top',
27
41
  };
28
- const results = getPopoverPosition(isRTL, contentWidth, contentHeight, 0, 0, reference, side, align, defaultPosition, trigger, ev);
42
+ const results = getPopoverPosition(isRTL, contentWidth, contentHeight, 0, 0, reference, side, align, defaultPosition, trigger, ev, zoom);
29
43
  const padding = size === 'cover' ? 0 : POPOVER_MD_BODY_PADDING;
30
44
  // MD mode now applies safe-area insets (previously passed 0, ignoring all safe areas).
31
45
  // This is needed for Android edge-to-edge (API 36+) where system bars overlap content.
@@ -54,30 +54,81 @@ export const getSafeAreaInsets = (doc) => {
54
54
  }
55
55
  return insets;
56
56
  };
57
+ /**
58
+ * Largest difference from 1 that the `offsetWidth` based zoom detection below
59
+ * attributes to integer rounding rather than to an actual CSS `zoom`. The
60
+ * rounding error is at most half a pixel over the width of the popover, which
61
+ * is well under this threshold for any realistic popover size.
62
+ */
63
+ const ZOOM_ROUNDING_TOLERANCE = 0.01;
64
+ /**
65
+ * Returns the cumulative CSS `zoom` factor applied to an element.
66
+ *
67
+ * When a CSS `zoom` other than 1 is set on an ancestor (e.g. the `html`
68
+ * element, as recommended by the docs for dynamic font scaling on Chrome for
69
+ * Android), `getBoundingClientRect()`, `clientX`/`clientY` and other geometry
70
+ * APIs report values in the *zoomed* (visual) coordinate space, while inline
71
+ * `top`/`left`/`--width` styles we set are interpreted in the *unzoomed*
72
+ * (layout) space and re-scaled by the browser. Dividing the rect-derived
73
+ * values by this factor converts them back to layout space so the popover is
74
+ * positioned and sized correctly. Returns 1 when no zoom is applied.
75
+ */
76
+ export const getElementCSSZoom = (el) => {
77
+ if (!el) {
78
+ return 1;
79
+ }
80
+ /**
81
+ * `currentCSSZoom` exposes the exact effective zoom of an element
82
+ * (Chromium 128+). When available we use it directly.
83
+ */
84
+ const currentCSSZoom = el.currentCSSZoom;
85
+ if (typeof currentCSSZoom === 'number' && currentCSSZoom > 0) {
86
+ return currentCSSZoom;
87
+ }
88
+ /**
89
+ * Fallback for browsers without `currentCSSZoom`: compare the rendered
90
+ * (zoomed) width from `getBoundingClientRect()` against the layout width
91
+ * from `offsetWidth`, which is not affected by CSS `zoom`.
92
+ */
93
+ const { width } = el.getBoundingClientRect();
94
+ const { offsetWidth } = el;
95
+ if (offsetWidth > 0 && width > 0) {
96
+ const ratio = width / offsetWidth;
97
+ /**
98
+ * `offsetWidth` is rounded to an integer while the bounding rect is not,
99
+ * so the ratio is rarely exactly 1 even when no zoom is applied. Treat
100
+ * sub-pixel differences as "no zoom" so that unzoomed popovers are not
101
+ * shifted by the rounding error. A real zoom deviates far more, though
102
+ * the same rounding leaves the detected factor approximate.
103
+ */
104
+ return Math.abs(ratio - 1) < ZOOM_ROUNDING_TOLERANCE ? 1 : ratio;
105
+ }
106
+ return 1;
107
+ };
57
108
  /**
58
109
  * Returns the dimensions of the popover
59
110
  * arrow on `ios` mode. If arrow is disabled
60
111
  * returns (0, 0).
61
112
  */
62
- export const getArrowDimensions = (arrowEl) => {
113
+ export const getArrowDimensions = (arrowEl, zoom = 1) => {
63
114
  if (!arrowEl) {
64
115
  return { arrowWidth: 0, arrowHeight: 0 };
65
116
  }
66
117
  const { width, height } = arrowEl.getBoundingClientRect();
67
- return { arrowWidth: width, arrowHeight: height };
118
+ return { arrowWidth: width / zoom, arrowHeight: height / zoom };
68
119
  };
69
120
  /**
70
121
  * Returns the recommended dimensions of the popover
71
122
  * that takes into account whether or not the width
72
123
  * should match the trigger width.
73
124
  */
74
- export const getPopoverDimensions = (size, contentEl, triggerEl) => {
125
+ export const getPopoverDimensions = (size, contentEl, triggerEl, zoom = 1) => {
75
126
  const contentDimentions = contentEl.getBoundingClientRect();
76
- const contentHeight = contentDimentions.height;
77
- let contentWidth = contentDimentions.width;
127
+ const contentHeight = contentDimentions.height / zoom;
128
+ let contentWidth = contentDimentions.width / zoom;
78
129
  if (size === 'cover' && triggerEl) {
79
130
  const triggerDimensions = triggerEl.getBoundingClientRect();
80
- contentWidth = triggerDimensions.width;
131
+ contentWidth = triggerDimensions.width / zoom;
81
132
  }
82
133
  return {
83
134
  contentWidth,
@@ -419,7 +470,7 @@ export const configureKeyboardInteraction = (popoverEl) => {
419
470
  * the reference point, preferred side, alignment
420
471
  * and viewport dimensions.
421
472
  */
422
- export const getPopoverPosition = (isRTL, contentWidth, contentHeight, arrowWidth, arrowHeight, reference, side, align, defaultPosition, triggerEl, event) => {
473
+ export const getPopoverPosition = (isRTL, contentWidth, contentHeight, arrowWidth, arrowHeight, reference, side, align, defaultPosition, triggerEl, event, zoom = 1) => {
423
474
  let referenceCoordinates = {
424
475
  top: 0,
425
476
  left: 0,
@@ -438,8 +489,8 @@ export const getPopoverPosition = (isRTL, contentWidth, contentHeight, arrowWidt
438
489
  }
439
490
  const mouseEv = event;
440
491
  referenceCoordinates = {
441
- top: mouseEv.clientY,
442
- left: mouseEv.clientX,
492
+ top: mouseEv.clientY / zoom,
493
+ left: mouseEv.clientX / zoom,
443
494
  width: 1,
444
495
  height: 1,
445
496
  };
@@ -471,10 +522,10 @@ export const getPopoverPosition = (isRTL, contentWidth, contentHeight, arrowWidt
471
522
  }
472
523
  const triggerBoundingBox = actualTriggerEl.getBoundingClientRect();
473
524
  referenceCoordinates = {
474
- top: triggerBoundingBox.top,
475
- left: triggerBoundingBox.left,
476
- width: triggerBoundingBox.width,
477
- height: triggerBoundingBox.height,
525
+ top: triggerBoundingBox.top / zoom,
526
+ left: triggerBoundingBox.left / zoom,
527
+ width: triggerBoundingBox.width / zoom,
528
+ height: triggerBoundingBox.height / zoom,
478
529
  };
479
530
  break;
480
531
  }
@@ -204,7 +204,7 @@ button {
204
204
 
205
205
  .select-text {
206
206
  flex: 1;
207
- min-width: 16px;
207
+ min-width: 2ch;
208
208
  font-size: inherit;
209
209
  text-overflow: ellipsis;
210
210
  white-space: inherit;
@@ -1,9 +1,9 @@
1
1
  /*!
2
2
  * (C) Ionic http://ionicframework.com - MIT License
3
3
  */
4
- import { Build, Host, h, forceUpdate } from "@stencil/core";
4
+ import { Build, Host, h, forceUpdate, } from "@stencil/core";
5
5
  import { ENABLE_HTML_CONTENT_DEFAULT } from "../../utils/config";
6
- import { compareOptions, createNotchController, createStartContainerController, isOptionSelected, checkInvalidState, } from "../../utils/forms/index";
6
+ import { compareOptions, createClickController, createNotchController, createStartContainerController, getSlottedClickContent, isOptionSelected, checkInvalidState, } from "../../utils/forms/index";
7
7
  import { focusVisibleElement, renderHiddenInput, inheritAttributes } from "../../utils/helpers";
8
8
  import { printIonWarning } from "../../utils/logging/index";
9
9
  import { actionSheetController, alertController, popoverController, modalController } from "../../utils/overlays";
@@ -109,41 +109,21 @@ export class Select {
109
109
  */
110
110
  this.required = false;
111
111
  this.onClick = (ev) => {
112
- const target = ev.target;
113
- const closestSlot = target.closest('[slot="start"], [slot="end"]');
114
- if (target === this.el || closestSlot === null) {
115
- this.setFocus();
116
- this.open(ev);
117
- }
118
- else {
119
- /**
120
- * Prevent clicks to the start/end slots from opening the select.
121
- * We ensure the target isn't this element in case the select is slotted
122
- * in, for example, an item. This would prevent the select from ever
123
- * being opened since the element itself has slot="start"/"end".
124
- *
125
- * Clicking a slotted element also causes a click
126
- * on the <label> element (since it wraps the slots).
127
- * Clicking <label> dispatches another click event on
128
- * the native form control that then bubbles up to this
129
- * listener. This additional event targets the host
130
- * element, so the select overlay is opened.
131
- *
132
- * When the slotted elements are clicked (and therefore
133
- * the ancestor <label> element) we want to prevent the label
134
- * from dispatching another click event.
135
- *
136
- * Do not call stopPropagation() because this will cause
137
- * click handlers on the slotted elements to never fire in React.
138
- * When developers do onClick in React a native "click" listener
139
- * is added on the root element, not the slotted element. When that
140
- * native click listener fires, React then dispatches the synthetic
141
- * click event on the slotted element. However, if stopPropagation
142
- * is called then the native click event will never bubble up
143
- * to the root element.
144
- */
145
- ev.preventDefault();
112
+ const slotted = getSlottedClickContent(ev, this.el);
113
+ /**
114
+ * Interactive slotted content, such as a button or a checkbox, handles its
115
+ * own click, so it should not open the select as well. Any other slotted
116
+ * content is decorative and behaves the same as clicking the select
117
+ * itself.
118
+ */
119
+ if (slotted !== null) {
120
+ const interactive = ev.target.closest(INTERACTIVE_SLOTTED_CONTENT);
121
+ if (interactive !== null && slotted.contains(interactive)) {
122
+ return;
123
+ }
146
124
  }
125
+ this.setFocus();
126
+ this.open(ev);
147
127
  };
148
128
  this.onFocus = () => {
149
129
  this.hasFocus = true;
@@ -214,6 +194,7 @@ export class Select {
214
194
  return Build.isBrowser && getIonMode(this) === 'md' && this.fill === 'outline';
215
195
  });
216
196
  this.startContainerController.calculateStartContainerWidth();
197
+ this.clickController = createClickController(el);
217
198
  this.updateOverlayOptions();
218
199
  this.emitStyle();
219
200
  this.mutationO = watchForOptions(this.el, 'ion-select-option', async () => {
@@ -750,6 +731,18 @@ export class Select {
750
731
  };
751
732
  this.ionStyle.emit(style);
752
733
  }
734
+ /**
735
+ * The label wrapping the slots has no `for` attribute, so the browser
736
+ * forwards a click on slotted content to the label's first labelable
737
+ * descendant, the internal button. That forwarded click bubbles back out of
738
+ * the shadow root targeting the host, where it would be emitted a second
739
+ * time and open the select. The controller swallows it during the capture
740
+ * phase, leaving the click on the slotted content itself alone so slotted
741
+ * links, checkboxes and buttons keep their default behavior.
742
+ */
743
+ onClickCapture(ev) {
744
+ this.clickController?.handleClickCapture(ev);
745
+ }
753
746
  renderLabel() {
754
747
  const { label } = this;
755
748
  return (h("div", { class: {
@@ -947,7 +940,7 @@ export class Select {
947
940
  const hasOutlineFill = mode === 'md' && fill === 'outline';
948
941
  renderHiddenInput(true, el, name, parseValue(value), disabled);
949
942
  const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || isExpanded));
950
- return (h(Host, { key: 'b2f161e3706e139e61440cd13e162714b1b75d72', onClick: this.onClick, class: createColorClasses(this.color, {
943
+ return (h(Host, { key: '31585557ac49c439939b5a084867f5039dc2f1ce', onClick: this.onClick, class: createColorClasses(this.color, {
951
944
  [mode]: true,
952
945
  'in-item': inItem,
953
946
  'in-item-color': hostContext('ion-item.ion-color', el),
@@ -965,7 +958,7 @@ export class Select {
965
958
  [`select-justify-${justify}`]: justifyEnabled,
966
959
  [`select-shape-${shape}`]: shape !== undefined,
967
960
  [`select-label-placement-${labelPlacement}`]: true,
968
- }) }, h("label", { key: '944a2eb468154a21260d181fdaf67828a71eb902', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick, part: "wrapper" }, hasOutlineFill && this.renderOutlineContainer(), h("div", { key: '927200c53548b1bb4f52d6a167605b724a7b7d0d', class: "select-start", part: "start", ref: (el) => (this.startContainerEl = el) }, h("slot", { key: '6e14b95e9b95c116b16744d630600e90977782bc', name: "start" })), h("div", { key: '8451ed4300ac005963075be36a04ea8763bc0fdd', class: "select-control", part: "control" }, this.renderLabel(), h("div", { key: '207e7b63f3224a4870579365ac992da6784fb31f', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox(), !hasFloatingOrStackedLabel && this.renderSelectIcon())), h("div", { key: '5c17367d488db4d570f31b25e33560efa9011500', class: "select-end", part: "end" }, hasFloatingOrStackedLabel && this.renderSelectIcon(), h("slot", { key: '21fd8c0d9bee8cffef9ef6984cacd31e8f38211c', name: "end" })), shouldRenderHighlight && h("div", { key: '1fff767db9a1ec07b274ef65ff7ae8fb976e6ad2', class: "select-highlight" })), this.renderBottomContent()));
961
+ }) }, h("label", { key: '368f5f0c77550be6a743752dd1acbfe9915f0a3d', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick, part: "wrapper" }, hasOutlineFill && this.renderOutlineContainer(), h("div", { key: '2e9039eaa15f398ebe54808ff659db89d3621681', class: "select-start", part: "start", ref: (el) => (this.startContainerEl = el) }, h("slot", { key: 'b83e362f89bd8cbc564ad7122778e3a0f08be66d', name: "start" })), h("div", { key: 'f55ac9fc3bbd9a4a3819a101a3780fc02ae8a8e0', class: "select-control", part: "control" }, this.renderLabel(), h("div", { key: 'e32984e57cda5cf341af8e354a2aef5a114827c0', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox(), !hasFloatingOrStackedLabel && this.renderSelectIcon())), h("div", { key: 'fc4cb7c392c46129afe709d9557ad9a10d72b564', class: "select-end", part: "end" }, hasFloatingOrStackedLabel && this.renderSelectIcon(), h("slot", { key: '6d65c92cdafe985a769fb3b41a58625077803eef', name: "end" })), shouldRenderHighlight && h("div", { key: '9a912c64d7cd77f074a069d126cd0bada1b71eed', class: "select-highlight" })), this.renderBottomContent()));
969
962
  }
970
963
  static get is() { return "ion-select"; }
971
964
  static get encapsulation() { return "shadow"; }
@@ -1611,6 +1604,15 @@ export class Select {
1611
1604
  "methodName": "styleChanged"
1612
1605
  }];
1613
1606
  }
1607
+ static get listeners() {
1608
+ return [{
1609
+ "name": "click",
1610
+ "method": "onClickCapture",
1611
+ "target": undefined,
1612
+ "capture": true,
1613
+ "passive": false
1614
+ }];
1615
+ }
1614
1616
  }
1615
1617
  const getOptionValue = (el) => {
1616
1618
  const value = el.value;
@@ -1851,3 +1853,30 @@ const extractOptionContent = (option, customHTMLEnabled) => {
1851
1853
  };
1852
1854
  let selectIds = 0;
1853
1855
  const OPTION_CLASS = 'select-interface-option';
1856
+ /**
1857
+ * Slotted content that handles its own click, so clicking it should not also
1858
+ * open the select.
1859
+ *
1860
+ * This deliberately does not reuse `focusableQueryString`. That selector
1861
+ * answers whether an element can take focus right now, which is a different
1862
+ * question: an ion-radio outside a radio group carries tabindex="-1" from the
1863
+ * group's roving tabindex, and disabled controls are excluded, yet both still
1864
+ * handle their own clicks.
1865
+ */
1866
+ const INTERACTIVE_SLOTTED_CONTENT = [
1867
+ 'a[href]',
1868
+ 'button',
1869
+ 'input[type="checkbox"]',
1870
+ 'input[type="radio"]',
1871
+ 'ion-button',
1872
+ 'ion-checkbox',
1873
+ 'ion-radio',
1874
+ 'ion-toggle',
1875
+ '[tabindex]:not([tabindex^="-"])',
1876
+ /**
1877
+ * Covers the remaining Ionic controls. The tags above are still listed
1878
+ * because ion-checkbox and ion-radio only carry this class when they are
1879
+ * outside an item, so a select inside an item would lose the match.
1880
+ */
1881
+ '.ion-focusable',
1882
+ ].join(', ');
@@ -204,7 +204,7 @@ button {
204
204
 
205
205
  .select-text {
206
206
  flex: 1;
207
- min-width: 16px;
207
+ min-width: 2ch;
208
208
  font-size: inherit;
209
209
  text-overflow: ellipsis;
210
210
  white-space: inherit;
@@ -155,6 +155,12 @@
155
155
  position: relative;
156
156
  flex: 1;
157
157
  width: 100%;
158
+ /**
159
+ * The textarea keeps a minimum width so that the value stays visible
160
+ * when a long label or wide slotted content would otherwise shrink
161
+ * it to nothing.
162
+ */
163
+ min-width: 2ch;
158
164
  max-width: 100%;
159
165
  max-height: 100%;
160
166
  border: 0;
@@ -292,7 +298,15 @@
292
298
 
293
299
  .native-wrapper {
294
300
  display: grid;
295
- min-width: inherit;
301
+ /**
302
+ * The wrapper has to carry the same minimum width as the textarea it holds.
303
+ * It is the flex item that competes with the label and the slots for space,
304
+ * so without it the textarea keeps its width but overflows the field.
305
+ *
306
+ * The minimum cannot be inherited because .textarea-control sets
307
+ * `min-width: 0` so that the slots keep their size.
308
+ */
309
+ min-width: 2ch;
296
310
  max-width: inherit;
297
311
  min-height: inherit;
298
312
  max-height: inherit;