@ionic/core 7.4.3-dev.11696365694.156f41d3 → 7.4.3-dev.11699471215.1cfbc6e9

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 (369) hide show
  1. package/components/alert.js +8 -0
  2. package/components/data.js +96 -22
  3. package/components/haptic.js +1 -0
  4. package/components/ion-datetime-button.js +4 -4
  5. package/components/ion-datetime.js +3 -3
  6. package/components/ion-header.js +1 -1
  7. package/components/ion-nav.js +1 -0
  8. package/components/ion-router.js +3 -0
  9. package/components/ion-select.js +1 -1
  10. package/components/ion-toast.js +150 -13
  11. package/components/ios.transition.js +1 -0
  12. package/components/overlays.js +1 -0
  13. package/dist/cjs/{app-globals-56164d1a.js → app-globals-84b6a756.js} +1 -1
  14. package/dist/cjs/{button-active-32f15660.js → button-active-f2147e85.js} +2 -2
  15. package/dist/cjs/{data-db832785.js → data-c8d21093.js} +96 -22
  16. package/dist/cjs/{haptic-c5f6b4d5.js → haptic-678abc9f.js} +1 -0
  17. package/dist/cjs/{index-6f887430.js → index-14a4821e.js} +47 -6
  18. package/dist/cjs/{index-5121bb90.js → index-97a3eade.js} +1 -1
  19. package/dist/cjs/{index-b183138a.js → index-e760ab42.js} +3 -3
  20. package/dist/cjs/index.cjs.js +7 -7
  21. package/dist/cjs/ion-accordion_2.cjs.entry.js +2 -2
  22. package/dist/cjs/ion-action-sheet.cjs.entry.js +5 -5
  23. package/dist/cjs/ion-alert.cjs.entry.js +13 -5
  24. package/dist/cjs/ion-app_8.cjs.entry.js +5 -5
  25. package/dist/cjs/ion-avatar_3.cjs.entry.js +2 -2
  26. package/dist/cjs/ion-back-button.cjs.entry.js +2 -2
  27. package/dist/cjs/ion-backdrop.cjs.entry.js +2 -2
  28. package/dist/cjs/ion-breadcrumb_2.cjs.entry.js +2 -2
  29. package/dist/cjs/ion-button_2.cjs.entry.js +2 -2
  30. package/dist/cjs/ion-card_5.cjs.entry.js +2 -2
  31. package/dist/cjs/ion-checkbox.cjs.entry.js +2 -2
  32. package/dist/cjs/ion-chip.cjs.entry.js +2 -2
  33. package/dist/cjs/ion-col_3.cjs.entry.js +2 -2
  34. package/dist/cjs/ion-datetime-button.cjs.entry.js +6 -6
  35. package/dist/cjs/ion-datetime_3.cjs.entry.js +7 -7
  36. package/dist/cjs/ion-fab_3.cjs.entry.js +2 -2
  37. package/dist/cjs/ion-img.cjs.entry.js +2 -2
  38. package/dist/cjs/ion-infinite-scroll_2.cjs.entry.js +2 -2
  39. package/dist/cjs/ion-input.cjs.entry.js +2 -2
  40. package/dist/cjs/ion-item-option_3.cjs.entry.js +2 -2
  41. package/dist/cjs/ion-item_8.cjs.entry.js +2 -2
  42. package/dist/cjs/ion-loading.cjs.entry.js +3 -3
  43. package/dist/cjs/ion-menu_3.cjs.entry.js +4 -4
  44. package/dist/cjs/ion-modal.cjs.entry.js +4 -4
  45. package/dist/cjs/ion-nav_2.cjs.entry.js +4 -3
  46. package/dist/cjs/ion-picker-column-internal.cjs.entry.js +3 -3
  47. package/dist/cjs/ion-picker-internal.cjs.entry.js +1 -1
  48. package/dist/cjs/ion-popover.cjs.entry.js +4 -4
  49. package/dist/cjs/ion-progress-bar.cjs.entry.js +2 -2
  50. package/dist/cjs/ion-radio_2.cjs.entry.js +2 -2
  51. package/dist/cjs/ion-range.cjs.entry.js +2 -2
  52. package/dist/cjs/ion-refresher_2.cjs.entry.js +3 -3
  53. package/dist/cjs/ion-reorder_2.cjs.entry.js +3 -3
  54. package/dist/cjs/ion-ripple-effect.cjs.entry.js +2 -2
  55. package/dist/cjs/ion-route_4.cjs.entry.js +5 -2
  56. package/dist/cjs/ion-searchbar.cjs.entry.js +2 -2
  57. package/dist/cjs/ion-segment_2.cjs.entry.js +2 -2
  58. package/dist/cjs/ion-select_3.cjs.entry.js +4 -4
  59. package/dist/cjs/ion-spinner.cjs.entry.js +2 -2
  60. package/dist/cjs/ion-split-pane.cjs.entry.js +2 -2
  61. package/dist/cjs/ion-tab-bar_2.cjs.entry.js +2 -2
  62. package/dist/cjs/ion-tab_2.cjs.entry.js +1 -1
  63. package/dist/cjs/ion-text.cjs.entry.js +2 -2
  64. package/dist/cjs/ion-textarea.cjs.entry.js +2 -2
  65. package/dist/cjs/ion-toast.cjs.entry.js +168 -33
  66. package/dist/cjs/ion-toggle.cjs.entry.js +3 -3
  67. package/dist/cjs/{ionic-global-14a0604b.js → ionic-global-a71608df.js} +1 -1
  68. package/dist/cjs/ionic.cjs.js +5 -5
  69. package/dist/cjs/{ios.transition-4b93903d.js → ios.transition-1fec34e9.js} +3 -2
  70. package/dist/cjs/loader.cjs.js +4 -4
  71. package/dist/cjs/{md.transition-79f3a215.js → md.transition-cdc3f16f.js} +2 -2
  72. package/dist/cjs/{overlays-d3a13e61.js → overlays-9cab437c.js} +2 -1
  73. package/dist/cjs/{status-tap-e2e45ff8.js → status-tap-8c22e017.js} +1 -1
  74. package/dist/collection/collection-manifest.json +2 -2
  75. package/dist/collection/components/alert/alert.js +8 -0
  76. package/dist/collection/components/alert/test/a11y/alert.e2e.js +11 -0
  77. package/dist/collection/components/datetime/datetime.js +12 -6
  78. package/dist/collection/components/datetime/test/hour-cycle/datetime.e2e.js +14 -0
  79. package/dist/collection/components/datetime/utils/data.js +33 -7
  80. package/dist/collection/components/datetime/utils/format.js +27 -10
  81. package/dist/collection/components/datetime/utils/helpers.js +37 -5
  82. package/dist/collection/components/datetime-button/datetime-button.js +4 -4
  83. package/dist/collection/components/header/header.ios.css +0 -18
  84. package/dist/collection/components/nav/nav.js +1 -0
  85. package/dist/collection/components/router/router.js +2 -0
  86. package/dist/collection/components/router/utils/path.js +1 -0
  87. package/dist/collection/components/select/select.js +1 -1
  88. package/dist/collection/components/toast/animations/ios.enter.js +2 -3
  89. package/dist/collection/components/toast/animations/ios.leave.js +2 -3
  90. package/dist/collection/components/toast/animations/md.enter.js +2 -3
  91. package/dist/collection/components/toast/animations/utils.js +85 -0
  92. package/dist/collection/components/toast/test/position-anchor/toast.e2e.js +45 -0
  93. package/dist/collection/components/toast/toast.js +91 -9
  94. package/dist/collection/utils/native/haptic.js +1 -0
  95. package/dist/collection/utils/overlays.js +1 -0
  96. package/dist/collection/utils/transition/ios.transition.js +1 -0
  97. package/dist/docs.json +75 -12
  98. package/dist/esm/{app-globals-8ae762aa.js → app-globals-df292a32.js} +1 -1
  99. package/dist/esm/{button-active-513e9fff.js → button-active-3dd473a1.js} +2 -2
  100. package/dist/esm/{data-009dbf15.js → data-44d9e816.js} +96 -22
  101. package/dist/esm/{haptic-6447af60.js → haptic-1243b917.js} +1 -0
  102. package/dist/esm/{index-61bddc90.js → index-3d6aefa2.js} +1 -1
  103. package/dist/esm/{index-87684bba.js → index-9f5eacab.js} +3 -3
  104. package/dist/esm/{index-2d388930.js → index-cb894020.js} +47 -6
  105. package/dist/esm/index.js +7 -7
  106. package/dist/esm/ion-accordion_2.entry.js +2 -2
  107. package/dist/esm/ion-action-sheet.entry.js +5 -5
  108. package/dist/esm/ion-alert.entry.js +13 -5
  109. package/dist/esm/ion-app_8.entry.js +5 -5
  110. package/dist/esm/ion-avatar_3.entry.js +2 -2
  111. package/dist/esm/ion-back-button.entry.js +2 -2
  112. package/dist/esm/ion-backdrop.entry.js +2 -2
  113. package/dist/esm/ion-breadcrumb_2.entry.js +2 -2
  114. package/dist/esm/ion-button_2.entry.js +2 -2
  115. package/dist/esm/ion-card_5.entry.js +2 -2
  116. package/dist/esm/ion-checkbox.entry.js +2 -2
  117. package/dist/esm/ion-chip.entry.js +2 -2
  118. package/dist/esm/ion-col_3.entry.js +2 -2
  119. package/dist/esm/ion-datetime-button.entry.js +6 -6
  120. package/dist/esm/ion-datetime_3.entry.js +7 -7
  121. package/dist/esm/ion-fab_3.entry.js +2 -2
  122. package/dist/esm/ion-img.entry.js +2 -2
  123. package/dist/esm/ion-infinite-scroll_2.entry.js +2 -2
  124. package/dist/esm/ion-input.entry.js +2 -2
  125. package/dist/esm/ion-item-option_3.entry.js +2 -2
  126. package/dist/esm/ion-item_8.entry.js +2 -2
  127. package/dist/esm/ion-loading.entry.js +3 -3
  128. package/dist/esm/ion-menu_3.entry.js +4 -4
  129. package/dist/esm/ion-modal.entry.js +4 -4
  130. package/dist/esm/ion-nav_2.entry.js +4 -3
  131. package/dist/esm/ion-picker-column-internal.entry.js +3 -3
  132. package/dist/esm/ion-picker-internal.entry.js +1 -1
  133. package/dist/esm/ion-popover.entry.js +4 -4
  134. package/dist/esm/ion-progress-bar.entry.js +2 -2
  135. package/dist/esm/ion-radio_2.entry.js +2 -2
  136. package/dist/esm/ion-range.entry.js +2 -2
  137. package/dist/esm/ion-refresher_2.entry.js +3 -3
  138. package/dist/esm/ion-reorder_2.entry.js +3 -3
  139. package/dist/esm/ion-ripple-effect.entry.js +2 -2
  140. package/dist/esm/ion-route_4.entry.js +5 -2
  141. package/dist/esm/ion-searchbar.entry.js +2 -2
  142. package/dist/esm/ion-segment_2.entry.js +2 -2
  143. package/dist/esm/ion-select_3.entry.js +4 -4
  144. package/dist/esm/ion-spinner.entry.js +2 -2
  145. package/dist/esm/ion-split-pane.entry.js +2 -2
  146. package/dist/esm/ion-tab-bar_2.entry.js +2 -2
  147. package/dist/esm/ion-tab_2.entry.js +1 -1
  148. package/dist/esm/ion-text.entry.js +2 -2
  149. package/dist/esm/ion-textarea.entry.js +2 -2
  150. package/dist/esm/ion-toast.entry.js +152 -17
  151. package/dist/esm/ion-toggle.entry.js +3 -3
  152. package/dist/esm/{ionic-global-b3fc28dd.js → ionic-global-63a8d8c9.js} +1 -1
  153. package/dist/esm/ionic.js +6 -6
  154. package/dist/esm/{ios.transition-81e1aed6.js → ios.transition-8ad209ea.js} +3 -2
  155. package/dist/esm/loader.js +5 -5
  156. package/dist/esm/{md.transition-5becd8b5.js → md.transition-43193ea7.js} +2 -2
  157. package/dist/esm/{overlays-8fc6656c.js → overlays-753933fc.js} +2 -1
  158. package/dist/esm/{status-tap-c5af0dba.js → status-tap-73e982b6.js} +1 -1
  159. package/dist/esm-es5/app-globals-df292a32.js +4 -0
  160. package/dist/esm-es5/{button-active-513e9fff.js → button-active-3dd473a1.js} +1 -1
  161. package/dist/esm-es5/data-44d9e816.js +4 -0
  162. package/dist/esm-es5/{index-61bddc90.js → index-3d6aefa2.js} +1 -1
  163. package/dist/esm-es5/{index-87684bba.js → index-9f5eacab.js} +1 -1
  164. package/dist/esm-es5/index.js +1 -1
  165. package/dist/esm-es5/ion-accordion_2.entry.js +1 -1
  166. package/dist/esm-es5/ion-action-sheet.entry.js +1 -1
  167. package/dist/esm-es5/ion-alert.entry.js +1 -1
  168. package/dist/esm-es5/ion-app_8.entry.js +1 -1
  169. package/dist/esm-es5/ion-avatar_3.entry.js +1 -1
  170. package/dist/esm-es5/ion-back-button.entry.js +1 -1
  171. package/dist/esm-es5/ion-backdrop.entry.js +1 -1
  172. package/dist/esm-es5/ion-breadcrumb_2.entry.js +1 -1
  173. package/dist/esm-es5/ion-button_2.entry.js +1 -1
  174. package/dist/esm-es5/ion-card_5.entry.js +1 -1
  175. package/dist/esm-es5/ion-checkbox.entry.js +1 -1
  176. package/dist/esm-es5/ion-chip.entry.js +1 -1
  177. package/dist/esm-es5/ion-col_3.entry.js +1 -1
  178. package/dist/esm-es5/ion-datetime-button.entry.js +1 -1
  179. package/dist/esm-es5/ion-datetime_3.entry.js +1 -1
  180. package/dist/esm-es5/ion-fab_3.entry.js +1 -1
  181. package/dist/esm-es5/ion-img.entry.js +1 -1
  182. package/dist/esm-es5/ion-infinite-scroll_2.entry.js +1 -1
  183. package/dist/esm-es5/ion-input.entry.js +1 -1
  184. package/dist/esm-es5/ion-item-option_3.entry.js +1 -1
  185. package/dist/esm-es5/ion-item_8.entry.js +1 -1
  186. package/dist/esm-es5/ion-loading.entry.js +1 -1
  187. package/dist/esm-es5/ion-menu_3.entry.js +1 -1
  188. package/dist/esm-es5/ion-modal.entry.js +1 -1
  189. package/dist/esm-es5/ion-nav_2.entry.js +1 -1
  190. package/dist/esm-es5/ion-picker-column-internal.entry.js +1 -1
  191. package/dist/esm-es5/ion-picker-internal.entry.js +1 -1
  192. package/dist/esm-es5/ion-popover.entry.js +1 -1
  193. package/dist/esm-es5/ion-progress-bar.entry.js +1 -1
  194. package/dist/esm-es5/ion-radio_2.entry.js +1 -1
  195. package/dist/esm-es5/ion-range.entry.js +1 -1
  196. package/dist/esm-es5/ion-refresher_2.entry.js +1 -1
  197. package/dist/esm-es5/ion-reorder_2.entry.js +1 -1
  198. package/dist/esm-es5/ion-ripple-effect.entry.js +1 -1
  199. package/dist/esm-es5/ion-route_4.entry.js +1 -1
  200. package/dist/esm-es5/ion-searchbar.entry.js +1 -1
  201. package/dist/esm-es5/ion-segment_2.entry.js +1 -1
  202. package/dist/esm-es5/ion-select_3.entry.js +1 -1
  203. package/dist/esm-es5/ion-spinner.entry.js +1 -1
  204. package/dist/esm-es5/ion-split-pane.entry.js +1 -1
  205. package/dist/esm-es5/ion-tab-bar_2.entry.js +1 -1
  206. package/dist/esm-es5/ion-tab_2.entry.js +1 -1
  207. package/dist/esm-es5/ion-text.entry.js +1 -1
  208. package/dist/esm-es5/ion-textarea.entry.js +1 -1
  209. package/dist/esm-es5/ion-toast.entry.js +1 -1
  210. package/dist/esm-es5/ion-toggle.entry.js +1 -1
  211. package/dist/esm-es5/{ionic-global-b3fc28dd.js → ionic-global-63a8d8c9.js} +1 -1
  212. package/dist/esm-es5/ionic.js +1 -1
  213. package/dist/esm-es5/{ios.transition-81e1aed6.js → ios.transition-8ad209ea.js} +1 -1
  214. package/dist/esm-es5/loader.js +1 -1
  215. package/dist/esm-es5/{md.transition-5becd8b5.js → md.transition-43193ea7.js} +1 -1
  216. package/dist/esm-es5/{overlays-8fc6656c.js → overlays-753933fc.js} +1 -1
  217. package/dist/esm-es5/{status-tap-c5af0dba.js → status-tap-73e982b6.js} +1 -1
  218. package/dist/html.html-data.json +11 -1
  219. package/dist/ionic/index.esm.js +1 -1
  220. package/dist/ionic/ionic.esm.js +1 -1
  221. package/dist/ionic/ionic.js +1 -1
  222. package/dist/ionic/{p-5c8c9748.system.entry.js → p-007168b8.system.entry.js} +1 -1
  223. package/dist/ionic/{p-ce7a651e.js → p-00cf2d6c.js} +1 -1
  224. package/dist/ionic/{p-6dfeeadf.entry.js → p-018ad59f.entry.js} +1 -1
  225. package/dist/ionic/{p-e89abe38.system.entry.js → p-037e2738.system.entry.js} +1 -1
  226. package/dist/ionic/{p-116641fe.entry.js → p-0793ebfd.entry.js} +1 -1
  227. package/dist/ionic/{p-972763df.js → p-0d198537.js} +1 -1
  228. package/dist/ionic/{p-37456282.system.entry.js → p-0e024f14.system.entry.js} +1 -1
  229. package/dist/ionic/{p-60838ce3.system.entry.js → p-10fcb3a3.system.entry.js} +1 -1
  230. package/dist/ionic/p-11eedecb.system.entry.js +4 -0
  231. package/dist/ionic/{p-605b085a.entry.js → p-138e06de.entry.js} +1 -1
  232. package/dist/ionic/p-17240d90.js +4 -0
  233. package/dist/ionic/{p-7e9e16bf.system.entry.js → p-17dd92fe.system.entry.js} +1 -1
  234. package/dist/ionic/{p-b95fd3c6.entry.js → p-26c9b9ba.entry.js} +1 -1
  235. package/dist/ionic/{p-6ca0e4b2.system.entry.js → p-28678af4.system.entry.js} +1 -1
  236. package/dist/ionic/{p-de676d36.system.entry.js → p-2dc6526e.system.entry.js} +1 -1
  237. package/dist/ionic/{p-c4d08d6d.system.entry.js → p-37fc0d22.system.entry.js} +1 -1
  238. package/dist/ionic/{p-42a7b112.entry.js → p-3bf7c0dc.entry.js} +1 -1
  239. package/dist/ionic/{p-e57a38f3.entry.js → p-3db27dec.entry.js} +1 -1
  240. package/dist/ionic/{p-83b7bbf9.entry.js → p-3dce88bf.entry.js} +1 -1
  241. package/dist/ionic/{p-ce24ddd7.system.entry.js → p-3e6b0330.system.entry.js} +1 -1
  242. package/dist/ionic/{p-3ae2faf0.entry.js → p-414a1506.entry.js} +1 -1
  243. package/dist/ionic/{p-13a91505.entry.js → p-454048da.entry.js} +1 -1
  244. package/dist/ionic/{p-c7fca267.entry.js → p-45e527e7.entry.js} +1 -1
  245. package/dist/ionic/{p-13ce151b.entry.js → p-469d6a98.entry.js} +1 -1
  246. package/dist/ionic/{p-a6d8476b.system.entry.js → p-47242aad.system.entry.js} +1 -1
  247. package/dist/ionic/p-4965f2d7.entry.js +4 -0
  248. package/dist/ionic/{p-88ad9cb6.entry.js → p-4c20879c.entry.js} +1 -1
  249. package/dist/ionic/{p-8fdd4a2f.system.js → p-4d6ea5f9.system.js} +1 -1
  250. package/dist/ionic/{p-08c5b9f4.system.entry.js → p-4e1b00c5.system.entry.js} +1 -1
  251. package/dist/ionic/{p-33630008.system.entry.js → p-4e76e29a.system.entry.js} +1 -1
  252. package/dist/ionic/{p-55b99166.entry.js → p-50327060.entry.js} +1 -1
  253. package/dist/ionic/{p-e24630f9.entry.js → p-50d83224.entry.js} +1 -1
  254. package/dist/ionic/p-534a1cbc.system.js +4 -0
  255. package/dist/ionic/{p-5e2dc8e0.js → p-54b06917.js} +1 -1
  256. package/dist/ionic/{p-4eab1bb4.entry.js → p-57743e20.entry.js} +1 -1
  257. package/dist/ionic/{p-d4cea1ba.system.js → p-57c5eca2.system.js} +1 -1
  258. package/dist/ionic/p-5aa99fb8.entry.js +4 -0
  259. package/dist/ionic/{p-ec102360.system.js → p-5c24c115.system.js} +1 -1
  260. package/dist/ionic/{p-47cb95be.system.entry.js → p-5f13271c.system.entry.js} +1 -1
  261. package/dist/ionic/{p-cd675d89.system.entry.js → p-5fd0a13e.system.entry.js} +1 -1
  262. package/dist/ionic/p-6641d7fa.js +4 -0
  263. package/dist/ionic/{p-8b79baf0.entry.js → p-68b405cc.entry.js} +1 -1
  264. package/dist/ionic/{p-bf9b1560.entry.js → p-6a49b57e.entry.js} +1 -1
  265. package/dist/ionic/{p-6522a762.system.entry.js → p-6c7d61b9.system.entry.js} +1 -1
  266. package/dist/ionic/{p-ebaeeee8.entry.js → p-6ce891b2.entry.js} +1 -1
  267. package/dist/ionic/{p-ee6d9730.entry.js → p-6d22c339.entry.js} +1 -1
  268. package/dist/ionic/{p-6bc9c436.system.entry.js → p-6f13b971.system.entry.js} +1 -1
  269. package/dist/ionic/{p-626f7142.system.entry.js → p-6f3099b6.system.entry.js} +1 -1
  270. package/dist/ionic/p-73eba881.system.js +4 -0
  271. package/dist/ionic/p-73f7e775.js +4 -0
  272. package/dist/ionic/{p-39715fcf.entry.js → p-7887ac7a.entry.js} +1 -1
  273. package/dist/ionic/{p-6b7e74ba.js → p-7a590a28.js} +1 -1
  274. package/dist/ionic/p-7b4e392c.js +4 -0
  275. package/dist/ionic/{p-de0f1af2.system.entry.js → p-7fd0f045.system.entry.js} +1 -1
  276. package/dist/ionic/{p-7a3caa4e.system.js → p-82c72668.system.js} +1 -1
  277. package/dist/ionic/{p-62428e04.system.entry.js → p-84549737.system.entry.js} +1 -1
  278. package/dist/ionic/{p-be321bb6.system.entry.js → p-8957b1de.system.entry.js} +1 -1
  279. package/dist/ionic/{p-6ba07931.system.entry.js → p-89e3d112.system.entry.js} +1 -1
  280. package/dist/ionic/{p-5e43aa8b.js → p-8a289322.js} +1 -1
  281. package/dist/ionic/{p-b5637aeb.system.entry.js → p-8f245bb0.system.entry.js} +1 -1
  282. package/dist/ionic/{p-70ab8b73.js → p-903c36fe.js} +1 -1
  283. package/dist/ionic/{p-04ef1ba6.entry.js → p-9201a4d3.entry.js} +1 -1
  284. package/dist/ionic/{p-a1a2dd4d.entry.js → p-92d72ad8.entry.js} +1 -1
  285. package/dist/ionic/{p-63a73b69.system.entry.js → p-9736406a.system.entry.js} +1 -1
  286. package/dist/ionic/{p-4616f20a.system.entry.js → p-98b108e2.system.entry.js} +1 -1
  287. package/dist/ionic/{p-03e2e541.system.entry.js → p-9a6f6789.system.entry.js} +1 -1
  288. package/dist/ionic/{p-3730f493.entry.js → p-9b796813.entry.js} +1 -1
  289. package/dist/ionic/{p-270aa06b.entry.js → p-9bd70bd2.entry.js} +1 -1
  290. package/dist/ionic/p-9e5bdf1a.entry.js +4 -0
  291. package/dist/ionic/{p-700a2cb1.system.entry.js → p-9e91c83f.system.entry.js} +1 -1
  292. package/dist/ionic/{p-93616477.system.js → p-9f9efb31.system.js} +1 -1
  293. package/dist/ionic/{p-cc3aa152.entry.js → p-a1d7f4ef.entry.js} +1 -1
  294. package/dist/ionic/{p-65a4c12f.system.entry.js → p-a39e9a0b.system.entry.js} +1 -1
  295. package/dist/ionic/{p-f920f5ca.entry.js → p-a3ea02d0.entry.js} +1 -1
  296. package/dist/ionic/{p-abf426cd.system.entry.js → p-a4e95028.system.entry.js} +1 -1
  297. package/dist/ionic/{p-ea88031d.entry.js → p-a51f5932.entry.js} +1 -1
  298. package/dist/ionic/{p-4912b933.entry.js → p-a7361c85.entry.js} +1 -1
  299. package/dist/ionic/{p-486b567b.system.entry.js → p-a9b13f18.system.entry.js} +1 -1
  300. package/dist/ionic/{p-0bd3cc92.entry.js → p-a9d7f984.entry.js} +1 -1
  301. package/dist/ionic/{p-53bbd357.system.entry.js → p-aa4b083c.system.entry.js} +1 -1
  302. package/dist/ionic/{p-6bbf2815.system.entry.js → p-abfd1f2e.system.entry.js} +1 -1
  303. package/dist/ionic/p-ac32f6ce.entry.js +4 -0
  304. package/dist/ionic/{p-5e84b718.system.entry.js → p-afafb6bf.system.entry.js} +1 -1
  305. package/dist/ionic/{p-918d5f19.system.js → p-b10f05b1.system.js} +1 -1
  306. package/dist/ionic/{p-40e16caa.system.entry.js → p-b1cf77e0.system.entry.js} +1 -1
  307. package/dist/ionic/{p-b49fe110.entry.js → p-b2397f35.entry.js} +1 -1
  308. package/dist/ionic/{p-1bce805b.entry.js → p-b27772bf.entry.js} +1 -1
  309. package/dist/ionic/{p-568fec78.entry.js → p-b4c0e9ee.entry.js} +1 -1
  310. package/dist/ionic/{p-bf8224f4.system.entry.js → p-b4daca17.system.entry.js} +1 -1
  311. package/dist/ionic/{p-7e46b6ab.entry.js → p-b7c158f8.entry.js} +1 -1
  312. package/dist/ionic/p-b8c3f071.system.js +4 -0
  313. package/dist/ionic/{p-b0dd4f33.entry.js → p-b9e2aede.entry.js} +1 -1
  314. package/dist/ionic/{p-8e28945a.system.entry.js → p-c09e1da9.system.entry.js} +1 -1
  315. package/dist/ionic/{p-4a1ac160.system.entry.js → p-c215a78a.system.entry.js} +1 -1
  316. package/dist/ionic/{p-d8b2c214.entry.js → p-c42d0ea3.entry.js} +1 -1
  317. package/dist/ionic/{p-73f50e29.system.js → p-c46fba6d.system.js} +1 -1
  318. package/dist/ionic/{p-c5729044.system.entry.js → p-c48d177b.system.entry.js} +1 -1
  319. package/dist/ionic/{p-3e5676b7.entry.js → p-ca655a7c.entry.js} +1 -1
  320. package/dist/ionic/{p-20e5eb3e.entry.js → p-d2a278b1.entry.js} +1 -1
  321. package/dist/ionic/{p-bfac43d7.system.entry.js → p-d90f0779.system.entry.js} +1 -1
  322. package/dist/ionic/{p-95f8cb47.entry.js → p-da024961.entry.js} +1 -1
  323. package/dist/ionic/{p-327fc1bf.entry.js → p-dd0c00ed.entry.js} +1 -1
  324. package/dist/ionic/{p-82f58c25.system.entry.js → p-e40b2cb4.system.entry.js} +1 -1
  325. package/dist/ionic/{p-82da795c.system.entry.js → p-e62d80e5.system.entry.js} +1 -1
  326. package/dist/ionic/{p-410beeda.system.entry.js → p-e6d2cca2.system.entry.js} +1 -1
  327. package/dist/ionic/{p-00aed720.system.js → p-ec25d547.system.js} +1 -1
  328. package/dist/ionic/{p-f0dcf99b.entry.js → p-ec29338e.entry.js} +1 -1
  329. package/dist/ionic/{p-1c406ee0.system.entry.js → p-ec451ef7.system.entry.js} +1 -1
  330. package/dist/ionic/{p-f9015336.js → p-ee8881d0.js} +1 -1
  331. package/dist/ionic/{p-a720dc73.entry.js → p-eff1ce2e.entry.js} +1 -1
  332. package/dist/ionic/{p-76e8336d.system.entry.js → p-f37d6823.system.entry.js} +1 -1
  333. package/dist/ionic/{p-c14fb011.system.entry.js → p-f6f4d4bb.system.entry.js} +1 -1
  334. package/dist/ionic/{p-cd12dcd9.entry.js → p-fa06c407.entry.js} +1 -1
  335. package/dist/ionic/{p-7dc0ee11.system.entry.js → p-fbc7995a.system.entry.js} +1 -1
  336. package/dist/ionic/{p-b098f738.system.js → p-fe813df6.system.js} +1 -1
  337. package/dist/types/components/datetime/datetime-interface.d.ts +1 -0
  338. package/dist/types/components/datetime/datetime.d.ts +2 -2
  339. package/dist/types/components/datetime/utils/data.d.ts +3 -3
  340. package/dist/types/components/datetime/utils/format.d.ts +3 -3
  341. package/dist/types/components/datetime/utils/helpers.d.ts +15 -1
  342. package/dist/types/components/toast/animations/ios.enter.d.ts +2 -1
  343. package/dist/types/components/toast/animations/ios.leave.d.ts +2 -2
  344. package/dist/types/components/toast/animations/md.enter.d.ts +2 -1
  345. package/dist/types/components/toast/animations/utils.d.ts +18 -0
  346. package/dist/types/components/toast/toast-interface.d.ts +11 -0
  347. package/dist/types/components/toast/toast.d.ts +21 -1
  348. package/dist/types/components.d.ts +16 -8
  349. package/hydrate/index.js +267 -42
  350. package/package.json +6 -7
  351. package/dist/esm-es5/app-globals-8ae762aa.js +0 -4
  352. package/dist/esm-es5/data-009dbf15.js +0 -4
  353. package/dist/ionic/p-05f10762.entry.js +0 -4
  354. package/dist/ionic/p-1a36bf45.system.entry.js +0 -4
  355. package/dist/ionic/p-2309dba2.system.js +0 -4
  356. package/dist/ionic/p-27614d55.entry.js +0 -4
  357. package/dist/ionic/p-44ef7224.system.js +0 -4
  358. package/dist/ionic/p-6edbc09b.system.js +0 -4
  359. package/dist/ionic/p-7129d04e.entry.js +0 -4
  360. package/dist/ionic/p-72a1cbc7.js +0 -4
  361. package/dist/ionic/p-78a293a5.js +0 -4
  362. package/dist/ionic/p-7cfd253c.js +0 -4
  363. package/dist/ionic/p-90d892fd.entry.js +0 -4
  364. package/dist/ionic/p-f978ccd1.js +0 -4
  365. /package/dist/esm-es5/{haptic-6447af60.js → haptic-1243b917.js} +0 -0
  366. /package/dist/esm-es5/{index-2d388930.js → index-cb894020.js} +0 -0
  367. /package/dist/ionic/{p-91546be9.system.js → p-26fbffd4.system.js} +0 -0
  368. /package/dist/ionic/{p-14d7b7e2.system.js → p-b4b4bb29.system.js} +0 -0
  369. /package/dist/ionic/{p-bb6f38ed.js → p-b923f3d7.js} +0 -0
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import { isAfter, isBefore, isSameDay } from "./comparison";
5
5
  import { getLocalizedDayPeriod, removeDateTzOffset, getFormattedHour, addTimePadding, getTodayLabel, getYear, } from "./format";
