@ionic/core 8.0.0-beta.0 → 8.0.0-beta.1

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 (359) hide show
  1. package/components/input-shims.js +8 -1
  2. package/components/ion-item-divider.js +1 -1
  3. package/components/ion-menu.js +6 -27
  4. package/components/ion-modal.js +37 -5
  5. package/components/item.js +23 -9
  6. package/components/overlays.js +79 -36
  7. package/components/picker-column.js +20 -5
  8. package/components/popover.js +4 -4
  9. package/dist/cjs/{app-globals-92ad1b3d.js → app-globals-4d26cb5a.js} +1 -1
  10. package/dist/cjs/{button-active-8f6a8e77.js → button-active-e447f58b.js} +1 -1
  11. package/dist/cjs/{hardware-back-button-2696acaf.js → hardware-back-button-4cb049f1.js} +2 -2
  12. package/dist/cjs/{index-88b3bd6f.js → index-92bb95d6.js} +3 -3
  13. package/dist/cjs/{index-16fc2c94.js → index-bbc5b1f7.js} +2 -2
  14. package/dist/cjs/{index-0ffe376d.js → index-ea266398.js} +2 -2
  15. package/dist/cjs/index.cjs.js +8 -8
  16. package/dist/cjs/{input-shims-37843ce5.js → input-shims-679d87bc.js} +8 -1
  17. package/dist/cjs/ion-accordion_2.cjs.entry.js +2 -2
  18. package/dist/cjs/ion-action-sheet.cjs.entry.js +5 -5
  19. package/dist/cjs/ion-alert.cjs.entry.js +5 -5
  20. package/dist/cjs/ion-app_8.cjs.entry.js +7 -7
  21. package/dist/cjs/ion-avatar_3.cjs.entry.js +2 -2
  22. package/dist/cjs/ion-back-button.cjs.entry.js +2 -2
  23. package/dist/cjs/ion-backdrop.cjs.entry.js +2 -2
  24. package/dist/cjs/ion-breadcrumb_2.cjs.entry.js +2 -2
  25. package/dist/cjs/ion-button_2.cjs.entry.js +2 -2
  26. package/dist/cjs/ion-card_5.cjs.entry.js +2 -2
  27. package/dist/cjs/ion-checkbox.cjs.entry.js +2 -2
  28. package/dist/cjs/ion-chip.cjs.entry.js +2 -2
  29. package/dist/cjs/ion-col_3.cjs.entry.js +2 -2
  30. package/dist/cjs/ion-datetime-button.cjs.entry.js +2 -2
  31. package/dist/cjs/ion-datetime_3.cjs.entry.js +4 -4
  32. package/dist/cjs/ion-fab_3.cjs.entry.js +2 -2
  33. package/dist/cjs/ion-img.cjs.entry.js +2 -2
  34. package/dist/cjs/ion-infinite-scroll_2.cjs.entry.js +2 -2
  35. package/dist/cjs/ion-input.cjs.entry.js +2 -2
  36. package/dist/cjs/ion-item-option_3.cjs.entry.js +2 -2
  37. package/dist/cjs/ion-item_8.cjs.entry.js +25 -11
  38. package/dist/cjs/ion-loading.cjs.entry.js +4 -4
  39. package/dist/cjs/ion-menu_3.cjs.entry.js +11 -32
  40. package/dist/cjs/ion-modal.cjs.entry.js +42 -10
  41. package/dist/cjs/ion-nav_2.cjs.entry.js +3 -3
  42. package/dist/cjs/ion-picker-column-option.cjs.entry.js +2 -2
  43. package/dist/cjs/ion-picker-column.cjs.entry.js +22 -7
  44. package/dist/cjs/ion-picker.cjs.entry.js +1 -1
  45. package/dist/cjs/ion-popover.cjs.entry.js +8 -8
  46. package/dist/cjs/ion-progress-bar.cjs.entry.js +2 -2
  47. package/dist/cjs/ion-radio_2.cjs.entry.js +2 -2
  48. package/dist/cjs/ion-range.cjs.entry.js +2 -2
  49. package/dist/cjs/ion-refresher_2.cjs.entry.js +2 -2
  50. package/dist/cjs/ion-reorder_2.cjs.entry.js +2 -2
  51. package/dist/cjs/ion-ripple-effect.cjs.entry.js +2 -2
  52. package/dist/cjs/ion-route_4.cjs.entry.js +2 -2
  53. package/dist/cjs/ion-searchbar.cjs.entry.js +2 -2
  54. package/dist/cjs/ion-segment_2.cjs.entry.js +2 -2
  55. package/dist/cjs/ion-select_3.cjs.entry.js +4 -4
  56. package/dist/cjs/ion-spinner.cjs.entry.js +2 -2
  57. package/dist/cjs/ion-split-pane.cjs.entry.js +2 -2
  58. package/dist/cjs/ion-tab-bar_2.cjs.entry.js +2 -2
  59. package/dist/cjs/ion-tab_2.cjs.entry.js +1 -1
  60. package/dist/cjs/ion-text.cjs.entry.js +2 -2
  61. package/dist/cjs/ion-textarea.cjs.entry.js +2 -2
  62. package/dist/cjs/ion-toast.cjs.entry.js +4 -4
  63. package/dist/cjs/ion-toggle.cjs.entry.js +2 -2
  64. package/dist/cjs/{ionic-global-59a10130.js → ionic-global-59aa7eb7.js} +1 -1
  65. package/dist/cjs/ionic.cjs.js +5 -5
  66. package/dist/cjs/{ios.transition-b102ee38.js → ios.transition-997fe325.js} +2 -2
  67. package/dist/cjs/loader.cjs.js +4 -4
  68. package/dist/cjs/{md.transition-a5454240.js → md.transition-2b76c2c6.js} +2 -2
  69. package/dist/cjs/{overlays-6b7d156b.js → overlays-3d02b54f.js} +81 -37
  70. package/dist/cjs/{status-tap-b60dcbd8.js → status-tap-3761c2d4.js} +1 -1
  71. package/dist/collection/collection-manifest.json +1 -1
  72. package/dist/collection/components/datetime/test/basic/datetime.e2e.js +3 -1
  73. package/dist/collection/components/input/test/item/input.e2e.js +21 -0
  74. package/dist/collection/components/item/item.ios.css +1 -1
  75. package/dist/collection/components/item/item.js +20 -6
  76. package/dist/collection/components/item/item.md.css +5 -15
  77. package/dist/collection/components/item-divider/item-divider.md.css +4 -14
  78. package/dist/collection/components/menu/menu.js +6 -26
  79. package/dist/collection/components/modal/modal.js +37 -5
  80. package/dist/collection/components/modal/test/modal-attributes.spec.js +32 -0
  81. package/dist/collection/components/picker-column/picker-column.js +20 -5
  82. package/dist/collection/components/popover/popover.js +5 -4
  83. package/dist/collection/components/textarea/test/item/textarea.e2e.js +21 -0
  84. package/dist/collection/utils/focus-trap.js +78 -0
  85. package/dist/collection/utils/input-shims/input-shims.js +8 -1
  86. package/dist/collection/utils/overlays.js +3 -34
  87. package/dist/docs.json +2 -2
  88. package/dist/esm/{app-globals-5cf6195b.js → app-globals-cfb6787b.js} +1 -1
  89. package/dist/esm/{button-active-4407b98c.js → button-active-454e5c57.js} +1 -1
  90. package/dist/esm/{hardware-back-button-b410a047.js → hardware-back-button-3a14f99e.js} +2 -2
  91. package/dist/esm/{index-8758824c.js → index-03086279.js} +2 -2
  92. package/dist/esm/{index-1eff8599.js → index-5847f4a9.js} +3 -3
  93. package/dist/esm/{index-4c30cddd.js → index-9b6d6df3.js} +2 -2
  94. package/dist/esm/index.js +8 -8
  95. package/dist/esm/{input-shims-91e6634c.js → input-shims-56c1f603.js} +8 -1
  96. package/dist/esm/ion-accordion_2.entry.js +2 -2
  97. package/dist/esm/ion-action-sheet.entry.js +5 -5
  98. package/dist/esm/ion-alert.entry.js +5 -5
  99. package/dist/esm/ion-app_8.entry.js +7 -7
  100. package/dist/esm/ion-avatar_3.entry.js +2 -2
  101. package/dist/esm/ion-back-button.entry.js +2 -2
  102. package/dist/esm/ion-backdrop.entry.js +2 -2
  103. package/dist/esm/ion-breadcrumb_2.entry.js +2 -2
  104. package/dist/esm/ion-button_2.entry.js +2 -2
  105. package/dist/esm/ion-card_5.entry.js +2 -2
  106. package/dist/esm/ion-checkbox.entry.js +2 -2
  107. package/dist/esm/ion-chip.entry.js +2 -2
  108. package/dist/esm/ion-col_3.entry.js +2 -2
  109. package/dist/esm/ion-datetime-button.entry.js +2 -2
  110. package/dist/esm/ion-datetime_3.entry.js +4 -4
  111. package/dist/esm/ion-fab_3.entry.js +2 -2
  112. package/dist/esm/ion-img.entry.js +2 -2
  113. package/dist/esm/ion-infinite-scroll_2.entry.js +2 -2
  114. package/dist/esm/ion-input.entry.js +2 -2
  115. package/dist/esm/ion-item-option_3.entry.js +2 -2
  116. package/dist/esm/ion-item_8.entry.js +25 -11
  117. package/dist/esm/ion-loading.entry.js +4 -4
  118. package/dist/esm/ion-menu_3.entry.js +11 -32
  119. package/dist/esm/ion-modal.entry.js +42 -10
  120. package/dist/esm/ion-nav_2.entry.js +3 -3
  121. package/dist/esm/ion-picker-column-option.entry.js +2 -2
  122. package/dist/esm/ion-picker-column.entry.js +22 -7
  123. package/dist/esm/ion-picker.entry.js +1 -1
  124. package/dist/esm/ion-popover.entry.js +8 -8
  125. package/dist/esm/ion-progress-bar.entry.js +2 -2
  126. package/dist/esm/ion-radio_2.entry.js +2 -2
  127. package/dist/esm/ion-range.entry.js +2 -2
  128. package/dist/esm/ion-refresher_2.entry.js +2 -2
  129. package/dist/esm/ion-reorder_2.entry.js +2 -2
  130. package/dist/esm/ion-ripple-effect.entry.js +2 -2
  131. package/dist/esm/ion-route_4.entry.js +2 -2
  132. package/dist/esm/ion-searchbar.entry.js +2 -2
  133. package/dist/esm/ion-segment_2.entry.js +2 -2
  134. package/dist/esm/ion-select_3.entry.js +4 -4
  135. package/dist/esm/ion-spinner.entry.js +2 -2
  136. package/dist/esm/ion-split-pane.entry.js +2 -2
  137. package/dist/esm/ion-tab-bar_2.entry.js +2 -2
  138. package/dist/esm/ion-tab_2.entry.js +1 -1
  139. package/dist/esm/ion-text.entry.js +2 -2
  140. package/dist/esm/ion-textarea.entry.js +2 -2
  141. package/dist/esm/ion-toast.entry.js +4 -4
  142. package/dist/esm/ion-toggle.entry.js +2 -2
  143. package/dist/esm/{ionic-global-ad9a1810.js → ionic-global-c976d684.js} +1 -1
  144. package/dist/esm/ionic.js +6 -6
  145. package/dist/esm/{ios.transition-189b73b7.js → ios.transition-a097dbf5.js} +2 -2
  146. package/dist/esm/loader.js +5 -5
  147. package/dist/esm/{md.transition-c9761eef.js → md.transition-b4170ef7.js} +2 -2
  148. package/dist/esm/{overlays-c69d2a07.js → overlays-4ba3b255.js} +81 -38
  149. package/dist/esm/{status-tap-1d638ee6.js → status-tap-7a12f017.js} +1 -1
  150. package/dist/esm-es5/app-globals-cfb6787b.js +4 -0
  151. package/dist/esm-es5/{button-active-4407b98c.js → button-active-454e5c57.js} +1 -1
  152. package/dist/esm-es5/{hardware-back-button-b410a047.js → hardware-back-button-3a14f99e.js} +1 -1
  153. package/dist/esm-es5/{index-8758824c.js → index-03086279.js} +1 -1
  154. package/dist/esm-es5/{index-1eff8599.js → index-5847f4a9.js} +1 -1
  155. package/dist/esm-es5/{index-4c30cddd.js → index-9b6d6df3.js} +1 -1
  156. package/dist/esm-es5/index.js +1 -1
  157. package/dist/esm-es5/{input-shims-91e6634c.js → input-shims-56c1f603.js} +1 -1
  158. package/dist/esm-es5/ion-accordion_2.entry.js +1 -1
  159. package/dist/esm-es5/ion-action-sheet.entry.js +1 -1
  160. package/dist/esm-es5/ion-alert.entry.js +1 -1
  161. package/dist/esm-es5/ion-app_8.entry.js +1 -1
  162. package/dist/esm-es5/ion-avatar_3.entry.js +1 -1
  163. package/dist/esm-es5/ion-back-button.entry.js +1 -1
  164. package/dist/esm-es5/ion-backdrop.entry.js +1 -1
  165. package/dist/esm-es5/ion-breadcrumb_2.entry.js +1 -1
  166. package/dist/esm-es5/ion-button_2.entry.js +1 -1
  167. package/dist/esm-es5/ion-card_5.entry.js +1 -1
  168. package/dist/esm-es5/ion-checkbox.entry.js +1 -1
  169. package/dist/esm-es5/ion-chip.entry.js +1 -1
  170. package/dist/esm-es5/ion-col_3.entry.js +1 -1
  171. package/dist/esm-es5/ion-datetime-button.entry.js +1 -1
  172. package/dist/esm-es5/ion-datetime_3.entry.js +1 -1
  173. package/dist/esm-es5/ion-fab_3.entry.js +1 -1
  174. package/dist/esm-es5/ion-img.entry.js +1 -1
  175. package/dist/esm-es5/ion-infinite-scroll_2.entry.js +1 -1
  176. package/dist/esm-es5/ion-input.entry.js +1 -1
  177. package/dist/esm-es5/ion-item-option_3.entry.js +1 -1
  178. package/dist/esm-es5/ion-item_8.entry.js +1 -1
  179. package/dist/esm-es5/ion-loading.entry.js +1 -1
  180. package/dist/esm-es5/ion-menu_3.entry.js +1 -1
  181. package/dist/esm-es5/ion-modal.entry.js +1 -1
  182. package/dist/esm-es5/ion-nav_2.entry.js +1 -1
  183. package/dist/esm-es5/ion-picker-column-option.entry.js +1 -1
  184. package/dist/esm-es5/ion-picker-column.entry.js +1 -1
  185. package/dist/esm-es5/ion-picker.entry.js +1 -1
  186. package/dist/esm-es5/ion-popover.entry.js +1 -1
  187. package/dist/esm-es5/ion-progress-bar.entry.js +1 -1
  188. package/dist/esm-es5/ion-radio_2.entry.js +1 -1
  189. package/dist/esm-es5/ion-range.entry.js +1 -1
  190. package/dist/esm-es5/ion-refresher_2.entry.js +1 -1
  191. package/dist/esm-es5/ion-reorder_2.entry.js +1 -1
  192. package/dist/esm-es5/ion-ripple-effect.entry.js +1 -1
  193. package/dist/esm-es5/ion-route_4.entry.js +1 -1
  194. package/dist/esm-es5/ion-searchbar.entry.js +1 -1
  195. package/dist/esm-es5/ion-segment_2.entry.js +1 -1
  196. package/dist/esm-es5/ion-select_3.entry.js +1 -1
  197. package/dist/esm-es5/ion-spinner.entry.js +1 -1
  198. package/dist/esm-es5/ion-split-pane.entry.js +1 -1
  199. package/dist/esm-es5/ion-tab-bar_2.entry.js +1 -1
  200. package/dist/esm-es5/ion-tab_2.entry.js +1 -1
  201. package/dist/esm-es5/ion-text.entry.js +1 -1
  202. package/dist/esm-es5/ion-textarea.entry.js +1 -1
  203. package/dist/esm-es5/ion-toast.entry.js +1 -1
  204. package/dist/esm-es5/ion-toggle.entry.js +1 -1
  205. package/dist/esm-es5/{ionic-global-ad9a1810.js → ionic-global-c976d684.js} +1 -1
  206. package/dist/esm-es5/ionic.js +1 -1
  207. package/dist/esm-es5/{ios.transition-189b73b7.js → ios.transition-a097dbf5.js} +1 -1
  208. package/dist/esm-es5/loader.js +1 -1
  209. package/dist/esm-es5/md.transition-b4170ef7.js +4 -0
  210. package/dist/esm-es5/overlays-4ba3b255.js +4 -0
  211. package/dist/esm-es5/{status-tap-1d638ee6.js → status-tap-7a12f017.js} +1 -1
  212. package/dist/ionic/index.esm.js +1 -1
  213. package/dist/ionic/ionic.esm.js +1 -1
  214. package/dist/ionic/ionic.js +1 -1
  215. package/dist/ionic/p-03f63663.system.js +4 -0
  216. package/dist/ionic/{p-d9b6b588.entry.js → p-060fdc03.entry.js} +1 -1
  217. package/dist/ionic/{p-7292add8.entry.js → p-06fccad7.entry.js} +1 -1
  218. package/dist/ionic/{p-eb506d19.system.entry.js → p-08dfa278.system.entry.js} +1 -1
  219. package/dist/ionic/{p-0612cdcc.system.entry.js → p-09872ec8.system.entry.js} +1 -1
  220. package/dist/ionic/p-0ca35c1d.system.entry.js +4 -0
  221. package/dist/ionic/{p-916a4e14.entry.js → p-0efb1cce.entry.js} +1 -1
  222. package/dist/ionic/{p-0b34d3a7.system.js → p-134d4936.system.js} +1 -1
  223. package/dist/ionic/{p-5e70f800.system.entry.js → p-1600d68c.system.entry.js} +1 -1
  224. package/dist/ionic/p-19e79fe8.entry.js +4 -0
  225. package/dist/ionic/{p-de0a7606.system.entry.js → p-1a5ed3fe.system.entry.js} +1 -1
  226. package/dist/ionic/{p-f7d802e1.entry.js → p-1a68de09.entry.js} +1 -1
  227. package/dist/ionic/{p-3c47c5c8.system.entry.js → p-1bca443b.system.entry.js} +1 -1
  228. package/dist/ionic/{p-3d77b300.system.entry.js → p-1c436e95.system.entry.js} +1 -1
  229. package/dist/ionic/{p-e46adaf1.system.entry.js → p-1ccbaaf3.system.entry.js} +1 -1
  230. package/dist/ionic/{p-8fe3c4ef.entry.js → p-1ce172db.entry.js} +1 -1
  231. package/dist/ionic/{p-5133c4a3.system.entry.js → p-1e0a18a1.system.entry.js} +1 -1
  232. package/dist/ionic/{p-6e14d3ca.system.entry.js → p-1ed99eba.system.entry.js} +1 -1
  233. package/dist/ionic/{p-de55ec45.js → p-1fa738c4.js} +1 -1
  234. package/dist/ionic/p-22d2a891.js +4 -0
  235. package/dist/ionic/{p-385f66bc.entry.js → p-25850474.entry.js} +1 -1
  236. package/dist/ionic/{p-ceceac26.js → p-27594fc2.js} +1 -1
  237. package/dist/ionic/{p-ec77b7ad.system.entry.js → p-2b3e0d99.system.entry.js} +1 -1
  238. package/dist/ionic/{p-13e8ad2e.entry.js → p-300b2cf1.entry.js} +1 -1
  239. package/dist/ionic/{p-6525a8cd.system.js → p-30892e0c.system.js} +1 -1
  240. package/dist/ionic/{p-16e06393.system.js → p-3410a9cb.system.js} +1 -1
  241. package/dist/ionic/{p-973c7550.system.entry.js → p-3bac30bf.system.entry.js} +1 -1
  242. package/dist/ionic/{p-cefbb7b7.entry.js → p-41970e75.entry.js} +1 -1
  243. package/dist/ionic/p-41b9cdd2.entry.js +4 -0
  244. package/dist/ionic/{p-5eabaa80.js → p-43322b14.js} +1 -1
  245. package/dist/ionic/p-4523be60.entry.js +4 -0
  246. package/dist/ionic/{p-5d64e680.entry.js → p-466bdeae.entry.js} +1 -1
  247. package/dist/ionic/{p-717c4b72.entry.js → p-4825e380.entry.js} +1 -1
  248. package/dist/ionic/p-4ad02639.entry.js +4 -0
  249. package/dist/ionic/{p-1df25966.entry.js → p-4c2cac66.entry.js} +1 -1
  250. package/dist/ionic/{p-00a762c9.entry.js → p-5a055df4.entry.js} +1 -1
  251. package/dist/ionic/{p-5d7e32ce.js → p-5aa60929.js} +1 -1
  252. package/dist/ionic/{p-e311af42.entry.js → p-5afb6e48.entry.js} +1 -1
  253. package/dist/ionic/{p-5797981d.system.entry.js → p-5c3991e3.system.entry.js} +2 -2
  254. package/dist/ionic/{p-1f79e54a.entry.js → p-602494c6.entry.js} +1 -1
  255. package/dist/ionic/{p-ed7a529f.js → p-60efe117.js} +1 -1
  256. package/dist/ionic/{p-c9e21694.system.entry.js → p-62f15daf.system.entry.js} +2 -2
  257. package/dist/ionic/{p-f0a7e80b.js → p-65d3f0e9.js} +1 -1
  258. package/dist/ionic/p-6657681b.system.entry.js +4 -0
  259. package/dist/ionic/{p-98e6b3b8.system.js → p-6d95943d.system.js} +1 -1
  260. package/dist/ionic/p-6e1fa025.js +4 -0
  261. package/dist/ionic/{p-6ad90d41.entry.js → p-6e5eeb35.entry.js} +1 -1
  262. package/dist/ionic/{p-f7ccf8d9.entry.js → p-6f6d56f1.entry.js} +1 -1
  263. package/dist/ionic/{p-e1819aee.js → p-6fd26009.js} +1 -1
  264. package/dist/ionic/{p-11bb459e.system.entry.js → p-70218e28.system.entry.js} +1 -1
  265. package/dist/ionic/{p-d47a1a78.system.entry.js → p-72bc2484.system.entry.js} +1 -1
  266. package/dist/ionic/{p-acf70e64.system.entry.js → p-7541ca9f.system.entry.js} +1 -1
  267. package/dist/ionic/{p-34d0f143.system.entry.js → p-7665bbbc.system.entry.js} +1 -1
  268. package/dist/ionic/{p-1d545773.entry.js → p-77982637.entry.js} +1 -1
  269. package/dist/ionic/{p-0a8a78db.system.entry.js → p-780ff3b5.system.entry.js} +1 -1
  270. package/dist/ionic/{p-415ccddd.entry.js → p-7a3fa32c.entry.js} +1 -1
  271. package/dist/ionic/{p-9f84474d.entry.js → p-7b44b443.entry.js} +1 -1
  272. package/dist/ionic/p-7cc01684.js +4 -0
  273. package/dist/ionic/{p-2d7624d4.system.js → p-816476b0.system.js} +1 -1
  274. package/dist/ionic/{p-b434ded7.system.entry.js → p-81869a97.system.entry.js} +1 -1
  275. package/dist/ionic/{p-97248203.system.entry.js → p-82f5375e.system.entry.js} +1 -1
  276. package/dist/ionic/{p-d3f79a49.js → p-842777af.js} +1 -1
  277. package/dist/ionic/{p-1a4db355.system.entry.js → p-85464e28.system.entry.js} +2 -2
  278. package/dist/ionic/{p-9d795c4b.entry.js → p-85cb4733.entry.js} +1 -1
  279. package/dist/ionic/{p-fd783a38.system.entry.js → p-874510e9.system.entry.js} +1 -1
  280. package/dist/ionic/{p-d7c78a97.system.entry.js → p-8aeed464.system.entry.js} +1 -1
  281. package/dist/ionic/p-8ba5912c.entry.js +4 -0
  282. package/dist/ionic/{p-72fa96bf.system.js → p-8d602214.system.js} +1 -1
  283. package/dist/ionic/{p-640fac4a.system.entry.js → p-8e3ee444.system.entry.js} +1 -1
  284. package/dist/ionic/{p-892e2567.system.entry.js → p-8e83b7f1.system.entry.js} +1 -1
  285. package/dist/ionic/{p-1e07fdb2.system.entry.js → p-91a72ad6.system.entry.js} +1 -1
  286. package/dist/ionic/p-9382ebab.entry.js +4 -0
  287. package/dist/ionic/{p-3209217f.entry.js → p-942c19cb.entry.js} +1 -1
  288. package/dist/ionic/{p-eb9803e9.system.js → p-95e14c7b.system.js} +1 -1
  289. package/dist/ionic/{p-d13689a6.entry.js → p-96391c0e.entry.js} +1 -1
  290. package/dist/ionic/{p-80704be1.entry.js → p-97135baa.entry.js} +1 -1
  291. package/dist/ionic/p-a06af32c.system.js +4 -0
  292. package/dist/ionic/{p-446f3909.system.entry.js → p-a375c9f6.system.entry.js} +1 -1
  293. package/dist/ionic/{p-93e79b55.js → p-a58ec401.js} +1 -1
  294. package/dist/ionic/p-a5b7a286.entry.js +4 -0
  295. package/dist/ionic/{p-31e02742.system.js → p-a71dc777.system.js} +1 -1
  296. package/dist/ionic/{p-174856b4.system.js → p-a8cc0027.system.js} +1 -1
  297. package/dist/ionic/{p-c8d61b6c.system.entry.js → p-aaca8dd4.system.entry.js} +1 -1
  298. package/dist/ionic/{p-2dcf2ec2.system.entry.js → p-ad2b216a.system.entry.js} +1 -1
  299. package/dist/ionic/{p-ef636601.entry.js → p-add93c7a.entry.js} +1 -1
  300. package/dist/ionic/{p-ab427719.entry.js → p-afcd4f49.entry.js} +1 -1
  301. package/dist/ionic/{p-94f85e19.system.entry.js → p-b1a9e85a.system.entry.js} +1 -1
  302. package/dist/ionic/{p-dd7c79ce.system.entry.js → p-b4bb9cd0.system.entry.js} +1 -1
  303. package/dist/ionic/{p-d8643420.system.entry.js → p-baa409f1.system.entry.js} +1 -1
  304. package/dist/ionic/{p-8b8b900d.entry.js → p-bcb58446.entry.js} +1 -1
  305. package/dist/ionic/p-c2336a9e.system.entry.js +4 -0
  306. package/dist/ionic/{p-1deadb7f.system.js → p-c38c5dfc.system.js} +1 -1
  307. package/dist/ionic/{p-5d530ae5.entry.js → p-c3a2e5cc.entry.js} +1 -1
  308. package/dist/ionic/{p-c6dbc089.system.entry.js → p-c5b77291.system.entry.js} +1 -1
  309. package/dist/ionic/{p-b2d58604.system.entry.js → p-cb0e4100.system.entry.js} +1 -1
  310. package/dist/ionic/{p-6dbea874.system.entry.js → p-cb3f2ab6.system.entry.js} +1 -1
  311. package/dist/ionic/{p-bca27ea7.entry.js → p-cbc3840e.entry.js} +1 -1
  312. package/dist/ionic/{p-4bbc949f.system.entry.js → p-cd366840.system.entry.js} +1 -1
  313. package/dist/ionic/{p-60a92a48.system.entry.js → p-cf852615.system.entry.js} +1 -1
  314. package/dist/ionic/{p-174b0d50.system.entry.js → p-d4d0538c.system.entry.js} +1 -1
  315. package/dist/ionic/{p-993da5df.entry.js → p-d504bc71.entry.js} +1 -1
  316. package/dist/ionic/{p-0dca0eee.system.entry.js → p-da83d833.system.entry.js} +1 -1
  317. package/dist/ionic/{p-4dfe0487.system.entry.js → p-dcfc297d.system.entry.js} +1 -1
  318. package/dist/ionic/{p-5f9fbad0.entry.js → p-ddc4e717.entry.js} +1 -1
  319. package/dist/ionic/{p-d7dc29c5.entry.js → p-ded27993.entry.js} +1 -1
  320. package/dist/ionic/{p-4b3a4938.entry.js → p-df7ea05d.entry.js} +1 -1
  321. package/dist/ionic/p-e15eda82.system.js +4 -0
  322. package/dist/ionic/{p-d84c9fc4.entry.js → p-e38b3c29.entry.js} +1 -1
  323. package/dist/ionic/{p-6d659d62.entry.js → p-e470466e.entry.js} +1 -1
  324. package/dist/ionic/{p-12b55b00.system.entry.js → p-ebe0be94.system.entry.js} +1 -1
  325. package/dist/ionic/{p-89ca4c4b.system.js → p-eec92f77.system.js} +1 -1
  326. package/dist/ionic/{p-7e185a31.entry.js → p-ef99a759.entry.js} +1 -1
  327. package/dist/ionic/{p-2b3544ad.entry.js → p-f16bfd53.entry.js} +1 -1
  328. package/dist/ionic/{p-df6a1571.entry.js → p-f3d6085c.entry.js} +1 -1
  329. package/dist/ionic/{p-3807cd45.system.entry.js → p-f6a6b7ef.system.entry.js} +1 -1
  330. package/dist/ionic/{p-ef9736b9.entry.js → p-f71082f7.entry.js} +1 -1
  331. package/dist/ionic/{p-3c51cf97.system.entry.js → p-f7ed6a44.system.entry.js} +1 -1
  332. package/dist/ionic/{p-0dfbbdbe.entry.js → p-fc5ddbf6.entry.js} +1 -1
  333. package/dist/ionic/{p-f7c3d736.system.entry.js → p-fd94dd20.system.entry.js} +1 -1
  334. package/dist/ionic/{p-6aeb0272.entry.js → p-feb66f6f.entry.js} +1 -1
  335. package/dist/types/components/menu/menu.d.ts +0 -2
  336. package/dist/types/utils/focus-trap.d.ts +35 -0
  337. package/dist/types/utils/overlays.d.ts +0 -6
  338. package/hydrate/index.js +223 -114
  339. package/package.json +1 -1
  340. package/dist/collection/components/modal/test/a11y/modal.spec.js +0 -22
  341. package/dist/esm-es5/app-globals-5cf6195b.js +0 -4
  342. package/dist/esm-es5/md.transition-c9761eef.js +0 -4
  343. package/dist/esm-es5/overlays-c69d2a07.js +0 -4
  344. package/dist/ionic/p-0f25a7bb.system.js +0 -4
  345. package/dist/ionic/p-0f81df5e.entry.js +0 -4
  346. package/dist/ionic/p-17082c91.system.js +0 -4
  347. package/dist/ionic/p-2c768965.entry.js +0 -4
  348. package/dist/ionic/p-32fb7d95.entry.js +0 -4
  349. package/dist/ionic/p-4e7abe76.js +0 -4
  350. package/dist/ionic/p-5dbf7222.entry.js +0 -4
  351. package/dist/ionic/p-75861cd3.entry.js +0 -4
  352. package/dist/ionic/p-90b3e3b0.system.entry.js +0 -4
  353. package/dist/ionic/p-96107183.js +0 -4
  354. package/dist/ionic/p-986a47ee.system.entry.js +0 -4
  355. package/dist/ionic/p-9c93fdcd.js +0 -4
  356. package/dist/ionic/p-9ecc1e42.entry.js +0 -4
  357. package/dist/ionic/p-cd0ffc8c.entry.js +0 -4
  358. package/dist/ionic/p-df504a37.system.js +0 -4
  359. package/dist/ionic/p-e755046f.system.entry.js +0 -4
