voyager-ionic-core 8.7.6 → 8.7.9

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 (251) hide show
  1. package/components/button.js +3 -7
  2. package/components/checkbox.js +4 -7
  3. package/components/header.js +42 -4
  4. package/components/index2.js +74 -3
  5. package/components/ion-accordion.js +93 -14
  6. package/components/ion-input.js +6 -14
  7. package/components/ion-select.js +58 -10
  8. package/components/ion-textarea.js +5 -13
  9. package/components/ion-toggle.js +4 -7
  10. package/components/{notch-controller.js → validity.js} +14 -1
  11. package/dist/cjs/{index-CD5Rjp23.js → index-094mMFB-.js} +76 -5
  12. package/dist/cjs/index.cjs.js +3 -3
  13. package/dist/cjs/ion-accordion_2.cjs.entry.js +91 -13
  14. package/dist/cjs/ion-app_8.cjs.entry.js +43 -5
  15. package/dist/cjs/ion-button_2.cjs.entry.js +3 -7
  16. package/dist/cjs/ion-checkbox.cjs.entry.js +4 -7
  17. package/dist/cjs/ion-input.cjs.entry.js +7 -15
  18. package/dist/cjs/ion-modal.cjs.entry.js +1 -1
  19. package/dist/cjs/ion-nav_2.cjs.entry.js +1 -1
  20. package/dist/cjs/ion-popover.cjs.entry.js +1 -1
  21. package/dist/cjs/ion-select_3.cjs.entry.js +56 -10
  22. package/dist/cjs/ion-textarea.cjs.entry.js +6 -14
  23. package/dist/cjs/ion-toggle.cjs.entry.js +4 -7
  24. package/dist/cjs/ionic.cjs.js +1 -1
  25. package/dist/cjs/{ios.transition-j9CclgEW.js → ios.transition-BOt_uW73.js} +1 -1
  26. package/dist/cjs/loader.cjs.js +1 -1
  27. package/dist/cjs/{md.transition-CwFyRSfv.js → md.transition-Dt968VXB.js} +1 -1
  28. package/dist/cjs/{notch-controller-Bzqhjm4f.js → validity-C8QoAYT2.js} +14 -0
  29. package/dist/collection/components/accordion/accordion.js +93 -14
  30. package/dist/collection/components/button/button.js +3 -7
  31. package/dist/collection/components/checkbox/checkbox.js +4 -7
  32. package/dist/collection/components/header/header.ios.css +27 -1
  33. package/dist/collection/components/header/header.js +5 -4
  34. package/dist/collection/components/header/header.utils.js +37 -0
  35. package/dist/collection/components/input/input.js +6 -14
  36. package/dist/collection/components/select/select.js +59 -11
  37. package/dist/collection/components/textarea/textarea.js +5 -13
  38. package/dist/collection/components/toggle/toggle.js +4 -7
  39. package/dist/collection/utils/forms/index.js +1 -0
  40. package/dist/collection/utils/forms/validity.js +15 -0
  41. package/dist/collection/utils/test/playwright/page/utils/spy-on-event.js +32 -0
  42. package/dist/collection/utils/transition/index.js +74 -3
  43. package/dist/docs.json +1 -1
  44. package/dist/esm/{index-D6G2seR8.js → index-r2D9DEro.js} +76 -5
  45. package/dist/esm/index.js +3 -3
  46. package/dist/esm/ion-accordion_2.entry.js +91 -13
  47. package/dist/esm/ion-app_8.entry.js +43 -5
  48. package/dist/esm/ion-button_2.entry.js +3 -7
  49. package/dist/esm/ion-checkbox.entry.js +4 -7
  50. package/dist/esm/ion-input.entry.js +6 -14
  51. package/dist/esm/ion-modal.entry.js +1 -1
  52. package/dist/esm/ion-nav_2.entry.js +1 -1
  53. package/dist/esm/ion-popover.entry.js +1 -1
  54. package/dist/esm/ion-select_3.entry.js +55 -9
  55. package/dist/esm/ion-textarea.entry.js +5 -13
  56. package/dist/esm/ion-toggle.entry.js +4 -7
  57. package/dist/esm/ionic.js +1 -1
  58. package/dist/esm/{ios.transition-Bpq9ixwv.js → ios.transition-BDzw0_Hm.js} +1 -1
  59. package/dist/esm/loader.js +1 -1
  60. package/dist/esm/{md.transition-zOA0oanq.js → md.transition-BzDYi3qq.js} +1 -1
  61. package/dist/esm/{notch-controller-BwelN_JM.js → validity-B8oWougr.js} +14 -1
  62. package/dist/ionic/index.esm.js +1 -1
  63. package/dist/ionic/ionic.esm.js +1 -1
  64. package/dist/ionic/p-43ed1ef5.entry.js +4 -0
  65. package/dist/ionic/p-4cc26913.entry.js +4 -0
  66. package/dist/ionic/{p-323421af.entry.js → p-5a39a99a.entry.js} +1 -1
  67. package/dist/ionic/p-5fb517e4.entry.js +4 -0
  68. package/dist/ionic/p-8bdfc8f6.entry.js +4 -0
  69. package/dist/ionic/{p-9a36e2e7.entry.js → p-95bddd49.entry.js} +1 -1
  70. package/dist/ionic/{p-DPhQmGJN.js → p-C7hRNDhM.js} +1 -1
  71. package/dist/ionic/p-DUt5fQmA.js +4 -0
  72. package/dist/ionic/{p-9R1XyICs.js → p-DZRJwG4S.js} +1 -1
  73. package/dist/ionic/{p-DCv9sLH2.js → p-DieJyvMP.js} +1 -1
  74. package/dist/ionic/p-d0a2a1ab.entry.js +4 -0
  75. package/dist/ionic/p-dc2e126d.entry.js +4 -0
  76. package/dist/ionic/{p-de7b5fa3.entry.js → p-e16b69e1.entry.js} +1 -1
  77. package/dist/ionic/p-f65f9308.entry.js +4 -0
  78. package/dist/ionic/p-fc278823.entry.js +4 -0
  79. package/dist/ionic/svg/checkbox-outline.svg +1 -0
  80. package/dist/ionic/svg/checkbox-sharp.svg +1 -0
  81. package/dist/ionic/svg/checkbox.svg +1 -0
  82. package/dist/ionic/svg/checkmark-circle-outline.svg +1 -0
  83. package/dist/ionic/svg/checkmark-circle-sharp.svg +1 -0
  84. package/dist/ionic/svg/checkmark-circle.svg +1 -0
  85. package/dist/ionic/svg/checkmark-done-circle-outline.svg +1 -0
  86. package/dist/ionic/svg/checkmark-done-circle-sharp.svg +1 -0
  87. package/dist/ionic/svg/checkmark-done-circle.svg +1 -0
  88. package/dist/ionic/svg/checkmark-done-outline.svg +1 -0
  89. package/dist/ionic/svg/checkmark-done-sharp.svg +1 -0
  90. package/dist/ionic/svg/checkmark-done.svg +1 -0
  91. package/dist/ionic/svg/checkmark-outline.svg +1 -0
  92. package/dist/ionic/svg/checkmark-sharp.svg +1 -0
  93. package/dist/ionic/svg/checkmark.svg +1 -0
  94. package/dist/ionic/svg/chevron-back-circle-outline.svg +1 -0
  95. package/dist/ionic/svg/chevron-back-circle-sharp.svg +1 -0
  96. package/dist/ionic/svg/chevron-back-circle.svg +1 -0
  97. package/dist/ionic/svg/chevron-back-outline.svg +1 -0
  98. package/dist/ionic/svg/chevron-back-sharp.svg +1 -0
  99. package/dist/ionic/svg/chevron-back.svg +1 -0
  100. package/dist/ionic/svg/chevron-collapse-outline.svg +1 -0
  101. package/dist/ionic/svg/chevron-collapse-sharp.svg +1 -0
  102. package/dist/ionic/svg/chevron-collapse.svg +1 -0
  103. package/dist/ionic/svg/chevron-down-circle-outline.svg +1 -0
  104. package/dist/ionic/svg/chevron-down-circle-sharp.svg +1 -0
  105. package/dist/ionic/svg/chevron-down-circle.svg +1 -0
  106. package/dist/ionic/svg/chevron-down-outline.svg +1 -0
  107. package/dist/ionic/svg/chevron-down-sharp.svg +1 -0
  108. package/dist/ionic/svg/chevron-down.svg +1 -0
  109. package/dist/ionic/svg/chevron-expand-outline.svg +1 -0
  110. package/dist/ionic/svg/chevron-expand-sharp.svg +1 -0
  111. package/dist/ionic/svg/chevron-expand.svg +1 -0
  112. package/dist/ionic/svg/chevron-forward-circle-outline.svg +1 -0
  113. package/dist/ionic/svg/chevron-forward-circle-sharp.svg +1 -0
  114. package/dist/ionic/svg/chevron-forward-circle.svg +1 -0
  115. package/dist/ionic/svg/chevron-forward-outline.svg +1 -0
  116. package/dist/ionic/svg/chevron-forward-sharp.svg +1 -0
  117. package/dist/ionic/svg/chevron-forward.svg +1 -0
  118. package/dist/ionic/svg/chevron-up-circle-outline.svg +1 -0
  119. package/dist/ionic/svg/chevron-up-circle-sharp.svg +1 -0
  120. package/dist/ionic/svg/chevron-up-circle.svg +1 -0
  121. package/dist/ionic/svg/chevron-up-outline.svg +1 -0
  122. package/dist/ionic/svg/chevron-up-sharp.svg +1 -0
  123. package/dist/ionic/svg/chevron-up.svg +1 -0
  124. package/dist/ionic/svg/clipboard-outline.svg +1 -0
  125. package/dist/ionic/svg/clipboard-sharp.svg +1 -0
  126. package/dist/ionic/svg/clipboard.svg +1 -0
  127. package/dist/ionic/svg/close-circle-outline.svg +1 -0
  128. package/dist/ionic/svg/close-circle-sharp.svg +1 -0
  129. package/dist/ionic/svg/close-circle.svg +1 -0
  130. package/dist/ionic/svg/close-outline.svg +1 -0
  131. package/dist/ionic/svg/close-sharp.svg +1 -0
  132. package/dist/ionic/svg/close.svg +1 -0
  133. package/dist/ionic/svg/cloud-circle-outline.svg +1 -0
  134. package/dist/ionic/svg/cloud-circle-sharp.svg +1 -0
  135. package/dist/ionic/svg/cloud-circle.svg +1 -0
  136. package/dist/ionic/svg/cloud-done-outline.svg +1 -0
  137. package/dist/ionic/svg/cloud-done-sharp.svg +1 -0
  138. package/dist/ionic/svg/cloud-done.svg +1 -0
  139. package/dist/ionic/svg/cloud-download-outline.svg +1 -0
  140. package/dist/ionic/svg/cloud-download-sharp.svg +1 -0
  141. package/dist/ionic/svg/cloud-download.svg +1 -0
  142. package/dist/ionic/svg/cloud-offline-outline.svg +1 -0
  143. package/dist/ionic/svg/cloud-offline-sharp.svg +1 -0
  144. package/dist/ionic/svg/cloud-offline.svg +1 -0
  145. package/dist/ionic/svg/cloud-outline.svg +1 -0
  146. package/dist/ionic/svg/cloud-sharp.svg +1 -0
  147. package/dist/ionic/svg/cloud-upload-outline.svg +1 -0
  148. package/dist/ionic/svg/cloud-upload-sharp.svg +1 -0
  149. package/dist/ionic/svg/cloud-upload.svg +1 -0
  150. package/dist/ionic/svg/cloud.svg +1 -0
  151. package/dist/ionic/svg/cloudy-night-outline.svg +1 -0
  152. package/dist/ionic/svg/cloudy-night-sharp.svg +1 -0
  153. package/dist/ionic/svg/cloudy-night.svg +1 -0
  154. package/dist/ionic/svg/cloudy-outline.svg +1 -0
  155. package/dist/ionic/svg/cloudy-sharp.svg +1 -0
  156. package/dist/ionic/svg/cloudy.svg +1 -0
  157. package/dist/ionic/svg/code-download-outline.svg +1 -0
  158. package/dist/ionic/svg/code-download-sharp.svg +1 -0
  159. package/dist/ionic/svg/code-download.svg +1 -0
  160. package/dist/ionic/svg/code-outline.svg +1 -0
  161. package/dist/ionic/svg/code-sharp.svg +1 -0
  162. package/dist/ionic/svg/code-slash-outline.svg +1 -0
  163. package/dist/ionic/svg/code-slash-sharp.svg +1 -0
  164. package/dist/ionic/svg/code-slash.svg +1 -0
  165. package/dist/ionic/svg/code-working-outline.svg +1 -0
  166. package/dist/ionic/svg/code-working-sharp.svg +1 -0
  167. package/dist/ionic/svg/code-working.svg +1 -0
  168. package/dist/ionic/svg/code.svg +1 -0
  169. package/dist/ionic/svg/cog-outline.svg +1 -0
  170. package/dist/ionic/svg/cog-sharp.svg +1 -0
  171. package/dist/ionic/svg/cog.svg +1 -0
  172. package/dist/ionic/svg/color-fill-outline.svg +1 -0
  173. package/dist/ionic/svg/color-fill-sharp.svg +1 -0
  174. package/dist/ionic/svg/color-fill.svg +1 -0
  175. package/dist/ionic/svg/color-filter-outline.svg +1 -0
  176. package/dist/ionic/svg/color-filter-sharp.svg +1 -0
  177. package/dist/ionic/svg/color-filter.svg +1 -0
  178. package/dist/ionic/svg/color-palette-outline.svg +1 -0
  179. package/dist/ionic/svg/color-palette-sharp.svg +1 -0
  180. package/dist/ionic/svg/color-palette.svg +1 -0
  181. package/dist/ionic/svg/color-wand-outline.svg +1 -0
  182. package/dist/ionic/svg/color-wand-sharp.svg +1 -0
  183. package/dist/ionic/svg/color-wand.svg +1 -0
  184. package/dist/ionic/svg/compass-outline.svg +1 -0
  185. package/dist/ionic/svg/compass-sharp.svg +1 -0
  186. package/dist/ionic/svg/compass.svg +1 -0
  187. package/dist/ionic/svg/construct-outline.svg +1 -0
  188. package/dist/ionic/svg/construct-sharp.svg +1 -0
  189. package/dist/ionic/svg/construct.svg +1 -0
  190. package/dist/ionic/svg/contract-outline.svg +1 -0
  191. package/dist/ionic/svg/contract-sharp.svg +1 -0
  192. package/dist/ionic/svg/contract.svg +1 -0
  193. package/dist/ionic/svg/contrast-outline.svg +1 -0
  194. package/dist/ionic/svg/contrast-sharp.svg +1 -0
  195. package/dist/ionic/svg/contrast.svg +1 -0
  196. package/dist/ionic/svg/copy-outline.svg +1 -0
  197. package/dist/ionic/svg/copy-sharp.svg +1 -0
  198. package/dist/ionic/svg/copy.svg +1 -0
  199. package/dist/ionic/svg/create-outline.svg +1 -0
  200. package/dist/ionic/svg/create-sharp.svg +1 -0
  201. package/dist/ionic/svg/create.svg +1 -0
  202. package/dist/ionic/svg/crop-outline.svg +1 -0
  203. package/dist/ionic/svg/crop-sharp.svg +1 -0
  204. package/dist/ionic/svg/crop.svg +1 -0
  205. package/dist/ionic/svg/cube-outline.svg +1 -0
  206. package/dist/ionic/svg/cube-sharp.svg +1 -0
  207. package/dist/ionic/svg/cube.svg +1 -0
  208. package/dist/ionic/svg/cut-outline.svg +1 -0
  209. package/dist/ionic/svg/cut-sharp.svg +1 -0
  210. package/dist/ionic/svg/cut.svg +1 -0
  211. package/dist/ionic/svg/desktop-outline.svg +1 -0
  212. package/dist/ionic/svg/desktop-sharp.svg +1 -0
  213. package/dist/ionic/svg/desktop.svg +1 -0
  214. package/dist/ionic/svg/diamond-outline.svg +1 -0
  215. package/dist/ionic/svg/diamond-sharp.svg +1 -0
  216. package/dist/ionic/svg/diamond.svg +1 -0
  217. package/dist/ionic/svg/dice-outline.svg +1 -0
  218. package/dist/ionic/svg/dice-sharp.svg +1 -0
  219. package/dist/ionic/svg/dice.svg +1 -0
  220. package/dist/ionic/svg/disc-outline.svg +1 -0
  221. package/dist/ionic/svg/disc-sharp.svg +1 -0
  222. package/dist/ionic/svg/disc.svg +1 -0
  223. package/dist/ionic/svg/document-attach-outline.svg +1 -0
  224. package/dist/ionic/svg/document-attach-sharp.svg +1 -0
  225. package/dist/ionic/svg/document-attach.svg +1 -0
  226. package/dist/ionic/svg/document-lock-outline.svg +1 -0
  227. package/dist/ionic/svg/document-lock-sharp.svg +1 -0
  228. package/dist/ionic/svg/document-lock.svg +1 -0
  229. package/dist/ionic/svg/document-outline.svg +1 -0
  230. package/dist/types/components/accordion/accordion.d.ts +18 -1
  231. package/dist/types/components/checkbox/checkbox.d.ts +0 -1
  232. package/dist/types/components/header/header.utils.d.ts +10 -0
  233. package/dist/types/components/input/input.d.ts +0 -4
  234. package/dist/types/components/select/select.d.ts +6 -0
  235. package/dist/types/components/textarea/textarea.d.ts +0 -4
  236. package/dist/types/components/toggle/toggle.d.ts +0 -1
  237. package/dist/types/utils/forms/index.d.ts +1 -0
  238. package/dist/types/utils/forms/validity.d.ts +10 -0
  239. package/dist/types/utils/transition/index.d.ts +9 -0
  240. package/hydrate/index.js +262 -73
  241. package/hydrate/index.mjs +262 -73
  242. package/package.json +3 -3
  243. package/dist/ionic/p-1c8a476d.entry.js +0 -4
  244. package/dist/ionic/p-3355a2ff.entry.js +0 -4
  245. package/dist/ionic/p-62e50f80.entry.js +0 -4
  246. package/dist/ionic/p-785026d7.entry.js +0 -4
  247. package/dist/ionic/p-78c74a3e.entry.js +0 -4
  248. package/dist/ionic/p-83fc84e7.entry.js +0 -4
  249. package/dist/ionic/p-913a7c1e.entry.js +0 -4
  250. package/dist/ionic/p-CMhMiYSX.js +0 -4
  251. package/dist/ionic/p-c17c0a01.entry.js +0 -4
