@ionic/core 7.4.4-dev.11696956070.1faa3cfe → 7.4.4-dev.11699472243.1ccd503d

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 (276) hide show
  1. package/components/alert.js +8 -0
  2. package/components/checkbox.js +0 -3
  3. package/components/data.js +96 -22
  4. package/components/haptic.js +1 -0
  5. package/components/icon.js +9 -5
  6. package/components/index.js +1 -0
  7. package/components/index4.js +26 -19
  8. package/components/index7.js +1 -1
  9. package/components/ion-datetime-button.js +4 -4
  10. package/components/ion-datetime.js +3 -3
  11. package/components/ion-menu.js +0 -12
  12. package/components/ion-nav.js +1 -0
  13. package/components/ion-router.js +3 -0
  14. package/components/ion-select.js +1 -1
  15. package/components/ion-toast.js +157 -13
  16. package/components/ion-toggle.js +0 -3
  17. package/components/ios.transition.js +1 -0
  18. package/components/overlays.js +1 -0
  19. package/components/radio-group.js +1 -1
  20. package/components/radio.js +1 -4
  21. package/dist/cjs/{button-active-c358e83c.js → button-active-f2147e85.js} +1 -1
  22. package/dist/cjs/{data-db832785.js → data-c8d21093.js} +96 -22
  23. package/dist/cjs/{haptic-c5f6b4d5.js → haptic-678abc9f.js} +1 -0
  24. package/dist/cjs/{index-1f1ea05f.js → index-2e612e35.js} +26 -19
  25. package/dist/cjs/{index-fa649bd8.js → index-33d2809c.js} +2 -2
  26. package/dist/cjs/{index-d8d1fc0b.js → index-d8f84c5a.js} +1 -1
  27. package/dist/cjs/index.cjs.js +8 -6
  28. package/dist/cjs/ion-accordion_2.cjs.entry.js +1 -1
  29. package/dist/cjs/ion-action-sheet.cjs.entry.js +3 -3
  30. package/dist/cjs/ion-alert.cjs.entry.js +11 -3
  31. package/dist/cjs/ion-app_8.cjs.entry.js +1 -1
  32. package/dist/cjs/ion-back-button.cjs.entry.js +1 -1
  33. package/dist/cjs/ion-breadcrumb_2.cjs.entry.js +1 -1
  34. package/dist/cjs/ion-button_2.cjs.entry.js +9 -5
  35. package/dist/cjs/ion-checkbox.cjs.entry.js +0 -3
  36. package/dist/cjs/ion-datetime-button.cjs.entry.js +4 -4
  37. package/dist/cjs/ion-datetime_3.cjs.entry.js +6 -6
  38. package/dist/cjs/ion-fab_3.cjs.entry.js +1 -1
  39. package/dist/cjs/ion-input.cjs.entry.js +1 -1
  40. package/dist/cjs/ion-item_8.cjs.entry.js +1 -1
  41. package/dist/cjs/ion-loading.cjs.entry.js +1 -1
  42. package/dist/cjs/ion-menu_3.cjs.entry.js +6 -17
  43. package/dist/cjs/ion-modal.cjs.entry.js +2 -2
  44. package/dist/cjs/ion-nav_2.cjs.entry.js +2 -1
  45. package/dist/cjs/ion-picker-column-internal.cjs.entry.js +1 -1
  46. package/dist/cjs/ion-popover.cjs.entry.js +2 -2
  47. package/dist/cjs/ion-radio_2.cjs.entry.js +2 -5
  48. package/dist/cjs/ion-refresher_2.cjs.entry.js +2 -2
  49. package/dist/cjs/ion-reorder_2.cjs.entry.js +2 -2
  50. package/dist/cjs/ion-route_4.cjs.entry.js +3 -0
  51. package/dist/cjs/ion-searchbar.cjs.entry.js +1 -1
  52. package/dist/cjs/ion-select_3.cjs.entry.js +3 -3
  53. package/dist/cjs/ion-toast.cjs.entry.js +174 -32
  54. package/dist/cjs/ion-toggle.cjs.entry.js +2 -5
  55. package/dist/cjs/ionic.cjs.js +1 -1
  56. package/dist/cjs/{ios.transition-4195d10d.js → ios.transition-8ddf91e6.js} +2 -1
  57. package/dist/cjs/loader.cjs.js +1 -1
  58. package/dist/cjs/{md.transition-0713f667.js → md.transition-44ff8566.js} +1 -1
  59. package/dist/cjs/{overlays-efc9d511.js → overlays-9cab437c.js} +1 -0
  60. package/dist/collection/components/alert/alert.js +8 -0
  61. package/dist/collection/components/alert/test/a11y/alert.e2e.js +11 -0
  62. package/dist/collection/components/checkbox/checkbox.js +0 -3
  63. package/dist/collection/components/datetime/datetime.js +12 -6
  64. package/dist/collection/components/datetime/test/hour-cycle/datetime.e2e.js +14 -0
  65. package/dist/collection/components/datetime/utils/data.js +33 -7
  66. package/dist/collection/components/datetime/utils/format.js +27 -10
  67. package/dist/collection/components/datetime/utils/helpers.js +37 -5
  68. package/dist/collection/components/datetime-button/datetime-button.js +4 -4
  69. package/dist/collection/components/menu/menu.js +0 -12
  70. package/dist/collection/components/menu/test/multiple/menu.e2e.js +60 -0
  71. package/dist/collection/components/nav/nav.js +1 -0
  72. package/dist/collection/components/radio/radio.js +1 -4
  73. package/dist/collection/components/radio-group/radio-group.js +1 -1
  74. package/dist/collection/components/router/router.js +2 -0
  75. package/dist/collection/components/router/utils/path.js +1 -0
  76. package/dist/collection/components/select/select.js +1 -1
  77. package/dist/collection/components/toast/animations/ios.enter.js +2 -3
  78. package/dist/collection/components/toast/animations/ios.leave.js +2 -3
  79. package/dist/collection/components/toast/animations/md.enter.js +2 -3
  80. package/dist/collection/components/toast/animations/utils.js +85 -0
  81. package/dist/collection/components/toast/test/position-anchor/toast.e2e.js +45 -0
  82. package/dist/collection/components/toast/toast.js +98 -9
  83. package/dist/collection/components/toggle/toggle.js +0 -3
  84. package/dist/collection/index.js +1 -0
  85. package/dist/collection/utils/menu-controller/index.js +26 -19
  86. package/dist/collection/utils/native/haptic.js +1 -0
  87. package/dist/collection/utils/overlays.js +1 -0
  88. package/dist/collection/utils/transition/ios.transition.js +1 -0
  89. package/dist/docs.json +73 -10
  90. package/dist/esm/{button-active-7180a130.js → button-active-3dd473a1.js} +1 -1
  91. package/dist/esm/{data-009dbf15.js → data-44d9e816.js} +96 -22
  92. package/dist/esm/{haptic-6447af60.js → haptic-1243b917.js} +1 -0
  93. package/dist/esm/{index-ecfc2c9f.js → index-504b03f0.js} +1 -1
  94. package/dist/esm/{index-0b0dd67c.js → index-6e10cd02.js} +2 -2
  95. package/dist/esm/{index-97a2bb98.js → index-c3e624b7.js} +26 -19
  96. package/dist/esm/index.js +7 -6
  97. package/dist/esm/ion-accordion_2.entry.js +1 -1
  98. package/dist/esm/ion-action-sheet.entry.js +3 -3
  99. package/dist/esm/ion-alert.entry.js +11 -3
  100. package/dist/esm/ion-app_8.entry.js +1 -1
  101. package/dist/esm/ion-back-button.entry.js +1 -1
  102. package/dist/esm/ion-breadcrumb_2.entry.js +1 -1
  103. package/dist/esm/ion-button_2.entry.js +9 -5
  104. package/dist/esm/ion-checkbox.entry.js +0 -3
  105. package/dist/esm/ion-datetime-button.entry.js +4 -4
  106. package/dist/esm/ion-datetime_3.entry.js +6 -6
  107. package/dist/esm/ion-fab_3.entry.js +1 -1
  108. package/dist/esm/ion-input.entry.js +1 -1
  109. package/dist/esm/ion-item_8.entry.js +1 -1
  110. package/dist/esm/ion-loading.entry.js +1 -1
  111. package/dist/esm/ion-menu_3.entry.js +5 -16
  112. package/dist/esm/ion-modal.entry.js +2 -2
  113. package/dist/esm/ion-nav_2.entry.js +2 -1
  114. package/dist/esm/ion-picker-column-internal.entry.js +1 -1
  115. package/dist/esm/ion-popover.entry.js +2 -2
  116. package/dist/esm/ion-radio_2.entry.js +2 -5
  117. package/dist/esm/ion-refresher_2.entry.js +2 -2
  118. package/dist/esm/ion-reorder_2.entry.js +2 -2
  119. package/dist/esm/ion-route_4.entry.js +3 -0
  120. package/dist/esm/ion-searchbar.entry.js +1 -1
  121. package/dist/esm/ion-select_3.entry.js +3 -3
  122. package/dist/esm/ion-toast.entry.js +157 -15
  123. package/dist/esm/ion-toggle.entry.js +2 -5
  124. package/dist/esm/ionic.js +1 -1
  125. package/dist/esm/{ios.transition-875ba2ea.js → ios.transition-6707a3a1.js} +2 -1
  126. package/dist/esm/loader.js +1 -1
  127. package/dist/esm/{md.transition-54c79f72.js → md.transition-957964fd.js} +1 -1
  128. package/dist/esm/{overlays-84621c0a.js → overlays-753933fc.js} +1 -0
  129. package/dist/esm-es5/{button-active-7180a130.js → button-active-3dd473a1.js} +1 -1
  130. package/dist/esm-es5/data-44d9e816.js +4 -0
  131. package/dist/esm-es5/{index-0b0dd67c.js → index-6e10cd02.js} +1 -1
  132. package/dist/esm-es5/index-c3e624b7.js +4 -0
  133. package/dist/esm-es5/index.js +1 -1
  134. package/dist/esm-es5/ion-accordion_2.entry.js +1 -1
  135. package/dist/esm-es5/ion-action-sheet.entry.js +1 -1
  136. package/dist/esm-es5/ion-alert.entry.js +1 -1
  137. package/dist/esm-es5/ion-app_8.entry.js +1 -1
  138. package/dist/esm-es5/ion-back-button.entry.js +1 -1
  139. package/dist/esm-es5/ion-breadcrumb_2.entry.js +1 -1
  140. package/dist/esm-es5/ion-button_2.entry.js +1 -1
  141. package/dist/esm-es5/ion-checkbox.entry.js +1 -1
  142. package/dist/esm-es5/ion-datetime-button.entry.js +1 -1
  143. package/dist/esm-es5/ion-datetime_3.entry.js +1 -1
  144. package/dist/esm-es5/ion-fab_3.entry.js +1 -1
  145. package/dist/esm-es5/ion-input.entry.js +1 -1
  146. package/dist/esm-es5/ion-item_8.entry.js +1 -1
  147. package/dist/esm-es5/ion-loading.entry.js +1 -1
  148. package/dist/esm-es5/ion-menu_3.entry.js +1 -1
  149. package/dist/esm-es5/ion-modal.entry.js +1 -1
  150. package/dist/esm-es5/ion-nav_2.entry.js +1 -1
  151. package/dist/esm-es5/ion-picker-column-internal.entry.js +1 -1
  152. package/dist/esm-es5/ion-popover.entry.js +1 -1
  153. package/dist/esm-es5/ion-radio_2.entry.js +1 -1
  154. package/dist/esm-es5/ion-refresher_2.entry.js +1 -1
  155. package/dist/esm-es5/ion-reorder_2.entry.js +1 -1
  156. package/dist/esm-es5/ion-searchbar.entry.js +1 -1
  157. package/dist/esm-es5/ion-select_3.entry.js +1 -1
  158. package/dist/esm-es5/ion-toast.entry.js +1 -1
  159. package/dist/esm-es5/ion-toggle.entry.js +1 -1
  160. package/dist/esm-es5/ionic.js +1 -1
  161. package/dist/esm-es5/{ios.transition-875ba2ea.js → ios.transition-6707a3a1.js} +1 -1
  162. package/dist/esm-es5/loader.js +1 -1
  163. package/dist/esm-es5/{md.transition-54c79f72.js → md.transition-957964fd.js} +1 -1
  164. package/dist/html.html-data.json +11 -1
  165. package/dist/ionic/index.esm.js +1 -1
  166. package/dist/ionic/ionic.esm.js +1 -1
  167. package/dist/ionic/{p-2134558d.entry.js → p-0023e6eb.entry.js} +1 -1
  168. package/dist/ionic/{p-0dcdf480.system.entry.js → p-00f709ca.system.entry.js} +1 -1
  169. package/dist/ionic/{p-2330af92.system.entry.js → p-037e2738.system.entry.js} +1 -1
  170. package/dist/ionic/{p-678f37d7.entry.js → p-03f7e3cc.entry.js} +1 -1
  171. package/dist/ionic/{p-a1d7f4ef.entry.js → p-0459db58.entry.js} +1 -1
  172. package/dist/ionic/{p-b2397f35.entry.js → p-06756f31.entry.js} +1 -1
  173. package/dist/ionic/p-0779a5c8.system.js +4 -0
  174. package/dist/ionic/{p-8c17d825.js → p-0d198537.js} +1 -1
  175. package/dist/ionic/{p-a9d7f984.entry.js → p-0d3d44e7.entry.js} +1 -1
  176. package/dist/ionic/p-100ea813.system.entry.js +4 -0
  177. package/dist/ionic/{p-f4267847.system.entry.js → p-10fcb3a3.system.entry.js} +1 -1
  178. package/dist/ionic/{p-00d3814a.system.entry.js → p-14fd96a2.system.entry.js} +1 -1
  179. package/dist/ionic/p-17240d90.js +4 -0
  180. package/dist/ionic/{p-af39c1c5.js → p-1d9b39f3.js} +1 -1
  181. package/dist/ionic/{p-a1528344.entry.js → p-2acea831.entry.js} +1 -1
  182. package/dist/ionic/p-2b47b2ce.entry.js +4 -0
  183. package/dist/ionic/p-32b5f10e.entry.js +4 -0
  184. package/dist/ionic/{p-007168b8.system.entry.js → p-3634b770.system.entry.js} +1 -1
  185. package/dist/ionic/{p-3d278648.system.entry.js → p-416d7f8d.system.entry.js} +1 -1
  186. package/dist/ionic/{p-979dc719.entry.js → p-44fa0a61.entry.js} +1 -1
  187. package/dist/ionic/{p-a51f5932.entry.js → p-4555335a.entry.js} +1 -1
  188. package/dist/ionic/p-469d6a98.entry.js +4 -0
  189. package/dist/ionic/{p-a4e95028.system.entry.js → p-48159bfc.system.entry.js} +1 -1
  190. package/dist/ionic/p-50125c8c.js +4 -0
  191. package/dist/ionic/p-520789c2.js +4 -0
  192. package/dist/ionic/{p-17dd92fe.system.entry.js → p-5b5311f6.system.entry.js} +1 -1
  193. package/dist/ionic/{p-24952f8a.system.entry.js → p-5cafe439.system.entry.js} +1 -1
  194. package/dist/ionic/{p-eaa58d23.entry.js → p-60dee335.entry.js} +1 -1
  195. package/dist/ionic/p-68b405cc.entry.js +4 -0
  196. package/dist/ionic/{p-6ce891b2.entry.js → p-6a3c14d1.entry.js} +1 -1
  197. package/dist/ionic/{p-28678af4.system.entry.js → p-6a92db9d.system.entry.js} +1 -1
  198. package/dist/ionic/p-6cfcb294.system.js +4 -0
  199. package/dist/ionic/{p-018ad59f.entry.js → p-70441a5b.entry.js} +1 -1
  200. package/dist/ionic/p-73eba881.system.js +1 -1
  201. package/dist/ionic/{p-0c7d0167.system.entry.js → p-7520e873.system.entry.js} +1 -1
  202. package/dist/ionic/{p-df951755.system.entry.js → p-88a1a4fe.system.entry.js} +1 -1
  203. package/dist/ionic/{p-0fc8a522.system.entry.js → p-8957b1de.system.entry.js} +1 -1
  204. package/dist/ionic/{p-9e6bf328.system.js → p-90012797.system.js} +1 -1
  205. package/dist/ionic/{p-a8403bed.system.entry.js → p-9736406a.system.entry.js} +1 -1
  206. package/dist/ionic/{p-0e070fbe.entry.js → p-9b796813.entry.js} +1 -1
  207. package/dist/ionic/{p-2062958e.js → p-9dbc208c.js} +1 -1
  208. package/dist/ionic/{p-52e5f8f0.system.entry.js → p-a157df46.system.entry.js} +1 -1
  209. package/dist/ionic/p-a4ce3b06.system.entry.js +4 -0
  210. package/dist/ionic/{p-f6f4d4bb.system.entry.js → p-a60cff26.system.entry.js} +1 -1
  211. package/dist/ionic/{p-a6c52452.entry.js → p-a7361c85.entry.js} +1 -1
  212. package/dist/ionic/{p-32eaa293.entry.js → p-a99e7e72.entry.js} +1 -1
  213. package/dist/ionic/p-aae05032.entry.js +4 -0
  214. package/dist/ionic/{p-7061fa75.system.entry.js → p-ae57449e.system.entry.js} +1 -1
  215. package/dist/ionic/{p-e92068d4.system.entry.js → p-ae8121f5.system.entry.js} +1 -1
  216. package/dist/ionic/{p-d17638e9.system.js → p-b25a96b7.system.js} +1 -1
  217. package/dist/ionic/{p-53d4606a.entry.js → p-b4f14d9e.entry.js} +1 -1
  218. package/dist/ionic/{p-ec29338e.entry.js → p-b7ac706d.entry.js} +1 -1
  219. package/dist/ionic/p-b8c3f071.system.js +4 -0
  220. package/dist/ionic/{p-dd0c00ed.entry.js → p-bc7420cc.entry.js} +1 -1
  221. package/dist/ionic/{p-ab37db48.entry.js → p-c0c794dd.entry.js} +1 -1
  222. package/dist/ionic/{p-e40b2cb4.system.entry.js → p-ccdd595c.system.entry.js} +1 -1
  223. package/dist/ionic/p-d0d59328.entry.js +4 -0
  224. package/dist/ionic/p-d1df86ff.entry.js +4 -0
  225. package/dist/ionic/{p-f1c2678b.system.entry.js → p-d8eeabae.system.entry.js} +1 -1
  226. package/dist/ionic/{p-cd075e75.system.entry.js → p-db8b267a.system.entry.js} +1 -1
  227. package/dist/ionic/{p-5fd0a13e.system.entry.js → p-dcfea01f.system.entry.js} +1 -1
  228. package/dist/ionic/{p-b7258ddb.system.js → p-e0f66356.system.js} +1 -1
  229. package/dist/ionic/{p-7c901810.system.js → p-ec25d547.system.js} +1 -1
  230. package/dist/ionic/{p-67e21699.entry.js → p-ef4408d6.entry.js} +1 -1
  231. package/dist/ionic/{p-d511de89.system.entry.js → p-efd574eb.system.entry.js} +1 -1
  232. package/dist/ionic/{p-7fd0f045.system.entry.js → p-f48af9da.system.entry.js} +1 -1
  233. package/dist/node_modules/ionicons/dist/collection/components/icon/icon.css +46 -4
  234. package/dist/types/components/datetime/datetime-interface.d.ts +1 -0
  235. package/dist/types/components/datetime/datetime.d.ts +2 -2
  236. package/dist/types/components/datetime/utils/data.d.ts +3 -3
  237. package/dist/types/components/datetime/utils/format.d.ts +3 -3
  238. package/dist/types/components/datetime/utils/helpers.d.ts +15 -1
  239. package/dist/types/components/menu/menu-interface.d.ts +0 -1
  240. package/dist/types/components/toast/animations/ios.enter.d.ts +2 -1
  241. package/dist/types/components/toast/animations/ios.leave.d.ts +2 -2
  242. package/dist/types/components/toast/animations/md.enter.d.ts +2 -1
  243. package/dist/types/components/toast/animations/utils.d.ts +18 -0
  244. package/dist/types/components/toast/toast-interface.d.ts +11 -0
  245. package/dist/types/components/toast/toast.d.ts +21 -1
  246. package/dist/types/components.d.ts +16 -8
  247. package/dist/types/index.d.ts +1 -0
  248. package/dist/types/utils/menu-controller/index.d.ts +1 -2
  249. package/hydrate/index.js +309 -87
  250. package/package.json +5 -6
  251. package/dist/esm-es5/data-009dbf15.js +0 -4
  252. package/dist/esm-es5/index-97a2bb98.js +0 -4
  253. package/dist/ionic/p-07c816fb.entry.js +0 -4
  254. package/dist/ionic/p-15041a8c.system.js +0 -4
  255. package/dist/ionic/p-15278928.entry.js +0 -4
  256. package/dist/ionic/p-44ef7224.system.js +0 -4
  257. package/dist/ionic/p-4c274938.entry.js +0 -4
  258. package/dist/ionic/p-63b4ef44.system.entry.js +0 -4
  259. package/dist/ionic/p-775f3749.entry.js +0 -4
  260. package/dist/ionic/p-77872abc.entry.js +0 -4
  261. package/dist/ionic/p-77b9d68a.system.entry.js +0 -4
  262. package/dist/ionic/p-7cfd253c.js +0 -4
  263. package/dist/ionic/p-8b33cfef.entry.js +0 -4
  264. package/dist/ionic/p-a1e2f98c.js +0 -4
  265. package/dist/ionic/p-c5395981.js +0 -4
  266. package/dist/ionic/p-c9524896.system.js +0 -4
  267. package/dist/ionic/p-d055bba9.entry.js +0 -4
  268. /package/dist/esm-es5/{haptic-6447af60.js → haptic-1243b917.js} +0 -0
  269. /package/dist/esm-es5/{index-ecfc2c9f.js → index-504b03f0.js} +0 -0
  270. /package/dist/esm-es5/{overlays-84621c0a.js → overlays-753933fc.js} +0 -0
  271. /package/dist/ionic/{p-0a87858b.js → p-15bae383.js} +0 -0
  272. /package/dist/ionic/{p-8985b268.system.js → p-3f919368.system.js} +0 -0
  273. /package/dist/ionic/{p-c8ec0d79.system.js → p-82c72668.system.js} +0 -0
  274. /package/dist/ionic/{p-14d7b7e2.system.js → p-b4b4bb29.system.js} +0 -0
  275. /package/dist/ionic/{p-bb6f38ed.js → p-b923f3d7.js} +0 -0
  276. /package/dist/ionic/{p-68a3da51.js → p-ee8881d0.js} +0 -0