@@ -41,3 +41,24 @@ configs().forEach(({ title, screenshot, config }) => {
41
41
  });
42
42
  });
43
43
  });
44
+ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
45
+ test.describe(title('input: item functionality'), () => {
46
+ test('clicking padded space within item should focus the input', async ({ page }) => {
47
+ await page.setContent(`
48
+ <ion-item>
49
+ <ion-input label="Input"></ion-input>
50
+ </ion-item>
51
+ `, config);
52
+ const itemNative = page.locator('.item-native');
53
+ const input = page.locator('ion-input input');
54
+ // Clicks the padded space within the item
55
+ await itemNative.click({
56
+ position: {
57
+ x: 5,
58
+ y: 5,
59
+ },
60
+ });
61
+ await expect(input).toBeFocused();
62
+ });
63
+ });
64
+ });
@@ -189,7 +189,7 @@
189
189
  background: var(--ion-color-contrast);
190
190
  }
191
191
  }
192
- :host(.item-has-interactive-control) {
192
+ :host(.item-control-needs-pointer-cursor) {
193
193
  cursor: pointer;
194
194
  }
195
195
 
@@ -199,7 +199,7 @@ export class Item {
199
199
  }
200
200
  }
201
201
  getFirstInteractive() {
202
- const controls = this.el.querySelectorAll('ion-toggle:not([disabled]), ion-checkbox:not([disabled]), ion-radio:not([disabled]), ion-select:not([disabled])');
202
+ const controls = this.el.querySelectorAll('ion-toggle:not([disabled]), ion-checkbox:not([disabled]), ion-radio:not([disabled]), ion-select:not([disabled]), ion-input:not([disabled]), ion-textarea:not([disabled])');
203
203
  return controls[0];
204
204
  }
