@ionic/core 9.0.0 → 9.0.1-dev.11787248963.10a00c73

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 (596) 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-63OhffQv.js → p-66ogmUZU.js} +1 -1
  99. package/components/p-6Vp915Y7.js +4 -0
  100. package/components/p-7PNwKFZi.js +4 -0
  101. package/components/{p-G0TxqHfe.js → p-A8MJRBIY.js} +1 -1
  102. package/components/p-AQcCdH2_.js +4 -0
  103. package/{dist/ionic/p-Dn0mqQ_R.js → components/p-B6x5_b9w.js} +1 -1
  104. package/components/p-B8MQjdvk.js +4 -0
  105. package/components/p-BA_4ZIEg.js +4 -0
  106. package/components/p-BFtL8t1r.js +4 -0
  107. package/components/{p-DaA_8eqt.js → p-BMfgF-Tv.js} +1 -1
  108. package/components/p-BPDxVIRr.js +4 -0
  109. package/components/p-BSARlp49.js +4 -0
  110. package/components/p-B_gJaBk0.js +4 -0
  111. package/components/p-BdwCtX8Y.js +4 -0
  112. package/components/p-Bg4OwDwb.js +4 -0
  113. package/components/{p-DV85C0e0.js → p-BgUIV8NQ.js} +1 -1
  114. package/components/p-Bnc0m4SW.js +4 -0
  115. package/components/p-BpLt_Ptn.js +4 -0
  116. package/components/p-BqBDq1Ma.js +4 -0
  117. package/components/{p-C_phlPMC.js → p-BrFaQbGY.js} +1 -1
  118. package/{dist/ionic/p-Cdjxf_yg.js → components/p-BuPAFTWI.js} +1 -1
  119. package/components/p-Bx2saTHs.js +4 -0
  120. package/components/p-BxhE2W85.js +4 -0
  121. package/components/p-CHswSpKy.js +4 -0
  122. package/components/{p-fruGqVHh.js → p-CQAjyETU.js} +1 -1
  123. package/components/{p-1jI5oW-W.js → p-CR9OgE6N.js} +1 -1
  124. package/components/p-CWETxTjE.js +4 -0
  125. package/components/p-CaZeZIL2.js +4 -0
  126. package/components/p-CaiZOhfC.js +4 -0
  127. package/components/p-CgvDC7hC.js +4 -0
  128. package/components/{p-BqPNzJf6.js → p-CqyGR9Aq.js} +1 -1
  129. package/components/{p-UIBJkZf8.js → p-D0YpjgON.js} +1 -1
  130. package/components/p-D7ysFE2B.js +4 -0
  131. package/{dist/ionic/p-4eOQC00Z.js → components/p-DCWfzDM8.js} +1 -1
  132. package/components/{p-DwpKZ6rl.js → p-DDdkefwf.js} +1 -1
  133. package/components/{p-DzRT60Tw.js → p-DEW7CnUc.js} +1 -1
  134. package/components/p-DQ1IPvZO.js +4 -0
  135. package/components/p-DcOH6-o5.js +4 -0
  136. package/components/{p-DD5fQ4EQ.js → p-DfdYCsov.js} +1 -1
  137. package/components/{p-DSzSbVP2.js → p-DhOoEIAs.js} +1 -1
  138. package/components/{p-DM-PrAoh.js → p-Dl_7b_UJ.js} +1 -1
  139. package/components/p-DqAI6tg7.js +4 -0
  140. package/components/p-DrehWDfv.js +4 -0
  141. package/components/{p-ryyf_ItD.js → p-DysqCsJu.js} +1 -1
  142. package/components/p-H1f2qsk4.js +4 -0
  143. package/components/p-HVYBAhFx.js +4 -0
  144. package/components/{p-CbhUdtjf.js → p-Kmrg3Fed.js} +1 -1
  145. package/components/{p-Bjig0DJK.js → p-RFfE9hF6.js} +1 -1
  146. package/{dist/ionic/p-CBWAXjA5.js → components/p-SR-LLqp_.js} +1 -1
  147. package/components/p-eFI3mtEX.js +4 -0
  148. package/components/p-gFwXiYC_.js +4 -0
  149. package/components/p-tX3UxCnU.js +4 -0
  150. package/components/p-v2NpoOHp.js +4 -0
  151. package/dist/cjs/{animation-C0mOHzej.js → animation-D-OqR4a4.js} +1 -1
  152. package/dist/cjs/{app-globals-BREG4twP.js → app-globals-BzgwARwJ.js} +1 -1
  153. package/dist/cjs/{button-active-CVMevT9a.js → button-active-BlWSD7uK.js} +2 -2
  154. package/dist/cjs/{format-pp0Du3K-.js → format-D7ig6Vm0.js} +1 -1
  155. package/dist/cjs/{framework-delegate-Dfo5XsGv.js → framework-delegate-BZUx4TnE.js} +1 -1
  156. package/dist/cjs/{gesture-controller-BDUH7687.js → gesture-controller-CeJslptU.js} +6 -14
  157. package/dist/cjs/{hardware-back-button-fqpYh-kd.js → hardware-back-button-JOAEFSzc.js} +1 -1
  158. package/dist/cjs/{helpers-YPQybDph.js → helpers-Dj5o76mq.js} +1 -1
  159. package/dist/cjs/{index-BLdJCcJY.js → index-2sO-zkZ2.js} +4 -4
  160. package/dist/cjs/{index-uvry__L4.js → index-BrVMoqUk.js} +3 -1
  161. package/dist/cjs/{index-zVCah4Uz.js → index-C8zH6b3d.js} +2 -2
  162. package/dist/cjs/{index-DXsPSne6.js → index-CZ6vzt_q.js} +5 -5
  163. package/dist/cjs/{index-DDg31ZF5.js → index-Csue6G3m.js} +2 -2
  164. package/dist/cjs/{index-DwlRtFZe.js → index-DRPqwSvU.js} +1 -1
  165. package/dist/cjs/{index-B7zJsYWS.js → index-EJLjthTK.js} +1 -2
  166. package/dist/cjs/index.cjs.js +14 -14
  167. package/dist/cjs/{input-shims-Cbu1fcye.js → input-shims-Bh7bnt2v.js} +3 -3
  168. package/dist/cjs/{input.utils-BZdMWVrt.js → input.utils-Cq3g9uHy.js} +1 -1
  169. package/dist/cjs/ion-accordion_2.cjs.entry.js +335 -364
  170. package/dist/cjs/ion-action-sheet.cjs.entry.js +60 -140
  171. package/dist/cjs/ion-alert.cjs.entry.js +67 -159
  172. package/dist/cjs/ion-app_8.cjs.entry.js +163 -258
  173. package/dist/cjs/ion-avatar_3.cjs.entry.js +2 -8
  174. package/dist/cjs/ion-back-button.cjs.entry.js +21 -45
  175. package/dist/cjs/ion-backdrop.cjs.entry.js +14 -18
  176. package/dist/cjs/ion-breadcrumb_2.cjs.entry.js +117 -195
  177. package/dist/cjs/ion-button_2.cjs.entry.js +61 -130
  178. package/dist/cjs/ion-card_5.cjs.entry.js +28 -80
  179. package/dist/cjs/ion-checkbox.cjs.entry.js +98 -147
  180. package/dist/cjs/ion-chip.cjs.entry.js +10 -16
  181. package/dist/cjs/ion-col_3.cjs.entry.js +6 -126
  182. package/dist/cjs/ion-datetime-button.cjs.entry.js +232 -248
  183. package/dist/cjs/ion-datetime.cjs.entry.js +775 -953
  184. package/dist/cjs/ion-fab_3.cjs.entry.js +78 -136
  185. package/dist/cjs/ion-img.cjs.entry.js +11 -31
  186. package/dist/cjs/ion-infinite-scroll_2.cjs.entry.js +71 -98
  187. package/dist/cjs/ion-input-otp.cjs.entry.js +352 -424
  188. package/dist/cjs/ion-input-password-toggle.cjs.entry.js +14 -29
  189. package/dist/cjs/ion-input.cjs.entry.js +158 -302
  190. package/dist/cjs/ion-item-option_3.cjs.entry.js +54 -98
  191. package/dist/cjs/ion-item_8.cjs.entry.js +61 -157
  192. package/dist/cjs/ion-loading.cjs.entry.js +54 -131
  193. package/dist/cjs/ion-menu_3.cjs.entry.js +94 -158
  194. package/dist/cjs/ion-modal.cjs.entry.js +206 -362
  195. package/dist/cjs/ion-nav_2.cjs.entry.js +26 -78
  196. package/dist/cjs/ion-picker-column-option.cjs.entry.js +23 -33
  197. package/dist/cjs/ion-picker-column.cjs.entry.js +389 -410
  198. package/dist/cjs/ion-picker.cjs.entry.js +390 -400
  199. package/dist/cjs/ion-popover.cjs.entry.js +184 -292
  200. package/dist/cjs/ion-progress-bar.cjs.entry.js +23 -29
  201. package/dist/cjs/ion-radio_2.cjs.entry.js +128 -201
  202. package/dist/cjs/ion-range.cjs.entry.js +223 -293
  203. package/dist/cjs/ion-refresher_2.cjs.entry.js +89 -154
  204. package/dist/cjs/ion-reorder_2.cjs.entry.js +19 -49
  205. package/dist/cjs/ion-ripple-effect.cjs.entry.js +13 -13
  206. package/dist/cjs/ion-route_4.cjs.entry.js +45 -144
  207. package/dist/cjs/ion-searchbar.cjs.entry.js +182 -268
  208. package/dist/cjs/ion-segment-content.cjs.entry.js +1 -1
  209. package/dist/cjs/ion-segment-view.cjs.entry.js +12 -24
  210. package/dist/cjs/ion-segment_2.cjs.entry.js +122 -161
  211. package/dist/cjs/ion-select-modal.cjs.entry.js +19 -21
  212. package/dist/cjs/ion-select_3.cjs.entry.js +151 -319
  213. package/dist/cjs/ion-spinner.cjs.entry.js +6 -21
  214. package/dist/cjs/ion-split-pane.cjs.entry.js +14 -27
  215. package/dist/cjs/ion-tab-bar_2.cjs.entry.js +32 -89
  216. package/dist/cjs/ion-tab_2.cjs.entry.js +22 -49
  217. package/dist/cjs/ion-text.cjs.entry.js +2 -8
  218. package/dist/cjs/ion-textarea.cjs.entry.js +139 -256
  219. package/dist/cjs/ion-toast.cjs.entry.js +106 -221
  220. package/dist/cjs/ion-toggle.cjs.entry.js +114 -165
  221. package/dist/cjs/{ionic-global-k6hOWWpn.js → ionic-global-DvgIzM2F.js} +1 -1
  222. package/dist/cjs/ionic.cjs.js +4 -4
  223. package/dist/cjs/{ios.transition-zTmJz8T-.js → ios.transition-zIgdoSYe.js} +4 -4
  224. package/dist/cjs/{item-multiple-inputs-BdYSbfKN.js → item-multiple-inputs-DG-ZGm6j.js} +1 -1
  225. package/dist/cjs/loader.cjs.js +4 -4
  226. package/dist/cjs/{md.transition-nb_4pUXu.js → md.transition-CXeJ9rfh.js} +4 -4
  227. package/dist/cjs/{overlays-KaNVDNqC.js → overlays-Bg0auTQa.js} +6 -6
  228. package/dist/cjs/{select-option-render-pULCGldr.js → select-option-render-7m1WdFzF.js} +2 -2
  229. package/dist/cjs/{slot-mutation-controller-DPHmqXdV.js → slot-mutation-controller-BJEJzx_e.js} +1 -1
  230. package/dist/cjs/{status-tap-o9IIymsP.js → status-tap-DxbUM5XX.js} +3 -3
  231. package/dist/cjs/{swipe-back-B7X9VOlH.js → swipe-back-F_DBt-Aw.js} +4 -4
  232. package/dist/collection/components/accordion/accordion.js +310 -314
  233. package/dist/collection/components/accordion-group/accordion-group.js +23 -46
  234. package/dist/collection/components/action-sheet/action-sheet.js +49 -128
  235. package/dist/collection/components/action-sheet/test/basic/fixture.js +0 -3
  236. package/dist/collection/components/alert/alert.js +56 -147
  237. package/dist/collection/components/app/app.js +0 -3
  238. package/dist/collection/components/back-button/back-button.js +19 -42
  239. package/dist/collection/components/backdrop/backdrop.js +14 -16
  240. package/dist/collection/components/badge/badge.js +0 -6
  241. package/dist/collection/components/breadcrumb/breadcrumb.js +29 -90
  242. package/dist/collection/components/breadcrumbs/breadcrumbs.js +87 -102
  243. package/dist/collection/components/button/button.js +59 -127
  244. package/dist/collection/components/buttons/buttons.js +15 -13
  245. package/dist/collection/components/card/card.js +20 -53
  246. package/dist/collection/components/card-header/card-header.js +8 -12
  247. package/dist/collection/components/card-subtitle/card-subtitle.js +0 -6
  248. package/dist/collection/components/card-title/card-title.js +0 -6
  249. package/dist/collection/components/checkbox/checkbox.js +95 -143
  250. package/dist/collection/components/chip/chip.js +10 -14
  251. package/dist/collection/components/col/col.js +0 -120
  252. package/dist/collection/components/content/content.js +60 -90
  253. package/dist/collection/components/datetime/datetime.js +762 -939
  254. package/dist/collection/components/datetime-button/datetime-button.js +229 -244
  255. package/dist/collection/components/fab/fab.js +13 -20
  256. package/dist/collection/components/fab-button/fab-button.js +54 -103
  257. package/dist/collection/components/fab-list/fab-list.js +11 -10
  258. package/dist/collection/components/footer/footer.js +43 -49
  259. package/dist/collection/components/grid/grid.js +6 -4
  260. package/dist/collection/components/header/header.js +23 -33
  261. package/dist/collection/components/img/img.js +9 -28
  262. package/dist/collection/components/infinite-scroll/infinite-scroll.js +66 -73
  263. package/dist/collection/components/infinite-scroll-content/infinite-scroll-content.js +3 -20
  264. package/dist/collection/components/input/input.js +154 -297
  265. package/dist/collection/components/input-otp/input-otp.js +350 -421
  266. package/dist/collection/components/input-password-toggle/input-password-toggle.js +13 -27
  267. package/dist/collection/components/item/item.js +37 -80
  268. package/dist/collection/components/item-divider/item-divider.js +10 -15
  269. package/dist/collection/components/item-option/item-option.js +20 -48
  270. package/dist/collection/components/item-options/item-options.js +7 -10
  271. package/dist/collection/components/item-sliding/item-sliding.js +26 -36
  272. package/dist/collection/components/label/label.js +4 -24
  273. package/dist/collection/components/list/list.js +6 -9
  274. package/dist/collection/components/list-header/list-header.js +0 -10
  275. package/dist/collection/components/loading/loading.js +46 -122
  276. package/dist/collection/components/menu/menu.js +55 -99
  277. package/dist/collection/components/menu-button/menu-button.js +19 -28
  278. package/dist/collection/components/menu-toggle/menu-toggle.js +13 -20
  279. package/dist/collection/components/modal/modal.js +196 -351
  280. package/dist/collection/components/modal/test/fixtures.js +0 -3
  281. package/dist/collection/components/nav/nav.js +12 -45
  282. package/dist/collection/components/nav/view-controller.js +1 -7
  283. package/dist/collection/components/nav-link/nav-link.js +9 -20
  284. package/dist/collection/components/note/note.js +0 -6
  285. package/dist/collection/components/picker/picker.js +388 -397
  286. package/dist/collection/components/picker-column/picker-column.js +389 -409
  287. package/dist/collection/components/picker-column-option/picker-column-option.js +21 -30
  288. package/dist/collection/components/popover/popover.js +176 -283
  289. package/dist/collection/components/popover/test/fixture.js +0 -1
  290. package/dist/collection/components/progress-bar/progress-bar.js +22 -26
  291. package/dist/collection/components/radio/radio.js +62 -98
  292. package/dist/collection/components/radio-group/radio-group.js +64 -99
  293. package/dist/collection/components/radio-group/test/fixtures.js +0 -2
  294. package/dist/collection/components/range/range.js +220 -289
  295. package/dist/collection/components/refresher/refresher.js +79 -105
  296. package/dist/collection/components/refresher-content/refresher-content.js +3 -40
  297. package/dist/collection/components/reorder/reorder.js +0 -1
  298. package/dist/collection/components/reorder-group/reorder-group.js +14 -43
  299. package/dist/collection/components/ripple-effect/ripple-effect.js +12 -11
  300. package/dist/collection/components/route/route.js +9 -38
  301. package/dist/collection/components/route-redirect/route-redirect.js +0 -31
  302. package/dist/collection/components/router/router.js +27 -35
  303. package/dist/collection/components/router/utils/matching.js +0 -1
  304. package/dist/collection/components/router-link/router-link.js +10 -35
  305. package/dist/collection/components/router-outlet/router-outlet.js +12 -34
  306. package/dist/collection/components/searchbar/searchbar.js +180 -265
  307. package/dist/collection/components/segment/segment.js +76 -113
  308. package/dist/collection/components/segment-button/segment-button.js +44 -44
  309. package/dist/collection/components/segment-view/segment-view.js +12 -23
  310. package/dist/collection/components/select/select.js +127 -240
  311. package/dist/collection/components/select-modal/select-modal.js +11 -12
  312. package/dist/collection/components/select-modal/test/fixtures.js +1 -8
  313. package/dist/collection/components/select-option/select-option.js +7 -44
  314. package/dist/collection/components/select-popover/select-popover.js +10 -25
  315. package/dist/collection/components/select-popover/test/fixtures.js +1 -8
  316. package/dist/collection/components/skeleton-text/skeleton-text.js +6 -10
  317. package/dist/collection/components/spinner/spinner.js +6 -19
  318. package/dist/collection/components/split-pane/split-pane.js +13 -25
  319. package/dist/collection/components/tab/tab.js +4 -15
  320. package/dist/collection/components/tab-bar/tab-bar.js +12 -30
  321. package/dist/collection/components/tab-button/tab-button.js +19 -56
  322. package/dist/collection/components/tabs/tabs.js +17 -31
  323. package/dist/collection/components/text/text.js +0 -6
  324. package/dist/collection/components/textarea/textarea.js +135 -251
  325. package/dist/collection/components/title/title.js +0 -16
  326. package/dist/collection/components/toast/toast.js +97 -211
  327. package/dist/collection/components/toggle/toggle.js +111 -161
  328. package/dist/collection/components/toolbar/toolbar.js +3 -8
  329. package/dist/collection/global/config.js +3 -1
  330. package/dist/collection/utils/gesture/gesture-controller.js +6 -14
  331. package/dist/collection/utils/sanitization/index.js +0 -1
  332. package/dist/collection/utils/test/late-props/late-props.js +69 -0
  333. package/dist/collection/utils/test/playwright/page/event-spy.js +8 -9
  334. package/dist/collection/utils/test/press-keys.js +1 -4
  335. package/dist/docs.json +1 -1
  336. package/dist/esm/{animation-CGFdmGk9.js → animation-TxGPYeDn.js} +1 -1
  337. package/dist/esm/{app-globals-CYmMeGdU.js → app-globals-Do8rJest.js} +1 -1
  338. package/dist/esm/{button-active-BDOsVAiZ.js → button-active-ChA4D-ml.js} +2 -2
  339. package/dist/esm/{format-Dcwga61t.js → format-CVk5e_GP.js} +2 -2
  340. package/dist/esm/{framework-delegate-BHTU2Ip9.js → framework-delegate-DaLWnISz.js} +1 -1
  341. package/dist/esm/{gesture-controller-TXPDHL13.js → gesture-controller-B_gJaBk0.js} +6 -14
  342. package/dist/esm/{hardware-back-button-gLJHMX_F.js → hardware-back-button-D8W4L0JP.js} +1 -1
  343. package/dist/esm/{helpers-CAGf8Wgp.js → helpers-BIgoInJU.js} +1 -1
  344. package/dist/esm/{index-DcPaH5uL.js → index-BmLuEdV7.js} +1 -1
  345. package/dist/esm/{index-T0JxBI8V.js → index-BmOR8tCv.js} +2 -2
  346. package/dist/esm/{index-CqneaaGd.js → index-C5ZdL0qp.js} +5 -5
  347. package/dist/esm/{index-WlteAIqz.js → index-C8Dsa6li.js} +4 -4
  348. package/dist/esm/{index-ChhhtsGZ.js → index-CKYcsw8f.js} +3 -1
  349. package/dist/esm/{index-Clc-28O1.js → index-DHw2lZxe.js} +2 -2
  350. package/dist/esm/{index-CKM1DdGm.js → index-elneMH8y.js} +1 -2
  351. package/dist/esm/index.js +14 -14
  352. package/dist/esm/{input-shims-B8sfni1e.js → input-shims-09NN97kF.js} +3 -3
  353. package/dist/esm/{input.utils-B1ValN_N.js → input.utils-BxyH9l1w.js} +1 -1
  354. package/dist/esm/ion-accordion_2.entry.js +335 -364
  355. package/dist/esm/ion-action-sheet.entry.js +60 -140
  356. package/dist/esm/ion-alert.entry.js +67 -159
  357. package/dist/esm/ion-app_8.entry.js +163 -258
  358. package/dist/esm/ion-avatar_3.entry.js +2 -8
  359. package/dist/esm/ion-back-button.entry.js +21 -45
  360. package/dist/esm/ion-backdrop.entry.js +14 -18
  361. package/dist/esm/ion-breadcrumb_2.entry.js +117 -195
  362. package/dist/esm/ion-button_2.entry.js +61 -130
  363. package/dist/esm/ion-card_5.entry.js +28 -80
  364. package/dist/esm/ion-checkbox.entry.js +98 -147
  365. package/dist/esm/ion-chip.entry.js +10 -16
  366. package/dist/esm/ion-col_3.entry.js +6 -126
  367. package/dist/esm/ion-datetime-button.entry.js +232 -248
  368. package/dist/esm/ion-datetime.entry.js +775 -953
  369. package/dist/esm/ion-fab_3.entry.js +78 -136
  370. package/dist/esm/ion-img.entry.js +11 -31
  371. package/dist/esm/ion-infinite-scroll_2.entry.js +71 -98
  372. package/dist/esm/ion-input-otp.entry.js +352 -424
  373. package/dist/esm/ion-input-password-toggle.entry.js +14 -29
  374. package/dist/esm/ion-input.entry.js +158 -302
  375. package/dist/esm/ion-item-option_3.entry.js +54 -98
  376. package/dist/esm/ion-item_8.entry.js +61 -157
  377. package/dist/esm/ion-loading.entry.js +54 -131
  378. package/dist/esm/ion-menu_3.entry.js +94 -158
  379. package/dist/esm/ion-modal.entry.js +206 -362
  380. package/dist/esm/ion-nav_2.entry.js +26 -78
  381. package/dist/esm/ion-picker-column-option.entry.js +23 -33
  382. package/dist/esm/ion-picker-column.entry.js +389 -410
  383. package/dist/esm/ion-picker.entry.js +390 -400
  384. package/dist/esm/ion-popover.entry.js +184 -292
  385. package/dist/esm/ion-progress-bar.entry.js +23 -29
  386. package/dist/esm/ion-radio_2.entry.js +128 -201
  387. package/dist/esm/ion-range.entry.js +223 -293
  388. package/dist/esm/ion-refresher_2.entry.js +89 -154
  389. package/dist/esm/ion-reorder_2.entry.js +19 -49
  390. package/dist/esm/ion-ripple-effect.entry.js +13 -13
  391. package/dist/esm/ion-route_4.entry.js +45 -144
  392. package/dist/esm/ion-searchbar.entry.js +182 -268
  393. package/dist/esm/ion-segment-content.entry.js +1 -1
  394. package/dist/esm/ion-segment-view.entry.js +12 -24
  395. package/dist/esm/ion-segment_2.entry.js +122 -161
  396. package/dist/esm/ion-select-modal.entry.js +19 -21
  397. package/dist/esm/ion-select_3.entry.js +151 -319
  398. package/dist/esm/ion-spinner.entry.js +6 -21
  399. package/dist/esm/ion-split-pane.entry.js +14 -27
  400. package/dist/esm/ion-tab-bar_2.entry.js +32 -89
  401. package/dist/esm/ion-tab_2.entry.js +22 -49
  402. package/dist/esm/ion-text.entry.js +2 -8
  403. package/dist/esm/ion-textarea.entry.js +139 -256
  404. package/dist/esm/ion-toast.entry.js +106 -221
  405. package/dist/esm/ion-toggle.entry.js +114 -165
  406. package/dist/esm/{ionic-global-BVB7BrLT.js → ionic-global-lrowsHfi.js} +1 -1
  407. package/dist/esm/ionic.js +5 -5
  408. package/dist/esm/{ios.transition-DXRCmcbC.js → ios.transition-BQhADrk1.js} +4 -4
  409. package/dist/esm/{item-multiple-inputs-rU8VaNNg.js → item-multiple-inputs-D_N3fDkD.js} +1 -1
  410. package/dist/esm/loader.js +5 -5
  411. package/dist/esm/{md.transition-BMngO4i_.js → md.transition-D58NpmRa.js} +4 -4
  412. package/dist/esm/{overlays-CPmIs9Ls.js → overlays-BpnIFlXI.js} +6 -6
  413. package/dist/esm/{select-option-render-C4m76VGH.js → select-option-render-lIuu64EV.js} +2 -2
  414. package/dist/esm/{slot-mutation-controller-DiE_C9un.js → slot-mutation-controller-rS_T3FDR.js} +1 -1
  415. package/dist/esm/{status-tap-CHB7KwIb.js → status-tap-CpFQMLl6.js} +3 -3
  416. package/dist/esm/{swipe-back-C9HW1bug.js → swipe-back-rmc7zeNW.js} +4 -4
  417. package/dist/ionic/index.esm.js +1 -1
  418. package/dist/ionic/ionic.esm.js +1 -1
  419. package/dist/ionic/p-05800a02.entry.js +4 -0
  420. package/dist/ionic/p-0eb50dca.entry.js +4 -0
  421. package/dist/ionic/p-16e9f542.entry.js +4 -0
  422. package/dist/ionic/p-18d532a3.entry.js +4 -0
  423. package/dist/ionic/p-1db2afb4.entry.js +4 -0
  424. package/dist/ionic/p-1df75f9e.entry.js +4 -0
  425. package/dist/ionic/p-295ff427.entry.js +4 -0
  426. package/dist/ionic/p-34b9379b.entry.js +4 -0
  427. package/dist/ionic/p-39a8d4e0.entry.js +4 -0
  428. package/dist/ionic/p-4437015c.entry.js +4 -0
  429. package/dist/ionic/p-478035a7.entry.js +4 -0
  430. package/dist/ionic/p-485fb218.entry.js +4 -0
  431. package/dist/ionic/p-48c859fe.entry.js +4 -0
  432. package/dist/ionic/p-49b9d405.entry.js +4 -0
  433. package/dist/ionic/p-56307aea.entry.js +4 -0
  434. package/dist/ionic/p-5b906fd6.entry.js +4 -0
  435. package/dist/ionic/p-5ee2d7b1.entry.js +4 -0
  436. package/dist/ionic/p-5f216b79.entry.js +4 -0
  437. package/dist/ionic/p-61c799d1.entry.js +4 -0
  438. package/dist/ionic/p-63bbba8d.entry.js +4 -0
  439. package/dist/ionic/p-68507e70.entry.js +4 -0
  440. package/dist/ionic/{p-ded69ceb.entry.js → p-6f048604.entry.js} +1 -1
  441. package/dist/ionic/p-70ee8888.entry.js +4 -0
  442. package/dist/ionic/p-72ad7c64.entry.js +4 -0
  443. package/dist/ionic/p-75887ee0.entry.js +4 -0
  444. package/dist/ionic/p-873a315a.entry.js +4 -0
  445. package/dist/ionic/p-881b6954.entry.js +4 -0
  446. package/dist/ionic/p-886d9e66.entry.js +4 -0
  447. package/dist/ionic/p-8dd4c026.entry.js +4 -0
  448. package/dist/ionic/p-8e007f11.entry.js +4 -0
  449. package/dist/ionic/p-8f51110d.entry.js +4 -0
  450. package/dist/ionic/p-90ba736e.entry.js +4 -0
  451. package/dist/ionic/p-959df5f8.entry.js +4 -0
  452. package/dist/ionic/p-9e455875.entry.js +4 -0
  453. package/dist/ionic/{p-CBR_W98Z.js → p-9wczfs_v.js} +1 -1
  454. package/dist/ionic/p-B1Y7LZhV.js +4 -0
  455. package/dist/ionic/p-B5RyLYvl.js +4 -0
  456. package/dist/ionic/{p-CPcPmkGv.js → p-BQv5i5Kf.js} +1 -1
  457. package/{components/p-8FN7p701.js → dist/ionic/p-BZVE25Gu.js} +1 -1
  458. package/{components/p-DFvZn99E.js → dist/ionic/p-BZxjcGRP.js} +1 -1
  459. package/dist/ionic/p-B_gJaBk0.js +4 -0
  460. package/dist/ionic/p-BnGA34Pd.js +4 -0
  461. package/dist/ionic/p-ByLaqOPm.js +4 -0
  462. package/dist/ionic/p-C06QNN45.js +4 -0
  463. package/dist/ionic/p-C4IBDDj6.js +4 -0
  464. package/dist/ionic/p-CCVlNZ__.js +4 -0
  465. package/dist/ionic/{p-CMRtMbJc.js → p-CDBop-kz.js} +1 -1
  466. package/dist/ionic/p-CKYcsw8f.js +5 -0
  467. package/dist/ionic/p-CazSodad.js +4 -0
  468. package/{components/p-ia3IDdJS.js → dist/ionic/p-ClrlQU2y.js} +1 -1
  469. package/dist/ionic/{p-UIBJkZf8.js → p-D0YpjgON.js} +1 -1
  470. package/dist/ionic/p-D0dfUysx.js +4 -0
  471. package/dist/ionic/{p-BB0LlG4y.js → p-D9yvytgv.js} +1 -1
  472. package/{components/p-C5KYjZWD.js → dist/ionic/p-DF_Uqql8.js} +1 -1
  473. package/dist/ionic/{p-BYEAtHr-.js → p-DXJgZWgi.js} +1 -1
  474. package/dist/ionic/{p-D94_RztK.js → p-DdhHqKj-.js} +1 -1
  475. package/dist/ionic/p-De0eY881.js +4 -0
  476. package/dist/ionic/p-DgUL3JbO.js +4 -0
  477. package/dist/ionic/{p-7CBuOvEo.js → p-RzUn7cKs.js} +1 -1
  478. package/dist/ionic/p-VquyMbjp.js +4 -0
  479. package/dist/ionic/p-a0fee899.entry.js +4 -0
  480. package/dist/ionic/p-a54bcd16.entry.js +4 -0
  481. package/dist/ionic/p-aebc4d69.entry.js +4 -0
  482. package/dist/ionic/p-b5f37106.entry.js +4 -0
  483. package/dist/ionic/{p-40424a88.entry.js → p-b62bfce8.entry.js} +1 -1
  484. package/dist/ionic/p-b7a11b58.entry.js +4 -0
  485. package/dist/ionic/p-bbf6878c.entry.js +4 -0
  486. package/dist/ionic/p-c49165af.entry.js +4 -0
  487. package/dist/ionic/p-cad4eccf.entry.js +4 -0
  488. package/dist/ionic/p-cdc5115e.entry.js +4 -0
  489. package/dist/ionic/p-d3384a40.entry.js +4 -0
  490. package/dist/ionic/p-d8bae128.entry.js +4 -0
  491. package/dist/ionic/p-d8deff43.entry.js +4 -0
  492. package/dist/ionic/p-ddfb7e5f.entry.js +4 -0
  493. package/dist/ionic/p-e538f18d.entry.js +4 -0
  494. package/dist/ionic/p-f376876b.entry.js +4 -0
  495. package/dist/ionic/p-f7dd1ed9.entry.js +4 -0
  496. package/dist/ionic/p-fbd83d4c.entry.js +4 -0
  497. package/dist/types/components/refresher/refresher.d.ts +7 -0
  498. package/hydrate/index.js +5450 -8380
  499. package/hydrate/index.mjs +5450 -8380
  500. package/package.json +1 -1
  501. package/components/p--m5cCjbK.js +0 -4
  502. package/components/p-B4uHHhPK.js +0 -4
  503. package/components/p-BNJOu1Q2.js +0 -4
  504. package/components/p-BOvLNVKq.js +0 -4
  505. package/components/p-BeamQXHF.js +0 -4
  506. package/components/p-BjluhQMI.js +0 -4
  507. package/components/p-BlsIikdZ.js +0 -4
  508. package/components/p-BrD9Xv62.js +0 -4
  509. package/components/p-BvJqoZ5R.js +0 -4
  510. package/components/p-Bz6z3Asd.js +0 -4
  511. package/components/p-C6HnVvHO.js +0 -4
  512. package/components/p-C7jvh5Wy.js +0 -4
  513. package/components/p-C9BGR5fy.js +0 -4
  514. package/components/p-CB-y1CdP.js +0 -4
  515. package/components/p-CHH3loEE.js +0 -4
  516. package/components/p-CJKUWjmg.js +0 -4
  517. package/components/p-CMLAwl_N.js +0 -4
  518. package/components/p-CejmQs3h.js +0 -4
  519. package/components/p-CtZqa4HM.js +0 -4
  520. package/components/p-D9qIVSWm.js +0 -4
  521. package/components/p-DE-3iMNW.js +0 -4
  522. package/components/p-DHFt2rdc.js +0 -4
  523. package/components/p-D_RCyzwu.js +0 -4
  524. package/components/p-D_tD8r3L.js +0 -4
  525. package/components/p-DjCtLZbF.js +0 -4
  526. package/components/p-Dmd2xqCe.js +0 -4
  527. package/components/p-G6JR-cr_.js +0 -4
  528. package/components/p-GG5GhznE.js +0 -4
  529. package/components/p-TXPDHL13.js +0 -4
  530. package/components/p-_IKFD3ID.js +0 -4
  531. package/components/p-dKq2jIum.js +0 -4
  532. package/components/p-iYhH60Tc.js +0 -4
  533. package/dist/ionic/p-06ec7136.entry.js +0 -4
  534. package/dist/ionic/p-09fe4fa3.entry.js +0 -4
  535. package/dist/ionic/p-10d45a07.entry.js +0 -4
  536. package/dist/ionic/p-208c8a07.entry.js +0 -4
  537. package/dist/ionic/p-212474fa.entry.js +0 -4
  538. package/dist/ionic/p-2eef1396.entry.js +0 -4
  539. package/dist/ionic/p-347e005d.entry.js +0 -4
  540. package/dist/ionic/p-3a0b3f1d.entry.js +0 -4
  541. package/dist/ionic/p-3b071259.entry.js +0 -4
  542. package/dist/ionic/p-4204184c.entry.js +0 -4
  543. package/dist/ionic/p-47464391.entry.js +0 -4
  544. package/dist/ionic/p-4f9c9126.entry.js +0 -4
  545. package/dist/ionic/p-5JsKPLJD.js +0 -4
  546. package/dist/ionic/p-5bc485c6.entry.js +0 -4
  547. package/dist/ionic/p-603a61e6.entry.js +0 -4
  548. package/dist/ionic/p-60576951.entry.js +0 -4
  549. package/dist/ionic/p-67a81d33.entry.js +0 -4
  550. package/dist/ionic/p-6affb775.entry.js +0 -4
  551. package/dist/ionic/p-6f120c25.entry.js +0 -4
  552. package/dist/ionic/p-71c82b60.entry.js +0 -4
  553. package/dist/ionic/p-79325ffe.entry.js +0 -4
  554. package/dist/ionic/p-7e4d51fa.entry.js +0 -4
  555. package/dist/ionic/p-7f5d4664.entry.js +0 -4
  556. package/dist/ionic/p-80ee82fc.entry.js +0 -4
  557. package/dist/ionic/p-84af7dbc.entry.js +0 -4
  558. package/dist/ionic/p-89ca830a.entry.js +0 -4
  559. package/dist/ionic/p-93b8ec8f.entry.js +0 -4
  560. package/dist/ionic/p-946f65c2.entry.js +0 -4
  561. package/dist/ionic/p-9c4b39fb.entry.js +0 -4
  562. package/dist/ionic/p-B1NEZUzQ.js +0 -4
  563. package/dist/ionic/p-B1ck5iy-.js +0 -4
  564. package/dist/ionic/p-B4FrqdW0.js +0 -4
  565. package/dist/ionic/p-C-94tAim.js +0 -4
  566. package/dist/ionic/p-C-eHZMYE.js +0 -4
  567. package/dist/ionic/p-CaRuIadB.js +0 -4
  568. package/dist/ionic/p-ChhhtsGZ.js +0 -5
  569. package/dist/ionic/p-CzS1qWve.js +0 -4
  570. package/dist/ionic/p-DjjfauRM.js +0 -4
  571. package/dist/ionic/p-DkUB-ROc.js +0 -4
  572. package/dist/ionic/p-DplOqGUv.js +0 -4
  573. package/dist/ionic/p-Dst_XmZh.js +0 -4
  574. package/dist/ionic/p-TXPDHL13.js +0 -4
  575. package/dist/ionic/p-a438b193.entry.js +0 -4
  576. package/dist/ionic/p-babaaaa7.entry.js +0 -4
  577. package/dist/ionic/p-be08d500.entry.js +0 -4
  578. package/dist/ionic/p-be9a4f51.entry.js +0 -4
  579. package/dist/ionic/p-c00d3092.entry.js +0 -4
  580. package/dist/ionic/p-c36dc8f5.entry.js +0 -4
  581. package/dist/ionic/p-c72a7e17.entry.js +0 -4
  582. package/dist/ionic/p-c8edd88c.entry.js +0 -4
  583. package/dist/ionic/p-ce0e380b.entry.js +0 -4
  584. package/dist/ionic/p-ce32912b.entry.js +0 -4
  585. package/dist/ionic/p-d07cf130.entry.js +0 -4
  586. package/dist/ionic/p-d27edeb3.entry.js +0 -4
  587. package/dist/ionic/p-d5d2c506.entry.js +0 -4
  588. package/dist/ionic/p-d5e31ca9.entry.js +0 -4
  589. package/dist/ionic/p-de91444f.entry.js +0 -4
  590. package/dist/ionic/p-df72866d.entry.js +0 -4
  591. package/dist/ionic/p-e47e3151.entry.js +0 -4
  592. package/dist/ionic/p-e621e5e8.entry.js +0 -4
  593. package/dist/ionic/p-eea9cf93.entry.js +0 -4
  594. package/dist/ionic/p-f402f5a4.entry.js +0 -4
  595. package/dist/ionic/p-fe1bfbcf.entry.js +0 -4
  596. package/dist/ionic/p-ffb90460.entry.js +0 -4
