voyager-ionic-core 7.6.0 → 7.6.3

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 (399) hide show
  1. package/components/data.js +64 -14
  2. package/components/icon.js +15 -3
  3. package/components/index7.js +1 -1
  4. package/components/ion-datetime.js +23 -4
  5. package/components/ion-input.js +23 -4
  6. package/components/ion-menu.js +2 -2
  7. package/components/ion-refresher-content.js +10 -3
  8. package/components/ion-refresher.js +4 -183
  9. package/components/ion-select.js +2 -2
  10. package/components/ion-split-pane.js +2 -2
  11. package/components/ion-textarea.js +27 -4
  12. package/components/item.js +2 -2
  13. package/components/radio-group.js +9 -1
  14. package/components/refresher.utils.js +196 -0
  15. package/css/core.css +0 -8
  16. package/css/core.css.map +1 -1
  17. package/css/ionic.bundle.css +1 -1
  18. package/css/ionic.bundle.css.map +1 -1
  19. package/dist/cjs/{app-globals-0af482c7.js → app-globals-7def22c8.js} +1 -1
  20. package/dist/cjs/{button-active-a5185907.js → button-active-962fe442.js} +1 -1
  21. package/dist/cjs/{data-36b9094e.js → data-a5109f09.js} +64 -14
  22. package/dist/cjs/{index-f8f13389.js → index-17ab7794.js} +3 -3
  23. package/dist/cjs/{index-ce101dc9.js → index-3b012034.js} +1 -1
  24. package/dist/cjs/{index-bbb4336c.js → index-50dcfe2f.js} +21 -8
  25. package/dist/cjs/{index-09471526.js → index-f52c6d38.js} +1 -1
  26. package/dist/cjs/index.cjs.js +7 -7
  27. package/dist/cjs/ion-accordion_2.cjs.entry.js +3 -3
  28. package/dist/cjs/ion-action-sheet.cjs.entry.js +4 -4
  29. package/dist/cjs/ion-alert.cjs.entry.js +4 -4
  30. package/dist/cjs/ion-app_8.cjs.entry.js +4 -4
  31. package/dist/cjs/ion-avatar_3.cjs.entry.js +2 -2
  32. package/dist/cjs/ion-back-button.cjs.entry.js +3 -3
  33. package/dist/cjs/ion-backdrop.cjs.entry.js +2 -2
  34. package/dist/cjs/ion-breadcrumb_2.cjs.entry.js +3 -3
  35. package/dist/cjs/ion-button_2.cjs.entry.js +17 -5
  36. package/dist/cjs/ion-card_5.cjs.entry.js +2 -2
  37. package/dist/cjs/ion-checkbox.cjs.entry.js +2 -2
  38. package/dist/cjs/ion-chip.cjs.entry.js +2 -2
  39. package/dist/cjs/ion-col_3.cjs.entry.js +2 -2
  40. package/dist/cjs/ion-datetime-button.cjs.entry.js +3 -3
  41. package/dist/cjs/ion-datetime_3.cjs.entry.js +28 -9
  42. package/dist/cjs/ion-fab_3.cjs.entry.js +3 -3
  43. package/dist/cjs/ion-img.cjs.entry.js +2 -2
  44. package/dist/cjs/ion-infinite-scroll_2.cjs.entry.js +2 -2
  45. package/dist/cjs/ion-input.cjs.entry.js +26 -7
  46. package/dist/cjs/ion-item-option_3.cjs.entry.js +2 -2
  47. package/dist/cjs/ion-item_8.cjs.entry.js +5 -5
  48. package/dist/cjs/ion-loading.cjs.entry.js +3 -3
  49. package/dist/cjs/ion-menu_3.cjs.entry.js +7 -7
  50. package/dist/cjs/ion-modal.cjs.entry.js +4 -4
  51. package/dist/cjs/ion-nav_2.cjs.entry.js +3 -3
  52. package/dist/cjs/ion-picker-column-internal.cjs.entry.js +2 -2
  53. package/dist/cjs/ion-picker-internal.cjs.entry.js +1 -1
  54. package/dist/cjs/ion-popover.cjs.entry.js +4 -4
  55. package/dist/cjs/ion-progress-bar.cjs.entry.js +2 -2
  56. package/dist/cjs/ion-radio_2.cjs.entry.js +11 -3
  57. package/dist/cjs/ion-range.cjs.entry.js +2 -2
  58. package/dist/cjs/ion-refresher_2.cjs.entry.js +30 -15
  59. package/dist/cjs/ion-reorder_2.cjs.entry.js +3 -3
  60. package/dist/cjs/ion-ripple-effect.cjs.entry.js +2 -2
  61. package/dist/cjs/ion-route_4.cjs.entry.js +2 -2
  62. package/dist/cjs/ion-searchbar.cjs.entry.js +3 -3
  63. package/dist/cjs/ion-segment_2.cjs.entry.js +2 -2
  64. package/dist/cjs/ion-select_3.cjs.entry.js +6 -6
  65. package/dist/cjs/ion-spinner.cjs.entry.js +2 -2
  66. package/dist/cjs/ion-split-pane.cjs.entry.js +4 -4
  67. package/dist/cjs/ion-tab-bar_2.cjs.entry.js +2 -2
  68. package/dist/cjs/ion-tab_2.cjs.entry.js +1 -1
  69. package/dist/cjs/ion-text.cjs.entry.js +2 -2
  70. package/dist/cjs/ion-textarea.cjs.entry.js +29 -6
  71. package/dist/cjs/ion-toast.cjs.entry.js +3 -3
  72. package/dist/cjs/ion-toggle.cjs.entry.js +3 -3
  73. package/dist/cjs/{ionic-global-f4a2093b.js → ionic-global-a4edbf03.js} +1 -1
  74. package/dist/cjs/ionic.cjs.js +4 -4
  75. package/dist/cjs/{ios.transition-6787b799.js → ios.transition-b5353f3e.js} +2 -2
  76. package/dist/cjs/loader.cjs.js +3 -3
  77. package/dist/cjs/{md.transition-e033d20a.js → md.transition-67157dd9.js} +2 -2
  78. package/dist/cjs/{overlays-27a6fb16.js → overlays-e77cc023.js} +1 -1
  79. package/dist/cjs/{status-tap-415acac6.js → status-tap-b5d77c08.js} +1 -1
  80. package/dist/collection/collection-manifest.json +1 -1
  81. package/dist/collection/components/datetime/datetime.ios.css +3 -1
  82. package/dist/collection/components/datetime/datetime.js +23 -4
  83. package/dist/collection/components/datetime/test/basic/datetime.e2e.js +29 -0
  84. package/dist/collection/components/datetime/test/manipulation.spec.js +133 -1
  85. package/dist/collection/components/datetime/test/prefer-wheel/datetime.spec.js +27 -0
  86. package/dist/collection/components/datetime/utils/manipulation.js +65 -15
  87. package/dist/collection/components/input/input.ios.css +20 -0
  88. package/dist/collection/components/input/input.js +22 -3
  89. package/dist/collection/components/input/input.md.css +21 -0
  90. package/dist/collection/components/input/test/clear-on-edit/input.e2e.js +28 -8
  91. package/dist/collection/components/input/test/slot/input.e2e.js +6 -2
  92. package/dist/collection/components/item/item.ios.css +6 -0
  93. package/dist/collection/components/item/item.md.css +6 -0
  94. package/dist/collection/components/label/test/a11y/label.e2e.js +25 -0
  95. package/dist/collection/components/menu/menu.ios.css +3 -4
  96. package/dist/collection/components/menu/menu.md.css +3 -4
  97. package/dist/collection/components/menu/test/custom/menu.e2e.js +61 -0
  98. package/dist/collection/components/modal/modal.js +1 -1
  99. package/dist/collection/components/radio/test/a11y/radio.e2e.js +15 -1
  100. package/dist/collection/components/radio/test/legacy/a11y/radio.e2e.js +15 -2
  101. package/dist/collection/components/radio-group/radio-group.js +9 -1
  102. package/dist/collection/components/range/range.js +1 -1
  103. package/dist/collection/components/refresher/refresher.js +3 -0
  104. package/dist/collection/components/refresher/refresher.utils.js +19 -11
  105. package/dist/collection/components/refresher-content/refresher-content.js +9 -3
  106. package/dist/collection/components/select/select.ios.css +20 -0
  107. package/dist/collection/components/select/select.md.css +21 -0
  108. package/dist/collection/components/select/test/slot/select.e2e.js +6 -2
  109. package/dist/collection/components/split-pane/split-pane.ios.css +10 -2
  110. package/dist/collection/components/split-pane/split-pane.md.css +10 -2
  111. package/dist/collection/components/textarea/test/clear-on-edit/textarea.e2e.js +36 -0
  112. package/dist/collection/components/textarea/test/slot/textarea.e2e.js +6 -2
  113. package/dist/collection/components/textarea/textarea.ios.css +20 -0
  114. package/dist/collection/components/textarea/textarea.js +26 -3
  115. package/dist/collection/components/textarea/textarea.md.css +21 -0
  116. package/dist/docs.json +34 -8
  117. package/dist/esm/{app-globals-722340c4.js → app-globals-8c62bec2.js} +1 -1
  118. package/dist/esm/{button-active-c6ee4f50.js → button-active-308d3edd.js} +1 -1
  119. package/dist/esm/{data-f5c75b4e.js → data-775093f5.js} +64 -14
  120. package/dist/esm/{index-0c12c22b.js → index-1193f005.js} +1 -1
  121. package/dist/esm/{index-1932b201.js → index-4743453d.js} +3 -3
  122. package/dist/esm/{index-08d686eb.js → index-b7d870cf.js} +21 -8
  123. package/dist/esm/{index-c132c5f1.js → index-f7dc70ba.js} +1 -1
  124. package/dist/esm/index.js +7 -7
  125. package/dist/esm/ion-accordion_2.entry.js +3 -3
  126. package/dist/esm/ion-action-sheet.entry.js +4 -4
  127. package/dist/esm/ion-alert.entry.js +4 -4
  128. package/dist/esm/ion-app_8.entry.js +4 -4
  129. package/dist/esm/ion-avatar_3.entry.js +2 -2
  130. package/dist/esm/ion-back-button.entry.js +3 -3
  131. package/dist/esm/ion-backdrop.entry.js +2 -2
  132. package/dist/esm/ion-breadcrumb_2.entry.js +3 -3
  133. package/dist/esm/ion-button_2.entry.js +17 -5
  134. package/dist/esm/ion-card_5.entry.js +2 -2
  135. package/dist/esm/ion-checkbox.entry.js +2 -2
  136. package/dist/esm/ion-chip.entry.js +2 -2
  137. package/dist/esm/ion-col_3.entry.js +2 -2
  138. package/dist/esm/ion-datetime-button.entry.js +3 -3
  139. package/dist/esm/ion-datetime_3.entry.js +28 -9
  140. package/dist/esm/ion-fab_3.entry.js +3 -3
  141. package/dist/esm/ion-img.entry.js +2 -2
  142. package/dist/esm/ion-infinite-scroll_2.entry.js +2 -2
  143. package/dist/esm/ion-input.entry.js +26 -7
  144. package/dist/esm/ion-item-option_3.entry.js +2 -2
  145. package/dist/esm/ion-item_8.entry.js +5 -5
  146. package/dist/esm/ion-loading.entry.js +3 -3
  147. package/dist/esm/ion-menu_3.entry.js +7 -7
  148. package/dist/esm/ion-modal.entry.js +4 -4
  149. package/dist/esm/ion-nav_2.entry.js +3 -3
  150. package/dist/esm/ion-picker-column-internal.entry.js +2 -2
  151. package/dist/esm/ion-picker-internal.entry.js +1 -1
  152. package/dist/esm/ion-popover.entry.js +4 -4
  153. package/dist/esm/ion-progress-bar.entry.js +2 -2
  154. package/dist/esm/ion-radio_2.entry.js +11 -3
  155. package/dist/esm/ion-range.entry.js +2 -2
  156. package/dist/esm/ion-refresher_2.entry.js +30 -15
  157. package/dist/esm/ion-reorder_2.entry.js +3 -3
  158. package/dist/esm/ion-ripple-effect.entry.js +2 -2
  159. package/dist/esm/ion-route_4.entry.js +2 -2
  160. package/dist/esm/ion-searchbar.entry.js +3 -3
  161. package/dist/esm/ion-segment_2.entry.js +2 -2
  162. package/dist/esm/ion-select_3.entry.js +6 -6
  163. package/dist/esm/ion-spinner.entry.js +2 -2
  164. package/dist/esm/ion-split-pane.entry.js +4 -4
  165. package/dist/esm/ion-tab-bar_2.entry.js +2 -2
  166. package/dist/esm/ion-tab_2.entry.js +1 -1
  167. package/dist/esm/ion-text.entry.js +2 -2
  168. package/dist/esm/ion-textarea.entry.js +29 -6
  169. package/dist/esm/ion-toast.entry.js +3 -3
  170. package/dist/esm/ion-toggle.entry.js +3 -3
  171. package/dist/esm/{ionic-global-c0cda98e.js → ionic-global-1f99b929.js} +1 -1
  172. package/dist/esm/ionic.js +5 -5
  173. package/dist/esm/{ios.transition-802a84a6.js → ios.transition-3376ccb2.js} +2 -2
  174. package/dist/esm/loader.js +4 -4
  175. package/dist/esm/{md.transition-43c2874d.js → md.transition-f992779f.js} +2 -2
  176. package/dist/esm/{overlays-32ef481d.js → overlays-b33f6bca.js} +1 -1
  177. package/dist/esm/{status-tap-2b93b1b5.js → status-tap-16fd8f3d.js} +1 -1
  178. package/dist/esm-es5/app-globals-8c62bec2.js +4 -0
  179. package/dist/esm-es5/{button-active-c6ee4f50.js → button-active-308d3edd.js} +1 -1
  180. package/dist/esm-es5/data-775093f5.js +4 -0
  181. package/dist/esm-es5/{index-0c12c22b.js → index-1193f005.js} +1 -1
  182. package/dist/esm-es5/{index-1932b201.js → index-4743453d.js} +1 -1
  183. package/dist/esm-es5/index-b7d870cf.js +5 -0
  184. package/dist/esm-es5/index.js +1 -1
  185. package/dist/esm-es5/ion-accordion_2.entry.js +1 -1
  186. package/dist/esm-es5/ion-action-sheet.entry.js +1 -1
  187. package/dist/esm-es5/ion-alert.entry.js +1 -1
  188. package/dist/esm-es5/ion-app_8.entry.js +1 -1
  189. package/dist/esm-es5/ion-avatar_3.entry.js +1 -1
  190. package/dist/esm-es5/ion-back-button.entry.js +1 -1
  191. package/dist/esm-es5/ion-backdrop.entry.js +1 -1
  192. package/dist/esm-es5/ion-breadcrumb_2.entry.js +1 -1
  193. package/dist/esm-es5/ion-button_2.entry.js +1 -1
  194. package/dist/esm-es5/ion-card_5.entry.js +1 -1
  195. package/dist/esm-es5/ion-checkbox.entry.js +1 -1
  196. package/dist/esm-es5/ion-chip.entry.js +1 -1
  197. package/dist/esm-es5/ion-col_3.entry.js +1 -1
  198. package/dist/esm-es5/ion-datetime-button.entry.js +1 -1
  199. package/dist/esm-es5/ion-datetime_3.entry.js +1 -1
  200. package/dist/esm-es5/ion-fab_3.entry.js +1 -1
  201. package/dist/esm-es5/ion-img.entry.js +1 -1
  202. package/dist/esm-es5/ion-infinite-scroll_2.entry.js +1 -1
  203. package/dist/esm-es5/ion-input.entry.js +1 -1
  204. package/dist/esm-es5/ion-item-option_3.entry.js +1 -1
  205. package/dist/esm-es5/ion-item_8.entry.js +1 -1
  206. package/dist/esm-es5/ion-loading.entry.js +1 -1
  207. package/dist/esm-es5/ion-menu_3.entry.js +1 -1
  208. package/dist/esm-es5/ion-modal.entry.js +1 -1
  209. package/dist/esm-es5/ion-nav_2.entry.js +1 -1
  210. package/dist/esm-es5/ion-picker-column-internal.entry.js +1 -1
  211. package/dist/esm-es5/ion-picker-internal.entry.js +1 -1
  212. package/dist/esm-es5/ion-popover.entry.js +1 -1
  213. package/dist/esm-es5/ion-progress-bar.entry.js +1 -1
  214. package/dist/esm-es5/ion-radio_2.entry.js +1 -1
  215. package/dist/esm-es5/ion-range.entry.js +1 -1
  216. package/dist/esm-es5/ion-refresher_2.entry.js +1 -1
  217. package/dist/esm-es5/ion-reorder_2.entry.js +1 -1
  218. package/dist/esm-es5/ion-ripple-effect.entry.js +1 -1
  219. package/dist/esm-es5/ion-route_4.entry.js +1 -1
  220. package/dist/esm-es5/ion-searchbar.entry.js +1 -1
  221. package/dist/esm-es5/ion-segment_2.entry.js +1 -1
  222. package/dist/esm-es5/ion-select_3.entry.js +1 -1
  223. package/dist/esm-es5/ion-spinner.entry.js +1 -1
  224. package/dist/esm-es5/ion-split-pane.entry.js +1 -1
  225. package/dist/esm-es5/ion-tab-bar_2.entry.js +1 -1
  226. package/dist/esm-es5/ion-tab_2.entry.js +1 -1
  227. package/dist/esm-es5/ion-text.entry.js +1 -1
  228. package/dist/esm-es5/ion-textarea.entry.js +1 -1
  229. package/dist/esm-es5/ion-toast.entry.js +1 -1
  230. package/dist/esm-es5/ion-toggle.entry.js +1 -1
  231. package/dist/esm-es5/{ionic-global-c0cda98e.js → ionic-global-1f99b929.js} +1 -1
  232. package/dist/esm-es5/ionic.js +1 -1
  233. package/dist/esm-es5/{ios.transition-802a84a6.js → ios.transition-3376ccb2.js} +1 -1
  234. package/dist/esm-es5/loader.js +1 -1
  235. package/dist/esm-es5/md.transition-f992779f.js +4 -0
  236. package/dist/esm-es5/{overlays-32ef481d.js → overlays-b33f6bca.js} +1 -1
  237. package/dist/esm-es5/{status-tap-2b93b1b5.js → status-tap-16fd8f3d.js} +1 -1
  238. package/dist/html.html-data.json +13 -1
  239. package/dist/ionic/index.esm.js +1 -1
  240. package/dist/ionic/ionic.esm.js +1 -1
  241. package/dist/ionic/ionic.js +1 -1
  242. package/dist/ionic/{p-f70970cf.js → p-0235067a.js} +1 -1
  243. package/dist/ionic/p-02cb0cf0.entry.js +4 -0
  244. package/dist/ionic/{p-cdbeaadc.js → p-04377cfa.js} +1 -1
  245. package/dist/ionic/{p-f656e032.system.entry.js → p-043aa6cc.system.entry.js} +1 -1
  246. package/dist/ionic/{p-c3c3333a.js → p-0509fd34.js} +1 -1
  247. package/dist/ionic/{p-765f4dde.entry.js → p-0550f802.entry.js} +1 -1
  248. package/dist/ionic/{p-d032f825.system.entry.js → p-068ec6d3.system.entry.js} +1 -1
  249. package/dist/ionic/{p-8acae6b0.system.entry.js → p-06abe918.system.entry.js} +1 -1
  250. package/dist/ionic/{p-5e745192.system.js → p-0aa78a8d.system.js} +1 -1
  251. package/dist/ionic/{p-b56d0866.system.entry.js → p-0ebc87b7.system.entry.js} +1 -1
  252. package/dist/ionic/{p-e7ea9815.system.entry.js → p-149567b1.system.entry.js} +1 -1
  253. package/dist/ionic/{p-b4a51c42.system.js → p-1501b945.system.js} +1 -1
  254. package/dist/ionic/{p-0add7211.entry.js → p-154e5e06.entry.js} +1 -1
  255. package/dist/ionic/{p-6f8dbe92.system.entry.js → p-158efe8d.system.entry.js} +1 -1
  256. package/dist/ionic/{p-8804a472.system.entry.js → p-17d283b9.system.entry.js} +1 -1
  257. package/dist/ionic/p-18cae04f.js +4 -0
  258. package/dist/ionic/{p-e3584231.system.js → p-19d9ceb8.system.js} +1 -1
  259. package/dist/ionic/{p-2d539df1.entry.js → p-1b27ac67.entry.js} +1 -1
  260. package/dist/ionic/{p-a3277a67.entry.js → p-1c249831.entry.js} +1 -1
  261. package/dist/ionic/{p-0e53f8ea.system.entry.js → p-20e0e75d.system.entry.js} +1 -1
  262. package/dist/ionic/p-213e377d.system.entry.js +4 -0
  263. package/dist/ionic/{p-9f6ee2c0.system.entry.js → p-254ec7c0.system.entry.js} +1 -1
  264. package/dist/ionic/{p-78aadecb.entry.js → p-26c4bf85.entry.js} +1 -1
  265. package/dist/ionic/{p-a1987850.entry.js → p-2894d5f6.entry.js} +1 -1
  266. package/dist/ionic/{p-9738fd82.js → p-290d3fe9.js} +1 -1
  267. package/dist/ionic/{p-8d69a624.entry.js → p-2b3debd5.entry.js} +1 -1
  268. package/dist/ionic/{p-958d6ebe.system.entry.js → p-2ba9a9bd.system.entry.js} +2 -2
  269. package/dist/ionic/{p-c847fb35.system.entry.js → p-328107a5.system.entry.js} +1 -1
  270. package/dist/ionic/p-328b49db.system.entry.js +4 -0
  271. package/dist/ionic/{p-1161a793.entry.js → p-3313c481.entry.js} +1 -1
  272. package/dist/ionic/{p-2938823a.system.entry.js → p-332ea4d3.system.entry.js} +1 -1
  273. package/dist/ionic/p-3381c3f4.entry.js +4 -0
  274. package/dist/ionic/{p-a0d7bb5e.system.js → p-3671f1b9.system.js} +1 -1
  275. package/dist/ionic/{p-b7010c69.system.entry.js → p-39f96ff6.system.entry.js} +1 -1
  276. package/dist/ionic/{p-98f3d827.entry.js → p-3dfc522b.entry.js} +1 -1
  277. package/dist/ionic/{p-88fde0e0.entry.js → p-3e8d5e53.entry.js} +1 -1
  278. package/dist/ionic/{p-ef126ae8.system.entry.js → p-41208f54.system.entry.js} +1 -1
  279. package/dist/ionic/{p-a0bb7b92.system.entry.js → p-43f03cf4.system.entry.js} +1 -1
  280. package/dist/ionic/{p-caf21b46.system.entry.js → p-4489dd20.system.entry.js} +1 -1
  281. package/dist/ionic/{p-72f6ff89.js → p-44a56556.js} +1 -1
  282. package/dist/ionic/{p-353b349d.entry.js → p-44dc52e5.entry.js} +1 -1
  283. package/dist/ionic/{p-80fa068e.entry.js → p-47bb15a1.entry.js} +1 -1
  284. package/dist/ionic/p-4a3218d4.system.entry.js +4 -0
  285. package/dist/ionic/{p-3f5179b5.entry.js → p-4f400544.entry.js} +1 -1
  286. package/dist/ionic/{p-16756e94.system.entry.js → p-507ddbfe.system.entry.js} +1 -1
  287. package/dist/ionic/p-52cfafe9.system.js +5 -0
  288. package/dist/ionic/{p-4155f352.system.js → p-5ad1fe3b.system.js} +1 -1
  289. package/dist/ionic/p-5e0c7fdc.entry.js +4 -0
  290. package/dist/ionic/{p-8f5d30f5.entry.js → p-5ff99b79.entry.js} +1 -1
  291. package/dist/ionic/{p-d37b441e.entry.js → p-60959b71.entry.js} +1 -1
  292. package/dist/ionic/{p-28a2c2a2.entry.js → p-61e4d3ec.entry.js} +1 -1
  293. package/dist/ionic/{p-9709ebd8.system.entry.js → p-6337e56b.system.entry.js} +1 -1
  294. package/dist/ionic/{p-ada96dd0.system.entry.js → p-648ad047.system.entry.js} +1 -1
  295. package/dist/ionic/{p-51a087d6.entry.js → p-6855f26a.entry.js} +1 -1
  296. package/dist/ionic/{p-4fb51e61.system.entry.js → p-69641343.system.entry.js} +1 -1
  297. package/dist/ionic/{p-47b6ba5b.js → p-6ab03751.js} +1 -1
  298. package/dist/ionic/{p-517a9885.system.entry.js → p-6c277fa2.system.entry.js} +1 -1
  299. package/dist/ionic/{p-46d400b4.system.entry.js → p-6e0539ea.system.entry.js} +1 -1
  300. package/dist/ionic/{p-dee7c1d0.system.entry.js → p-6fba0ce1.system.entry.js} +1 -1
  301. package/dist/ionic/p-72cb0718.system.entry.js +4 -0
  302. package/dist/ionic/{p-9eec42cc.system.entry.js → p-745e3339.system.entry.js} +1 -1
  303. package/dist/ionic/{p-1b19c04b.entry.js → p-767f1a92.entry.js} +1 -1
  304. package/dist/ionic/{p-c9a21dfd.system.entry.js → p-793a10e0.system.entry.js} +1 -1
  305. package/dist/ionic/p-799da666.entry.js +4 -0
  306. package/dist/ionic/{p-5ecae037.js → p-7fae5c36.js} +1 -1
  307. package/dist/ionic/{p-ea69616e.entry.js → p-84b567a6.entry.js} +1 -1
  308. package/dist/ionic/{p-b6f9d32a.entry.js → p-85f48531.entry.js} +1 -1
  309. package/dist/ionic/p-87bb3735.system.js +4 -0
  310. package/dist/ionic/p-8dae44aa.entry.js +4 -0
  311. package/dist/ionic/{p-908475e7.system.entry.js → p-8f301ac5.system.entry.js} +1 -1
  312. package/dist/ionic/{p-cfe57b1b.entry.js → p-928ee57a.entry.js} +1 -1
  313. package/dist/ionic/{p-953009b1.entry.js → p-93390f78.entry.js} +1 -1
  314. package/dist/ionic/p-93419ece.system.entry.js +4 -0
  315. package/dist/ionic/p-97174c1e.js +4 -0
  316. package/dist/ionic/{p-6de472cb.js → p-98f35d98.js} +1 -1
  317. package/dist/ionic/p-9a68d8ef.system.js +4 -0
  318. package/dist/ionic/{p-5b365ca7.system.js → p-9f94c72e.system.js} +1 -1
  319. package/dist/ionic/{p-1208f939.entry.js → p-9fb45814.entry.js} +1 -1
  320. package/dist/ionic/{p-3e6b47e8.system.entry.js → p-9fda6824.system.entry.js} +1 -1
  321. package/dist/ionic/{p-31fcb233.system.js → p-a074be82.system.js} +1 -1
  322. package/dist/ionic/p-a20bb802.entry.js +4 -0
  323. package/dist/ionic/{p-17da5ed1.entry.js → p-a3013394.entry.js} +1 -1
  324. package/dist/ionic/p-a4461d1c.system.entry.js +4 -0
  325. package/dist/ionic/{p-8314281e.system.js → p-a49931aa.system.js} +1 -1
  326. package/dist/ionic/{p-e6d68e02.system.entry.js → p-a821750c.system.entry.js} +1 -1
  327. package/dist/ionic/{p-5bebc7b3.system.entry.js → p-abd5d0d5.system.entry.js} +1 -1
  328. package/dist/ionic/{p-270e1a1d.entry.js → p-ade3cf46.entry.js} +1 -1
  329. package/dist/ionic/{p-6fbecbda.entry.js → p-aed4931c.entry.js} +1 -1
  330. package/dist/ionic/{p-e24ce1e5.system.js → p-afa9f205.system.js} +1 -1
  331. package/dist/ionic/{p-c91ccbfa.system.entry.js → p-b7058a0e.system.entry.js} +1 -1
  332. package/dist/ionic/{p-cce9f61a.system.entry.js → p-b7a2ffc9.system.entry.js} +1 -1
  333. package/dist/ionic/{p-b3b3efba.system.entry.js → p-b8a9e195.system.entry.js} +1 -1
  334. package/dist/ionic/{p-ddb30596.entry.js → p-b964aba3.entry.js} +1 -1
  335. package/dist/ionic/{p-9b7f0b0f.entry.js → p-bdf71399.entry.js} +1 -1
  336. package/dist/ionic/{p-6e70dd1a.system.entry.js → p-beeed22c.system.entry.js} +1 -1
  337. package/dist/ionic/{p-f8a5bb89.entry.js → p-c08fe2c0.entry.js} +1 -1
  338. package/dist/ionic/{p-4d67d27a.entry.js → p-c1701827.entry.js} +1 -1
  339. package/dist/ionic/{p-18ba8221.entry.js → p-c23eff76.entry.js} +1 -1
  340. package/dist/ionic/{p-b5f9f14c.entry.js → p-c68dd1e0.entry.js} +1 -1
  341. package/dist/ionic/p-c8aadc98.system.entry.js +4 -0
  342. package/dist/ionic/{p-3dd98a73.entry.js → p-cad1126a.entry.js} +1 -1
  343. package/dist/ionic/{p-042e6f4b.entry.js → p-cd1b920b.entry.js} +1 -1
  344. package/dist/ionic/p-cd574dfa.js +4 -0
  345. package/dist/ionic/{p-3a45a82b.entry.js → p-cf235986.entry.js} +1 -1
  346. package/dist/ionic/p-d0748f6d.entry.js +4 -0
  347. package/dist/ionic/{p-b6f5e4f2.system.entry.js → p-d93eed83.system.entry.js} +1 -1
  348. package/dist/ionic/{p-e94c392d.entry.js → p-da5e2652.entry.js} +1 -1
  349. package/dist/ionic/p-da666998.system.entry.js +4 -0
  350. package/dist/ionic/{p-7d92bf15.system.entry.js → p-dc71e4ef.system.entry.js} +1 -1
  351. package/dist/ionic/{p-6577aea9.system.entry.js → p-ddd48faf.system.entry.js} +1 -1
  352. package/dist/ionic/p-e2903cdc.system.entry.js +4 -0
  353. package/dist/ionic/{p-2092f39f.entry.js → p-e33d1ebc.entry.js} +1 -1
  354. package/dist/ionic/p-eb246b50.entry.js +4 -0
  355. package/dist/ionic/p-ee810056.system.entry.js +4 -0
  356. package/dist/ionic/{p-33a37fad.system.js → p-f6e9c227.system.js} +1 -1
  357. package/dist/ionic/{p-251666e2.entry.js → p-f894e0ad.entry.js} +1 -1
  358. package/dist/types/components/datetime/datetime.d.ts +3 -0
  359. package/dist/types/components/datetime/utils/manipulation.d.ts +34 -7
  360. package/dist/types/components/input/input.d.ts +3 -0
  361. package/dist/types/components/modal/modal.d.ts +3 -0
  362. package/dist/types/components/range/range.d.ts +3 -0
  363. package/dist/types/components/refresher/refresher.d.ts +3 -0
  364. package/dist/types/components/refresher/refresher.utils.d.ts +16 -0
  365. package/dist/types/components/textarea/textarea.d.ts +3 -0
  366. package/dist/types/components.d.ts +18 -10
  367. package/hydrate/index.js +221 -83
  368. package/package.json +7 -7
  369. package/dist/esm-es5/app-globals-722340c4.js +0 -4
  370. package/dist/esm-es5/data-f5c75b4e.js +0 -4
  371. package/dist/esm-es5/index-08d686eb.js +0 -5
  372. package/dist/esm-es5/md.transition-43c2874d.js +0 -4
  373. package/dist/ionic/p-01d14eba.system.entry.js +0 -4
  374. package/dist/ionic/p-1786bc72.js +0 -4
  375. package/dist/ionic/p-28249b10.system.entry.js +0 -4
  376. package/dist/ionic/p-2aea8b1e.js +0 -4
  377. package/dist/ionic/p-2d3b9fa3.system.entry.js +0 -4
  378. package/dist/ionic/p-350f7292.system.entry.js +0 -4
  379. package/dist/ionic/p-4233cc1e.system.entry.js +0 -4
  380. package/dist/ionic/p-564af202.system.entry.js +0 -4
  381. package/dist/ionic/p-588fdf40.entry.js +0 -4
  382. package/dist/ionic/p-5e4eec2e.entry.js +0 -4
  383. package/dist/ionic/p-5eda1d7d.entry.js +0 -4
  384. package/dist/ionic/p-6ad34705.system.entry.js +0 -4
  385. package/dist/ionic/p-6de62649.system.entry.js +0 -4
  386. package/dist/ionic/p-82e3d633.system.js +0 -4
  387. package/dist/ionic/p-91d33c4a.js +0 -4
  388. package/dist/ionic/p-9e447eb1.system.js +0 -4
  389. package/dist/ionic/p-a4afcc88.entry.js +0 -4
  390. package/dist/ionic/p-a9978d08.entry.js +0 -4
  391. package/dist/ionic/p-afd6ca9d.entry.js +0 -4
  392. package/dist/ionic/p-d3b030b8.system.js +0 -5
  393. package/dist/ionic/p-dc6af8e9.entry.js +0 -4
  394. package/dist/ionic/p-f0445d82.system.entry.js +0 -4
  395. package/dist/ionic/p-fba0a6e7.system.entry.js +0 -4
  396. package/dist/ionic/p-feae5133.entry.js +0 -4
  397. /package/dist/esm-es5/{index-c132c5f1.js → index-f7dc70ba.js} +0 -0
  398. /package/dist/ionic/{p-ea96fa73.js → p-831269de.js} +0 -0
  399. /package/dist/ionic/{p-8050b9b9.system.js → p-dfb6de03.system.js} +0 -0