205
205
  render() {
@@ -241,7 +241,17 @@ export class Item {
241
241
  */
242
242
  const clickedWithinShadowRoot = this.el.shadowRoot.contains(target);
243
243
  if (clickedWithinShadowRoot) {
244
- firstInteractive.click();
244
+ /**
245
+ * For input/textarea clicking the padding should focus the
246
+ * text field (thus making it editable). For everything else,
247
+ * we want to click the control so it activates.
248
+ */
249
+ if (firstInteractive.tagName === 'ION-INPUT' || firstInteractive.tagName === 'ION-TEXTAREA') {
250
+ firstInteractive.setFocus();
251
+ }
252
+ else {
253
+ firstInteractive.click();
254
+ }
245
255
  }
246
256
  }
247
257
  }
@@ -255,25 +265,29 @@ export class Item {
255
265
  const ariaDisabled = disabled || childStyles['item-interactive-disabled'] ? 'true' : null;
256
266
  const fillValue = fill || 'none';
257
267
  const inList = hostContext('ion-list', this.el) && !hostContext('ion-radio-group', this.el);
258
- return (h(Host, { key: '077c9ab04985292f79c30691151d2778a26285fb', "aria-disabled": ariaDisabled, class: Object.assign(Object.assign(Object.assign({}, childStyles), labelColorStyles), createColorClasses(this.color, {
268
+ /**
269
+ * Inputs and textareas do not need to show a cursor pointer.
270
+ * However, other form controls such as checkboxes and radios do.
271
+ */
272
+ const firstInteractiveNeedsPointerCursor = firstInteractive !== undefined && !['ION-INPUT', 'ION-TEXTAREA'].includes(firstInteractive.tagName);
273
+ return (h(Host, { key: 'cea10ae44ddc3ac8ebcee481f2696bae900a3a34', "aria-disabled": ariaDisabled, class: Object.assign(Object.assign(Object.assign({}, childStyles), labelColorStyles), createColorClasses(this.color, {
259
274
  item: true,
260
275
  [mode]: true,
261
276
  'item-lines-default': lines === undefined,
262
277
  [`item-lines-${lines}`]: lines !== undefined,
263
278
  [`item-fill-${fillValue}`]: true,
264
279
  [`item-shape-${shape}`]: shape !== undefined,
265
- 'item-has-interactive-control': firstInteractive !== undefined,
280
+ 'item-control-needs-pointer-cursor': firstInteractiveNeedsPointerCursor,
266
281
  'item-disabled': disabled,
267
282
  'in-list': inList,
268
283
  'item-multiple-inputs': this.multipleInputs,
269
284
  'ion-activatable': canActivate,
270
285
  'ion-focusable': this.focusable,
271
286
  'item-rtl': document.dir === 'rtl',
272
- })), role: inList ? 'listitem' : null }, h(TagType, Object.assign({ key: '08bb75c85d0584e9fb7f461e9e06b9b651ef3515' }, attrs, inheritedAriaAttributes, { class: "item-native", part: "native", disabled: disabled }, clickFn), h("slot", { key: '3f742b07c4a58eadedf675be4878a3e00070750e', name: "start" }), h("div", { key: '0160b8963434f3107856a2df2fb96f1abb4fdbfe', class: "item-inner" }, h("div", { key: '9439b21474443341f06a651d7c44aef90bd4c591', class: "input-wrapper" }, h("slot", { key: '8034e1337a6c950b7725bc9aa46d55de980827bf' })), h("slot", { key: '690de6d3dd3a238ab7a2d3dfea69daa6647e5134', name: "end" }), showDetail && (h("ion-icon", { icon: detailIcon, lazy: false, class: "item-detail-icon", part: "detail-icon", "aria-hidden": "true", "flip-rtl": detailIcon === chevronForward })), h("div", { key: 'e96885084ca845656fd4d18902528ce7de207c86', class: "item-inner-highlight" })), canActivate && mode === 'md' && h("ion-ripple-effect", null), h("div", { key: '64e5323c380e05aa183e8dd7fbe560d084725f5e', class: "item-highlight" })), h("div", { key: '677132e6193981697f494b215ddc02407fdd96a5', class: "item-bottom" }, h("slot", { key: 'cda34a9208020bbb18ca5313e0bfbf270f024012', name: "error" }), h("slot", { key: 'c1b3541b11ece13309d0e28dd3a95c048dfab43f', name: "helper" }), counterString && h("ion-note", { class: "item-counter" }, counterString))));
287
+ })), role: inList ? 'listitem' : null }, h(TagType, Object.assign({ key: '48fd3c900652d21d364c738ceb328101dfce6260' }, attrs, inheritedAriaAttributes, { class: "item-native", part: "native", disabled: disabled }, clickFn), h("slot", { key: 'd6f1e007a969f60977789f4cca3d2a8a3f52dd70', name: "start" }), h("div", { key: '0a8fafdaf5171ab073890532d65dd96aa9d2aa86', class: "item-inner" }, h("div", { key: '063bd8f3d87b8efee1f97582cb212db8dc502bf4', class: "input-wrapper" }, h("slot", { key: '18276aad72ef4e91c1a5d6f368729589f9b50205' })), h("slot", { key: '39e365fbd888084b54b58811a44c6ae019801d92', name: "end" }), showDetail && (h("ion-icon", { icon: detailIcon, lazy: false, class: "item-detail-icon", part: "detail-icon", "aria-hidden": "true", "flip-rtl": detailIcon === chevronForward })), h("div", { key: '96daef747b2ba84fe8206c332624a90640ecc448', class: "item-inner-highlight" })), canActivate && mode === 'md' && h("ion-ripple-effect", null), h("div", { key: 'e6d77ef9da1b7a6e530ba37e37f51aa8e1102460', class: "item-highlight" })), h("div", { key: '20223b90730b563bb38edd5f3769b2b7607d8097', class: "item-bottom" }, h("slot", { key: '4657f1f0a57ddc5e136473d98a93e91eed00ec19', name: "error" }), h("slot", { key: '37a5acffe53d3e6a472cc2fac1548362b236cad8', name: "helper" }), counterString && h("ion-note", { class: "item-counter" }, counterString))));
273
288
  }