@@ -3,19 +3,19 @@
3
3
  */
4
4
  'use strict';
5
5
 
6
- var index = require('./index-uvry__L4.js');
6
+ var index = require('./index-BrVMoqUk.js');
7
7
  var focusVisible = require('./focus-visible-CCvKiLh3.js');
8
- var helpers = require('./helpers-YPQybDph.js');
9
- var overlays = require('./overlays-KaNVDNqC.js');
8
+ var helpers = require('./helpers-Dj5o76mq.js');
9
+ var overlays = require('./overlays-Bg0auTQa.js');
10
10
  var dir = require('./dir-zwDPRE5K.js');
11
11
  var theme = require('./theme-Bw0rpaNN.js');
12
12
  var index$1 = require('./index-wOmugbdg.js');
13
- var ionicGlobal = require('./ionic-global-k6hOWWpn.js');
14
- var format = require('./format-pp0Du3K-.js');
13
+ var ionicGlobal = require('./ionic-global-DvgIzM2F.js');
14
+ var format = require('./format-D7ig6Vm0.js');
15
15
  require('./index-DkNv4J_i.js');
16
- require('./hardware-back-button-fqpYh-kd.js');
17
- require('./framework-delegate-Dfo5XsGv.js');
18
- require('./gesture-controller-BDUH7687.js');
16
+ require('./hardware-back-button-JOAEFSzc.js');
17
+ require('./framework-delegate-BZUx4TnE.js');
18
+ require('./gesture-controller-CeJslptU.js');
19
19
 
