voyager-ionic-core 8.0.1 → 8.1.0
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/checkbox.js +3 -3
- package/components/index2.js +119 -1
- package/components/ion-accordion-group.js +2 -2
- package/components/ion-content.js +6 -4
- package/components/ion-datetime-button.js +2 -2
- package/components/ion-datetime.js +17 -14
- package/components/ion-fab-button.js +2 -2
- package/components/ion-fab-list.js +2 -2
- package/components/ion-fab.js +2 -2
- package/components/ion-footer.js +2 -2
- package/components/ion-grid.js +2 -2
- package/components/ion-header.js +2 -2
- package/components/ion-img.js +1 -1
- package/components/ion-infinite-scroll-content.js +2 -2
- package/components/ion-infinite-scroll.js +1 -1
- package/components/ion-input-password-toggle.js +3 -3
- package/components/ion-input.js +8 -4
- package/components/ion-item-divider.js +2 -2
- package/components/ion-item-group.js +1 -1
- package/components/ion-item-option.js +2 -2
- package/components/ion-item-options.js +1 -1
- package/components/ion-item-sliding.js +1 -1
- package/components/ion-loading.js +2 -2
- package/components/ion-menu-button.js +2 -2
- package/components/ion-menu-toggle.js +2 -2
- package/components/ion-menu.js +2 -2
- package/components/ion-modal.js +10 -8
- package/components/ion-nav-link.js +1 -1
- package/components/ion-nav.js +1 -1
- package/components/ion-note.js +2 -2
- package/components/ion-picker-legacy.js +2 -2
- package/components/ion-progress-bar.js +1 -1
- package/components/ion-range.js +3 -3
- package/components/ion-refresher-content.js +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-router-link.js +2 -2
- package/components/ion-router-outlet.js +1 -1
- package/components/ion-row.js +1 -1
- package/components/ion-searchbar.js +4 -4
- package/components/ion-segment-button.js +3 -3
- package/components/ion-segment.js +2 -2
- package/components/ion-select-option.js +1 -1
- package/components/ion-select.js +2 -2
- package/components/ion-skeleton-text.js +2 -2
- package/components/ion-split-pane.js +2 -2
- package/components/ion-tab-bar.js +2 -2
- package/components/ion-tab-button.js +2 -2
- package/components/ion-tab.js +2 -2
- package/components/ion-tabs.js +1 -1
- package/components/ion-text.js +2 -2
- package/components/ion-textarea.js +2 -2
- package/components/ion-thumbnail.js +1 -1
- package/components/ion-title.js +2 -2
- package/components/ion-toast.js +2 -2
- package/components/ion-toggle.js +3 -3
- package/components/ion-toolbar.js +2 -2
- package/components/ios.transition.js +94 -67
- package/components/label.js +3 -3
- package/components/list-header.js +2 -2
- package/components/list.js +1 -1
- package/components/overlays.js +3 -2
- package/components/picker-column-option.js +2 -2
- package/components/picker-column.js +156 -4
- package/components/picker-column2.js +2 -2
- package/components/picker.js +2 -2
- package/components/popover.js +6 -4
- package/components/radio-group.js +1 -1
- package/components/radio.js +3 -3
- package/components/ripple-effect.js +1 -1
- package/components/select-popover.js +2 -2
- package/components/spinner.js +1 -1
- package/css/core.css +1 -1
- package/css/core.css.map +1 -1
- package/css/global.bundle.css.map +1 -1
- package/css/ionic.bundle.css +1 -1
- package/css/ionic.bundle.css.map +1 -1
- package/css/palettes/dark.always.css +1 -1
- package/css/palettes/dark.always.css.map +1 -1
- package/css/palettes/dark.class.css +1 -1
- package/css/palettes/dark.class.css.map +1 -1
- package/css/palettes/dark.system.css +1 -1
- package/css/palettes/dark.system.css.map +1 -1
- package/css/palettes/high-contrast-dark.always.css.map +1 -1
- package/css/palettes/high-contrast-dark.class.css.map +1 -1
- package/css/palettes/high-contrast-dark.system.css.map +1 -1
- package/css/palettes/high-contrast.always.css.map +1 -1
- package/css/palettes/high-contrast.class.css.map +1 -1
- package/css/palettes/high-contrast.system.css.map +1 -1
- package/css/typography.css.map +1 -1
- package/dist/cjs/{app-globals-542c4d91.js → app-globals-66b7dc06.js} +1 -1
- package/dist/cjs/{button-active-47528f4c.js → button-active-9135c809.js} +1 -1
- package/dist/cjs/{hardware-back-button-06ae4d9c.js → hardware-back-button-ed931127.js} +2 -2
- package/dist/cjs/index-8709af32.js +2234 -0
- package/dist/cjs/{index-c76a1d14.js → index-c0b7f8f4.js} +124 -6
- package/dist/cjs/{index-57b504ac.js → index-c54654c6.js} +2 -2
- package/dist/cjs/index.cjs.js +9 -9
- package/dist/cjs/ion-accordion_2.cjs.entry.js +4 -4
- package/dist/cjs/ion-action-sheet.cjs.entry.js +5 -5
- package/dist/cjs/ion-alert.cjs.entry.js +5 -5
- package/dist/cjs/ion-app_8.cjs.entry.js +20 -19
- package/dist/cjs/ion-avatar_3.cjs.entry.js +3 -3
- package/dist/cjs/ion-back-button.cjs.entry.js +2 -2
- package/dist/cjs/ion-backdrop.cjs.entry.js +2 -2
- package/dist/cjs/ion-breadcrumb_2.cjs.entry.js +2 -2
- package/dist/cjs/ion-button_2.cjs.entry.js +2 -2
- package/dist/cjs/ion-card_5.cjs.entry.js +2 -2
- package/dist/cjs/ion-checkbox.cjs.entry.js +5 -5
- package/dist/cjs/ion-chip.cjs.entry.js +2 -2
- package/dist/cjs/ion-col_3.cjs.entry.js +5 -5
- package/dist/cjs/ion-datetime-button.cjs.entry.js +4 -4
- package/dist/cjs/ion-datetime_3.cjs.entry.js +25 -22
- package/dist/cjs/ion-fab_3.cjs.entry.js +8 -8
- package/dist/cjs/ion-img.cjs.entry.js +3 -3
- package/dist/cjs/ion-infinite-scroll_2.cjs.entry.js +5 -5
- package/dist/cjs/ion-input-password-toggle.cjs.entry.js +5 -5
- package/dist/cjs/ion-input.cjs.entry.js +9 -6
- package/dist/cjs/ion-item-option_3.cjs.entry.js +6 -6
- package/dist/cjs/ion-item_8.cjs.entry.js +15 -15
- package/dist/cjs/ion-loading.cjs.entry.js +6 -6
- package/dist/cjs/ion-menu_3.cjs.entry.js +11 -11
- package/dist/cjs/ion-modal.cjs.entry.js +13 -12
- package/dist/cjs/ion-nav_2.cjs.entry.js +6 -5
- package/dist/cjs/ion-picker-column-option.cjs.entry.js +4 -4
- package/dist/cjs/ion-picker-column.cjs.entry.js +156 -6
- package/dist/cjs/ion-picker.cjs.entry.js +3 -3
- package/dist/cjs/ion-popover.cjs.entry.js +9 -8
- package/dist/cjs/ion-progress-bar.cjs.entry.js +3 -3
- package/dist/cjs/ion-radio_2.cjs.entry.js +6 -6
- package/dist/cjs/ion-range.cjs.entry.js +5 -5
- package/dist/cjs/ion-refresher_2.cjs.entry.js +4 -4
- package/dist/cjs/ion-reorder_2.cjs.entry.js +4 -4
- package/dist/cjs/ion-ripple-effect.cjs.entry.js +3 -3
- package/dist/cjs/ion-route_4.cjs.entry.js +4 -4
- package/dist/cjs/ion-searchbar.cjs.entry.js +6 -6
- package/dist/cjs/ion-segment_2.cjs.entry.js +7 -7
- package/dist/cjs/ion-select_3.cjs.entry.js +9 -9
- package/dist/cjs/ion-spinner.cjs.entry.js +3 -3
- package/dist/cjs/ion-split-pane.cjs.entry.js +4 -4
- package/dist/cjs/ion-tab-bar_2.cjs.entry.js +6 -6
- package/dist/cjs/ion-tab_2.cjs.entry.js +4 -4
- package/dist/cjs/ion-text.cjs.entry.js +4 -4
- package/dist/cjs/ion-textarea.cjs.entry.js +4 -4
- package/dist/cjs/ion-toast.cjs.entry.js +6 -6
- package/dist/cjs/ion-toggle.cjs.entry.js +5 -5
- package/dist/cjs/{ionic-global-f3622afe.js → ionic-global-35b86a09.js} +1 -1
- package/dist/cjs/ionic.cjs.js +5 -5
- package/dist/cjs/{ios.transition-288dfa83.js → ios.transition-5ddf92f1.js} +98 -69
- package/dist/cjs/loader.cjs.js +4 -4
- package/dist/cjs/{md.transition-6e5f6a8d.js → md.transition-047c18c5.js} +4 -2
- package/dist/cjs/{overlays-32cfd236.js → overlays-cb04d075.js} +5 -3
- package/dist/cjs/{status-tap-c47ff5f5.js → status-tap-5b2775cd.js} +1 -1
- package/dist/collection/collection-manifest.json +1 -1
- package/dist/collection/components/accordion-group/accordion-group.js +3 -3
- package/dist/collection/components/checkbox/checkbox.js +4 -4
- package/dist/collection/components/content/content.js +23 -4
- package/dist/collection/components/content/test/content.spec.js +27 -0
- package/dist/collection/components/datetime/datetime.js +18 -15
- package/dist/collection/components/datetime/test/overlay-roles/datetime.e2e.js +34 -0
- package/dist/collection/components/datetime-button/datetime-button.js +2 -2
- package/dist/collection/components/fab/fab.js +2 -2
- package/dist/collection/components/fab-button/fab-button.js +2 -2
- package/dist/collection/components/fab-list/fab-list.js +2 -2
- package/dist/collection/components/footer/footer.js +2 -2
- package/dist/collection/components/grid/grid.js +2 -2
- package/dist/collection/components/header/header.js +2 -2
- package/dist/collection/components/img/img.js +1 -1
- package/dist/collection/components/infinite-scroll/infinite-scroll.js +1 -1
- package/dist/collection/components/infinite-scroll-content/infinite-scroll-content.js +2 -2
- package/dist/collection/components/input/input.js +25 -5
- package/dist/collection/components/input/test/input.spec.js +13 -0
- package/dist/collection/components/input-password-toggle/input-password-toggle.js +3 -3
- package/dist/collection/components/item/test/a11y/item.e2e.js +24 -4
- package/dist/collection/components/item-divider/item-divider.js +2 -2
- package/dist/collection/components/item-group/item-group.js +1 -1
- package/dist/collection/components/item-option/item-option.js +2 -2
- package/dist/collection/components/item-options/item-options.js +1 -1
- package/dist/collection/components/item-sliding/item-sliding.js +1 -1
- package/dist/collection/components/label/label.ios.css +1 -1
- package/dist/collection/components/label/label.js +2 -2
- package/dist/collection/components/list/list.js +1 -1
- package/dist/collection/components/list-header/list-header.js +2 -2
- package/dist/collection/components/loading/loading.js +2 -2
- package/dist/collection/components/menu/menu.js +2 -2
- package/dist/collection/components/menu-button/menu-button.js +2 -2
- package/dist/collection/components/menu-toggle/menu-toggle.js +2 -2
- package/dist/collection/components/modal/gestures/sheet.js +3 -2
- package/dist/collection/components/modal/modal.js +25 -6
- package/dist/collection/components/modal/test/basic/modal.spec.js +19 -0
- package/dist/collection/components/nav/nav.js +1 -1
- package/dist/collection/components/nav-link/nav-link.js +1 -1
- package/dist/collection/components/note/note.js +2 -2
- package/dist/collection/components/picker/picker.js +2 -2
- package/dist/collection/components/picker-column/picker-column.css +19 -0
- package/dist/collection/components/picker-column/picker-column.js +159 -4
- package/dist/collection/components/picker-column/test/picker-column.spec.js +83 -0
- package/dist/collection/components/picker-column-option/picker-column-option.js +2 -2
- package/dist/collection/components/picker-legacy/picker.js +2 -2
- package/dist/collection/components/picker-legacy-column/picker-column.js +2 -2
- package/dist/collection/components/popover/popover.js +23 -4
- package/dist/collection/components/popover/test/basic/popover.spec.js +19 -0
- package/dist/collection/components/progress-bar/progress-bar.js +1 -1
- package/dist/collection/components/radio/radio.js +3 -3
- package/dist/collection/components/radio-group/radio-group.js +2 -2
- package/dist/collection/components/range/range.js +4 -4
- 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/router-link/router-link.js +2 -2
- package/dist/collection/components/router-outlet/router-outlet.js +1 -1
- package/dist/collection/components/row/row.js +1 -1
- package/dist/collection/components/searchbar/searchbar.js +5 -5
- package/dist/collection/components/segment/segment.js +3 -3
- package/dist/collection/components/segment-button/segment-button.js +3 -3
- package/dist/collection/components/select/select.js +3 -3
- package/dist/collection/components/select/test/fill/select.e2e.js +25 -0
- package/dist/collection/components/select-option/select-option.js +1 -1
- package/dist/collection/components/select-popover/select-popover.js +1 -1
- package/dist/collection/components/select-popover/select-popover.md.css +8 -1
- 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 +3 -3
- 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 +4 -4
- package/dist/collection/components/toolbar/toolbar.js +2 -2
- package/dist/collection/utils/focus-controller/index.js +112 -0
- package/dist/collection/utils/focus-controller/test/generic/focus-controller.e2e.js +52 -0
- package/dist/collection/utils/focus-controller/test/ionic/focus-controller.e2e.js +52 -0
- package/dist/collection/utils/overlays.js +2 -1
- package/dist/collection/utils/transition/index.js +11 -1
- package/dist/collection/utils/transition/ios.transition.js +94 -67
- package/dist/docs.json +109 -14
- package/dist/esm/{app-globals-3cbaf9d9.js → app-globals-b99e6d29.js} +1 -1
- package/dist/esm/{button-active-9e3c1f3b.js → button-active-920addb8.js} +1 -1
- package/dist/esm/{hardware-back-button-804f43bb.js → hardware-back-button-2d9760b6.js} +2 -2
- package/dist/esm/{index-8dbae644.js → index-7ae7186a.js} +2 -2
- package/dist/esm/{index-f7fbe1fb.js → index-8e6b6a24.js} +122 -4
- package/dist/esm/index-9aab3bcf.js +2196 -0
- package/dist/esm/index.js +9 -9
- package/dist/esm/ion-accordion_2.entry.js +4 -4
- package/dist/esm/ion-action-sheet.entry.js +5 -5
- package/dist/esm/ion-alert.entry.js +5 -5
- package/dist/esm/ion-app_8.entry.js +20 -19
- package/dist/esm/ion-avatar_3.entry.js +3 -3
- package/dist/esm/ion-back-button.entry.js +2 -2
- package/dist/esm/ion-backdrop.entry.js +2 -2
- package/dist/esm/ion-breadcrumb_2.entry.js +2 -2
- package/dist/esm/ion-button_2.entry.js +2 -2
- package/dist/esm/ion-card_5.entry.js +2 -2
- package/dist/esm/ion-checkbox.entry.js +5 -5
- package/dist/esm/ion-chip.entry.js +2 -2
- package/dist/esm/ion-col_3.entry.js +5 -5
- package/dist/esm/ion-datetime-button.entry.js +4 -4
- package/dist/esm/ion-datetime_3.entry.js +25 -22
- package/dist/esm/ion-fab_3.entry.js +8 -8
- package/dist/esm/ion-img.entry.js +3 -3
- package/dist/esm/ion-infinite-scroll_2.entry.js +5 -5
- package/dist/esm/ion-input-password-toggle.entry.js +5 -5
- package/dist/esm/ion-input.entry.js +9 -6
- package/dist/esm/ion-item-option_3.entry.js +6 -6
- package/dist/esm/ion-item_8.entry.js +15 -15
- package/dist/esm/ion-loading.entry.js +6 -6
- package/dist/esm/ion-menu_3.entry.js +11 -11
- package/dist/esm/ion-modal.entry.js +13 -12
- package/dist/esm/ion-nav_2.entry.js +6 -5
- package/dist/esm/ion-picker-column-option.entry.js +4 -4
- package/dist/esm/ion-picker-column.entry.js +156 -6
- package/dist/esm/ion-picker.entry.js +3 -3
- package/dist/esm/ion-popover.entry.js +9 -8
- package/dist/esm/ion-progress-bar.entry.js +3 -3
- package/dist/esm/ion-radio_2.entry.js +6 -6
- package/dist/esm/ion-range.entry.js +5 -5
- package/dist/esm/ion-refresher_2.entry.js +4 -4
- package/dist/esm/ion-reorder_2.entry.js +4 -4
- package/dist/esm/ion-ripple-effect.entry.js +3 -3
- package/dist/esm/ion-route_4.entry.js +4 -4
- package/dist/esm/ion-searchbar.entry.js +6 -6
- package/dist/esm/ion-segment_2.entry.js +7 -7
- package/dist/esm/ion-select_3.entry.js +9 -9
- package/dist/esm/ion-spinner.entry.js +3 -3
- package/dist/esm/ion-split-pane.entry.js +4 -4
- package/dist/esm/ion-tab-bar_2.entry.js +6 -6
- package/dist/esm/ion-tab_2.entry.js +4 -4
- package/dist/esm/ion-text.entry.js +4 -4
- package/dist/esm/ion-textarea.entry.js +4 -4
- package/dist/esm/ion-toast.entry.js +6 -6
- package/dist/esm/ion-toggle.entry.js +5 -5
- package/dist/esm/{ionic-global-d2d8f882.js → ionic-global-4528d288.js} +1 -1
- package/dist/esm/ionic.js +6 -6
- package/dist/esm/{ios.transition-a0041e41.js → ios.transition-e35d0940.js} +98 -69
- package/dist/esm/loader.js +5 -5
- package/dist/esm/{md.transition-0c0602d9.js → md.transition-4b90a1f0.js} +4 -2
- package/dist/esm/{overlays-696d25f5.js → overlays-df2c06b2.js} +5 -4
- package/dist/esm/{status-tap-37a74d1c.js → status-tap-12c27922.js} +1 -1
- package/dist/esm-es5/app-globals-b99e6d29.js +4 -0
- package/dist/esm-es5/{button-active-9e3c1f3b.js → button-active-920addb8.js} +1 -1
- package/dist/esm-es5/{hardware-back-button-804f43bb.js → hardware-back-button-2d9760b6.js} +1 -1
- package/dist/esm-es5/{index-8dbae644.js → index-7ae7186a.js} +1 -1
- package/dist/esm-es5/index-8e6b6a24.js +4 -0
- package/dist/esm-es5/index-9aab3bcf.js +5 -0
- package/dist/esm-es5/index.js +1 -1
- package/dist/esm-es5/ion-accordion_2.entry.js +1 -1
- 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-avatar_3.entry.js +1 -1
- package/dist/esm-es5/ion-back-button.entry.js +1 -1
- package/dist/esm-es5/ion-backdrop.entry.js +1 -1
- package/dist/esm-es5/ion-breadcrumb_2.entry.js +1 -1
- package/dist/esm-es5/ion-button_2.entry.js +1 -1
- package/dist/esm-es5/ion-card_5.entry.js +1 -1
- package/dist/esm-es5/ion-checkbox.entry.js +1 -1
- package/dist/esm-es5/ion-chip.entry.js +1 -1
- package/dist/esm-es5/ion-col_3.entry.js +1 -1
- package/dist/esm-es5/ion-datetime-button.entry.js +1 -1
- package/dist/esm-es5/ion-datetime_3.entry.js +1 -1
- package/dist/esm-es5/ion-fab_3.entry.js +1 -1
- package/dist/esm-es5/ion-img.entry.js +1 -1
- package/dist/esm-es5/ion-infinite-scroll_2.entry.js +1 -1
- package/dist/esm-es5/ion-input-password-toggle.entry.js +1 -1
- package/dist/esm-es5/ion-input.entry.js +1 -1
- package/dist/esm-es5/ion-item-option_3.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-option.entry.js +1 -1
- package/dist/esm-es5/ion-picker-column.entry.js +1 -1
- package/dist/esm-es5/ion-picker.entry.js +1 -1
- package/dist/esm-es5/ion-popover.entry.js +1 -1
- package/dist/esm-es5/ion-progress-bar.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-ripple-effect.entry.js +1 -1
- package/dist/esm-es5/ion-route_4.entry.js +1 -1
- package/dist/esm-es5/ion-searchbar.entry.js +1 -1
- package/dist/esm-es5/ion-segment_2.entry.js +1 -1
- package/dist/esm-es5/ion-select_3.entry.js +1 -1
- package/dist/esm-es5/ion-spinner.entry.js +1 -1
- package/dist/esm-es5/ion-split-pane.entry.js +1 -1
- package/dist/esm-es5/ion-tab-bar_2.entry.js +1 -1
- package/dist/esm-es5/ion-tab_2.entry.js +1 -1
- package/dist/esm-es5/ion-text.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-global-d2d8f882.js → ionic-global-4528d288.js} +1 -1
- package/dist/esm-es5/ionic.js +1 -1
- package/dist/esm-es5/ios.transition-e35d0940.js +4 -0
- package/dist/esm-es5/loader.js +1 -1
- package/dist/esm-es5/md.transition-4b90a1f0.js +4 -0
- package/dist/esm-es5/{overlays-696d25f5.js → overlays-df2c06b2.js} +1 -1
- package/dist/esm-es5/{status-tap-37a74d1c.js → status-tap-12c27922.js} +1 -1
- package/dist/html.html-data.json +24 -0
- package/dist/ionic/index.esm.js +1 -1
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/ionic.js +1 -1
- package/dist/ionic/{p-94731a92.system.entry.js → p-01a27023.system.entry.js} +1 -1
- package/dist/ionic/p-0395be73.entry.js +4 -0
- package/dist/ionic/p-03b86a5e.js +4 -0
- package/dist/ionic/{p-057b5866.entry.js → p-049d43bd.entry.js} +1 -1
- package/dist/ionic/p-0536574e.entry.js +4 -0
- package/dist/ionic/{p-e3005be4.system.entry.js → p-08ea3402.system.entry.js} +1 -1
- package/dist/ionic/{p-3f5b86b4.entry.js → p-09538818.entry.js} +1 -1
- package/dist/ionic/{p-470f73c4.entry.js → p-09b4e9ec.entry.js} +1 -1
- package/dist/ionic/{p-aa0ed22b.system.entry.js → p-0a6d801e.system.entry.js} +1 -1
- package/dist/ionic/{p-53a3b33c.system.entry.js → p-0b007acc.system.entry.js} +1 -1
- package/dist/ionic/{p-b76bcd9e.system.entry.js → p-10feef7e.system.entry.js} +1 -1
- package/dist/ionic/p-130299c9.entry.js +4 -0
- package/dist/ionic/p-15d1ddba.js +4 -0
- package/dist/ionic/{p-c3ca0292.system.entry.js → p-199f826f.system.entry.js} +1 -1
- package/dist/ionic/p-1b435d20.entry.js +4 -0
- package/dist/ionic/{p-c671b28e.js → p-1cc0b31f.js} +1 -1
- package/dist/ionic/{p-c4676693.entry.js → p-1eb63fa4.entry.js} +1 -1
- package/dist/ionic/{p-9b31ebfa.entry.js → p-207e11dc.entry.js} +1 -1
- package/dist/ionic/p-26bb6bb8.entry.js +4 -0
- package/dist/ionic/{p-5d3a8503.system.entry.js → p-279f3bac.system.entry.js} +1 -1
- package/dist/ionic/{p-e49099b0.entry.js → p-29de09dd.entry.js} +1 -1
- package/dist/ionic/{p-6730a2f1.entry.js → p-2c588aa2.entry.js} +1 -1
- package/dist/ionic/p-2ff0e0aa.system.js +4 -0
- package/dist/ionic/p-30baae57.system.js +4 -0
- package/dist/ionic/{p-806aad8f.system.js → p-31d27232.system.js} +1 -1
- package/dist/ionic/p-33e10509.system.js +4 -0
- package/dist/ionic/{p-a592f1b8.system.entry.js → p-380efbfa.system.entry.js} +1 -1
- package/dist/ionic/p-3c27be4a.entry.js +4 -0
- package/dist/ionic/p-3d015cdb.system.js +5 -0
- package/dist/ionic/{p-70181008.entry.js → p-3f53a0b1.entry.js} +1 -1
- package/dist/ionic/p-433157a4.entry.js +4 -0
- package/dist/ionic/{p-fc94e18f.entry.js → p-4824398b.entry.js} +1 -1
- package/dist/ionic/p-498eb648.system.entry.js +4 -0
- package/dist/ionic/{p-8caca06c.system.entry.js → p-4d8f408d.system.entry.js} +1 -1
- package/dist/ionic/{p-4c153abb.entry.js → p-5091f63c.entry.js} +1 -1
- package/dist/ionic/{p-42f00e72.system.entry.js → p-509620b8.system.entry.js} +1 -1
- package/dist/ionic/{p-d1a8f599.entry.js → p-5109a566.entry.js} +1 -1
- package/dist/ionic/{p-7f59064a.entry.js → p-52ce473d.entry.js} +1 -1
- package/dist/ionic/{p-33d926c3.entry.js → p-52f53904.entry.js} +1 -1
- package/dist/ionic/{p-4e548bd7.system.entry.js → p-55f99a39.system.entry.js} +1 -1
- package/dist/ionic/{p-1e4d7975.system.js → p-5734ac17.system.js} +1 -1
- package/dist/ionic/{p-2b1e669d.system.entry.js → p-57bc32e2.system.entry.js} +1 -1
- package/dist/ionic/{p-d11c336d.js → p-5cc6dcf5.js} +1 -1
- package/dist/ionic/p-5dc9f99a.entry.js +4 -0
- package/dist/ionic/p-5ec3bb70.system.entry.js +4 -0
- package/dist/ionic/{p-ebe0aa6d.entry.js → p-606f069c.entry.js} +1 -1
- package/dist/ionic/{p-93e43f42.system.entry.js → p-628967e3.system.entry.js} +1 -1
- package/dist/ionic/{p-5fbc2eae.system.entry.js → p-62e44e4a.system.entry.js} +1 -1
- package/dist/ionic/p-66ed603b.js +4 -0
- package/dist/ionic/{p-a801da4b.system.entry.js → p-670c9f57.system.entry.js} +1 -1
- package/dist/ionic/{p-fd392e7f.system.entry.js → p-6a2cf398.system.entry.js} +1 -1
- package/dist/ionic/{p-5a3a3373.entry.js → p-6c3666d5.entry.js} +1 -1
- package/dist/ionic/{p-1a5227b3.system.entry.js → p-6df12af0.system.entry.js} +1 -1
- package/dist/ionic/{p-bd6d9610.entry.js → p-6ec88301.entry.js} +1 -1
- package/dist/ionic/p-6f008ad2.js +4 -0
- package/dist/ionic/{p-2ab5db0d.system.entry.js → p-700567ab.system.entry.js} +1 -1
- package/dist/ionic/p-712d54ae.js +4 -0
- package/dist/ionic/{p-94180ecc.entry.js → p-7349de07.entry.js} +1 -1
- package/dist/ionic/p-7402fcdf.entry.js +4 -0
- package/dist/ionic/{p-5ff497dc.system.entry.js → p-77731f19.system.entry.js} +1 -1
- package/dist/ionic/{p-c07e7a5d.entry.js → p-78405458.entry.js} +1 -1
- package/dist/ionic/{p-748e6b2b.system.entry.js → p-7d6fd45f.system.entry.js} +1 -1
- package/dist/ionic/{p-720927ad.entry.js → p-7eb47906.entry.js} +1 -1
- package/dist/ionic/p-80265a58.entry.js +4 -0
- package/dist/ionic/{p-8627f783.system.entry.js → p-83d748f8.system.entry.js} +2 -2
- package/dist/ionic/p-842c9fca.system.js +4 -0
- package/dist/ionic/{p-c7e0b81a.entry.js → p-8a03fbee.entry.js} +1 -1
- package/dist/ionic/{p-576786c0.system.entry.js → p-8cb80f83.system.entry.js} +1 -1
- package/dist/ionic/{p-cdee3a44.system.entry.js → p-8d14ee8c.system.entry.js} +2 -2
- package/dist/ionic/p-90dfc454.system.entry.js +4 -0
- package/dist/ionic/{p-819e8479.system.entry.js → p-9213681c.system.entry.js} +1 -1
- package/dist/ionic/p-92d7e99d.system.js +4 -0
- package/dist/ionic/{p-d6229f05.system.entry.js → p-9664a1a2.system.entry.js} +1 -1
- package/dist/ionic/{p-b799a007.entry.js → p-9797f6eb.entry.js} +1 -1
- package/dist/ionic/{p-5d4d89e0.system.entry.js → p-9848d7be.system.entry.js} +1 -1
- package/dist/ionic/{p-9384565a.entry.js → p-98f6116f.entry.js} +1 -1
- package/dist/ionic/{p-c62571da.entry.js → p-99884813.entry.js} +1 -1
- package/dist/ionic/{p-48888af6.system.entry.js → p-99ca9787.system.entry.js} +1 -1
- package/dist/ionic/{p-45034312.system.entry.js → p-9bfd7cda.system.entry.js} +1 -1
- package/dist/ionic/p-9c6dcf78.system.entry.js +4 -0
- package/dist/ionic/{p-051d2d23.js → p-9da86308.js} +1 -1
- package/dist/ionic/{p-34511b1d.js → p-9ec42be0.js} +1 -1
- package/dist/ionic/{p-0d960144.system.entry.js → p-a2e94ade.system.entry.js} +1 -1
- package/dist/ionic/{p-1980c728.system.js → p-a39d3482.system.js} +1 -1
- package/dist/ionic/p-a488b7ab.system.js +4 -0
- package/dist/ionic/{p-5d80b741.entry.js → p-a4ab7449.entry.js} +1 -1
- package/dist/ionic/{p-2c3c7cb9.system.entry.js → p-a50f23bf.system.entry.js} +2 -2
- package/dist/ionic/{p-80f85095.system.entry.js → p-a76ab3ea.system.entry.js} +1 -1
- package/dist/ionic/{p-77ce6034.js → p-a953ef66.js} +1 -1
- package/dist/ionic/{p-08c4d048.entry.js → p-aaaaaea1.entry.js} +1 -1
- package/dist/ionic/{p-c23627c3.entry.js → p-b02eda30.entry.js} +1 -1
- package/dist/ionic/{p-49cdc4f2.entry.js → p-b04c27d8.entry.js} +1 -1
- package/dist/ionic/{p-0b12d1ee.system.entry.js → p-b07affd5.system.entry.js} +1 -1
- package/dist/ionic/{p-2f308f7f.system.entry.js → p-b28d3ccb.system.entry.js} +2 -2
- package/dist/ionic/{p-320cfcab.entry.js → p-b563b6ac.entry.js} +1 -1
- package/dist/ionic/p-b62ae60a.system.entry.js +4 -0
- package/dist/ionic/p-b9181033.system.entry.js +4 -0
- package/dist/ionic/{p-1930d8e7.entry.js → p-ba70039f.entry.js} +1 -1
- package/dist/ionic/{p-b571cab1.entry.js → p-bbbe869e.entry.js} +1 -1
- package/dist/ionic/{p-283fd4e1.system.entry.js → p-c41435e6.system.entry.js} +1 -1
- package/dist/ionic/p-cec8589b.system.js +4 -0
- package/dist/ionic/{p-bbbe3138.system.entry.js → p-d69b26d9.system.entry.js} +1 -1
- package/dist/ionic/p-d73a16e6.system.entry.js +4 -0
- package/dist/ionic/p-dba5cb84.js +5 -0
- package/dist/ionic/{p-63265e00.system.entry.js → p-dc0d9ff5.system.entry.js} +2 -2
- package/dist/ionic/{p-f5c42f72.entry.js → p-dc1e363a.entry.js} +1 -1
- package/dist/ionic/{p-c9ba1908.entry.js → p-df517d1f.entry.js} +1 -1
- package/dist/ionic/{p-2a3e98fb.system.entry.js → p-e0a8ffd0.system.entry.js} +1 -1
- package/dist/ionic/{p-e9ef13be.system.entry.js → p-e6e197f5.system.entry.js} +1 -1
- package/dist/ionic/{p-0af79ebd.entry.js → p-e6e88ab9.entry.js} +1 -1
- package/dist/ionic/{p-4e5288de.system.js → p-e81f22e3.system.js} +1 -1
- package/dist/ionic/{p-aa0f60b2.system.js → p-eb3023c9.system.js} +1 -1
- package/dist/ionic/p-ecbdbf25.system.entry.js +4 -0
- package/dist/ionic/{p-26d33af2.system.entry.js → p-ed5aebaa.system.entry.js} +1 -1
- package/dist/ionic/{p-23e440b6.entry.js → p-f357707e.entry.js} +1 -1
- package/dist/ionic/{p-e885f3c4.entry.js → p-f53bcebd.entry.js} +1 -1
- package/dist/ionic/p-f9baf25c.entry.js +4 -0
- package/dist/ionic/{p-ee3bbaf2.entry.js → p-fa8f2e62.entry.js} +1 -1
- package/dist/ionic/{p-6e9bd6ba.system.entry.js → p-fb21fd1c.system.entry.js} +1 -1
- package/dist/ionic/{p-bdd3053f.entry.js → p-fcecca8f.entry.js} +1 -1
- package/dist/types/components/accordion-group/accordion-group.d.ts +3 -4
- package/dist/types/components/checkbox/checkbox.d.ts +3 -4
- package/dist/types/components/content/content.d.ts +8 -0
- package/dist/types/components/datetime/datetime.d.ts +2 -0
- package/dist/types/components/input/input.d.ts +6 -0
- package/dist/types/components/modal/modal-interface.d.ts +1 -0
- package/dist/types/components/modal/modal.d.ts +18 -0
- package/dist/types/components/picker-column/picker-column.d.ts +37 -0
- package/dist/types/components/popover/popover-interface.d.ts +1 -0
- package/dist/types/components/popover/popover.d.ts +18 -0
- package/dist/types/components/radio-group/radio-group.d.ts +2 -0
- package/dist/types/components/range/range.d.ts +1 -1
- package/dist/types/components/searchbar/searchbar.d.ts +2 -0
- package/dist/types/components/segment/segment.d.ts +3 -2
- package/dist/types/components/select/select.d.ts +2 -0
- package/dist/types/components/textarea/textarea.d.ts +2 -0
- package/dist/types/components/toggle/toggle.d.ts +3 -2
- package/dist/types/components.d.ts +44 -12
- package/dist/types/utils/config.d.ts +9 -0
- package/dist/types/utils/focus-controller/index.d.ts +13 -0
- package/dist/types/utils/overlays.d.ts +1 -0
- package/hydrate/index.js +43566 -39256
- package/package.json +6 -6
- package/dist/cjs/index-1437d080.js +0 -11980
- package/dist/esm/index-5dc2b88e.js +0 -11942
- package/dist/esm-es5/app-globals-3cbaf9d9.js +0 -4
- package/dist/esm-es5/index-5dc2b88e.js +0 -18
- package/dist/esm-es5/index-f7fbe1fb.js +0 -4
- package/dist/esm-es5/ios.transition-a0041e41.js +0 -4
- package/dist/esm-es5/md.transition-0c0602d9.js +0 -4
- package/dist/ionic/p-06d5221c.js +0 -4
- package/dist/ionic/p-06fad524.system.js +0 -4
- package/dist/ionic/p-0d56dea9.entry.js +0 -4
- package/dist/ionic/p-13bfcef4.system.entry.js +0 -4
- package/dist/ionic/p-16016625.system.js +0 -4
- package/dist/ionic/p-20304962.js +0 -4
- package/dist/ionic/p-2dfdda15.system.entry.js +0 -4
- package/dist/ionic/p-2fa34b5c.entry.js +0 -4
- package/dist/ionic/p-32048e4c.system.js +0 -18
- package/dist/ionic/p-385964e6.entry.js +0 -4
- package/dist/ionic/p-4324e8a4.entry.js +0 -4
- package/dist/ionic/p-45664cb9.system.js +0 -4
- package/dist/ionic/p-4ad48ec9.system.entry.js +0 -4
- package/dist/ionic/p-4af0b730.js +0 -8
- package/dist/ionic/p-4fcef939.entry.js +0 -4
- package/dist/ionic/p-567a21a2.system.entry.js +0 -4
- package/dist/ionic/p-583f8865.system.entry.js +0 -4
- package/dist/ionic/p-58f89707.js +0 -4
- package/dist/ionic/p-7536b4b3.system.js +0 -4
- package/dist/ionic/p-7ef5bb32.entry.js +0 -4
- package/dist/ionic/p-8664c316.entry.js +0 -4
- package/dist/ionic/p-8c4fc85f.system.js +0 -4
- package/dist/ionic/p-8e031d97.entry.js +0 -4
- package/dist/ionic/p-8f48c966.system.entry.js +0 -4
- package/dist/ionic/p-adb896a0.entry.js +0 -4
- package/dist/ionic/p-b0093947.system.js +0 -4
- package/dist/ionic/p-cb4f96f3.system.js +0 -4
- package/dist/ionic/p-cc856712.entry.js +0 -4
- package/dist/ionic/p-cd1b9056.js +0 -4
- package/dist/ionic/p-d918e7ef.system.entry.js +0 -4
- package/dist/ionic/p-df062892.system.entry.js +0 -4
- package/dist/ionic/p-f0be340f.entry.js +0 -4
- package/dist/ionic/p-fdf40b09.js +0 -4
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
|
+
*/
|
|
4
|
+
import { config } from "../../global/config";
|
|
5
|
+
import { printIonWarning } from "../logging/index";
|
|
6
|
+
/**
|
|
7
|
+
* Moves focus to a specified element. Note that we do not remove the tabindex
|
|
8
|
+
* because that can result in an unintentional blur. Non-focusables can't be
|
|
9
|
+
* focused, so the body will get focused again.
|
|
10
|
+
*/
|
|
11
|
+
const moveFocus = (el) => {
|
|
12
|
+
el.tabIndex = -1;
|
|
13
|
+
el.focus();
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Elements that are hidden using `display: none` should not be focused even if
|
|
17
|
+
* they are present in the DOM.
|
|
18
|
+
*/
|
|
19
|
+
const isVisible = (el) => {
|
|
20
|
+
return el.offsetParent !== null;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* The focus controller allows us to manage focus within a view so assistive
|
|
24
|
+
* technologies can inform users of changes to the navigation state. Traditional
|
|
25
|
+
* native apps have a way of informing assistive technology about a navigation
|
|
26
|
+
* state change. Mobile browsers have this too, but only when doing a full page
|
|
27
|
+
* load. In a single page app we do not do that, so we need to build this
|
|
28
|
+
* integration ourselves.
|
|
29
|
+
*/
|
|
30
|
+
export const createFocusController = () => {
|
|
31
|
+
const saveViewFocus = (referenceEl) => {
|
|
32
|
+
const focusManagerEnabled = config.get('focusManagerPriority', false);
|
|
33
|
+
/**
|
|
34
|
+
* When going back to a previously visited page focus should typically be moved
|
|
35
|
+
* back to the element that was last focused when the user was on this view.
|
|
36
|
+
*/
|
|
37
|
+
if (focusManagerEnabled) {
|
|
38
|
+
const activeEl = document.activeElement;
|
|
39
|
+
if (activeEl !== null && (referenceEl === null || referenceEl === void 0 ? void 0 : referenceEl.contains(activeEl))) {
|
|
40
|
+
activeEl.setAttribute(LAST_FOCUS, 'true');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
const setViewFocus = (referenceEl) => {
|
|
45
|
+
const focusManagerPriorities = config.get('focusManagerPriority', false);
|
|
46
|
+
/**
|
|
47
|
+
* If the focused element is a descendant of the referenceEl then it's possible
|
|
48
|
+
* that the app developer manually moved focus, so we do not want to override that.
|
|
49
|
+
* This can happen with inputs the are focused when a view transitions in.
|
|
50
|
+
*/
|
|
51
|
+
if (Array.isArray(focusManagerPriorities) && !referenceEl.contains(document.activeElement)) {
|
|
52
|
+
/**
|
|
53
|
+
* When going back to a previously visited view focus should always be moved back
|
|
54
|
+
* to the element that the user was last focused on when they were on this view.
|
|
55
|
+
*/
|
|
56
|
+
const lastFocus = referenceEl.querySelector(`[${LAST_FOCUS}]`);
|
|
57
|
+
if (lastFocus && isVisible(lastFocus)) {
|
|
58
|
+
moveFocus(lastFocus);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
for (const priority of focusManagerPriorities) {
|
|
62
|
+
/**
|
|
63
|
+
* For each recognized case (excluding the default case) make sure to return
|
|
64
|
+
* so that the fallback focus behavior does not run.
|
|
65
|
+
*
|
|
66
|
+
* We intentionally query for specific roles/semantic elements so that the
|
|
67
|
+
* transition manager can work with both Ionic and non-Ionic UI components.
|
|
68
|
+
*
|
|
69
|
+
* If new selectors are added, be sure to remove the outline ring by adding
|
|
70
|
+
* new selectors to rule in core.scss.
|
|
71
|
+
*/
|
|
72
|
+
switch (priority) {
|
|
73
|
+
case 'content':
|
|
74
|
+
const content = referenceEl.querySelector('main, [role="main"]');
|
|
75
|
+
if (content && isVisible(content)) {
|
|
76
|
+
moveFocus(content);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
break;
|
|
80
|
+
case 'heading':
|
|
81
|
+
const headingOne = referenceEl.querySelector('h1, [role="heading"][aria-level="1"]');
|
|
82
|
+
if (headingOne && isVisible(headingOne)) {
|
|
83
|
+
moveFocus(headingOne);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
break;
|
|
87
|
+
case 'banner':
|
|
88
|
+
const header = referenceEl.querySelector('header, [role="banner"]');
|
|
89
|
+
if (header && isVisible(header)) {
|
|
90
|
+
moveFocus(header);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
break;
|
|
94
|
+
default:
|
|
95
|
+
printIonWarning(`Unrecognized focus manager priority value ${priority}`);
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* If there is nothing to focus then focus the page so focus at least moves to
|
|
101
|
+
* the correct view. The browser will then determine where within the page to
|
|
102
|
+
* move focus to.
|
|
103
|
+
*/
|
|
104
|
+
moveFocus(referenceEl);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
return {
|
|
108
|
+
saveViewFocus,
|
|
109
|
+
setViewFocus,
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
const LAST_FOCUS = 'ion-last-focus';
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
|
+
*/
|
|
4
|
+
import { expect } from "@playwright/test";
|
|
5
|
+
import { configs, test } from "../../../test/playwright/index";
|
|
6
|
+
configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
|
7
|
+
test.describe(title('focus controller: generic components'), () => {
|
|
8
|
+
test.beforeEach(async ({ page }) => {
|
|
9
|
+
await page.goto('/src/utils/focus-controller/test/generic', config);
|
|
10
|
+
});
|
|
11
|
+
test('should focus heading', async ({ page }) => {
|
|
12
|
+
const goToPageOneButton = page.locator('page-root button.page-one');
|
|
13
|
+
const nav = page.locator('ion-nav');
|
|
14
|
+
const ionNavDidChange = await nav.spyOnEvent('ionNavDidChange');
|
|
15
|
+
// Focus heading on Page One
|
|
16
|
+
await goToPageOneButton.click();
|
|
17
|
+
await ionNavDidChange.next();
|
|
18
|
+
const pageOneTitle = page.locator('page-one h1');
|
|
19
|
+
await expect(pageOneTitle).toBeFocused();
|
|
20
|
+
});
|
|
21
|
+
test('should focus banner', async ({ page }) => {
|
|
22
|
+
const goToPageThreeButton = page.locator('page-root button.page-three');
|
|
23
|
+
const nav = page.locator('ion-nav');
|
|
24
|
+
const ionNavDidChange = await nav.spyOnEvent('ionNavDidChange');
|
|
25
|
+
const pageThreeHeader = page.locator('page-three header');
|
|
26
|
+
await goToPageThreeButton.click();
|
|
27
|
+
await ionNavDidChange.next();
|
|
28
|
+
await expect(pageThreeHeader).toBeFocused();
|
|
29
|
+
});
|
|
30
|
+
test('should focus content', async ({ page }) => {
|
|
31
|
+
const goToPageTwoButton = page.locator('page-root button.page-two');
|
|
32
|
+
const nav = page.locator('ion-nav');
|
|
33
|
+
const ionNavDidChange = await nav.spyOnEvent('ionNavDidChange');
|
|
34
|
+
const pageTwoContent = page.locator('page-two main');
|
|
35
|
+
await goToPageTwoButton.click();
|
|
36
|
+
await ionNavDidChange.next();
|
|
37
|
+
await expect(pageTwoContent).toBeFocused();
|
|
38
|
+
});
|
|
39
|
+
test('should return focus when going back', async ({ page, browserName }) => {
|
|
40
|
+
test.skip(browserName === 'webkit', 'Desktop Safari does not consider buttons to be focusable');
|
|
41
|
+
const goToPageOneButton = page.locator('page-root button.page-one');
|
|
42
|
+
const nav = page.locator('ion-nav');
|
|
43
|
+
const ionNavDidChange = await nav.spyOnEvent('ionNavDidChange');
|
|
44
|
+
const pageOneBackButton = page.locator('page-one ion-back-button');
|
|
45
|
+
await goToPageOneButton.click();
|
|
46
|
+
await ionNavDidChange.next();
|
|
47
|
+
await pageOneBackButton.click();
|
|
48
|
+
await ionNavDidChange.next();
|
|
49
|
+
await expect(goToPageOneButton).toBeFocused();
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
|
+
*/
|
|
4
|
+
import { expect } from "@playwright/test";
|
|
5
|
+
import { configs, test } from "../../../test/playwright/index";
|
|
6
|
+
configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
|
7
|
+
test.describe(title('focus controller: ionic components'), () => {
|
|
8
|
+
test.beforeEach(async ({ page }) => {
|
|
9
|
+
await page.goto('/src/utils/focus-controller/test/ionic', config);
|
|
10
|
+
});
|
|
11
|
+
test('should focus heading', async ({ page }) => {
|
|
12
|
+
const goToPageOneButton = page.locator('page-root ion-button.page-one');
|
|
13
|
+
const nav = page.locator('ion-nav');
|
|
14
|
+
const ionNavDidChange = await nav.spyOnEvent('ionNavDidChange');
|
|
15
|
+
// Focus heading on Page One
|
|
16
|
+
await goToPageOneButton.click();
|
|
17
|
+
await ionNavDidChange.next();
|
|
18
|
+
const pageOneTitle = page.locator('page-one ion-title');
|
|
19
|
+
await expect(pageOneTitle).toBeFocused();
|
|
20
|
+
});
|
|
21
|
+
test('should focus banner', async ({ page }) => {
|
|
22
|
+
const goToPageThreeButton = page.locator('page-root ion-button.page-three');
|
|
23
|
+
const nav = page.locator('ion-nav');
|
|
24
|
+
const ionNavDidChange = await nav.spyOnEvent('ionNavDidChange');
|
|
25
|
+
const pageThreeHeader = page.locator('page-three ion-header');
|
|
26
|
+
await goToPageThreeButton.click();
|
|
27
|
+
await ionNavDidChange.next();
|
|
28
|
+
await expect(pageThreeHeader).toBeFocused();
|
|
29
|
+
});
|
|
30
|
+
test('should focus content', async ({ page }) => {
|
|
31
|
+
const goToPageTwoButton = page.locator('page-root ion-button.page-two');
|
|
32
|
+
const nav = page.locator('ion-nav');
|
|
33
|
+
const ionNavDidChange = await nav.spyOnEvent('ionNavDidChange');
|
|
34
|
+
const pageTwoContent = page.locator('page-two ion-content');
|
|
35
|
+
await goToPageTwoButton.click();
|
|
36
|
+
await ionNavDidChange.next();
|
|
37
|
+
await expect(pageTwoContent).toBeFocused();
|
|
38
|
+
});
|
|
39
|
+
test('should return focus when going back', async ({ page, browserName }) => {
|
|
40
|
+
test.skip(browserName === 'webkit', 'Desktop Safari does not consider buttons to be focusable');
|
|
41
|
+
const goToPageOneButton = page.locator('page-root ion-button.page-one');
|
|
42
|
+
const nav = page.locator('ion-nav');
|
|
43
|
+
const ionNavDidChange = await nav.spyOnEvent('ionNavDidChange');
|
|
44
|
+
const pageOneBackButton = page.locator('page-one ion-back-button');
|
|
45
|
+
await goToPageOneButton.click();
|
|
46
|
+
await ionNavDidChange.next();
|
|
47
|
+
await pageOneBackButton.click();
|
|
48
|
+
await ionNavDidChange.next();
|
|
49
|
+
await expect(goToPageOneButton).toBeFocused();
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -152,7 +152,7 @@ const trapKeyboardFocus = (ev, doc) => {
|
|
|
152
152
|
* behind the sheet should be focusable until
|
|
153
153
|
* the backdrop is enabled.
|
|
154
154
|
*/
|
|
155
|
-
if (lastOverlay.classList.contains(
|
|
155
|
+
if (lastOverlay.classList.contains(FOCUS_TRAP_DISABLE_CLASS)) {
|
|
156
156
|
return;
|
|
157
157
|
}
|
|
158
158
|
const trapScopedFocus = () => {
|
|
@@ -827,3 +827,4 @@ const revealOverlaysToScreenReaders = () => {
|
|
|
827
827
|
}
|
|
828
828
|
}
|
|
829
829
|
};
|
|
830
|
+
export const FOCUS_TRAP_DISABLE_CLASS = 'ion-disable-focus-trap';
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
3
|
*/
|
|
4
|
+
import { config } from "../../global/config";
|
|
4
5
|
import { Build, writeTask } from "@stencil/core";
|
|
5
6
|
import { LIFECYCLE_DID_ENTER, LIFECYCLE_DID_LEAVE, LIFECYCLE_WILL_ENTER, LIFECYCLE_WILL_LEAVE, } from "../../components/nav/constants";
|
|
7
|
+
import { createFocusController } from "../focus-controller";
|
|
6
8
|
import { raf } from "../helpers";
|
|
7
9
|
const iosTransitionAnimation = () => import('./ios.transition');
|
|
8
10
|
const mdTransitionAnimation = () => import('./md.transition');
|
|
11
|
+
const focusController = createFocusController();
|
|
9
12
|
// TODO(FW-2832): types
|
|
10
13
|
export const transition = (opts) => {
|
|
11
14
|
return new Promise((resolve, reject) => {
|
|
@@ -27,6 +30,7 @@ export const transition = (opts) => {
|
|
|
27
30
|
const beforeTransition = (opts) => {
|
|
28
31
|
const enteringEl = opts.enteringEl;
|
|
29
32
|
const leavingEl = opts.leavingEl;
|
|
33
|
+
focusController.saveViewFocus(leavingEl);
|
|
30
34
|
setZIndex(enteringEl, leavingEl, opts.direction);
|
|
31
35
|
if (opts.showGoBack) {
|
|
32
36
|
enteringEl.classList.add('can-go-back');
|
|
@@ -61,6 +65,7 @@ const afterTransition = (opts) => {
|
|
|
61
65
|
leavingEl.classList.remove('ion-page-invisible');
|
|
62
66
|
leavingEl.style.removeProperty('pointer-events');
|
|
63
67
|
}
|
|
68
|
+
focusController.setViewFocus(enteringEl);
|
|
64
69
|
};
|
|
65
70
|
const getAnimationBuilder = async (opts) => {
|
|
66
71
|
if (!opts.leavingEl || !opts.animated || opts.duration === 0) {
|
|
@@ -93,7 +98,12 @@ const animation = async (animationBuilder, opts) => {
|
|
|
93
98
|
const noAnimation = async (opts) => {
|
|
94
99
|
const enteringEl = opts.enteringEl;
|
|
95
100
|
const leavingEl = opts.leavingEl;
|
|
96
|
-
|
|
101
|
+
const focusManagerEnabled = config.get('focusManagerPriority', false);
|
|
102
|
+
/**
|
|
103
|
+
* If the focus manager is enabled then we need to wait for Ionic components to be
|
|
104
|
+
* rendered otherwise the component to focus may not be focused because it is hidden.
|
|
105
|
+
*/
|
|
106
|
+
await waitForReady(opts, focusManagerEnabled);
|
|
97
107
|
fireWillEvents(enteringEl, leavingEl);
|
|
98
108
|
fireDidEvents(enteringEl, leavingEl);
|
|
99
109
|
return {
|
|
@@ -55,20 +55,22 @@ const createLargeTitleTransition = (rootAnimation, rtl, backDirection, enteringE
|
|
|
55
55
|
const leavingLargeTitleBox = leavingLargeTitle.getBoundingClientRect();
|
|
56
56
|
const enteringBackButtonBox = enteringBackButton.getBoundingClientRect();
|
|
57
57
|
const enteringBackButtonTextEl = shadow(enteringBackButton).querySelector('.button-text');
|
|
58
|
-
|
|
58
|
+
// Text element not rendered if developers pass text="" to the back button
|
|
59
|
+
const enteringBackButtonTextBox = enteringBackButtonTextEl === null || enteringBackButtonTextEl === void 0 ? void 0 : enteringBackButtonTextEl.getBoundingClientRect();
|
|
59
60
|
const leavingLargeTitleTextEl = shadow(leavingLargeTitle).querySelector('.toolbar-title');
|
|
60
61
|
const leavingLargeTitleTextBox = leavingLargeTitleTextEl.getBoundingClientRect();
|
|
61
|
-
animateLargeTitle(rootAnimation, rtl, backDirection, leavingLargeTitle, leavingLargeTitleBox, leavingLargeTitleTextBox, enteringBackButtonTextEl, enteringBackButtonTextBox);
|
|
62
|
+
animateLargeTitle(rootAnimation, rtl, backDirection, leavingLargeTitle, leavingLargeTitleBox, leavingLargeTitleTextBox, enteringBackButtonBox, enteringBackButtonTextEl, enteringBackButtonTextBox);
|
|
62
63
|
animateBackButton(rootAnimation, rtl, backDirection, enteringBackButton, enteringBackButtonBox, enteringBackButtonTextEl, enteringBackButtonTextBox, leavingLargeTitle, leavingLargeTitleTextBox);
|
|
63
64
|
}
|
|
64
65
|
else if (shouldAnimationBackward) {
|
|
65
66
|
const enteringLargeTitleBox = enteringLargeTitle.getBoundingClientRect();
|
|
66
67
|
const leavingBackButtonBox = leavingBackButton.getBoundingClientRect();
|
|
67
68
|
const leavingBackButtonTextEl = shadow(leavingBackButton).querySelector('.button-text');
|
|
68
|
-
|
|
69
|
+
// Text element not rendered if developers pass text="" to the back button
|
|
70
|
+
const leavingBackButtonTextBox = leavingBackButtonTextEl === null || leavingBackButtonTextEl === void 0 ? void 0 : leavingBackButtonTextEl.getBoundingClientRect();
|
|
69
71
|
const enteringLargeTitleTextEl = shadow(enteringLargeTitle).querySelector('.toolbar-title');
|
|
70
72
|
const enteringLargeTitleTextBox = enteringLargeTitleTextEl.getBoundingClientRect();
|
|
71
|
-
animateLargeTitle(rootAnimation, rtl, backDirection, enteringLargeTitle, enteringLargeTitleBox, enteringLargeTitleTextBox, leavingBackButtonTextEl, leavingBackButtonTextBox);
|
|
73
|
+
animateLargeTitle(rootAnimation, rtl, backDirection, enteringLargeTitle, enteringLargeTitleBox, enteringLargeTitleTextBox, leavingBackButtonBox, leavingBackButtonTextEl, leavingBackButtonTextBox);
|
|
72
74
|
animateBackButton(rootAnimation, rtl, backDirection, leavingBackButton, leavingBackButtonBox, leavingBackButtonTextEl, leavingBackButtonTextBox, enteringLargeTitle, enteringLargeTitleTextBox);
|
|
73
75
|
}
|
|
74
76
|
return {
|
|
@@ -82,26 +84,31 @@ const animateBackButton = (rootAnimation, rtl, backDirection, backButtonEl, back
|
|
|
82
84
|
const TEXT_ORIGIN_X = rtl ? 'right' : 'left';
|
|
83
85
|
const ICON_ORIGIN_X = rtl ? 'left' : 'right';
|
|
84
86
|
const CONTAINER_ORIGIN_X = rtl ? 'right' : 'left';
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
* If the texts do not match up then the back button text scale adjusts
|
|
89
|
-
* to not perfectly match the large title text otherwise the
|
|
90
|
-
* proportions will be incorrect.
|
|
91
|
-
* When the texts match we scale both the width and height to account for
|
|
92
|
-
* font weight differences between the title and back button.
|
|
93
|
-
*/
|
|
94
|
-
const doTitleAndButtonTextsMatch = ((_a = backButtonTextEl.textContent) === null || _a === void 0 ? void 0 : _a.trim()) === ((_b = largeTitleEl.textContent) === null || _b === void 0 ? void 0 : _b.trim());
|
|
95
|
-
const WIDTH_SCALE = largeTitleTextBox.width / backButtonTextBox.width;
|
|
96
|
-
/**
|
|
97
|
-
* We subtract an offset to account for slight sizing/padding
|
|
98
|
-
* differences between the title and the back button.
|
|
99
|
-
*/
|
|
100
|
-
const HEIGHT_SCALE = (largeTitleTextBox.height - LARGE_TITLE_SIZE_OFFSET) / backButtonTextBox.height;
|
|
101
|
-
const TEXT_START_SCALE = doTitleAndButtonTextsMatch
|
|
102
|
-
? `scale(${WIDTH_SCALE}, ${HEIGHT_SCALE})`
|
|
103
|
-
: `scale(${HEIGHT_SCALE})`;
|
|
87
|
+
let WIDTH_SCALE = 1;
|
|
88
|
+
let HEIGHT_SCALE = 1;
|
|
89
|
+
let TEXT_START_SCALE = `scale(${HEIGHT_SCALE})`;
|
|
104
90
|
const TEXT_END_SCALE = 'scale(1)';
|
|
91
|
+
if (backButtonTextEl && backButtonTextBox) {
|
|
92
|
+
/**
|
|
93
|
+
* When the title and back button texts match then they should overlap during the
|
|
94
|
+
* page transition. If the texts do not match up then the back button text scale
|
|
95
|
+
* adjusts to not perfectly match the large title text otherwise the proportions
|
|
96
|
+
* will be incorrect. When the texts match we scale both the width and height to
|
|
97
|
+
* account for font weight differences between the title and back button.
|
|
98
|
+
*/
|
|
99
|
+
const doTitleAndButtonTextsMatch = ((_a = backButtonTextEl.textContent) === null || _a === void 0 ? void 0 : _a.trim()) === ((_b = largeTitleEl.textContent) === null || _b === void 0 ? void 0 : _b.trim());
|
|
100
|
+
WIDTH_SCALE = largeTitleTextBox.width / backButtonTextBox.width;
|
|
101
|
+
/**
|
|
102
|
+
* Subtract an offset to account for slight sizing/padding differences between the
|
|
103
|
+
* title and the back button.
|
|
104
|
+
*/
|
|
105
|
+
HEIGHT_SCALE = (largeTitleTextBox.height - LARGE_TITLE_SIZE_OFFSET) / backButtonTextBox.height;
|
|
106
|
+
/**
|
|
107
|
+
* Even though we set TEXT_START_SCALE to HEIGHT_SCALE above, we potentially need
|
|
108
|
+
* to re-compute this here since the HEIGHT_SCALE may have changed.
|
|
109
|
+
*/
|
|
110
|
+
TEXT_START_SCALE = doTitleAndButtonTextsMatch ? `scale(${WIDTH_SCALE}, ${HEIGHT_SCALE})` : `scale(${HEIGHT_SCALE})`;
|
|
111
|
+
}
|
|
105
112
|
const backButtonIconEl = shadow(backButtonEl).querySelector('ion-icon');
|
|
106
113
|
const backButtonIconBox = backButtonIconEl.getBoundingClientRect();
|
|
107
114
|
/**
|
|
@@ -198,11 +205,11 @@ const animateBackButton = (rootAnimation, rtl, backDirection, backButtonEl, back
|
|
|
198
205
|
top: '0px',
|
|
199
206
|
[CONTAINER_ORIGIN_X]: '0px',
|
|
200
207
|
})
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
208
|
+
/**
|
|
209
|
+
* The write hooks must be set on this animation as it is guaranteed to run. Other
|
|
210
|
+
* animations such as the back button text animation will not run if the back button
|
|
211
|
+
* has no visible text.
|
|
212
|
+
*/
|
|
206
213
|
.beforeAddWrite(() => {
|
|
207
214
|
backButtonEl.style.setProperty('display', 'none');
|
|
208
215
|
clonedBackButtonEl.style.setProperty(TEXT_ORIGIN_X, BACK_BUTTON_START_OFFSET);
|
|
@@ -211,6 +218,11 @@ const animateBackButton = (rootAnimation, rtl, backDirection, backButtonEl, back
|
|
|
211
218
|
backButtonEl.style.setProperty('display', '');
|
|
212
219
|
clonedBackButtonEl.style.setProperty('display', 'none');
|
|
213
220
|
clonedBackButtonEl.style.removeProperty(TEXT_ORIGIN_X);
|
|
221
|
+
})
|
|
222
|
+
.keyframes(CONTAINER_KEYFRAMES);
|
|
223
|
+
enteringBackButtonTextAnimation
|
|
224
|
+
.beforeStyles({
|
|
225
|
+
'transform-origin': `${TEXT_ORIGIN_X} top`,
|
|
214
226
|
})
|
|
215
227
|
.keyframes(TEXT_KEYFRAMES);
|
|
216
228
|
enteringBackButtonIconAnimation
|
|
@@ -224,7 +236,7 @@ const animateBackButton = (rootAnimation, rtl, backDirection, backButtonEl, back
|
|
|
224
236
|
enteringBackButtonAnimation,
|
|
225
237
|
]);
|
|
226
238
|
};
|
|
227
|
-
const animateLargeTitle = (rootAnimation, rtl, backDirection, largeTitleEl, largeTitleBox, largeTitleTextBox, backButtonTextEl, backButtonTextBox) => {
|
|
239
|
+
const animateLargeTitle = (rootAnimation, rtl, backDirection, largeTitleEl, largeTitleBox, largeTitleTextBox, backButtonBox, backButtonTextEl, backButtonTextBox) => {
|
|
228
240
|
var _a, _b;
|
|
229
241
|
/**
|
|
230
242
|
* The horizontal transform origin for the large title
|
|
@@ -244,52 +256,67 @@ const animateLargeTitle = (rootAnimation, rtl, backDirection, largeTitleEl, larg
|
|
|
244
256
|
* title and the back button due to padding and font weight.
|
|
245
257
|
*/
|
|
246
258
|
const LARGE_TITLE_TRANSLATION_OFFSET = 8;
|
|
259
|
+
let END_TRANSLATE_X = rtl
|
|
260
|
+
? `-${window.innerWidth - backButtonBox.right - LARGE_TITLE_TRANSLATION_OFFSET}px`
|
|
261
|
+
: `${backButtonBox.x + LARGE_TITLE_TRANSLATION_OFFSET}px`;
|
|
247
262
|
/**
|
|
248
|
-
*
|
|
249
|
-
* This ensures that the back button and title overlap during
|
|
250
|
-
* the animation. Note that since both elements either fade in
|
|
251
|
-
* or fade out over the course of the animation, neither element
|
|
252
|
-
* will be fully visible on top of the other. As a result, the overlap
|
|
253
|
-
* does not need to be perfect, so approximate values are acceptable here.
|
|
263
|
+
* How much to scale the large title up/down by.
|
|
254
264
|
*/
|
|
255
|
-
|
|
256
|
-
? `-${window.innerWidth - backButtonTextBox.right - LARGE_TITLE_TRANSLATION_OFFSET}px`
|
|
257
|
-
: `${backButtonTextBox.x - LARGE_TITLE_TRANSLATION_OFFSET}px`;
|
|
265
|
+
let HEIGHT_SCALE = 0.5;
|
|
258
266
|
/**
|
|
259
|
-
* The
|
|
260
|
-
* should match with the top of the
|
|
261
|
-
* back button text element.
|
|
262
|
-
* We subtract 2px to account for the top padding
|
|
263
|
-
* on the large title element.
|
|
267
|
+
* The large title always starts full size.
|
|
264
268
|
*/
|
|
265
|
-
const
|
|
266
|
-
const END_TRANSLATE_Y = `${backButtonTextBox.y - LARGE_TITLE_TOP_PADDING}px`;
|
|
269
|
+
const START_SCALE = 'scale(1)';
|
|
267
270
|
/**
|
|
268
|
-
*
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
* large title should start at (roughly) the size of the back button
|
|
272
|
-
* and then scale up to its original size.
|
|
273
|
-
*
|
|
274
|
-
* Note that since both elements either fade in
|
|
275
|
-
* or fade out over the course of the animation, neither element
|
|
276
|
-
* will be fully visible on top of the other. As a result, the overlap
|
|
277
|
-
* does not need to be perfect, so approximate values are acceptable here.
|
|
271
|
+
* By default, we don't worry about having the large title scaled to perfectly
|
|
272
|
+
* match the back button because we don't know if the back button's text matches
|
|
273
|
+
* the large title's text.
|
|
278
274
|
*/
|
|
275
|
+
let END_SCALE = `scale(${HEIGHT_SCALE})`;
|
|
276
|
+
// Text element not rendered if developers pass text="" to the back button
|
|
277
|
+
if (backButtonTextEl && backButtonTextBox) {
|
|
278
|
+
/**
|
|
279
|
+
* The scaled title should (roughly) overlap the back button. This ensures that
|
|
280
|
+
* the back button and title overlap during the animation. Note that since both
|
|
281
|
+
* elements either fade in or fade out over the course of the animation, neither
|
|
282
|
+
* element will be fully visible on top of the other. As a result, the overlap
|
|
283
|
+
* does not need to be perfect, so approximate values are acceptable here.
|
|
284
|
+
*/
|
|
285
|
+
END_TRANSLATE_X = rtl
|
|
286
|
+
? `-${window.innerWidth - backButtonTextBox.right - LARGE_TITLE_TRANSLATION_OFFSET}px`
|
|
287
|
+
: `${backButtonTextBox.x - LARGE_TITLE_TRANSLATION_OFFSET}px`;
|
|
288
|
+
/**
|
|
289
|
+
* In the forward direction, the large title should start at its normal size and
|
|
290
|
+
* then scale down to be (roughly) the size of the back button on the other view.
|
|
291
|
+
* In the backward direction, the large title should start at (roughly) the size
|
|
292
|
+
* of the back button and then scale up to its original size.
|
|
293
|
+
* Note that since both elements either fade in or fade out over the course of the
|
|
294
|
+
* animation, neither element will be fully visible on top of the other. As a result,
|
|
295
|
+
* the overlap does not need to be perfect, so approximate values are acceptable here.
|
|
296
|
+
*/
|
|
297
|
+
/**
|
|
298
|
+
* When the title and back button texts match then they should overlap during the
|
|
299
|
+
* page transition. If the texts do not match up then the large title text scale
|
|
300
|
+
* adjusts to not perfectly match the back button text otherwise the proportions
|
|
301
|
+
* will be incorrect. When the texts match we scale both the width and height to
|
|
302
|
+
* account for font weight differences between the title and back button.
|
|
303
|
+
*/
|
|
304
|
+
const doTitleAndButtonTextsMatch = ((_a = backButtonTextEl.textContent) === null || _a === void 0 ? void 0 : _a.trim()) === ((_b = largeTitleEl.textContent) === null || _b === void 0 ? void 0 : _b.trim());
|
|
305
|
+
const WIDTH_SCALE = backButtonTextBox.width / largeTitleTextBox.width;
|
|
306
|
+
HEIGHT_SCALE = backButtonTextBox.height / (largeTitleTextBox.height - LARGE_TITLE_SIZE_OFFSET);
|
|
307
|
+
/**
|
|
308
|
+
* Even though we set TEXT_START_SCALE to HEIGHT_SCALE above, we potentially need
|
|
309
|
+
* to re-compute this here since the HEIGHT_SCALE may have changed.
|
|
310
|
+
*/
|
|
311
|
+
END_SCALE = doTitleAndButtonTextsMatch ? `scale(${WIDTH_SCALE}, ${HEIGHT_SCALE})` : `scale(${HEIGHT_SCALE})`;
|
|
312
|
+
}
|
|
279
313
|
/**
|
|
280
|
-
*
|
|
281
|
-
*
|
|
282
|
-
* If the texts do not match up then the large title text scale adjusts
|
|
283
|
-
* to not perfectly match the back button text otherwise the
|
|
284
|
-
* proportions will be incorrect.
|
|
285
|
-
* When the texts match we scale both the width and height to account for
|
|
286
|
-
* font weight differences between the title and back button.
|
|
314
|
+
* The midpoints of the back button and the title should align such that the back
|
|
315
|
+
* button and title appear to be centered with each other.
|
|
287
316
|
*/
|
|
288
|
-
const
|
|
289
|
-
const
|
|
290
|
-
const
|
|
291
|
-
const START_SCALE = 'scale(1)';
|
|
292
|
-
const END_SCALE = doTitleAndButtonTextsMatch ? `scale(${WIDTH_SCALE}, ${HEIGHT_SCALE})` : `scale(${HEIGHT_SCALE})`;
|
|
317
|
+
const backButtonMidPoint = backButtonBox.top + backButtonBox.height / 2;
|
|
318
|
+
const titleMidPoint = (largeTitleBox.height * HEIGHT_SCALE) / 2;
|
|
319
|
+
const END_TRANSLATE_Y = `${backButtonMidPoint - titleMidPoint}px`;
|
|
293
320
|
const BACKWARDS_KEYFRAMES = [
|
|
294
321
|
{ offset: 0, opacity: 0, transform: `translate3d(${END_TRANSLATE_X}, ${END_TRANSLATE_Y}, 0) ${END_SCALE}` },
|
|
295
322
|
{ offset: 0.1, opacity: 0 },
|