274
289
  static get is() { return "ion-item"; }
275
290
  static get encapsulation() { return "shadow"; }
276
- static get delegatesFocus() { return true; }
277
291
  static get originalStyleUrls() {
278
292
  return {
279
293
  "ios": ["item.ios.scss"],
@@ -189,7 +189,7 @@
189
189
  background: var(--ion-color-contrast);
190
190
  }
191
191
  }
192
- :host(.item-has-interactive-control) {
192
+ :host(.item-control-needs-pointer-cursor) {
193
193
  cursor: pointer;
194
194
  }
195
195
 
@@ -872,13 +872,13 @@ ion-ripple-effect {
872
872
  }
873
873
 
874
874
  ::slotted([slot=start]) {
875
- -webkit-margin-end: 32px;
876
- margin-inline-end: 32px;
875
+ -webkit-margin-end: 16px;
876
+ margin-inline-end: 16px;
877
877
  }
878
878
 
879
879
  ::slotted([slot=end]) {
880
- -webkit-margin-start: 32px;
881
- margin-inline-start: 32px;
880
+ -webkit-margin-start: 16px;
881
+ margin-inline-start: 16px;
882
882
  }
883
883
 
884
884
  :host(.item-fill-solid) ::slotted([slot=start]),
@@ -942,16 +942,6 @@ ion-ripple-effect {
942
942
  padding-bottom: 10px;
943
943
  }
944
944
 
945
- ::slotted(ion-note[slot=start]) {
946
- -webkit-padding-end: 16px;
947
- padding-inline-end: 16px;
948
- }
949
-
950
- ::slotted(ion-note[slot=end]) {
951
- -webkit-padding-start: 16px;
952
- padding-inline-start: 16px;
953
- }
954
-
955
945
  ::slotted(ion-avatar) {
956
946
  width: 40px;
957
947
  height: 40px;
@@ -290,13 +290,13 @@
290
290
  }
291
291
 
292
292
  ::slotted([slot=start]) {
293
- -webkit-margin-end: 32px;
294
- margin-inline-end: 32px;
293
+ -webkit-margin-end: 16px;
294
+ margin-inline-end: 16px;
295
295
  }
296
296
 
297
297
  ::slotted([slot=end]) {
298
- -webkit-margin-start: 32px;
299
- margin-inline-start: 32px;
298
+ -webkit-margin-start: 16px;
299
+ margin-inline-start: 16px;
300
300
  }
301
301
 
302
302
  ::slotted(ion-label) {
@@ -346,16 +346,6 @@
346
346
  padding-bottom: 10px;
347
347
  }
348
348
 
349
- ::slotted(ion-note[slot=start]) {
350
- -webkit-padding-end: 16px;
351
- padding-inline-end: 16px;
352
- }
353
-
354
- ::slotted(ion-note[slot=end]) {
355
- -webkit-padding-start: 16px;
356
- padding-inline-start: 16px;
357
- }
358
-
359
349
  ::slotted(ion-avatar) {
360
350
  width: 40px;
361
351
  height: 40px;
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import { Build, Host, h } from "@stencil/core";
5
5
  import { getTimeGivenProgression } from "../../utils/animation/cubic-bezier";
6
+ import { focusFirstDescendant, focusLastDescendant } from "../../utils/focus-trap";
6
7
  import { GESTURE_CONTROLLER } from "../../utils/gesture/index";
7
8
  import { shoudUseCloseWatcher } from "../../utils/hardware-back-button";
8
9
  import { inheritAriaAttributes, assert, clamp, isEndSide as isEnd } from "../../utils/helpers";
@@ -15,7 +16,6 @@ const iosEasing = 'cubic-bezier(0.32,0.72,0,1)';
15
16
  const mdEasing = 'cubic-bezier(0.0,0.0,0.2,1)';
16
17
  const iosEasingReverse = 'cubic-bezier(1, 0, 0.68, 0.28)';
17
18
  const mdEasingReverse = 'cubic-bezier(0.4, 0, 0.6, 1)';
18
- const focusableQueryString = '[tabindex]:not([tabindex^="-"]), input:not([type=hidden]):not([tabindex^="-"]), textarea:not([tabindex^="-"]), button:not([tabindex^="-"]), select:not([tabindex^="-"]), .ion-focusable:not([tabindex^="-"])';
19
19
  /**
20
20
  * @part container - The container for the menu content.
21
21
  * @part backdrop - The backdrop that appears over the main content when the menu is open.
@@ -253,27 +253,6 @@ export class Menu {
253
253
  setOpen(shouldOpen, animated = true) {
254
254
  return menuController._setOpen(this, shouldOpen, animated);
255
255
  }
256
- focusFirstDescendant() {
257
- const { el } = this;
258
- const firstInput = el.querySelector(focusableQueryString);
259
- if (firstInput) {
260
- firstInput.focus();
261
- }
262
- else {
263
- el.focus();
264
- }
265
- }
266
- focusLastDescendant() {
267
- const { el } = this;
268
- const inputs = Array.from(el.querySelectorAll(focusableQueryString));
269
- const lastInput = inputs.length > 0 ? inputs[inputs.length - 1] : null;
270
- if (lastInput) {
271
- lastInput.focus();
272
- }
273
- else {
274
- el.focus();
275
- }
276
- }
277
256
  trapKeyboardFocus(ev, doc) {
278
257
  const target = ev.target;
279
258
  if (!target) {
@@ -291,13 +270,14 @@ export class Menu {
291
270
  * Otherwise, we are about to have focus go out of the menu.
292
271
  * Wrap the focus to either the first or last element.
293
272
  */
273
+ const { el } = this;
294
274
  /**
295
275
  * Once we call `focusFirstDescendant`, another focus event
296
276
  * will fire, which will cause `lastFocus` to be updated
297
277
  * before we can run the code after that. We cache the value
298
278
  * here to avoid that.
299
279
  */
300
- this.focusFirstDescendant();
280
+ focusFirstDescendant(el);
301
281
  /**
302
282
  * If the cached last focused element is the same as the now-
303
283
  * active element, that means the user was on the first element
@@ -305,7 +285,7 @@ export class Menu {
305
285
  * last descendant.
306
286
  */
307
287
  if (this.lastFocus === doc.activeElement) {
308
- this.focusLastDescendant();
288
+ focusLastDescendant(el);
309
289
  }
310
290
  }
311
291
  }