20
20
  /**
21
21
  * Returns the current date as
@@ -768,144 +768,781 @@ const Datetime = class {
768
768
  this.ionBlur = index.createEvent(this, "ionBlur", 7);
769
769
  this.ionStyle = index.createEvent(this, "ionStyle", 7);
770
770
  this.ionRender = index.createEvent(this, "ionRender", 7);
771
+ this.inputId = `ion-dt-${datetimeIds++}`;
772
+ /**
773
+ * Set true only by `visibleCallback`. Lets `hiddenCallback` ignore the
774
+ * synthetic "not intersecting" entry IntersectionObserver fires on
775
+ * `observe()` when the host mounts offscreen.
776
+ *
777
+ * Don't reset this in `disconnectedCallback`. Overlays disconnect and
778
+ * reconnect the host without re-creating the observers, so a reset there
779
+ * makes `hiddenCallback` miss the dismissal.
780
+ */
781
+ this.hasBeenIntersecting = false;
782
+ this.prevPresentation = null;
783
+ this.showMonthAndYear = false;
784
+ this.activeParts = [];
785
+ this.workingParts = {
786
+ month: 5,
787
+ day: 28,
788
+ year: 2021,
789
+ hour: 13,
790
+ minute: 52,
791
+ ampm: 'pm',
792
+ isAdjacentDay: false,
793
+ };
794
+ this.isTimePopoverOpen = false;
795
+ /**
796
+ * The name of the control, which is submitted with the form data.
797
+ */
798
+ this.name = this.inputId;
799
+ /**
800
+ * If `true`, the user cannot interact with the datetime.
801
+ */
802
+ this.disabled = false;
803
+ /**
804
+ * If `true`, the datetime appears normal but the selected date cannot be changed.
805
+ */
806
+ this.readonly = false;
807
+ /**
808
+ * If `true`, the datetime calendar displays a six-week (42-day) layout,
809
+ * including days from the previous and next months to fill the grid.
810
+ * These adjacent days are selectable unless disabled.
811
+ */
812
+ this.showAdjacentDays = false;
813
+ /**
814
+ * Which values you want to select. `"date"` will show
815
+ * a calendar picker to select the month, day, and year. `"time"`
816
+ * will show a time picker to select the hour, minute, and (optionally)
817
+ * AM/PM. `"date-time"` will show the date picker first and time picker second.
818
+ * `"time-date"` will show the time picker first and date picker second.
819
+ */
820
+ this.presentation = 'date-time';
821
+ /**
822
+ * The text to display on the picker's cancel button.
823
+ */
824
+ this.cancelText = 'Cancel';
825
+ /**
826
+ * The text to display on the picker's "Done" button.
827
+ */
828
+ this.doneText = 'Done';
829
+ /**
830
+ * The text to display on the picker's "Clear" button.
831
+ */
832
+ this.clearText = 'Clear';
833
+ /**
834
+ * The locale to use for `ion-datetime`. This
835
+ * impacts month and day name formatting.
836
+ * The `"default"` value refers to the default
837
+ * locale set by your device.
838
+ */
839
+ this.locale = 'default';
840
+ /**
841
+ * The first day of the week to use for `ion-datetime`. The
842
+ * default value is `0` and represents Sunday.
843
+ */
844
+ this.firstDayOfWeek = 0;
845
+ /**
846
+ * If `true`, multiple dates can be selected at once. Only
847
+ * applies to `presentation="date"` and `preferWheel="false"`.
848
+ */
849
+ this.multiple = false;
850
+ /**
851
+ * If `true`, a header will be shown above the calendar
852
+ * picker. This will include both the slotted title, and
853
+ * the selected date.
854
+ */
855
+ this.showDefaultTitle = false;
856
+ /**
857
+ * If `true`, the default "Cancel" and "OK" buttons
858
+ * will be rendered at the bottom of the `ion-datetime`
859
+ * component. Developers can also use the `button` slot
860
+ * if they want to customize these buttons. If custom
861
+ * buttons are set in the `button` slot then the
862
+ * default buttons will not be rendered.
863
+ */
864
+ this.showDefaultButtons = false;
865
+ /**
866
+ * If `true`, a "Clear" button will be rendered alongside
867
+ * the default "Cancel" and "OK" buttons at the bottom of the `ion-datetime`
868
+ * component. Developers can also use the `button` slot
869
+ * if they want to customize these buttons. If custom
870
+ * buttons are set in the `button` slot then the
871
+ * default buttons will not be rendered.
872
+ */
873
+ this.showClearButton = false;
874
+ /**
875
+ * If `true`, the default "Time" label will be rendered
876
+ * for the time selector of the `ion-datetime` component.
877
+ * Developers can also use the `time-label` slot
878
+ * if they want to customize this label. If a custom
879
+ * label is set in the `time-label` slot then the
880
+ * default label will not be rendered.
881
+ */
882
+ this.showDefaultTimeLabel = true;
883
+ /**
884
+ * If `cover`, the `ion-datetime` will expand to cover the full width of its container.
885
+ * If `fixed`, the `ion-datetime` will have a fixed width.
886
+ */
887
+ this.size = 'fixed';
888
+ /**
889
+ * If `true`, a wheel picker will be rendered instead of a calendar grid
890
+ * where possible. If `false`, a calendar grid will be rendered instead of
891
+ * a wheel picker where possible.
892
+ *
893
+ * A wheel picker can be rendered instead of a grid when `presentation` is
894
+ * one of the following values: `"date"`, `"date-time"`, or `"time-date"`.
895
+ *
896
+ * A wheel picker will always be rendered regardless of
897
+ * the `preferWheel` value when `presentation` is one of the following values:
898
+ * `"time"`, `"month"`, `"month-year"`, or `"year"`.
899
+ */
900
+ this.preferWheel = false;
901
+ this.warnIfIncorrectValueUsage = () => {
902
+ const { multiple, value } = this;
903
+ if (!multiple && Array.isArray(value)) {
904
+ /**
905
+ * We do some processing on the `value` array so
906
+ * that it looks more like an array when logged to
907
+ * the console.
908
+ * Example given ['a', 'b']
909
+ * Default toString() behavior: a,b
910
+ * Custom behavior: ['a', 'b']
911
+ */
912
+ index.printIonWarning(`[ion-datetime] - An array of values was passed, but multiple is "false". This is incorrect usage and may result in unexpected behaviors. To dismiss this warning, pass a string to the "value" property when multiple="false".
913
+
914
+ Value Passed: [${value.map((v) => `'${v}'`).join(', ')}]
915
+ `, this.el);
916
+ }
917
+ };
918
+ this.setValue = (value) => {
919
+ this.value = value;
920
+ this.ionChange.emit({ value });
921
+ };
922
+ /**
923
+ * Returns the DatetimePart interface
924
+ * to use when rendering an initial set of
925
+ * data. This should be used when rendering an
926
+ * interface in an environment where the `value`
927
+ * may not be set. This function works
928
+ * by returning the first selected date and then
929
+ * falling back to defaultParts if no active date
930
+ * is selected.
931
+ */
932
+ this.getActivePartsWithFallback = () => {
933
+ const { defaultParts } = this;
934
+ return this.getActivePart() ?? defaultParts;
935
+ };
936
+ this.getActivePart = () => {
937
+ const { activeParts } = this;
938
+ return Array.isArray(activeParts) ? activeParts[0] : activeParts;
939
+ };
940
+ this.closeParentOverlay = (role) => {
941
+ const popoverOrModal = this.el.closest('ion-modal, ion-popover');
942
+ if (popoverOrModal) {
943
+ popoverOrModal.dismiss(undefined, role);
944
+ }
945
+ };
946
+ this.setWorkingParts = (parts) => {
947
+ this.workingParts = {
948
+ ...parts,
949
+ };
950
+ };
951
+ this.setActiveParts = (parts, removeDate = false) => {
952
+ /** if the datetime component is in readonly mode,
953
+ * allow browsing of the calendar without changing
954
+ * the set value
955
+ */
956
+ if (this.readonly) {
957
+ return;
958
+ }
959
+ const { multiple, minParts, maxParts, activeParts } = this;
960
+ /**
961
+ * When setting the active parts, it is possible
962
+ * to set invalid data. For example,
963
+ * when updating January 31 to February,
964
+ * February 31 does not exist. As a result
965
+ * we need to validate the active parts and
966
+ * ensure that we are only setting valid dates.
967
+ * Additionally, we need to update the working parts
968
+ * too in the event that the validated parts are different.
969
+ */
970
+ const validatedParts = format.validateParts(parts, minParts, maxParts);
971
+ this.setWorkingParts(validatedParts);
972
+ if (multiple) {
973
+ const activePartsArray = Array.isArray(activeParts) ? activeParts : [activeParts];
974
+ if (removeDate) {
975
+ this.activeParts = activePartsArray.filter((p) => !format.isSameDay(p, validatedParts));
976
+ }
977
+ else {
978
+ this.activeParts = [...activePartsArray, validatedParts];
979
+ }
980
+ }
981
+ else {
982
+ this.activeParts = {
983
+ ...validatedParts,
984
+ };
985
+ }
986
+ const hasSlottedButtons = this.el.querySelector('[slot="buttons"]') !== null;
987
+ if (hasSlottedButtons || this.showDefaultButtons) {
988
+ return;
989
+ }
990
+ this.confirm();
991
+ };
992
+ this.initializeKeyboardListeners = () => {
993
+ const calendarBodyRef = this.calendarBodyRef;
994
+ if (!calendarBodyRef) {
995
+ return;
996
+ }
997
+ const root = this.el.shadowRoot;
998
+ /**
999
+ * Get a reference to the month
1000
+ * element we are currently viewing.
1001
+ */
1002
+ const currentMonth = calendarBodyRef.querySelector('.calendar-month:nth-of-type(2)');
1003
+ /**
1004
+ * When focusing the calendar body, we want to pass focus
1005
+ * to the working day, but other days should
1006
+ * only be accessible using the arrow keys. Pressing
1007
+ * Tab should jump between bodies of selectable content.
1008
+ */
1009
+ const checkCalendarBodyFocus = (ev) => {
1010
+ const record = ev[0];
1011
+ /**
1012
+ * If calendar body was already focused
1013
+ * when this fired or if the calendar body
1014
+ * if not currently focused, we should not re-focus
1015
+ * the inner day.
1016
+ */
1017
+ if (record.oldValue?.includes('ion-focused') || !calendarBodyRef.classList.contains('ion-focused')) {
1018
+ return;
1019
+ }
1020
+ this.focusWorkingDay(currentMonth);
1021
+ };
1022
+ const mo = new MutationObserver(checkCalendarBodyFocus);
1023
+ mo.observe(calendarBodyRef, { attributeFilter: ['class'], attributeOldValue: true });
1024
+ this.destroyKeyboardMO = () => {
1025
+ mo?.disconnect();
1026
+ };
1027
+ /**
1028
+ * We must use keydown not keyup as we want
1029
+ * to prevent scrolling when using the arrow keys.
1030
+ */
1031
+ calendarBodyRef.addEventListener('keydown', (ev) => {
1032
+ const activeElement = root.activeElement;
1033
+ if (!activeElement || !activeElement.classList.contains('calendar-day')) {
1034
+ return;
1035
+ }
1036
+ const parts = format.getPartsFromCalendarDay(activeElement);
1037
+ let partsToFocus;
1038
+ switch (ev.key) {
1039
+ case 'ArrowDown':
1040
+ ev.preventDefault();
1041
+ partsToFocus = format.getNextWeek(parts);
1042
+ break;
1043
+ case 'ArrowUp':
1044
+ ev.preventDefault();
1045
+ partsToFocus = format.getPreviousWeek(parts);
1046
+ break;
1047
+ case 'ArrowRight':
1048
+ ev.preventDefault();
1049
+ partsToFocus = format.getNextDay(parts);
1050
+ break;
1051
+ case 'ArrowLeft':
1052
+ ev.preventDefault();
1053
+ partsToFocus = format.getPreviousDay(parts);
1054
+ break;
1055
+ case 'Home':
1056
+ ev.preventDefault();
1057
+ partsToFocus = format.getStartOfWeek(parts);
1058
+ break;
1059
+ case 'End':
1060
+ ev.preventDefault();
1061
+ partsToFocus = format.getEndOfWeek(parts);
1062
+ break;
1063
+ case 'PageUp':
1064
+ ev.preventDefault();
1065
+ partsToFocus = ev.shiftKey ? format.getPreviousYear(parts) : format.getPreviousMonth(parts);
1066
+ break;
1067
+ case 'PageDown':
1068
+ ev.preventDefault();
1069
+ partsToFocus = ev.shiftKey ? format.getNextYear(parts) : format.getNextMonth(parts);
1070
+ break;
1071
+ /**
1072
+ * Do not preventDefault here
1073
+ * as we do not want to override other
1074
+ * browser defaults such as pressing Enter/Space
1075
+ * to select a day.
1076
+ */
1077
+ default:
1078
+ return;
1079
+ }
1080
+ /**
1081
+ * If the day we want to move focus to is
1082
+ * disabled, do not do anything.
1083
+ */
1084
+ if (isDayDisabled(partsToFocus, this.minParts, this.maxParts)) {
1085
+ return;
1086
+ }
1087
+ this.setWorkingParts({
1088
+ ...this.workingParts,
1089
+ ...partsToFocus,
1090
+ });
1091
+ /**
1092
+ * Give view a chance to re-render
1093
+ * then move focus to the new working day
1094
+ */
1095
+ requestAnimationFrame(() => this.focusWorkingDay(currentMonth));
1096
+ });
1097
+ };
1098
+ this.focusWorkingDay = (currentMonth) => {
1099
+ /**
1100
+ * Get the number of offset days so
1101
+ * we know how much to offset our next selector by
1102
+ * to grab the correct calendar-day element.
1103
+ */
1104
+ const { day, month, year } = this.workingParts;
1105
+ const firstOfMonth = new Date(`${month}/1/${year}`).getDay();
1106
+ const offset = firstOfMonth >= this.firstDayOfWeek
1107
+ ? firstOfMonth - this.firstDayOfWeek
1108
+ : 7 - (this.firstDayOfWeek - firstOfMonth);
1109
+ if (day === null) {
1110
+ return;
1111
+ }
1112
+ /**
1113
+ * Get the calendar day element
1114
+ * and focus it.
1115
+ */
1116
+ const dayEl = currentMonth.querySelector(`.calendar-day-wrapper:nth-of-type(${offset + day}) .calendar-day`);
1117
+ if (dayEl) {
1118
+ dayEl.focus();
1119
+ }
1120
+ };
1121
+ this.processMinParts = () => {
1122
+ const { min, defaultParts } = this;
1123
+ if (min === undefined) {
1124
+ this.minParts = undefined;
1125
+ return;
1126
+ }
1127
+ this.minParts = format.parseMinParts(min, defaultParts);
1128
+ };
1129
+ this.processMaxParts = () => {
1130
+ const { max, defaultParts } = this;
1131
+ if (max === undefined) {
1132
+ this.maxParts = undefined;
1133
+ return;
1134
+ }
1135
+ this.maxParts = format.parseMaxParts(max, defaultParts);
1136
+ };
1137
+ this.initializeCalendarListener = () => {
1138
+ const calendarBodyRef = this.calendarBodyRef;
1139
+ if (!calendarBodyRef) {
1140
+ return;
1141
+ }
1142
+ /**
1143
+ * For performance reasons, we only render 3
1144
+ * months at a time: The current month, the previous
1145
+ * month, and the next month. We have a scroll listener
1146
+ * on the calendar body to append/prepend new months.
1147
+ *
1148
+ * We can do this because Stencil is smart enough to not
1149
+ * re-create the .calendar-month containers, but rather
1150
+ * update the content within those containers.
1151
+ *
1152
+ * As an added bonus, WebKit has some troubles with
1153
+ * scroll-snap-stop: always, so not rendering all of
1154
+ * the months in a row allows us to mostly sidestep
1155
+ * that issue.
1156
+ */
1157
+ const months = calendarBodyRef.querySelectorAll('.calendar-month');
1158
+ const startMonth = months[0];
1159
+ const workingMonth = months[1];
1160
+ const endMonth = months[2];
1161
+ const mode = ionicGlobal.getIonMode(this);
1162
+ const needsiOSRubberBandFix = mode === 'ios' && typeof navigator !== 'undefined' && navigator.maxTouchPoints > 1;
1163
+ /**
1164
+ * Before setting up the scroll listener,
1165
+ * scroll the middle month into view.
1166
+ * scrollIntoView() will scroll entire page
1167
+ * if element is not in viewport. Use scrollLeft instead.
1168
+ */
1169
+ index.writeTask(() => {
1170
+ calendarBodyRef.scrollLeft = startMonth.clientWidth * (dir.isRTL(this.el) ? -1 : 1);
1171
+ const getChangedMonth = (parts) => {
1172
+ const box = calendarBodyRef.getBoundingClientRect();
1173
+ /**
1174
+ * If the current scroll position is all the way to the left
1175
+ * then we have scrolled to the previous month.
1176
+ * Otherwise, assume that we have scrolled to the next
1177
+ * month. We have a tolerance of 2px to account for
1178
+ * sub pixel rendering.
1179
+ *
1180
+ * Check below the next line ensures that we did not
1181
+ * swipe and abort (i.e. we swiped but we are still on the current month).
1182
+ */
1183
+ const condition = dir.isRTL(this.el) ? calendarBodyRef.scrollLeft >= -2 : calendarBodyRef.scrollLeft <= 2;
1184
+ const month = condition ? startMonth : endMonth;
1185
+ /**
1186
+ * The edge of the month must be lined up with
1187
+ * the edge of the calendar body in order for
1188
+ * the component to update. Otherwise, it
1189
+ * may be the case that the user has paused their
1190
+ * swipe or the browser has not finished snapping yet.
1191
+ * Rather than check if the x values are equal,
1192
+ * we give it a tolerance of 2px to account for
1193
+ * sub pixel rendering.
1194
+ */
1195
+ const monthBox = month.getBoundingClientRect();
1196
+ if (Math.abs(monthBox.x - box.x) > 2)
1197
+ return;
1198
+ /**
1199
+ * If we're force-rendering a month, assume we've
1200
+ * scrolled to that and return it.
1201
+ *
1202
+ * If forceRenderDate is ever used in a context where the
1203
+ * forced month is not immediately auto-scrolled to, this
1204
+ * should be updated to also check whether `month` has the
1205
+ * same month and year as the forced date.
1206
+ */
1207
+ const { forceRenderDate } = this;
1208
+ if (forceRenderDate !== undefined) {
1209
+ return { month: forceRenderDate.month, year: forceRenderDate.year, day: forceRenderDate.day };
1210
+ }
1211
+ /**
1212
+ * From here, we can determine if the start
1213
+ * month or the end month was scrolled into view.
1214
+ * If no month was changed, then we can return from
1215
+ * the scroll callback early.
1216
+ */
1217
+ if (month === startMonth) {
1218
+ return format.getPreviousMonth(parts);
1219
+ }
1220
+ else if (month === endMonth) {
1221
+ return format.getNextMonth(parts);
1222
+ }
1223
+ else {
1224
+ return;
1225
+ }
1226
+ };
1227
+ const updateActiveMonth = () => {
1228
+ if (needsiOSRubberBandFix) {
1229
+ calendarBodyRef.style.removeProperty('pointer-events');
1230
+ appliediOSRubberBandFix = false;
1231
+ }
1232
+ /**
1233
+ * If the month did not change
1234
+ * then we can return early.
1235
+ */
1236
+ const newDate = getChangedMonth(this.workingParts);
1237
+ if (!newDate)
1238
+ return;
1239
+ const { month, day, year } = newDate;
1240
+ if (isMonthDisabled({ month, year, day: null }, {
1241
+ minParts: { ...this.minParts, day: null },
1242
+ maxParts: { ...this.maxParts, day: null },
1243
+ })) {
1244
+ return;
1245
+ }
1246
+ /**
1247
+ * Prevent scrolling for other browsers
1248
+ * to give the DOM time to update and the container
1249
+ * time to properly snap.
1250
+ */
1251
+ calendarBodyRef.style.setProperty('overflow', 'hidden');
1252
+ /**
1253
+ * Use a writeTask here to ensure
1254
+ * that the state is updated and the
1255
+ * correct month is scrolled into view
1256
+ * in the same frame. This is not
1257
+ * typically a problem on newer devices
1258
+ * but older/slower device may have a flicker
1259
+ * if we did not do this.
1260
+ */
1261
+ index.writeTask(() => {
1262
+ this.setWorkingParts({
1263
+ ...this.workingParts,
1264
+ month,
1265
+ day: day,
1266
+ year,
1267
+ });
1268
+ calendarBodyRef.scrollLeft = workingMonth.clientWidth * (dir.isRTL(this.el) ? -1 : 1);
1269
+ calendarBodyRef.style.removeProperty('overflow');
1270
+ if (this.resolveForceDateScrolling) {
1271
+ this.resolveForceDateScrolling();
1272
+ }
1273
+ const activeEl = this.el.shadowRoot.activeElement;
1274
+ if (activeEl && activeEl.classList.contains('calendar-day')) {
1275
+ activeEl.closest('.calendar-body')?.focus();
1276
+ }
1277
+ });
1278
+ };
1279
+ /**
1280
+ * When the container finishes scrolling we
1281
+ * need to update the DOM with the selected month.
1282
+ */
1283
+ let scrollTimeout;
1284
+ /**
1285
+ * We do not want to attempt to set pointer-events
1286
+ * multiple times within a single swipe gesture as
1287
+ * that adds unnecessary work to the main thread.
1288
+ */
1289
+ let appliediOSRubberBandFix = false;
1290
+ const scrollCallback = () => {
1291
+ if (scrollTimeout) {
1292
+ clearTimeout(scrollTimeout);
1293
+ }
1294
+ /**
1295
+ * On iOS it is possible to quickly rubber band
1296
+ * the scroll area before the scroll timeout has fired.
1297
+ * This results in users reaching the end of the scrollable
1298
+ * container before the DOM has updated.
1299
+ * By setting `pointer-events: none` we can ensure that
1300
+ * subsequent swipes do not happen while the container
1301
+ * is snapping.
1302
+ */
1303
+ if (!appliediOSRubberBandFix && needsiOSRubberBandFix) {
1304
+ calendarBodyRef.style.setProperty('pointer-events', 'none');
1305
+ appliediOSRubberBandFix = true;
1306
+ }
1307
+ // Wait ~3 frames
1308
+ scrollTimeout = setTimeout(updateActiveMonth, 50);
1309
+ };
1310
+ calendarBodyRef.addEventListener('scroll', scrollCallback);
1311
+ this.destroyCalendarListener = () => {
1312
+ calendarBodyRef.removeEventListener('scroll', scrollCallback);
1313
+ };
1314
+ });
1315
+ };
1316
+ /**
1317
+ * Clean up all listeners except for the overlay
1318
+ * listener. This is so that we can re-create the listeners
1319
+ * if the datetime has been hidden/presented by a modal or popover.
1320
+ */
1321
+ this.destroyInteractionListeners = () => {
1322
+ const { destroyCalendarListener, destroyKeyboardMO } = this;
1323
+ if (destroyCalendarListener !== undefined) {
1324
+ destroyCalendarListener();
1325
+ }
1326
+ if (destroyKeyboardMO !== undefined) {
1327
+ destroyKeyboardMO();
1328
+ }
1329
+ };
1330
+ /**
1331
+ * TODO(FW-6931): Remove this fallback upon solving the root cause
1332
+ * Fallback to ensure the datetime becomes ready even if
1333
+ * IntersectionObserver never reports it as intersecting.
1334
+ *
1335
+ * This is primarily used in environments where the observer
1336
+ * might not fire as expected, such as when running under
1337
+ * synthetic tests that stub IntersectionObserver.
1338
+ */
1339
+ this.ensureReadyIfVisible = () => {
1340
+ if (this.el.classList.contains('datetime-ready')) {
1341
+ return;
1342
+ }
1343
+ const rect = this.el.getBoundingClientRect();
1344
+ if (rect.width === 0 || rect.height === 0) {
1345
+ return;
1346
+ }
1347
+ this.markReady();
1348
+ };
1349
+ this.markReady = () => {
1350
+ if (this.el.classList.contains('datetime-ready')) {
1351
+ return;
1352
+ }
1353
+ this.initializeListeners();
1354
+ /**
1355
+ * TODO FW-2793: Datetime needs a frame to ensure that it
1356
+ * can properly scroll contents into view. As a result
1357
+ * we hide the scrollable content until after that frame
1358
+ * so users do not see the content quickly shifting. The downside
1359
+ * is that the content will pop into view a frame after. Maybe there
1360
+ * is a better way to handle this?
1361
+ */
1362
+ index.writeTask(() => {
1363
+ this.el.classList.add('datetime-ready');
1364
+ });
1365
+ };
1366
+ this.loadTimeoutCleanup = () => {
1367
+ if (this.loadTimeout) {
1368
+ clearTimeout(this.loadTimeout);
1369
+ this.loadTimeout = undefined;
1370
+ }
1371
+ };
1372
+ this.processValue = (value) => {
1373
+ const hasValue = value !== null && value !== undefined && value !== '' && (!Array.isArray(value) || value.length > 0);
1374
+ const valueToProcess = hasValue ? format.parseDate(value) : this.defaultParts;
1375
+ const { minParts, maxParts, workingParts, el } = this;
1376
+ this.warnIfIncorrectValueUsage();
1377
+ /**
1378
+ * Return early if the value wasn't parsed correctly, such as
1379
+ * if an improperly formatted date string was provided.
1380
+ */
1381
+ if (!valueToProcess) {
1382
+ return;
1383
+ }
1384
+ /**
1385
+ * Datetime should only warn of out of bounds values
1386
+ * if set by the user. If the `value` is undefined,
1387
+ * we will default to today's date which may be out
1388
+ * of bounds. In this case, the warning makes it look
1389
+ * like the developer did something wrong which is
1390
+ * not true.
1391
+ */
1392
+ if (hasValue) {
1393
+ format.warnIfValueOutOfBounds(valueToProcess, minParts, maxParts);
1394
+ }
1395
+ /**
1396
+ * If there are multiple values, clamp to the last one.
1397
+ * This is because the last value is the one that the user
1398
+ * has most recently interacted with.
1399
+ */
1400
+ const singleValue = Array.isArray(valueToProcess) ? valueToProcess[valueToProcess.length - 1] : valueToProcess;
1401
+ const targetValue = format.clampDate(singleValue, minParts, maxParts);
1402
+ const { month, day, year, hour, minute } = targetValue;
1403
+ const ampm = format.parseAmPm(hour);
1404
+ /**
1405
+ * Since `activeParts` indicates a value that been explicitly selected
1406
+ * either by the user or the app, only update `activeParts` if the
1407
+ * `value` property is set.
1408
+ */
1409
+ if (hasValue) {
1410
+ if (Array.isArray(valueToProcess)) {
1411
+ this.activeParts = [...valueToProcess];
1412
+ }
1413
+ else {
1414
+ this.activeParts = {
1415
+ month,
1416
+ day,
1417
+ year,
1418
+ hour,
1419
+ minute,
1420
+ ampm,
1421
+ };
1422
+ }
1423
+ }
1424
+ else {
1425
+ /**
1426
+ * Reset the active parts if the value is not set.
1427
+ * This will clear the selected calendar day when
1428
+ * performing a clear action or using the reset() method.
1429
+ */
1430
+ this.activeParts = [];
1431
+ }
1432
+ const didChangeMonth = (month !== undefined && month !== workingParts.month) || (year !== undefined && year !== workingParts.year);
1433
+ const bodyIsVisible = el.classList.contains('datetime-ready');
1434
+ const { isGridStyle, showMonthAndYear } = this;
1435
+ if (isGridStyle && didChangeMonth && bodyIsVisible && !showMonthAndYear) {
1436
+ /**
1437
+ * Only animate if:
1438
+ * 1. We're using grid style (wheel style pickers should just jump to new value)
1439
+ * 2. The month and/or year actually changed, and both are defined (otherwise there's nothing to animate to)
1440
+ * 3. The calendar body is visible (prevents animation when in collapsed datetime-button, for example)
1441
+ * 4. The month/year picker is not open (since you wouldn't see the animation anyway)
1442
+ */
1443
+ this.animateToDate(targetValue);
1444
+ }
1445
+ else {
1446
+ this.setWorkingParts({
1447
+ month,
1448
+ day,
1449
+ year,
1450
+ hour,
1451
+ minute,
1452
+ ampm,
1453
+ });
1454
+ }
1455
+ };
1456
+ this.animateToDate = async (targetValue) => {
1457
+ const { workingParts } = this;
1458
+ /**
1459
+ * Tell other render functions that we need to force the
1460
+ * target month to appear in place of the actual next/prev month.
1461
+ * Because this is a State variable, a rerender will be triggered
1462
+ * automatically, updating the rendered months.
1463
+ */
1464
+ this.forceRenderDate = targetValue;
1465
+ /**
1466
+ * Flag that we've started scrolling to the forced date.
1467
+ * The resolve function will be called by the datetime's
1468
+ * scroll listener when it's done updating everything.
1469
+ * This is a replacement for making prev/nextMonth async,
1470
+ * since the logic we're waiting on is in a listener.
1471
+ */
1472
+ const forceDateScrollingPromise = new Promise((resolve) => {
1473
+ this.resolveForceDateScrolling = resolve;
1474
+ });
1475
+ /**
1476
+ * Animate smoothly to the forced month. This will also update
1477
+ * workingParts and correct the surrounding months for us.
1478
+ */
1479
+ const targetMonthIsBefore = format.isBefore(targetValue, workingParts);
1480
+ targetMonthIsBefore ? this.prevMonth() : this.nextMonth();
1481
+ await forceDateScrollingPromise;
1482
+ this.resolveForceDateScrolling = undefined;
1483
+ this.forceRenderDate = undefined;
1484
+ };
1485
+ this.onFocus = () => {
1486
+ this.ionFocus.emit();
1487
+ };
1488
+ this.onBlur = () => {
1489
+ this.ionBlur.emit();
1490
+ };
1491
+ this.hasValue = () => {
1492
+ return this.value != null;
1493
+ };
1494
+ this.nextMonth = () => {
1495
+ const calendarBodyRef = this.calendarBodyRef;
1496
+ if (!calendarBodyRef) {
1497
+ return;
1498
+ }
1499
+ const nextMonth = calendarBodyRef.querySelector('.calendar-month:last-of-type');
1500
+ if (!nextMonth) {
1501
+ return;
1502
+ }
1503
+ const left = nextMonth.offsetWidth * 2;
1504
+ const scrollMode = index.config.getBoolean('animated', true) ? 'smooth' : 'instant';
1505
+ calendarBodyRef.scrollTo({
1506
+ top: 0,
1507
+ left: left * (dir.isRTL(this.el) ? -1 : 1),
1508
+ behavior: scrollMode,
1509
+ });
1510
+ };
1511
+ this.prevMonth = () => {
1512
+ const calendarBodyRef = this.calendarBodyRef;
1513
+ if (!calendarBodyRef) {
1514
+ return;
1515
+ }
1516
+ const prevMonth = calendarBodyRef.querySelector('.calendar-month:first-of-type');
1517
+ if (!prevMonth) {
1518
+ return;
1519
+ }
1520
+ const left = prevMonth.offsetWidth * 2;
1521
+ const scrollMode = index.config.getBoolean('animated', true) ? 'smooth' : 'instant';
1522
+ calendarBodyRef.scrollTo({
1523
+ top: 0,
1524
+ left: left * (dir.isRTL(this.el) ? 1 : -1),
1525
+ behavior: scrollMode,
1526
+ });
1527
+ };
1528
+ this.toggleMonthAndYearView = () => {
1529
+ this.showMonthAndYear = !this.showMonthAndYear;
1530
+ };
771
1531
  }
