@ionic/core 8.8.14-dev.11784037956.17449639 → 8.8.14-dev.11784216165.1ecbf364
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/index.js +1 -1
- package/components/ion-action-sheet.js +1 -1
- package/components/ion-alert.js +1 -1
- package/components/ion-back-button.js +1 -1
- package/components/ion-button.js +1 -1
- package/components/ion-card.js +1 -1
- package/components/ion-chip.js +1 -1
- package/components/ion-datetime-button.js +1 -1
- package/components/ion-datetime.js +1 -1
- package/components/ion-fab-button.js +1 -1
- package/components/ion-img.js +1 -1
- package/components/ion-infinite-scroll-content.js +1 -1
- package/components/ion-input-password-toggle.js +1 -1
- package/components/ion-input.js +1 -1
- package/components/ion-item-option.js +1 -1
- package/components/ion-item.js +1 -1
- package/components/ion-loading.js +1 -1
- package/components/ion-menu-button.js +1 -1
- package/components/ion-menu.js +1 -1
- package/components/ion-modal.js +1 -1
- package/components/ion-nav.js +1 -1
- package/components/ion-popover.js +1 -1
- package/components/ion-progress-bar.js +1 -1
- package/components/ion-radio.js +1 -1
- package/components/ion-range.js +1 -1
- package/components/ion-refresher-content.js +1 -1
- package/components/ion-refresher.js +1 -1
- package/components/ion-reorder-group.js +1 -1
- package/components/ion-reorder.js +1 -1
- package/components/ion-ripple-effect.js +1 -1
- package/components/ion-router-link.js +1 -1
- package/components/ion-router-outlet.js +1 -1
- package/components/ion-router.js +1 -1
- package/components/ion-row.js +1 -1
- package/components/ion-searchbar.js +1 -1
- package/components/ion-segment-button.js +1 -1
- package/components/ion-segment-content.js +1 -1
- package/components/ion-segment-view.js +1 -1
- package/components/ion-segment.js +1 -1
- package/components/ion-select-modal.js +1 -1
- package/components/ion-select-option.js +1 -1
- package/components/ion-select-popover.js +1 -1
- package/components/ion-select.js +1 -1
- package/components/ion-skeleton-text.js +1 -1
- package/components/ion-spinner.js +1 -1
- package/components/ion-split-pane.js +1 -1
- package/components/ion-tab-bar.js +1 -1
- package/components/ion-tab-button.js +1 -1
- package/components/ion-tab.js +1 -1
- package/components/ion-tabs.js +1 -1
- package/components/ion-text.js +1 -1
- package/components/ion-textarea.js +1 -1
- package/components/ion-thumbnail.js +1 -1
- package/components/ion-title.js +1 -1
- package/components/ion-toast.js +1 -1
- package/components/ion-toggle.js +1 -1
- package/components/ion-toolbar.js +1 -1
- package/components/p-279dFMvg.js +4 -0
- package/components/p-BSQPZ79H.js +4 -0
- package/components/{p-BHrrc-3d.js → p-Buf_7zcy.js} +1 -1
- package/components/p-BwKpO3Is.js +4 -0
- package/components/p-C-Rx1zny.js +4 -0
- package/components/p-CHzfYZbv.js +4 -0
- package/components/p-D4h1H_hh.js +4 -0
- package/components/{p-BSEgsdFI.js → p-DhkITZ-y.js} +1 -1
- package/components/{p-5bE_Wz4Y.js → p-DpV-p5Xs.js} +1 -1
- package/components/{p-Cfx4M1Bn.js → p-Dz74mwlk.js} +1 -1
- package/components/p-LMGfIvTf.js +4 -0
- package/components/{p-BLmJ0zRm.js → p-XJWMAP8m.js} +1 -1
- package/components/p-_lHSumhG.js +4 -0
- package/components/p-j9Da6cYO.js +4 -0
- package/components/p-jOtMJMv8.js +4 -0
- package/components/{p-B60hm8Qv.js → p-r0aq7dpt.js} +1 -1
- package/components/p-uTR_dEqg.js +4 -0
- package/components/{p-rCa2eL0j.js → p-wk2QqrAo.js} +1 -1
- package/dist/cjs/config-DWdFbSNK.js +35 -0
- package/dist/cjs/index-Cueg3U4w.js +429 -0
- package/dist/cjs/index.cjs.js +6 -6
- package/dist/cjs/ion-action-sheet.cjs.entry.js +27 -7
- package/dist/cjs/ion-alert.cjs.entry.js +64 -25
- package/dist/cjs/ion-app_8.cjs.entry.js +23 -9
- package/dist/cjs/ion-avatar_3.cjs.entry.js +1 -1
- package/dist/cjs/ion-col_3.cjs.entry.js +1 -1
- package/dist/cjs/{ion-datetime_3.cjs.entry.js → ion-datetime.cjs.entry.js} +1 -639
- package/dist/cjs/ion-img.cjs.entry.js +3 -1
- package/dist/cjs/ion-infinite-scroll_2.cjs.entry.js +3 -2
- package/dist/cjs/ion-input.cjs.entry.js +4 -4
- package/dist/cjs/ion-item_8.cjs.entry.js +2 -2
- package/dist/cjs/ion-loading.cjs.entry.js +10 -5
- package/dist/cjs/ion-menu_3.cjs.entry.js +1 -1
- package/dist/cjs/ion-modal.cjs.entry.js +23 -33
- package/dist/cjs/ion-nav_2.cjs.entry.js +2 -115
- package/dist/cjs/ion-popover.cjs.entry.js +9 -5
- package/dist/cjs/ion-progress-bar.cjs.entry.js +1 -1
- package/dist/cjs/ion-radio_2.cjs.entry.js +3 -3
- package/dist/cjs/ion-range.cjs.entry.js +3 -3
- package/dist/cjs/ion-refresher_2.cjs.entry.js +6 -5
- package/dist/cjs/ion-reorder_2.cjs.entry.js +2 -2
- package/dist/cjs/ion-ripple-effect.cjs.entry.js +1 -1
- package/dist/cjs/ion-route_4.cjs.entry.js +18 -4
- package/dist/cjs/ion-searchbar.cjs.entry.js +5 -5
- package/dist/cjs/ion-segment-content.cjs.entry.js +1 -1
- package/dist/cjs/ion-segment-view.cjs.entry.js +2 -2
- package/dist/cjs/ion-segment_2.cjs.entry.js +4 -4
- package/dist/cjs/ion-select-modal.cjs.entry.js +84 -30
- package/dist/cjs/ion-select_3.cjs.entry.js +407 -49
- package/dist/cjs/ion-spinner.cjs.entry.js +1 -1
- package/dist/cjs/ion-split-pane.cjs.entry.js +2 -2
- package/dist/cjs/ion-tab-bar_2.cjs.entry.js +4 -4
- package/dist/cjs/ion-tab_2.cjs.entry.js +3 -3
- package/dist/cjs/ion-text.cjs.entry.js +2 -2
- package/dist/cjs/ion-textarea.cjs.entry.js +2 -2
- package/dist/cjs/ion-toast.cjs.entry.js +6 -5
- package/dist/cjs/ion-toggle.cjs.entry.js +3 -3
- package/dist/cjs/ionic.cjs.js +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/overlay-control-label-D2sdL2O8.js +50 -0
- package/dist/cjs/{overlays-B9UiYZ4R.js → overlays-DSmSrd_4.js} +27 -30
- package/dist/cjs/select-option-render-DTF50t5r.js +124 -0
- package/dist/collection/collection-manifest.json +6 -10
- package/dist/collection/components/action-sheet/action-sheet.ios.css +229 -2
- package/dist/collection/components/action-sheet/action-sheet.js +24 -5
- package/dist/collection/components/action-sheet/action-sheet.md.css +175 -2
- package/dist/collection/components/alert/alert.ios.css +280 -10
- package/dist/collection/components/alert/alert.js +59 -21
- package/dist/collection/components/alert/alert.md.css +269 -20
- package/dist/collection/components/img/img.js +6 -1
- package/dist/collection/components/input/input.js +8 -8
- package/dist/collection/components/loading/loading.js +7 -3
- package/dist/collection/components/modal/gestures/sheet.js +0 -8
- package/dist/collection/components/modal/gestures/swipe-to-close.js +0 -8
- package/dist/collection/components/modal/modal.ios.css +0 -8
- package/dist/collection/components/modal/modal.js +23 -17
- package/dist/collection/components/modal/modal.md.css +0 -8
- package/dist/collection/components/nav/nav.js +4 -219
- package/dist/collection/components/popover/popover.ios.css +15 -0
- package/dist/collection/components/popover/popover.js +7 -3
- package/dist/collection/components/popover/popover.md.css +15 -0
- package/dist/collection/components/progress-bar/progress-bar.js +1 -1
- package/dist/collection/components/radio/radio.js +4 -4
- 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 +1 -1
- package/dist/collection/components/reorder/reorder.js +1 -1
- 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/route/route.js +1 -1
- package/dist/collection/components/router/utils/dom.js +22 -3
- package/dist/collection/components/router-link/router-link.js +2 -2
- package/dist/collection/components/router-outlet/router-outlet.js +38 -5
- package/dist/collection/components/row/row.js +1 -1
- package/dist/collection/components/searchbar/searchbar.js +9 -9
- 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.ios.css +33 -0
- package/dist/collection/components/select/select.js +323 -16
- package/dist/collection/components/select/select.md.css +33 -0
- package/dist/collection/components/select-modal/select-modal.ios.css +219 -0
- package/dist/collection/components/select-modal/select-modal.js +79 -26
- package/dist/collection/components/select-modal/select-modal.md.css +165 -0
- package/dist/collection/components/select-option/select-option.js +67 -3
- package/dist/collection/components/select-popover/select-popover.ios.css +219 -0
- package/dist/collection/components/select-popover/select-popover.js +78 -26
- package/dist/collection/components/select-popover/select-popover.md.css +165 -0
- 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.js +2 -2
- package/dist/collection/components/thumbnail/thumbnail.js +1 -1
- 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/index.js +1 -1
- package/dist/collection/utils/overlay-control-label.js +45 -0
- package/dist/collection/utils/overlays.js +26 -29
- package/dist/collection/utils/sanitization/index.js +274 -18
- package/dist/collection/utils/select-option-render.js +119 -0
- package/dist/docs.json +497 -1189
- package/dist/esm/config-BwKpO3Is.js +31 -0
- package/dist/esm/{index-DV3sJJW8.js → index-AlrZKoWR.js} +1 -1
- package/dist/esm/index-DQSkZyOJ.js +424 -0
- package/dist/esm/index.js +3 -2
- package/dist/esm/ion-accordion_2.entry.js +1 -1
- package/dist/esm/ion-action-sheet.entry.js +27 -7
- package/dist/esm/ion-alert.entry.js +63 -24
- package/dist/esm/ion-app_8.entry.js +23 -9
- package/dist/esm/ion-avatar_3.entry.js +1 -1
- package/dist/esm/ion-back-button.entry.js +1 -1
- package/dist/esm/ion-breadcrumb_2.entry.js +1 -1
- package/dist/esm/ion-col_3.entry.js +1 -1
- package/dist/esm/{ion-datetime_3.entry.js → ion-datetime.entry.js} +5 -641
- package/dist/esm/ion-fab_3.entry.js +1 -1
- package/dist/esm/ion-img.entry.js +4 -2
- package/dist/esm/ion-infinite-scroll_2.entry.js +2 -1
- package/dist/esm/ion-input-password-toggle.entry.js +1 -1
- package/dist/esm/ion-input.entry.js +5 -5
- package/dist/esm/ion-item_8.entry.js +3 -3
- package/dist/esm/ion-loading.entry.js +9 -4
- package/dist/esm/ion-menu_3.entry.js +2 -2
- package/dist/esm/ion-modal.entry.js +23 -33
- package/dist/esm/ion-nav_2.entry.js +3 -116
- package/dist/esm/ion-popover.entry.js +9 -5
- package/dist/esm/ion-progress-bar.entry.js +1 -1
- package/dist/esm/ion-radio_2.entry.js +3 -3
- package/dist/esm/ion-range.entry.js +3 -3
- package/dist/esm/ion-refresher_2.entry.js +5 -4
- package/dist/esm/ion-reorder_2.entry.js +3 -3
- package/dist/esm/ion-ripple-effect.entry.js +1 -1
- package/dist/esm/ion-route_4.entry.js +18 -4
- package/dist/esm/ion-searchbar.entry.js +6 -6
- package/dist/esm/ion-segment-content.entry.js +1 -1
- package/dist/esm/ion-segment-view.entry.js +2 -2
- package/dist/esm/ion-segment_2.entry.js +4 -4
- package/dist/esm/ion-select-modal.entry.js +84 -30
- package/dist/esm/ion-select_3.entry.js +410 -52
- package/dist/esm/ion-spinner.entry.js +1 -1
- package/dist/esm/ion-split-pane.entry.js +2 -2
- package/dist/esm/ion-tab-bar_2.entry.js +4 -4
- package/dist/esm/ion-tab_2.entry.js +3 -3
- package/dist/esm/ion-text.entry.js +2 -2
- package/dist/esm/ion-textarea.entry.js +2 -2
- package/dist/esm/ion-toast.entry.js +5 -4
- package/dist/esm/ion-toggle.entry.js +4 -4
- package/dist/esm/ionic.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/overlay-control-label-BSQPZ79H.js +47 -0
- package/dist/esm/{overlays-Bmfhux69.js → overlays-DLNOHWNc.js} +28 -31
- package/dist/esm/select-option-render-B8nWZRnd.js +122 -0
- package/dist/html.html-data.json +52 -80
- package/dist/ionic/index.esm.js +1 -1
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/p-038eb991.entry.js +4 -0
- package/dist/ionic/{p-3a126bca.entry.js → p-259d0d98.entry.js} +1 -1
- package/dist/ionic/{p-fabcce6c.entry.js → p-341032b3.entry.js} +1 -1
- package/dist/ionic/{p-3a7d1e91.entry.js → p-4502a274.entry.js} +1 -1
- package/dist/ionic/p-4621c387.entry.js +4 -0
- package/dist/ionic/p-4ace7762.entry.js +4 -0
- package/dist/ionic/p-4bb3eb60.entry.js +4 -0
- package/dist/ionic/p-4e9ec5c5.entry.js +4 -0
- package/dist/ionic/{p-874b4bd8.entry.js → p-51cd1643.entry.js} +1 -1
- package/dist/ionic/p-5c3ec490.entry.js +4 -0
- package/dist/ionic/p-5d1ac2c7.entry.js +4 -0
- package/dist/ionic/{p-3ae5f277.entry.js → p-627fabd9.entry.js} +1 -1
- package/dist/ionic/{p-e0be05c5.entry.js → p-629e4703.entry.js} +1 -1
- package/dist/ionic/p-700795f6.entry.js +4 -0
- package/dist/ionic/{p-5d1da0a2.entry.js → p-76e92a84.entry.js} +1 -1
- package/dist/ionic/p-79a36078.entry.js +4 -0
- package/dist/ionic/{p-9f1103ce.entry.js → p-7a37b3ce.entry.js} +1 -1
- package/dist/ionic/{p-3353c229.entry.js → p-80b44b3c.entry.js} +1 -1
- package/dist/ionic/p-913b218a.entry.js +4 -0
- package/dist/ionic/{p-390ca786.entry.js → p-9177f4ac.entry.js} +1 -1
- package/dist/ionic/{p-DV3sJJW8.js → p-AlrZKoWR.js} +1 -1
- package/dist/ionic/p-BDtODLZ4.js +4 -0
- package/dist/ionic/p-BSQPZ79H.js +4 -0
- package/dist/ionic/p-BwKpO3Is.js +4 -0
- package/dist/ionic/p-Cg5-OQYy.js +4 -0
- package/dist/ionic/p-DCOvXkOm.js +4 -0
- package/dist/ionic/p-a18dcb3c.entry.js +4 -0
- package/dist/ionic/{p-4858af1f.entry.js → p-a5213260.entry.js} +1 -1
- package/dist/ionic/{p-37e720da.entry.js → p-a7628bc7.entry.js} +1 -1
- package/dist/ionic/p-a9a33367.entry.js +4 -0
- package/dist/ionic/p-ad728198.entry.js +4 -0
- package/dist/ionic/{p-ef4c3bee.entry.js → p-b1599fca.entry.js} +1 -1
- package/dist/ionic/{p-84d5ce05.entry.js → p-b9ac1fe0.entry.js} +1 -1
- package/dist/ionic/p-bfc8c629.entry.js +4 -0
- package/dist/ionic/p-c08e666a.entry.js +4 -0
- package/dist/ionic/p-c474f471.entry.js +4 -0
- package/dist/ionic/{p-cf91e738.entry.js → p-c93553d2.entry.js} +1 -1
- package/dist/ionic/p-ce7992c4.entry.js +4 -0
- package/dist/ionic/{p-75dc25ba.entry.js → p-d2c7f046.entry.js} +1 -1
- package/dist/ionic/{p-c4d8641b.entry.js → p-d8387b99.entry.js} +1 -1
- package/dist/ionic/{p-9a65ac7f.entry.js → p-db1b6738.entry.js} +1 -1
- package/dist/ionic/p-ed797c72.entry.js +4 -0
- package/dist/ionic/{p-8eb8ee76.entry.js → p-ef93ca92.entry.js} +1 -1
- package/dist/ionic/p-f09f9642.entry.js +4 -0
- package/dist/ionic/p-f1c06f82.entry.js +4 -0
- package/dist/ionic/p-f718fccb.entry.js +4 -0
- package/dist/ionic/{p-0fa9c382.entry.js → p-fe4aa1db.entry.js} +1 -1
- package/dist/types/components/img/img.d.ts +2 -0
- package/dist/types/components/input/input.d.ts +1 -1
- package/dist/types/components/modal/modal.d.ts +11 -4
- package/dist/types/components/nav/nav-interface.d.ts +0 -1
- package/dist/types/components/nav/nav.d.ts +2 -22
- package/dist/types/components/route/route.d.ts +1 -1
- package/dist/types/components/router-outlet/router-outlet.d.ts +7 -0
- package/dist/types/components/searchbar/searchbar.d.ts +1 -1
- package/dist/types/components/select/select-interface.d.ts +31 -0
- package/dist/types/components/select/select.d.ts +18 -0
- package/dist/types/components/select-option/select-option.d.ts +42 -1
- package/dist/types/components.d.ts +74 -303
- package/dist/types/index.d.ts +1 -1
- package/dist/types/interface.d.ts +0 -1
- package/dist/types/utils/config.d.ts +0 -8
- package/dist/types/utils/overlay-control-label.d.ts +32 -0
- package/dist/types/utils/overlays.d.ts +11 -9
- package/dist/types/utils/sanitization/index.d.ts +58 -2
- package/dist/types/utils/select-option-render.d.ts +53 -0
- package/hydrate/index.js +1410 -1292
- package/hydrate/index.mjs +1410 -1292
- package/package.json +37 -5
- package/components/ion-picker-legacy-column.d.ts +0 -11
- package/components/ion-picker-legacy-column.js +0 -4
- package/components/ion-picker-legacy.d.ts +0 -11
- package/components/ion-picker-legacy.js +0 -4
- package/components/p-B1BWKArA.js +0 -4
- package/components/p-B4PlLGHT.js +0 -4
- package/components/p-BFsEcwW9.js +0 -4
- package/components/p-CFRyvUvJ.js +0 -4
- package/components/p-CU5rbWAW.js +0 -4
- package/components/p-CgLiHbz0.js +0 -4
- package/components/p-MLyEeL3Q.js +0 -4
- package/components/p-PgMVWD8U.js +0 -4
- package/components/p-k_E4tX5Z.js +0 -4
- package/dist/cjs/config-xninhj0J.js +0 -201
- package/dist/collection/components/picker-legacy/animations/ios.enter.js +0 -27
- package/dist/collection/components/picker-legacy/animations/ios.leave.js +0 -23
- package/dist/collection/components/picker-legacy/picker-interface.js +0 -1
- package/dist/collection/components/picker-legacy/picker.ios.css +0 -300
- package/dist/collection/components/picker-legacy/picker.js +0 -890
- package/dist/collection/components/picker-legacy/picker.md.css +0 -287
- package/dist/collection/components/picker-legacy-column/picker-column.ios.css +0 -231
- package/dist/collection/components/picker-legacy-column/picker-column.js +0 -422
- package/dist/collection/components/picker-legacy-column/picker-column.md.css +0 -222
- package/dist/collection/components/picker-legacy-column/test/test.utils.js +0 -43
- package/dist/esm/config-DQCONYYp.js +0 -195
- package/dist/ionic/p-01f81ea5.entry.js +0 -4
- package/dist/ionic/p-02473803.entry.js +0 -4
- package/dist/ionic/p-20b1a044.entry.js +0 -4
- package/dist/ionic/p-21eb76d5.entry.js +0 -4
- package/dist/ionic/p-27d30585.entry.js +0 -4
- package/dist/ionic/p-2bb2cb18.entry.js +0 -4
- package/dist/ionic/p-2f529a55.entry.js +0 -4
- package/dist/ionic/p-485fda23.entry.js +0 -4
- package/dist/ionic/p-48fa7fb1.entry.js +0 -4
- package/dist/ionic/p-4baa5b82.entry.js +0 -4
- package/dist/ionic/p-4d9181c7.entry.js +0 -4
- package/dist/ionic/p-50e1194a.entry.js +0 -4
- package/dist/ionic/p-532eb373.entry.js +0 -4
- package/dist/ionic/p-8fce95d5.entry.js +0 -4
- package/dist/ionic/p-B0zdMdR0.js +0 -4
- package/dist/ionic/p-DzWaWHGc.js +0 -4
- package/dist/ionic/p-a21add2f.entry.js +0 -4
- package/dist/ionic/p-ab60b48a.entry.js +0 -4
- package/dist/ionic/p-ec090e0a.entry.js +0 -4
- package/dist/ionic/p-f386f6ae.entry.js +0 -4
- package/dist/ionic/p-f994dc44.entry.js +0 -4
- package/dist/ionic/p-fd76f647.entry.js +0 -4
- package/dist/ionic/p-fda60562.entry.js +0 -4
- package/dist/types/components/picker-legacy/animations/ios.enter.d.ts +0 -5
- package/dist/types/components/picker-legacy/animations/ios.leave.d.ts +0 -5
- package/dist/types/components/picker-legacy/picker-interface.d.ts +0 -52
- package/dist/types/components/picker-legacy/picker.d.ts +0 -158
- package/dist/types/components/picker-legacy-column/picker-column.d.ts +0 -46
- package/dist/types/components/picker-legacy-column/test/test.utils.d.ts +0 -9
|
@@ -2,14 +2,17 @@
|
|
|
2
2
|
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
3
|
*/
|
|
4
4
|
import { Build, Host, h, forceUpdate } from "@stencil/core";
|
|
5
|
+
import { ENABLE_HTML_CONTENT_DEFAULT } from "../../utils/config";
|
|
5
6
|
import { compareOptions, createNotchController, isOptionSelected, checkInvalidState } from "../../utils/forms/index";
|
|
6
7
|
import { focusVisibleElement, renderHiddenInput, inheritAttributes } from "../../utils/helpers";
|
|
7
8
|
import { printIonWarning } from "../../utils/logging/index";
|
|
8
9
|
import { actionSheetController, alertController, popoverController, modalController } from "../../utils/overlays";
|
|
9
10
|
import { isRTL } from "../../utils/rtl/index";
|
|
11
|
+
import { reflectPropertiesToAttributes, sanitizeDOMTree } from "../../utils/sanitization/index";
|
|
10
12
|
import { createColorClasses, hostContext } from "../../utils/theme";
|
|
11
13
|
import { watchForOptions } from "../../utils/watch-options";
|
|
12
14
|
import { caretDownSharp, chevronExpand } from "ionicons/icons";
|
|
15
|
+
import { config } from "../../global/config";
|
|
13
16
|
import { getIonMode } from "../../global/ionic-global";
|
|
14
17
|
// TODO(FW-2832): types
|
|
15
18
|
/**
|
|
@@ -37,6 +40,7 @@ export class Select {
|
|
|
37
40
|
this.helperTextId = `${this.inputId}-helper-text`;
|
|
38
41
|
this.errorTextId = `${this.inputId}-error-text`;
|
|
39
42
|
this.inheritedAttributes = {};
|
|
43
|
+
this.customHTMLEnabled = config.get('innerHTMLTemplatesEnabled', ENABLE_HTML_CONTENT_DEFAULT);
|
|
40
44
|
this.isExpanded = false;
|
|
41
45
|
/**
|
|
42
46
|
* The `hasFocus` state ensures the focus class is
|
|
@@ -162,9 +166,40 @@ export class Select {
|
|
|
162
166
|
this.emitStyle();
|
|
163
167
|
}
|
|
164
168
|
setValue(value) {
|
|
169
|
+
if (this.isValueEqual(this.value, value)) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
165
172
|
this.value = value;
|
|
166
173
|
this.ionChange.emit({ value });
|
|
167
174
|
}
|
|
175
|
+
isValueEqual(currentValue, newValue) {
|
|
176
|
+
if (this.multiple) {
|
|
177
|
+
const currentArr = Array.isArray(currentValue) ? currentValue : [];
|
|
178
|
+
const newArr = Array.isArray(newValue) ? newValue : [];
|
|
179
|
+
if (currentArr.length !== newArr.length) {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
// Multiset compare: each new value must match a distinct current value.
|
|
183
|
+
// A plain `every(isOptionSelected)` would accept ['a','a'] as equal to
|
|
184
|
+
// ['a','b'] when both 'a' and 'b' map to options whose values overlap.
|
|
185
|
+
const remaining = currentArr.slice();
|
|
186
|
+
return newArr.every((val) => {
|
|
187
|
+
const idx = remaining.findIndex((c) => compareOptions(c, val, this.compareWith));
|
|
188
|
+
if (idx === -1) {
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
remaining.splice(idx, 1);
|
|
192
|
+
return true;
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
if (currentValue == null && newValue == null) {
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
if (currentValue == null || newValue == null) {
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
return compareOptions(currentValue, newValue, this.compareWith);
|
|
202
|
+
}
|
|
168
203
|
async connectedCallback() {
|
|
169
204
|
const { el } = this;
|
|
170
205
|
this.notchController = createNotchController(el, () => this.notchSpacerEl, () => this.labelSlot);
|
|
@@ -399,10 +434,11 @@ export class Select {
|
|
|
399
434
|
.join(' ');
|
|
400
435
|
const optClass = `${OPTION_CLASS} ${copyClasses}`;
|
|
401
436
|
const isSelected = isOptionSelected(selectValue, value, this.compareWith);
|
|
437
|
+
const { content, startContent, endContent } = extractOptionContent(option, this.customHTMLEnabled);
|
|
402
438
|
return {
|
|
403
|
-
|
|
404
|
-
text: option.textContent,
|
|
439
|
+
text: content !== null && content !== void 0 ? content : '',
|
|
405
440
|
cssClass: optClass,
|
|
441
|
+
disabled: option.disabled,
|
|
406
442
|
handler: () => {
|
|
407
443
|
this.setValue(value);
|
|
408
444
|
},
|
|
@@ -410,6 +446,9 @@ export class Select {
|
|
|
410
446
|
'aria-checked': isSelected ? 'true' : 'false',
|
|
411
447
|
role: 'radio',
|
|
412
448
|
},
|
|
449
|
+
startContent,
|
|
450
|
+
endContent,
|
|
451
|
+
description: option.description,
|
|
413
452
|
};
|
|
414
453
|
});
|
|
415
454
|
// Add "cancel" button
|
|
@@ -430,13 +469,19 @@ export class Select {
|
|
|
430
469
|
.filter((cls) => cls !== 'hydrated')
|
|
431
470
|
.join(' ');
|
|
432
471
|
const optClass = `${OPTION_CLASS} ${copyClasses}`;
|
|
472
|
+
const { content, startContent, endContent } = extractOptionContent(option, this.customHTMLEnabled);
|
|
433
473
|
return {
|
|
434
474
|
type: inputType,
|
|
435
475
|
cssClass: optClass,
|
|
436
|
-
label:
|
|
476
|
+
label: content !== null && content !== void 0 ? content : '',
|
|
437
477
|
value,
|
|
438
478
|
checked: isOptionSelected(selectValue, value, this.compareWith),
|
|
439
479
|
disabled: option.disabled,
|
|
480
|
+
startContent,
|
|
481
|
+
endContent,
|
|
482
|
+
description: option.description,
|
|
483
|
+
labelPlacement: option.labelPlacement,
|
|
484
|
+
justify: option.justify,
|
|
440
485
|
};
|
|
441
486
|
});
|
|
442
487
|
return alertInputs;
|
|
@@ -449,8 +494,9 @@ export class Select {
|
|
|
449
494
|
.filter((cls) => cls !== 'hydrated')
|
|
450
495
|
.join(' ');
|
|
451
496
|
const optClass = `${OPTION_CLASS} ${copyClasses}`;
|
|
497
|
+
const { content, startContent, endContent } = extractOptionContent(option, this.customHTMLEnabled);
|
|
452
498
|
return {
|
|
453
|
-
text:
|
|
499
|
+
text: content !== null && content !== void 0 ? content : '',
|
|
454
500
|
cssClass: optClass,
|
|
455
501
|
value,
|
|
456
502
|
checked: isOptionSelected(selectValue, value, this.compareWith),
|
|
@@ -461,6 +507,11 @@ export class Select {
|
|
|
461
507
|
this.close();
|
|
462
508
|
}
|
|
463
509
|
},
|
|
510
|
+
startContent,
|
|
511
|
+
endContent,
|
|
512
|
+
description: option.description,
|
|
513
|
+
labelPlacement: option.labelPlacement,
|
|
514
|
+
justify: option.justify,
|
|
464
515
|
};
|
|
465
516
|
});
|
|
466
517
|
return popoverOptions;
|
|
@@ -493,15 +544,21 @@ export class Select {
|
|
|
493
544
|
ionShadowTarget: this.nativeWrapperEl,
|
|
494
545
|
} });
|
|
495
546
|
}
|
|
547
|
+
const options = this.createOverlaySelectOptions(this.childOpts, value);
|
|
548
|
+
const hasRichContent = options.some((opt) => opt.startContent || opt.endContent || opt.description);
|
|
496
549
|
const popoverOpts = Object.assign(Object.assign({ mode,
|
|
497
550
|
event, alignment: 'center', size,
|
|
498
|
-
showBackdrop }, interfaceOptions), { component: 'ion-select-popover', cssClass: [
|
|
551
|
+
showBackdrop }, interfaceOptions), { component: 'ion-select-popover', cssClass: [
|
|
552
|
+
'select-popover',
|
|
553
|
+
hasRichContent ? 'select-popover-rich-content' : undefined,
|
|
554
|
+
interfaceOptions.cssClass,
|
|
555
|
+
], componentProps: {
|
|
499
556
|
header: interfaceOptions.header,
|
|
500
557
|
subHeader: interfaceOptions.subHeader,
|
|
501
558
|
message: interfaceOptions.message,
|
|
502
559
|
multiple,
|
|
503
560
|
value,
|
|
504
|
-
options
|
|
561
|
+
options,
|
|
505
562
|
} });
|
|
506
563
|
/**
|
|
507
564
|
* Workaround for Stencil to autodefine
|
|
@@ -628,12 +685,18 @@ export class Select {
|
|
|
628
685
|
}
|
|
629
686
|
return;
|
|
630
687
|
}
|
|
631
|
-
|
|
688
|
+
/**
|
|
689
|
+
* Returns the text to display in the select based on the selected value.
|
|
690
|
+
*
|
|
691
|
+
* @param useHTML If `true`, the returned text will include any custom HTML content from the selected option. If `false`, the returned text will be plain text without any HTML. Defaults to `false`.
|
|
692
|
+
* @returns The text to display in the select, either with or without HTML based on the `useHTML` parameter.
|
|
693
|
+
*/
|
|
694
|
+
getText(useHTML = false) {
|
|
632
695
|
const selectedText = this.selectedText;
|
|
633
696
|
if (selectedText != null && selectedText !== '') {
|
|
634
697
|
return selectedText;
|
|
635
698
|
}
|
|
636
|
-
return generateText(this.childOpts, this.value, this.compareWith);
|
|
699
|
+
return generateText(this.childOpts, this.value, this.compareWith, useHTML);
|
|
637
700
|
}
|
|
638
701
|
setFocus() {
|
|
639
702
|
if (this.focusEl) {
|
|
@@ -703,6 +766,47 @@ export class Select {
|
|
|
703
766
|
*/
|
|
704
767
|
return this.renderLabel();
|
|
705
768
|
}
|
|
769
|
+
/**
|
|
770
|
+
* Wraps text nodes in the select text with span elements
|
|
771
|
+
* so spacing can be added between elements without
|
|
772
|
+
* changing the display to prevent losing the ellipses
|
|
773
|
+
* behavior.
|
|
774
|
+
*
|
|
775
|
+
* Only wraps when the string contains HTML elements
|
|
776
|
+
* alongside text.
|
|
777
|
+
*/
|
|
778
|
+
wrapSelectTextNodes(html) {
|
|
779
|
+
const temp = document.createElement('div');
|
|
780
|
+
temp.innerHTML = html;
|
|
781
|
+
const hasElements = Array.from(temp.childNodes).some((n) => n.nodeType === Node.ELEMENT_NODE);
|
|
782
|
+
// Return the plain text
|
|
783
|
+
if (!hasElements) {
|
|
784
|
+
return html;
|
|
785
|
+
}
|
|
786
|
+
Array.from(temp.childNodes).forEach((node) => {
|
|
787
|
+
var _a, _b, _c, _d;
|
|
788
|
+
if (node.nodeType === Node.TEXT_NODE && ((_a = node.textContent) === null || _a === void 0 ? void 0 : _a.trim())) {
|
|
789
|
+
const text = node.textContent;
|
|
790
|
+
/**
|
|
791
|
+
* Split comma separator from the text content
|
|
792
|
+
* e.g., ", Bacon" becomes ", " text node + <span>Bacon</span>.
|
|
793
|
+
*/
|
|
794
|
+
const commaMatch = text.match(/^(,\s*)(.*)/);
|
|
795
|
+
if (commaMatch) {
|
|
796
|
+
const commaNode = document.createTextNode(commaMatch[1]);
|
|
797
|
+
const wrapper = document.createElement('span');
|
|
798
|
+
wrapper.textContent = commaMatch[2];
|
|
799
|
+
(_b = node.parentNode) === null || _b === void 0 ? void 0 : _b.replaceChild(wrapper, node);
|
|
800
|
+
(_c = wrapper.parentNode) === null || _c === void 0 ? void 0 : _c.insertBefore(commaNode, wrapper);
|
|
801
|
+
return;
|
|
802
|
+
}
|
|
803
|
+
const wrapper = document.createElement('span');
|
|
804
|
+
(_d = node.parentNode) === null || _d === void 0 ? void 0 : _d.replaceChild(wrapper, node);
|
|
805
|
+
wrapper.appendChild(node);
|
|
806
|
+
}
|
|
807
|
+
});
|
|
808
|
+
return temp.innerHTML;
|
|
809
|
+
}
|
|
706
810
|
/**
|
|
707
811
|
* Renders either the placeholder
|
|
708
812
|
* or the selected values based on
|
|
@@ -710,7 +814,7 @@ export class Select {
|
|
|
710
814
|
*/
|
|
711
815
|
renderSelectText() {
|
|
712
816
|
const { placeholder } = this;
|
|
713
|
-
const displayValue = this.getText();
|
|
817
|
+
const displayValue = this.getText(true);
|
|
714
818
|
let addPlaceholderClass = false;
|
|
715
819
|
let selectText = displayValue;
|
|
716
820
|
if (selectText === '' && placeholder !== undefined) {
|
|
@@ -722,6 +826,10 @@ export class Select {
|
|
|
722
826
|
'select-placeholder': addPlaceholderClass,
|
|
723
827
|
};
|
|
724
828
|
const textPart = addPlaceholderClass ? 'placeholder' : 'text';
|
|
829
|
+
if (this.customHTMLEnabled) {
|
|
830
|
+
const wrapped = this.wrapSelectTextNodes(selectText);
|
|
831
|
+
return h("div", { "aria-hidden": "true", class: selectTextClasses, part: textPart, innerHTML: wrapped });
|
|
832
|
+
}
|
|
725
833
|
return (h("div", { "aria-hidden": "true", class: selectTextClasses, part: textPart }, selectText));
|
|
726
834
|
}
|
|
727
835
|
/**
|
|
@@ -744,6 +852,7 @@ export class Select {
|
|
|
744
852
|
get ariaLabel() {
|
|
745
853
|
var _a;
|
|
746
854
|
const { placeholder, inheritedAttributes } = this;
|
|
855
|
+
// Get the plain text from the selected text
|
|
747
856
|
const displayValue = this.getText();
|
|
748
857
|
// The aria label should be preferred over visible text if both are specified
|
|
749
858
|
const definedLabel = (_a = inheritedAttributes['aria-label']) !== null && _a !== void 0 ? _a : this.labelText;
|
|
@@ -837,7 +946,7 @@ export class Select {
|
|
|
837
946
|
* TODO(FW-5592): Remove hasStartEndSlots condition
|
|
838
947
|
*/
|
|
839
948
|
const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || isExpanded || hasStartEndSlots));
|
|
840
|
-
return (h(Host, { key: '
|
|
949
|
+
return (h(Host, { key: 'a3036d51e0db13332641e9523264ddd1ab031912', onClick: this.onClick, class: createColorClasses(this.color, {
|
|
841
950
|
[mode]: true,
|
|
842
951
|
'in-item': inItem,
|
|
843
952
|
'in-item-color': hostContext('ion-item.ion-color', el),
|
|
@@ -855,7 +964,7 @@ export class Select {
|
|
|
855
964
|
[`select-justify-${justify}`]: justifyEnabled,
|
|
856
965
|
[`select-shape-${shape}`]: shape !== undefined,
|
|
857
966
|
[`select-label-placement-${labelPlacement}`]: true,
|
|
858
|
-
}) }, h("label", { key: '
|
|
967
|
+
}) }, h("label", { key: '58b77f683499b958840721bdb59a9bf822c7f218', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick, part: "wrapper" }, this.renderLabelContainer(), h("div", { key: '9e68d96524c1b87d6cb1bdce79fa86f2022be04a', class: "select-wrapper-inner", part: "inner" }, h("slot", { key: 'c9bcc5d684d2cefadff6ad3ec91498d5b405afc5', name: "start" }), h("div", { key: '5405bc15ffb3437ca00c64fbbc83d8eb2631c4ea', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox()), h("slot", { key: '95e2f041c8517afb1cc6bddb2c3c38cf41f2376e', name: "end" }), !hasFloatingOrStackedLabel && this.renderSelectIcon()), hasFloatingOrStackedLabel && this.renderSelectIcon(), shouldRenderHighlight && h("div", { key: 'f3d2410f678ea22a107121aea1bbda197a618ed6', class: "select-highlight" })), this.renderBottomContent()));
|
|
859
968
|
}
|
|
860
969
|
static get is() { return "ion-select"; }
|
|
861
970
|
static get encapsulation() { return "shadow"; }
|
|
@@ -1515,25 +1624,223 @@ const parseValue = (value) => {
|
|
|
1515
1624
|
}
|
|
1516
1625
|
return value.toString();
|
|
1517
1626
|
};
|
|
1518
|
-
const generateText = (opts, value, compareWith) => {
|
|
1627
|
+
const generateText = (opts, value, compareWith, useHTML = false) => {
|
|
1519
1628
|
if (value === undefined) {
|
|
1520
1629
|
return '';
|
|
1521
1630
|
}
|
|
1522
1631
|
if (Array.isArray(value)) {
|
|
1523
1632
|
return value
|
|
1524
|
-
.map((v) => textForValue(opts, v, compareWith))
|
|
1633
|
+
.map((v) => textForValue(opts, v, compareWith, useHTML))
|
|
1525
1634
|
.filter((opt) => opt !== null)
|
|
1526
1635
|
.join(', ');
|
|
1527
1636
|
}
|
|
1528
1637
|
else {
|
|
1529
|
-
return textForValue(opts, value, compareWith) || '';
|
|
1638
|
+
return textForValue(opts, value, compareWith, useHTML) || '';
|
|
1530
1639
|
}
|
|
1531
1640
|
};
|
|
1532
|
-
|
|
1641
|
+
/**
|
|
1642
|
+
* Returns the display text for a given value from the list of options.
|
|
1643
|
+
* When `useHTML` is true, returns sanitized HTML for the select text.
|
|
1644
|
+
* When `useHTML` is false, returns plain text for aria-label and other
|
|
1645
|
+
* text-only contexts.
|
|
1646
|
+
*
|
|
1647
|
+
* @param opts - The list of ion-select-option elements.
|
|
1648
|
+
* @param value - The value to find the matching option for.
|
|
1649
|
+
* @param compareWith - Custom comparison function or property name.
|
|
1650
|
+
* @param useHTML - If true, returns HTML string. If false, returns plain text.
|
|
1651
|
+
*/
|
|
1652
|
+
const textForValue = (opts, value, compareWith, useHTML = false) => {
|
|
1533
1653
|
const selectOpt = opts.find((opt) => {
|
|
1534
1654
|
return compareOptions(value, getOptionValue(opt), compareWith);
|
|
1535
1655
|
});
|
|
1536
|
-
|
|
1656
|
+
const customHTMLEnabled = config.get('innerHTMLTemplatesEnabled', ENABLE_HTML_CONTENT_DEFAULT);
|
|
1657
|
+
if (!selectOpt) {
|
|
1658
|
+
return null;
|
|
1659
|
+
}
|
|
1660
|
+
// Return sanitized HTML for the select text
|
|
1661
|
+
if (customHTMLEnabled && useHTML) {
|
|
1662
|
+
return getOptionContent(selectOpt, undefined, true);
|
|
1663
|
+
}
|
|
1664
|
+
/**
|
|
1665
|
+
* When custom HTML is enabled, extract only the default slot content.
|
|
1666
|
+
* This ensures aria-label and other text-only contexts read only
|
|
1667
|
+
* the relevant option text.
|
|
1668
|
+
*/
|
|
1669
|
+
if (customHTMLEnabled) {
|
|
1670
|
+
const content = getOptionContent(selectOpt);
|
|
1671
|
+
if (typeof content === 'string') {
|
|
1672
|
+
return content;
|
|
1673
|
+
}
|
|
1674
|
+
/**
|
|
1675
|
+
* Elements were found in the default slot, extract and concatenate
|
|
1676
|
+
* their text content while trimming whitespace.
|
|
1677
|
+
*/
|
|
1678
|
+
if (content) {
|
|
1679
|
+
const texts = Array.from(content.childNodes)
|
|
1680
|
+
.map((n) => { var _a; return (_a = n.textContent) === null || _a === void 0 ? void 0 : _a.trim(); })
|
|
1681
|
+
.filter((t) => t);
|
|
1682
|
+
return texts.join(' ') || null;
|
|
1683
|
+
}
|
|
1684
|
+
// Empty option
|
|
1685
|
+
return null;
|
|
1686
|
+
}
|
|
1687
|
+
return getDefaultSlotPlainText(selectOpt);
|
|
1688
|
+
};
|
|
1689
|
+
/**
|
|
1690
|
+
* Trims whitespace from all text nodes within a DOM tree.
|
|
1691
|
+
* This prevents invisible layout shifts and unwanted gaps between
|
|
1692
|
+
* elements when HTML content is injected via innerHTML or cloneNode,
|
|
1693
|
+
* as browsers preserve whitespace (tabs, newlines, spaces) from
|
|
1694
|
+
* the original source markup.
|
|
1695
|
+
*
|
|
1696
|
+
* @param node The root node to start trimming text nodes from.
|
|
1697
|
+
*/
|
|
1698
|
+
const trimTextNodes = (node) => {
|
|
1699
|
+
node.childNodes.forEach((child) => {
|
|
1700
|
+
var _a;
|
|
1701
|
+
if (child.nodeType === Node.TEXT_NODE) {
|
|
1702
|
+
child.textContent = ((_a = child.textContent) === null || _a === void 0 ? void 0 : _a.trim()) || '';
|
|
1703
|
+
}
|
|
1704
|
+
else if (child.nodeType === Node.ELEMENT_NODE) {
|
|
1705
|
+
trimTextNodes(child);
|
|
1706
|
+
}
|
|
1707
|
+
});
|
|
1708
|
+
};
|
|
1709
|
+
/**
|
|
1710
|
+
* Extracts and clones content from an `ion-select-option` element
|
|
1711
|
+
* for rendering within overlay interfaces or the select text when `customHTMLEnabled` is `true`.
|
|
1712
|
+
*
|
|
1713
|
+
* @param option - The `ion-select-option` element to extract content from.
|
|
1714
|
+
* @param slotName - Optional slot name to extract. If omitted, extracts the default slot content.
|
|
1715
|
+
* @param useHTML - If `true`, the returned string will include any custom HTML content. If `false`, the returned string will be plain text without any HTML.
|
|
1716
|
+
* @returns When `useHTML` is `true`, a sanitized HTML string. When `false`, a
|
|
1717
|
+
* div element containing cloned child nodes. Returns `null` if no matching
|
|
1718
|
+
* content is found.
|
|
1719
|
+
*/
|
|
1720
|
+
const getOptionContent = (option, slotName, useHTML = false) => {
|
|
1721
|
+
let nodes;
|
|
1722
|
+
if (slotName) {
|
|
1723
|
+
// Named slot: get elements with matching slot attribute
|
|
1724
|
+
nodes = Array.from(option.children).filter((el) => el.getAttribute('slot') === slotName);
|
|
1725
|
+
}
|
|
1726
|
+
else {
|
|
1727
|
+
// Default slot: get nodes without a slot attribute
|
|
1728
|
+
const defaultSlot = getOptionDefaultSlot(option) || [];
|
|
1729
|
+
nodes = defaultSlot.filter((node) => {
|
|
1730
|
+
var _a;
|
|
1731
|
+
/**
|
|
1732
|
+
* Exclude whitespace-only text nodes (newline noise between
|
|
1733
|
+
* markup elements). Element nodes are always kept, even when
|
|
1734
|
+
* their textContent is empty (e.g. <svg>, <img>).
|
|
1735
|
+
*/
|
|
1736
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
1737
|
+
return ((_a = node.textContent) === null || _a === void 0 ? void 0 : _a.trim().length) !== 0;
|
|
1738
|
+
}
|
|
1739
|
+
return true;
|
|
1740
|
+
});
|
|
1741
|
+
}
|
|
1742
|
+
if (nodes.length === 0) {
|
|
1743
|
+
return null;
|
|
1744
|
+
}
|
|
1745
|
+
// Return plain text if no elements are found
|
|
1746
|
+
if (!slotName && nodes.every((n) => n.nodeType === Node.TEXT_NODE)) {
|
|
1747
|
+
return nodes.map((n) => { var _a; return (_a = n.textContent) === null || _a === void 0 ? void 0 : _a.trim(); }).join(' ') || null;
|
|
1748
|
+
}
|
|
1749
|
+
/**
|
|
1750
|
+
* Mirror known custom-element properties (e.g. ion-icon's `icon`)
|
|
1751
|
+
* onto attributes before cloning. Frameworks like Vue set these as
|
|
1752
|
+
* DOM properties, which `cloneNode` doesn't copy, so without this
|
|
1753
|
+
* step the cloned overlay copy renders without the prop's value.
|
|
1754
|
+
*/
|
|
1755
|
+
nodes.forEach((n) => {
|
|
1756
|
+
if (n.nodeType === Node.ELEMENT_NODE) {
|
|
1757
|
+
reflectPropertiesToAttributes(n);
|
|
1758
|
+
}
|
|
1759
|
+
});
|
|
1760
|
+
// Clone each node into a temporary container
|
|
1761
|
+
const container = document.createElement('div');
|
|
1762
|
+
nodes.forEach((n) => {
|
|
1763
|
+
var _a;
|
|
1764
|
+
const clone = n.cloneNode(true);
|
|
1765
|
+
if (clone.nodeType === Node.TEXT_NODE) {
|
|
1766
|
+
clone.textContent = ((_a = clone.textContent) === null || _a === void 0 ? void 0 : _a.trim()) || '';
|
|
1767
|
+
}
|
|
1768
|
+
else {
|
|
1769
|
+
trimTextNodes(clone);
|
|
1770
|
+
}
|
|
1771
|
+
container.appendChild(clone);
|
|
1772
|
+
});
|
|
1773
|
+
/**
|
|
1774
|
+
* Sanitize the cloned DOM in place. Trusted attributes (size, color,
|
|
1775
|
+
* shape, etc.) are preserved; event handlers, javascript: URLs, and
|
|
1776
|
+
* blocked tags are stripped.
|
|
1777
|
+
*/
|
|
1778
|
+
sanitizeDOMTree(container);
|
|
1779
|
+
if (useHTML) {
|
|
1780
|
+
return container.innerHTML.trim() || null;
|
|
1781
|
+
}
|
|
1782
|
+
return container;
|
|
1783
|
+
};
|
|
1784
|
+
/**
|
|
1785
|
+
* Returns the child nodes that belong to the default slot of an
|
|
1786
|
+
* option element, excluding any nodes that are assigned to named
|
|
1787
|
+
* slots.
|
|
1788
|
+
*
|
|
1789
|
+
* @param option - The `ion-select-option` element to extract default-slot nodes from.
|
|
1790
|
+
* @returns An array of default slot nodes, or `null` if none are found.
|
|
1791
|
+
*/
|
|
1792
|
+
const getOptionDefaultSlot = (option) => {
|
|
1793
|
+
const defaultSlotNodes = Array.from(option.childNodes).filter((node) => {
|
|
1794
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
1795
|
+
return !node.hasAttribute('slot');
|
|
1796
|
+
}
|
|
1797
|
+
return node.nodeType === Node.TEXT_NODE;
|
|
1798
|
+
});
|
|
1799
|
+
if (defaultSlotNodes.length === 0) {
|
|
1800
|
+
return null;
|
|
1801
|
+
}
|
|
1802
|
+
return defaultSlotNodes;
|
|
1803
|
+
};
|
|
1804
|
+
/**
|
|
1805
|
+
* Extracts plain text from only the default slot of an option,
|
|
1806
|
+
* excluding content assigned to named slots (start/end).
|
|
1807
|
+
*/
|
|
1808
|
+
const getDefaultSlotPlainText = (option) => {
|
|
1809
|
+
const texts = Array.from(option.childNodes)
|
|
1810
|
+
.filter((node) => {
|
|
1811
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
1812
|
+
return !node.hasAttribute('slot');
|
|
1813
|
+
}
|
|
1814
|
+
return node.nodeType === Node.TEXT_NODE;
|
|
1815
|
+
})
|
|
1816
|
+
.filter((node) => node.nodeType === Node.TEXT_NODE)
|
|
1817
|
+
.map((n) => { var _a; return (_a = n.textContent) === null || _a === void 0 ? void 0 : _a.trim(); })
|
|
1818
|
+
.filter((t) => t);
|
|
1819
|
+
return texts.join(' ');
|
|
1820
|
+
};
|
|
1821
|
+
/**
|
|
1822
|
+
* Extracts the rich content from an `ion-select-option`.
|
|
1823
|
+
* When `customHTMLEnabled` is `false`, only the plain text from the
|
|
1824
|
+
* default slot is read and the start and end slots are skipped.
|
|
1825
|
+
*
|
|
1826
|
+
* @param option - The `ion-select-option` element to extract content from.
|
|
1827
|
+
* @param customHTMLEnabled - Whether custom HTML rendering is enabled
|
|
1828
|
+
* via the `innerHTMLTemplatesEnabled` config.
|
|
1829
|
+
*/
|
|
1830
|
+
const extractOptionContent = (option, customHTMLEnabled) => {
|
|
1831
|
+
var _a, _b;
|
|
1832
|
+
if (!customHTMLEnabled) {
|
|
1833
|
+
return {
|
|
1834
|
+
content: getDefaultSlotPlainText(option),
|
|
1835
|
+
startContent: undefined,
|
|
1836
|
+
endContent: undefined,
|
|
1837
|
+
};
|
|
1838
|
+
}
|
|
1839
|
+
return {
|
|
1840
|
+
content: getOptionContent(option),
|
|
1841
|
+
startContent: (_a = getOptionContent(option, 'start')) !== null && _a !== void 0 ? _a : undefined,
|
|
1842
|
+
endContent: (_b = getOptionContent(option, 'end')) !== null && _b !== void 0 ? _b : undefined,
|
|
1843
|
+
};
|
|
1537
1844
|
};
|
|
1538
1845
|
let selectIds = 0;
|
|
1539
1846
|
const OPTION_CLASS = 'select-interface-option';
|
|
@@ -75,6 +75,14 @@
|
|
|
75
75
|
* @prop --border-width: Width of the select border
|
|
76
76
|
*
|
|
77
77
|
* @prop --ripple-color: The color of the ripple effect on MD mode.
|
|
78
|
+
*
|
|
79
|
+
* @prop --select-text-media-width: The width of media (icons/images) in the select text.
|
|
80
|
+
* @prop --select-text-media-height: The height of media (icons/images) in the select text.
|
|
81
|
+
* @prop --select-text-media-border-width: The border width of media (icons/images) in the select text.
|
|
82
|
+
* @prop --select-text-media-border-color: The border color of media (icons/images) in the select text.
|
|
83
|
+
* @prop --select-text-media-border-radius: The border radius of media (icons/images) in the select text.
|
|
84
|
+
* @prop --select-text-media-border-style: The border style of media (icons/images) in the select text.
|
|
85
|
+
* @prop --select-text-gap: The gap between elements in the select text.
|
|
78
86
|
*/
|
|
79
87
|
--padding-top: 0px;
|
|
80
88
|
--padding-end: 0px;
|
|
@@ -87,6 +95,9 @@
|
|
|
87
95
|
--highlight-color-focused: var(--ion-color-primary, #0054e9);
|
|
88
96
|
--highlight-color-valid: var(--ion-color-success, #2dd55b);
|
|
89
97
|
--highlight-color-invalid: var(--ion-color-danger, #c5000f);
|
|
98
|
+
--select-text-media-height: 1.5em;
|
|
99
|
+
--select-text-media-width: 1.5em;
|
|
100
|
+
--select-text-gap: 12px;
|
|
90
101
|
/**
|
|
91
102
|
* This is a private API that is used to switch
|
|
92
103
|
* out the highlight color based on the state
|
|
@@ -227,6 +238,28 @@ button {
|
|
|
227
238
|
overflow: hidden;
|
|
228
239
|
}
|
|
229
240
|
|
|
241
|
+
/**
|
|
242
|
+
* If the select text contains rich content, we want to add some
|
|
243
|
+
* spacing between the elements without changing the display to
|
|
244
|
+
* prevent losing the ellipses behavior.
|
|
245
|
+
*/
|
|
246
|
+
.select-text > * + * {
|
|
247
|
+
margin-inline-start: var(--select-text-gap);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.select-text img,
|
|
251
|
+
.select-text ion-img,
|
|
252
|
+
.select-text ion-icon,
|
|
253
|
+
.select-text ion-thumbnail,
|
|
254
|
+
.select-text ion-avatar {
|
|
255
|
+
border-radius: var(--select-text-media-border-radius);
|
|
256
|
+
width: var(--select-text-media-width);
|
|
257
|
+
height: var(--select-text-media-height);
|
|
258
|
+
border-width: var(--select-text-media-border-width);
|
|
259
|
+
border-style: var(--select-text-media-border-style);
|
|
260
|
+
border-color: var(--select-text-media-border-color);
|
|
261
|
+
}
|
|
262
|
+
|
|
230
263
|
.select-wrapper {
|
|
231
264
|
-webkit-padding-start: var(--padding-start);
|
|
232
265
|
padding-inline-start: var(--padding-start);
|