@ionic/core 7.5.8 → 7.6.1-dev.11701921257.1d512d3c
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/animation.js +12 -11
- package/components/checkbox.js +5 -3
- package/components/index4.js +10 -12
- package/components/index5.js +0 -22
- package/components/input-shims.js +12 -7
- package/components/input.utils.js +3 -2
- package/components/ion-datetime.js +2 -2
- package/components/ion-infinite-scroll.js +11 -3
- package/components/ion-input.js +31 -8
- package/components/ion-modal.js +2 -2
- package/components/ion-range.js +5 -3
- package/components/ion-select.js +44 -29
- package/components/ion-skeleton-text.js +14 -1
- package/components/ion-textarea.js +30 -7
- package/components/ion-toast.js +419 -74
- package/components/ion-toggle.js +5 -3
- package/components/item.js +2 -2
- package/components/label.js +2 -2
- package/components/overlays.js +2 -1
- package/components/radio-group.js +2 -0
- package/components/radio.js +45 -5
- package/dist/cjs/{animation-cc40e39c.js → animation-9b401d39.js} +13 -12
- package/dist/cjs/{button-active-417ccdcb.js → button-active-a5185907.js} +1 -1
- package/dist/cjs/{capacitor-46980811.js → capacitor-c04564bf.js} +1 -1
- package/dist/cjs/compare-with-utils-df1001d7.js +44 -0
- package/dist/cjs/{haptic-216df36c.js → haptic-b882e0bb.js} +1 -1
- package/dist/cjs/{index-8c1e77d6.js → index-b4f986cd.js} +1 -1
- package/dist/cjs/index-c8d52405.js +10 -0
- package/dist/cjs/{index-5cbb20f9.js → index-ce101dc9.js} +11 -13
- package/dist/cjs/{index-d4c2e02c.js → index-f8f13389.js} +2 -2
- package/dist/cjs/index.cjs.js +8 -8
- package/dist/cjs/{input-shims-87102b6a.js → input-shims-a23bb0f4.js} +15 -10
- package/dist/cjs/{input.utils-2a11c1fe.js → input.utils-3d0166a2.js} +4 -3
- package/dist/cjs/ion-action-sheet.cjs.entry.js +6 -6
- package/dist/cjs/ion-alert.cjs.entry.js +6 -6
- package/dist/cjs/ion-app_8.cjs.entry.js +8 -8
- package/dist/cjs/ion-checkbox.cjs.entry.js +5 -3
- package/dist/cjs/ion-datetime_3.cjs.entry.js +7 -7
- package/dist/cjs/ion-infinite-scroll_2.cjs.entry.js +11 -3
- package/dist/cjs/ion-input.cjs.entry.js +34 -11
- package/dist/cjs/ion-item_8.cjs.entry.js +17 -4
- package/dist/cjs/ion-loading.cjs.entry.js +3 -3
- package/dist/cjs/ion-menu_3.cjs.entry.js +5 -5
- package/dist/cjs/ion-modal.cjs.entry.js +8 -8
- package/dist/cjs/ion-nav_2.cjs.entry.js +1 -1
- package/dist/cjs/ion-picker-column-internal.cjs.entry.js +3 -3
- package/dist/cjs/ion-popover.cjs.entry.js +4 -4
- package/dist/cjs/ion-radio_2.cjs.entry.js +9 -4
- package/dist/cjs/ion-range.cjs.entry.js +5 -3
- package/dist/cjs/ion-refresher_2.cjs.entry.js +4 -4
- package/dist/cjs/ion-reorder_2.cjs.entry.js +3 -3
- package/dist/cjs/ion-select_3.cjs.entry.js +51 -35
- package/dist/cjs/ion-tab-bar_2.cjs.entry.js +4 -4
- package/dist/cjs/ion-textarea.cjs.entry.js +33 -10
- package/dist/cjs/ion-toast.cjs.entry.js +434 -92
- package/dist/cjs/ion-toggle.cjs.entry.js +8 -6
- package/dist/cjs/ionic.cjs.js +1 -1
- package/dist/cjs/{ios.transition-a4ffb5a2.js → ios.transition-6787b799.js} +3 -3
- package/dist/cjs/{keyboard-9390928c.js → keyboard-0272231f.js} +1 -1
- package/dist/cjs/{keyboard-7d621ee9.js → keyboard-af1bb365.js} +3 -3
- package/dist/cjs/{keyboard-controller-2158b478.js → keyboard-controller-c05e747a.js} +2 -2
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/{md.transition-292abe1c.js → md.transition-e033d20a.js} +3 -3
- package/dist/cjs/{notch-controller-1dce508a.js → notch-controller-9735e7ac.js} +1 -1
- package/dist/cjs/{overlays-5c379703.js → overlays-27a6fb16.js} +3 -1
- package/dist/collection/components/checkbox/checkbox.ios.css +0 -6
- package/dist/collection/components/checkbox/checkbox.js +4 -1
- package/dist/collection/components/checkbox/checkbox.md.css +0 -6
- package/dist/collection/components/checkbox/test/checkbox.spec.js +14 -0
- package/dist/collection/components/datetime/datetime.ios.css +1 -0
- package/dist/collection/components/datetime/datetime.md.css +1 -0
- package/dist/collection/components/infinite-scroll/infinite-scroll.js +11 -3
- package/dist/collection/components/infinite-scroll/test/small-dom-update/infinite-scroll.e2e.js +31 -0
- package/dist/collection/components/input/input.ios.css +10 -3
- package/dist/collection/components/input/input.js +31 -6
- package/dist/collection/components/input/input.md.css +13 -12
- package/dist/collection/components/input/test/slot/input.e2e.js +51 -0
- package/dist/collection/components/item/item.ios.css +41 -3
- package/dist/collection/components/item/item.md.css +41 -3
- package/dist/collection/components/item/test/basic/item.e2e.js +1 -1
- package/dist/collection/components/item/test/disabled/item.e2e.js +0 -1
- package/dist/collection/components/label/label.ios.css +14 -3
- package/dist/collection/components/label/label.md.css +14 -3
- package/dist/collection/components/modal/gestures/swipe-to-close.js +2 -1
- package/dist/collection/components/note/test/a11y/note.e2e.js +43 -0
- package/dist/collection/components/radio/radio.ios.css +0 -6
- package/dist/collection/components/radio/radio.js +7 -3
- package/dist/collection/components/radio/radio.md.css +0 -6
- package/dist/collection/components/radio/test/radio.spec.js +14 -0
- package/dist/collection/components/radio-group/radio-group.js +24 -0
- package/dist/collection/components/radio-group/test/radio-group.spec.js +69 -0
- package/dist/collection/components/range/range.ios.css +0 -6
- package/dist/collection/components/range/range.js +4 -1
- package/dist/collection/components/range/range.md.css +0 -6
- package/dist/collection/components/range/test/range.spec.js +16 -0
- package/dist/collection/components/select/select.ios.css +60 -7
- package/dist/collection/components/select/select.js +45 -28
- package/dist/collection/components/select/select.md.css +63 -19
- package/dist/collection/components/select/test/item/select.e2e.js +15 -0
- package/dist/collection/components/select/test/label/select.e2e.js +1 -1
- package/dist/collection/components/select/test/legacy/wrapping/select.e2e.js +1 -1
- package/dist/collection/components/select/test/slot/select.e2e.js +67 -0
- package/dist/collection/components/skeleton-text/skeleton-text.js +39 -0
- package/dist/collection/components/textarea/test/slot/textarea.e2e.js +51 -0
- package/dist/collection/components/textarea/textarea.ios.css +37 -5
- package/dist/collection/components/textarea/textarea.js +30 -5
- package/dist/collection/components/textarea/textarea.md.css +47 -14
- package/dist/collection/components/toast/animations/ios.enter.js +2 -1
- package/dist/collection/components/toast/animations/md.enter.js +4 -3
- package/dist/collection/components/toast/animations/utils.js +20 -14
- package/dist/collection/components/toast/gestures/swipe-to-dismiss.js +267 -0
- package/dist/collection/components/toast/test/swipe-gesture/toast.e2e.js +84 -0
- package/dist/collection/components/toast/test/toast-config.spec.js +25 -0
- package/dist/collection/components/toast/test/toast.spec.js +80 -0
- package/dist/collection/components/toast/toast.ios.css +10 -10
- package/dist/collection/components/toast/toast.js +104 -1
- package/dist/collection/components/toast/toast.md.css +10 -0
- package/dist/collection/components/toggle/test/toggle.spec.js +12 -0
- package/dist/collection/components/toggle/toggle.ios.css +0 -6
- package/dist/collection/components/toggle/toggle.js +4 -1
- package/dist/collection/components/toggle/toggle.md.css +0 -6
- package/dist/collection/utils/animation/animation.js +12 -11
- package/dist/collection/utils/animation/test/animation.spec.js +16 -0
- package/dist/collection/utils/browser/index.js +0 -22
- package/dist/collection/utils/forms/compare-with-utils.js +39 -0
- package/dist/collection/utils/forms/index.js +1 -0
- package/dist/collection/utils/input-shims/input-shims.js +12 -6
- package/dist/collection/utils/menu-controller/index.js +10 -12
- package/dist/collection/utils/overlays.js +1 -0
- package/dist/collection/utils/slot-mutation-controller.js +3 -2
- package/dist/docs.json +159 -2
- package/dist/esm/{animation-fb0e0f6f.js → animation-dde8cc0d.js} +13 -12
- package/dist/esm/{button-active-3fdf3e4f.js → button-active-c6ee4f50.js} +1 -1
- package/dist/esm/{capacitor-b0e5fe83.js → capacitor-59395cbd.js} +1 -1
- package/dist/esm/compare-with-utils-a96ff2ea.js +41 -0
- package/dist/esm/{haptic-152c4172.js → haptic-554688a5.js} +1 -1
- package/dist/esm/{index-80492ed3.js → index-0c12c22b.js} +11 -13
- package/dist/esm/{index-d8817fb0.js → index-1932b201.js} +2 -2
- package/dist/esm/{index-ba9976bb.js → index-82eeb47f.js} +1 -1
- package/dist/esm/index-a5d50daf.js +7 -0
- package/dist/esm/index.js +8 -8
- package/dist/esm/{input-shims-0a2e541d.js → input-shims-6539ce13.js} +14 -9
- package/dist/esm/{input.utils-2846d430.js → input.utils-a5a2d164.js} +4 -3
- package/dist/esm/ion-action-sheet.entry.js +6 -6
- package/dist/esm/ion-alert.entry.js +6 -6
- package/dist/esm/ion-app_8.entry.js +8 -8
- package/dist/esm/ion-checkbox.entry.js +5 -3
- package/dist/esm/ion-datetime_3.entry.js +7 -7
- package/dist/esm/ion-infinite-scroll_2.entry.js +11 -3
- package/dist/esm/ion-input.entry.js +34 -11
- package/dist/esm/ion-item_8.entry.js +17 -4
- package/dist/esm/ion-loading.entry.js +3 -3
- package/dist/esm/ion-menu_3.entry.js +5 -5
- package/dist/esm/ion-modal.entry.js +8 -8
- package/dist/esm/ion-nav_2.entry.js +1 -1
- package/dist/esm/ion-picker-column-internal.entry.js +3 -3
- package/dist/esm/ion-popover.entry.js +4 -4
- package/dist/esm/ion-radio_2.entry.js +9 -4
- package/dist/esm/ion-range.entry.js +5 -3
- package/dist/esm/ion-refresher_2.entry.js +4 -4
- package/dist/esm/ion-reorder_2.entry.js +3 -3
- package/dist/esm/ion-select_3.entry.js +47 -31
- package/dist/esm/ion-tab-bar_2.entry.js +4 -4
- package/dist/esm/ion-textarea.entry.js +33 -10
- package/dist/esm/ion-toast.entry.js +417 -75
- package/dist/esm/ion-toggle.entry.js +8 -6
- package/dist/esm/ionic.js +1 -1
- package/dist/esm/{ios.transition-fd16bec1.js → ios.transition-802a84a6.js} +3 -3
- package/dist/esm/{keyboard-c402e885.js → keyboard-52278bd7.js} +3 -3
- package/dist/esm/{keyboard-dbb05fb9.js → keyboard-73175e24.js} +1 -1
- package/dist/esm/{keyboard-controller-5d90929a.js → keyboard-controller-ec5c2bfa.js} +2 -2
- package/dist/esm/loader.js +1 -1
- package/dist/esm/{md.transition-94ac93e1.js → md.transition-43c2874d.js} +3 -3
- package/dist/esm/{notch-controller-d09b6aca.js → notch-controller-fea7f9c5.js} +1 -1
- package/dist/esm/{overlays-abf58489.js → overlays-32ef481d.js} +3 -2
- package/dist/esm-es5/{animation-fb0e0f6f.js → animation-dde8cc0d.js} +1 -1
- package/dist/esm-es5/{button-active-3fdf3e4f.js → button-active-c6ee4f50.js} +1 -1
- package/dist/esm-es5/{capacitor-b0e5fe83.js → capacitor-59395cbd.js} +1 -1
- package/dist/esm-es5/compare-with-utils-a96ff2ea.js +4 -0
- package/dist/esm-es5/{haptic-152c4172.js → haptic-554688a5.js} +1 -1
- package/dist/esm-es5/index-0c12c22b.js +4 -0
- package/dist/esm-es5/{index-d8817fb0.js → index-1932b201.js} +1 -1
- package/dist/esm-es5/{index-ba9976bb.js → index-82eeb47f.js} +1 -1
- package/dist/esm-es5/index.js +1 -1
- package/dist/esm-es5/input-shims-6539ce13.js +4 -0
- package/dist/esm-es5/input.utils-a5a2d164.js +4 -0
- package/dist/esm-es5/ion-action-sheet.entry.js +1 -1
- package/dist/esm-es5/ion-alert.entry.js +1 -1
- package/dist/esm-es5/ion-app_8.entry.js +1 -1
- package/dist/esm-es5/ion-checkbox.entry.js +1 -1
- package/dist/esm-es5/ion-datetime_3.entry.js +1 -1
- package/dist/esm-es5/ion-infinite-scroll_2.entry.js +1 -1
- package/dist/esm-es5/ion-input.entry.js +1 -1
- package/dist/esm-es5/ion-item_8.entry.js +1 -1
- package/dist/esm-es5/ion-loading.entry.js +1 -1
- package/dist/esm-es5/ion-menu_3.entry.js +1 -1
- package/dist/esm-es5/ion-modal.entry.js +1 -1
- package/dist/esm-es5/ion-nav_2.entry.js +1 -1
- package/dist/esm-es5/ion-picker-column-internal.entry.js +1 -1
- package/dist/esm-es5/ion-popover.entry.js +1 -1
- package/dist/esm-es5/ion-radio_2.entry.js +1 -1
- package/dist/esm-es5/ion-range.entry.js +1 -1
- package/dist/esm-es5/ion-refresher_2.entry.js +1 -1
- package/dist/esm-es5/ion-reorder_2.entry.js +1 -1
- package/dist/esm-es5/ion-select_3.entry.js +1 -1
- package/dist/esm-es5/ion-tab-bar_2.entry.js +1 -1
- package/dist/esm-es5/ion-textarea.entry.js +1 -1
- package/dist/esm-es5/ion-toast.entry.js +1 -1
- package/dist/esm-es5/ion-toggle.entry.js +1 -1
- package/dist/esm-es5/ionic.js +1 -1
- package/dist/esm-es5/{ios.transition-fd16bec1.js → ios.transition-802a84a6.js} +1 -1
- package/dist/esm-es5/{keyboard-c402e885.js → keyboard-52278bd7.js} +1 -1
- package/dist/esm-es5/{keyboard-dbb05fb9.js → keyboard-73175e24.js} +1 -1
- package/dist/esm-es5/{keyboard-controller-5d90929a.js → keyboard-controller-ec5c2bfa.js} +1 -1
- package/dist/esm-es5/loader.js +1 -1
- package/dist/esm-es5/md.transition-43c2874d.js +4 -0
- package/dist/esm-es5/{notch-controller-d09b6aca.js → notch-controller-fea7f9c5.js} +1 -1
- package/dist/esm-es5/{overlays-abf58489.js → overlays-32ef481d.js} +1 -1
- package/dist/html.html-data.json +14 -1
- package/dist/ionic/index.esm.js +1 -1
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/p-01d14eba.system.entry.js +4 -0
- package/dist/ionic/{p-3de71759.entry.js → p-042e6f4b.entry.js} +1 -1
- package/dist/ionic/p-05d83227.system.entry.js +4 -0
- package/dist/ionic/{p-32e19bee.system.js → p-0bd51c34.system.js} +1 -1
- package/dist/ionic/{p-73637557.system.entry.js → p-16756e94.system.entry.js} +1 -1
- package/dist/ionic/p-1b19c04b.entry.js +4 -0
- package/dist/ionic/{p-95c26010.system.js → p-1cca10d6.system.js} +1 -1
- package/dist/ionic/p-1e4371bd.js +4 -0
- package/dist/ionic/{p-0519cd21.entry.js → p-251666e2.entry.js} +1 -1
- package/dist/ionic/{p-4e8e09e1.js → p-27281edd.js} +1 -1
- package/dist/ionic/p-28249b10.system.entry.js +4 -0
- package/dist/ionic/p-28a2c2a2.entry.js +4 -0
- package/dist/ionic/p-29d03b3a.js +4 -0
- package/dist/ionic/p-2b7827c7.js +4 -0
- package/dist/ionic/p-2d3b9fa3.system.entry.js +4 -0
- package/dist/ionic/p-2d539df1.entry.js +4 -0
- package/dist/ionic/{p-a0126dd5.system.entry.js → p-3137c025.system.entry.js} +1 -1
- package/dist/ionic/{p-30029cc2.system.js → p-31fcb233.system.js} +1 -1
- package/dist/ionic/{p-b0dc1cf9.system.js → p-33a37fad.system.js} +1 -1
- package/dist/ionic/p-36d187af.js +4 -0
- package/dist/ionic/p-376a6063.js +4 -0
- package/dist/ionic/p-38f2c6bb.system.js +4 -0
- package/dist/ionic/{p-2ba0657d.system.entry.js → p-39c31982.system.entry.js} +1 -1
- package/dist/ionic/{p-75445583.js → p-3a75d7fd.js} +1 -1
- package/dist/ionic/{p-d40a974a.entry.js → p-3dd98a73.entry.js} +1 -1
- package/dist/ionic/p-3e6b47e8.system.entry.js +4 -0
- package/dist/ionic/p-3f5179b5.entry.js +4 -0
- package/dist/ionic/p-40f68333.system.js +4 -0
- package/dist/ionic/{p-643a8fae.js → p-42f189f4.js} +1 -1
- package/dist/ionic/{p-9c3b6849.entry.js → p-438e1b8a.entry.js} +1 -1
- package/dist/ionic/{p-b752714f.system.entry.js → p-46d400b4.system.entry.js} +1 -1
- package/dist/ionic/{p-61d7d7fb.js → p-47b6ba5b.js} +1 -1
- package/dist/ionic/{p-b04e4d62.entry.js → p-4d67d27a.entry.js} +1 -1
- package/dist/ionic/{p-0b1bc636.entry.js → p-4f3ae45a.entry.js} +1 -1
- package/dist/ionic/{p-18b6bd23.system.entry.js → p-517a9885.system.entry.js} +1 -1
- package/dist/ionic/p-53ec4f1c.system.js +4 -0
- package/dist/ionic/p-5e4eec2e.entry.js +4 -0
- package/dist/ionic/{p-57477107.system.js → p-5e745192.system.js} +1 -1
- package/dist/ionic/{p-ad019ef0.entry.js → p-5eda1d7d.entry.js} +1 -1
- package/dist/ionic/{p-4890093d.js → p-6de472cb.js} +1 -1
- package/dist/ionic/{p-08f196ce.system.entry.js → p-6de62649.system.entry.js} +1 -1
- package/dist/ionic/p-72f6ff89.js +4 -0
- package/dist/ionic/p-765f4dde.entry.js +4 -0
- package/dist/ionic/{p-3f6270b3.entry.js → p-78aadecb.entry.js} +1 -1
- package/dist/ionic/p-7d92bf15.system.entry.js +4 -0
- package/dist/ionic/p-7ee0f3f2.entry.js +4 -0
- package/dist/ionic/p-8314281e.system.js +4 -0
- package/dist/ionic/p-88d5fbd3.js +4 -0
- package/dist/ionic/{p-0e4f2e17.system.js → p-8985cdb6.system.js} +1 -1
- package/dist/ionic/{p-d7be6b7e.system.entry.js → p-8acae6b0.system.entry.js} +1 -1
- package/dist/ionic/p-8d69a624.entry.js +4 -0
- package/dist/ionic/p-8de17614.system.entry.js +4 -0
- package/dist/ionic/p-91d33c4a.js +4 -0
- package/dist/ionic/p-979d4f5c.system.js +4 -0
- package/dist/ionic/p-9b7f0b0f.entry.js +4 -0
- package/dist/ionic/p-9e447eb1.system.js +4 -0
- package/dist/ionic/p-9f6ee2c0.system.entry.js +4 -0
- package/dist/ionic/{p-94389114.system.entry.js → p-a0bb7b92.system.entry.js} +1 -1
- package/dist/ionic/{p-f2c21dae.system.js → p-a0d7bb5e.system.js} +1 -1
- package/dist/ionic/{p-82045bc1.entry.js → p-a3277a67.entry.js} +1 -1
- package/dist/ionic/{p-50880712.entry.js → p-a9978d08.entry.js} +1 -1
- package/dist/ionic/{p-3b686a65.system.entry.js → p-ada96dd0.system.entry.js} +1 -1
- package/dist/ionic/p-afd6ca9d.entry.js +4 -0
- package/dist/ionic/p-b56d0866.system.entry.js +4 -0
- package/dist/ionic/{p-67da080d.entry.js → p-b6f9d32a.entry.js} +1 -1
- package/dist/ionic/p-c61cc894.js +4 -0
- package/dist/ionic/{p-304383f9.system.js → p-cabad15b.system.js} +1 -1
- package/dist/ionic/{p-31158892.js → p-cdbeaadc.js} +1 -1
- package/dist/ionic/p-d032f825.system.entry.js +4 -0
- package/dist/ionic/p-d51674c5.system.js +4 -0
- package/dist/ionic/{p-98d82c73.system.js → p-ddbb2d5b.system.js} +1 -1
- package/dist/ionic/p-de6f8b28.system.js +4 -0
- package/dist/ionic/p-de756e5c.js +4 -0
- package/dist/ionic/{p-73ea8f82.system.entry.js → p-dee7c1d0.system.entry.js} +1 -1
- package/dist/ionic/p-dfd9432a.entry.js +4 -0
- package/dist/ionic/{p-af5cfad2.system.js → p-e24ce1e5.system.js} +1 -1
- package/dist/ionic/p-e3584231.system.js +1 -1
- package/dist/ionic/p-f0445d82.system.entry.js +4 -0
- package/dist/ionic/p-f656e032.system.entry.js +4 -0
- package/dist/ionic/{p-17f893be.js → p-f70970cf.js} +1 -1
- package/dist/ionic/{p-e553006f.system.entry.js → p-fba0a6e7.system.entry.js} +1 -1
- package/dist/ionic/p-feae5133.entry.js +4 -0
- package/dist/types/components/checkbox/checkbox.d.ts +1 -0
- package/dist/types/components/infinite-scroll/infinite-scroll.d.ts +7 -0
- package/dist/types/components/input/input.d.ts +2 -0
- package/dist/types/components/radio/radio.d.ts +1 -0
- package/dist/types/components/radio-group/radio-group-interface.d.ts +1 -0
- package/dist/types/components/radio-group/radio-group.d.ts +8 -1
- package/dist/types/components/range/range.d.ts +1 -0
- package/dist/types/components/router/router.d.ts +2 -1
- package/dist/types/components/select/select.d.ts +6 -1
- package/dist/types/components/skeleton-text/skeleton-text.d.ts +9 -1
- package/dist/types/components/textarea/textarea.d.ts +2 -0
- package/dist/types/components/toast/animations/utils.d.ts +15 -4
- package/dist/types/components/toast/gestures/swipe-to-dismiss.d.ts +9 -0
- package/dist/types/components/toast/toast-interface.d.ts +2 -0
- package/dist/types/components/toast/toast.d.ts +28 -1
- package/dist/types/components/toggle/toggle.d.ts +1 -0
- package/dist/types/components.d.ts +37 -6
- package/dist/types/interface.d.ts +1 -5
- package/dist/types/jest.d.ts +5 -0
- package/dist/types/utils/animation/animation-interface.d.ts +4 -4
- package/dist/types/utils/browser/index.d.ts +11 -2
- package/dist/types/utils/forms/compare-with-utils.d.ts +18 -0
- package/dist/types/utils/forms/index.d.ts +1 -0
- package/dist/types/utils/hardware-back-button.d.ts +4 -0
- package/dist/types/utils/overlays.d.ts +1 -0
- package/dist/types/utils/slot-mutation-controller.d.ts +2 -2
- package/hydrate/index.js +643 -184
- package/package.json +1 -1
- package/dist/cjs/index-306a7476.js +0 -32
- package/dist/collection/components/item/test/text/item.e2e.js +0 -14
- package/dist/esm/index-7a14ecec.js +0 -29
- package/dist/esm-es5/index-80492ed3.js +0 -4
- package/dist/esm-es5/input-shims-0a2e541d.js +0 -4
- package/dist/esm-es5/input.utils-2846d430.js +0 -4
- package/dist/esm-es5/md.transition-94ac93e1.js +0 -4
- package/dist/ionic/p-1d17219f.entry.js +0 -4
- package/dist/ionic/p-232d1f22.entry.js +0 -4
- package/dist/ionic/p-25b32c3d.entry.js +0 -4
- package/dist/ionic/p-2ab4e925.system.entry.js +0 -4
- package/dist/ionic/p-2d5aeccc.js +0 -4
- package/dist/ionic/p-2d600c25.system.js +0 -4
- package/dist/ionic/p-308e1341.js +0 -4
- package/dist/ionic/p-32303650.system.entry.js +0 -4
- package/dist/ionic/p-34c39c48.entry.js +0 -4
- package/dist/ionic/p-3c58a71b.js +0 -4
- package/dist/ionic/p-3e960213.system.entry.js +0 -4
- package/dist/ionic/p-3fd26bd6.system.entry.js +0 -4
- package/dist/ionic/p-3fe96156.system.js +0 -4
- package/dist/ionic/p-42ba3902.entry.js +0 -4
- package/dist/ionic/p-4a31c99f.entry.js +0 -4
- package/dist/ionic/p-5a68960f.entry.js +0 -4
- package/dist/ionic/p-6470b136.entry.js +0 -4
- package/dist/ionic/p-6c37f051.js +0 -4
- package/dist/ionic/p-7b8d0af2.system.entry.js +0 -4
- package/dist/ionic/p-7faba551.system.entry.js +0 -4
- package/dist/ionic/p-83af3685.system.js +0 -4
- package/dist/ionic/p-856c430d.js +0 -4
- package/dist/ionic/p-93000a81.system.entry.js +0 -4
- package/dist/ionic/p-98b14ece.entry.js +0 -4
- package/dist/ionic/p-990ffd0e.js +0 -4
- package/dist/ionic/p-a6f9dd7b.entry.js +0 -4
- package/dist/ionic/p-a98dc0c1.entry.js +0 -4
- package/dist/ionic/p-a9e3b5be.system.entry.js +0 -4
- package/dist/ionic/p-ab9456e9.system.entry.js +0 -4
- package/dist/ionic/p-b4bad293.system.entry.js +0 -4
- package/dist/ionic/p-c3289ef2.entry.js +0 -4
- package/dist/ionic/p-c3d09cf2.system.entry.js +0 -4
- package/dist/ionic/p-d1cb29a8.system.entry.js +0 -4
- package/dist/ionic/p-d43f1f3d.system.js +0 -4
- package/dist/ionic/p-d662d908.js +0 -4
- package/dist/ionic/p-d9695ad9.system.js +0 -4
- package/dist/ionic/p-e4d90573.js +0 -4
- package/dist/ionic/p-f54c72b0.system.js +0 -4
- package/dist/ionic/p-f7a36cd0.system.js +0 -4
- package/dist/ionic/p-f967631d.js +0 -4
- /package/dist/esm-es5/{index-7a14ecec.js → index-a5d50daf.js} +0 -0
- /package/dist/ionic/{p-0e94957a.system.js → p-792919fd.system.js} +0 -0
- /package/dist/ionic/{p-b347cfd1.js → p-7b30edcc.js} +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
3
|
*/
|
|
4
4
|
import { Host, h, forceUpdate } from "@stencil/core";
|
|
5
|
-
import { createLegacyFormController, createNotchController } from "../../utils/forms/index";
|
|
5
|
+
import { compareOptions, createLegacyFormController, createNotchController, isOptionSelected } from "../../utils/forms/index";
|
|
6
6
|
import { findItemLabel, focusElement, getAriaLabel, renderHiddenInput, inheritAttributes } from "../../utils/helpers";
|
|
7
7
|
import { printIonWarning } from "../../utils/logging/index";
|
|
8
8
|
import { actionSheetController, alertController, popoverController } from "../../utils/overlays";
|
|
@@ -16,6 +16,8 @@ import { getIonMode } from "../../global/ionic-global";
|
|
|
16
16
|
* @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
|
|
17
17
|
*
|
|
18
18
|
* @slot label - The label text to associate with the select. Use the `labelPlacement` property to control where the label is placed relative to the select. Use this if you need to render a label with custom HTML.
|
|
19
|
+
* @slot start - Content to display at the leading edge of the select.
|
|
20
|
+
* @slot end - Content to display at the trailing edge of the select.
|
|
19
21
|
*
|
|
20
22
|
* @part placeholder - The text displayed in the select when there is no value.
|
|
21
23
|
* @part text - The displayed value of the select.
|
|
@@ -30,8 +32,22 @@ export class Select {
|
|
|
30
32
|
// This flag ensures we log the deprecation warning at most once.
|
|
31
33
|
this.hasLoggedDeprecationWarning = false;
|
|
32
34
|
this.onClick = (ev) => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
const target = ev.target;
|
|
36
|
+
const closestSlot = target.closest('[slot="start"], [slot="end"]');
|
|
37
|
+
if (target === this.el || closestSlot === null) {
|
|
38
|
+
this.setFocus();
|
|
39
|
+
this.open(ev);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
/**
|
|
43
|
+
* Prevent clicks to the start/end slots from opening the select.
|
|
44
|
+
* We ensure the target isn't this element in case the select is slotted
|
|
45
|
+
* in, for example, an item. This would prevent the select from ever
|
|
46
|
+
* being opened since the element itself has slot="start"/"end".
|
|
47
|
+
*/
|
|
48
|
+
ev.stopPropagation();
|
|
49
|
+
ev.preventDefault();
|
|
50
|
+
}
|
|
35
51
|
};
|
|
36
52
|
this.onFocus = () => {
|
|
37
53
|
this.ionFocus.emit();
|
|
@@ -465,6 +481,8 @@ export class Select {
|
|
|
465
481
|
style['has-placeholder'] = this.placeholder !== undefined;
|
|
466
482
|
style['has-value'] = this.hasValue();
|
|
467
483
|
style['has-focus'] = this.isExpanded;
|
|
484
|
+
// TODO(FW-3194): remove this
|
|
485
|
+
style['legacy'] = !!this.legacy;
|
|
468
486
|
}
|
|
469
487
|
this.ionStyle.emit(style);
|
|
470
488
|
}
|
|
@@ -532,7 +550,27 @@ export class Select {
|
|
|
532
550
|
const rtl = isRTL(el) ? 'rtl' : 'ltr';
|
|
533
551
|
const inItem = hostContext('ion-item', this.el);
|
|
534
552
|
const shouldRenderHighlight = mode === 'md' && fill !== 'outline' && !inItem;
|
|
553
|
+
const hasValue = this.hasValue();
|
|
554
|
+
const hasStartEndSlots = el.querySelector('[slot="start"], [slot="end"]') !== null;
|
|
535
555
|
renderHiddenInput(true, el, name, parseValue(value), disabled);
|
|
556
|
+
/**
|
|
557
|
+
* If the label is stacked, it should always sit above the select.
|
|
558
|
+
* For floating labels, the label should move above the select if
|
|
559
|
+
* the select has a value, is open, or has anything in either
|
|
560
|
+
* the start or end slot.
|
|
561
|
+
*
|
|
562
|
+
* If there is content in the start slot, the label would overlap
|
|
563
|
+
* it if not forced to float. This is also applied to the end slot
|
|
564
|
+
* because with the default or solid fills, the select is not
|
|
565
|
+
* vertically centered in the container, but the label is. This
|
|
566
|
+
* causes the slots and label to appear vertically offset from each
|
|
567
|
+
* other when the label isn't floating above the input. This doesn't
|
|
568
|
+
* apply to the outline fill, but this was not accounted for to keep
|
|
569
|
+
* things consistent.
|
|
570
|
+
*
|
|
571
|
+
* TODO(FW-5592): Remove hasStartEndSlots condition
|
|
572
|
+
*/
|
|
573
|
+
const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || isExpanded || hasStartEndSlots));
|
|
536
574
|
return (h(Host, { onClick: this.onClick, class: createColorClasses(this.color, {
|
|
537
575
|
[mode]: true,
|
|
538
576
|
'in-item': inItem,
|
|
@@ -540,7 +578,8 @@ export class Select {
|
|
|
540
578
|
'select-disabled': disabled,
|
|
541
579
|
'select-expanded': isExpanded,
|
|
542
580
|
'has-expanded-icon': expandedIcon !== undefined,
|
|
543
|
-
'has-value':
|
|
581
|
+
'has-value': hasValue,
|
|
582
|
+
'label-floating': labelShouldFloat,
|
|
544
583
|
'has-placeholder': placeholder !== undefined,
|
|
545
584
|
'ion-focusable': true,
|
|
546
585
|
[`select-${rtl}`]: true,
|
|
@@ -548,7 +587,7 @@ export class Select {
|
|
|
548
587
|
[`select-justify-${justify}`]: justifyEnabled,
|
|
549
588
|
[`select-shape-${shape}`]: shape !== undefined,
|
|
550
589
|
[`select-label-placement-${labelPlacement}`]: true,
|
|
551
|
-
}) }, h("label", { class: "select-wrapper", id: "select-label" }, this.renderLabelContainer(), h("div", { class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), !hasFloatingOrStackedLabel && this.renderSelectIcon()
|
|
590
|
+
}) }, h("label", { class: "select-wrapper", id: "select-label" }, this.renderLabelContainer(), h("div", { class: "select-wrapper-inner" }, h("slot", { name: "start" }), h("div", { class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox()), h("slot", { name: "end" }), !hasFloatingOrStackedLabel && this.renderSelectIcon()), hasFloatingOrStackedLabel && this.renderSelectIcon(), shouldRenderHighlight && h("div", { class: "select-highlight" }))));
|
|
552
591
|
}
|
|
553
592
|
// TODO FW-3194 - Remove this
|
|
554
593
|
renderLegacySelect() {
|
|
@@ -737,7 +776,7 @@ Developers can use the "legacy" property to continue using the legacy form marku
|
|
|
737
776
|
"optional": true,
|
|
738
777
|
"docs": {
|
|
739
778
|
"tags": [],
|
|
740
|
-
"text": "
|
|
779
|
+
"text": "This property allows developers to specify a custom function or property\nname for comparing objects when determining the selected option in the\nion-select. When not specified, the default behavior will use strict\nequality (===) for comparison."
|
|
741
780
|
},
|
|
742
781
|
"attribute": "compare-with",
|
|
743
782
|
"reflect": false
|
|
@@ -1215,17 +1254,6 @@ Developers can use the "legacy" property to continue using the legacy form marku
|
|
|
1215
1254
|
}];
|
|
1216
1255
|
}
|
|
1217
1256
|
}
|
|
1218
|
-
const isOptionSelected = (currentValue, compareValue, compareWith) => {
|
|
1219
|
-
if (currentValue === undefined) {
|
|
1220
|
-
return false;
|
|
1221
|
-
}
|
|
1222
|
-
if (Array.isArray(currentValue)) {
|
|
1223
|
-
return currentValue.some((val) => compareOptions(val, compareValue, compareWith));
|
|
1224
|
-
}
|
|
1225
|
-
else {
|
|
1226
|
-
return compareOptions(currentValue, compareValue, compareWith);
|
|
1227
|
-
}
|
|
1228
|
-
};
|
|
1229
1257
|
const getOptionValue = (el) => {
|
|
1230
1258
|
const value = el.value;
|
|
1231
1259
|
return value === undefined ? el.textContent || '' : value;
|
|
@@ -1239,17 +1267,6 @@ const parseValue = (value) => {
|
|
|
1239
1267
|
}
|
|
1240
1268
|
return value.toString();
|
|
1241
1269
|
};
|
|
1242
|
-
const compareOptions = (currentValue, compareValue, compareWith) => {
|
|
1243
|
-
if (typeof compareWith === 'function') {
|
|
1244
|
-
return compareWith(currentValue, compareValue);
|
|
1245
|
-
}
|
|
1246
|
-
else if (typeof compareWith === 'string') {
|
|
1247
|
-
return currentValue[compareWith] === compareValue[compareWith];
|
|
1248
|
-
}
|
|
1249
|
-
else {
|
|
1250
|
-
return Array.isArray(compareValue) ? compareValue.includes(currentValue) : currentValue === compareValue;
|
|
1251
|
-
}
|
|
1252
|
-
};
|
|
1253
1270
|
const generateText = (opts, value, compareWith) => {
|
|
1254
1271
|
if (value === undefined) {
|
|
1255
1272
|
return '';
|
|
@@ -132,6 +132,10 @@
|
|
|
132
132
|
overflow: hidden;
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
+
:host(.in-item:not(.legacy-select)) {
|
|
136
|
+
flex: 1 1 0;
|
|
137
|
+
}
|
|
138
|
+
|
|
135
139
|
:host(.in-item.legacy-select) {
|
|
136
140
|
position: static;
|
|
137
141
|
max-width: 45%;
|
|
@@ -232,6 +236,12 @@ button {
|
|
|
232
236
|
margin-top: 0;
|
|
233
237
|
margin-bottom: 0;
|
|
234
238
|
position: relative;
|
|
239
|
+
/**
|
|
240
|
+
* Prevent the icon from shrinking when the label and/or
|
|
241
|
+
* selected item text is long enough to fill the rest of
|
|
242
|
+
* the container.
|
|
243
|
+
*/
|
|
244
|
+
flex-shrink: 0;
|
|
235
245
|
}
|
|
236
246
|
|
|
237
247
|
/**
|
|
@@ -315,6 +325,23 @@ button {
|
|
|
315
325
|
transition: opacity 150ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
316
326
|
}
|
|
317
327
|
|
|
328
|
+
.select-wrapper-inner {
|
|
329
|
+
display: flex;
|
|
330
|
+
align-items: center;
|
|
331
|
+
overflow: hidden;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
:host(.select-label-placement-stacked) .select-wrapper-inner,
|
|
335
|
+
:host(.select-label-placement-floating) .select-wrapper-inner {
|
|
336
|
+
/**
|
|
337
|
+
* When using a stacked/floating label, the inner wrapper is
|
|
338
|
+
* stacked vertically under the label container. This line
|
|
339
|
+
* ensures that the inner wrapper fills all the remaining height
|
|
340
|
+
* of the component.
|
|
341
|
+
*/
|
|
342
|
+
flex-grow: 1;
|
|
343
|
+
}
|
|
344
|
+
|
|
318
345
|
:host(.ion-touched.ion-invalid) {
|
|
319
346
|
--highlight-color: var(--highlight-color-invalid);
|
|
320
347
|
}
|
|
@@ -555,11 +582,23 @@ button {
|
|
|
555
582
|
* The placeholder should be hidden when the label
|
|
556
583
|
* is on top of the select. This prevents the label
|
|
557
584
|
* from overlapping any placeholder value.
|
|
585
|
+
*
|
|
586
|
+
* TODO(FW-5592): Remove :not(.label-floating) piece
|
|
558
587
|
*/
|
|
559
|
-
:host(.select-label-placement-floating) .native-wrapper .select-placeholder {
|
|
588
|
+
:host(.select-label-placement-floating:not(.label-floating)) .native-wrapper .select-placeholder {
|
|
560
589
|
opacity: 0;
|
|
561
590
|
}
|
|
562
591
|
|
|
592
|
+
/**
|
|
593
|
+
* We don't use .label-floating here because that would
|
|
594
|
+
* also include the case where the label is floating due
|
|
595
|
+
* to content in the start/end slot. We want the opacity
|
|
596
|
+
* to remain at the default in this case, since the select
|
|
597
|
+
* isn't being actively interacted with.
|
|
598
|
+
*
|
|
599
|
+
* TODO(FW-5592): Change entire selector to:
|
|
600
|
+
* :host(.label-floating.select-label-placement-floating) .native-wrapper .select-placeholder
|
|
601
|
+
*/
|
|
563
602
|
:host(.select-expanded.select-label-placement-floating) .native-wrapper .select-placeholder,
|
|
564
603
|
:host(.ion-focused.select-label-placement-floating) .native-wrapper .select-placeholder,
|
|
565
604
|
:host(.has-value.select-label-placement-floating) .native-wrapper .select-placeholder {
|
|
@@ -569,10 +608,7 @@ button {
|
|
|
569
608
|
/**
|
|
570
609
|
* This makes the label sit above the input.
|
|
571
610
|
*/
|
|
572
|
-
:host(.
|
|
573
|
-
:host(.select-expanded.select-label-placement-floating) .label-text-wrapper,
|
|
574
|
-
:host(.ion-focused.select-label-placement-floating) .label-text-wrapper,
|
|
575
|
-
:host(.has-value.select-label-placement-floating) .label-text-wrapper {
|
|
611
|
+
:host(.label-floating) .label-text-wrapper {
|
|
576
612
|
transform: translateY(50%) scale(0.75);
|
|
577
613
|
/**
|
|
578
614
|
* Label text should not extend
|
|
@@ -581,6 +617,23 @@ button {
|
|
|
581
617
|
max-width: calc(100% / 0.75);
|
|
582
618
|
}
|
|
583
619
|
|
|
620
|
+
::slotted([slot=start]), ::slotted([slot=end]) {
|
|
621
|
+
/**
|
|
622
|
+
* Prevent the slots from shrinking when the label and/or
|
|
623
|
+
* selected item text is long enough to fill the rest of
|
|
624
|
+
* the container.
|
|
625
|
+
*/
|
|
626
|
+
flex-shrink: 0;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
::slotted([slot=start]) {
|
|
630
|
+
margin-inline-end: 16px;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
::slotted([slot=end]) {
|
|
634
|
+
margin-inline-start: 16px;
|
|
635
|
+
}
|
|
636
|
+
|
|
584
637
|
/**
|
|
585
638
|
* Convert a font size to a dynamic font size.
|
|
586
639
|
* Fonts that participate in Dynamic Type should use
|
|
@@ -824,10 +877,7 @@ button {
|
|
|
824
877
|
}
|
|
825
878
|
}
|
|
826
879
|
|
|
827
|
-
:host(.select-fill-solid
|
|
828
|
-
:host(.select-expanded.select-fill-solid.select-label-placement-floating) .label-text-wrapper,
|
|
829
|
-
:host(.ion-focused.select-fill-solid.select-label-placement-floating) .label-text-wrapper,
|
|
830
|
-
:host(.has-value.select-fill-solid.select-label-placement-floating) .label-text-wrapper {
|
|
880
|
+
:host(.label-floating.select-fill-solid) .label-text-wrapper {
|
|
831
881
|
/**
|
|
832
882
|
* Label text should not extend
|
|
833
883
|
* beyond the bounds of the select.
|
|
@@ -983,10 +1033,7 @@ button {
|
|
|
983
1033
|
/**
|
|
984
1034
|
* This makes the label sit above the select.
|
|
985
1035
|
*/
|
|
986
|
-
:host(.
|
|
987
|
-
:host(.ion-focused.select-fill-outline.select-label-placement-floating) .label-text-wrapper,
|
|
988
|
-
:host(.has-value.select-fill-outline.select-label-placement-floating) .label-text-wrapper,
|
|
989
|
-
:host(.select-fill-outline.select-label-placement-stacked) .label-text-wrapper {
|
|
1036
|
+
:host(.label-floating.select-fill-outline) .label-text-wrapper {
|
|
990
1037
|
transform: translateY(-32%) scale(0.75);
|
|
991
1038
|
margin-left: 0;
|
|
992
1039
|
margin-right: 0;
|
|
@@ -1131,10 +1178,7 @@ button {
|
|
|
1131
1178
|
* the floating/stacked label. We simulate this "cut out"
|
|
1132
1179
|
* by removing the top border from the notch fragment.
|
|
1133
1180
|
*/
|
|
1134
|
-
:host(.
|
|
1135
|
-
:host(.ion-focused.select-fill-outline.select-label-placement-floating) .select-outline-notch,
|
|
1136
|
-
:host(.has-value.select-fill-outline.select-label-placement-floating) .select-outline-notch,
|
|
1137
|
-
:host(.select-fill-outline.select-label-placement-stacked) .select-outline-notch {
|
|
1181
|
+
:host(.label-floating.select-fill-outline) .select-outline-notch {
|
|
1138
1182
|
border-top: none;
|
|
1139
1183
|
}
|
|
1140
1184
|
|
|
@@ -1299,8 +1343,8 @@ button {
|
|
|
1299
1343
|
--border-radius: 16px;
|
|
1300
1344
|
}
|
|
1301
1345
|
|
|
1302
|
-
:host(.select-label-placement-stacked) .
|
|
1303
|
-
:host(.select-label-placement-floating) .
|
|
1346
|
+
:host(.select-label-placement-stacked) .select-wrapper-inner,
|
|
1347
|
+
:host(.select-label-placement-floating) .select-wrapper-inner {
|
|
1304
1348
|
width: calc(100% - 0.8125rem - 4px);
|
|
1305
1349
|
}
|
|
1306
1350
|
|
|
@@ -37,5 +37,20 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
|
|
37
37
|
const list = page.locator('ion-list');
|
|
38
38
|
await expect(list).toHaveScreenshot(screenshot(`select-inset-list-no-fill`));
|
|
39
39
|
});
|
|
40
|
+
test('should render correctly in an item inside of a flex container', async ({ page }) => {
|
|
41
|
+
await page.setContent(`
|
|
42
|
+
<div id="container" style="display: flex">
|
|
43
|
+
<ion-list>
|
|
44
|
+
<ion-item>
|
|
45
|
+
<ion-select label="Fruit" value="apple">
|
|
46
|
+
<ion-select-option value="apple">Apple</ion-select-option>
|
|
47
|
+
</ion-select>
|
|
48
|
+
</ion-item>
|
|
49
|
+
<ion-list>
|
|
50
|
+
</div>
|
|
51
|
+
`, config);
|
|
52
|
+
const container = page.locator('#container');
|
|
53
|
+
await expect(container).toHaveScreenshot(screenshot(`select-item-flex-container`));
|
|
54
|
+
});
|
|
40
55
|
});
|
|
41
56
|
});
|
|
@@ -121,7 +121,7 @@ configs().forEach(({ title, screenshot, config }) => {
|
|
|
121
121
|
});
|
|
122
122
|
test('label should appear on top of the select when the select is expanded', async ({ page }) => {
|
|
123
123
|
await page.setContent(`
|
|
124
|
-
<ion-select class="select-expanded" label="Label" label-placement="floating" placeholder="Select a Fruit">
|
|
124
|
+
<ion-select class="select-expanded label-floating" label="Label" label-placement="floating" placeholder="Select a Fruit">
|
|
125
125
|
<ion-select-option value="apples">Apples</ion-select-option>
|
|
126
126
|
</ion-select>
|
|
127
127
|
`, config);
|
|
@@ -27,7 +27,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
|
|
27
27
|
await page.setContent(`
|
|
28
28
|
<ion-item>
|
|
29
29
|
<ion-label>Really long label should not wrap</ion-label>
|
|
30
|
-
<ion-select value="wrap" class="ion-text-wrap">
|
|
30
|
+
<ion-select value="wrap" legacy="true" class="ion-text-wrap">
|
|
31
31
|
<ion-select-option value="wrap">Should wrap value only when label exists and really long text exists to make it wrap the text</ion-select-option>
|
|
32
32
|
</ion-select>
|
|
33
33
|
</ion-item>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
|
+
*/
|
|
4
|
+
import { expect } from "@playwright/test";
|
|
5
|
+
import { configs, test } from "../../../../utils/test/playwright/index";
|
|
6
|
+
configs().forEach(({ title, screenshot, config }) => {
|
|
7
|
+
test.describe(title('select: start and end slots (visual checks)'), () => {
|
|
8
|
+
test('should not have visual regressions with a start-positioned label', async ({ page }) => {
|
|
9
|
+
await page.setContent(`
|
|
10
|
+
<ion-select label-placement="start" fill="solid" placeholder="Select weight" label="Weight">
|
|
11
|
+
<ion-icon slot="start" name="barbell" aria-hidden="true"></ion-icon>
|
|
12
|
+
<ion-label slot="end">lbs</ion-label>
|
|
13
|
+
</ion-select>
|
|
14
|
+
`, config);
|
|
15
|
+
const select = page.locator('ion-select');
|
|
16
|
+
await expect(select).toHaveScreenshot(screenshot(`select-slots-label-start`));
|
|
17
|
+
});
|
|
18
|
+
test('should not have visual regressions with a floating label', async ({ page }) => {
|
|
19
|
+
await page.setContent(`
|
|
20
|
+
<ion-select label-placement="floating" fill="solid" placeholder="Select weight" label="Weight">
|
|
21
|
+
<ion-icon slot="start" name="barbell" aria-hidden="true"></ion-icon>
|
|
22
|
+
<ion-label slot="end">lbs</ion-label>
|
|
23
|
+
</ion-select>
|
|
24
|
+
`, config);
|
|
25
|
+
const select = page.locator('ion-select');
|
|
26
|
+
await expect(select).toHaveScreenshot(screenshot(`select-slots-label-floating`));
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
|
31
|
+
test.describe(title('select: start and end slots (functionality checks)'), () => {
|
|
32
|
+
test('should raise floating label when there is content in the start slot', async ({ page }) => {
|
|
33
|
+
await page.setContent(`
|
|
34
|
+
<ion-select label-placement="floating" fill="solid" label="Weight">
|
|
35
|
+
<ion-icon slot="start" name="barbell" aria-hidden="true"></ion-icon>
|
|
36
|
+
</ion-select>
|
|
37
|
+
`, config);
|
|
38
|
+
const select = page.locator('ion-select');
|
|
39
|
+
await expect(select).toHaveClass(/label-floating/);
|
|
40
|
+
});
|
|
41
|
+
test('should raise floating label when there is content in the end slot', async ({ page }) => {
|
|
42
|
+
await page.setContent(`
|
|
43
|
+
<ion-select label-placement="floating" fill="solid" label="Weight">
|
|
44
|
+
<ion-icon slot="end" name="barbell" aria-hidden="true"></ion-icon>
|
|
45
|
+
</ion-select>
|
|
46
|
+
`, config);
|
|
47
|
+
const select = page.locator('ion-select');
|
|
48
|
+
await expect(select).toHaveClass(/label-floating/);
|
|
49
|
+
});
|
|
50
|
+
test('should not open select when slotted buttons are clicked', async ({ page }) => {
|
|
51
|
+
await page.setContent(`
|
|
52
|
+
<ion-select label="Favorite Pizza" placeholder="Select a pizza">
|
|
53
|
+
<ion-select-option value="pepperoni">Pepperoni</ion-select-option>
|
|
54
|
+
<ion-select-option value="supreme">Supreme</ion-select-option>
|
|
55
|
+
<ion-select-option value="chicken">Chicken</ion-select-option>
|
|
56
|
+
<ion-button fill="clear" slot="end" aria-label="Show/hide password">
|
|
57
|
+
<ion-icon slot="icon-only" name="eye" aria-hidden="true"></ion-icon>
|
|
58
|
+
</ion-button>
|
|
59
|
+
</ion-select>
|
|
60
|
+
`, config);
|
|
61
|
+
await page.click('ion-select ion-button[slot="end"]');
|
|
62
|
+
await page.waitForChanges();
|
|
63
|
+
const select = page.locator('ion-select');
|
|
64
|
+
await expect(select).not.toHaveClass(/select-expanded/);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
});
|
|
@@ -9,6 +9,18 @@ export class SkeletonText {
|
|
|
9
9
|
constructor() {
|
|
10
10
|
this.animated = false;
|
|
11
11
|
}
|
|
12
|
+
componentWillLoad() {
|
|
13
|
+
this.emitStyle();
|
|
14
|
+
}
|
|
15
|
+
emitStyle() {
|
|
16
|
+
// The emitted property is used by item in order
|
|
17
|
+
// to add the item-skeleton-text class which applies
|
|
18
|
+
// overflow: hidden to its label
|
|
19
|
+
const style = {
|
|
20
|
+
'skeleton-text': true,
|
|
21
|
+
};
|
|
22
|
+
this.ionStyle.emit(style);
|
|
23
|
+
}
|
|
12
24
|
render() {
|
|
13
25
|
const animated = this.animated && config.getBoolean('animated', true);
|
|
14
26
|
const inMedia = hostContext('ion-avatar', this.el) || hostContext('ion-thumbnail', this.el);
|
|
@@ -53,5 +65,32 @@ export class SkeletonText {
|
|
|
53
65
|
}
|
|
54
66
|
};
|
|
55
67
|
}
|
|
68
|
+
static get events() {
|
|
69
|
+
return [{
|
|
70
|
+
"method": "ionStyle",
|
|
71
|
+
"name": "ionStyle",
|
|
72
|
+
"bubbles": true,
|
|
73
|
+
"cancelable": true,
|
|
74
|
+
"composed": true,
|
|
75
|
+
"docs": {
|
|
76
|
+
"tags": [{
|
|
77
|
+
"name": "internal",
|
|
78
|
+
"text": undefined
|
|
79
|
+
}],
|
|
80
|
+
"text": "Emitted when the styles change."
|
|
81
|
+
},
|
|
82
|
+
"complexType": {
|
|
83
|
+
"original": "StyleEventDetail",
|
|
84
|
+
"resolved": "StyleEventDetail",
|
|
85
|
+
"references": {
|
|
86
|
+
"StyleEventDetail": {
|
|
87
|
+
"location": "import",
|
|
88
|
+
"path": "../../interface",
|
|
89
|
+
"id": "src/interface.d.ts::StyleEventDetail"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}];
|
|
94
|
+
}
|
|
56
95
|
static get elementRef() { return "el"; }
|
|
57
96
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
|
+
*/
|
|
4
|
+
import { expect } from "@playwright/test";
|
|
5
|
+
import { configs, test } from "../../../../utils/test/playwright/index";
|
|
6
|
+
configs().forEach(({ title, screenshot, config }) => {
|
|
7
|
+
test.describe(title('textarea: start and end slots (visual checks)'), () => {
|
|
8
|
+
test('should not have visual regressions with a start-positioned label', async ({ page }) => {
|
|
9
|
+
await page.setContent(`
|
|
10
|
+
<ion-textarea label-placement="start" fill="solid" value="100" label="Weight">
|
|
11
|
+
<ion-icon slot="start" name="barbell" aria-hidden="true"></ion-icon>
|
|
12
|
+
<ion-label slot="end">lbs</ion-label>
|
|
13
|
+
</ion-textarea>
|
|
14
|
+
`, config);
|
|
15
|
+
const textarea = page.locator('ion-textarea');
|
|
16
|
+
await expect(textarea).toHaveScreenshot(screenshot(`textarea-slots-label-start`));
|
|
17
|
+
});
|
|
18
|
+
test('should not have visual regressions with a floating label', async ({ page }) => {
|
|
19
|
+
await page.setContent(`
|
|
20
|
+
<ion-textarea label-placement="floating" fill="solid" value="100" label="Weight">
|
|
21
|
+
<ion-icon slot="start" name="barbell" aria-hidden="true"></ion-icon>
|
|
22
|
+
<ion-label slot="end">lbs</ion-label>
|
|
23
|
+
</ion-textarea>
|
|
24
|
+
`, config);
|
|
25
|
+
const textarea = page.locator('ion-textarea');
|
|
26
|
+
await expect(textarea).toHaveScreenshot(screenshot(`textarea-slots-label-floating`));
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
|
31
|
+
test.describe(title('textarea: start and end slots (functionality checks)'), () => {
|
|
32
|
+
test('should raise floating label when there is content in the start slot', async ({ page }) => {
|
|
33
|
+
await page.setContent(`
|
|
34
|
+
<ion-textarea label-placement="floating" fill="solid" label="Weight">
|
|
35
|
+
<ion-icon slot="start" name="barbell" aria-hidden="true"></ion-icon>
|
|
36
|
+
</ion-textarea>
|
|
37
|
+
`, config);
|
|
38
|
+
const textarea = page.locator('ion-textarea');
|
|
39
|
+
await expect(textarea).toHaveClass(/label-floating/);
|
|
40
|
+
});
|
|
41
|
+
test('should raise floating label when there is content in the end slot', async ({ page }) => {
|
|
42
|
+
await page.setContent(`
|
|
43
|
+
<ion-textarea label-placement="floating" fill="solid" label="Weight">
|
|
44
|
+
<ion-icon slot="end" name="barbell" aria-hidden="true"></ion-icon>
|
|
45
|
+
</ion-textarea>
|
|
46
|
+
`, config);
|
|
47
|
+
const textarea = page.locator('ion-textarea');
|
|
48
|
+
await expect(textarea).toHaveClass(/label-floating/);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -356,9 +356,7 @@
|
|
|
356
356
|
}
|
|
357
357
|
|
|
358
358
|
.native-wrapper {
|
|
359
|
-
display: flex;
|
|
360
359
|
position: relative;
|
|
361
|
-
flex-grow: 1;
|
|
362
360
|
width: 100%;
|
|
363
361
|
height: 100%;
|
|
364
362
|
}
|
|
@@ -429,6 +427,12 @@
|
|
|
429
427
|
word-break: break-word;
|
|
430
428
|
}
|
|
431
429
|
|
|
430
|
+
.textarea-wrapper-inner {
|
|
431
|
+
display: flex;
|
|
432
|
+
width: 100%;
|
|
433
|
+
min-height: inherit;
|
|
434
|
+
}
|
|
435
|
+
|
|
432
436
|
:host(.ion-touched.ion-invalid) {
|
|
433
437
|
--highlight-color: var(--highlight-color-invalid);
|
|
434
438
|
}
|
|
@@ -704,6 +708,13 @@
|
|
|
704
708
|
margin-bottom: 0px;
|
|
705
709
|
}
|
|
706
710
|
|
|
711
|
+
:host(.textarea-label-placement-stacked) ::slotted([slot=start]),
|
|
712
|
+
:host(.textarea-label-placement-stacked) ::slotted([slot=end]),
|
|
713
|
+
:host(.textarea-label-placement-floating) ::slotted([slot=start]),
|
|
714
|
+
:host(.textarea-label-placement-floating) ::slotted([slot=end]) {
|
|
715
|
+
margin-top: 8px;
|
|
716
|
+
}
|
|
717
|
+
|
|
707
718
|
/**
|
|
708
719
|
* This makes the label sit over the textarea
|
|
709
720
|
* when the textarea is blurred and has no value.
|
|
@@ -729,9 +740,7 @@
|
|
|
729
740
|
/**
|
|
730
741
|
* This makes the label sit above the textarea.
|
|
731
742
|
*/
|
|
732
|
-
:host(.
|
|
733
|
-
:host(.has-focus.textarea-label-placement-floating) .label-text-wrapper,
|
|
734
|
-
:host(.has-value.textarea-label-placement-floating) .label-text-wrapper {
|
|
743
|
+
:host(.label-floating) .label-text-wrapper {
|
|
735
744
|
transform: translateY(50%) scale(0.75);
|
|
736
745
|
/**
|
|
737
746
|
* Label text should not extend
|
|
@@ -740,6 +749,29 @@
|
|
|
740
749
|
max-width: calc(100% / 0.75);
|
|
741
750
|
}
|
|
742
751
|
|
|
752
|
+
.start-slot-wrapper, .end-slot-wrapper {
|
|
753
|
+
padding-left: 0;
|
|
754
|
+
padding-right: 0;
|
|
755
|
+
padding-top: var(--padding-top);
|
|
756
|
+
padding-bottom: var(--padding-bottom);
|
|
757
|
+
display: flex;
|
|
758
|
+
flex-shrink: 0;
|
|
759
|
+
align-self: start;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
::slotted([slot=start]),
|
|
763
|
+
::slotted([slot=end]) {
|
|
764
|
+
margin-top: 0;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
::slotted([slot=start]) {
|
|
768
|
+
margin-inline-end: 16px;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
::slotted([slot=end]) {
|
|
772
|
+
margin-inline-start: 16px;
|
|
773
|
+
}
|
|
774
|
+
|
|
743
775
|
/**
|
|
744
776
|
* Convert a font size to a dynamic font size.
|
|
745
777
|
* Fonts that participate in Dynamic Type should use
|
|
@@ -13,6 +13,8 @@ import { getCounterText } from "../input/input.utils";
|
|
|
13
13
|
* @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
|
|
14
14
|
*
|
|
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
|
+
* @slot start - Content to display at the leading edge of the textarea. (EXPERIMENTAL)
|
|
17
|
+
* @slot end - Content to display at the trailing edge of the textarea. (EXPERIMENTAL)
|
|
16
18
|
*/
|
|
17
19
|
export class Textarea {
|
|
18
20
|
constructor() {
|
|
@@ -121,7 +123,7 @@ export class Textarea {
|
|
|
121
123
|
connectedCallback() {
|
|
122
124
|
const { el } = this;
|
|
123
125
|
this.legacyFormController = createLegacyFormController(el);
|
|
124
|
-
this.slotMutationController = createSlotMutationController(el, 'label', () => forceUpdate(this));
|
|
126
|
+
this.slotMutationController = createSlotMutationController(el, ['label', 'start', 'end'], () => forceUpdate(this));
|
|
125
127
|
this.notchController = createNotchController(el, () => this.notchSpacerEl, () => this.labelSlot);
|
|
126
128
|
this.emitStyle();
|
|
127
129
|
this.debounceChanged();
|
|
@@ -191,6 +193,8 @@ export class Textarea {
|
|
|
191
193
|
'has-placeholder': this.placeholder !== undefined,
|
|
192
194
|
'has-value': this.hasValue(),
|
|
193
195
|
'has-focus': this.hasFocus,
|
|
196
|
+
// TODO(FW-2876): remove this
|
|
197
|
+
legacy: !!this.legacy,
|
|
194
198
|
});
|
|
195
199
|
}
|
|
196
200
|
}
|
|
@@ -362,20 +366,41 @@ Developers can use the "legacy" property to continue using the legacy form marku
|
|
|
362
366
|
return (h("div", { class: "textarea-bottom" }, this.renderHintText(), this.renderCounter()));
|
|
363
367
|
}
|
|
364
368
|
renderTextarea() {
|
|
365
|
-
const { inputId, disabled, fill, shape, labelPlacement } = this;
|
|
369
|
+
const { inputId, disabled, fill, shape, labelPlacement, el, hasFocus } = this;
|
|
366
370
|
const mode = getIonMode(this);
|
|
367
371
|
const value = this.getValue();
|
|
368
372
|
const inItem = hostContext('ion-item', this.el);
|
|
369
373
|
const shouldRenderHighlight = mode === 'md' && fill !== 'outline' && !inItem;
|
|
374
|
+
const hasValue = this.hasValue();
|
|
375
|
+
const hasStartEndSlots = el.querySelector('[slot="start"], [slot="end"]') !== null;
|
|
376
|
+
/**
|
|
377
|
+
* If the label is stacked, it should always sit above the textarea.
|
|
378
|
+
* For floating labels, the label should move above the textarea if
|
|
379
|
+
* the textarea has a value, is focused, or has anything in either
|
|
380
|
+
* the start or end slot.
|
|
381
|
+
*
|
|
382
|
+
* If there is content in the start slot, the label would overlap
|
|
383
|
+
* it if not forced to float. This is also applied to the end slot
|
|
384
|
+
* because with the default or solid fills, the textarea is not
|
|
385
|
+
* vertically centered in the container, but the label is. This
|
|
386
|
+
* causes the slots and label to appear vertically offset from each
|
|
387
|
+
* other when the label isn't floating above the input. This doesn't
|
|
388
|
+
* apply to the outline fill, but this was not accounted for to keep
|
|
389
|
+
* things consistent.
|
|
390
|
+
*
|
|
391
|
+
* TODO(FW-5592): Remove hasStartEndSlots condition
|
|
392
|
+
*/
|
|
393
|
+
const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
|
|
370
394
|
return (h(Host, { class: createColorClasses(this.color, {
|
|
371
395
|
[mode]: true,
|
|
372
|
-
'has-value':
|
|
373
|
-
'has-focus':
|
|
396
|
+
'has-value': hasValue,
|
|
397
|
+
'has-focus': hasFocus,
|
|
398
|
+
'label-floating': labelShouldFloat,
|
|
374
399
|
[`textarea-fill-${fill}`]: fill !== undefined,
|
|
375
400
|
[`textarea-shape-${shape}`]: shape !== undefined,
|
|
376
401
|
[`textarea-label-placement-${labelPlacement}`]: true,
|
|
377
402
|
'textarea-disabled': disabled,
|
|
378
|
-
}) }, h("label", { class: "textarea-wrapper" }, this.renderLabelContainer(), h("div", { class: "native-wrapper", ref: (el) => (this.textareaWrapper = el) }, h("textarea", Object.assign({ class: "native-textarea", ref: (el) => (this.nativeInput = el), id: inputId, disabled: disabled, autoCapitalize: this.autocapitalize, autoFocus: this.autofocus, enterKeyHint: this.enterkeyhint, inputMode: this.inputmode, minLength: this.minlength, maxLength: this.maxlength, name: this.name, placeholder: this.placeholder || '', readOnly: this.readonly, required: this.required, spellcheck: this.spellcheck, cols: this.cols, rows: this.rows, wrap: this.wrap, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, onKeyDown: this.onKeyDown }, this.inheritedAttributes), value)), shouldRenderHighlight && h("div", { class: "textarea-highlight" })), this.renderBottomContent()));
|
|
403
|
+
}) }, h("label", { class: "textarea-wrapper", htmlFor: inputId }, this.renderLabelContainer(), h("div", { class: "textarea-wrapper-inner" }, h("div", { class: "start-slot-wrapper" }, h("slot", { name: "start" })), h("div", { class: "native-wrapper", ref: (el) => (this.textareaWrapper = el) }, h("textarea", Object.assign({ class: "native-textarea", ref: (el) => (this.nativeInput = el), id: inputId, disabled: disabled, autoCapitalize: this.autocapitalize, autoFocus: this.autofocus, enterKeyHint: this.enterkeyhint, inputMode: this.inputmode, minLength: this.minlength, maxLength: this.maxlength, name: this.name, placeholder: this.placeholder || '', readOnly: this.readonly, required: this.required, spellcheck: this.spellcheck, cols: this.cols, rows: this.rows, wrap: this.wrap, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, onKeyDown: this.onKeyDown }, this.inheritedAttributes), value)), h("div", { class: "end-slot-wrapper" }, h("slot", { name: "end" }))), shouldRenderHighlight && h("div", { class: "textarea-highlight" })), this.renderBottomContent()));
|
|
379
404
|
}
|
|
380
405
|
render() {
|
|
381
406
|
const { legacyFormController } = this;
|