772
- inputId = `ion-dt-${datetimeIds++}`;
773
- calendarBodyRef;
774
- popoverRef;
775
- intersectionTrackerRef;
776
- clearFocusVisible;
777
- parsedMinuteValues;
778
- parsedHourValues;
779
- parsedMonthValues;
780
- parsedYearValues;
781
- parsedDayValues;
782
- destroyCalendarListener;
783
- destroyKeyboardMO;
784
- // TODO(FW-2832): types (DatetimeParts causes some errors that need untangling)
785
- minParts;
786
- maxParts;
787
- todayParts;
788
- defaultParts;
789
- loadTimeout;
790
- /**
791
- * Set true only by `visibleCallback`. Lets `hiddenCallback` ignore the
792
- * synthetic "not intersecting" entry IntersectionObserver fires on
793
- * `observe()` when the host mounts offscreen.
794
- *
795
- * Don't reset this in `disconnectedCallback`. Overlays disconnect and
796
- * reconnect the host without re-creating the observers, so a reset there
797
- * makes `hiddenCallback` miss the dismissal.
798
- */
799
- hasBeenIntersecting = false;
800
- prevPresentation = null;
801
- resolveForceDateScrolling;
802
- showMonthAndYear = false;
803
- activeParts = [];
804
- workingParts = {
805
- month: 5,
806
- day: 28,
807
- year: 2021,
808
- hour: 13,
809
- minute: 52,
810
- ampm: 'pm',
811
- isAdjacentDay: false,
812
- };
813
- get el() { return index.getElement(this); }
814
- isTimePopoverOpen = false;
815
- /**
816
- * When defined, will force the datetime to render the month
817
- * containing the specified date. Currently, this should only
818
- * be used to enable immediately auto-scrolling to the new month,
819
- * and should then be reset to undefined once the transition is
820
- * finished and the forced month is now in view.
821
- *
822
- * Applies to grid-style datetimes only.
823
- */
824
- forceRenderDate;
825
- /**
826
- * The color to use from your application's color palette.
827
- * Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`.
828
- * For more information on colors, refer to [theming](/docs/theming/basics).
829
- */
830
- color;
831
- /**
832
- * The name of the control, which is submitted with the form data.
833
- */
834
- name = this.inputId;
835
- /**
836
- * If `true`, the user cannot interact with the datetime.
837
- */
838
- disabled = false;
839
- /**
840
- * Formatting options for dates and times.
841
- * Should include a 'date' and/or 'time' object, each of which is of type [Intl.DateTimeFormatOptions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#options).
842
- *
843
- */
844
- formatOptions;
845
1532
  formatOptionsChanged() {
846
1533
  const { el, formatOptions, presentation } = this;
847
1534
  checkForPresentationFormatMismatch(el, presentation, formatOptions);
848
1535
  warnIfTimeZoneProvided(el, formatOptions);
849
1536
  }