@@ -0,0 +1,60 @@
1
+ /*!
2
+ * (C) Ionic http://ionicframework.com - MIT License
3
+ */
4
+ import { expect } from "@playwright/test";
5
+ import { configs, test } from "../../../../utils/test/playwright/index";
6
+ /**
7
+ * This behavior does not vary across modes/directions
8
+ */
9
+ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
10
+ test.describe(title('menu: multiple'), () => {
11
+ test.beforeEach(async ({ page }, testInfo) => {
12
+ testInfo.annotations.push({
13
+ type: 'issue',
14
+ description: 'https://github.com/ionic-team/ionic-framework/issues/18974',
15
+ });
16
+ await page.goto(`/src/components/menu/test/multiple`, config);
17
+ });
18
+ test('should present each menu on the same side individually', async ({ page }) => {
19
+ const primaryMenu = page.locator('ion-menu#primary-menu');
20
+ const secondaryMenu = page.locator('ion-menu#secondary-menu');
21
+ await primaryMenu.evaluate((el) => el.open());
22
+ await expect(primaryMenu).toBeVisible();
23
+ await primaryMenu.evaluate((el) => el.close());
24
+ await expect(primaryMenu).toBeHidden();
25
+ await secondaryMenu.evaluate((el) => el.open());
26
+ await expect(secondaryMenu).toBeVisible();
27
+ await secondaryMenu.evaluate((el) => el.close());
28
+ await expect(secondaryMenu).toBeHidden();
29
+ });
30
+ test('should close first menu when showing another menu on same side', async ({ page }) => {
31
+ const primaryMenu = page.locator('ion-menu#primary-menu');
32
+ const secondaryMenu = page.locator('ion-menu#secondary-menu');
33
+ await primaryMenu.evaluate((el) => el.open());
34
+ await expect(primaryMenu).toBeVisible();
35
+ await secondaryMenu.evaluate((el) => el.open());
36
+ await expect(primaryMenu).toBeHidden();
37
+ await expect(secondaryMenu).toBeVisible();
38
+ });
39
+ test('passing side to the menuController when multiple menus have that side should result in a warning', async ({ page, }) => {
40
+ const logs = [];
41
+ page.on('console', (msg) => {
42
+ if (msg.type() === 'warning') {
43
+ logs.push(msg.text());
44
+ }
45
+ });
46
+ await page.evaluate(() => window.menuController.open('start'));
47
+ expect(logs.length).toBe(1);
48
+ });
49
+ test('passing side to the menuController when multiple disabled menus have that side should result in a warning', async ({ page, }) => {
50
+ const logs = [];
51
+ page.on('console', (msg) => {
52
+ if (msg.type() === 'warning') {
53
+ logs.push(msg.text());
54
+ }
55
+ });
56
+ await page.evaluate(() => window.menuController.open('end'));
57
+ expect(logs.length).toBe(1);
58
+ });
59
+ });
60
+ });
@@ -672,6 +672,7 @@ export class Nav {
672
672
  : undefined;
673
673
  const mode = getIonMode(this);
674
674
  const enteringEl = enteringView.element;
675
+ // eslint-disable-next-line @typescript-eslint/prefer-optional-chain
675
676
  const leavingEl = leavingView && leavingView.element;
676
677
  const animationOpts = Object.assign(Object.assign({ mode, showGoBack: this.canGoBackSync(enteringView), baseEl: this.el, progressCallback, animated: this.animated && config.getBoolean('animated', true), enteringEl,
677
678
  leavingEl }, opts), { animationBuilder: opts.animationBuilder || this.animation || config.get('navAnimation') });
@@ -27,10 +27,7 @@ export class Radio {
27
27
  }
28
28
  };