6
- import { getNumDaysInMonth, is24Hour } from "./helpers";
6
+ import { getNumDaysInMonth, is24Hour, getHourCycle } from "./helpers";
7
7
  import { getNextMonth, getPreviousMonth, getInternalHourValue } from "./manipulation";
8
8
  /**
9
9
  * Returns the current date as
@@ -34,8 +34,14 @@ const minutes = [
34
34
  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
35
35
  32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
36
36
  ];
37
+ // h11 hour system uses 0-11. Midnight starts at 0:00am.
38
+ const hour11 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
39
+ // h12 hour system uses 0-12. Midnight starts at 12:00am.
37
40
  const hour12 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
41
+ // h23 hour system uses 0-23. Midnight starts at 0:00.
38
42
  const hour23 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23];
43
+ // h24 hour system uses 1-24. Midnight starts at 24:00.
44
+ const hour24 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 0];
39
45
  /**
40
46
  * Given a locale and a mode,
41
47
  * return an array with formatted days
@@ -104,14 +110,33 @@ export const getDaysOfMonth = (month, year, firstDayOfWeek) => {
104
110
  }
105
111
  return days;
106
112
  };
113
+ /**
114
+ * Returns an array of pre-defined hour
115
+ * values based on the provided hourCycle.
116
+ */
117
+ const getHourData = (hourCycle) => {
118
+ switch (hourCycle) {
119
+ case 'h11':
120
+ return hour11;
121
+ case 'h12':
122
+ return hour12;
123
+ case 'h23':
124
+ return hour23;
125
+ case 'h24':
126
+ return hour24;
127
+ default:
128
+ throw new Error(`Invalid hour cycle "${hourCycle}"`);
129
+ }
130
+ };
107
131
  /**
108
132
  * Given a local, reference datetime parts and option
109
133
  * max/min bound datetime parts, calculate the acceptable
110
134
  * hour and minute values according to the bounds and locale.
111
135
  */