850
- /**
851
- * If `true`, the datetime appears normal but the selected date cannot be changed.
852
- */
853
- readonly = false;
854
- /**
855
- * Returns if an individual date (calendar day) is enabled or disabled.
856
- *
857
- * If `true`, the day will be enabled/interactive.
858
- * If `false`, the day will be disabled/non-interactive.
859
- *
860
- * The function accepts an ISO 8601 date string of a given day.
861
- * By default, all days are enabled. Developers can use this function
862
- * to write custom logic to disable certain days.
863
- *
864
- * The function is called for each rendered calendar day, for the previous, current and next month.
865
- * Custom implementations should be optimized for performance to avoid jank.
866
- */
867
- isDateEnabled;
868
- /**
869
- * If `true`, the datetime calendar displays a six-week (42-day) layout,
870
- * including days from the previous and next months to fill the grid.
871
- * These adjacent days are selectable unless disabled.
872
- */
873
- showAdjacentDays = false;
874
1537
  disabledChanged() {
875
1538
  this.emitStyle();
876
1539
  }
877
- /**
878
- * The minimum datetime allowed. Value must be a date string
879
- * following the
880
- * [ISO 8601 datetime format standard](https://www.w3.org/TR/NOTE-datetime),
881
- * such as `1996-12-19`. The format does not have to be specific to an exact
882
- * datetime. For example, the minimum could just be the year, such as `1994`.
883
- * Defaults to the beginning of the year, 100 years ago from today.
884
- */
885
- min;
886
1540
  minChanged() {
887
1541
  this.processMinParts();
888
1542
  }