@@ -14,7 +14,7 @@ var keyboardController = require('./keyboard-controller-GXBiBRKS.js');
14
14
  var cubicBezier = require('./cubic-bezier-DAjy1V-e.js');
15
15
  var frameworkDelegate = require('./framework-delegate-DMJRBuDi.js');
16
16
  var lockController = require('./lock-controller-aDB9wrEf.js');
17
- var index$2 = require('./index-CD5Rjp23.js');
17
+ var index$2 = require('./index-094mMFB-.js');
18
18
  require('./index-DkNv4J_i.js');
19
19
  require('./keyboard-UuAS4D_9.js');
20
20
  require('./capacitor-DmA66EwP.js');
@@ -710,6 +710,8 @@ Footer.style = {
710
710
  };
711
711
 
712
712
  const TRANSITION = 'all 0.2s ease-in-out';
713
+ const ROLE_NONE = 'none';
714
+ const ROLE_BANNER = 'banner';
713
715
  const cloneElement = (tagName) => {
714
716
  const getCachedEl = document.querySelector(`${tagName}.ion-cloned-element`);
715
717
  if (getCachedEl !== null) {
@@ -836,6 +838,7 @@ const setHeaderActive = (headerIndex, active = true) => {
836
838
  const toolbars = headerIndex.toolbars;
837
839
  const ionTitles = toolbars.map((toolbar) => toolbar.ionTitleEl);
838
840
  if (active) {
841
+ headerEl.setAttribute('role', ROLE_BANNER);
839
842
  headerEl.classList.remove('header-collapse-condense-inactive');
840
843
  ionTitles.forEach((ionTitle) => {
841
844
  if (ionTitle) {
@@ -844,6 +847,16 @@ const setHeaderActive = (headerIndex, active = true) => {
844
847
  });
845
848
  }
846
849
  else {
850
+ /**
851
+ * There can only be one banner landmark per page.
852
+ * By default, all ion-headers have the banner role.
853
+ * This causes an accessibility issue when using a
854
+ * condensed header since there are two ion-headers
855
+ * on the page at once (active and inactive).
856
+ * To solve this, the role needs to be toggled
857
+ * based on which header is active.
858
+ */
859
+ headerEl.setAttribute('role', ROLE_NONE);
847
860
  headerEl.classList.add('header-collapse-condense-inactive');
848
861
  /**
849
862
  * The small title should only be accessed by screen readers
@@ -903,8 +916,32 @@ const handleHeaderFade = (scrollEl, baseEl, condenseHeader) => {
903
916
  });
904
917
  });
905
918
  };
919
+ /**
920
+ * Get the role type for the ion-header.
921
+ *
922
+ * @param isInsideMenu If ion-header is inside ion-menu.
923
+ * @param isCondensed If ion-header has collapse="condense".
924
+ * @param mode The current mode.
925
+ * @returns 'none' if inside ion-menu or if condensed in md
926
+ * mode, otherwise 'banner'.
927
+ */
928
+ const getRoleType = (isInsideMenu, isCondensed, mode) => {
929
+ // If the header is inside a menu, it should not have the banner role.
930
+ if (isInsideMenu) {
931
+ return ROLE_NONE;
932
+ }
933
+ /**
934
+ * Only apply role="none" to `md` mode condensed headers
935
+ * since the large header is never shown.
936
+ */
937
+ if (isCondensed && mode === 'md') {
938
+ return ROLE_NONE;
939
+ }
940
+ // Default to banner role.
941
+ return ROLE_BANNER;
942
+ };
906
943
 
907
- const headerIosCss = "ion-header{display:block;position:relative;-ms-flex-order:-1;order:-1;width:100%;z-index:10}ion-header ion-toolbar:first-of-type{padding-top:var(--ion-safe-area-top, 0)}.header-ios ion-toolbar:last-of-type{--border-width:0 0 0.55px}@supports ((-webkit-backdrop-filter: blur(0)) or (backdrop-filter: blur(0))){.header-background{left:0;right:0;top:0;bottom:0;position:absolute;-webkit-backdrop-filter:saturate(180%) blur(20px);backdrop-filter:saturate(180%) blur(20px)}.header-translucent-ios ion-toolbar{--opacity:.8}.header-collapse-condense-inactive .header-background{-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px)}}.header-ios.ion-no-border ion-toolbar:last-of-type{--border-width:0}.header-collapse-fade ion-toolbar{--opacity-scale:inherit}.header-collapse-condense{z-index:9}.header-collapse-condense ion-toolbar{position:-webkit-sticky;position:sticky;top:0}.header-collapse-condense ion-toolbar:first-of-type{padding-top:0px;z-index:1}.header-collapse-condense ion-toolbar{--background:var(--ion-background-color, #fff);z-index:0}.header-collapse-condense ion-toolbar:last-of-type{--border-width:0px}.header-collapse-condense ion-toolbar ion-searchbar{padding-top:0px;padding-bottom:13px}.header-collapse-main{--opacity-scale:1}.header-collapse-main ion-toolbar{--opacity-scale:inherit}.header-collapse-main ion-toolbar.in-toolbar ion-title,.header-collapse-main ion-toolbar.in-toolbar ion-buttons{-webkit-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}.header-collapse-condense-inactive:not(.header-collapse-condense) ion-toolbar.in-toolbar ion-title,.header-collapse-condense-inactive:not(.header-collapse-condense) ion-toolbar.in-toolbar ion-buttons.buttons-collapse{opacity:0;pointer-events:none}.header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-title,.header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-buttons.buttons-collapse{visibility:hidden}ion-header.header-ios:not(.header-collapse-main):has(~ion-content ion-header.header-ios[collapse=condense],~ion-content ion-header.header-ios.header-collapse-condense){opacity:0}";
944
+ const headerIosCss = "ion-header{display:block;position:relative;-ms-flex-order:-1;order:-1;width:100%;z-index:10}ion-header ion-toolbar:first-of-type{padding-top:var(--ion-safe-area-top, 0)}.header-ios ion-toolbar:last-of-type{--border-width:0 0 0.55px}@supports ((-webkit-backdrop-filter: blur(0)) or (backdrop-filter: blur(0))){.header-background{left:0;right:0;top:0;bottom:0;position:absolute;-webkit-backdrop-filter:saturate(180%) blur(20px);backdrop-filter:saturate(180%) blur(20px)}.header-translucent-ios ion-toolbar{--opacity:.8}.header-collapse-condense-inactive .header-background{-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px)}}.header-ios.ion-no-border ion-toolbar:last-of-type{--border-width:0}.header-collapse-fade ion-toolbar{--opacity-scale:inherit}.header-collapse-fade.header-transitioning ion-toolbar{--background:transparent;--border-style:none}.header-collapse-condense{z-index:9}.header-collapse-condense ion-toolbar{position:-webkit-sticky;position:sticky;top:0}.header-collapse-condense ion-toolbar:first-of-type{padding-top:0px;z-index:1}.header-collapse-condense ion-toolbar{z-index:0}.header-collapse-condense ion-toolbar:last-of-type{--border-width:0px}.header-collapse-condense ion-toolbar ion-searchbar{padding-top:0px;padding-bottom:13px}.header-collapse-main{--opacity-scale:1}.header-collapse-main ion-toolbar{--opacity-scale:inherit}.header-collapse-main ion-toolbar.in-toolbar ion-title,.header-collapse-main ion-toolbar.in-toolbar ion-buttons{-webkit-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}.header-collapse-condense ion-toolbar,.header-collapse-condense-inactive.header-transitioning:not(.header-collapse-condense) ion-toolbar{--background:var(--ion-background-color, #fff)}.header-collapse-condense-inactive.header-transitioning:not(.header-collapse-condense) ion-toolbar{--border-style:none;--opacity-scale:1}.header-collapse-condense-inactive:not(.header-collapse-condense) ion-toolbar.in-toolbar ion-title,.header-collapse-condense-inactive:not(.header-collapse-condense) ion-toolbar.in-toolbar ion-buttons.buttons-collapse{opacity:0;pointer-events:none}.header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-title,.header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-buttons.buttons-collapse{visibility:hidden}ion-header.header-ios:not(.header-collapse-main):has(~ion-content ion-header.header-ios[collapse=condense],~ion-content ion-header.header-ios.header-collapse-condense){opacity:0}";
908
945
 
909
946
  const headerMdCss = "ion-header{display:block;position:relative;-ms-flex-order:-1;order:-1;width:100%;z-index:10}ion-header ion-toolbar:first-of-type{padding-top:var(--ion-safe-area-top, 0)}.header-md{-webkit-box-shadow:0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12);box-shadow:0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12)}.header-collapse-condense{display:none}.header-md.ion-no-border{-webkit-box-shadow:none;box-shadow:none}";
910
947
 
@@ -1044,16 +1081,17 @@ const Header = class {
1044
1081
  const { translucent, inheritedAttributes } = this;
1045
1082
  const mode = ionicGlobal.getIonMode(this);
1046
1083
  const collapse = this.collapse || 'none';
1084
+ const isCondensed = collapse === 'condense';
1047
1085
  // banner role must be at top level, so remove role if inside a menu
1048
- const roleType = theme.hostContext('ion-menu', this.el) ? 'none' : 'banner';
1049
- return (index.h(index.Host, Object.assign({ key: 'b6cc27f0b08afc9fcc889683525da765d80ba672', role: roleType, class: {
1086
+ const roleType = getRoleType(theme.hostContext('ion-menu', this.el), isCondensed, mode);
1087
+ return (index.h(index.Host, Object.assign({ key: '863c4568cd7b8c0ec55109f193bbbaed68a1346e', role: roleType, class: {
1050
1088
  [mode]: true,
1051
1089
  // Used internally for styling
1052
1090
  [`header-${mode}`]: true,
1053
1091
  [`header-translucent`]: this.translucent,
1054
1092
  [`header-collapse-${collapse}`]: true,
1055
1093
  [`header-translucent-${mode}`]: this.translucent,
1056
- } }, inheritedAttributes), mode === 'ios' && translucent && index.h("div", { key: '395766d4dcee3398bc91960db21f922095292f14', class: "header-background" }), index.h("slot", { key: '09a67ece27b258ff1248805d43d92a49b2c6859a' })));
1094
+ } }, inheritedAttributes), mode === 'ios' && translucent && index.h("div", { key: '25c3bdce328b0b35607d154c8b8374679313d881', class: "header-background" }), index.h("slot", { key: 'b44fab0a9be7920b9650da26117c783e751e1702' })));
1057
1095
  }
1058
1096
  get el() { return index.getElement(this); }
1059
1097
  };
@@ -215,11 +215,7 @@ const Button = class {
215
215
  target,
216
216
  };
217
217
  let fill = this.fill;
218
- /**
219
- * We check both undefined and null to
220
- * work around https://github.com/ionic-team/stencil/issues/3586.
221
- */
222
- if (fill == null) {
218
+ if (fill === undefined) {
223
219
  fill = this.inToolbar || this.inListHeader ? 'clear' : 'solid';
224
220
  }
225
221
  /**
@@ -232,7 +228,7 @@ const Button = class {
232
228
  {
233
229
  type !== 'button' && this.renderHiddenButton();
234
230
  }
235
- return (index.h(index.Host, { key: 'b105ad09215adb3ca2298acdadf0dc9154bbb9b0', onClick: this.handleClick, "aria-disabled": disabled ? 'true' : null, class: theme.createColorClasses(color, {
231
+ return (index.h(index.Host, { key: 'ed82ea53705523f9afc5f1a9addff44cc6424f27', onClick: this.handleClick, "aria-disabled": disabled ? 'true' : null, class: theme.createColorClasses(color, {
236
232
  [mode]: true,
237
233
  [buttonType]: true,
238
234
  [`${buttonType}-${expand}`]: expand !== undefined,
@@ -247,7 +243,7 @@ const Button = class {
247
243
  'button-disabled': disabled,
248
244
  'ion-activatable': true,
249
245
  'ion-focusable': true,
250
- }) }, index.h(TagType, Object.assign({ key: '66b4e7112bcb9e41d5a723fbbadb0a3104f9ee1d' }, attrs, { class: "button-native", part: "native", disabled: disabled, onFocus: this.onFocus, onBlur: this.onBlur }, inheritedAttributes), index.h("span", { key: '1439fc3da280221028dcf7ce8ec9dab273c4d4bb', class: "button-inner" }, index.h("slot", { key: 'd5269ae1afc87ec7b99746032f59cbae93720a9f', name: "icon-only", onSlotchange: this.slotChanged }), index.h("slot", { key: '461c83e97aa246aa86d83e14f1e15a288d35041e', name: "start" }), index.h("slot", { key: '807170d47101f9f6a333dd4ff489c89284f306fe' }), index.h("slot", { key: 'e67f116dd0349a0d27893e4f3ff0ccef1d402f80', name: "end" })), mode === 'md' && index.h("ion-ripple-effect", { key: '273f0bd9645a36c1bfd18a5c2ab4f81e22b7b989', type: this.rippleType }))));
246
+ }) }, index.h(TagType, Object.assign({ key: 'fadec13053469dd0405bbbc61b70ced568aa4826' }, attrs, { class: "button-native", part: "native", disabled: disabled, onFocus: this.onFocus, onBlur: this.onBlur }, inheritedAttributes), index.h("span", { key: '6bf0e5144fb1148002e88038522402b789689d2c', class: "button-inner" }, index.h("slot", { key: '25da0ca155cfa9e2754842c34f4fd09f576ac2d2', name: "icon-only", onSlotchange: this.slotChanged }), index.h("slot", { key: '51414065bb11953ec9d818f8d9353589bc9072c5', name: "start" }), index.h("slot", { key: 'c9b5f8842aeabd20628df2f4600f1257ea913d8d' }), index.h("slot", { key: '478dd3671c7be1909fc84e672f0fa8dfe6082263', name: "end" })), mode === 'md' && index.h("ion-ripple-effect", { key: 'e1d55f85a55144d743f58a5914cd116cb065fa8c', type: this.rippleType }))));
251
247
  }
252
248
  get el() { return index.getElement(this); }
253
249
  static get watchers() { return {
@@ -76,7 +76,6 @@ const Checkbox = class {
76
76
  };
77
77
  this.toggleChecked = (ev) => {
78
78
  ev.preventDefault();
79
- this.setFocus();
80
79
  this.setChecked(!this.checked);
81
80
  this.indeterminate = false;
82
81
  };
@@ -113,9 +112,7 @@ const Checkbox = class {
113
112
  }
114
113
  /** @internal */
115
114
  async setFocus() {
116
- if (this.focusEl) {
117
- this.focusEl.focus();
118
- }
115
+ this.el.focus();
119
116
  }
120
117
  getHintTextID() {
121
118
  const { el, helperText, errorText, helperTextId, errorTextId } = this;
@@ -151,7 +148,7 @@ const Checkbox = class {
151
148
  helpers.renderHiddenInput(true, el, name, checked ? value : '', disabled);
152
149
  // The host element must have a checkbox role to ensure proper VoiceOver
153
150
  // support in Safari for accessibility.
154
- return (index.h(index.Host, { key: '26cbe7220e555107200e9b5deeae754aa534a80b', role: "checkbox", "aria-checked": indeterminate ? 'mixed' : `${checked}`, "aria-describedby": this.getHintTextID(), "aria-invalid": this.getHintTextID() === this.errorTextId, "aria-labelledby": hasLabelContent ? this.inputLabelId : null, "aria-label": inheritedAttributes['aria-label'] || null, "aria-disabled": disabled ? 'true' : null, tabindex: disabled ? undefined : 0, onKeyDown: this.onKeyDown, class: theme.createColorClasses(color, {
151
+ return (index.h(index.Host, { key: 'ee2e02d28f9d15a1ec746609f7e9559444f621e5', role: "checkbox", "aria-checked": indeterminate ? 'mixed' : `${checked}`, "aria-describedby": this.getHintTextID(), "aria-invalid": this.getHintTextID() === this.errorTextId, "aria-labelledby": hasLabelContent ? this.inputLabelId : null, "aria-label": inheritedAttributes['aria-label'] || null, "aria-disabled": disabled ? 'true' : null, tabindex: disabled ? undefined : 0, onKeyDown: this.onKeyDown, onFocus: this.onFocus, onBlur: this.onBlur, onClick: this.onClick, class: theme.createColorClasses(color, {
155
152
  [mode]: true,
156
153
  'in-item': theme.hostContext('ion-item', el),
157
154
  'checkbox-checked': checked,
@@ -161,10 +158,10 @@ const Checkbox = class {
161
158
  [`checkbox-justify-${justify}`]: justify !== undefined,
162
159
  [`checkbox-alignment-${alignment}`]: alignment !== undefined,
163
160
  [`checkbox-label-placement-${labelPlacement}`]: true,
164
- }), onClick: this.onClick }, index.h("label", { key: 'f025cec5ff08e8be4487b9cc0324616ca5dfae2a', class: "checkbox-wrapper", htmlFor: inputId }, index.h("input", Object.assign({ key: 'dc53f7e4e240dc2e18556e6350df2b5c3169f553', type: "checkbox", checked: checked ? true : undefined, disabled: disabled, id: inputId, onChange: this.toggleChecked, onFocus: () => this.onFocus(), onBlur: () => this.onBlur(), ref: (focusEl) => (this.focusEl = focusEl), required: required }, inheritedAttributes)), index.h("div", { key: 'a625e9b50c3b617de8bbbfd624d772454fecaf2d', class: {
161
+ }) }, index.h("label", { key: '84d4c33da0348dc65ad36fb0fafd48be366dcf3b', class: "checkbox-wrapper", htmlFor: inputId }, index.h("input", Object.assign({ key: '427db69a3ab8a17aa0867519c90f585b8930406b', type: "checkbox", checked: checked ? true : undefined, disabled: disabled, id: inputId, onChange: this.toggleChecked, required: required }, inheritedAttributes)), index.h("div", { key: '9dda7024b3a4f1ee55351f783f9a10f9b4ad0d12', class: {
165
162
  'label-text-wrapper': true,
166
163
  'label-text-wrapper-hidden': !hasLabelContent,
167
- }, part: "label", id: this.inputLabelId, onClick: this.onDivLabelClick }, index.h("slot", { key: '87d1a90691327945f4343406706e4ab27f453844' }), this.renderHintText()), index.h("div", { key: 'b57fed8cdecee4df1ef0d57f157267ee77fac653', class: "native-wrapper" }, index.h("svg", { key: '13a8aac044d46dc99e3b60a1a643785511f216ac', class: "checkbox-icon", viewBox: "0 0 24 24", part: "container", "aria-hidden": "true" }, path)))));
164
+ }, part: "label", id: this.inputLabelId, onClick: this.onDivLabelClick }, index.h("slot", { key: 'f9d1d545ffd4164b650808241b51ea1bedc6a42c' }), this.renderHintText()), index.h("div", { key: 'a96d61ac324864228f14caa0e9f2c0d15418882e', class: "native-wrapper" }, index.h("svg", { key: '64ff3e4d87e190601811ef64323edec18d510cd1', class: "checkbox-icon", viewBox: "0 0 24 24", part: "container", "aria-hidden": "true" }, path)))));
168
165
  }
169
166
  getSVGPath(mode, indeterminate) {
170
167
  let path = indeterminate ? (index.h("path", { d: "M6 12L18 12", part: "mark" })) : (index.h("path", { d: "M5.9,12.5l3.8,3.8l8.8-8.8", part: "mark" }));
@@ -4,7 +4,7 @@
4
4
  'use strict';
5
5
 
6
6
  var index = require('./index-D6Wc6v08.js');
7
- var notchController = require('./notch-controller-Bzqhjm4f.js');
7
+ var validity = require('./validity-C8QoAYT2.js');
8
8
  var helpers = require('./helpers-DrTqNghc.js');
9
9
  var input_utils = require('./input.utils-B_QROI2g.js');
10
10
  var theme = require('./theme-CeDs6Hcv.js');
@@ -232,22 +232,14 @@ const Input = class {
232
232
  componentWillLoad() {
233
233
  this.inheritedAttributes = Object.assign(Object.assign({}, helpers.inheritAriaAttributes(this.el)), helpers.inheritAttributes(this.el, ['tabindex', 'title', 'data-form-type', 'dir']));
234
234
  }
235
- /**
236
- * Checks if the input is in an invalid state based on Ionic validation classes
237
- */
238
- checkInvalidState() {
239
- const hasIonTouched = this.el.classList.contains('ion-touched');
240
- const hasIonInvalid = this.el.classList.contains('ion-invalid');
241
- return hasIonTouched && hasIonInvalid;
242
- }
243
235
  connectedCallback() {
244
236
  const { el } = this;
245
237
  this.slotMutationController = input_utils.createSlotMutationController(el, ['label', 'start', 'end'], () => index.forceUpdate(this));
246
- this.notchController = notchController.createNotchController(el, () => this.notchSpacerEl, () => this.labelSlot);
238
+ this.notchController = validity.createNotchController(el, () => this.notchSpacerEl, () => this.labelSlot);
247
239
  // Watch for class changes to update validation state
248
240
  if (typeof MutationObserver !== 'undefined') {
249
241
  this.validationObserver = new MutationObserver(() => {
250
- const newIsInvalid = this.checkInvalidState();
242
+ const newIsInvalid = validity.checkInvalidState(el);
251
243
  if (this.isInvalid !== newIsInvalid) {
252
244
  this.isInvalid = newIsInvalid;
253
245
  // Force a re-render to update aria-describedby immediately
@@ -260,7 +252,7 @@ const Input = class {
260
252
  });
261
253
  }
262
254
  // Always set initial state
263
- this.isInvalid = this.checkInvalidState();
255
+ this.isInvalid = validity.checkInvalidState(el);
264
256
  this.debounceChanged();
265
257
  {
266
258
  document.dispatchEvent(new CustomEvent('ionInputDidLoad', {
@@ -524,7 +516,7 @@ const Input = class {
524
516
  * TODO(FW-5592): Remove hasStartEndSlots condition
525
517
  */
526
518
  const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
527
- return (index.h(index.Host, { key: '8a51f0300d5bc66392f9ab9a6fa0b5d388072a33', class: theme.createColorClasses(this.color, {
519
+ return (index.h(index.Host, { key: '97b5308021064d9e7434ef2d3d96f27045c1b0c4', class: theme.createColorClasses(this.color, {
528
520
  [mode]: true,
529
521
  'has-value': hasValue,
530
522
  'has-focus': hasFocus,
@@ -535,14 +527,14 @@ const Input = class {
535
527
  'in-item': inItem,
536
528
  'in-item-color': theme.hostContext('ion-item.ion-color', this.el),
537
529
  'input-disabled': disabled,
538
- }) }, index.h("label", { key: '9f8cf88d7d0e27931b51bd9c67f048c7fc6f5703', class: "input-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), index.h("div", { key: '7ad30bf9777774062a6ccf9a3ba804f251eef1bb', class: "native-wrapper", onClick: this.onLabelClick }, index.h("slot", { key: '8af0b0325d101df8eed7d24f2767d6ca4d307319', name: "start" }), index.h("input", Object.assign({ key: '1c53f7f9fa2567f3df19681cf4e7c21be382eae6', class: "native-input", ref: (input) => (this.nativeInput = input), id: inputId, disabled: disabled, autoCapitalize: this.autocapitalize, autoComplete: this.autocomplete, autoCorrect: this.autocorrect, autoFocus: this.autofocus, enterKeyHint: this.enterkeyhint, inputMode: this.inputmode, min: this.min, max: this.max, minLength: this.minlength, maxLength: this.maxlength, multiple: this.multiple, name: this.name, pattern: this.pattern, placeholder: this.placeholder || '', readOnly: readonly, required: this.required, spellcheck: this.spellcheck, step: this.step, type: this.type, value: value, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, onKeyDown: this.onKeydown, onCompositionstart: this.onCompositionStart, onCompositionend: this.onCompositionEnd, "aria-describedby": this.getHintTextID(), "aria-invalid": this.isInvalid ? 'true' : undefined }, this.inheritedAttributes)), this.clearInput && !readonly && !disabled && (index.h("button", { key: 'b081d0e1ec1444b4c9cca145fc9cd2ad4a68b3da', "aria-label": "reset", type: "button", class: "input-clear-icon", onPointerDown: (ev) => {
530
+ }) }, index.h("label", { key: '353f68726ce180299bd9adc81e5ff7d26a48f54f', class: "input-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), index.h("div", { key: '2034b4bad04fc157f3298a1805819216b6f439d0', class: "native-wrapper", onClick: this.onLabelClick }, index.h("slot", { key: '96bb5e30176b2bd76dfb75bfbf6c1c3d4403f4bb', name: "start" }), index.h("input", Object.assign({ key: '1a1d75b0e414a95c89d5a760757c33548d234aca', class: "native-input", ref: (input) => (this.nativeInput = input), id: inputId, disabled: disabled, autoCapitalize: this.autocapitalize, autoComplete: this.autocomplete, autoCorrect: this.autocorrect, autoFocus: this.autofocus, enterKeyHint: this.enterkeyhint, inputMode: this.inputmode, min: this.min, max: this.max, minLength: this.minlength, maxLength: this.maxlength, multiple: this.multiple, name: this.name, pattern: this.pattern, placeholder: this.placeholder || '', readOnly: readonly, required: this.required, spellcheck: this.spellcheck, step: this.step, type: this.type, value: value, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, onKeyDown: this.onKeydown, onCompositionstart: this.onCompositionStart, onCompositionend: this.onCompositionEnd, "aria-describedby": this.getHintTextID(), "aria-invalid": this.isInvalid ? 'true' : undefined }, this.inheritedAttributes)), this.clearInput && !readonly && !disabled && (index.h("button", { key: '95f3df17b7691d9a2e7dcd4a51f16a94aa3ca36f', "aria-label": "reset", type: "button", class: "input-clear-icon", onPointerDown: (ev) => {
539
531
  /**
540
532
  * This prevents mobile browsers from
541
533
  * blurring the input when the clear
542
534
  * button is activated.
543
535
  */
544
536
  ev.preventDefault();
545
- }, onClick: this.clearTextInput }, index.h("ion-icon", { key: '01535299241c3635460c05646420acf62a1ff567', "aria-hidden": "true", icon: clearIconData }))), index.h("slot", { key: '480f3eb58b08ae792866a5b9b4c068748c5567cc', name: "end" })), shouldRenderHighlight && index.h("div", { key: 'a8609cacee88e4a09f1cca65b6a47cb79a56f35e', class: "input-highlight" })), this.renderBottomContent()));
537
+ }, onClick: this.clearTextInput }, index.h("ion-icon", { key: '16b0af75eed50c8115fb5597f73b5fbf71c2530e', "aria-hidden": "true", icon: clearIconData }))), index.h("slot", { key: 'c48da0f8ddb3764ac43efa705bb4a6bb2d9cc2fd', name: "end" })), shouldRenderHighlight && index.h("div", { key: 'f15238481fc20de56ca7ecb6e350b3c024cc755e', class: "input-highlight" })), this.renderBottomContent()));
546
538
  }
547
539
  get el() { return index.getElement(this); }
548
540
  static get watchers() { return {
@@ -11,7 +11,7 @@ var lockController = require('./lock-controller-aDB9wrEf.js');
11
11
  var capacitor = require('./capacitor-DmA66EwP.js');
12
12
  var overlays = require('./overlays-DxIZwUXI.js');
13
13
  var theme = require('./theme-CeDs6Hcv.js');
14
- var index$4 = require('./index-CD5Rjp23.js');
14
+ var index$4 = require('./index-094mMFB-.js');
15
15
  var ionicGlobal = require('./ionic-global-HMVqOFGO.js');
16
16
  var keyboard = require('./keyboard-hHzlEQpk.js');
17
17
  var animation = require('./animation-Bt3H9L1C.js');
@@ -6,7 +6,7 @@
6
6
  var index = require('./index-D6Wc6v08.js');
7
7
  var cubicBezier = require('./cubic-bezier-DAjy1V-e.js');
8
8
  var helpers = require('./helpers-DrTqNghc.js');
9
- var index$1 = require('./index-CD5Rjp23.js');
9
+ var index$1 = require('./index-094mMFB-.js');
10
10
  var ionicGlobal = require('./ionic-global-HMVqOFGO.js');
11
11
  var frameworkDelegate = require('./framework-delegate-DMJRBuDi.js');
12
12
 
@@ -10,7 +10,7 @@ var helpers = require('./helpers-DrTqNghc.js');
10
10
  var lockController = require('./lock-controller-aDB9wrEf.js');
11
11
  var ionicGlobal = require('./ionic-global-HMVqOFGO.js');
12
12
  var theme = require('./theme-CeDs6Hcv.js');
13
- var index$1 = require('./index-CD5Rjp23.js');
13
+ var index$1 = require('./index-094mMFB-.js');
14
14
  var animation = require('./animation-Bt3H9L1C.js');
15
15
  require('./index-DkNv4J_i.js');
16
16
  require('./hardware-back-button-VCK4V3mG.js');
@@ -4,7 +4,7 @@
4
4
  'use strict';
5
5
 
6
6
  var index = require('./index-D6Wc6v08.js');
7
- var notchController = require('./notch-controller-Bzqhjm4f.js');
7
+ var validity = require('./validity-C8QoAYT2.js');
8
8
  var compareWithUtils = require('./compare-with-utils-DSicavqM.js');
9
9
  var helpers = require('./helpers-DrTqNghc.js');
10
10
  var overlays = require('./overlays-DxIZwUXI.js');
@@ -45,6 +45,10 @@ const Select = class {
45
45
  * is applied in both cases.
46
46
  */
47
47
  this.hasFocus = false;
48
+ /**
49
+ * Track validation state for proper aria-live announcements.
50
+ */
51
+ this.isInvalid = false;
48
52
  /**
49
53
  * The text to display on the cancel button.
50
54
  */
@@ -161,7 +165,7 @@ const Select = class {
161
165
  }
162
166
  async connectedCallback() {
163
167
  const { el } = this;
164
- this.notchController = notchController.createNotchController(el, () => this.notchSpacerEl, () => this.labelSlot);
168
+ this.notchController = validity.createNotchController(el, () => this.notchSpacerEl, () => this.labelSlot);
165
169
  this.updateOverlayOptions();
166
170
  this.emitStyle();
167
171
  this.mutationO = watchOptions.watchForOptions(this.el, 'ion-select-option', async () => {
@@ -174,9 +178,46 @@ const Select = class {
174
178
  */
175
179
  index.forceUpdate(this);
176
180
  });
181
+ // Watch for class changes to update validation state.
182
+ if (typeof MutationObserver !== 'undefined') {
183
+ this.validationObserver = new MutationObserver(() => {
184
+ const newIsInvalid = validity.checkInvalidState(this.el);
185
+ if (this.isInvalid !== newIsInvalid) {
186
+ this.isInvalid = newIsInvalid;
187
+ /**
188
+ * Screen readers tend to announce changes
189
+ * to `aria-describedby` when the attribute
190
+ * is changed during a blur event for a
191
+ * native form control.
192
+ * However, the announcement can be spotty
193
+ * when using a non-native form control
194
+ * and `forceUpdate()`.
195
+ * This is due to `forceUpdate()` internally
196
+ * rescheduling the DOM update to a lower
197
+ * priority queue regardless if it's called
198
+ * inside a Promise or not, thus causing
199
+ * the screen reader to potentially miss the
200
+ * change.
201
+ * By using a State variable inside a Promise,
202
+ * it guarantees a re-render immediately at
203
+ * a higher priority.
204
+ */
205
+ Promise.resolve().then(() => {
206
+ this.hintTextID = this.getHintTextID();
207
+ });
208
+ }
209
+ });
210
+ this.validationObserver.observe(el, {
211
+ attributes: true,
212
+ attributeFilter: ['class'],
213
+ });
214
+ }
215
+ // Always set initial state
216
+ this.isInvalid = validity.checkInvalidState(this.el);
177
217
  }
178
218
  componentWillLoad() {
179
219
  this.inheritedAttributes = helpers.inheritAttributes(this.el, ['aria-label']);
220
+ this.hintTextID = this.getHintTextID();
180
221
  }
181
222
  componentDidLoad() {
182
223
  /**
@@ -200,6 +241,11 @@ const Select = class {
200
241
  this.notchController.destroy();
201
242
  this.notchController = undefined;
202
243
  }
244
+ // Clean up validation observer to prevent memory leaks.
245
+ if (this.validationObserver) {
246
+ this.validationObserver.disconnect();
247
+ this.validationObserver = undefined;
248
+ }
203
249
  }
204
250
  /**
205
251
  * Open the select overlay. The overlay is either an alert, action sheet, or popover,
@@ -670,11 +716,11 @@ const Select = class {
670
716
  }
671
717
  renderListbox() {
672
718
  const { disabled, inputId, isExpanded, required } = this;
673
- return (index.h("button", { disabled: disabled, id: inputId, "aria-label": this.ariaLabel, "aria-haspopup": "dialog", "aria-expanded": `${isExpanded}`, "aria-describedby": this.getHintTextID(), "aria-invalid": this.getHintTextID() === this.errorTextId, "aria-required": `${required}`, onFocus: this.onFocus, onBlur: this.onBlur, ref: (focusEl) => (this.focusEl = focusEl) }));
719
+ return (index.h("button", { disabled: disabled, id: inputId, "aria-label": this.ariaLabel, "aria-haspopup": "dialog", "aria-expanded": `${isExpanded}`, "aria-describedby": this.hintTextID, "aria-invalid": this.isInvalid ? 'true' : undefined, "aria-required": `${required}`, onFocus: this.onFocus, onBlur: this.onBlur, ref: (focusEl) => (this.focusEl = focusEl) }));
674
720
  }
675
721
  getHintTextID() {
676
- const { el, helperText, errorText, helperTextId, errorTextId } = this;
677
- if (el.classList.contains('ion-touched') && el.classList.contains('ion-invalid') && errorText) {
722
+ const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
723
+ if (isInvalid && errorText) {
678
724
  return errorTextId;
679
725
  }
680
726
  if (helperText) {
@@ -686,10 +732,10 @@ const Select = class {
686
732
  * Renders the helper text or error text values
687
733
  */
688
734
  renderHintText() {
689
- const { helperText, errorText, helperTextId, errorTextId } = this;
735
+ const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
690
736
  return [
691
- index.h("div", { id: helperTextId, class: "helper-text", part: "supporting-text helper-text" }, helperText),
692
- index.h("div", { id: errorTextId, class: "error-text", part: "supporting-text error-text" }, errorText),
737
+ index.h("div", { id: helperTextId, class: "helper-text", part: "supporting-text helper-text", "aria-live": "polite" }, !isInvalid ? helperText : null),
738
+ index.h("div", { id: errorTextId, class: "error-text", part: "supporting-text error-text", role: "alert" }, isInvalid ? errorText : null),
693
739
  ];
694
740
  }
695
741
  /**
@@ -737,7 +783,7 @@ const Select = class {
737
783
  * TODO(FW-5592): Remove hasStartEndSlots condition
738
784
  */
739
785
  const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || isExpanded || hasStartEndSlots));
740
- return (index.h(index.Host, { key: 'c03fb65e8fc9f9aab295e07b282377d57d910519', onClick: this.onClick, class: theme.createColorClasses(this.color, {
786
+ return (index.h(index.Host, { key: '35b5e18e6f79a802ff2d46d1242e80ff755cc0b9', onClick: this.onClick, class: theme.createColorClasses(this.color, {
741
787
  [mode]: true,
742
788
  'in-item': inItem,
743
789
  'in-item-color': theme.hostContext('ion-item.ion-color', el),
@@ -755,7 +801,7 @@ const Select = class {
755
801
  [`select-justify-${justify}`]: justifyEnabled,
756
802
  [`select-shape-${shape}`]: shape !== undefined,
757
803
  [`select-label-placement-${labelPlacement}`]: true,
758
- }) }, index.h("label", { key: '0d0c8ec55269adcac625f2899a547f4e7f3e3741', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick }, this.renderLabelContainer(), index.h("div", { key: 'f6dfc93c0e23cbe75a2947abde67d842db2dad78', class: "select-wrapper-inner" }, index.h("slot", { key: '957bfadf9f101f519091419a362d3abdc2be66f6', name: "start" }), index.h("div", { key: 'ca349202a484e7f2e884533fd330f0b136754f7d', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox()), index.h("slot", { key: 'f0e62a6533ff1c8f62bd2d27f60b23385c4fa9ed', name: "end" }), !hasFloatingOrStackedLabel && this.renderSelectIcon()), hasFloatingOrStackedLabel && this.renderSelectIcon(), shouldRenderHighlight && index.h("div", { key: 'fb840d46bafafb09898ebeebbe8c181906a3d8a2', class: "select-highlight" })), this.renderBottomContent()));
804
+ }) }, index.h("label", { key: '6005b34a0c50bc4d7653a4276bc232ecd02e083c', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick }, this.renderLabelContainer(), index.h("div", { key: 'c7e07aa81ae856c057f16275dd058f37c5670a47', class: "select-wrapper-inner" }, index.h("slot", { key: '7fc2deefe0424404caacdbbd9e08ed43ba55d28a', name: "start" }), index.h("div", { key: '157d74ee717b1bc30b5f1c233a09b0c8456aa68e', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox()), index.h("slot", { key: 'ea66db304528b82bf9317730b6dce3db2612f235', name: "end" }), !hasFloatingOrStackedLabel && this.renderSelectIcon()), hasFloatingOrStackedLabel && this.renderSelectIcon(), shouldRenderHighlight && index.h("div", { key: '786eb1530b7476f0615d4e7c0bf4e7e4dc66509c', class: "select-highlight" })), this.renderBottomContent()));
759
805
  }
760
806
  get el() { return index.getElement(this); }
761
807
  static get watchers() { return {
@@ -4,7 +4,7 @@
4
4
  'use strict';
5
5
 
6
6
  var index = require('./index-D6Wc6v08.js');
7
- var notchController = require('./notch-controller-Bzqhjm4f.js');
7
+ var validity = require('./validity-C8QoAYT2.js');
8
8
  var helpers = require('./helpers-DrTqNghc.js');
9
9
  var input_utils = require('./input.utils-B_QROI2g.js');
10
10
  var theme = require('./theme-CeDs6Hcv.js');
@@ -192,22 +192,14 @@ const Textarea = class {
192
192
  this.el.click();
193
193
  }
194
194
  }
195
- /**
196
- * Checks if the textarea is in an invalid state based on Ionic validation classes
197
- */
198
- checkValidationState() {
199
- const hasIonTouched = this.el.classList.contains('ion-touched');
200
- const hasIonInvalid = this.el.classList.contains('ion-invalid');
201
- return hasIonTouched && hasIonInvalid;
202
- }
203
195
  connectedCallback() {
204
196
  const { el } = this;
205
197
  this.slotMutationController = input_utils.createSlotMutationController(el, ['label', 'start', 'end'], () => index.forceUpdate(this));
206
- this.notchController = notchController.createNotchController(el, () => this.notchSpacerEl, () => this.labelSlot);
198
+ this.notchController = validity.createNotchController(el, () => this.notchSpacerEl, () => this.labelSlot);
207
199
  // Watch for class changes to update validation state
208
200
  if (typeof MutationObserver !== 'undefined') {
209
201
  this.validationObserver = new MutationObserver(() => {
210
- const newIsInvalid = this.checkValidationState();
202
+ const newIsInvalid = validity.checkInvalidState(this.el);
211
203
  if (this.isInvalid !== newIsInvalid) {
212
204
  this.isInvalid = newIsInvalid;
213
205
  // Force a re-render to update aria-describedby immediately
@@ -220,7 +212,7 @@ const Textarea = class {
220
212
  });
221
213
  }
222
214
  // Always set initial state
223
- this.isInvalid = this.checkValidationState();
215
+ this.isInvalid = validity.checkInvalidState(this.el);
224
216
  this.debounceChanged();
225
217
  {
226
218
  document.dispatchEvent(new CustomEvent('ionInputDidLoad', {
@@ -484,7 +476,7 @@ const Textarea = class {
484
476
  * TODO(FW-5592): Remove hasStartEndSlots condition
485
477
  */
486
478
  const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
487
- return (index.h(index.Host, { key: '26b46666a92b3f652775bb1c46661f9a30392104', class: theme.createColorClasses(this.color, {
479
+ return (index.h(index.Host, { key: 'a70a62d7aae3831a50acd74f60b930925ada1326', class: theme.createColorClasses(this.color, {
488
480
  [mode]: true,
489
481
  'has-value': hasValue,
490
482
  'has-focus': hasFocus,
@@ -493,7 +485,7 @@ const Textarea = class {
493
485
  [`textarea-shape-${shape}`]: shape !== undefined,
494
486
  [`textarea-label-placement-${labelPlacement}`]: true,
495
487
  'textarea-disabled': disabled,
496
- }) }, index.h("label", { key: '2649da816216959ebe1f34cafd9dedbac20ec3c2', class: "textarea-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), index.h("div", { key: 'dca98593efece1b044dbcda045fa70882d715cb2', class: "textarea-wrapper-inner" }, index.h("div", { key: '2019daf87fddca5ec0b2e336f0376fd9642bae1b', class: "start-slot-wrapper" }, index.h("slot", { key: '36c423c394a71d08261705b9d6729e756bf65924', name: "start" })), index.h("div", { key: '0c3ea34105c7eddfa4094371c5d288c50ed10db3', class: "native-wrapper", ref: (el) => (this.textareaWrapper = el) }, index.h("textarea", Object.assign({ key: 'ce173b83b16aff43d293fa1edef9b66c6676227b', class: "native-textarea", ref: (el) => (this.nativeInput = el), id: inputId, disabled: disabled, autoCapitalize: this.autocapitalize, autoFocus: this.autofocus, enterKeyHint: this.enterkeyhint, inputMode: this.inputmode, minLength: this.minlength, maxLength: this.maxlength, name: this.name, placeholder: this.placeholder || '', readOnly: this.readonly, required: this.required, spellcheck: this.spellcheck, cols: this.cols, rows: this.rows, wrap: this.wrap, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, onKeyDown: this.onKeyDown, "aria-describedby": this.getHintTextID(), "aria-invalid": this.isInvalid ? 'true' : undefined }, this.inheritedAttributes), value)), index.h("div", { key: '756e343cfd208bb5ad9ecf08d77cbb0a9606dc7b', class: "end-slot-wrapper" }, index.h("slot", { key: '0eb596814a037fa4634ff8c5bac0045540edfe21', name: "end" }))), shouldRenderHighlight && index.h("div", { key: 'df62f896eb6e0e2d1217aa487c198eb82a52bcb8', class: "textarea-highlight" })), this.renderBottomContent()));
488
+ }) }, index.h("label", { key: '8a2dd59a60f7469df84018eb0ede3a9ec3862703', class: "textarea-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), index.h("div", { key: '1bfc368236e3da7a225a45118c27fbfc1fe5fa46', class: "textarea-wrapper-inner" }, index.h("div", { key: '215cbb2635ff52e31a8973376989b85e7245d40f', class: "start-slot-wrapper" }, index.h("slot", { key: '9f6b461cdee9d629deb695d2bea054ece2f32305', name: "start" })), index.h("div", { key: 'c1af35a2d5bc452bebe0b22a26d15ff52b4e9fc8', class: "native-wrapper", ref: (el) => (this.textareaWrapper = el) }, index.h("textarea", Object.assign({ key: '69a69b3cf0932baafbe37e6e846f1a571608d3f2', class: "native-textarea", ref: (el) => (this.nativeInput = el), id: inputId, disabled: disabled, autoCapitalize: this.autocapitalize, autoFocus: this.autofocus, enterKeyHint: this.enterkeyhint, inputMode: this.inputmode, minLength: this.minlength, maxLength: this.maxlength, name: this.name, placeholder: this.placeholder || '', readOnly: this.readonly, required: this.required, spellcheck: this.spellcheck, cols: this.cols, rows: this.rows, wrap: this.wrap, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, onKeyDown: this.onKeyDown, "aria-describedby": this.getHintTextID(), "aria-invalid": this.isInvalid ? 'true' : undefined }, this.inheritedAttributes), value)), index.h("div", { key: 'c053ea8b865d0e29763aed2e4939cc9c9e374c15', class: "end-slot-wrapper" }, index.h("slot", { key: '930aa641833b0df54b9ea10368fc2f46d5f491f6', name: "end" }))), shouldRenderHighlight && index.h("div", { key: '8d12597d15f5f429d80e8272ea99e64ed924e482', class: "textarea-highlight" })), this.renderBottomContent()));
497
489
  }
498
490
  get el() { return index.getElement(this); }
499
491
  static get watchers() { return {
@@ -138,7 +138,6 @@ const Toggle = class {
138
138
  const { checked, value } = this;
139
139
  const isNowChecked = !checked;
140
140
  this.checked = isNowChecked;
141
- this.setFocus();
142
141
  this.ionChange.emit({
143
142
  checked: isNowChecked,
144
143
  value,
@@ -189,9 +188,7 @@ const Toggle = class {
189
188
  return this.value || '';
190
189
  }
191
190
  setFocus() {
192
- if (this.focusEl) {
193
- this.focusEl.focus();
194
- }
191
+ this.el.focus();
195
192
  }
196
193
  renderOnOffSwitchLabels(mode, checked) {
197
194
  const icon = this.getSwitchLabelIcon(mode, checked);
@@ -241,7 +238,7 @@ const Toggle = class {
241
238
  const value = this.getValue();
242
239
  const rtl = dir.isRTL(el) ? 'rtl' : 'ltr';
243
240
  helpers.renderHiddenInput(true, el, name, checked ? value : '', disabled);
244
- return (index.h(index.Host, { key: '21037ea2e8326f58c84becadde475f007f931924', role: "switch", "aria-checked": `${checked}`, "aria-describedby": this.getHintTextID(), "aria-invalid": this.getHintTextID() === errorTextId, onClick: this.onClick, "aria-labelledby": hasLabel ? inputLabelId : null, "aria-label": inheritedAttributes['aria-label'] || null, "aria-disabled": disabled ? 'true' : null, tabindex: disabled ? undefined : 0, onKeyDown: this.onKeyDown, class: theme.createColorClasses(color, {
241
+ return (index.h(index.Host, { key: '17bbbc8d229868e5c872b2bc5a3faf579780c5e0', role: "switch", "aria-checked": `${checked}`, "aria-describedby": this.getHintTextID(), "aria-invalid": this.getHintTextID() === errorTextId, onClick: this.onClick, "aria-labelledby": hasLabel ? inputLabelId : null, "aria-label": inheritedAttributes['aria-label'] || null, "aria-disabled": disabled ? 'true' : null, tabindex: disabled ? undefined : 0, onKeyDown: this.onKeyDown, onFocus: this.onFocus, onBlur: this.onBlur, class: theme.createColorClasses(color, {
245
242
  [mode]: true,
246
243
  'in-item': theme.hostContext('ion-item', el),
247
244
  'toggle-activated': activated,
@@ -251,10 +248,10 @@ const Toggle = class {
251
248
  [`toggle-alignment-${alignment}`]: alignment !== undefined,
252
249
  [`toggle-label-placement-${labelPlacement}`]: true,
253
250
  [`toggle-${rtl}`]: true,
254
- }) }, index.h("label", { key: '4d153679d118d01286f6633d1c19558a97745ff6', class: "toggle-wrapper", htmlFor: inputId }, index.h("input", Object.assign({ key: '0dfcd4df15b8d41bec5ff5f8912503afbb7bec53', type: "checkbox", role: "switch", "aria-checked": `${checked}`, checked: checked, disabled: disabled, id: inputId, onFocus: () => this.onFocus(), onBlur: () => this.onBlur(), ref: (focusEl) => (this.focusEl = focusEl), required: required }, inheritedAttributes)), index.h("div", { key: 'ffed3a07ba2ab70e5b232e6041bc3b6b34be8331', class: {
251
+ }) }, index.h("label", { key: '673625b62a2c909e95dccb642c91312967a6cd1c', class: "toggle-wrapper", htmlFor: inputId }, index.h("input", Object.assign({ key: '7dc3f357b4708116663970047765da9f8f845bf0', type: "checkbox", role: "switch", "aria-checked": `${checked}`, checked: checked, disabled: disabled, id: inputId, required: required }, inheritedAttributes)), index.h("div", { key: '8f1c6a182031e8cbc6727e5f4ac0e00ad4247447', class: {
255
252
  'label-text-wrapper': true,
256
253
  'label-text-wrapper-hidden': !hasLabel,
257
- }, part: "label", id: inputLabelId, onClick: this.onDivLabelClick }, index.h("slot", { key: 'd88e1e3dcdd8293f6b61f237cd7a0511dcbce300' }), this.renderHintText()), index.h("div", { key: '0e924225f5f0caf3c88738acb6c557bd8c1b68f6', class: "native-wrapper" }, this.renderToggleControl()))));
254
+ }, part: "label", id: inputLabelId, onClick: this.onDivLabelClick }, index.h("slot", { key: '8322b9d54dc7edeb4e16fefcde9f7ebca8d5c3e1' }), this.renderHintText()), index.h("div", { key: 'fe6984143db817a7b3020a3f57cf5418fc3dcc0e', class: "native-wrapper" }, this.renderToggleControl()))));
258
255
  }
259
256
  get el() { return index.getElement(this); }
260
257
  static get watchers() { return {