29
29
  this.onClick = () => {
30
- const { radioGroup, checked, disabled } = this;
31
- if (disabled) {
32
- return;
33
- }
30
+ const { radioGroup, checked } = this;
34
31
  /**
35
32
  * The legacy control uses a native input inside
36
33
  * of the radio host, so we can set this.checked
@@ -33,7 +33,7 @@ export class RadioGroup {
33
33
  * using the `name` attribute.
34
34
  */
35
35
  const selectedRadio = ev.target && ev.target.closest('ion-radio');
36
- if (selectedRadio && selectedRadio.disabled === false) {
36
+ if (selectedRadio) {
37
37
  const currentValue = this.value;
38
38
  const newValue = selectedRadio.value;
39
39
  if (newValue !== currentValue) {
@@ -215,12 +215,14 @@ export class Router {
215
215
  }
216
216
  const routes = readRoutes(this.el);
217
217
  const fromChain = findChainForSegments(from, routes);
218
+ // eslint-disable-next-line @typescript-eslint/prefer-optional-chain
218
219
  const beforeLeaveHook = fromChain && fromChain[fromChain.length - 1].beforeLeave;
219
220
  const canLeave = beforeLeaveHook ? await beforeLeaveHook() : true;
220
221
  if (canLeave === false || typeof canLeave === 'object') {
221
222
  return canLeave;
222
223
  }
223
224
  const toChain = findChainForSegments(to, routes);
225
+ // eslint-disable-next-line @typescript-eslint/prefer-optional-chain
224
226
  const beforeEnterHook = toChain && toChain[toChain.length - 1].beforeEnter;
225
227
  return beforeEnterHook ? beforeEnterHook() : true;
226
228
  }
@@ -38,6 +38,7 @@ export const chainToSegments = (chain) => {
38
38
  for (const route of chain) {
39
39
  for (const segment of route.segments) {
40
40
  if (segment[0] === ':') {
41
+ // eslint-disable-next-line @typescript-eslint/prefer-optional-chain
41
42
  const param = route.params && route.params[segment.slice(1)];
42
43
  if (!param) {
43
44
  return null;
@@ -642,7 +642,7 @@ Developers can use the "legacy" property to continue using the legacy form marku
642
642
  }
643
643
  renderListbox() {
644
644
  const { disabled, inputId, isExpanded } = this;
645
- return (h("button", { disabled: disabled, id: inputId, "aria-label": this.ariaLabel, "aria-haspopup": "listbox", "aria-expanded": `${isExpanded}`, onFocus: this.onFocus, onBlur: this.onBlur, ref: (focusEl) => (this.focusEl = focusEl) }));
645
+ return (h("button", { disabled: disabled, id: inputId, "aria-label": this.ariaLabel, "aria-haspopup": "dialog", "aria-expanded": `${isExpanded}`, onFocus: this.onFocus, onBlur: this.onBlur, ref: (focusEl) => (this.focusEl = focusEl) }));
646
646
  }
647
647
  render() {
648
648
  const { legacyFormController } = this;
@@ -6,13 +6,12 @@ import { getElementRoot } from "../../../utils/helpers";
6
6
  /**
7
7
  * iOS Toast Enter Animation
8
8
  */
9
- export const iosEnterAnimation = (baseEl, position) => {
9
+ export const iosEnterAnimation = (baseEl, opts) => {
10
10
  const baseAnimation = createAnimation();
11
11
  const wrapperAnimation = createAnimation();
12
+ const { position, top, bottom } = opts;
12
13
  const root = getElementRoot(baseEl);
13
14
  const wrapperEl = root.querySelector('.toast-wrapper');
14
- const bottom = `calc(-10px - var(--ion-safe-area-bottom, 0px))`;
15
- const top = `calc(10px + var(--ion-safe-area-top, 0px))`;
16
15
  wrapperAnimation.addElement(wrapperEl);
17
16
  switch (position) {
18
17
  case 'top':
@@ -6,13 +6,12 @@ import { getElementRoot } from "../../../utils/helpers";
6
6
  /**
7
7
  * iOS Toast Leave Animation
8
8
  */
9
- export const iosLeaveAnimation = (baseEl, position) => {
9
+ export const iosLeaveAnimation = (baseEl, opts) => {
10
10
  const baseAnimation = createAnimation();
11
11
  const wrapperAnimation = createAnimation();
12
+ const { position, top, bottom } = opts;
12
13
  const root = getElementRoot(baseEl);
13
14
  const wrapperEl = root.querySelector('.toast-wrapper');
14
- const bottom = `calc(-10px - var(--ion-safe-area-bottom, 0px))`;
15
- const top = `calc(10px + var(--ion-safe-area-top, 0px))`;
16
15
  wrapperAnimation.addElement(wrapperEl);
17
16
  switch (position) {
18
17
  case 'top':
@@ -6,13 +6,12 @@ import { getElementRoot } from "../../../utils/helpers";
6
6
  /**
7
7
  * MD Toast Enter Animation
8
8
  */
9
- export const mdEnterAnimation = (baseEl, position) => {
9
+ export const mdEnterAnimation = (baseEl, opts) => {
10
10
  const baseAnimation = createAnimation();
11
11
  const wrapperAnimation = createAnimation();
12
+ const { position, top, bottom } = opts;
12
13
  const root = getElementRoot(baseEl);
13
14
  const wrapperEl = root.querySelector('.toast-wrapper');
14
- const bottom = `calc(8px + var(--ion-safe-area-bottom, 0px))`;
15
- const top = `calc(8px + var(--ion-safe-area-top, 0px))`;
16
15
  wrapperAnimation.addElement(wrapperEl);
17
16
  switch (position) {
18
17
  case 'top':
@@ -0,0 +1,85 @@
1
+ /*!
2
+ * (C) Ionic http://ionicframework.com - MIT License
3
+ */
4
+ import { win } from "../../../utils/browser/index";
5
+ import { printIonWarning } from "../../../utils/logging/index";
6
+ /**
7
+ * Calculate the CSS top and bottom position of the toast, to be used
8
+ * as starting points for the animation keyframes.
9
+ *
10
+ * Note that MD animates bottom-positioned toasts using style.bottom,
11
+ * which calculates from the bottom edge of the screen, while iOS uses
12
+ * translateY, which calculates from the top edge of the screen. This
13
+ * is why the bottom calculates differ slightly between modes.
14
+ *
15
+ * @param position The value of the toast's position prop.
16
+ * @param positionAnchor The element the toast should be anchored to,
17
+ * if applicable.
18
+ * @param mode The toast component's mode (md, ios, etc).
19
+ * @param toast A reference to the toast element itself.
20
+ */
21
+ export function getAnimationPosition(position, positionAnchor, mode, toast) {
22
+ /**
23
+ * Start with a predefined offset from the edge the toast will be
24
+ * positioned relative to, whether on the screen or anchor element.
25
+ */
26
+ let offset;
27
+ if (mode === 'md') {
28
+ offset = 8;
29
+ }
30
+ else {
31
+ offset = position === 'top' ? 10 : -10;
32
+ }
33
+ /**
34
+ * If positionAnchor is defined, add in the distance from the target
35
+ * screen edge to the target anchor edge. For position="top", the
36
+ * bottom anchor edge is targeted. For position="bottom", the top
37
+ * anchor edge is targeted.
38
+ */
39
+ if (positionAnchor && win) {
40
+ warnIfAnchorIsHidden(positionAnchor, toast);
41
+ const box = positionAnchor.getBoundingClientRect();
42
+ if (position === 'top') {
43
+ offset += box.bottom;
44
+ }
45
+ else if (position === 'bottom') {
46
+ /**
47
+ * Just box.top is the distance from the top edge of the screen
48
+ * to the top edge of the anchor. We want to calculate from the
49
+ * bottom edge of the screen instead.
50
+ */
51
+ if (mode === 'md') {
52
+ offset += win.innerHeight - box.top;
53
+ }
54
+ else {
55
+ offset -= win.innerHeight - box.top;
56
+ }
57
+ }
58
+ /**
59
+ * We don't include safe area here because that should already be
60
+ * accounted for when checking the position of the anchor.
61
+ */
62
+ return {
63
+ top: `${offset}px`,
64
+ bottom: `${offset}px`,
65
+ };
66
+ }
67
+ else {
68
+ return {
69
+ top: `calc(${offset}px + var(--ion-safe-area-top, 0px))`,
70
+ bottom: mode === 'md'
71
+ ? `calc(${offset}px + var(--ion-safe-area-bottom, 0px))`
72
+ : `calc(${offset}px - var(--ion-safe-area-bottom, 0px))`,
73
+ };
74
+ }
75
+ }
76
+ /**
77
+ * If the anchor element is hidden, getBoundingClientRect()
78
+ * will return all 0s for it, which can cause unexpected
79
+ * results in the position calculation when animating.
80
+ */
81
+ function warnIfAnchorIsHidden(positionAnchor, toast) {
82
+ if (positionAnchor.offsetParent === null) {
83
+ printIonWarning('The positionAnchor element for ion-toast was found in the DOM, but appears to be hidden. This may lead to unexpected positioning of the toast.', toast);
84
+ }
85
+ }
@@ -0,0 +1,45 @@
1
+ /*!
2
+ * (C) Ionic http://ionicframework.com - MIT License
3
+ */
4
+ import { expect } from "@playwright/test";
5
+ import { configs, test } from "../../../../utils/test/playwright/index";
6
+ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
7
+ test.describe(title('toast: positionAnchor'), () => {
8
+ test.beforeEach(async ({ page }) => {
9
+ await page.goto('/src/components/toast/test/position-anchor', config);
10
+ /**
11
+ * We need to screenshot the whole page to ensure the toasts are positioned
12
+ * correctly, but we don't need much extra white space between the header
13
+ * and footer.
14
+ */
15
+ await page.setViewportSize({
16
+ width: 425,
17
+ height: 425,
18
+ });
19
+ });
20
+ test('should place top-position toast underneath anchor', async ({ page }) => {
21
+ const ionToastDidPresent = await page.spyOnEvent('ionToastDidPresent');
22
+ await page.click('#headerAnchor');
23
+ await ionToastDidPresent.next();
24
+ await expect(page).toHaveScreenshot(screenshot(`toast-header-anchor`));
25
+ });
26
+ test('should place bottom-position toast above anchor', async ({ page }) => {
27
+ const ionToastDidPresent = await page.spyOnEvent('ionToastDidPresent');
28
+ await page.click('#footerAnchor');
29
+ await ionToastDidPresent.next();
30
+ await expect(page).toHaveScreenshot(screenshot(`toast-footer-anchor`));
31
+ });
32
+ test('should ignore anchor for middle-position toast', async ({ page }) => {
33
+ const ionToastDidPresent = await page.spyOnEvent('ionToastDidPresent');
34
+ await page.click('#middleAnchor');
35
+ await ionToastDidPresent.next();
36
+ await expect(page).toHaveScreenshot(screenshot(`toast-middle-anchor`));
37
+ });
38
+ test('should correctly anchor toast when using an element reference', async ({ page }) => {
39
+ const ionToastDidPresent = await page.spyOnEvent('ionToastDidPresent');
40
+ await page.click('#headerElAnchor');
41
+ await ionToastDidPresent.next();
42
+ await expect(page).toHaveScreenshot(screenshot(`toast-header-el-anchor`));
43
+ });
44
+ });
45
+ });
@@ -15,6 +15,7 @@ import { iosEnterAnimation } from "./animations/ios.enter";
15
15
  import { iosLeaveAnimation } from "./animations/ios.leave";
16
16
  import { mdEnterAnimation } from "./animations/md.enter";
17
17
  import { mdLeaveAnimation } from "./animations/md.leave";
18
+ import { getAnimationPosition } from "./animations/utils";
18
19
  // TODO(FW-2832): types
19
20
  /**
20
21
  * @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
@@ -54,6 +55,7 @@ export class Toast {
54
55
  this.message = undefined;
55
56
  this.keyboardClose = false;
56
57
  this.position = 'bottom';
58
+ this.positionAnchor = undefined;
57
59
  this.buttons = undefined;
58
60
  this.translucent = false;
59
61
  this.animated = true;
@@ -101,7 +103,19 @@ export class Toast {
101
103
  async present() {
102
104
  const unlock = await this.lockController.lock();
103
105
  await this.delegateController.attachViewToDom();
104
- await present(this, 'toastEnter', iosEnterAnimation, mdEnterAnimation, this.position);
106
+ const { el, position } = this;
107
+ const anchor = this.getAnchorElement();
108
+ const animationPosition = getAnimationPosition(position, anchor, getIonMode(this), el);
109
+ /**
110
+ * Cache the calculated position of the toast, so we can re-use it
111
+ * in the dismiss animation.
112
+ */
113
+ this.lastPresentedPosition = animationPosition;
114
+ await present(this, 'toastEnter', iosEnterAnimation, mdEnterAnimation, {
115
+ position,
116
+ top: animationPosition.top,
117
+ bottom: animationPosition.bottom,
118
+ });
105
119
  /**
106
120
  * Content is revealed to screen readers after
107
121
  * the transition to avoid jank since this
@@ -123,15 +137,28 @@ export class Toast {
123
137
  * Some examples include: ``"cancel"`, `"destructive"`, "selected"`, and `"backdrop"`.
124
138
  */
125
139
  async dismiss(data, role) {
140
+ var _a, _b;
126
141
  const unlock = await this.lockController.lock();
127
- if (this.durationTimeout) {
128
- clearTimeout(this.durationTimeout);
142
+ const { durationTimeout, position, lastPresentedPosition } = this;
143
+ if (durationTimeout) {
144
+ clearTimeout(durationTimeout);
129
145
  }
130
- const dismissed = await dismiss(this, data, role, 'toastLeave', iosLeaveAnimation, mdLeaveAnimation, this.position);
146
+ const dismissed = await dismiss(this, data, role, 'toastLeave', iosLeaveAnimation, mdLeaveAnimation,
147
+ /**
148
+ * Fetch the cached position that was calculated back in the present
149
+ * animation. We always want to animate the dismiss from the same
150
+ * position the present stopped at, so the animation looks continuous.
151
+ */
152
+ {
153
+ position,
154
+ top: (_a = lastPresentedPosition === null || lastPresentedPosition === void 0 ? void 0 : lastPresentedPosition.top) !== null && _a !== void 0 ? _a : '',
155
+ bottom: (_b = lastPresentedPosition === null || lastPresentedPosition === void 0 ? void 0 : lastPresentedPosition.bottom) !== null && _b !== void 0 ? _b : '',
156
+ });
131
157
  if (dismissed) {
132
158
  this.delegateController.removeViewFromDom();
133
159
  this.revealContentToScreenReader = false;
134
160
  }
161
+ this.lastPresentedPosition = undefined;
135
162
  unlock();
136
163
  return dismissed;
137
164
  }
@@ -155,6 +182,44 @@ export class Toast {
155
182
  : [];
156
183
  return buttons;
157
184
  }
185
+ /**
186
+ * Returns the element specified by the positionAnchor prop,
187
+ * or undefined if prop's value is an ID string and the element
188
+ * is not found in the DOM.
189
+ */
190
+ getAnchorElement() {
191
+ const { position, positionAnchor, el } = this;
192
+ /**
193
+ * If positionAnchor is undefined then
194
+ * no anchor should be used when presenting the toast.
195
+ */
196
+ if (positionAnchor === undefined) {
197
+ return;
198
+ }
199
+ if (position === 'middle' && positionAnchor !== undefined) {
200
+ printIonWarning('The positionAnchor property is ignored when using position="middle".', this.el);
201
+ return undefined;
202
+ }
203
+ if (typeof positionAnchor === 'string') {
204
+ /**
205
+ * If the anchor is defined as an ID, find the element.
206
+ * We do this on every present so the toast doesn't need
207
+ * to account for the surrounding DOM changing since the
208
+ * last time it was presented.
209
+ */
210
+ const foundEl = document.getElementById(positionAnchor);
211
+ if (foundEl === null) {
212
+ printIonWarning(`An anchor element with an ID of "${positionAnchor}" was not found in the DOM.`, el);
213
+ return undefined;
214
+ }
215
+ return foundEl;
216
+ }
217
+ if (positionAnchor instanceof HTMLElement) {
218
+ return positionAnchor;
219
+ }
220
+ printIonWarning('Invalid positionAnchor value:', positionAnchor, el);
221
+ return undefined;
222
+ }
158
223
  async buttonClick(button) {
159
224
  const role = button.role;
160
225
  if (isCancel(role)) {
@@ -517,12 +582,34 @@ export class Toast {
517
582
  "optional": false,
518
583
  "docs": {
519
584
  "tags": [],
520
- "text": "The position of the toast on the screen."
585
+ "text": "The starting position of the toast on the screen. Can be tweaked further\nusing the `positionAnchor` property."
521
586
  },
522
587
  "attribute": "position",
523
588
  "reflect": false,
524
589
  "defaultValue": "'bottom'"
525
590
  },
591
+ "positionAnchor": {
592
+ "type": "string",
593
+ "mutable": false,
594
+ "complexType": {
595
+ "original": "HTMLElement | string",
596
+ "resolved": "HTMLElement | string | undefined",
597
+ "references": {
598
+ "HTMLElement": {
599
+ "location": "global",
600
+ "id": "global::HTMLElement"
601
+ }
602
+ }
603
+ },
604
+ "required": false,
605
+ "optional": true,
606
+ "docs": {
607
+ "tags": [],
608
+ "text": "The element to anchor the toast's position to. Can be set as a direct reference\nor the ID of the element. With `position=\"bottom\"`, the toast will sit above the\nchosen element. With `position=\"top\"`, the toast will sit below the chosen element.\nWith `position=\"middle\"`, the value of `positionAnchor` is ignored."
609
+ },
610
+ "attribute": "position-anchor",
611
+ "reflect": false
612
+ },
526
613
  "buttons": {
527
614
  "type": "unknown",
528
615
  "mutable": false,
@@ -813,8 +900,9 @@ export class Toast {
813
900
  "id": "global::Promise"
814
901
  },
815
902
  "ToastPresentOptions": {
816
- "location": "global",
817
- "id": "global::ToastPresentOptions"
903
+ "location": "import",
904
+ "path": "./toast-interface",
905
+ "id": "src/components/toast/toast-interface.ts::ToastPresentOptions"
818
906
  }
819
907
  },
820
908
  "return": "Promise<void>"
@@ -846,8 +934,9 @@ export class Toast {
846
934
  "id": "global::Promise"
847
935
  },
848
936
  "ToastDismissOptions": {
849
- "location": "global",
850
- "id": "global::ToastDismissOptions"
937
+ "location": "import",
938
+ "path": "./toast-interface",
939
+ "id": "src/components/toast/toast-interface.ts::ToastDismissOptions"
851
940
  }
852
941
  },
853
942
  "return": "Promise<boolean>"
@@ -44,9 +44,6 @@ export class Toggle {
44
44
  }
45
45
  };
46
46
  this.onClick = (ev) => {
47
- if (this.disabled) {
48
- return;
49
- }
50
47
  ev.preventDefault();
51
48
  if (this.lastDrag + 300 < Date.now()) {
52
49
  this.toggleChecked();
@@ -13,6 +13,7 @@ export { componentOnReady } from './utils/helpers';
13
13
  export { isPlatform, getPlatforms } from './utils/platform';
14
14
  export { IonicSafeString } from './utils/sanitization';
15
15
  export { getMode, setupConfig } from './utils/config';
16
+ export { openURL } from './utils/theme';
16
17
  export { LIFECYCLE_WILL_ENTER, LIFECYCLE_DID_ENTER, LIFECYCLE_WILL_LEAVE, LIFECYCLE_DID_LEAVE, LIFECYCLE_WILL_UNLOAD, } from './components/nav/constants';
17
18
  export { menuController } from './utils/menu-controller';
18
19
  export { alertController, actionSheetController, modalController, loadingController, pickerController, popoverController, toastController, } from './utils/overlays';
@@ -1,6 +1,7 @@
1
1
  /*!
2
2
  * (C) Ionic http://ionicframework.com - MIT License
3
3
  */
4
+ import { printIonWarning } from "../logging/index";
4
5
  import { MENU_BACK_BUTTON_PRIORITY } from "../hardware-back-button";
5
6
  import { componentOnReady } from "../helpers";
6
7
  import { menuOverlayAnimation } from "./animations/overlay";
@@ -10,21 +11,21 @@ const createMenuController = () => {
10
11
  const menuAnimations = new Map();
11
12
  const menus = [];
12
13
  const open = async (menu) => {
13
- const menuEl = await get(menu);
14
+ const menuEl = await get(menu, true);
14
15
  if (menuEl) {
15
16
  return menuEl.open();
16
17
  }
17
18
  return false;
18
19
  };
19
20
  const close = async (menu) => {
20
- const menuEl = await (menu !== undefined ? get(menu) : getOpen());
21
+ const menuEl = await (menu !== undefined ? get(menu, true) : getOpen());
21
22
  if (menuEl !== undefined) {
22
23
  return menuEl.close();
23
24
  }
24
25
  return false;
25
26
  };
26
27
  const toggle = async (menu) => {
27
- const menuEl = await get(menu);
28
+ const menuEl = await get(menu, true);
28
29
  if (menuEl) {
29
30
  return menuEl.toggle();
30
31
  }
@@ -62,18 +63,35 @@ const createMenuController = () => {
62
63
  }
63
64
  return false;
64
65
  };
65
- const get = async (menu) => {
66
+ /**
67
+ * Finds and returns the menu specified by "menu" if registered.
68
+ * @param menu - The side or ID of the desired menu
69
+ * @param logOnMultipleSideMenus - If true, this function will log a warning
70
+ * if "menu" is a side but multiple menus on the same side were found. Since this function
71
+ * is used in multiple places, we default this log to false so that the calling
72
+ * functions can choose whether or not it is appropriate to log this warning.
73
+ */
74
+ const get = async (menu, logOnMultipleSideMenus = false) => {
66
75
  await waitUntilReady();
67
76
  if (menu === 'start' || menu === 'end') {
68
77
  // there could be more than one menu on the same side
69
78
  // so first try to get the enabled one
70
- const menuRef = find((m) => m.side === menu && !m.disabled);
71
- if (menuRef) {
72
- return menuRef;
79
+ const menuRefs = menus.filter((m) => m.side === menu && !m.disabled);
80
+ if (menuRefs.length >= 1) {
81
+ if (menuRefs.length > 1 && logOnMultipleSideMenus) {
82
+ printIonWarning(`menuController queried for a menu on the "${menu}" side, but ${menuRefs.length} menus were found. The first menu reference will be used. If this is not the behavior you want then pass the ID of the menu instead of its side.`, menuRefs.map((m) => m.el));
83
+ }
84
+ return menuRefs[0].el;
73
85
  }
74
86
  // didn't find a menu side that is enabled
75
87
  // so try to get the first menu side found
76
- return find((m) => m.side === menu);
88
+ const sideMenuRefs = menus.filter((m) => m.side === menu);
89
+ if (sideMenuRefs.length >= 1) {
90
+ if (sideMenuRefs.length > 1 && logOnMultipleSideMenus) {
91
+ printIonWarning(`menuController queried for a menu on the "${menu}" side, but ${sideMenuRefs.length} menus were found. The first menu reference will be used. If this is not the behavior you want then pass the ID of the menu instead of its side.`, sideMenuRefs.map((m) => m.el));
92
+ }
93
+ return sideMenuRefs[0].el;
94
+ }
77
95
  }
78
96
  else if (menu != null) {
79
97
  // the menuId was not left or right
@@ -115,9 +133,6 @@ const createMenuController = () => {
115
133
  };
116
134
  const _register = (menu) => {
117
135
  if (menus.indexOf(menu) < 0) {
118
- if (!menu.disabled) {
119
- _setActiveMenu(menu);
120
- }
121
136
  menus.push(menu);
122
137
  }
123
138
  };
@@ -127,13 +142,6 @@ const createMenuController = () => {
127
142
  menus.splice(index, 1);
128
143
  }
129
144
  };
130
- const _setActiveMenu = (menu) => {
131
- // if this menu should be enabled
132
- // then find all the other menus on this same side
133
- // and automatically disable other same side menus
134
- const side = menu.side;
135
- menus.filter((m) => m.side === side && m !== menu).forEach((m) => (m.disabled = true));
136
- };
137
145
  const _setOpen = async (menu, shouldOpen, animated) => {
138
146
  if (isAnimatingSync()) {
139
147
  return false;
@@ -205,7 +213,6 @@ const createMenuController = () => {
205
213
  _register,
206
214
  _unregister,
207
215
  _setOpen,
208
- _setActiveMenu,
209
216
  };
210
217
  };
211
218
  export const menuController = /*@__PURE__*/ createMenuController();
@@ -75,6 +75,7 @@ const HapticEngine = {
75
75
  * if the browser does not support the Vibrate API.
76
76
  */
77
77
  if ((capacitor === null || capacitor === void 0 ? void 0 : capacitor.getPlatform()) === 'web') {
78
+ // eslint-disable-next-line @typescript-eslint/prefer-optional-chain
78
79
  return typeof navigator !== 'undefined' && navigator.vibrate !== undefined;
79
80
  }
80
81
  return true;
@@ -68,6 +68,7 @@ export const setOverlayId = (el) => {
68
68
  return el.id;
69
69
  };
70
70
  export const createOverlay = (tagName, opts) => {
71
+ // eslint-disable-next-line @typescript-eslint/prefer-optional-chain
71
72
  if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined') {
72
73
  return window.customElements.whenDefined(tagName).then(() => {
73
74
  const element = document.createElement(tagName);
@@ -202,6 +202,7 @@ export const iosTransitionAnimation = (navEl, opts) => {
202
202
  .easing(opts.easing || EASING)
203
203
  .fill('both')
204
204
  .beforeRemoveClass('ion-page-invisible');
205
+ // eslint-disable-next-line @typescript-eslint/prefer-optional-chain
205
206
  if (leavingEl && navEl !== null && navEl !== undefined) {
206
207
  const navDecorAnimation = createAnimation();
207
208
  navDecorAnimation.addElement(navEl);