112
- export const generateTime = (refParts, hourCycle = 'h12', minParts, maxParts, hourValues, minuteValues) => {
113
- const use24Hour = hourCycle === 'h23';
114
- let processedHours = use24Hour ? hour23 : hour12;
136
+ export const generateTime = (locale, refParts, hourCycle = 'h12', minParts, maxParts, hourValues, minuteValues) => {
137
+ const computedHourCycle = getHourCycle(locale, hourCycle);
138
+ const use24Hour = is24Hour(computedHourCycle);
139
+ let processedHours = getHourData(computedHourCycle);
115
140
  let processedMinutes = minutes;
116
141
  let isAMAllowed = true;
117
142
  let isPMAllowed = true;
@@ -443,11 +468,12 @@ export const getCombinedDateColumnData = (locale, todayParts, minParts, maxParts
443
468
  };
444
469
  };
445
470
  export const getTimeColumnsData = (locale, refParts, hourCycle, minParts, maxParts, allowedHourValues, allowedMinuteValues) => {
446
- const use24Hour = is24Hour(locale, hourCycle);
447
- const { hours, minutes, am, pm } = generateTime(refParts, use24Hour ? 'h23' : 'h12', minParts, maxParts, allowedHourValues, allowedMinuteValues);
471
+ const computedHourCycle = getHourCycle(locale, hourCycle);
472
+ const use24Hour = is24Hour(computedHourCycle);
473
+ const { hours, minutes, am, pm } = generateTime(locale, refParts, computedHourCycle, minParts, maxParts, allowedHourValues, allowedMinuteValues);
448
474
  const hoursItems = hours.map((hour) => {
449
475
  return {
450
- text: getFormattedHour(hour, use24Hour),
476
+ text: getFormattedHour(hour, computedHourCycle),
451
477
  value: getInternalHourValue(hour, use24Hour, refParts.ampm),
452
478
  };
453
479
  });
@@ -1,6 +1,7 @@
1
1
  /*!
2
2
  * (C) Ionic http://ionicframework.com - MIT License
3
3
  */
4
+ import { is24Hour } from "./helpers";
4
5
  import { convertDataToISO } from "./manipulation";
5
6
  const getFormattedDayPeriod = (dayPeriod) => {
6
7
  if (dayPeriod === undefined) {
@@ -8,7 +9,7 @@ const getFormattedDayPeriod = (dayPeriod) => {
8
9
  }
9
10
  return dayPeriod.toUpperCase();
10
11
  };
11
- export const getLocalizedTime = (locale, refParts, use24Hour) => {
12
+ export const getLocalizedTime = (locale, refParts, hourCycle) => {
12
13
  const timeParts = {
13
14
  hour: refParts.hour,
14
15
  minute: refParts.minute,
@@ -30,7 +31,7 @@ export const getLocalizedTime = (locale, refParts, use24Hour) => {
30
31
  * We use hourCycle here instead of hour12 due to:
31
32
  * https://bugs.chromium.org/p/chromium/issues/detail?id=1347316&q=hour12&can=2
32
33
  */
33
- hourCycle: use24Hour ? 'h23' : 'h12',
34
+ hourCycle,
34
35
  /**
35
36
  * Setting Z at the end indicates that this
36
37
  * date string is in the UTC time zone. This
@@ -69,17 +70,33 @@ export const addTimePadding = (value) => {
69
70
  * 12 hour times it ensures that
70
71
  * hour 0 is formatted as '12'.
71
72
  */
72
- export const getFormattedHour = (hour, use24Hour) => {
73
- if (use24Hour) {
74
- return addTimePadding(hour);
75
- }
73
+ export const getFormattedHour = (hour, hourCycle) => {
76
74
  /**
77
- * If using 12 hour
78
- * format, make sure hour
79
- * 0 is formatted as '12'.
75
+ * Midnight for h11 starts at 0:00am
76
+ * Midnight for h12 starts at 12:00am
77
+ * Midnight for h23 starts at 00:00
78
+ * Midnight for h24 starts at 24:00
80
79
  */
81
80
  if (hour === 0) {
82
- return '12';
81
+ switch (hourCycle) {
82
+ case 'h11':
83
+ return '0';
84
+ case 'h12':
85
+ return '12';
86
+ case 'h23':
87
+ return '00';
88
+ case 'h24':
89
+ return '24';
90
+ default:
91
+ throw new Error(`Invalid hour cycle "${hourCycle}"`);
92
+ }
93
+ }
94
+ const use24Hour = is24Hour(hourCycle);
95
+ /**
96
+ * h23 and h24 use 24 hour times.
97
+ */
98
+ if (use24Hour) {
99
+ return addTimePadding(hour);
83
100
  }
84
101
  return hour.toString();
85
102
  };
@@ -10,13 +10,19 @@
10
10
  export const isLeapYear = (year) => {
11
11
  return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
12
12
  };
13
- export const is24Hour = (locale, hourCycle) => {
13
+ /**
14
+ * Determines the hour cycle for a user.
15
+ * If the hour cycle is explicitly defined, just use that.
16
+ * Otherwise, we try to derive it from either the specified
17
+ * locale extension tags or from Intl.DateTimeFormat directly.
18
+ */
19
+ export const getHourCycle = (locale, hourCycle) => {
14
20
  /**
15
- * If developer has explicitly enabled h23 time
21
+ * If developer has explicitly enabled 24-hour time
16
22
  * then return early and do not look at the system default.
17
23
  */
18
24
  if (hourCycle !== undefined) {
19
- return hourCycle === 'h23';
25
+ return hourCycle;
20
26
  }
21
27
  /**
22
28
  * If hourCycle was not specified, check the locale
@@ -27,7 +33,7 @@ export const is24Hour = (locale, hourCycle) => {
27
33
  const formatted = new Intl.DateTimeFormat(locale, { hour: 'numeric' });
28
34
  const options = formatted.resolvedOptions();
29
35
  if (options.hourCycle !== undefined) {
30
- return options.hourCycle === 'h23';
36
+ return options.hourCycle;
31
37
  }
32
38
  /**
33
39
  * If hourCycle is not specified (either through lack
@@ -40,7 +46,33 @@ export const is24Hour = (locale, hourCycle) => {
40
46
  if (!hour) {
41
47
  throw new Error('Hour value not found from DateTimeFormat');
42
48
  }
43
- return hour.value === '00';
49
+ /**
50
+ * Midnight for h11 starts at 0:00am
51
+ * Midnight for h12 starts at 12:00am
52
+ * Midnight for h23 starts at 00:00
53
+ * Midnight for h24 starts at 24:00
54
+ */
55
+ switch (hour.value) {
56
+ case '0':
57
+ return 'h11';
58
+ case '12':
59
+ return 'h12';
60
+ case '00':
61
+ return 'h23';
62
+ case '24':
63
+ return 'h24';
64
+ default:
65
+ throw new Error(`Invalid hour cycle "${hourCycle}"`);
66
+ }
67
+ };
68
+ /**
69
+ * Determine if the hour cycle uses a 24-hour format.
70
+ * Returns true for h23 and h24. Returns false otherwise.
71
+ * If you don't know the hourCycle, use getHourCycle above
72
+ * and pass the result into this function.
73
+ */
74
+ export const is24Hour = (hourCycle) => {
75
+ return hourCycle === 'h23' || hourCycle === 'h24';
44
76
  };
45
77
  /**
46
78
  * Given a date object, returns the number
@@ -8,7 +8,7 @@ import { createColorClasses } from "../../utils/theme";
8
8
  import { getIonMode } from "../../global/ionic-global";
9
9
  import { getToday } from "../datetime/utils/data";
10
10
  import { getMonthAndYear, getMonthDayAndYear, getLocalizedDateTime, getLocalizedTime } from "../datetime/utils/format";
11
- import { is24Hour } from "../datetime/utils/helpers";
11
+ import { getHourCycle } from "../datetime/utils/helpers";
12
12
  import { parseDate } from "../datetime/utils/parse";
13
13
  /**
14
14
  * @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
@@ -65,13 +65,13 @@ export class DatetimeButton {
65
65
  * warning in the console.
66
66
  */
67
67
  const firstParsedDatetime = parsedDatetimes[0];
68
- const use24Hour = is24Hour(locale, hourCycle);
68
+ const computedHourCycle = getHourCycle(locale, hourCycle);
69
69
  this.dateText = this.timeText = undefined;
70
70
  switch (datetimePresentation) {
71
71
  case 'date-time':
72
72
  case 'time-date':
73
73
  const dateText = getMonthDayAndYear(locale, firstParsedDatetime);
74
- const timeText = getLocalizedTime(locale, firstParsedDatetime, use24Hour);
74
+ const timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle);
75
75
  if (preferWheel) {
76
76
  this.dateText = `${dateText} ${timeText}`;
77
77
  }
@@ -98,7 +98,7 @@ export class DatetimeButton {
98
98
  }
99
99
  break;
100
100
  case 'time':
101
- this.timeText = getLocalizedTime(locale, firstParsedDatetime, use24Hour);
101
+ this.timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle);
102
102
  break;
103
103
  case 'month-year':
104
104
  this.dateText = getMonthAndYear(locale, firstParsedDatetime);
@@ -103,22 +103,4 @@ ion-header ion-toolbar:first-of-type {
103
103
  .header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-title,
104
104
  .header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-buttons.buttons-collapse {
105
105
  visibility: hidden;
106
- }
107
-
108
- /**
109
- * The main header is only hidden once the collapsible large
110
- * title is configured. As a result, if the main header loads
111
- * before the collapsible large title is configured then the
112
- * main header will be visible briefly before being hidden
113
- * by the collapsible large title.
114
- *
115
- * The following selector ensures that any main header
116
- * on a page with a collapsible large title is hidden
117
- * before the collapsible large title is configured.
118
- * Once the collapsible large title is configured the main
119
- * header will have the ".header-collapse-main" class, and
120
- * this selector will no longer apply.
121
- */
122
- ion-header:not(.header-collapse-main):has(~ ion-content ion-header[collapse=condense]) {
123
- opacity: 0;
124
106
  }
@@ -672,6 +672,7 @@ export class Nav {
672
672
  : undefined;
673
673
  const mode = getIonMode(this);
674
674
  const enteringEl = enteringView.element;
675
+ // eslint-disable-next-line @typescript-eslint/prefer-optional-chain
675
676
  const leavingEl = leavingView && leavingView.element;
676
677
  const animationOpts = Object.assign(Object.assign({ mode, showGoBack: this.canGoBackSync(enteringView), baseEl: this.el, progressCallback, animated: this.animated && config.getBoolean('animated', true), enteringEl,
677
678
  leavingEl }, opts), { animationBuilder: opts.animationBuilder || this.animation || config.get('navAnimation') });
@@ -215,12 +215,14 @@ export class Router {
215
215
  }
216
216
  const routes = readRoutes(this.el);
217
217
  const fromChain = findChainForSegments(from, routes);
218
+ // eslint-disable-next-line @typescript-eslint/prefer-optional-chain
218
219
  const beforeLeaveHook = fromChain && fromChain[fromChain.length - 1].beforeLeave;
219
220
  const canLeave = beforeLeaveHook ? await beforeLeaveHook() : true;
220
221
  if (canLeave === false || typeof canLeave === 'object') {
221
222
  return canLeave;
222
223
  }
223
224
  const toChain = findChainForSegments(to, routes);
225
+ // eslint-disable-next-line @typescript-eslint/prefer-optional-chain
224
226
  const beforeEnterHook = toChain && toChain[toChain.length - 1].beforeEnter;
225
227
  return beforeEnterHook ? beforeEnterHook() : true;
226
228
  }
@@ -38,6 +38,7 @@ export const chainToSegments = (chain) => {
38
38
  for (const route of chain) {
39
39
  for (const segment of route.segments) {
40
40
  if (segment[0] === ':') {
41
+ // eslint-disable-next-line @typescript-eslint/prefer-optional-chain
41
42
  const param = route.params && route.params[segment.slice(1)];
42
43
  if (!param) {
43
44
  return null;
@@ -642,7 +642,7 @@ Developers can use the "legacy" property to continue using the legacy form marku
642
642
  }
643
643
  renderListbox() {
644
644
  const { disabled, inputId, isExpanded } = this;
645
- return (h("button", { disabled: disabled, id: inputId, "aria-label": this.ariaLabel, "aria-haspopup": "listbox", "aria-expanded": `${isExpanded}`, onFocus: this.onFocus, onBlur: this.onBlur, ref: (focusEl) => (this.focusEl = focusEl) }));
645
+ return (h("button", { disabled: disabled, id: inputId, "aria-label": this.ariaLabel, "aria-haspopup": "dialog", "aria-expanded": `${isExpanded}`, onFocus: this.onFocus, onBlur: this.onBlur, ref: (focusEl) => (this.focusEl = focusEl) }));
646
646
  }
647
647
  render() {
648
648
  const { legacyFormController } = this;
@@ -6,13 +6,12 @@ import { getElementRoot } from "../../../utils/helpers";
6
6
  /**
7
7
  * iOS Toast Enter Animation
8
8
  */
9
- export const iosEnterAnimation = (baseEl, position) => {
9
+ export const iosEnterAnimation = (baseEl, opts) => {
10
10
  const baseAnimation = createAnimation();
11
11
  const wrapperAnimation = createAnimation();
12
+ const { position, top, bottom } = opts;
12
13
  const root = getElementRoot(baseEl);
13
14
  const wrapperEl = root.querySelector('.toast-wrapper');
14
- const bottom = `calc(-10px - var(--ion-safe-area-bottom, 0px))`;
15
- const top = `calc(10px + var(--ion-safe-area-top, 0px))`;
16
15
  wrapperAnimation.addElement(wrapperEl);
17
16
  switch (position) {
18
17
  case 'top':
@@ -6,13 +6,12 @@ import { getElementRoot } from "../../../utils/helpers";
6
6
  /**
7
7
  * iOS Toast Leave Animation
8
8
  */
9
- export const iosLeaveAnimation = (baseEl, position) => {
9
+ export const iosLeaveAnimation = (baseEl, opts) => {
10
10
  const baseAnimation = createAnimation();
11
11
  const wrapperAnimation = createAnimation();
12
+ const { position, top, bottom } = opts;
12
13
  const root = getElementRoot(baseEl);
13
14
  const wrapperEl = root.querySelector('.toast-wrapper');
14
- const bottom = `calc(-10px - var(--ion-safe-area-bottom, 0px))`;
15
- const top = `calc(10px + var(--ion-safe-area-top, 0px))`;
16
15
  wrapperAnimation.addElement(wrapperEl);
17
16
  switch (position) {
18
17
  case 'top':
@@ -6,13 +6,12 @@ import { getElementRoot } from "../../../utils/helpers";
6
6
  /**
7
7
  * MD Toast Enter Animation
8
8
  */
9
- export const mdEnterAnimation = (baseEl, position) => {
9
+ export const mdEnterAnimation = (baseEl, opts) => {
10
10
  const baseAnimation = createAnimation();
11
11
  const wrapperAnimation = createAnimation();
12
+ const { position, top, bottom } = opts;
12
13
  const root = getElementRoot(baseEl);
13
14
  const wrapperEl = root.querySelector('.toast-wrapper');
14
- const bottom = `calc(8px + var(--ion-safe-area-bottom, 0px))`;
15
- const top = `calc(8px + var(--ion-safe-area-top, 0px))`;
16
15
  wrapperAnimation.addElement(wrapperEl);
17
16
  switch (position) {
18
17
  case 'top':
@@ -0,0 +1,85 @@
1
+ /*!
2
+ * (C) Ionic http://ionicframework.com - MIT License
3
+ */
4
+ import { win } from "../../../utils/browser/index";
5
+ import { printIonWarning } from "../../../utils/logging/index";
6
+ /**
7
+ * Calculate the CSS top and bottom position of the toast, to be used
8
+ * as starting points for the animation keyframes.
9
+ *
10
+ * Note that MD animates bottom-positioned toasts using style.bottom,
11
+ * which calculates from the bottom edge of the screen, while iOS uses
12
+ * translateY, which calculates from the top edge of the screen. This
13
+ * is why the bottom calculates differ slightly between modes.
14
+ *
15
+ * @param position The value of the toast's position prop.
16
+ * @param positionAnchor The element the toast should be anchored to,
17
+ * if applicable.
18
+ * @param mode The toast component's mode (md, ios, etc).
19
+ * @param toast A reference to the toast element itself.
20
+ */
21
+ export function getAnimationPosition(position, positionAnchor, mode, toast) {
22
+ /**
23
+ * Start with a predefined offset from the edge the toast will be
24
+ * positioned relative to, whether on the screen or anchor element.
25
+ */
26
+ let offset;
27
+ if (mode === 'md') {
28
+ offset = 8;
29
+ }
30
+ else {
31
+ offset = position === 'top' ? 10 : -10;
32
+ }
33
+ /**
34
+ * If positionAnchor is defined, add in the distance from the target
35
+ * screen edge to the target anchor edge. For position="top", the
36
+ * bottom anchor edge is targeted. For position="bottom", the top
37
+ * anchor edge is targeted.
38
+ */
39
+ if (positionAnchor && win) {
40
+ warnIfAnchorIsHidden(positionAnchor, toast);
41
+ const box = positionAnchor.getBoundingClientRect();
42
+ if (position === 'top') {
43
+ offset += box.bottom;
44
+ }
45
+ else if (position === 'bottom') {
46
+ /**
47
+ * Just box.top is the distance from the top edge of the screen
48
+ * to the top edge of the anchor. We want to calculate from the
49
+ * bottom edge of the screen instead.
50
+ */
51
+ if (mode === 'md') {
52
+ offset += win.innerHeight - box.top;
53
+ }
54
+ else {
55
+ offset -= win.innerHeight - box.top;
56
+ }
57
+ }
58
+ /**
59
+ * We don't include safe area here because that should already be
60
+ * accounted for when checking the position of the anchor.
61
+ */
62
+ return {
63
+ top: `${offset}px`,
64
+ bottom: `${offset}px`,
65
+ };
66
+ }
67
+ else {
68
+ return {
69
+ top: `calc(${offset}px + var(--ion-safe-area-top, 0px))`,
70
+ bottom: mode === 'md'
71
+ ? `calc(${offset}px + var(--ion-safe-area-bottom, 0px))`
72
+ : `calc(${offset}px - var(--ion-safe-area-bottom, 0px))`,
73
+ };
74
+ }
75
+ }
76
+ /**
77
+ * If the anchor element is hidden, getBoundingClientRect()
78
+ * will return all 0s for it, which can cause unexpected
79
+ * results in the position calculation when animating.
80
+ */
81
+ function warnIfAnchorIsHidden(positionAnchor, toast) {
82
+ if (positionAnchor.offsetParent === null) {
83
+ printIonWarning('The positionAnchor element for ion-toast was found in the DOM, but appears to be hidden. This may lead to unexpected positioning of the toast.', toast);
84
+ }
85
+ }
@@ -0,0 +1,45 @@
1
+ /*!
2
+ * (C) Ionic http://ionicframework.com - MIT License
3
+ */
4
+ import { expect } from "@playwright/test";
5
+ import { configs, test } from "../../../../utils/test/playwright/index";
6
+ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
7
+ test.describe(title('toast: positionAnchor'), () => {
8
+ test.beforeEach(async ({ page }) => {
9
+ await page.goto('/src/components/toast/test/position-anchor', config);
10
+ /**
11
+ * We need to screenshot the whole page to ensure the toasts are positioned
12
+ * correctly, but we don't need much extra white space between the header
13
+ * and footer.
14
+ */
15
+ await page.setViewportSize({
16
+ width: 425,
17
+ height: 425,
18
+ });
19
+ });
20
+ test('should place top-position toast underneath anchor', async ({ page }) => {
21
+ const ionToastDidPresent = await page.spyOnEvent('ionToastDidPresent');
22
+ await page.click('#headerAnchor');
23
+ await ionToastDidPresent.next();
24
+ await expect(page).toHaveScreenshot(screenshot(`toast-header-anchor`));
25
+ });
26
+ test('should place bottom-position toast above anchor', async ({ page }) => {
27
+ const ionToastDidPresent = await page.spyOnEvent('ionToastDidPresent');
28
+ await page.click('#footerAnchor');
29
+ await ionToastDidPresent.next();
30
+ await expect(page).toHaveScreenshot(screenshot(`toast-footer-anchor`));
31
+ });
32
+ test('should ignore anchor for middle-position toast', async ({ page }) => {
33
+ const ionToastDidPresent = await page.spyOnEvent('ionToastDidPresent');
34
+ await page.click('#middleAnchor');
35
+ await ionToastDidPresent.next();
36
+ await expect(page).toHaveScreenshot(screenshot(`toast-middle-anchor`));
37
+ });
38
+ test('should correctly anchor toast when using an element reference', async ({ page }) => {
39
+ const ionToastDidPresent = await page.spyOnEvent('ionToastDidPresent');
40
+ await page.click('#headerElAnchor');
41
+ await ionToastDidPresent.next();
42
+ await expect(page).toHaveScreenshot(screenshot(`toast-header-el-anchor`));
43
+ });
44
+ });
45
+ });
@@ -15,6 +15,7 @@ import { iosEnterAnimation } from "./animations/ios.enter";
15
15
  import { iosLeaveAnimation } from "./animations/ios.leave";
16
16
  import { mdEnterAnimation } from "./animations/md.enter";
17
17
  import { mdLeaveAnimation } from "./animations/md.leave";
18
+ import { getAnimationPosition } from "./animations/utils";
18
19
  // TODO(FW-2832): types
19
20
  /**
20
21
  * @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
@@ -54,6 +55,7 @@ export class Toast {
54
55
  this.message = undefined;
55
56
  this.keyboardClose = false;
56
57
  this.position = 'bottom';
58
+ this.positionAnchor = undefined;
57
59
  this.buttons = undefined;
58
60
  this.translucent = false;
59
61
  this.animated = true;
@@ -101,7 +103,19 @@ export class Toast {
101
103
  async present() {
102
104
  const unlock = await this.lockController.lock();
103
105
  await this.delegateController.attachViewToDom();
104
- await present(this, 'toastEnter', iosEnterAnimation, mdEnterAnimation, this.position);
106
+ const { el, position } = this;
107
+ const anchor = this.getAnchorElement();
108
+ const animationPosition = getAnimationPosition(position, anchor, getIonMode(this), el);
109
+ /**
110
+ * Cache the calculated position of the toast, so we can re-use it
111
+ * in the dismiss animation.
112
+ */
113
+ this.lastPresentedPosition = animationPosition;
114
+ await present(this, 'toastEnter', iosEnterAnimation, mdEnterAnimation, {
115
+ position,
116
+ top: animationPosition.top,
117
+ bottom: animationPosition.bottom,
118
+ });
105
119
  /**
106
120
  * Content is revealed to screen readers after
107
121
  * the transition to avoid jank since this
@@ -123,15 +137,28 @@ export class Toast {
123
137
  * Some examples include: ``"cancel"`, `"destructive"`, "selected"`, and `"backdrop"`.
124
138
  */
125
139
  async dismiss(data, role) {
140
+ var _a, _b;
126
141
  const unlock = await this.lockController.lock();
127
- if (this.durationTimeout) {
128
- clearTimeout(this.durationTimeout);
142
+ const { durationTimeout, position, lastPresentedPosition } = this;
143
+ if (durationTimeout) {
144
+ clearTimeout(durationTimeout);
129
145
  }
130
- const dismissed = await dismiss(this, data, role, 'toastLeave', iosLeaveAnimation, mdLeaveAnimation, this.position);
146
+ const dismissed = await dismiss(this, data, role, 'toastLeave', iosLeaveAnimation, mdLeaveAnimation,
147
+ /**
148
+ * Fetch the cached position that was calculated back in the present
149
+ * animation. We always want to animate the dismiss from the same
150
+ * position the present stopped at, so the animation looks continuous.
151
+ */
152
+ {
153
+ position,
154
+ top: (_a = lastPresentedPosition === null || lastPresentedPosition === void 0 ? void 0 : lastPresentedPosition.top) !== null && _a !== void 0 ? _a : '',
155
+ bottom: (_b = lastPresentedPosition === null || lastPresentedPosition === void 0 ? void 0 : lastPresentedPosition.bottom) !== null && _b !== void 0 ? _b : '',
156
+ });
131
157
  if (dismissed) {
132
158
  this.delegateController.removeViewFromDom();
133
159
  this.revealContentToScreenReader = false;
134
160
  }
161
+ this.lastPresentedPosition = undefined;
135
162
  unlock();
136
163
  return dismissed;
137
164
  }
@@ -155,6 +182,37 @@ export class Toast {
155
182
  : [];
156
183
  return buttons;
157
184
  }
185
+ /**
186
+ * Returns the element specified by the positionAnchor prop,
187
+ * or undefined if prop's value is an ID string and the element
188
+ * is not found in the DOM.
189
+ */
190
+ getAnchorElement() {
191
+ const { position, positionAnchor, el } = this;
192
+ if (position === 'middle' && positionAnchor !== undefined) {
193
+ printIonWarning('The positionAnchor property is ignored when using position="middle".', this.el);
194
+ return undefined;
195
+ }
196
+ if (typeof positionAnchor === 'string') {
197
+ /**
198
+ * If the anchor is defined as an ID, find the element.
199
+ * We do this on every present so the toast doesn't need
200
+ * to account for the surrounding DOM changing since the
201
+ * last time it was presented.
202
+ */
203
+ const foundEl = document.getElementById(positionAnchor);
204
+ if (foundEl === null) {
205
+ printIonWarning(`An anchor element with an ID of "${positionAnchor}" was not found in the DOM.`, el);
206
+ return undefined;
207
+ }
208
+ return foundEl;
209
+ }
210
+ if (positionAnchor instanceof HTMLElement) {
211
+ return positionAnchor;
212
+ }
213
+ printIonWarning('Invalid positionAnchor value:', positionAnchor, el);
214
+ return undefined;
215
+ }
158
216
  async buttonClick(button) {
159
217
  const role = button.role;
160
218
  if (isCancel(role)) {
@@ -517,12 +575,34 @@ export class Toast {
517
575
  "optional": false,
518
576
  "docs": {
519
577
  "tags": [],
520
- "text": "The position of the toast on the screen."
578
+ "text": "The starting position of the toast on the screen. Can be tweaked further\nusing the `positionAnchor` property."
521
579
  },
522
580
  "attribute": "position",
523
581
  "reflect": false,
524
582
  "defaultValue": "'bottom'"
525
583
  },
584
+ "positionAnchor": {
585
+ "type": "string",
586
+ "mutable": false,
587
+ "complexType": {
588
+ "original": "HTMLElement | string",
589
+ "resolved": "HTMLElement | string | undefined",
590
+ "references": {
591
+ "HTMLElement": {
592
+ "location": "global",
593
+ "id": "global::HTMLElement"
594
+ }
595
+ }
596
+ },
597
+ "required": false,
598
+ "optional": true,
599
+ "docs": {
600
+ "tags": [],
601
+ "text": "The element to anchor the toast's position to. Can be set as a direct reference\nor the ID of the element. With `position=\"bottom\"`, the toast will sit above the\nchosen element. With `position=\"top\"`, the toast will sit below the chosen element.\nWith `position=\"middle\"`, the value of `positionAnchor` is ignored."
602
+ },
603
+ "attribute": "position-anchor",
604
+ "reflect": false
605
+ },
526
606
  "buttons": {
527
607
  "type": "unknown",
528
608
  "mutable": false,
@@ -813,8 +893,9 @@ export class Toast {
813
893
  "id": "global::Promise"
814
894
  },
815
895
  "ToastPresentOptions": {
816
- "location": "global",
817
- "id": "global::ToastPresentOptions"
896
+ "location": "import",
897
+ "path": "./toast-interface",
898
+ "id": "src/components/toast/toast-interface.ts::ToastPresentOptions"
818
899
  }
819
900
  },
820
901
  "return": "Promise<void>"
@@ -846,8 +927,9 @@ export class Toast {
846
927
  "id": "global::Promise"
847
928
  },
848
929
  "ToastDismissOptions": {
849
- "location": "global",
850
- "id": "global::ToastDismissOptions"
930
+ "location": "import",
931
+ "path": "./toast-interface",
932
+ "id": "src/components/toast/toast-interface.ts::ToastDismissOptions"
851
933
  }
852
934
  },
853
935
  "return": "Promise<boolean>"