@ionic/core 8.7.16-dev.11769623699.1fe289a4 → 8.7.16-dev.11770318223.1177a6ea
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.
- package/components/button.js +20 -15
- package/components/checkbox.js +3 -3
- package/components/content.js +3 -3
- package/components/header.js +2 -2
- package/components/helpers.js +18 -4
- package/components/ion-card-content.js +7 -8
- package/components/ion-card-header.js +2 -2
- package/components/ion-card-subtitle.js +2 -2
- package/components/ion-card-title.js +2 -2
- package/components/ion-chip.js +2 -2
- package/components/ion-col.js +2 -2
- package/components/ion-datetime-button.js +2 -2
- package/components/ion-datetime.js +11 -17
- package/components/ion-divider.js +2 -2
- package/components/ion-fab-button.js +2 -2
- package/components/ion-fab-list.js +2 -2
- package/components/ion-fab.js +2 -2
- package/components/ion-footer.js +2 -2
- package/components/ion-grid.js +2 -2
- package/components/ion-img.js +2 -2
- package/components/ion-infinite-scroll-content.js +2 -2
- package/components/ion-infinite-scroll.js +1 -1
- package/components/ion-input-otp.js +62 -7
- package/components/ion-input-password-toggle.js +3 -3
- package/components/ion-input.js +4 -4
- package/components/ion-item-divider.js +2 -2
- package/components/ion-item-group.js +1 -1
- package/components/ion-item-option.js +2 -2
- package/components/ion-item-options.js +1 -1
- package/components/ion-item-sliding.js +1 -1
- package/components/ion-loading.js +2 -2
- package/components/ion-menu-button.js +2 -2
- package/components/ion-menu-toggle.js +2 -2
- package/components/ion-menu.js +2 -2
- package/components/ion-nav-link.js +1 -1
- package/components/ion-nav.js +1 -1
- package/components/ion-note.js +2 -2
- package/components/ion-picker-legacy.js +2 -2
- package/components/ion-progress-bar.js +1 -1
- package/components/ion-range.js +3 -3
- package/components/ion-refresher-content.js +2 -2
- package/components/ion-refresher.js +1 -1
- package/components/ion-reorder-group.js +1 -1
- package/components/ion-reorder.js +2 -2
- package/components/ion-router-link.js +2 -2
- package/components/ion-router-outlet.js +1 -1
- package/components/ion-row.js +2 -2
- package/components/ion-searchbar.js +4 -4
- package/components/ion-segment-button.js +2 -2
- package/components/ion-segment-content.js +1 -1
- package/components/ion-segment-view.js +2 -2
- package/components/ion-segment.js +2 -2
- package/components/ion-select-option.js +1 -1
- package/components/ion-select.js +3 -3
- package/components/ion-skeleton-text.js +2 -2
- package/components/ion-split-pane.js +2 -2
- package/components/ion-tab-bar.js +2 -2
- package/components/ion-tab-button.js +2 -2
- package/components/ion-tab.js +2 -2
- package/components/ion-tabs.js +1 -1
- package/components/ion-text.js +2 -2
- package/components/ion-textarea.js +81 -14
- package/components/ion-thumbnail.js +2 -2
- package/components/ion-toast.js +2 -2
- package/components/ion-toggle.js +3 -3
- package/components/label.js +2 -2
- package/components/list-header.js +2 -2
- package/components/list.js +1 -1
- package/components/modal.js +4 -4
- package/components/overlays.js +93 -2
- package/components/picker-column-option.js +2 -2
- package/components/picker-column.js +3 -3
- package/components/picker-column2.js +2 -2
- package/components/picker.js +2 -2
- package/components/popover.js +2 -2
- package/components/radio-group.js +2 -2
- package/components/radio.js +3 -3
- package/components/ripple-effect.js +1 -1
- package/components/select-modal.js +1 -1
- package/components/select-popover.js +2 -2
- package/components/spinner.js +1 -1
- package/components/theme.js +25 -1
- package/components/title.js +2 -2
- package/components/toolbar.js +2 -2
- package/components/validity.js +32 -1
- package/css/core.css +1 -1
- package/css/core.css.map +1 -1
- package/css/ionic/bundle.ionic.css +1 -1
- package/css/ionic/bundle.ionic.css.map +1 -1
- package/css/ionic/core.ionic.css +1 -1
- package/css/ionic/core.ionic.css.map +1 -1
- package/css/ionic.bundle.css +1 -1
- package/css/ionic.bundle.css.map +1 -1
- package/dist/cjs/{animation-CD5nuON9.js → animation-C04i0Aq2.js} +2 -2
- package/dist/cjs/{app-globals-CoW5jvJu.js → app-globals-BP1XPbBb.js} +1 -1
- package/dist/cjs/{button-active-Dxyabn6T.js → button-active-B9D1nnqS.js} +2 -2
- package/dist/cjs/{capacitor-C8raJ_tU.js → capacitor-CbwHRb4L.js} +1 -1
- package/dist/cjs/{config-C5fsO43a.js → config-CPCkFfH2.js} +1 -1
- package/dist/cjs/{data-MoL8Ckx5.js → data-BpYscHnl.js} +1 -1
- package/dist/cjs/{framework-delegate-Bwdk9vFS.js → framework-delegate-C7fZ8bup.js} +2 -2
- package/dist/cjs/{haptic-BU6_qLwg.js → haptic-CYmISoOJ.js} +1 -1
- package/dist/cjs/{helpers-DnouLczu.js → helpers-DF1tCuxf.js} +19 -5
- package/dist/cjs/{index-C4_FN9N0.js → index-B2l1iL59.js} +4 -4
- package/dist/cjs/{index-JtyffOXl.js → index-BVcv37_B.js} +4 -4
- package/dist/cjs/{index-CADY2xEW.js → index-BioRZa_4.js} +3 -3
- package/dist/cjs/{index-DUoP_H1L.js → index-C2sRwpb7.js} +2 -2
- package/dist/cjs/{index-D6Wc6v08.js → index-DjlJwy91.js} +41 -4
- package/dist/cjs/index.cjs.js +12 -12
- package/dist/cjs/{input-shims-C-YCyXjg.js → input-shims-BYRSBwuG.js} +6 -6
- package/dist/cjs/{input.utils-C3-BwdV0.js → input.utils-BBh_FWGy.js} +3 -3
- package/dist/cjs/ion-accordion_2.cjs.entry.js +4 -4
- package/dist/cjs/ion-action-sheet.cjs.entry.js +10 -10
- package/dist/cjs/ion-alert.cjs.entry.js +11 -11
- package/dist/cjs/ion-app_8.cjs.entry.js +23 -23
- package/dist/cjs/ion-avatar_3.cjs.entry.js +5 -5
- package/dist/cjs/ion-back-button.cjs.entry.js +4 -4
- package/dist/cjs/ion-backdrop.cjs.entry.js +2 -2
- package/dist/cjs/ion-breadcrumb_2.cjs.entry.js +4 -4
- package/dist/cjs/ion-button_2.cjs.entry.js +23 -18
- package/dist/cjs/ion-card_5.cjs.entry.js +15 -17
- package/dist/cjs/ion-checkbox.cjs.entry.js +8 -8
- package/dist/cjs/ion-chip.cjs.entry.js +5 -5
- package/dist/cjs/ion-col_3.cjs.entry.js +8 -8
- package/dist/cjs/ion-datetime-button.cjs.entry.js +7 -7
- package/dist/cjs/ion-datetime_3.cjs.entry.js +21 -21
- package/dist/cjs/ion-divider.cjs.entry.js +4 -4
- package/dist/cjs/ion-fab_3.cjs.entry.js +10 -10
- package/dist/cjs/ion-img.cjs.entry.js +5 -5
- package/dist/cjs/ion-infinite-scroll_2.cjs.entry.js +8 -8
- package/dist/cjs/ion-input-otp.cjs.entry.js +69 -10
- package/dist/cjs/ion-input-password-toggle.cjs.entry.js +6 -6
- package/dist/cjs/ion-input.cjs.entry.js +11 -11
- package/dist/cjs/ion-item-option_3.cjs.entry.js +9 -9
- package/dist/cjs/ion-item_8.cjs.entry.js +16 -16
- package/dist/cjs/ion-loading.cjs.entry.js +10 -10
- package/dist/cjs/ion-menu_3.cjs.entry.js +14 -14
- package/dist/cjs/ion-modal.cjs.entry.js +16 -16
- package/dist/cjs/ion-nav_2.cjs.entry.js +8 -8
- package/dist/cjs/ion-picker-column-option.cjs.entry.js +6 -6
- package/dist/cjs/ion-picker-column.cjs.entry.js +9 -9
- package/dist/cjs/ion-picker.cjs.entry.js +4 -4
- package/dist/cjs/ion-popover.cjs.entry.js +10 -10
- package/dist/cjs/ion-progress-bar.cjs.entry.js +5 -5
- package/dist/cjs/ion-radio_2.cjs.entry.js +10 -10
- package/dist/cjs/ion-range.cjs.entry.js +8 -8
- package/dist/cjs/ion-refresher_2.cjs.entry.js +11 -11
- package/dist/cjs/ion-reorder_2.cjs.entry.js +9 -9
- package/dist/cjs/ion-ripple-effect.cjs.entry.js +3 -3
- package/dist/cjs/ion-route_4.cjs.entry.js +6 -6
- package/dist/cjs/ion-searchbar.cjs.entry.js +8 -8
- package/dist/cjs/ion-segment-content.cjs.entry.js +2 -2
- package/dist/cjs/ion-segment-view.cjs.entry.js +3 -3
- package/dist/cjs/ion-segment_2.cjs.entry.js +8 -8
- package/dist/cjs/ion-select-modal.cjs.entry.js +7 -7
- package/dist/cjs/ion-select_3.cjs.entry.js +14 -14
- package/dist/cjs/ion-spinner.cjs.entry.js +4 -4
- package/dist/cjs/ion-split-pane.cjs.entry.js +4 -4
- package/dist/cjs/ion-tab-bar_2.cjs.entry.js +11 -11
- package/dist/cjs/ion-tab_2.cjs.entry.js +6 -6
- package/dist/cjs/ion-text.cjs.entry.js +5 -5
- package/dist/cjs/ion-textarea.cjs.entry.js +88 -18
- package/dist/cjs/ion-toast.cjs.entry.js +10 -10
- package/dist/cjs/ion-toggle.cjs.entry.js +10 -10
- package/dist/cjs/{ionic-global-DpRwOXLK.js → ionic-global-Dq_E1GCa.js} +5 -5
- package/dist/cjs/ionic.cjs.js +4 -4
- package/dist/cjs/{ios.transition-Dt4GT8w5.js → ios.transition-DRha8gOi.js} +5 -5
- package/dist/cjs/{keyboard-B8HJHbg3.js → keyboard-DYFGJjuN.js} +4 -4
- package/dist/cjs/{keyboard-controller-O8n0dTQz.js → keyboard-controller-DNlzZiH-.js} +3 -3
- package/dist/cjs/{keyboard-BlrG3xPK.js → keyboard-sMvh7TE6.js} +1 -1
- package/dist/cjs/loader.cjs.js +4 -4
- package/dist/cjs/{md.transition-BolcQzNP.js → md.transition-Dh46qaSH.js} +5 -5
- package/dist/cjs/{notch-controller-BE80VRju.js → notch-controller-qvgjFR8h.js} +2 -2
- package/dist/cjs/{overlays-CRSQCKrz.js → overlays-CA-nLfRi.js} +97 -6
- package/dist/cjs/{status-tap-e-hyosXV.js → status-tap-BLw3gi_z.js} +3 -3
- package/dist/cjs/{swipe-back-CR060nOX.js → swipe-back-BD2lWufH.js} +2 -2
- package/dist/cjs/{theme-CeDs6Hcv.js → theme-IlOsGAz7.js} +25 -1
- package/dist/cjs/validity-QmuwEptc.js +51 -0
- package/dist/collection/components/button/button.ionic.css +10 -0
- package/dist/collection/components/button/button.ios.css +19 -0
- package/dist/collection/components/button/button.js +17 -12
- package/dist/collection/components/button/button.md.css +24 -0
- package/dist/collection/components/card-content/card-content.ionic.css +4 -7
- package/dist/collection/components/card-content/card-content.ios.css +5 -35
- package/dist/collection/components/card-content/card-content.js +3 -4
- package/dist/collection/components/card-content/card-content.md.css +5 -35
- package/dist/collection/components/card-header/card-header.js +2 -2
- package/dist/collection/components/card-subtitle/card-subtitle.js +2 -2
- package/dist/collection/components/card-title/card-title.js +2 -2
- package/dist/collection/components/checkbox/checkbox.js +3 -3
- package/dist/collection/components/chip/chip.js +2 -2
- package/dist/collection/components/col/col.js +2 -2
- package/dist/collection/components/content/content.js +3 -3
- package/dist/collection/components/datetime/datetime.ionic.css +5 -13
- package/dist/collection/components/datetime/datetime.ios.css +47 -12
- package/dist/collection/components/datetime/datetime.js +4 -4
- package/dist/collection/components/datetime/datetime.md.css +37 -2
- package/dist/collection/components/datetime-button/datetime-button.js +2 -2
- package/dist/collection/components/divider/divider.js +2 -2
- package/dist/collection/components/fab/fab.js +2 -2
- package/dist/collection/components/fab-button/fab-button.js +2 -2
- package/dist/collection/components/fab-list/fab-list.js +2 -2
- package/dist/collection/components/footer/footer.js +2 -2
- package/dist/collection/components/grid/grid.js +2 -2
- package/dist/collection/components/header/header.js +2 -2
- package/dist/collection/components/img/img.js +2 -2
- package/dist/collection/components/infinite-scroll/infinite-scroll.js +1 -1
- package/dist/collection/components/infinite-scroll-content/infinite-scroll-content.js +2 -2
- package/dist/collection/components/input/input.js +4 -4
- package/dist/collection/components/input-otp/input-otp.ionic.css +2 -0
- package/dist/collection/components/input-otp/input-otp.ios.css +3 -0
- package/dist/collection/components/input-otp/input-otp.js +69 -4
- package/dist/collection/components/input-otp/input-otp.md.css +3 -0
- package/dist/collection/components/input-password-toggle/input-password-toggle.js +3 -3
- package/dist/collection/components/item-divider/item-divider.js +2 -2
- package/dist/collection/components/item-group/item-group.js +1 -1
- package/dist/collection/components/item-option/item-option.js +2 -2
- package/dist/collection/components/item-options/item-options.js +1 -1
- package/dist/collection/components/item-sliding/item-sliding.js +1 -1
- package/dist/collection/components/label/label.js +2 -2
- package/dist/collection/components/list/list.js +1 -1
- package/dist/collection/components/list-header/list-header.js +2 -2
- package/dist/collection/components/loading/loading.js +2 -2
- package/dist/collection/components/menu/menu.js +2 -2
- package/dist/collection/components/menu-button/menu-button.js +2 -2
- package/dist/collection/components/menu-toggle/menu-toggle.js +2 -2
- package/dist/collection/components/modal/modal.js +4 -4
- package/dist/collection/components/nav/nav.js +1 -1
- package/dist/collection/components/nav-link/nav-link.js +1 -1
- package/dist/collection/components/note/note.js +2 -2
- package/dist/collection/components/picker/picker.js +2 -2
- package/dist/collection/components/picker-column/picker-column.js +3 -3
- package/dist/collection/components/picker-column-option/picker-column-option.js +2 -2
- package/dist/collection/components/picker-legacy/picker.js +2 -2
- package/dist/collection/components/picker-legacy-column/picker-column.js +2 -2
- package/dist/collection/components/popover/popover.js +2 -2
- package/dist/collection/components/progress-bar/progress-bar.js +1 -1
- package/dist/collection/components/radio/radio.js +3 -3
- package/dist/collection/components/radio-group/radio-group.js +2 -2
- package/dist/collection/components/range/range.js +3 -3
- package/dist/collection/components/refresher/refresher.js +1 -1
- package/dist/collection/components/refresher-content/refresher-content.js +2 -2
- package/dist/collection/components/reorder/reorder.js +2 -2
- package/dist/collection/components/reorder-group/reorder-group.js +1 -1
- package/dist/collection/components/ripple-effect/ripple-effect.js +1 -1
- package/dist/collection/components/router-link/router-link.js +2 -2
- package/dist/collection/components/router-outlet/router-outlet.js +1 -1
- package/dist/collection/components/row/row.js +2 -2
- package/dist/collection/components/searchbar/searchbar.js +4 -4
- package/dist/collection/components/segment/segment.js +2 -2
- package/dist/collection/components/segment-button/segment-button.js +2 -2
- package/dist/collection/components/segment-content/segment-content.js +1 -1
- package/dist/collection/components/segment-view/segment-view.js +2 -2
- package/dist/collection/components/select/select.js +3 -3
- package/dist/collection/components/select-modal/select-modal.js +1 -1
- package/dist/collection/components/select-option/select-option.js +1 -1
- package/dist/collection/components/select-popover/select-popover.js +2 -2
- package/dist/collection/components/skeleton-text/skeleton-text.js +2 -2
- package/dist/collection/components/spinner/spinner.js +1 -1
- package/dist/collection/components/split-pane/split-pane.js +2 -2
- package/dist/collection/components/tab/tab.js +2 -2
- package/dist/collection/components/tab-bar/tab-bar.js +2 -2
- package/dist/collection/components/tab-button/tab-button.js +2 -2
- package/dist/collection/components/tabs/tabs.js +1 -1
- package/dist/collection/components/text/text.js +2 -2
- package/dist/collection/components/textarea/textarea.ionic.css +11 -14
- package/dist/collection/components/textarea/textarea.ios.css +8 -14
- package/dist/collection/components/textarea/textarea.js +89 -11
- package/dist/collection/components/textarea/textarea.md.css +9 -14
- package/dist/collection/components/thumbnail/thumbnail.js +2 -2
- package/dist/collection/components/title/title.js +2 -2
- package/dist/collection/components/toast/toast.js +2 -2
- package/dist/collection/components/toggle/toggle.js +3 -3
- package/dist/collection/components/toolbar/toolbar.js +2 -2
- package/dist/collection/utils/focus-trap.js +13 -2
- package/dist/collection/utils/forms/validity.js +31 -0
- package/dist/collection/utils/helpers.js +18 -4
- package/dist/collection/utils/overlays.js +80 -0
- package/dist/collection/utils/theme.js +25 -1
- package/dist/docs.json +178 -15
- package/dist/esm/{animation-BNuoDl-O.js → animation-C5cgFymd.js} +2 -2
- package/dist/esm/{app-globals-tX0s9Zd7.js → app-globals-BQa4bHAm.js} +1 -1
- package/dist/esm/{button-active-BF6GZ_yH.js → button-active-DpavRUgB.js} +2 -2
- package/dist/esm/{capacitor-pzVAlnC0.js → capacitor-Bc47Xxvc.js} +1 -1
- package/dist/esm/{config-mCdtaoPe.js → config-DK9FWNvn.js} +1 -1
- package/dist/esm/{data-DFCY8gnk.js → data-B5lRlGxI.js} +1 -1
- package/dist/esm/{framework-delegate-D2mUP0WI.js → framework-delegate-Dx6tn-_w.js} +2 -2
- package/dist/esm/{haptic-bBvyATla.js → haptic-Dti4RWuD.js} +1 -1
- package/dist/esm/{helpers-Bsml3FcE.js → helpers-6l6yFg3S.js} +19 -5
- package/dist/esm/{index-Bnw-zNoN.js → index-B6MWWbnL.js} +3 -3
- package/dist/esm/{index-BpFi2B8W.js → index-CXCvNx5X.js} +2 -2
- package/dist/esm/{index-BQI9hSZP.js → index-DO9elf_6.js} +4 -4
- package/dist/esm/{index-C8IsBmNU.js → index-gD7P82jx.js} +41 -4
- package/dist/esm/{index-M3l-IyxQ.js → index-urxfV0GK.js} +4 -4
- package/dist/esm/index.js +12 -12
- package/dist/esm/{input-shims-ACbgRt10.js → input-shims-CK_oprMl.js} +6 -6
- package/dist/esm/{input.utils-loPnHH5H.js → input.utils-C3tJs_iL.js} +3 -3
- package/dist/esm/ion-accordion_2.entry.js +4 -4
- package/dist/esm/ion-action-sheet.entry.js +10 -10
- package/dist/esm/ion-alert.entry.js +11 -11
- package/dist/esm/ion-app_8.entry.js +23 -23
- package/dist/esm/ion-avatar_3.entry.js +5 -5
- package/dist/esm/ion-back-button.entry.js +4 -4
- package/dist/esm/ion-backdrop.entry.js +2 -2
- package/dist/esm/ion-breadcrumb_2.entry.js +4 -4
- package/dist/esm/ion-button_2.entry.js +23 -18
- package/dist/esm/ion-card_5.entry.js +15 -17
- package/dist/esm/ion-checkbox.entry.js +8 -8
- package/dist/esm/ion-chip.entry.js +5 -5
- package/dist/esm/ion-col_3.entry.js +8 -8
- package/dist/esm/ion-datetime-button.entry.js +7 -7
- package/dist/esm/ion-datetime_3.entry.js +21 -21
- package/dist/esm/ion-divider.entry.js +4 -4
- package/dist/esm/ion-fab_3.entry.js +10 -10
- package/dist/esm/ion-img.entry.js +5 -5
- package/dist/esm/ion-infinite-scroll_2.entry.js +8 -8
- package/dist/esm/ion-input-otp.entry.js +69 -10
- package/dist/esm/ion-input-password-toggle.entry.js +6 -6
- package/dist/esm/ion-input.entry.js +11 -11
- package/dist/esm/ion-item-option_3.entry.js +9 -9
- package/dist/esm/ion-item_8.entry.js +16 -16
- package/dist/esm/ion-loading.entry.js +10 -10
- package/dist/esm/ion-menu_3.entry.js +14 -14
- package/dist/esm/ion-modal.entry.js +16 -16
- package/dist/esm/ion-nav_2.entry.js +8 -8
- package/dist/esm/ion-picker-column-option.entry.js +6 -6
- package/dist/esm/ion-picker-column.entry.js +9 -9
- package/dist/esm/ion-picker.entry.js +4 -4
- package/dist/esm/ion-popover.entry.js +10 -10
- package/dist/esm/ion-progress-bar.entry.js +5 -5
- package/dist/esm/ion-radio_2.entry.js +10 -10
- package/dist/esm/ion-range.entry.js +8 -8
- package/dist/esm/ion-refresher_2.entry.js +11 -11
- package/dist/esm/ion-reorder_2.entry.js +9 -9
- package/dist/esm/ion-ripple-effect.entry.js +3 -3
- package/dist/esm/ion-route_4.entry.js +6 -6
- package/dist/esm/ion-searchbar.entry.js +8 -8
- package/dist/esm/ion-segment-content.entry.js +2 -2
- package/dist/esm/ion-segment-view.entry.js +3 -3
- package/dist/esm/ion-segment_2.entry.js +8 -8
- package/dist/esm/ion-select-modal.entry.js +7 -7
- package/dist/esm/ion-select_3.entry.js +14 -14
- package/dist/esm/ion-spinner.entry.js +4 -4
- package/dist/esm/ion-split-pane.entry.js +4 -4
- package/dist/esm/ion-tab-bar_2.entry.js +11 -11
- package/dist/esm/ion-tab_2.entry.js +6 -6
- package/dist/esm/ion-text.entry.js +5 -5
- package/dist/esm/ion-textarea.entry.js +88 -18
- package/dist/esm/ion-toast.entry.js +10 -10
- package/dist/esm/ion-toggle.entry.js +10 -10
- package/dist/esm/{ionic-global-2lDD9k7y.js → ionic-global-KnoA5TnE.js} +5 -5
- package/dist/esm/ionic.js +5 -5
- package/dist/esm/{ios.transition-uJxJFbq8.js → ios.transition-D-ZEPllL.js} +5 -5
- package/dist/esm/{keyboard-CU1vRv-b.js → keyboard-C7jpSDLg.js} +1 -1
- package/dist/esm/{keyboard-B-HHSSYU.js → keyboard-CrGPuspU.js} +4 -4
- package/dist/esm/{keyboard-controller-Dplyc4OV.js → keyboard-controller-CFeM2qrY.js} +3 -3
- package/dist/esm/loader.js +5 -5
- package/dist/esm/{md.transition-Dp4NTeSh.js → md.transition-DiPaaGY2.js} +5 -5
- package/dist/esm/{notch-controller-BvFDmO69.js → notch-controller-CEiB8plC.js} +2 -2
- package/dist/esm/{overlays-B037a9Tz.js → overlays-BMHHx7Tm.js} +97 -6
- package/dist/esm/{status-tap-DXVlluKS.js → status-tap-BAJGCN-1.js} +3 -3
- package/dist/esm/{swipe-back-DNhAt9fY.js → swipe-back-bZ7qcCmT.js} +2 -2
- package/dist/esm/{theme-DiVJyqlX.js → theme-DaJxRxSQ.js} +25 -1
- package/dist/esm/validity-BjW8SOqw.js +48 -0
- package/dist/html.html-data.json +28 -1
- package/dist/ionic/index.esm.js +1 -1
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/{p-5daa0980.entry.js → p-01dec443.entry.js} +1 -1
- package/dist/ionic/{p-04b1d37a.entry.js → p-01e2ad58.entry.js} +1 -1
- package/dist/ionic/{p-112e1ca9.entry.js → p-04c2c873.entry.js} +1 -1
- package/dist/ionic/{p-28a9d991.entry.js → p-09aab7d0.entry.js} +1 -1
- package/dist/ionic/{p-be82dc77.entry.js → p-0b51f337.entry.js} +1 -1
- package/dist/ionic/{p-616dd053.entry.js → p-131e3b2d.entry.js} +1 -1
- package/dist/ionic/{p-0f124806.entry.js → p-1454c314.entry.js} +1 -1
- package/dist/ionic/p-14c73725.entry.js +4 -0
- package/dist/ionic/p-14d44c66.entry.js +4 -0
- package/dist/ionic/{p-a35678f4.entry.js → p-1af56d46.entry.js} +1 -1
- package/dist/ionic/{p-0744265c.entry.js → p-1c00e5cc.entry.js} +1 -1
- package/dist/ionic/{p-0ac7c560.entry.js → p-25db2a16.entry.js} +1 -1
- package/dist/ionic/{p-60549f06.entry.js → p-2ef8db38.entry.js} +1 -1
- package/dist/ionic/{p-0607ce8e.entry.js → p-31706aa0.entry.js} +1 -1
- package/dist/ionic/{p-19b2060d.entry.js → p-39f88b4f.entry.js} +1 -1
- package/dist/ionic/p-3b163efb.entry.js +4 -0
- package/dist/ionic/{p-ecba552f.entry.js → p-3d69c783.entry.js} +1 -1
- package/dist/ionic/{p-e1d84521.entry.js → p-3d7263e2.entry.js} +1 -1
- package/dist/ionic/p-3f93e610.entry.js +4 -0
- package/dist/ionic/{p-Cq83JWMg.js → p-44OfGWEp.js} +1 -1
- package/dist/ionic/{p-5543b7b8.entry.js → p-45ffc1cb.entry.js} +1 -1
- package/dist/ionic/{p-a89211bd.entry.js → p-4d7a2141.entry.js} +1 -1
- package/dist/ionic/{p-f667945d.entry.js → p-51ddc430.entry.js} +1 -1
- package/dist/ionic/{p-d9c9592a.entry.js → p-69bef533.entry.js} +1 -1
- package/dist/ionic/{p-dacd8666.entry.js → p-717fa143.entry.js} +1 -1
- package/dist/ionic/{p-742fed9f.entry.js → p-7482c8b3.entry.js} +1 -1
- package/dist/ionic/{p-bd295ca7.entry.js → p-74cab2da.entry.js} +1 -1
- package/dist/ionic/p-788de6f7.entry.js +4 -0
- package/dist/ionic/{p-01577340.entry.js → p-7ab2b10c.entry.js} +1 -1
- package/dist/ionic/{p-ecf8e713.entry.js → p-7dc9aa9a.entry.js} +1 -1
- package/dist/ionic/{p-27dbb44c.entry.js → p-7f6069f4.entry.js} +1 -1
- package/dist/ionic/{p-472b2ca3.entry.js → p-8093e290.entry.js} +1 -1
- package/dist/ionic/{p-59a79bd9.entry.js → p-82ca1cae.entry.js} +1 -1
- package/dist/ionic/{p-5f9d9c14.entry.js → p-83c3c072.entry.js} +1 -1
- package/dist/ionic/p-8ddbeb52.entry.js +4 -0
- package/dist/ionic/{p-af1f624e.entry.js → p-9e985573.entry.js} +1 -1
- package/dist/ionic/p-9f29b55e.entry.js +4 -0
- package/dist/ionic/{p-qZR4N8Lu.js → p-B0QqVGqF.js} +1 -1
- package/dist/ionic/p-BAmXMA83.js +4 -0
- package/dist/ionic/p-BIyO17h7.js +4 -0
- package/dist/ionic/p-BjW8SOqw.js +4 -0
- package/dist/ionic/{p-UafGZQ8e.js → p-Br3trE7L.js} +1 -1
- package/dist/ionic/{p-DeEDqH91.js → p-BunTRNUk.js} +1 -1
- package/dist/ionic/p-CCy93Kdo.js +4 -0
- package/dist/ionic/{p-HpOiAvpC.js → p-CDRncjej.js} +1 -1
- package/dist/ionic/{p-CtUK3cKk.js → p-CH4Ab9QE.js} +1 -1
- package/dist/ionic/{p-B3uz75uZ.js → p-CYW7idR0.js} +1 -1
- package/dist/ionic/{p-B-D7Cfki.js → p-Ccfet-fb.js} +1 -1
- package/dist/ionic/p-CdcKo7Br.js +4 -0
- package/dist/ionic/{p-COLHV2ym.js → p-CsyYiC5f.js} +1 -1
- package/dist/ionic/{p-DyaKZbAH.js → p-CtS5hTli.js} +1 -1
- package/dist/ionic/{p-DbQ5QkTP.js → p-Cv5jk_TK.js} +1 -1
- package/dist/ionic/{p-q1ZSn0l7.js → p-CzuA64hv.js} +1 -1
- package/dist/ionic/{p-D-BelbiX.js → p-DGDvjMxF.js} +1 -1
- package/dist/ionic/p-DKogfaNJ.js +4 -0
- package/dist/ionic/p-DOsU-ODO.js +4 -0
- package/dist/ionic/p-DPrmF8Ki.js +4 -0
- package/dist/ionic/p-DYzvRXm5.js +4 -0
- package/dist/ionic/p-DaJxRxSQ.js +4 -0
- package/dist/ionic/{p-CvRDI-Iz.js → p-TL0QOgYo.js} +1 -1
- package/dist/ionic/p-We-0jbXn.js +4 -0
- package/dist/ionic/{p-c082f853.entry.js → p-a0c5e546.entry.js} +1 -1
- package/dist/ionic/{p-0eecce18.entry.js → p-a339cde1.entry.js} +1 -1
- package/dist/ionic/p-a59f21b3.entry.js +4 -0
- package/dist/ionic/{p-d3f64c58.entry.js → p-a5f4fe92.entry.js} +1 -1
- package/dist/ionic/{p-826267d6.entry.js → p-aaff29dd.entry.js} +1 -1
- package/dist/ionic/{p-0c41c8a8.entry.js → p-b4da10d5.entry.js} +1 -1
- package/dist/ionic/{p-8f541b05.entry.js → p-bb04a3d7.entry.js} +1 -1
- package/dist/ionic/{p-a6a37a34.entry.js → p-bc19095e.entry.js} +1 -1
- package/dist/ionic/{p-8ee09d4e.entry.js → p-bd0057bd.entry.js} +1 -1
- package/dist/ionic/{p-da49c0fe.entry.js → p-bf763ab7.entry.js} +1 -1
- package/dist/ionic/{p-cdbfbff6.entry.js → p-c66416de.entry.js} +1 -1
- package/dist/ionic/{p-b475ec18.entry.js → p-d103fef9.entry.js} +1 -1
- package/dist/ionic/{p-68c064ce.entry.js → p-d9c0d206.entry.js} +1 -1
- package/dist/ionic/{p-412d5d9e.entry.js → p-e278c474.entry.js} +1 -1
- package/dist/ionic/{p-6bb99f41.entry.js → p-e8344f8f.entry.js} +1 -1
- package/dist/ionic/{p-04e0ff62.entry.js → p-ec510664.entry.js} +1 -1
- package/dist/ionic/p-eyZt9Ndv.js +4 -0
- package/dist/ionic/{p-8681a2a7.entry.js → p-f0894af8.entry.js} +1 -1
- package/dist/ionic/p-gD7P82jx.js +5 -0
- package/dist/ionic/p-hPTD29t1.js +4 -0
- package/dist/types/components/button/button.d.ts +4 -2
- package/dist/types/components/input-otp/input-otp.d.ts +37 -0
- package/dist/types/components/textarea/textarea.d.ts +36 -0
- package/dist/types/components.d.ts +18 -2
- package/dist/types/utils/focus-trap.d.ts +1 -1
- package/dist/types/utils/forms/validity.d.ts +7 -0
- package/dist/types/utils/theme.d.ts +9 -0
- package/hydrate/index.js +527 -210
- package/hydrate/index.mjs +527 -210
- package/package.json +1 -1
- package/dist/cjs/validity-BpS37YFM.js +0 -19
- package/dist/esm/validity-DJztqcrH.js +0 -17
- package/dist/ionic/p-2dc676b2.entry.js +0 -4
- package/dist/ionic/p-381eb2a4.entry.js +0 -4
- package/dist/ionic/p-57a2d30b.entry.js +0 -4
- package/dist/ionic/p-63a2b52a.entry.js +0 -4
- package/dist/ionic/p-7fe3ea65.entry.js +0 -4
- package/dist/ionic/p-BiTKUjko.js +0 -4
- package/dist/ionic/p-ByhhQryg.js +0 -4
- package/dist/ionic/p-C8IsBmNU.js +0 -5
- package/dist/ionic/p-C8r4dtYR.js +0 -4
- package/dist/ionic/p-CK1xn1Nt.js +0 -4
- package/dist/ionic/p-C_97se21.js +0 -4
- package/dist/ionic/p-DHeUgOSJ.js +0 -4
- package/dist/ionic/p-DJztqcrH.js +0 -4
- package/dist/ionic/p-DM-v_NNE.js +0 -4
- package/dist/ionic/p-DiVJyqlX.js +0 -4
- package/dist/ionic/p-DoGrslUl.js +0 -4
- package/dist/ionic/p-Dq8ap6AD.js +0 -4
- package/dist/ionic/p-add1a5d8.entry.js +0 -4
- package/dist/ionic/p-da0a2ca6.entry.js +0 -4
- package/dist/ionic/p-f6ca543c.entry.js +0 -4
- package/dist/ionic/p-nP9c7bo5.js +0 -4
- package/dist/ionic/p-of4jy1ch.js +0 -4
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
3
|
*/
|
|
4
4
|
import { Build, Host, forceUpdate, h, writeTask, } from "@stencil/core";
|
|
5
|
-
import { createNotchController, checkInvalidState } from "../../utils/forms/index";
|
|
5
|
+
import { createNotchController, checkInvalidState, reportValidityToElementInternals } from "../../utils/forms/index";
|
|
6
6
|
import { inheritAriaAttributes, debounceEvent, inheritAttributes, componentOnReady } from "../../utils/helpers";
|
|
7
7
|
import { createSlotMutationController } from "../../utils/slot-mutation-controller";
|
|
8
8
|
import { createColorClasses, hostContext } from "../../utils/theme";
|
|
@@ -15,6 +15,16 @@ import { getCounterText } from "../input/input.utils";
|
|
|
15
15
|
* @slot label - The label text to associate with the textarea. Use the `labelPlacement` property to control where the label is placed relative to the textarea. Use this if you need to render a label with custom HTML. (EXPERIMENTAL)
|
|
16
16
|
* @slot start - Content to display at the leading edge of the textarea. (EXPERIMENTAL)
|
|
17
17
|
* @slot end - Content to display at the trailing edge of the textarea. (EXPERIMENTAL)
|
|
18
|
+
*
|
|
19
|
+
* @part wrapper - The clickable label element that wraps the entire form field (label text, slots, and native textarea).
|
|
20
|
+
* @part container - The inner wrapper element that directly contains the native textarea element.
|
|
21
|
+
* @part label - The label text describing the textarea.
|
|
22
|
+
* @part native - The native textarea element.
|
|
23
|
+
* @part supporting-text - Supporting text displayed beneath the textarea label.
|
|
24
|
+
* @part helper-text - Supporting text displayed beneath the textarea label when the textarea is valid.
|
|
25
|
+
* @part error-text - Supporting text displayed beneath the textarea label when the textarea is invalid and touched.
|
|
26
|
+
* @part counter - The character counter displayed when the counter property is set.
|
|
27
|
+
* @part bottom - The container element for helper text, error text, and counter.
|
|
18
28
|
*/
|
|
19
29
|
export class Textarea {
|
|
20
30
|
constructor() {
|
|
@@ -161,6 +171,12 @@ export class Textarea {
|
|
|
161
171
|
*/
|
|
162
172
|
this.ionInput = debounce === undefined ? originalIonInput !== null && originalIonInput !== void 0 ? originalIonInput : ionInput : debounceEvent(ionInput, debounce);
|
|
163
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Update element internals when disabled prop changes
|
|
176
|
+
*/
|
|
177
|
+
disabledChanged() {
|
|
178
|
+
this.updateElementInternals();
|
|
179
|
+
}
|
|
164
180
|
/**
|
|
165
181
|
* Update the native input element when the value changes
|
|
166
182
|
*/
|
|
@@ -170,8 +186,22 @@ export class Textarea {
|
|
|
170
186
|
if (nativeInput && nativeInput.value !== value) {
|
|
171
187
|
nativeInput.value = value;
|
|
172
188
|
}
|
|
189
|
+
this.updateElementInternals();
|
|
173
190
|
this.runAutoGrow();
|
|
174
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* Update native input and element internals when required prop changes
|
|
194
|
+
*/
|
|
195
|
+
requiredChanged() {
|
|
196
|
+
// Explicitly update the native element's required attribute to ensure
|
|
197
|
+
// browser validation works correctly when required changes dynamically.
|
|
198
|
+
// While the template binding should handle this, we need to update it
|
|
199
|
+
// synchronously for the browser's validation to recognize the change.
|
|
200
|
+
if (this.nativeInput) {
|
|
201
|
+
this.nativeInput.required = this.required;
|
|
202
|
+
}
|
|
203
|
+
this.updateElementInternals();
|
|
204
|
+
}
|
|
175
205
|
/**
|
|
176
206
|
* dir is a globally enumerated attribute.
|
|
177
207
|
* As a result, creating these as properties
|
|
@@ -247,7 +277,14 @@ export class Textarea {
|
|
|
247
277
|
}
|
|
248
278
|
componentDidLoad() {
|
|
249
279
|
this.originalIonInput = this.ionInput;
|
|
280
|
+
this.updateElementInternals();
|
|
250
281
|
this.runAutoGrow();
|
|
282
|
+
// Override focus() to delegate to the native textarea.
|
|
283
|
+
// This is needed for Safari and Firefox which don't properly
|
|
284
|
+
// delegate focus when calling focus() directly on the host.
|
|
285
|
+
this.el.focus = () => {
|
|
286
|
+
this.setFocus();
|
|
287
|
+
};
|
|
251
288
|
}
|
|
252
289
|
componentDidRender() {
|
|
253
290
|
var _a;
|
|
@@ -356,12 +393,43 @@ export class Textarea {
|
|
|
356
393
|
getValue() {
|
|
357
394
|
return this.value || '';
|
|
358
395
|
}
|
|
396
|
+
/**
|
|
397
|
+
* Called when the form state is restored.
|
|
398
|
+
* Restores the component's value.
|
|
399
|
+
*/
|
|
400
|
+
formStateRestoreCallback(value) {
|
|
401
|
+
this.value = value;
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Called when the form is reset.
|
|
405
|
+
* Resets the component's value.
|
|
406
|
+
*/
|
|
407
|
+
formResetCallback() {
|
|
408
|
+
this.value = '';
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Updates the form value and reports validity state to the browser via
|
|
412
|
+
* ElementInternals. This should be called when the component loads, when
|
|
413
|
+
* the required prop changes, when the disabled prop changes, and when the value
|
|
414
|
+
* changes to ensure the form value stays in sync and validation state is updated.
|
|
415
|
+
*/
|
|
416
|
+
updateElementInternals() {
|
|
417
|
+
// Disabled form controls should not be included in form data
|
|
418
|
+
// Pass null to setFormValue when disabled to exclude it from form submission
|
|
419
|
+
const value = this.disabled ? null : this.getValue();
|
|
420
|
+
// ElementInternals may not be fully available in test environments
|
|
421
|
+
// so we need to check if the method exists before calling it
|
|
422
|
+
if (typeof this.internals.setFormValue === 'function') {
|
|
423
|
+
this.internals.setFormValue(value);
|
|
424
|
+
}
|
|
425
|
+
reportValidityToElementInternals(this.nativeInput, this.internals);
|
|
426
|
+
}
|
|
359
427
|
renderLabel() {
|
|
360
428
|
const { label } = this;
|
|
361
429
|
return (h("div", { class: {
|
|
362
430
|
'label-text-wrapper': true,
|
|
363
431
|
'label-text-wrapper-hidden': !this.hasLabel,
|
|
364
|
-
} }, label === undefined ? h("slot", { name: "label" }) : h("div", { class: "label-text" }, label)));
|
|
432
|
+
}, part: "label" }, label === undefined ? h("slot", { name: "label" }) : h("div", { class: "label-text" }, label)));
|
|
365
433
|
}
|
|
366
434
|
/**
|
|
367
435
|
* Gets any content passed into the `label` slot,
|
|
@@ -430,8 +498,8 @@ export class Textarea {
|
|
|
430
498
|
renderHintText() {
|
|
431
499
|
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
|
|
432
500
|
return [
|
|
433
|
-
h("div", { id: helperTextId, class: "helper-text", "aria-live": "polite" }, !isInvalid ? helperText : null),
|
|
434
|
-
h("div", { id: errorTextId, class: "error-text", role: "alert" }, isInvalid ? errorText : null),
|
|
501
|
+
h("div", { id: helperTextId, class: "helper-text", part: "supporting-text helper-text", "aria-live": "polite" }, !isInvalid ? helperText : null),
|
|
502
|
+
h("div", { id: errorTextId, class: "error-text", part: "supporting-text error-text", role: "alert" }, isInvalid ? errorText : null),
|
|
435
503
|
];
|
|
436
504
|
}
|
|
437
505
|
getHintTextID() {
|
|
@@ -449,7 +517,7 @@ export class Textarea {
|
|
|
449
517
|
if (counter !== true || maxlength === undefined) {
|
|
450
518
|
return;
|
|
451
519
|
}
|
|
452
|
-
return h("div", { class: "counter" }, getCounterText(value, maxlength, counterFormatter));
|
|
520
|
+
return (h("div", { class: "counter", part: "counter" }, getCounterText(value, maxlength, counterFormatter)));
|
|
453
521
|
}
|
|
454
522
|
/**
|
|
455
523
|
* Responsible for rendering helper text,
|
|
@@ -467,7 +535,7 @@ export class Textarea {
|
|
|
467
535
|
if (!hasHintText && !hasCounter) {
|
|
468
536
|
return;
|
|
469
537
|
}
|
|
470
|
-
return (h("div", { class: "textarea-bottom" }, this.renderHintText(), this.renderCounter()));
|
|
538
|
+
return (h("div", { class: "textarea-bottom", part: "bottom" }, this.renderHintText(), this.renderCounter()));
|
|
471
539
|
}
|
|
472
540
|
render() {
|
|
473
541
|
const { inputId, disabled, readonly, size, labelPlacement, el, hasFocus } = this;
|
|
@@ -497,7 +565,7 @@ export class Textarea {
|
|
|
497
565
|
* TODO(FW-5592): Remove hasStartEndSlots condition
|
|
498
566
|
*/
|
|
499
567
|
const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
|
|
500
|
-
return (h(Host, { key: '
|
|
568
|
+
return (h(Host, { key: '5be3ab7c5adf5ef61d70aff916d233239cc3034e', class: createColorClasses(this.color, {
|
|
501
569
|
[theme]: true,
|
|
502
570
|
'has-value': hasValue,
|
|
503
571
|
'has-focus': hasFocus,
|
|
@@ -506,9 +574,10 @@ export class Textarea {
|
|
|
506
574
|
[`textarea-shape-${shape}`]: shape !== undefined,
|
|
507
575
|
[`textarea-size-${size}`]: true,
|
|
508
576
|
[`textarea-label-placement-${labelPlacement}`]: true,
|
|
577
|
+
'in-item': inItem,
|
|
509
578
|
'textarea-disabled': disabled,
|
|
510
579
|
'textarea-readonly': readonly,
|
|
511
|
-
}) }, h("label", { key: '
|
|
580
|
+
}) }, h("label", { key: '7eb9826e9618606e1de74cb842c9236a2b5d0cb4', class: "textarea-wrapper", htmlFor: inputId, onClick: this.onLabelClick, part: "wrapper" }, this.renderLabelContainer(), h("div", { key: '5f0362d9f1f07f73b3d7d89d55fcb463ad0bc1da', class: "textarea-wrapper-inner" },
|
|
512
581
|
/**
|
|
513
582
|
* For the ionic theme, we render the outline container here
|
|
514
583
|
* instead of higher up, so it can be positioned relative to
|
|
@@ -518,10 +587,12 @@ export class Textarea {
|
|
|
518
587
|
* <label> element, ensuring that clicking the label text
|
|
519
588
|
* focuses the textarea.
|
|
520
589
|
*/
|
|
521
|
-
theme === 'ionic' && fill === 'outline' && h("div", { key: '
|
|
590
|
+
theme === 'ionic' && fill === 'outline' && h("div", { key: 'c8f68629935444bedaf41c8958e13fd1916a0871', class: "textarea-outline" }), h("div", { key: '56349914a8348214f9a663c768a3915fc70e21cd', class: "start-slot-wrapper" }, h("slot", { key: '8b399fd0f049f579f7af1183052614f459d52169', name: "start" })), h("div", { key: '5edec308a1ade5d4634ee5bae413e27a9f17e3cb', class: "native-wrapper", ref: (el) => (this.textareaWrapper = el), part: "container" }, h("textarea", Object.assign({ key: 'ac792e9d46e30bb0fe72b6e8f57880ff5114dff6', class: "native-textarea", part: "native", 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)), h("div", { key: '02e2a10f1f8fd6e05f457320cb90fade56cf06a9', class: "end-slot-wrapper" }, h("slot", { key: '4314c344b0054cafcb65358451afa2dbef5bd8ef', name: "end" }))), shouldRenderHighlight && h("div", { key: '94e8b3639665cf9c068abfd681e7fa4c515307f4', class: "textarea-highlight" })), this.renderBottomContent()));
|
|
522
591
|
}
|
|
523
592
|
static get is() { return "ion-textarea"; }
|
|
524
|
-
static get encapsulation() { return "
|
|
593
|
+
static get encapsulation() { return "shadow"; }
|
|
594
|
+
static get delegatesFocus() { return true; }
|
|
595
|
+
static get formAssociated() { return true; }
|
|
525
596
|
static get originalStyleUrls() {
|
|
526
597
|
return {
|
|
527
598
|
"ios": ["textarea.ios.scss"],
|
|
@@ -832,7 +903,7 @@ export class Textarea {
|
|
|
832
903
|
},
|
|
833
904
|
"getter": false,
|
|
834
905
|
"setter": false,
|
|
835
|
-
"reflect":
|
|
906
|
+
"reflect": true,
|
|
836
907
|
"attribute": "required",
|
|
837
908
|
"defaultValue": "false"
|
|
838
909
|
},
|
|
@@ -1246,9 +1317,15 @@ export class Textarea {
|
|
|
1246
1317
|
return [{
|
|
1247
1318
|
"propName": "debounce",
|
|
1248
1319
|
"methodName": "debounceChanged"
|
|
1320
|
+
}, {
|
|
1321
|
+
"propName": "disabled",
|
|
1322
|
+
"methodName": "disabledChanged"
|
|
1249
1323
|
}, {
|
|
1250
1324
|
"propName": "value",
|
|
1251
1325
|
"methodName": "valueChanged"
|
|
1326
|
+
}, {
|
|
1327
|
+
"propName": "required",
|
|
1328
|
+
"methodName": "requiredChanged"
|
|
1252
1329
|
}, {
|
|
1253
1330
|
"propName": "dir",
|
|
1254
1331
|
"methodName": "onDirChanged"
|
|
@@ -1263,5 +1340,6 @@ export class Textarea {
|
|
|
1263
1340
|
"passive": false
|
|
1264
1341
|
}];
|
|
1265
1342
|
}
|
|
1343
|
+
static get attachInternalsMemberName() { return "internals"; }
|
|
1266
1344
|
}
|
|
1267
1345
|
let textareaIds = 0;
|
|
@@ -152,12 +152,12 @@
|
|
|
152
152
|
background: initial;
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
:host
|
|
155
|
+
:host(.in-item) {
|
|
156
156
|
align-self: baseline;
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
-
:host
|
|
160
|
-
:host
|
|
159
|
+
:host(.in-item[slot=start]),
|
|
160
|
+
:host(.in-item[slot=end]) {
|
|
161
161
|
width: auto;
|
|
162
162
|
}
|
|
163
163
|
|
|
@@ -334,6 +334,7 @@
|
|
|
334
334
|
display: flex;
|
|
335
335
|
width: 100%;
|
|
336
336
|
min-height: inherit;
|
|
337
|
+
box-sizing: border-box;
|
|
337
338
|
}
|
|
338
339
|
|
|
339
340
|
:host(.ion-touched.ion-invalid) {
|
|
@@ -438,6 +439,10 @@
|
|
|
438
439
|
overflow: hidden;
|
|
439
440
|
}
|
|
440
441
|
|
|
442
|
+
.textarea-outline {
|
|
443
|
+
box-sizing: border-box;
|
|
444
|
+
}
|
|
445
|
+
|
|
441
446
|
/**
|
|
442
447
|
* If no label text is placed into the slot
|
|
443
448
|
* then the element should be hidden otherwise
|
|
@@ -547,17 +552,6 @@
|
|
|
547
552
|
opacity: 1;
|
|
548
553
|
}
|
|
549
554
|
|
|
550
|
-
/**
|
|
551
|
-
* When the rows attribute is set, the textarea should not force a min-height,
|
|
552
|
-
* but rather respect the natural height of the textarea. Specially when
|
|
553
|
-
* rows is set to 1.
|
|
554
|
-
*/
|
|
555
|
-
:host(.textarea-fill-outline.sc-ion-textarea-md-h[rows]),
|
|
556
|
-
:host(.textarea-label-placement-stacked[rows]),
|
|
557
|
-
:host(.textarea-label-placement-floating[rows]) {
|
|
558
|
-
min-height: auto;
|
|
559
|
-
}
|
|
560
|
-
|
|
561
555
|
.start-slot-wrapper,
|
|
562
556
|
.end-slot-wrapper {
|
|
563
557
|
display: flex;
|
|
@@ -1345,6 +1339,7 @@
|
|
|
1345
1339
|
:host(.textarea-fill-outline) .textarea-outline-end {
|
|
1346
1340
|
border-top: var(--border-width) var(--border-style) var(--border-color);
|
|
1347
1341
|
border-bottom: var(--border-width) var(--border-style) var(--border-color);
|
|
1342
|
+
box-sizing: border-box;
|
|
1348
1343
|
}
|
|
1349
1344
|
|
|
1350
1345
|
/**
|
|
@@ -10,9 +10,9 @@ import { getIonTheme } from "../../global/ionic-global";
|
|
|
10
10
|
export class Thumbnail {
|
|
11
11
|
render() {
|
|
12
12
|
const theme = getIonTheme(this);
|
|
13
|
-
return (h(Host, { key: '
|
|
13
|
+
return (h(Host, { key: '6053cf163155d4268dad4fc81ffc6bbc70d75659', class: {
|
|
14
14
|
[theme]: true,
|
|
15
|
-
} }, h("slot", { key: '
|
|
15
|
+
} }, h("slot", { key: 'b7afb5835bce7c7ed9e5cf44758bbe2d802e1271' })));
|
|
16
16
|
}
|
|
17
17
|
static get is() { return "ion-thumbnail"; }
|
|
18
18
|
static get encapsulation() { return "shadow"; }
|
|
@@ -27,11 +27,11 @@ export class ToolbarTitle {
|
|
|
27
27
|
render() {
|
|
28
28
|
const theme = getIonTheme(this);
|
|
29
29
|
const size = this.getSize();
|
|
30
|
-
return (h(Host, { key: '
|
|
30
|
+
return (h(Host, { key: '8db3e5f9dbd8b1762a9919eaeef29c98649dfb25', class: createColorClasses(this.color, {
|
|
31
31
|
[theme]: true,
|
|
32
32
|
[`title-${size}`]: true,
|
|
33
33
|
'title-rtl': document.dir === 'rtl',
|
|
34
|
-
}) }, h("div", { key: '
|
|
34
|
+
}) }, h("div", { key: 'a31ebae2c494a51d2145eec69d0b1bc635108a01', class: "toolbar-title" }, h("slot", { key: 'f5975b44b3e3afbf98dcbdb53fc78447b49407b3' }))));
|
|
35
35
|
}
|
|
36
36
|
static get is() { return "ion-title"; }
|
|
37
37
|
static get encapsulation() { return "shadow"; }
|
|
@@ -437,9 +437,9 @@ export class Toast {
|
|
|
437
437
|
if (layout === 'stacked' && startButtons.length > 0 && endButtons.length > 0) {
|
|
438
438
|
printIonWarning('[ion-toast] - This toast is using start and end buttons with the stacked toast layout. We recommend following the best practice of using either start or end buttons with the stacked toast layout.', el);
|
|
439
439
|
}
|
|
440
|
-
return (h(Host, Object.assign({ key: '
|
|
440
|
+
return (h(Host, Object.assign({ key: '3f25e3c14197723e0c97edb71ddeeccb4f9143b3', tabindex: "-1" }, this.htmlAttributes, { style: {
|
|
441
441
|
zIndex: `${60000 + this.overlayIndex}`,
|
|
442
|
-
}, class: createColorClasses(this.color, Object.assign(Object.assign({ [mode]: true, [theme]: true }, getClassMap(this.cssClass)), { 'overlay-hidden': true, 'toast-translucent': this.translucent, [`toast-shape-${shape}`]: shape !== undefined, [`toast-hue-${hue}`]: hue !== undefined })), onIonToastWillDismiss: this.dispatchCancelHandler }), h("div", { key: '
|
|
442
|
+
}, class: createColorClasses(this.color, Object.assign(Object.assign({ [mode]: true, [theme]: true }, getClassMap(this.cssClass)), { 'overlay-hidden': true, 'toast-translucent': this.translucent, [`toast-shape-${shape}`]: shape !== undefined, [`toast-hue-${hue}`]: hue !== undefined })), onIonToastWillDismiss: this.dispatchCancelHandler }), h("div", { key: 'cec09872b7e08429a62e5cb821e072fa6259e63a', class: wrapperClass }, h("div", { key: '8179d7a3c8b27536e37886a21293d1a6add60306', class: "toast-container", part: "container" }, this.renderButtons(startButtons, 'start'), this.icon !== undefined && (h("ion-icon", { key: 'ef87a58440d914e4c55b8b3ecaac45f983f35daf', class: "toast-icon", part: "icon", icon: this.icon, lazy: false, "aria-hidden": "true" })), h("div", { key: '56bca03e8501ad921cf2de37faace99a4f59cc71', class: "toast-content", role: "status", "aria-atomic": "true", "aria-live": "polite" }, !revealContentToScreenReader && header !== undefined && this.renderHeader('oldHeader', 'true'), !revealContentToScreenReader && message !== undefined && this.renderToastMessage('oldMessage', 'true'), revealContentToScreenReader && header !== undefined && this.renderHeader('header'), revealContentToScreenReader && message !== undefined && this.renderToastMessage('header')), this.renderButtons(endButtons, 'end')))));
|
|
443
443
|
}
|
|
444
444
|
static get is() { return "ion-toast"; }
|
|
445
445
|
static get encapsulation() { return "shadow"; }
|
|
@@ -338,7 +338,7 @@ export class Toggle {
|
|
|
338
338
|
const rtl = isRTL(el) ? 'rtl' : 'ltr';
|
|
339
339
|
const isIonicTheme = theme === 'ionic';
|
|
340
340
|
renderHiddenInput(true, el, name, checked ? value : '', disabled);
|
|
341
|
-
return (h(Host, { key: '
|
|
341
|
+
return (h(Host, { key: 'b12951146a79d3839e6263e91e747398a0fa901d', role: "switch", "aria-checked": `${checked}`, "aria-describedby": this.hintTextId, "aria-invalid": this.isInvalid ? 'true' : undefined, onClick: this.onClick, "aria-labelledby": hasLabel ? inputLabelId : null, "aria-label": inheritedAttributes['aria-label'] || null, "aria-disabled": disabled ? 'true' : null, "aria-required": required ? 'true' : undefined, tabindex: disabled ? undefined : 0, onKeyDown: this.onKeyDown, onFocus: this.onFocus, onBlur: this.onBlur, class: createColorClasses(color, {
|
|
342
342
|
[theme]: true,
|
|
343
343
|
'in-item': hostContext('ion-item', el),
|
|
344
344
|
'toggle-activated': activated,
|
|
@@ -350,10 +350,10 @@ export class Toggle {
|
|
|
350
350
|
[`toggle-${rtl}`]: true,
|
|
351
351
|
'ion-activatable': isIonicTheme,
|
|
352
352
|
'ion-focusable': isIonicTheme,
|
|
353
|
-
}) }, h("label", { key: '
|
|
353
|
+
}) }, h("label", { key: 'cf1d27243bf9bdd5bafaf6d86b76beb311b5e01c', class: "toggle-wrapper", htmlFor: inputId }, h("input", Object.assign({ key: 'b3eb0f146836f5994c15bf1fd67a79f72b9414f7', type: "checkbox", role: "switch", "aria-checked": `${checked}`, checked: checked, disabled: disabled, id: inputId, required: required }, inheritedAttributes)), h("div", { key: '56ddcfd6452f30fd6b38d0fd85be3ec966aa120b', class: {
|
|
354
354
|
'label-text-wrapper': true,
|
|
355
355
|
'label-text-wrapper-hidden': !hasLabel,
|
|
356
|
-
}, part: "label", id: inputLabelId, onClick: this.onDivLabelClick }, h("slot", { key: '
|
|
356
|
+
}, part: "label", id: inputLabelId, onClick: this.onDivLabelClick }, h("slot", { key: '706e5b667ee242fb1afb3e4afa613f9798fbe25b' }), this.renderHintText()), h("div", { key: '255ccd7d60f7d78b4eba8d380b303a72093e9d16', class: "native-wrapper" }, this.renderToggleControl()))));
|
|
357
357
|
}
|
|
358
358
|
static get is() { return "ion-toggle"; }
|
|
359
359
|
static get encapsulation() { return "shadow"; }
|
|
@@ -207,10 +207,10 @@ export class Toolbar {
|
|
|
207
207
|
this.childrenStyles.forEach((style) => {
|
|
208
208
|
Object.assign(childStyles, style);
|
|
209
209
|
});
|
|
210
|
-
return (h(Host, { key: '
|
|
210
|
+
return (h(Host, { key: '6f52a5408379012843d0b93ac20c25b868e0211c', class: Object.assign(Object.assign({}, createColorClasses(this.color, {
|
|
211
211
|
[theme]: true,
|
|
212
212
|
'in-toolbar': hostContext('ion-toolbar', this.el),
|
|
213
|
-
})), childStyles) }, h("div", { key: '
|
|
213
|
+
})), childStyles) }, h("div", { key: '8f79b04f7c26edb4d64b88d1e1a69ee6e4ab8773', class: "toolbar-background", part: "background" }), h("div", { key: '8a682653ea75f07fa583d9b7cf38850294e83448', class: "toolbar-container", part: "container" }, h("slot", { key: '1a4e3289bdc3802cbabdd99d4bd5ab45e10846d8', name: "start", onSlotchange: () => this.updateSlotClasses }), h("slot", { key: '5578aaf1d8bf6dba08ab4ac9ccd9b8d8fe6c8ff1', name: "secondary", onSlotchange: () => this.updateSlotClasses }), h("div", { key: 'd4ba11c8daf43ed164a9c89dafdd96c5d2b50a35', class: "toolbar-content", part: "content" }, h("slot", { key: '994952702fe18216044d10a96abbf9cf071612e3' })), h("slot", { key: '2e07d6585687764a0a24bbc1b2f456aec30bfea7', name: "primary", onSlotchange: () => this.updateSlotClasses }), h("slot", { key: 'ebcb8dcde1202d6ced4c251a3b78c30b1153849f', name: "end", onSlotchange: () => this.updateSlotClasses }))));
|
|
214
214
|
}
|
|
215
215
|
static get is() { return "ion-toolbar"; }
|
|
216
216
|
static get encapsulation() { return "shadow"; }
|
|
@@ -14,7 +14,7 @@ import { focusVisibleElement } from "./helpers";
|
|
|
14
14
|
* Note: We need this distinction because `disabled="false"` is
|
|
15
15
|
* valid usage for the disabled property on ion-button.
|
|
16
16
|
*/
|
|
17
|
-
export const focusableQueryString = '[tabindex]:not([tabindex^="-"]):not([hidden]):not([disabled]), input:not([type=hidden]):not([tabindex^="-"]):not([hidden]):not([disabled]), textarea:not([tabindex^="-"]):not([hidden]):not([disabled]), button:not([tabindex^="-"]):not([hidden]):not([disabled]), select:not([tabindex^="-"]):not([hidden]):not([disabled]), ion-checkbox:not([tabindex^="-"]):not([hidden]):not([disabled]), ion-radio:not([tabindex^="-"]):not([hidden]):not([disabled]), .ion-focusable:not([tabindex^="-"]):not([hidden]):not([disabled]), .ion-focusable[disabled="false"]:not([tabindex^="-"]):not([hidden])';
|
|
17
|
+
export const focusableQueryString = '[tabindex]:not([tabindex^="-"]):not([hidden]):not([disabled]), input:not([type=hidden]):not([tabindex^="-"]):not([hidden]):not([disabled]), textarea:not([tabindex^="-"]):not([hidden]):not([disabled]), button:not([tabindex^="-"]):not([hidden]):not([disabled]), select:not([tabindex^="-"]):not([hidden]):not([disabled]), ion-checkbox:not([tabindex^="-"]):not([hidden]):not([disabled]), ion-radio:not([tabindex^="-"]):not([hidden]):not([disabled]), ion-textarea:not([tabindex^="-"]):not([hidden]):not([disabled]), .ion-focusable:not([tabindex^="-"]):not([hidden]):not([disabled]), .ion-focusable[disabled="false"]:not([tabindex^="-"]):not([hidden])';
|
|
18
18
|
/**
|
|
19
19
|
* Focuses the first descendant in a context
|
|
20
20
|
* that can receive focus. If none exists,
|
|
@@ -66,7 +66,18 @@ const focusElementInContext = (hostToFocus, fallbackElement) => {
|
|
|
66
66
|
const shadowRoot = hostToFocus === null || hostToFocus === void 0 ? void 0 : hostToFocus.shadowRoot;
|
|
67
67
|
if (shadowRoot) {
|
|
68
68
|
// If there are no inner focusable elements, just focus the host element.
|
|
69
|
-
|
|
69
|
+
const innerFocusable = shadowRoot.querySelector(focusableQueryString);
|
|
70
|
+
// If the host has a setFocus() method, use it to delegate focus properly.
|
|
71
|
+
// This is needed for shadow DOM components like ion-textarea that override
|
|
72
|
+
// focus() to delegate to their inner native elements.
|
|
73
|
+
const hasSetFocus = typeof hostToFocus.setFocus === 'function';
|
|
74
|
+
if (innerFocusable && hasSetFocus) {
|
|
75
|
+
// Keep the host element so we can call setFocus() on it
|
|
76
|
+
elementToFocus = hostToFocus;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
elementToFocus = innerFocusable || hostToFocus;
|
|
80
|
+
}
|
|
70
81
|
}
|
|
71
82
|
if (elementToFocus) {
|
|
72
83
|
const radioGroup = elementToFocus.closest('ion-radio-group');
|
|
@@ -13,3 +13,34 @@ export const checkInvalidState = (el) => {
|
|
|
13
13
|
const hasIonInvalid = el.classList.contains('ion-invalid');
|
|
14
14
|
return hasIonTouched && hasIonInvalid;
|
|
15
15
|
};
|
|
16
|
+
export const getValidityFlags = (validity) => {
|
|
17
|
+
return {
|
|
18
|
+
badInput: validity.badInput,
|
|
19
|
+
customError: validity.customError,
|
|
20
|
+
patternMismatch: validity.patternMismatch,
|
|
21
|
+
rangeOverflow: validity.rangeOverflow,
|
|
22
|
+
rangeUnderflow: validity.rangeUnderflow,
|
|
23
|
+
stepMismatch: validity.stepMismatch,
|
|
24
|
+
tooLong: validity.tooLong,
|
|
25
|
+
tooShort: validity.tooShort,
|
|
26
|
+
typeMismatch: validity.typeMismatch,
|
|
27
|
+
valueMissing: validity.valueMissing,
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Reports the validity state of a native form element to ElementInternals.
|
|
32
|
+
* This delegates to the native element's built-in validation, which automatically
|
|
33
|
+
* handles required, minlength, maxlength, and other constraints.
|
|
34
|
+
*/
|
|
35
|
+
export const reportValidityToElementInternals = (nativeElement, internals) => {
|
|
36
|
+
if (!(nativeElement === null || nativeElement === void 0 ? void 0 : nativeElement.validity)) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (nativeElement.validity.valid) {
|
|
40
|
+
internals.setValidity({});
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
const validityFlags = getValidityFlags(nativeElement.validity);
|
|
44
|
+
internals.setValidity(validityFlags, nativeElement.validationMessage, nativeElement);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
@@ -225,10 +225,24 @@ export const focusVisibleElement = (el) => {
|
|
|
225
225
|
* however, there are times when we need to manually control
|
|
226
226
|
* this behavior so we call the `setFocus` method on ion-app
|
|
227
227
|
* which will let us explicitly set the elements to focus.
|
|
228
|
+
*
|
|
229
|
+
* Note: The element passed to this function might be an inner
|
|
230
|
+
* focusable element (e.g., a native <button> inside ion-button's
|
|
231
|
+
* shadow root). If so, we need to find the host element that has
|
|
232
|
+
* the ion-focusable class to pass to setFocus.
|
|
228
233
|
*/
|
|
229
|
-
|
|
234
|
+
let elToFocus = el;
|
|
235
|
+
// If the element doesn't have ion-focusable, check if it's inside
|
|
236
|
+
// a shadow root and use the host element instead
|
|
237
|
+
if (!el.classList.contains('ion-focusable')) {
|
|
238
|
+
const rootNode = el.getRootNode();
|
|
239
|
+
if (rootNode instanceof ShadowRoot && rootNode.host instanceof HTMLElement) {
|
|
240
|
+
elToFocus = rootNode.host;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (elToFocus.classList.contains('ion-focusable')) {
|
|
230
244
|
const appRootSelector = config.get('appRootSelector', 'ion-app');
|
|
231
|
-
const app =
|
|
245
|
+
const app = elToFocus.closest(appRootSelector);
|
|
232
246
|
if (app) {
|
|
233
247
|
if (appRootSelector === 'ion-app') {
|
|
234
248
|
/**
|
|
@@ -237,7 +251,7 @@ export const focusVisibleElement = (el) => {
|
|
|
237
251
|
* focus-visible utility is attached to the app root
|
|
238
252
|
* and will handle setting focus on the correct element.
|
|
239
253
|
*/
|
|
240
|
-
app.setFocus([
|
|
254
|
+
app.setFocus([elToFocus]);
|
|
241
255
|
}
|
|
242
256
|
else {
|
|
243
257
|
/**
|
|
@@ -254,7 +268,7 @@ export const focusVisibleElement = (el) => {
|
|
|
254
268
|
* The focus-visible utility is used to set focus on an
|
|
255
269
|
* element that uses `ion-focusable`.
|
|
256
270
|
*/
|
|
257
|
-
focusElements([
|
|
271
|
+
focusElements([elToFocus]);
|
|
258
272
|
});
|
|
259
273
|
}
|
|
260
274
|
}
|
|
@@ -319,6 +319,86 @@ const connectListeners = (doc) => {
|
|
|
319
319
|
doc.addEventListener('focus', (ev) => {
|
|
320
320
|
trapKeyboardFocus(ev, doc);
|
|
321
321
|
}, true);
|
|
322
|
+
// Listen for keydown events to intercept Tab navigation.
|
|
323
|
+
// This is needed for Safari and Firefox which may skip focusable
|
|
324
|
+
// elements or allow focus to escape the overlay.
|
|
325
|
+
// It also ensures proper focus delegation for shadow DOM elements
|
|
326
|
+
// like ion-textarea.
|
|
327
|
+
doc.addEventListener('keydown', (ev) => {
|
|
328
|
+
var _a, _b, _c;
|
|
329
|
+
if (ev.key !== 'Tab' && ev.key !== 'Alt+Tab')
|
|
330
|
+
return;
|
|
331
|
+
const lastOverlay = getPresentedOverlay(doc, 'ion-alert,ion-action-sheet,ion-loading,ion-modal,ion-picker-legacy,ion-popover');
|
|
332
|
+
if (!lastOverlay || lastOverlay.classList.contains(FOCUS_TRAP_DISABLE_CLASS))
|
|
333
|
+
return;
|
|
334
|
+
const activeElement = doc.activeElement;
|
|
335
|
+
if (activeElement === lastOverlay) {
|
|
336
|
+
ev.preventDefault();
|
|
337
|
+
focusFirstDescendant(lastOverlay);
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
// Check if activeElement is inside the overlay (including shadow DOM)
|
|
341
|
+
const isInsideOverlay = activeElement
|
|
342
|
+
? lastOverlay.contains(activeElement) ||
|
|
343
|
+
(activeElement.getRootNode() instanceof ShadowRoot &&
|
|
344
|
+
lastOverlay.contains(activeElement.getRootNode().host)) ||
|
|
345
|
+
((_b = (_a = lastOverlay.shadowRoot) === null || _a === void 0 ? void 0 : _a.contains(activeElement)) !== null && _b !== void 0 ? _b : false)
|
|
346
|
+
: false;
|
|
347
|
+
if (!isInsideOverlay)
|
|
348
|
+
return;
|
|
349
|
+
// Get all focusable elements from both light and shadow DOM
|
|
350
|
+
const allFocusable = [
|
|
351
|
+
...lastOverlay.querySelectorAll(focusableQueryString),
|
|
352
|
+
...(((_c = lastOverlay.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelectorAll(focusableQueryString)) || []),
|
|
353
|
+
];
|
|
354
|
+
if (allFocusable.length === 0) {
|
|
355
|
+
ev.preventDefault();
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
// Find current element's index (accounting for shadow DOM)
|
|
359
|
+
const currentIndex = activeElement
|
|
360
|
+
? allFocusable.findIndex((el) => {
|
|
361
|
+
var _a;
|
|
362
|
+
if (el === activeElement)
|
|
363
|
+
return true;
|
|
364
|
+
if ((_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.contains(activeElement))
|
|
365
|
+
return true;
|
|
366
|
+
const rootNode = activeElement.getRootNode();
|
|
367
|
+
return rootNode instanceof ShadowRoot && rootNode.host === el;
|
|
368
|
+
})
|
|
369
|
+
: -1;
|
|
370
|
+
ev.preventDefault();
|
|
371
|
+
// Helper to focus an element, handling shadow DOM properly
|
|
372
|
+
const focusElement = (element) => {
|
|
373
|
+
const shadowRoot = element.shadowRoot;
|
|
374
|
+
if (shadowRoot) {
|
|
375
|
+
const innerFocusable = shadowRoot.querySelector(focusableQueryString);
|
|
376
|
+
if (innerFocusable && typeof element.setFocus !== 'function') {
|
|
377
|
+
focusVisibleElement(innerFocusable);
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
focusVisibleElement(element);
|
|
382
|
+
};
|
|
383
|
+
if (ev.shiftKey) {
|
|
384
|
+
// Shift+Tab: previous element, wrap to last if at first
|
|
385
|
+
if (currentIndex <= 0) {
|
|
386
|
+
focusLastDescendant(lastOverlay);
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
focusElement(allFocusable[currentIndex - 1]);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
// Tab: next element, wrap to first if at last
|
|
394
|
+
if (currentIndex < 0 || currentIndex >= allFocusable.length - 1) {
|
|
395
|
+
focusFirstDescendant(lastOverlay);
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
398
|
+
focusElement(allFocusable[currentIndex + 1]);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}, true);
|
|
322
402
|
// handle back-button click
|
|
323
403
|
doc.addEventListener('ionBackButton', (ev) => {
|
|
324
404
|
const lastOverlay = getPresentedOverlay(doc);
|
|
@@ -1,8 +1,32 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
3
|
*/
|
|
4
|
+
/**
|
|
5
|
+
* Checks if an element has a parent matching the specified selector.
|
|
6
|
+
* This handles an element in both light DOM and shadow DOM contexts.
|
|
7
|
+
* @param selector The parent selector to check for (e.g., 'ion-datetime'
|
|
8
|
+
* or 'ion-toolbar[color]').
|
|
9
|
+
* @param el The element to check.
|
|
10
|
+
* @returns `true` if the element has a parent matching the specified selector,
|
|
11
|
+
* `false` otherwise.
|
|
12
|
+
*/
|
|
4
13
|
export const hostContext = (selector, el) => {
|
|
5
|
-
|
|
14
|
+
// Check the light DOM first
|
|
15
|
+
if (el.closest(selector) !== null) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
// For attribute or class selectors (e.g., 'ion-toolbar[color]' or
|
|
19
|
+
// 'ion-toolbar.ion-color') we can only check light DOM since tagName
|
|
20
|
+
// doesn't include attributes or classes.
|
|
21
|
+
if (selector.includes('[') || selector.includes('.')) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
// Check the shadow DOM by looking at the shadow root host and
|
|
25
|
+
// converting the selector to uppercase to compare with tagName
|
|
26
|
+
const upperCaseTagName = selector.toUpperCase();
|
|
27
|
+
const rootNode = el.getRootNode();
|
|
28
|
+
const shadowHost = rootNode instanceof ShadowRoot ? rootNode.host : null;
|
|
29
|
+
return (shadowHost === null || shadowHost === void 0 ? void 0 : shadowHost.tagName) === upperCaseTagName;
|
|
6
30
|
};
|
|
7
31
|
/**
|
|
8
32
|
* Create the mode and color classes for the component based on the classes passed in
|