@@ -16,7 +16,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
16
16
  });
17
17
  });
18
18
  test.describe(title('radio: keyboard navigation'), () => {
19
- test.beforeEach(async ({ page }) => {
19
+ test.beforeEach(async ({ page, browserName }) => {
20
20
  await page.setContent(`
21
21
  <ion-app>
22
22
  <ion-content>
@@ -55,6 +55,20 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
55
55
  </ion-content>
56
56
  </ion-app>
57
57
  `, config);
58
+ if (browserName === 'webkit') {
59
+ const radio = page.locator('#first-group ion-radio').first();
60
+ /**
61
+ * Sometimes Safari does not focus the first radio.
62
+ * This is a workaround to ensure the first radio is focused.
63
+ *
64
+ * Wait for the first radio to be rendered before tabbing.
65
+ * This is necessary because the first radio may not be rendered
66
+ * when the page first loads.
67
+ *
68
+ * This would cause the first radio to be skipped when tabbing.
69
+ */
70
+ await radio.waitFor();
71
+ }
58
72
  });
59
73
  test('tabbing should switch between radio groups', async ({ page, pageUtils }) => {
60
74
  const firstGroupRadios = page.locator('#first-group ion-radio');
@@ -8,9 +8,22 @@ import { configs, test } from "../../../../../utils/test/playwright/index";
8
8
  */
9
9
  configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
10
10
  test.describe(title('radio: a11y'), () => {
11
- test.beforeEach(async ({ page, skip }) => {
12
- skip.browser('webkit', 'Tabbing is flaky in Safari');
11
+ test.beforeEach(async ({ page, browserName }) => {
13
12
  await page.goto(`/src/components/radio/test/legacy/a11y`, config);
13
+ if (browserName === 'webkit') {
14
+ const radio = page.locator('#first-group ion-radio').first();
15
+ /**
16
+ * Sometimes Safari does not focus the first radio.
17
+ * This is a workaround to ensure the first radio is focused.
18
+ *
19
+ * Wait for the first radio to be rendered before tabbing.
20
+ * This is necessary because the first radio may not be rendered
21
+ * when the page first loads.
22
+ *
23
+ * This would cause the first radio to be skipped when tabbing.
24
+ */
25
+ await radio.waitFor();
26
+ }
14
27
  });
15
28
  test('tabbing should switch between radio groups', async ({ page, pageUtils }) => {
16
29
  const firstGroupRadios = page.locator('#first-group ion-radio');
@@ -33,7 +33,15 @@ 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
+ /**
37
+ * Our current disabled prop definition causes Stencil to mark it
38
+ * as optional. While this is not desired, fixing this behavior
39
+ * in Stencil is a significant breaking change, so this effort is
40
+ * being de-risked in STENCIL-917. Until then, we compromise
41
+ * here by checking for falsy `disabled` values instead of strictly
42
+ * checking `disabled === false`.
43
+ */
44
+ if (selectedRadio && !selectedRadio.disabled) {
37
45
  const currentValue = this.value;
38
46
  const newValue = selectedRadio.value;
39
47
  if (newValue !== currentValue) {
@@ -718,7 +718,7 @@ Developers can dismiss this warning by removing their usage of the "legacy" prop
718
718
  "optional": false,
719
719
  "docs": {
720
720
  "tags": [],
721
- "text": "A callback used to format the pin text.\nBy default the pin text is set to `Math.round(value)`."
721
+ "text": "A callback used to format the pin text.\nBy default the pin text is set to `Math.round(value)`.\n\nSee https://ionicframework.com/docs/troubleshooting/runtime#accessing-this\nif you need to access `this` from within the callback."
722
722
  },
723
723
  "defaultValue": "(value: number): number => Math.round(value)"
724
724
  },
@@ -8,6 +8,9 @@ import { clamp, componentOnReady, getElementRoot, raf, transitionEndAsync } from
8
8
  import { ImpactStyle, hapticImpact } from "../../utils/native/haptic";
9
9
  import { getIonMode } from "../../global/ionic-global";
10
10
  import { createPullingAnimation, createSnapBackAnimation, getRefresherAnimationType, handleScrollWhilePulling, handleScrollWhileRefreshing, setSpinnerOpacity, shouldUseNativeRefresher, translateElement, } from "./refresher.utils";
11
+ /**
12
+ * @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
13
+ */
11
14
  export class Refresher {
12
15
  constructor() {
13
16
  this.appliedStyles = false;
@@ -4,7 +4,6 @@
4
4
  import { writeTask } from "@stencil/core";
5
5
  import { createAnimation } from "../../utils/animation/animation";
6
6
  import { clamp, componentOnReady, transitionEndAsync } from "../../utils/helpers";
7
- import { isPlatform } from "../../utils/platform";
8
7
  export const getRefresherAnimationType = (contentEl) => {
9
8
  const previousSibling = contentEl.previousElementSibling;
10
9
  const hasHeader = previousSibling !== null && previousSibling.tagName === 'ION-HEADER';
@@ -162,6 +161,24 @@ export const translateElement = (el, value, duration = 200) => {
162
161
  };
163
162
  // Utils
164
163
  // -----------------------------
164
+ /**
165
+ * In order to use the native iOS refresher the device must support rubber band scrolling.
166
+ * As part of this, we need to exclude Desktop Safari because it has a slightly different rubber band effect that is not compatible with the native refresher in Ionic.
167
+ *
168
+ * We also need to be careful not to include devices that spoof their user agent.
169
+ * For example, when using iOS emulation in Chrome the user agent will be spoofed such that
170
+ * navigator.maxTouchPointer > 0. To work around this,
171
+ * we check to see if the apple-pay-logo is supported as a named image which is only
172
+ * true on Apple devices.
173
+ *
174
+ * We previously checked referencEl.style.webkitOverflowScrolling to explicitly check
175
+ * for rubber band support. However, this property was removed on iPadOS and it's possible
176
+ * that this will be removed on iOS in the future too.
177
+ *
178
+ */
179
+ export const supportsRubberBandScrolling = () => {
180
+ return navigator.maxTouchPoints > 0 && CSS.supports('background: -webkit-named-image(apple-pay-logo-black)');
181
+ };
165
182
  export const shouldUseNativeRefresher = async (referenceEl, mode) => {
166
183
  const refresherContent = referenceEl.querySelector('ion-refresher-content');
167
184
  if (!refresherContent) {
@@ -172,14 +189,5 @@ export const shouldUseNativeRefresher = async (referenceEl, mode) => {
172
189
  const refreshingSpinner = referenceEl.querySelector('ion-refresher-content .refresher-refreshing ion-spinner');
173
190
  return (pullingSpinner !== null &&
174
191
  refreshingSpinner !== null &&
175
- /**
176
- * We use webkitOverflowScrolling for feature detection with rubber band scrolling
177
- * on iOS. When doing referenceEl.style, webkitOverflowScrolling is undefined on non-iOS platforms.
178
- * However, it will be the empty string on iOS.
179
- * Note that we do not use getPropertyValue (and thus need to cast as any) because calling
180
- * getPropertyValue('-webkit-overflow-scrolling') will return the empty string if it is not
181
- * set on the element, even if the platform does not support that.
182
- */
183
- ((mode === 'ios' && isPlatform('mobile') && referenceEl.style.webkitOverflowScrolling !== undefined) ||
184
- mode === 'md'));
192
+ ((mode === 'ios' && supportsRubberBandScrolling()) || mode === 'md'));
185
193
  };
@@ -3,11 +3,11 @@
3
3
  */
4
4
  import { Host, h } from "@stencil/core";
5
5
  import { ENABLE_HTML_CONTENT_DEFAULT } from "../../utils/config";
6
- import { isPlatform } from "../../utils/platform";
7
6
  import { sanitizeDOMString } from "../../utils/sanitization/index";
8
7
  import { arrowDown, caretBackSharp } from "ionicons/icons";
9
8
  import { config } from "../../global/config";
10
9
  import { getIonMode } from "../../global/ionic-global";
10
+ import { supportsRubberBandScrolling } from "../refresher/refresher.utils";
11
11
  import { SPINNERS } from "../spinner/spinner-configs";
12
12
  export class RefresherContent {
13
13
  constructor() {
@@ -19,9 +19,15 @@ export class RefresherContent {
19
19
  }
20
20
  componentWillLoad() {
21
21
  if (this.pullingIcon === undefined) {
22
+ /**
23
+ * The native iOS refresher uses a spinner instead of
24
+ * an icon, so we need to see if this device supports
25
+ * the native iOS refresher.
26
+ */
27
+ const hasRubberBandScrolling = supportsRubberBandScrolling();
22
28
  const mode = getIonMode(this);
23
- const overflowRefresher = this.el.style.webkitOverflowScrolling !== undefined ? 'lines' : arrowDown;
24
- this.pullingIcon = config.get('refreshingIcon', mode === 'ios' && isPlatform('mobile') ? config.get('spinner', overflowRefresher) : 'circular');
29
+ const overflowRefresher = hasRubberBandScrolling ? 'lines' : arrowDown;
30
+ this.pullingIcon = config.get('refreshingIcon', mode === 'ios' && hasRubberBandScrolling ? config.get('spinner', overflowRefresher) : 'circular');
25
31
  }
26
32
  if (this.refreshingSpinner === undefined) {
27
33
  const mode = getIonMode(this);
@@ -628,10 +628,12 @@ button {
628
628
 
629
629
  ::slotted([slot=start]) {
630
630
  margin-inline-end: 16px;
631
+ margin-inline-start: 0;
631
632
  }
632
633
 
633
634
  ::slotted([slot=end]) {
634
635
  margin-inline-start: 16px;
636
+ margin-inline-end: 0;
635
637
  }
636
638
 
637
639
  /**
@@ -764,4 +766,22 @@ button {
764
766
 
765
767
  :host(.select-disabled) {
766
768
  opacity: 0.3;
769
+ }
770
+
771
+ /**
772
+ * Slotted buttons have a lot of default padding that can
773
+ * cause them to look misaligned from other pieces such
774
+ * as the control's label, especially when using a clear
775
+ * fill. We also make them circular to ensure that non-
776
+ * clear buttons and the focus/hover state on clear ones
777
+ * don't look too crowded.
778
+ */
779
+ ::slotted(ion-button[slot=start].button-has-icon-only),
780
+ ::slotted(ion-button[slot=end].button-has-icon-only) {
781
+ --border-radius: 50%;
782
+ --padding-start: 0;
783
+ --padding-end: 0;
784
+ --padding-top: 0;
785
+ --padding-bottom: 0;
786
+ aspect-ratio: 1;
767
787
  }
@@ -628,10 +628,12 @@ button {
628
628
 
629
629
  ::slotted([slot=start]) {
630
630
  margin-inline-end: 16px;
631
+ margin-inline-start: 0;
631
632
  }
632
633
 
633
634
  ::slotted([slot=end]) {
634
635
  margin-inline-start: 16px;
636
+ margin-inline-end: 0;
635
637
  }
636
638
 
637
639
  /**
@@ -1350,4 +1352,23 @@ button {
1350
1352
 
1351
1353
  :host(.select-disabled) {
1352
1354
  opacity: 0.38;
1355
+ }
1356
+
1357
+ /**
1358
+ * Slotted buttons have a lot of default padding that can
1359
+ * cause them to look misaligned from other pieces such
1360
+ * as the control's label, especially when using a clear
1361
+ * fill. We also make them circular to ensure that non-
1362
+ * clear buttons and the focus/hover state on clear ones
1363
+ * don't look too crowded.
1364
+ */
1365
+ ::slotted(ion-button[slot=start].button-has-icon-only),
1366
+ ::slotted(ion-button[slot=end].button-has-icon-only) {
1367
+ --border-radius: 50%;
1368
+ --padding-start: 8px;
1369
+ --padding-end: 8px;
1370
+ --padding-top: 8px;
1371
+ --padding-bottom: 8px;
1372
+ aspect-ratio: 1;
1373
+ min-height: 40px;
1353
1374
  }
@@ -9,7 +9,9 @@ configs().forEach(({ title, screenshot, config }) => {
9
9
  await page.setContent(`
10
10
  <ion-select label-placement="start" fill="solid" placeholder="Select weight" label="Weight">
11
11
  <ion-icon slot="start" name="barbell" aria-hidden="true"></ion-icon>
12
- <ion-label slot="end">lbs</ion-label>
12
+ <ion-button slot="end" aria-label="Show/hide password">
13
+ <ion-icon slot="icon-only" name="lock-closed" aria-hidden="true"></ion-icon>
14
+ </ion-button>
13
15
  </ion-select>
14
16
  `, config);
15
17
  const select = page.locator('ion-select');
@@ -19,7 +21,9 @@ configs().forEach(({ title, screenshot, config }) => {
19
21
  await page.setContent(`
20
22
  <ion-select label-placement="floating" fill="solid" placeholder="Select weight" label="Weight">
21
23
  <ion-icon slot="start" name="barbell" aria-hidden="true"></ion-icon>
22
- <ion-label slot="end">lbs</ion-label>
24
+ <ion-button slot="end" aria-label="Show/hide password">
25
+ <ion-icon slot="icon-only" name="lock-closed" aria-hidden="true"></ion-icon>
26
+ </ion-button>
23
27
  </ion-select>
24
28
  `, config);
25
29
  const select = page.locator('ion-select');
@@ -146,13 +146,21 @@
146
146
  top: 0;
147
147
  bottom: 0;
148
148
  position: relative;
149
- /* stylelint-disable-next-line declaration-no-important */
150
- box-shadow: none !important;
149
+ box-shadow: none;
151
150
  z-index: 0;
152
151
  }
153
152
 
154
153
  :host(.split-pane-visible) ::slotted(.split-pane-main) {
155
154
  flex: 1;
155
+ /**
156
+ * Content can overflow outside of a router outlet
157
+ * or a nav container to allow for the translucent
158
+ * tab bar effect to work. However, this can cause
159
+ * iOS page transitions to flow outside of the container
160
+ * and overlap the menu on larger viewports. As a result,
161
+ * we disable the overflow when that is the case.
162
+ */
163
+ overflow: hidden;
156
164
  }
157
165
 
158
166
  :host(.split-pane-visible) ::slotted(.split-pane-side:not(ion-menu)),
@@ -146,13 +146,21 @@
146
146
  top: 0;
147
147
  bottom: 0;
148
148
  position: relative;
149
- /* stylelint-disable-next-line declaration-no-important */
150
- box-shadow: none !important;
149
+ box-shadow: none;
151
150
  z-index: 0;
152
151
  }
153
152
 
154
153
  :host(.split-pane-visible) ::slotted(.split-pane-main) {
155
154
  flex: 1;
155
+ /**
156
+ * Content can overflow outside of a router outlet
157
+ * or a nav container to allow for the translucent
158
+ * tab bar effect to work. However, this can cause
159
+ * iOS page transitions to flow outside of the container
160
+ * and overlap the menu on larger viewports. As a result,
161
+ * we disable the overflow when that is the case.
162
+ */
163
+ overflow: hidden;
156
164
  }
157
165
 
158
166
  :host(.split-pane-visible) ::slotted(.split-pane-side:not(ion-menu)),
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import { expect } from "@playwright/test";
5
5
  import { test, configs } from "../../../../utils/test/playwright/index";
6
+ const IGNORED_KEYS = ['Tab', 'Shift', 'Meta', 'Alt', 'Control'];
6
7
  configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
7
8
  test.describe(title('textarea: clearOnEdit'), () => {
8
9
  test('should clear when typed into', async ({ page }) => {
@@ -21,5 +22,40 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
21
22
  await page.waitForChanges();
22
23
  await expect(textarea).toHaveJSProperty('value', 'abc');
23
24
  });
25
+ test('should not clear the textarea if it does not have an initial value when typing', async ({ page }) => {
26
+ await page.setContent(`<ion-textarea label="textarea" value="" clear-on-edit="true"></ion-textarea>`, config);
27
+ const textarea = page.locator('ion-textarea');
28
+ await textarea.click();
29
+ await textarea.type('hello world');
30
+ await expect(textarea).toHaveJSProperty('value', 'hello world');
31
+ });
32
+ IGNORED_KEYS.forEach((ignoredKey) => {
33
+ test(`should not clear when ${ignoredKey} is pressed`, async ({ page, skip }) => {
34
+ skip.browser((browserName) => browserName === 'firefox' && ignoredKey === 'Meta', 'Firefox incorrectly adds "OS" to the textarea when pressing the Meta key on Linux');
35
+ await page.setContent(`<ion-textarea value="abc" clear-on-edit="true" aria-label="textarea"></ion-textarea>`, config);
36
+ const textarea = page.locator('ion-textarea');
37
+ await textarea.locator('textarea').focus();
38
+ await page.keyboard.press(ignoredKey);
39
+ await page.waitForChanges();
40
+ await expect(textarea).toHaveJSProperty('value', 'abc');
41
+ });
42
+ });
43
+ test('should clear after when pressing valid key after pressing ignored key', async ({ page }) => {
44
+ test.info().annotations.push({
45
+ type: 'issue',
46
+ description: 'https://github.com/ionic-team/ionic-framework/issues/28633',
47
+ });
48
+ await page.setContent(`<ion-textarea value="abc" clear-on-edit="true" aria-label="textarea"></ion-textarea>`, config);
49
+ const textarea = page.locator('ion-textarea');
50
+ await textarea.locator('textarea').focus();
51
+ // ignored
52
+ await page.keyboard.press('Shift');
53
+ await page.waitForChanges();
54
+ await expect(textarea).toHaveJSProperty('value', 'abc');
55
+ // allowed
56
+ await page.keyboard.press('a');
57
+ await page.waitForChanges();
58
+ await expect(textarea).toHaveJSProperty('value', 'a');
59
+ });
24
60
  });
25
61
  });
@@ -9,7 +9,9 @@ configs().forEach(({ title, screenshot, config }) => {
9
9
  await page.setContent(`
10
10
  <ion-textarea label-placement="start" fill="solid" value="100" label="Weight">
11
11
  <ion-icon slot="start" name="barbell" aria-hidden="true"></ion-icon>
12
- <ion-label slot="end">lbs</ion-label>
12
+ <ion-button slot="end" aria-label="Show/hide password">
13
+ <ion-icon slot="icon-only" name="lock-closed" aria-hidden="true"></ion-icon>
14
+ </ion-button>
13
15
  </ion-textarea>
14
16
  `, config);
15
17
  const textarea = page.locator('ion-textarea');
@@ -19,7 +21,9 @@ configs().forEach(({ title, screenshot, config }) => {
19
21
  await page.setContent(`
20
22
  <ion-textarea label-placement="floating" fill="solid" value="100" label="Weight">
21
23
  <ion-icon slot="start" name="barbell" aria-hidden="true"></ion-icon>
22
- <ion-label slot="end">lbs</ion-label>
24
+ <ion-button slot="end" aria-label="Show/hide password">
25
+ <ion-icon slot="icon-only" name="lock-closed" aria-hidden="true"></ion-icon>
26
+ </ion-button>
23
27
  </ion-textarea>
24
28
  `, config);
25
29
  const textarea = page.locator('ion-textarea');
@@ -766,10 +766,12 @@
766
766
 
767
767
  ::slotted([slot=start]) {
768
768
  margin-inline-end: 16px;
769
+ margin-inline-start: 0;
769
770
  }
770
771
 
771
772
  ::slotted([slot=end]) {
772
773
  margin-inline-start: 16px;
774
+ margin-inline-end: 0;
773
775
  }
774
776
 
775
777
  /**
@@ -964,4 +966,22 @@
964
966
  :host(.legacy-textarea) .native-textarea[disabled],
965
967
  :host(.textarea-disabled) {
966
968
  opacity: 0.3;
969
+ }
970
+
971
+ /**
972
+ * Slotted buttons have a lot of default padding that can
973
+ * cause them to look misaligned from other pieces such
974
+ * as the control's label, especially when using a clear
975
+ * fill. We also make them circular to ensure that non-
976
+ * clear buttons and the focus/hover state on clear ones
977
+ * don't look too crowded.
978
+ */
979
+ ::slotted(ion-button[slot=start].button-has-icon-only),
980
+ ::slotted(ion-button[slot=end].button-has-icon-only) {
981
+ --border-radius: 50%;
982
+ --padding-start: 0;
983
+ --padding-end: 0;
984
+ --padding-top: 0;
985
+ --padding-bottom: 0;
986
+ aspect-ratio: 1;
967
987
  }
@@ -238,15 +238,38 @@ export class Textarea {
238
238
  if (!this.clearOnEdit) {
239
239
  return;
240
240
  }
241
+ /**
242
+ * The following keys do not modify the
243
+ * contents of the input. As a result, pressing
244
+ * them should not edit the textarea.
245
+ *
246
+ * We can't check to see if the value of the textarea
247
+ * was changed because we call checkClearOnEdit
248
+ * in a keydown listener, and the key has not yet
249
+ * been added to the textarea.
250
+ *
251
+ * Unlike ion-input, the "Enter" key does modify the
252
+ * textarea by adding a new line, so "Enter" is not
253
+ * included in the IGNORED_KEYS array.
254
+ */
255
+ const IGNORED_KEYS = ['Tab', 'Shift', 'Meta', 'Alt', 'Control'];
256
+ const pressedIgnoredKey = IGNORED_KEYS.includes(ev.key);
241
257
  /**
242
258
  * Clear the textarea if the control has not been previously cleared
243
259
  * during focus.
244
260
  */
245
- if (!this.didTextareaClearOnEdit && this.hasValue() && ev.key !== 'Tab') {
261
+ if (!this.didTextareaClearOnEdit && this.hasValue() && !pressedIgnoredKey) {
246
262
  this.value = '';
247
263
  this.emitInputChange(ev);
248
264
  }
249
- this.didTextareaClearOnEdit = true;
265
+ /**
266
+ * Pressing an IGNORED_KEYS first and
267
+ * then an allowed key will cause the input to not
268
+ * be cleared.
269
+ */
270
+ if (!pressedIgnoredKey) {
271
+ this.didTextareaClearOnEdit = true;
272
+ }
250
273
  }
251
274
  focusChange() {
252
275
  this.emitStyle();
@@ -825,7 +848,7 @@ Developers can use the "legacy" property to continue using the legacy form marku
825
848
  "optional": true,
826
849
  "docs": {
827
850
  "tags": [],
828
- "text": "A callback used to format the counter text.\nBy default the counter text is set to \"itemLength / maxLength\"."
851
+ "text": "A callback used to format the counter text.\nBy default the counter text is set to \"itemLength / maxLength\".\n\nSee https://ionicframework.com/docs/troubleshooting/runtime#accessing-this\nif you need to access `this` from within the callback."
829
852
  }
830
853
  },
831
854
  "errorText": {
@@ -766,10 +766,12 @@
766
766
 
767
767
  ::slotted([slot=start]) {
768
768
  margin-inline-end: 16px;
769
+ margin-inline-start: 0;
769
770
  }
770
771
 
771
772
  ::slotted([slot=end]) {
772
773
  margin-inline-start: 16px;
774
+ margin-inline-end: 0;
773
775
  }
774
776
 
775
777
  /**
@@ -1529,4 +1531,23 @@
1529
1531
 
1530
1532
  :host(.textarea-shape-round) {
1531
1533
  --border-radius: 16px;
1534
+ }
1535
+
1536
+ /**
1537
+ * Slotted buttons have a lot of default padding that can
1538
+ * cause them to look misaligned from other pieces such
1539
+ * as the control's label, especially when using a clear
1540
+ * fill. We also make them circular to ensure that non-
1541
+ * clear buttons and the focus/hover state on clear ones
1542
+ * don't look too crowded.
1543
+ */
1544
+ ::slotted(ion-button[slot=start].button-has-icon-only),
1545
+ ::slotted(ion-button[slot=end].button-has-icon-only) {
1546
+ --border-radius: 50%;
1547
+ --padding-start: 8px;
1548
+ --padding-end: 8px;
1549
+ --padding-top: 8px;
1550
+ --padding-bottom: 8px;
1551
+ aspect-ratio: 1;
1552
+ min-height: 40px;
1532
1553
  }
package/dist/docs.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
- "timestamp": "2023-12-07T03:01:23",
2
+ "timestamp": "2024-01-03T23:38:55",
3
3
  "compiler": {
4
4
  "name": "@stencil/core",
5
- "version": "4.8.1",
5
+ "version": "4.8.2",
6
6
  "typescriptVersion": "5.2.2"
7
7
  },
8
8
  "components": [
@@ -7627,7 +7627,7 @@
7627
7627
  },
7628
7628
  "mutable": false,
7629
7629
  "reflectToAttr": false,
7630
- "docs": "A callback used to format the header text that shows how many\ndates are selected. Only used if there are 0 or more than 1\nselected (i.e. unused for exactly 1). By default, the header\ntext is set to \"numberOfDates days\".",
7630
+ "docs": "A callback used to format the header text that shows how many\ndates are selected. Only used if there are 0 or more than 1\nselected (i.e. unused for exactly 1). By default, the header\ntext is set to \"numberOfDates days\".\n\nSee https://ionicframework.com/docs/troubleshooting/runtime#accessing-this\nif you need to access `this` from within the callback.",
7631
7631
  "docsTags": [],
7632
7632
  "values": [
7633
7633
  {
@@ -10162,7 +10162,7 @@
10162
10162
  },
10163
10163
  "mutable": false,
10164
10164
  "reflectToAttr": false,
10165
- "docs": "A callback used to format the counter text.\nBy default the counter text is set to \"itemLength / maxLength\".",
10165
+ "docs": "A callback used to format the counter text.\nBy default the counter text is set to \"itemLength / maxLength\".\n\nSee https://ionicframework.com/docs/troubleshooting/runtime#accessing-this\nif you need to access `this` from within the callback.",
10166
10166
  "docsTags": [],
10167
10167
  "values": [
10168
10168
  {
@@ -15091,7 +15091,7 @@
15091
15091
  "mutable": false,
15092
15092
  "attr": "can-dismiss",
15093
15093
  "reflectToAttr": false,
15094
- "docs": "Determines whether or not a modal can dismiss\nwhen calling the `dismiss` method.\n\nIf the value is `true` or the value's function returns `true`, the modal will close when trying to dismiss.\nIf the value is `false` or the value's function returns `false`, the modal will not close when trying to dismiss.",
15094
+ "docs": "Determines whether or not a modal can dismiss\nwhen calling the `dismiss` method.\n\nIf the value is `true` or the value's function returns `true`, the modal will close when trying to dismiss.\nIf the value is `false` or the value's function returns `false`, the modal will not close when trying to dismiss.\n\nSee https://ionicframework.com/docs/troubleshooting/runtime#accessing-this\nif you need to access `this` from within the callback.",
15095
15095
  "docsTags": [],
15096
15096
  "default": "true",
15097
15097
  "values": [
@@ -20286,7 +20286,7 @@
20286
20286
  },
20287
20287
  "mutable": false,
20288
20288
  "reflectToAttr": false,
20289
- "docs": "A callback used to format the pin text.\nBy default the pin text is set to `Math.round(value)`.",
20289
+ "docs": "A callback used to format the pin text.\nBy default the pin text is set to `Math.round(value)`.\n\nSee https://ionicframework.com/docs/troubleshooting/runtime#accessing-this\nif you need to access `this` from within the callback.",
20290
20290
  "docsTags": [],
20291
20291
  "default": "(value: number): number => Math.round(value)",
20292
20292
  "values": [
@@ -20620,7 +20620,12 @@
20620
20620
  "encapsulation": "none",
20621
20621
  "tag": "ion-refresher",
20622
20622
  "docs": "",
20623
- "docsTags": [],
20623
+ "docsTags": [
20624
+ {
20625
+ "name": "virtualProp",
20626
+ "text": "{\"ios\" | \"md\"} mode - The mode determines which platform styles to use."
20627
+ }
20628
+ ],
20624
20629
  "usage": {},
20625
20630
  "props": [
20626
20631
  {
@@ -20667,6 +20672,27 @@
20667
20672
  "optional": false,
20668
20673
  "required": false
20669
20674
  },
20675
+ {
20676
+ "name": "mode",
20677
+ "type": "\"ios\" | \"md\"",
20678
+ "mutable": false,
20679
+ "attr": "mode",
20680
+ "reflectToAttr": false,
20681
+ "docs": "The mode determines which platform styles to use.",
20682
+ "docsTags": [],
20683
+ "values": [
20684
+ {
20685
+ "value": "ios",
20686
+ "type": "string"
20687
+ },
20688
+ {
20689
+ "value": "md",
20690
+ "type": "string"
20691
+ }
20692
+ ],
20693
+ "optional": true,
20694
+ "required": false
20695
+ },
20670
20696
  {
20671
20697
  "name": "pullFactor",
20672
20698
  "type": "number",
@@ -26355,7 +26381,7 @@
26355
26381
  },
26356
26382
  "mutable": false,
26357
26383
  "reflectToAttr": false,
26358
- "docs": "A callback used to format the counter text.\nBy default the counter text is set to \"itemLength / maxLength\".",
26384
+ "docs": "A callback used to format the counter text.\nBy default the counter text is set to \"itemLength / maxLength\".\n\nSee https://ionicframework.com/docs/troubleshooting/runtime#accessing-this\nif you need to access `this` from within the callback.",
26359
26385
  "docsTags": [],
26360
26386
  "values": [
26361
26387
  {
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * (C) Ionic http://ionicframework.com - MIT License
3
3
  */
4
- import { i as initialize } from './ionic-global-c0cda98e.js';
4
+ import { i as initialize } from './ionic-global-1f99b929.js';
5
5
 
6
6
  const globalScripts = initialize;
7
7
 
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * (C) Ionic http://ionicframework.com - MIT License
3
3
  */
4
- import { w as writeTask } from './index-08d686eb.js';
4
+ import { w as writeTask } from './index-b7d870cf.js';
5
5
  import { h as hapticSelectionEnd, a as hapticSelectionStart, b as hapticSelectionChanged } from './haptic-554688a5.js';
6
6
  import { createGesture } from './index-2cf77112.js';
7
7