@@ -606,14 +586,14 @@ export class Menu {
606
586
  * the ionBackButton listener in the menu controller
607
587
  * will handle closing the menu when Escape is pressed.
608
588
  */
609
- return (h(Host, { key: 'c47b00136d61d7d705efadd4d2d06b87b18747a3', onKeyDown: shoudUseCloseWatcher() ? null : this.onKeydown, role: "navigation", "aria-label": inheritedAttributes['aria-label'] || 'menu', class: {
589
+ return (h(Host, { key: 'b75052668f8384e55009d5a9f436f2de590bf2c3', onKeyDown: shoudUseCloseWatcher() ? null : this.onKeydown, role: "navigation", "aria-label": inheritedAttributes['aria-label'] || 'menu', class: {
610
590
  [mode]: true,
611
591
  [`menu-type-${type}`]: true,
612
592
  'menu-enabled': !disabled,
613
593
  [`menu-side-${side}`]: true,
614
594
  'menu-pane-visible': isPaneVisible,
615
595
  'split-pane-side': hostContext('ion-split-pane', el),
616
- } }, h("div", { key: '829d5332be865b5aab6435e6a7c8872c7fb89b52', class: "menu-inner", part: "container", ref: (el) => (this.menuInnerEl = el) }, h("slot", { key: '5b47ee5da8238ec15d7371606cfbc3d384588ebb' })), h("ion-backdrop", { key: '58bc53f971865fd1615f267cd0259584b3045486', ref: (el) => (this.backdropEl = el), class: "menu-backdrop", tappable: false, stopPropagation: false, part: "backdrop" })));
596
+ } }, h("div", { key: 'd500486fe03917b9115fa399921d73f95602d14e', class: "menu-inner", part: "container", ref: (el) => (this.menuInnerEl = el) }, h("slot", { key: '2078b5b36210658681980be69b8dc791e0b7dd96' })), h("ion-backdrop", { key: 'c43171d0f0804c0430b319de54e80c38d1768c80', ref: (el) => (this.backdropEl = el), class: "menu-backdrop", tappable: false, stopPropagation: false, part: "backdrop" })));
617
597
  }