889
- /**
890
- * The maximum datetime allowed. Value must be a date string
891
- * following the
892
- * [ISO 8601 datetime format standard](https://www.w3.org/TR/NOTE-datetime),
893
- * `1996-12-19`. The format does not have to be specific to an exact
894
- * datetime. For example, the maximum could just be the year, such as `1994`.
895
- * Defaults to the end of this year.
896
- */
897
- max;
898
1543
  maxChanged() {
899
1544
  this.processMaxParts();
900
1545
  }
901
- /**
902
- * Which values you want to select. `"date"` will show
903
- * a calendar picker to select the month, day, and year. `"time"`
904
- * will show a time picker to select the hour, minute, and (optionally)
905
- * AM/PM. `"date-time"` will show the date picker first and time picker second.
906
- * `"time-date"` will show the time picker first and date picker second.
907
- */
908
- presentation = 'date-time';
909
1546
  presentationChanged() {
910
1547
  const { el, formatOptions, presentation } = this;
911
1548
  checkForPresentationFormatMismatch(el, presentation, formatOptions);
@@ -915,116 +1552,21 @@ const Datetime = class {
915
1552
  const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
916
1553
  return hasDatePresentation && !preferWheel;
917
1554
  }
918
- /**
919
- * The text to display on the picker's cancel button.
920
- */
921
- cancelText = 'Cancel';
922
- /**
923
- * The text to display on the picker's "Done" button.
924
- */
925
- doneText = 'Done';
926
- /**
927
- * The text to display on the picker's "Clear" button.
928
- */
929
- clearText = 'Clear';
930
- /**
931
- * Values used to create the list of selectable years. By default
932
- * the year values range between the `min` and `max` datetime inputs. However, to
933
- * control exactly which years to display, the `yearValues` input can take a number, an array
934
- * of numbers, or string of comma separated numbers. For example, to show upcoming and
935
- * recent leap years, then this input's value would be `yearValues="2008,2012,2016,2020,2024"`.
936
- */
937
- yearValues;
938
1555
  yearValuesChanged() {
939
1556
  this.parsedYearValues = format.convertToArrayOfNumbers(this.yearValues);
940
1557
  }
941
- /**
942
- * Values used to create the list of selectable months. By default
943
- * the month values range from `1` to `12`. However, to control exactly which months to
944
- * display, the `monthValues` input can take a number, an array of numbers, or a string of
945
- * comma separated numbers. For example, if only summer months should be shown, then this
946
- * input value would be `monthValues="6,7,8"`. Note that month numbers do *not* have a
947
- * zero-based index, meaning January's value is `1`, and December's is `12`.
948
- */
949
- monthValues;
950
1558
  monthValuesChanged() {
951
1559
  this.parsedMonthValues = format.convertToArrayOfNumbers(this.monthValues);
952
1560
  }
953
- /**
954
- * Values used to create the list of selectable days. By default
955
- * every day is shown for the given month. However, to control exactly which days of
956
- * the month to display, the `dayValues` input can take a number, an array of numbers, or
957
- * a string of comma separated numbers. Note that even if the array days have an invalid
958
- * number for the selected month, like `31` in February, it will correctly not show
959
- * days which are not valid for the selected month.
960
- */
961
- dayValues;
962
1561
  dayValuesChanged() {
963
1562
  this.parsedDayValues = format.convertToArrayOfNumbers(this.dayValues);
964
1563
  }
965
- /**
966
- * Values used to create the list of selectable hours. By default
967
- * the hour values range from `0` to `23` for 24-hour, or `1` to `12` for 12-hour. However,
968
- * to control exactly which hours to display, the `hourValues` input can take a number, an
969
- * array of numbers, or a string of comma separated numbers.
970
- */
971
- hourValues;
972
- hourValuesChanged() {
973
- this.parsedHourValues = format.convertToArrayOfNumbers(this.hourValues);
974
- }
975
- /**
976
- * Values used to create the list of selectable minutes. By default
977
- * the minutes range from `0` to `59`. However, to control exactly which minutes to display,
978
- * the `minuteValues` input can take a number, an array of numbers, or a string of comma
979
- * separated numbers. For example, if the minute selections should only be every 15 minutes,
980
- * then this input value would be `minuteValues="0,15,30,45"`.
981
- */
982
- minuteValues;
983
- minuteValuesChanged() {
984
- this.parsedMinuteValues = format.convertToArrayOfNumbers(this.minuteValues);
985
- }
986
- /**
987
- * The locale to use for `ion-datetime`. This
988
- * impacts month and day name formatting.
989
- * The `"default"` value refers to the default
990
- * locale set by your device.
991
- */
992
- locale = 'default';
993
- /**
994
- * The first day of the week to use for `ion-datetime`. The
995
- * default value is `0` and represents Sunday.
996
- */
997
- firstDayOfWeek = 0;
998
- /**
999
- * A callback used to format the header text that shows how many
1000
- * dates are selected. Only used if there are 0 or more than 1
1001
- * selected (i.e. unused for exactly 1). By default, the header
1002
- * text is set to "numberOfDates days".
1003
- *
1004
- * See https://ionicframework.com/docs/troubleshooting/runtime#accessing-this
1005
- * if you need to access `this` from within the callback.
1006
- */
1007
- titleSelectedDatesFormatter;
1008
- /**
1009
- * If `true`, multiple dates can be selected at once. Only
1010
- * applies to `presentation="date"` and `preferWheel="false"`.
1011
- */
1012
- multiple = false;
1013
- /**
1014
- * Used to apply custom text and background colors to specific dates.
1015
- *
1016
- * Can be either an array of objects containing ISO strings and colors,
1017
- * or a callback that receives an ISO string and returns the colors.
1018
- *
1019
- * Only applies to the `date`, `date-time`, and `time-date` presentations,
1020
- * with `preferWheel="false"`.
1021
- */
1022
- highlightedDates;
1023
- /**
1024
- * The value of the datetime as a valid ISO 8601 datetime string.
1025
- * This should be an array of strings only when `multiple="true"`.
1026
- */
1027
- value;
1564
+ hourValuesChanged() {
1565
+ this.parsedHourValues = format.convertToArrayOfNumbers(this.hourValues);
1566
+ }
1567
+ minuteValuesChanged() {
1568
+ this.parsedMinuteValues = format.convertToArrayOfNumbers(this.minuteValues);
1569
+ }
1028
1570
  /**
1029
1571
  * Update the datetime value when the value changes
1030
1572
  */
@@ -1036,97 +1578,6 @@ const Datetime = class {
1036
1578
  this.emitStyle();
1037
1579
  this.ionValueChange.emit({ value });
1038
1580
  }
1039
- /**
1040
- * If `true`, a header will be shown above the calendar
1041
- * picker. This will include both the slotted title, and
1042
- * the selected date.
1043
- */
1044
- showDefaultTitle = false;
1045
- /**
1046
- * If `true`, the default "Cancel" and "OK" buttons
1047
- * will be rendered at the bottom of the `ion-datetime`
1048
- * component. Developers can also use the `button` slot
1049
- * if they want to customize these buttons. If custom
1050
- * buttons are set in the `button` slot then the
1051
- * default buttons will not be rendered.
1052
- */
1053
- showDefaultButtons = false;
1054
- /**
1055
- * If `true`, a "Clear" button will be rendered alongside
1056
- * the default "Cancel" and "OK" buttons at the bottom of the `ion-datetime`
1057
- * component. Developers can also use the `button` slot
1058
- * if they want to customize these buttons. If custom
1059
- * buttons are set in the `button` slot then the
1060
- * default buttons will not be rendered.
1061
- */
1062
- showClearButton = false;
1063
- /**
1064
- * If `true`, the default "Time" label will be rendered
1065
- * for the time selector of the `ion-datetime` component.
1066
- * Developers can also use the `time-label` slot
1067
- * if they want to customize this label. If a custom
1068
- * label is set in the `time-label` slot then the
1069
- * default label will not be rendered.
1070
- */
1071
- showDefaultTimeLabel = true;
1072
- /**
1073
- * The hour cycle of the `ion-datetime`. If no value is set, this is
1074
- * specified by the current locale.
1075
- */
1076
- hourCycle;
1077
- /**
1078
- * If `cover`, the `ion-datetime` will expand to cover the full width of its container.
1079
- * If `fixed`, the `ion-datetime` will have a fixed width.
1080
- */
1081
- size = 'fixed';
1082
- /**
1083
- * If `true`, a wheel picker will be rendered instead of a calendar grid
1084
- * where possible. If `false`, a calendar grid will be rendered instead of
1085
- * a wheel picker where possible.
1086
- *
1087
- * A wheel picker can be rendered instead of a grid when `presentation` is
1088
- * one of the following values: `"date"`, `"date-time"`, or `"time-date"`.
1089
- *
1090
- * A wheel picker will always be rendered regardless of
1091
- * the `preferWheel` value when `presentation` is one of the following values:
1092
- * `"time"`, `"month"`, `"month-year"`, or `"year"`.
1093
- */
1094
- preferWheel = false;
1095
- /**
1096
- * Emitted when the datetime selection was cancelled.
1097
- */
1098
- ionCancel;
1099
- /**
1100
- * Emitted when the value (selected date) has changed.
1101
- *
1102
- * This event will not emit when programmatically setting the `value` property.
1103
- */
1104
- ionChange;
1105
- /**
1106
- * Emitted when the value property has changed.
1107
- * This is used to ensure that ion-datetime-button can respond
1108
- * to any value property changes.
1109
- * @internal
1110
- */
1111
- ionValueChange;
1112
- /**
1113
- * Emitted when the datetime has focus.
1114
- */
1115
- ionFocus;
1116
- /**
1117
- * Emitted when the datetime loses focus.
1118
- */
1119
- ionBlur;
1120
- /**
1121
- * Emitted when the styles change.
1122
- * @internal
1123
- */
1124
- ionStyle;
1125
- /**
1126
- * Emitted when componentDidRender is fired.
1127
- * @internal
1128
- */
1129
- ionRender;
1130
1581
  /**
1131
1582
  * Confirms the selected datetime value, updates the
1132
1583
  * `value` property, and optionally closes the popover
@@ -1196,425 +1647,10 @@ const Datetime = class {
1196
1647
  async getDefaultPart() {
1197
1648
  return this.defaultParts;
1198
1649
  }
1199
- warnIfIncorrectValueUsage = () => {
1200
- const { multiple, value } = this;
1201
- if (!multiple && Array.isArray(value)) {
1202
- /**
1203
- * We do some processing on the `value` array so
1204
- * that it looks more like an array when logged to
1205
- * the console.
1206
- * Example given ['a', 'b']
1207
- * Default toString() behavior: a,b
1208
- * Custom behavior: ['a', 'b']
1209
- */
1210
- index.printIonWarning(`[ion-datetime] - An array of values was passed, but multiple is "false". This is incorrect usage and may result in unexpected behaviors. To dismiss this warning, pass a string to the "value" property when multiple="false".
1211
-
1212
- Value Passed: [${value.map((v) => `'${v}'`).join(', ')}]
1213
- `, this.el);
1214
- }
1215
- };
1216
- setValue = (value) => {
1217
- this.value = value;
1218
- this.ionChange.emit({ value });
1219
- };
1220
- /**
1221
- * Returns the DatetimePart interface
1222
- * to use when rendering an initial set of
1223
- * data. This should be used when rendering an
1224
- * interface in an environment where the `value`
1225
- * may not be set. This function works
1226
- * by returning the first selected date and then
1227
- * falling back to defaultParts if no active date
1228
- * is selected.
1229
- */
1230
- getActivePartsWithFallback = () => {
1231
- const { defaultParts } = this;
1232
- return this.getActivePart() ?? defaultParts;
1233
- };
1234
- getActivePart = () => {
1235
- const { activeParts } = this;
1236
- return Array.isArray(activeParts) ? activeParts[0] : activeParts;
1237
- };
1238
- closeParentOverlay = (role) => {
1239
- const popoverOrModal = this.el.closest('ion-modal, ion-popover');
1240
- if (popoverOrModal) {
1241
- popoverOrModal.dismiss(undefined, role);
1242
- }
1243
- };
1244
- setWorkingParts = (parts) => {
1245
- this.workingParts = {
1246
- ...parts,
1247
- };
1248
- };
1249
- setActiveParts = (parts, removeDate = false) => {
1250
- /** if the datetime component is in readonly mode,
1251
- * allow browsing of the calendar without changing
1252
- * the set value
1253
- */
1254
- if (this.readonly) {
1255
- return;
1256
- }
1257
- const { multiple, minParts, maxParts, activeParts } = this;
1258
- /**
1259
- * When setting the active parts, it is possible
1260
- * to set invalid data. For example,
1261
- * when updating January 31 to February,
1262
- * February 31 does not exist. As a result
1263
- * we need to validate the active parts and
1264
- * ensure that we are only setting valid dates.
1265
- * Additionally, we need to update the working parts
1266
- * too in the event that the validated parts are different.
1267
- */
1268
- const validatedParts = format.validateParts(parts, minParts, maxParts);
1269
- this.setWorkingParts(validatedParts);
1270
- if (multiple) {
1271
- const activePartsArray = Array.isArray(activeParts) ? activeParts : [activeParts];
1272
- if (removeDate) {
1273
- this.activeParts = activePartsArray.filter((p) => !format.isSameDay(p, validatedParts));
1274
- }
1275
- else {
1276
- this.activeParts = [...activePartsArray, validatedParts];
1277
- }
1278
- }
1279
- else {
1280
- this.activeParts = {
1281
- ...validatedParts,
1282
- };
1283
- }
1284
- const hasSlottedButtons = this.el.querySelector('[slot="buttons"]') !== null;
1285
- if (hasSlottedButtons || this.showDefaultButtons) {
1286
- return;
1287
- }
1288
- this.confirm();
1289
- };
1290
1650
  get isCalendarPicker() {
1291
1651
  const { presentation } = this;
1292
1652
  return presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
1293
1653
  }