618
598
  static get is() { return "ion-menu"; }
619
599
  static get encapsulation() { return "shadow"; }
@@ -131,9 +131,41 @@ export class Modal {
131
131
  this.triggerController.removeClickListener();
132
132
  }
133
133
  componentWillLoad() {
134
- const { breakpoints, initialBreakpoint, el } = this;
134
+ const { breakpoints, initialBreakpoint, el, htmlAttributes } = this;
135
135
  const isSheetModal = (this.isSheetModal = breakpoints !== undefined && initialBreakpoint !== undefined);
136
- this.inheritedAttributes = inheritAttributes(el, ['aria-label', 'role']);
136
+ const attributesToInherit = ['aria-label', 'role'];
137
+ this.inheritedAttributes = inheritAttributes(el, attributesToInherit);
138
+ /**
139
+ * When using a controller modal you can set attributes
140
+ * using the htmlAttributes property. Since the above attributes
141
+ * need to be inherited inside of the modal, we need to look
142
+ * and see if these attributes are being set via htmlAttributes.
143
+ *
144
+ * We could alternatively move this to componentDidLoad to simplify the work
145
+ * here, but we'd then need to make inheritedAttributes a State variable,
146
+ * thus causing another render to always happen after the first render.
147
+ */
148
+ if (htmlAttributes !== undefined) {
149
+ attributesToInherit.forEach((attribute) => {
150
+ const attributeValue = htmlAttributes[attribute];
151
+ if (attributeValue) {
152
+ /**
153
+ * If an attribute we need to inherit was
154
+ * set using htmlAttributes then add it to
155
+ * inheritedAttributes and remove it from htmlAttributes.
156
+ * This ensures the attribute is inherited and not
157
+ * set on the host.
158
+ *
159
+ * In this case, if an inherited attribute is set
160
+ * on the host element and using htmlAttributes then
161
+ * htmlAttributes wins, but that's not a pattern that we recommend.
162
+ * The only time you'd need htmlAttributes is when using modalController.
163
+ */
164
+ this.inheritedAttributes = Object.assign(Object.assign({}, this.inheritedAttributes), { [attribute]: htmlAttributes[attribute] });
165
+ delete htmlAttributes[attribute];
166
+ }
167
+ });
168
+ }
137
169
  if (isSheetModal) {
138
170
  this.currentBreakpoint = this.initialBreakpoint;
139
171
  }
@@ -530,9 +562,9 @@ export class Modal {
530
562
  const mode = getIonMode(this);
531
563
  const isCardModal = presentingElement !== undefined && mode === 'ios';
532
564
  const isHandleCycle = handleBehavior === 'cycle';
533
- return (h(Host, Object.assign({ key: 'da1f96dae9c305c473dd3813d241b3cd5c3e8cea', "no-router": true, tabindex: "-1" }, htmlAttributes, { style: {
565
+ return (h(Host, Object.assign({ key: 'dbd61751e4964ad81fc1dee19468b716d4f23c8a', "no-router": true, tabindex: "-1" }, htmlAttributes, { style: {
534
566
  zIndex: `${20000 + this.overlayIndex}`,
535
- }, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, 'overlay-hidden': true }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle }), h("ion-backdrop", { key: 'a95b63273f1bf68e79d5aa23dc78ccf67449129e', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { class: "modal-shadow" }), h("div", Object.assign({ key: 'e425881c2027374cff0eb0583cdb3e66a8d3be7d',
567
+ }, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, 'overlay-hidden': true }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle }), h("ion-backdrop", { key: 'a7646a7a7aeef7eef1bb647373f509d4a26036ad', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { class: "modal-shadow" }), h("div", Object.assign({ key: 'bc6bc6ff7d2357206265240eaa76d730a0ecfd2c',
536
568
  /*
537
569
  role and aria-modal must be used on the
538
570
  same element. They must also be set inside the
@@ -541,7 +573,7 @@ export class Modal {
541
573
  */
542
574
  role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { class: "modal-handle",
543
575
  // Prevents the handle from receiving keyboard focus when it does not cycle
544
- tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle" })), h("slot", { key: '24c18af1e34b72a0dc05b80b6fc58017ab695acf' }))));
576
+ tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle" })), h("slot", { key: '0ce06b895deb1da5fbdefa65b079dbd1ada349f7' }))));
545
577
  }
546
578
  static get is() { return "ion-modal"; }
547
579
  static get encapsulation() { return "shadow"; }
@@ -0,0 +1,32 @@
1
+ /*!
2
+ * (C) Ionic http://ionicframework.com - MIT License
3
+ */
4
+ import { h } from "@stencil/core";
5
+ import { newSpecPage } from "@stencil/core/testing";
6
+ import { Modal } from "../modal";
7
+ it('should inherit attributes', async () => {
8
+ /**
9
+ * Note: This example should not be used in production.
10
+ * This only serves to check that `role` can be customized.
11
+ */
12
+ const page = await newSpecPage({
13
+ components: [Modal],
14
+ template: () => h("ion-modal", { overlayIndex: 1, "aria-label": "my label", role: "presentation" }),
15
+ });
16
+ const modal = page.body.querySelector('ion-modal');
17
+ const contentWrapper = modal.shadowRoot.querySelector('[part="content"]');
18
+ expect(contentWrapper.getAttribute('aria-label')).toBe('my label');
19
+ expect(contentWrapper.getAttribute('role')).toBe('presentation');
20
+ });
21
+ it('should inherit attributes when set via htmlAttributes', async () => {
22
+ const page = await newSpecPage({
23
+ components: [Modal],
24
+ template: () => (h("ion-modal", { overlayIndex: 1, htmlAttributes: { 'aria-label': 'my label', role: 'presentation' } })),
25
+ });
26
+ const modal = page.body.querySelector('ion-modal');
27
+ const contentWrapper = modal.shadowRoot.querySelector('[part="content"]');
28
+ expect(contentWrapper.getAttribute('aria-label')).toBe('my label');
29
+ expect(contentWrapper.getAttribute('role')).toBe('presentation');
30
+ expect(modal.hasAttribute('aria-label')).toBe(false);
31
+ expect(modal.hasAttribute('role')).toBe(false);
32
+ });
@@ -267,6 +267,13 @@ export class PickerColumn {
267
267
  * height of 0px.
268
268
  */
269
269
  componentWillLoad() {
270
+ /**
271
+ * We cache parentEl in a local variable
272
+ * so we don't need to keep accessing
273
+ * the class variable (which comes with
274
+ * a small performance hit)
275
+ */
276
+ const parentEl = (this.parentEl = this.el.closest('ion-picker'));
270
277
  const visibleCallback = (entries) => {
271
278
  const ev = entries[0];
272
279
  if (ev.isIntersecting) {
@@ -294,8 +301,16 @@ export class PickerColumn {
294
301
  }
295
302
  }
296
303
  };
297
- new IntersectionObserver(visibleCallback, { threshold: 0.001 }).observe(this.el);
298
- const parentEl = (this.parentEl = this.el.closest('ion-picker'));
304
+ /**
305
+ * Set the root to be the parent picker element
306
+ * This causes the IO callback
307
+ * to be fired in WebKit as soon as the element
308
+ * is visible. If we used the default root value
309
+ * then WebKit would only fire the IO callback
310
+ * after any animations (such as a modal transition)
311
+ * finished, and there would potentially be a flicker.
312
+ */
313
+ new IntersectionObserver(visibleCallback, { threshold: 0.001, root: this.parentEl }).observe(this.el);
299
314
  if (parentEl !== null) {
300
315
  // TODO(FW-2832): type
301
316
  parentEl.addEventListener('ionInputModeChange', (ev) => this.inputModeChange(ev));
@@ -364,14 +379,14 @@ export class PickerColumn {
364
379
  render() {
365
380
  const { color, disabled, isActive, numericInput } = this;
366
381
  const mode = getIonMode(this);
367
- return (h(Host, { key: '22dcc8dc9bc8c6035cba9f8825f231797464c652', class: createColorClasses(color, {
382
+ return (h(Host, { key: '0b055a464237262bab4d99b2de320c9ea1312f29', class: createColorClasses(color, {
368
383
  [mode]: true,
369
384
  ['picker-column-active']: isActive,
370
385
  ['picker-column-numeric-input']: numericInput,
371
386
  ['picker-column-disabled']: disabled,
372
- }) }, h("slot", { key: 'e93c2d8ea862e2d84ae9338ad2cbec0eea2230f8', name: "prefix" }), h("div", { key: 'a981c29b3cd9456b7f2523d1daa4d1797d389f03', class: "picker-opts", tabindex: disabled ? undefined : 0, ref: (el) => {
387
+ }) }, h("slot", { key: 'a162598e503c1f4eef59dbadaa5ecc11dc45d82c', name: "prefix" }), h("div", { key: '23f0370a1639adcdacde40fc59ced3cd49fc8e91', class: "picker-opts", tabindex: disabled ? undefined : 0, ref: (el) => {
373
388
  this.scrollEl = el;
374
- } }, h("div", { key: 'd80da940ecb2d8cea236ef9c74da1871a7ab6248', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: '2b05ef9d4116ca7940c3b61454517c02ee40bf9e', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: 'a557a7fb595d3bec5e0bd76b10f73cdc93b17bff', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("slot", { key: '4934b827a0b11dfcb2cb9a49740076609ab86f59' }), h("div", { key: 'f89592da27eb54e88e9a977aa4ecd9dc4d8e211d', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: '87c0cf79ce3b88c2328256ee6895612327653009', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: '24e96271c3e7468cc3cc5a6f3e384740c4fd9988', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0")), h("slot", { key: '2ed210e571787a88c06d7538cb7082875e85fb28', name: "suffix" })));
389
+ } }, h("div", { key: '9b86b9b11a53f06b3afea9b76ecca9344e025bc4', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: 'c95a1998f3d4c13ca60b81f0de01f1f5811d86df', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: '04381e68d992a247a38942aea307d1f863876eb5', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("slot", { key: '379fda12a9e49c5616e590deb9ddaea908fbed9b' }), h("div", { key: 'c911bf19f4bb531d1ca46d1b3f9d6286d0ac3801', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: '9dc907617ad53c1542d492ab1d60c986dd869348', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0"), h("div", { key: '219691c9c450dd1eecaf1304eac5870dad1d76e8', class: "picker-item-empty", "aria-hidden": "true" }, "\u00A0")), h("slot", { key: '8471ea689166cd864ad0fcdb959b7a9db15dfb8d', name: "suffix" })));
375
390
  }
376
391
  static get is() { return "ion-picker-column"; }
377
392
  static get encapsulation() { return "shadow"; }
@@ -2,11 +2,12 @@
2
2
  * (C) Ionic http://ionicframework.com - MIT License
3
3
  */
4
4
  import { Host, h } from "@stencil/core";
5
+ import { focusFirstDescendant } from "../../utils/focus-trap";
5
6
  import { CoreDelegate, attachComponent, detachComponent } from "../../utils/framework-delegate";
6
7
  import { addEventListener, raf, hasLazyBuild } from "../../utils/helpers";
7
8
  import { createLockController } from "../../utils/lock-controller";
8
9
  import { printIonWarning } from "../../utils/logging/index";
9
- import { BACKDROP, dismiss, eventMethod, focusFirstDescendant, prepareOverlay, present, setOverlayId, } from "../../utils/overlays";
10
+ import { BACKDROP, dismiss, eventMethod, prepareOverlay, present, setOverlayId } from "../../utils/overlays";
10
11
  import { isPlatform } from "../../utils/platform";
11
12
  import { getClassMap } from "../../utils/theme";
12
13
  import { deepReady, waitForMount } from "../../utils/transition/index";
@@ -269,7 +270,7 @@ export class Popover {
269
270
  * descendant inside of the popover.
270
271
  */
271
272
  if (this.focusDescendantOnPresent) {
272
- focusFirstDescendant(this.el, this.el);
273
+ focusFirstDescendant(el);
273
274
  }
274
275
  unlock();
275
276
  }
@@ -335,9 +336,9 @@ export class Popover {
335
336
  const { onLifecycle, parentPopover, dismissOnSelect, side, arrow, htmlAttributes } = this;
336
337
  const desktop = isPlatform('desktop');
337
338
  const enableArrow = arrow && !parentPopover;
338
- return (h(Host, Object.assign({ key: '71557e45cb839792d51f44786a3e8c1f92fd070c', "aria-modal": "true", "no-router": true, tabindex: "-1" }, htmlAttributes, { style: {
339
+ return (h(Host, Object.assign({ key: 'a4a6fb333562cb2ecc2ac2350541de9be61837af', "aria-modal": "true", "no-router": true, tabindex: "-1" }, htmlAttributes, { style: {
339
340
  zIndex: `${20000 + this.overlayIndex}`,
340
- }, class: Object.assign(Object.assign({}, getClassMap(this.cssClass)), { [mode]: true, 'popover-translucent': this.translucent, 'overlay-hidden': true, 'popover-desktop': desktop, [`popover-side-${side}`]: true, 'popover-nested': !!parentPopover }), onIonPopoverDidPresent: onLifecycle, onIonPopoverWillPresent: onLifecycle, onIonPopoverWillDismiss: onLifecycle, onIonPopoverDidDismiss: onLifecycle, onIonBackdropTap: this.onBackdropTap }), !parentPopover && h("ion-backdrop", { tappable: this.backdropDismiss, visible: this.showBackdrop, part: "backdrop" }), h("div", { key: '6b829c9938f208c55fe2ac749875e7acc3b95b93', class: "popover-wrapper ion-overlay-wrapper", onClick: dismissOnSelect ? () => this.dismiss() : undefined }, enableArrow && h("div", { class: "popover-arrow", part: "arrow" }), h("div", { key: '29f3706a787a4eae20b12c9589272f0b8026d0b2', class: "popover-content", part: "content" }, h("slot", { key: '51c20057566904cbfe4cc5e199180bd144b65ca6' })))));
341
+ }, class: Object.assign(Object.assign({}, getClassMap(this.cssClass)), { [mode]: true, 'popover-translucent': this.translucent, 'overlay-hidden': true, 'popover-desktop': desktop, [`popover-side-${side}`]: true, 'popover-nested': !!parentPopover }), onIonPopoverDidPresent: onLifecycle, onIonPopoverWillPresent: onLifecycle, onIonPopoverWillDismiss: onLifecycle, onIonPopoverDidDismiss: onLifecycle, onIonBackdropTap: this.onBackdropTap }), !parentPopover && h("ion-backdrop", { tappable: this.backdropDismiss, visible: this.showBackdrop, part: "backdrop" }), h("div", { key: 'de9c7ad73f221e6e9a55e2bc7e1ffad7b936b0dd', class: "popover-wrapper ion-overlay-wrapper", onClick: dismissOnSelect ? () => this.dismiss() : undefined }, enableArrow && h("div", { class: "popover-arrow", part: "arrow" }), h("div", { key: '1cb5abc9835c044e6d14d444283f34b65b0b134e', class: "popover-content", part: "content" }, h("slot", { key: '0e4db95e6341e823f87877325bb1164193ae6676' })))));
341
342
  }
342
343
  static get is() { return "ion-popover"; }
343
344
  static get encapsulation() { return "shadow"; }
@@ -41,3 +41,24 @@ configs().forEach(({ title, screenshot, config }) => {
41
41
  });
42
42
  });
43
43
  });
44
+ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
45
+ test.describe(title('textarea: item functionality'), () => {
46
+ test('clicking padded space within item should focus the textarea', async ({ page }) => {
47
+ await page.setContent(`
48
+ <ion-item>
49
+ <ion-textarea label="Textarea"></ion-textarea>
50
+ </ion-item>
51
+ `, config);
52
+ const itemNative = page.locator('.item-native');
53
+ const textarea = page.locator('ion-textarea textarea');
54
+ // Clicks the padded space within the item
55
+ await itemNative.click({
56
+ position: {
57
+ x: 5,
58
+ y: 5,
59
+ },
60
+ });
61
+ await expect(textarea).toBeFocused();
62
+ });
63
+ });
64
+ });
@@ -0,0 +1,78 @@
1
+ /*!
2
+ * (C) Ionic http://ionicframework.com - MIT License
3
+ */
4
+ import { focusVisibleElement } from "./helpers";
5
+ /**
6
+ * This query string selects elements that
7
+ * are eligible to receive focus. We select
8
+ * interactive elements that meet the following
9
+ * criteria:
10
+ * 1. Element does not have a negative tabindex
11
+ * 2. Element does not have `hidden`
12
+ * 3. Element does not have `disabled` for non-Ionic components.
13
+ * 4. Element does not have `disabled` or `disabled="true"` for Ionic components.
14
+ * Note: We need this distinction because `disabled="false"` is
15
+ * valid usage for the disabled property on ion-button.
16
+ */
17
+ export const focusableQueryString = '[tabindex]:not([tabindex^="-"]):not([hidden]):not([disabled]), input:not([type=hidden]):not([tabindex^="-"]):not([hidden]):not([disabled]), textarea:not([tabindex^="-"]):not([hidden]):not([disabled]), button:not([tabindex^="-"]):not([hidden]):not([disabled]), select:not([tabindex^="-"]):not([hidden]):not([disabled]), .ion-focusable:not([tabindex^="-"]):not([hidden]):not([disabled]), .ion-focusable[disabled="false"]:not([tabindex^="-"]):not([hidden])';
18
+ /**
19
+ * Focuses the first descendant in a context
20
+ * that can receive focus. If none exists,
21
+ * a fallback element will be focused.
22
+ * This fallback is typically an ancestor
23
+ * container such as a menu or overlay so focus does not
24
+ * leave the container we are trying to trap focus in.
25
+ *
26
+ * If no fallback is specified then we focus the container itself.
27
+ */
28
+ export const focusFirstDescendant = (ref, fallbackElement) => {
29
+ const firstInput = ref.querySelector(focusableQueryString);
30
+ focusElementInContext(firstInput, fallbackElement !== null && fallbackElement !== void 0 ? fallbackElement : ref);
31
+ };
32
+ /**
33
+ * Focuses the last descendant in a context
34
+ * that can receive focus. If none exists,
35
+ * a fallback element will be focused.
36
+ * This fallback is typically an ancestor
37
+ * container such as a menu or overlay so focus does not
38
+ * leave the container we are trying to trap focus in.
39
+ *
40
+ * If no fallback is specified then we focus the container itself.
41
+ */
42
+ export const focusLastDescendant = (ref, fallbackElement) => {
43
+ const inputs = Array.from(ref.querySelectorAll(focusableQueryString));
44
+ const lastInput = inputs.length > 0 ? inputs[inputs.length - 1] : null;
45
+ focusElementInContext(lastInput, fallbackElement !== null && fallbackElement !== void 0 ? fallbackElement : ref);
46
+ };
47
+ /**
48
+ * Focuses a particular element in a context. If the element
49
+ * doesn't have anything focusable associated with it then
50
+ * a fallback element will be focused.
51
+ *
52
+ * This fallback is typically an ancestor
53
+ * container such as a menu or overlay so focus does not
54
+ * leave the container we are trying to trap focus in.
55
+ * This should be used instead of the focus() method
56
+ * on most elements because the focusable element
57
+ * may not be the host element.
58
+ *
59
+ * For example, if an ion-button should be focused
60
+ * then we should actually focus the native <button>
61
+ * element inside of ion-button's shadow root, not
62
+ * the host element itself.
63
+ */
64
+ const focusElementInContext = (hostToFocus, fallbackElement) => {
65
+ let elementToFocus = hostToFocus;
66
+ const shadowRoot = hostToFocus === null || hostToFocus === void 0 ? void 0 : hostToFocus.shadowRoot;
67
+ if (shadowRoot) {
68
+ // If there are no inner focusable elements, just focus the host element.
69
+ elementToFocus = shadowRoot.querySelector(focusableQueryString) || hostToFocus;
70
+ }
71
+ if (elementToFocus) {
72
+ focusVisibleElement(elementToFocus);
73
+ }
74
+ else {
75
+ // Focus fallback element instead of letting focus escape
76
+ fallbackElement.focus();
77
+ }
78
+ };
@@ -29,7 +29,14 @@ export const startInputShims = async (config, platform) => {
29
29
  const keyboardHeight = config.getNumber('keyboardHeight', 290);
30
30
  const scrollAssist = config.getBoolean('scrollAssist', true);
31
31
  const hideCaret = config.getBoolean('hideCaretOnScroll', isIOS);
32
- const inputBlurring = config.getBoolean('inputBlurring', isIOS);
32
+ /**
33
+ * The team is evaluating if inputBlurring is still needed. As a result
34
+ * this feature is disabled by default as of Ionic 8.0. Developers are
35
+ * able to re-enable it temporarily. The team may remove this utility
36
+ * if it is determined that doing so would not bring any adverse side effects.
37
+ * TODO FW-6014 remove input blurring utility (including implementation)
38
+ */
39
+ const inputBlurring = config.getBoolean('inputBlurring', false);
33
40
  const scrollPadding = config.getBoolean('scrollPadding', true);
34
41
  const inputs = Array.from(doc.querySelectorAll('ion-input, ion-textarea'));
35
42
  const hideCaretMap = new WeakMap();