1294
- initializeKeyboardListeners = () => {
1295
- const calendarBodyRef = this.calendarBodyRef;
1296
- if (!calendarBodyRef) {
1297
- return;
1298
- }
1299
- const root = this.el.shadowRoot;
1300
- /**
1301
- * Get a reference to the month
1302
- * element we are currently viewing.
1303
- */
1304
- const currentMonth = calendarBodyRef.querySelector('.calendar-month:nth-of-type(2)');
1305
- /**
1306
- * When focusing the calendar body, we want to pass focus
1307
- * to the working day, but other days should
1308
- * only be accessible using the arrow keys. Pressing
1309
- * Tab should jump between bodies of selectable content.
1310
- */
1311
- const checkCalendarBodyFocus = (ev) => {
1312
- const record = ev[0];
1313
- /**
1314
- * If calendar body was already focused
1315
- * when this fired or if the calendar body
1316
- * if not currently focused, we should not re-focus
1317
- * the inner day.
1318
- */
1319
- if (record.oldValue?.includes('ion-focused') || !calendarBodyRef.classList.contains('ion-focused')) {
1320
- return;
1321
- }
1322
- this.focusWorkingDay(currentMonth);
1323
- };
1324
- const mo = new MutationObserver(checkCalendarBodyFocus);
1325
- mo.observe(calendarBodyRef, { attributeFilter: ['class'], attributeOldValue: true });
1326
- this.destroyKeyboardMO = () => {
1327
- mo?.disconnect();
1328
- };
1329
- /**
1330
- * We must use keydown not keyup as we want
1331
- * to prevent scrolling when using the arrow keys.
1332
- */
1333
- calendarBodyRef.addEventListener('keydown', (ev) => {
1334
- const activeElement = root.activeElement;
1335
- if (!activeElement || !activeElement.classList.contains('calendar-day')) {
1336
- return;
1337
- }
1338
- const parts = format.getPartsFromCalendarDay(activeElement);
1339
- let partsToFocus;
1340
- switch (ev.key) {
1341
- case 'ArrowDown':
1342
- ev.preventDefault();
1343
- partsToFocus = format.getNextWeek(parts);
1344
- break;
1345
- case 'ArrowUp':
1346
- ev.preventDefault();
1347
- partsToFocus = format.getPreviousWeek(parts);
1348
- break;
1349
- case 'ArrowRight':
1350
- ev.preventDefault();
1351
- partsToFocus = format.getNextDay(parts);
1352
- break;
1353
- case 'ArrowLeft':
1354
- ev.preventDefault();
1355
- partsToFocus = format.getPreviousDay(parts);
1356
- break;
1357
- case 'Home':
1358
- ev.preventDefault();
1359
- partsToFocus = format.getStartOfWeek(parts);
1360
- break;
1361
- case 'End':
1362
- ev.preventDefault();
1363
- partsToFocus = format.getEndOfWeek(parts);
1364
- break;
1365
- case 'PageUp':
1366
- ev.preventDefault();
1367
- partsToFocus = ev.shiftKey ? format.getPreviousYear(parts) : format.getPreviousMonth(parts);
1368
- break;
1369
- case 'PageDown':
1370
- ev.preventDefault();
1371
- partsToFocus = ev.shiftKey ? format.getNextYear(parts) : format.getNextMonth(parts);
1372
- break;
1373
- /**
1374
- * Do not preventDefault here
1375
- * as we do not want to override other
1376
- * browser defaults such as pressing Enter/Space
1377
- * to select a day.
1378
- */
1379
- default:
1380
- return;
1381
- }
1382
- /**
1383
- * If the day we want to move focus to is
1384
- * disabled, do not do anything.
1385
- */
1386
- if (isDayDisabled(partsToFocus, this.minParts, this.maxParts)) {
1387
- return;
1388
- }
1389
- this.setWorkingParts({
1390
- ...this.workingParts,
1391
- ...partsToFocus,
1392
- });
1393
- /**
1394
- * Give view a chance to re-render
1395
- * then move focus to the new working day
1396
- */
1397
- requestAnimationFrame(() => this.focusWorkingDay(currentMonth));
1398
- });
1399
- };
1400
- focusWorkingDay = (currentMonth) => {
1401
- /**
1402
- * Get the number of offset days so
1403
- * we know how much to offset our next selector by
1404
- * to grab the correct calendar-day element.
1405
- */
1406
- const { day, month, year } = this.workingParts;
1407
- const firstOfMonth = new Date(`${month}/1/${year}`).getDay();
1408
- const offset = firstOfMonth >= this.firstDayOfWeek
1409
- ? firstOfMonth - this.firstDayOfWeek
1410
- : 7 - (this.firstDayOfWeek - firstOfMonth);
1411
- if (day === null) {
1412
- return;
1413
- }
1414
- /**
1415
- * Get the calendar day element
1416
- * and focus it.
1417
- */
1418
- const dayEl = currentMonth.querySelector(`.calendar-day-wrapper:nth-of-type(${offset + day}) .calendar-day`);
1419
- if (dayEl) {
1420
- dayEl.focus();
1421
- }
1422
- };
1423
- processMinParts = () => {
1424
- const { min, defaultParts } = this;
1425
- if (min === undefined) {
1426
- this.minParts = undefined;
1427
- return;
1428
- }
1429
- this.minParts = format.parseMinParts(min, defaultParts);
1430
- };
1431
- processMaxParts = () => {
1432
- const { max, defaultParts } = this;
1433
- if (max === undefined) {
1434
- this.maxParts = undefined;
1435
- return;
1436
- }
1437
- this.maxParts = format.parseMaxParts(max, defaultParts);
1438
- };
1439
- initializeCalendarListener = () => {
1440
- const calendarBodyRef = this.calendarBodyRef;
1441
- if (!calendarBodyRef) {
1442
- return;
1443
- }
1444
- /**
1445
- * For performance reasons, we only render 3
1446
- * months at a time: The current month, the previous
1447
- * month, and the next month. We have a scroll listener
1448
- * on the calendar body to append/prepend new months.
1449
- *
1450
- * We can do this because Stencil is smart enough to not
1451
- * re-create the .calendar-month containers, but rather
1452
- * update the content within those containers.
1453
- *
1454
- * As an added bonus, WebKit has some troubles with
1455
- * scroll-snap-stop: always, so not rendering all of
1456
- * the months in a row allows us to mostly sidestep
1457
- * that issue.
1458
- */
1459
- const months = calendarBodyRef.querySelectorAll('.calendar-month');
1460
- const startMonth = months[0];
1461
- const workingMonth = months[1];
1462
- const endMonth = months[2];
1463
- const mode = ionicGlobal.getIonMode(this);
1464
- const needsiOSRubberBandFix = mode === 'ios' && typeof navigator !== 'undefined' && navigator.maxTouchPoints > 1;
1465
- /**
1466
- * Before setting up the scroll listener,
1467
- * scroll the middle month into view.
1468
- * scrollIntoView() will scroll entire page
1469
- * if element is not in viewport. Use scrollLeft instead.
1470
- */
1471
- index.writeTask(() => {
1472
- calendarBodyRef.scrollLeft = startMonth.clientWidth * (dir.isRTL(this.el) ? -1 : 1);
1473
- const getChangedMonth = (parts) => {
1474
- const box = calendarBodyRef.getBoundingClientRect();
1475
- /**
1476
- * If the current scroll position is all the way to the left
1477
- * then we have scrolled to the previous month.
1478
- * Otherwise, assume that we have scrolled to the next
1479
- * month. We have a tolerance of 2px to account for
1480
- * sub pixel rendering.
1481
- *
1482
- * Check below the next line ensures that we did not
1483
- * swipe and abort (i.e. we swiped but we are still on the current month).
1484
- */
1485
- const condition = dir.isRTL(this.el) ? calendarBodyRef.scrollLeft >= -2 : calendarBodyRef.scrollLeft <= 2;
1486
- const month = condition ? startMonth : endMonth;
1487
- /**
1488
- * The edge of the month must be lined up with
1489
- * the edge of the calendar body in order for
1490
- * the component to update. Otherwise, it
1491
- * may be the case that the user has paused their
1492
- * swipe or the browser has not finished snapping yet.
1493
- * Rather than check if the x values are equal,
1494
- * we give it a tolerance of 2px to account for
1495
- * sub pixel rendering.
1496
- */
1497
- const monthBox = month.getBoundingClientRect();
1498
- if (Math.abs(monthBox.x - box.x) > 2)
1499
- return;
1500
- /**
1501
- * If we're force-rendering a month, assume we've
1502
- * scrolled to that and return it.
1503
- *
1504
- * If forceRenderDate is ever used in a context where the
1505
- * forced month is not immediately auto-scrolled to, this
1506
- * should be updated to also check whether `month` has the
1507
- * same month and year as the forced date.
1508
- */
1509
- const { forceRenderDate } = this;
1510
- if (forceRenderDate !== undefined) {
1511
- return { month: forceRenderDate.month, year: forceRenderDate.year, day: forceRenderDate.day };
1512
- }
1513
- /**
1514
- * From here, we can determine if the start
1515
- * month or the end month was scrolled into view.
1516
- * If no month was changed, then we can return from
1517
- * the scroll callback early.
1518
- */
1519
- if (month === startMonth) {
1520
- return format.getPreviousMonth(parts);
1521
- }
1522
- else if (month === endMonth) {
1523
- return format.getNextMonth(parts);
1524
- }
1525
- else {
1526
- return;
1527
- }
1528
- };
1529
- const updateActiveMonth = () => {
1530
- if (needsiOSRubberBandFix) {
1531
- calendarBodyRef.style.removeProperty('pointer-events');
1532
- appliediOSRubberBandFix = false;
1533
- }
1534
- /**
1535
- * If the month did not change
1536
- * then we can return early.
1537
- */
1538
- const newDate = getChangedMonth(this.workingParts);
1539
- if (!newDate)
1540
- return;
1541
- const { month, day, year } = newDate;
1542
- if (isMonthDisabled({ month, year, day: null }, {
1543
- minParts: { ...this.minParts, day: null },
1544
- maxParts: { ...this.maxParts, day: null },
1545
- })) {
1546
- return;
1547
- }
1548
- /**
1549
- * Prevent scrolling for other browsers
1550
- * to give the DOM time to update and the container
1551
- * time to properly snap.
1552
- */
1553
- calendarBodyRef.style.setProperty('overflow', 'hidden');
1554
- /**
1555
- * Use a writeTask here to ensure
1556
- * that the state is updated and the
1557
- * correct month is scrolled into view
1558
- * in the same frame. This is not
1559
- * typically a problem on newer devices
1560
- * but older/slower device may have a flicker
1561
- * if we did not do this.
1562
- */
1563
- index.writeTask(() => {
1564
- this.setWorkingParts({
1565
- ...this.workingParts,
1566
- month,
1567
- day: day,
1568
- year,
1569
- });
1570
- calendarBodyRef.scrollLeft = workingMonth.clientWidth * (dir.isRTL(this.el) ? -1 : 1);
1571
- calendarBodyRef.style.removeProperty('overflow');
1572
- if (this.resolveForceDateScrolling) {
1573
- this.resolveForceDateScrolling();
1574
- }
1575
- const activeEl = this.el.shadowRoot.activeElement;
1576
- if (activeEl && activeEl.classList.contains('calendar-day')) {
1577
- activeEl.closest('.calendar-body')?.focus();
1578
- }
1579
- });
1580
- };
1581
- /**
1582
- * When the container finishes scrolling we
1583
- * need to update the DOM with the selected month.
1584
- */
1585
- let scrollTimeout;
1586
- /**
1587
- * We do not want to attempt to set pointer-events
1588
- * multiple times within a single swipe gesture as
1589
- * that adds unnecessary work to the main thread.
1590
- */
1591
- let appliediOSRubberBandFix = false;
1592
- const scrollCallback = () => {
1593
- if (scrollTimeout) {
1594
- clearTimeout(scrollTimeout);
1595
- }
1596
- /**
1597
- * On iOS it is possible to quickly rubber band
1598
- * the scroll area before the scroll timeout has fired.
1599
- * This results in users reaching the end of the scrollable
1600
- * container before the DOM has updated.
1601
- * By setting `pointer-events: none` we can ensure that
1602
- * subsequent swipes do not happen while the container
1603
- * is snapping.
1604
- */
1605
- if (!appliediOSRubberBandFix && needsiOSRubberBandFix) {
1606
- calendarBodyRef.style.setProperty('pointer-events', 'none');
1607
- appliediOSRubberBandFix = true;
1608
- }
1609
- // Wait ~3 frames
1610
- scrollTimeout = setTimeout(updateActiveMonth, 50);
1611
- };
1612
- calendarBodyRef.addEventListener('scroll', scrollCallback);
1613
- this.destroyCalendarListener = () => {
1614
- calendarBodyRef.removeEventListener('scroll', scrollCallback);
1615
- };
1616
- });
1617
- };
1618
1654
  connectedCallback() {
1619
1655
  this.clearFocusVisible = focusVisible.startFocusVisible(this.el).destroy;
1620
1656
  this.loadTimeout = setTimeout(() => {
@@ -1628,66 +1664,10 @@ const Datetime = class {
1628
1664
  }
1629
1665
  this.loadTimeoutCleanup();
1630
1666
  }
1631
- /**
1632
- * Clean up all listeners except for the overlay
1633
- * listener. This is so that we can re-create the listeners
1634
- * if the datetime has been hidden/presented by a modal or popover.
1635
- */
1636
- destroyInteractionListeners = () => {
1637
- const { destroyCalendarListener, destroyKeyboardMO } = this;
1638
- if (destroyCalendarListener !== undefined) {
1639
- destroyCalendarListener();
1640
- }
1641
- if (destroyKeyboardMO !== undefined) {
1642
- destroyKeyboardMO();
1643
- }
1644
- };
1645
1667
  initializeListeners() {
1646
1668
  this.initializeCalendarListener();
1647
1669
  this.initializeKeyboardListeners();
1648
1670
  }
1649
- /**
1650
- * TODO(FW-6931): Remove this fallback upon solving the root cause
1651
- * Fallback to ensure the datetime becomes ready even if
1652
- * IntersectionObserver never reports it as intersecting.
1653
- *
1654
- * This is primarily used in environments where the observer
1655
- * might not fire as expected, such as when running under
1656
- * synthetic tests that stub IntersectionObserver.
1657
- */
1658
- ensureReadyIfVisible = () => {
1659
- if (this.el.classList.contains('datetime-ready')) {
1660
- return;
1661
- }
1662
- const rect = this.el.getBoundingClientRect();
1663
- if (rect.width === 0 || rect.height === 0) {
1664
- return;
1665
- }
1666
- this.markReady();
1667
- };
1668
- markReady = () => {
1669
- if (this.el.classList.contains('datetime-ready')) {
1670
- return;
1671
- }
1672
- this.initializeListeners();
1673
- /**
1674
- * TODO FW-2793: Datetime needs a frame to ensure that it
1675
- * can properly scroll contents into view. As a result
1676
- * we hide the scrollable content until after that frame
1677
- * so users do not see the content quickly shifting. The downside
1678
- * is that the content will pop into view a frame after. Maybe there
1679
- * is a better way to handle this?
1680
- */
1681
- index.writeTask(() => {
1682
- this.el.classList.add('datetime-ready');
1683
- });
1684
- };
1685
- loadTimeoutCleanup = () => {
1686
- if (this.loadTimeout) {
1687
- clearTimeout(this.loadTimeout);
1688
- this.loadTimeout = undefined;
1689
- }
1690
- };
1691
1671
  componentDidLoad() {
1692
1672
  const { el, intersectionTrackerRef } = this;
1693
1673
  /**
@@ -1831,119 +1811,6 @@ const Datetime = class {
1831
1811
  this.ionRender.emit();
1832
1812
  });
1833
1813
  }
1834
- processValue = (value) => {
1835
- const hasValue = value !== null && value !== undefined && value !== '' && (!Array.isArray(value) || value.length > 0);
1836
- const valueToProcess = hasValue ? format.parseDate(value) : this.defaultParts;
1837
- const { minParts, maxParts, workingParts, el } = this;
1838
- this.warnIfIncorrectValueUsage();
1839
- /**
1840
- * Return early if the value wasn't parsed correctly, such as
1841
- * if an improperly formatted date string was provided.
1842
- */
1843
- if (!valueToProcess) {
1844
- return;
1845
- }
1846
- /**
1847
- * Datetime should only warn of out of bounds values
1848
- * if set by the user. If the `value` is undefined,
1849
- * we will default to today's date which may be out
1850
- * of bounds. In this case, the warning makes it look
1851
- * like the developer did something wrong which is
1852
- * not true.
1853
- */
1854
- if (hasValue) {
1855
- format.warnIfValueOutOfBounds(valueToProcess, minParts, maxParts);
1856
- }
1857
- /**
1858
- * If there are multiple values, clamp to the last one.
1859
- * This is because the last value is the one that the user
1860
- * has most recently interacted with.
1861
- */
1862
- const singleValue = Array.isArray(valueToProcess) ? valueToProcess[valueToProcess.length - 1] : valueToProcess;
1863
- const targetValue = format.clampDate(singleValue, minParts, maxParts);
1864
- const { month, day, year, hour, minute } = targetValue;
1865
- const ampm = format.parseAmPm(hour);
1866
- /**
1867
- * Since `activeParts` indicates a value that been explicitly selected
1868
- * either by the user or the app, only update `activeParts` if the
1869
- * `value` property is set.
1870
- */
1871
- if (hasValue) {
1872
- if (Array.isArray(valueToProcess)) {
1873
- this.activeParts = [...valueToProcess];
1874
- }
1875
- else {
1876
- this.activeParts = {
1877
- month,
1878
- day,
1879
- year,
1880
- hour,
1881
- minute,
1882
- ampm,
1883
- };
1884
- }
1885
- }
1886
- else {
1887
- /**
1888
- * Reset the active parts if the value is not set.
1889
- * This will clear the selected calendar day when
1890
- * performing a clear action or using the reset() method.
1891
- */
1892
- this.activeParts = [];
1893
- }
1894
- const didChangeMonth = (month !== undefined && month !== workingParts.month) || (year !== undefined && year !== workingParts.year);
1895
- const bodyIsVisible = el.classList.contains('datetime-ready');
1896
- const { isGridStyle, showMonthAndYear } = this;
1897
- if (isGridStyle && didChangeMonth && bodyIsVisible && !showMonthAndYear) {
1898
- /**
1899
- * Only animate if:
1900
- * 1. We're using grid style (wheel style pickers should just jump to new value)
1901
- * 2. The month and/or year actually changed, and both are defined (otherwise there's nothing to animate to)
1902
- * 3. The calendar body is visible (prevents animation when in collapsed datetime-button, for example)
1903
- * 4. The month/year picker is not open (since you wouldn't see the animation anyway)
1904
- */
1905
- this.animateToDate(targetValue);
1906
- }
1907
- else {
1908
- this.setWorkingParts({
1909
- month,
1910
- day,
1911
- year,
1912
- hour,
1913
- minute,
1914
- ampm,
1915
- });
1916
- }
1917
- };
1918
- animateToDate = async (targetValue) => {
1919
- const { workingParts } = this;
1920
- /**
1921
- * Tell other render functions that we need to force the
1922
- * target month to appear in place of the actual next/prev month.
1923
- * Because this is a State variable, a rerender will be triggered
1924
- * automatically, updating the rendered months.
1925
- */
1926
- this.forceRenderDate = targetValue;
1927
- /**
1928
- * Flag that we've started scrolling to the forced date.
1929
- * The resolve function will be called by the datetime's
1930
- * scroll listener when it's done updating everything.
1931
- * This is a replacement for making prev/nextMonth async,
1932
- * since the logic we're waiting on is in a listener.
1933
- */
1934
- const forceDateScrollingPromise = new Promise((resolve) => {
1935
- this.resolveForceDateScrolling = resolve;
1936
- });
1937
- /**
1938
- * Animate smoothly to the forced month. This will also update
1939
- * workingParts and correct the surrounding months for us.
1940
- */
1941
- const targetMonthIsBefore = format.isBefore(targetValue, workingParts);
1942
- targetMonthIsBefore ? this.prevMonth() : this.nextMonth();
1943
- await forceDateScrollingPromise;
1944
- this.resolveForceDateScrolling = undefined;
1945
- this.forceRenderDate = undefined;
1946
- };
1947
1814
  componentWillLoad() {
1948
1815
  const { el, formatOptions, highlightedDates, multiple, presentation, preferWheel } = this;
1949
1816
  if (multiple) {
@@ -1994,52 +1861,6 @@ const Datetime = class {
1994
1861
  'interactive-disabled': this.disabled,
1995
1862
  });
1996
1863
  }
1997
- onFocus = () => {
1998
- this.ionFocus.emit();
1999
- };
2000
- onBlur = () => {
2001
- this.ionBlur.emit();
2002
- };
2003
- hasValue = () => {
2004
- return this.value != null;
2005
- };
2006
- nextMonth = () => {
2007
- const calendarBodyRef = this.calendarBodyRef;
2008
- if (!calendarBodyRef) {
2009
- return;
2010
- }
2011
- const nextMonth = calendarBodyRef.querySelector('.calendar-month:last-of-type');
2012
- if (!nextMonth) {
2013
- return;
2014
- }
2015
- const left = nextMonth.offsetWidth * 2;
2016
- const scrollMode = index.config.getBoolean('animated', true) ? 'smooth' : 'instant';
2017
- calendarBodyRef.scrollTo({
2018
- top: 0,
2019
- left: left * (dir.isRTL(this.el) ? -1 : 1),
2020
- behavior: scrollMode,
2021
- });
2022
- };
2023
- prevMonth = () => {
2024
- const calendarBodyRef = this.calendarBodyRef;
2025
- if (!calendarBodyRef) {
2026
- return;
2027
- }
2028
- const prevMonth = calendarBodyRef.querySelector('.calendar-month:first-of-type');
2029
- if (!prevMonth) {
2030
- return;
2031
- }
2032
- const left = prevMonth.offsetWidth * 2;
2033
- const scrollMode = index.config.getBoolean('animated', true) ? 'smooth' : 'instant';
2034
- calendarBodyRef.scrollTo({
2035
- top: 0,
2036
- left: left * (dir.isRTL(this.el) ? 1 : -1),
2037
- behavior: scrollMode,
2038
- });
2039
- };
2040
- toggleMonthAndYearView = () => {
2041
- this.showMonthAndYear = !this.showMonthAndYear;
2042
- };
2043
1864
  /**
2044
1865
  * Universal render methods
2045
1866
  * These are pieces of datetime that
@@ -2720,6 +2541,7 @@ const Datetime = class {
2720
2541
  }),
2721
2542
  } }, index.h("div", { key: '20889d3c68dd5109633c0e214411a63d6f3025bb', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
2722
2543
  }
2544
+ get el() { return index.getElement(this); }
2723
2545
  static get watchers() { return {
2724
2546
  "formatOptions": [{
2725
2547
  "formatOptionsChanged": 0