@lion/ui 0.19.1 → 0.20.0-menu-system.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/collapsible.js +1 -0
- package/components/button/src/LionButton.js +4 -0
- package/components/button/test-suites/LionButton.suite.js +1 -0
- package/components/calendar/src/LionCalendar.js +3 -1
- package/components/calendar/test/lion-calendar.test.js +47 -67
- package/components/collapsible/src/DisclosureMixin.js +313 -0
- package/components/collapsible/test-suites/DisclosureMixin.suite.js +30 -0
- package/components/collapsible/types/DisclosureMixinTypes.ts +48 -0
- package/components/combobox/test/lion-combobox.test.js +1 -0
- package/components/form-core/src/form-group/FormGroupMixin.js +7 -0
- package/components/form-core/src/registration/FormRegistrarMixin.js +11 -0
- package/components/form-core/test/FormControlMixin.test.js +1 -0
- package/components/form-core/test/validate/Validator.test.js +2 -0
- package/components/form-core/test-suites/ValidateMixin.suite.js +2 -0
- package/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.js +1 -0
- package/components/input-datepicker/src/localizeNamespaceLoader.js +1 -0
- package/components/input-datepicker/test/lion-input-datepicker.test.js +9 -19
- package/components/input-email/src/LionInputEmail.js +0 -2
- package/components/input-email/test/lion-input-email.test.js +0 -6
- package/components/input-file/src/validators.js +1 -31
- package/components/input-file/test/FileValidators.test.js +0 -31
- package/components/input-file/translations/bg.js +0 -1
- package/components/input-file/translations/cs.js +0 -1
- package/components/input-file/translations/de.js +0 -2
- package/components/input-file/translations/en.js +0 -1
- package/components/input-file/translations/es.js +0 -1
- package/components/input-file/translations/fr.js +0 -1
- package/components/input-file/translations/hu.js +0 -1
- package/components/input-file/translations/id.js +0 -1
- package/components/input-file/translations/it.js +0 -1
- package/components/input-file/translations/nl.js +0 -1
- package/components/input-file/translations/pl.js +0 -1
- package/components/input-file/translations/ro.js +0 -1
- package/components/input-file/translations/ru.js +0 -1
- package/components/input-file/translations/sk.js +0 -1
- package/components/input-file/translations/uk.js +0 -1
- package/components/input-file/translations/zh.js +0 -1
- package/components/input-tel/src/LionInputTel.js +1 -1
- package/components/input-tel/test-suites/LionInputTel.suite.js +0 -7
- package/components/localize/test/date/formatDate.test.js +1 -0
- package/components/menu/CHANGELOG.md +37 -0
- package/components/menu/README.md +335 -0
- package/components/menu/index.js +2 -0
- package/components/menu/lion-menu-overlay.js +3 -0
- package/components/menu/lion-menu.js +3 -0
- package/components/menu/lion-spinbutton.js +3 -0
- package/components/menu/lion-toolbar.js +3 -0
- package/components/menu/lion-tree.js +3 -0
- package/components/menu/package.json +46 -0
- package/components/menu/requirements.temp.md +12 -0
- package/components/menu/src/InteractiveListMixin.js +840 -0
- package/components/menu/src/LionMenu.js +250 -0
- package/components/menu/src/LionMenuHybrid.js +46 -0
- package/components/menu/src/LionMenuOverlay.js +155 -0
- package/components/menu/src/LionSpinbutton.js +213 -0
- package/components/menu/src/LionToolbar.js +94 -0
- package/components/menu/src/LionTree.js +52 -0
- package/components/menu/src/MoreButtonMenuMixin.js +278 -0
- package/components/menu/src/MultiLevelListMixin.js +311 -0
- package/components/menu/src/utils/isInView.js +26 -0
- package/components/menu/src/utils/listItemInteractions.js +124 -0
- package/components/menu/test/InteractiveListMixin.test.js +3 -0
- package/components/menu/test/MoreButtonMenuMixin.test.js +4 -0
- package/components/menu/test/MultiLevelListMixin.test.js +3 -0
- package/components/menu/test/lion-menu-hybrid.test.js +3 -0
- package/components/menu/test/lion-menu.test.js +11 -0
- package/components/menu/test/lion-toolbar.test.js +8 -0
- package/components/menu/test/lion-tree.test.js +7 -0
- package/components/menu/test-helpers/mimicKeyPress.js +9 -0
- package/components/menu/test-suites/InteractiveListMixin.suite.js +454 -0
- package/components/menu/test-suites/LionMenu.suite.js +113 -0
- package/components/menu/test-suites/LionMenuHybrid.suite.js +583 -0
- package/components/menu/test-suites/MoreButtonMenuMixin.suite.js +372 -0
- package/components/menu/test-suites/MultiLevelListMixin.suite.js +303 -0
- package/components/menu/types/InteractiveListMixinTypes.d.ts +84 -0
- package/components/navigation-bar/README.md +1 -0
- package/components/navigation-bar/src/LionNavigationBar.js +439 -0
- package/components/navigation-bar/src/types.js +41 -0
- package/components/overlays/NEXT.md +49 -0
- package/components/overlays/src/OverlayController.js +278 -110
- package/components/overlays/src/OverlayMixin.js +58 -11
- package/components/overlays/src/OverlaysManager.js +2 -2
- package/components/overlays/src/configurations/visibility-trigger-partials/withHoverInteraction.js +9 -41
- package/components/overlays/src/utils/adopt-styles.js +3 -2
- package/components/overlays/src/utils/get-focusable-elements.js +4 -0
- package/components/overlays/src/utils/is-equal-config.js +10 -6
- package/components/overlays/test/OverlayController.test.js +127 -14
- package/components/overlays/test/utils-tests/is-equal-config.test.js +1 -1
- package/components/overlays/test/withHoverInteraction.test.js +0 -28
- package/components/overlays/test-suites/OverlayMixin.suite.js +8 -8
- package/components/overlays/types/ArrowMixinTypes.ts +3 -1
- package/components/overlays/types/OverlayConfig.ts +20 -5
- package/components/overlays/types/OverlayMixinTypes.ts +2 -0
- package/components/select-rich/test/lion-select-rich.test.js +3 -0
- package/custom-elements.json +30458 -17734
- package/dist-types/components/button/src/LionButton.d.ts +1 -0
- package/dist-types/components/button/src/LionButton.d.ts.map +1 -1
- package/dist-types/components/button/test-suites/LionButton.suite.d.ts.map +1 -1
- package/dist-types/components/calendar/src/LionCalendar.d.ts.map +1 -1
- package/dist-types/components/calendar/test/lion-calendar.test.d.ts.map +1 -1
- package/dist-types/components/collapsible/src/DisclosureMixin.d.ts +3 -0
- package/dist-types/components/collapsible/src/DisclosureMixin.d.ts.map +1 -0
- package/dist-types/components/collapsible/test-suites/DisclosureMixin.suite.d.ts +2 -0
- package/dist-types/components/collapsible/test-suites/DisclosureMixin.suite.d.ts.map +1 -0
- package/dist-types/components/collapsible/types/DisclosureMixinTypes.d.ts +24 -0
- package/dist-types/components/collapsible/types/DisclosureMixinTypes.d.ts.map +1 -0
- package/dist-types/components/combobox/src/LionCombobox.d.ts +1 -1
- package/dist-types/components/dialog/src/LionDialog.d.ts +6 -2
- package/dist-types/components/dialog/src/LionDialog.d.ts.map +1 -1
- package/dist-types/components/form-core/src/form-group/FormGroupMixin.d.ts.map +1 -1
- package/dist-types/components/form-core/src/registration/FormRegistrarMixin.d.ts.map +1 -1
- package/dist-types/components/form-core/test-suites/ValidateMixin.suite.d.ts.map +1 -1
- package/dist-types/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.d.ts.map +1 -1
- package/dist-types/components/input-datepicker/src/LionInputDatepicker.d.ts +1 -1
- package/dist-types/components/input-datepicker/src/localizeNamespaceLoader.d.ts.map +1 -1
- package/dist-types/components/input-datepicker/test/lion-input-datepicker.test.d.ts.map +1 -1
- package/dist-types/components/input-email/src/LionInputEmail.d.ts.map +1 -1
- package/dist-types/components/input-file/src/validators.d.ts +0 -11
- package/dist-types/components/input-file/src/validators.d.ts.map +1 -1
- package/dist-types/components/input-file/translations/bg-BG.d.ts +0 -1
- package/dist-types/components/input-file/translations/bg.d.ts +0 -1
- package/dist-types/components/input-file/translations/cs-CZ.d.ts +0 -1
- package/dist-types/components/input-file/translations/cs.d.ts +0 -1
- package/dist-types/components/input-file/translations/de-DE.d.ts +0 -1
- package/dist-types/components/input-file/translations/de.d.ts +0 -1
- package/dist-types/components/input-file/translations/en-AU.d.ts +0 -1
- package/dist-types/components/input-file/translations/en-GB.d.ts +0 -1
- package/dist-types/components/input-file/translations/en-PH.d.ts +0 -1
- package/dist-types/components/input-file/translations/en-US.d.ts +0 -1
- package/dist-types/components/input-file/translations/en.d.ts +0 -1
- package/dist-types/components/input-file/translations/es-ES.d.ts +0 -1
- package/dist-types/components/input-file/translations/es.d.ts +0 -1
- package/dist-types/components/input-file/translations/fr-BE.d.ts +0 -1
- package/dist-types/components/input-file/translations/fr-FR.d.ts +0 -1
- package/dist-types/components/input-file/translations/fr.d.ts +0 -1
- package/dist-types/components/input-file/translations/hu-HU.d.ts +0 -1
- package/dist-types/components/input-file/translations/hu.d.ts +0 -1
- package/dist-types/components/input-file/translations/id-ID.d.ts +0 -1
- package/dist-types/components/input-file/translations/id.d.ts +0 -1
- package/dist-types/components/input-file/translations/it-IT.d.ts +0 -1
- package/dist-types/components/input-file/translations/it.d.ts +0 -1
- package/dist-types/components/input-file/translations/nl-BE.d.ts +0 -1
- package/dist-types/components/input-file/translations/nl-NL.d.ts +0 -1
- package/dist-types/components/input-file/translations/nl.d.ts +0 -1
- package/dist-types/components/input-file/translations/pl-PL.d.ts +0 -1
- package/dist-types/components/input-file/translations/pl.d.ts +0 -1
- package/dist-types/components/input-file/translations/ro-RO.d.ts +0 -1
- package/dist-types/components/input-file/translations/ro.d.ts +0 -1
- package/dist-types/components/input-file/translations/ru-RU.d.ts +0 -1
- package/dist-types/components/input-file/translations/ru.d.ts +0 -1
- package/dist-types/components/input-file/translations/sk-SK.d.ts +0 -1
- package/dist-types/components/input-file/translations/sk.d.ts +0 -1
- package/dist-types/components/input-file/translations/uk-UA.d.ts +0 -1
- package/dist-types/components/input-file/translations/uk.d.ts +0 -1
- package/dist-types/components/input-file/translations/zh-CN.d.ts +0 -1
- package/dist-types/components/input-file/translations/zh.d.ts +0 -1
- package/dist-types/components/input-tel/src/LionInputTel.d.ts.map +1 -1
- package/dist-types/components/input-tel/test-suites/LionInputTel.suite.d.ts.map +1 -1
- package/dist-types/components/menu/index.d.ts +3 -0
- package/dist-types/components/menu/index.d.ts.map +1 -0
- package/dist-types/components/menu/lion-menu-overlay.d.ts +2 -0
- package/dist-types/components/menu/lion-menu-overlay.d.ts.map +1 -0
- package/dist-types/components/menu/lion-menu.d.ts +2 -0
- package/dist-types/components/menu/lion-menu.d.ts.map +1 -0
- package/dist-types/components/menu/lion-spinbutton.d.ts +2 -0
- package/dist-types/components/menu/lion-spinbutton.d.ts.map +1 -0
- package/dist-types/components/menu/lion-toolbar.d.ts +2 -0
- package/dist-types/components/menu/lion-toolbar.d.ts.map +1 -0
- package/dist-types/components/menu/lion-tree.d.ts +2 -0
- package/dist-types/components/menu/lion-tree.d.ts.map +1 -0
- package/dist-types/components/menu/src/InteractiveListMixin.d.ts +617 -0
- package/dist-types/components/menu/src/InteractiveListMixin.d.ts.map +1 -0
- package/dist-types/components/menu/src/LionMenu.d.ts +635 -0
- package/dist-types/components/menu/src/LionMenu.d.ts.map +1 -0
- package/dist-types/components/menu/src/LionMenuHybrid.d.ts +19 -0
- package/dist-types/components/menu/src/LionMenuHybrid.d.ts.map +1 -0
- package/dist-types/components/menu/src/LionMenuOverlay.d.ts +1015 -0
- package/dist-types/components/menu/src/LionMenuOverlay.d.ts.map +1 -0
- package/dist-types/components/menu/src/LionSpinbutton.d.ts +58 -0
- package/dist-types/components/menu/src/LionSpinbutton.d.ts.map +1 -0
- package/dist-types/components/menu/src/LionToolbar.d.ts +8 -0
- package/dist-types/components/menu/src/LionToolbar.d.ts.map +1 -0
- package/dist-types/components/menu/src/LionTree.d.ts +447 -0
- package/dist-types/components/menu/src/LionTree.d.ts.map +1 -0
- package/dist-types/components/menu/src/MoreButtonMenuMixin.d.ts +39 -0
- package/dist-types/components/menu/src/MoreButtonMenuMixin.d.ts.map +1 -0
- package/dist-types/components/menu/src/MultiLevelListMixin.d.ts +503 -0
- package/dist-types/components/menu/src/MultiLevelListMixin.d.ts.map +1 -0
- package/dist-types/components/menu/src/utils/isInView.d.ts +9 -0
- package/dist-types/components/menu/src/utils/isInView.d.ts.map +1 -0
- package/dist-types/components/menu/src/utils/listItemInteractions.d.ts +48 -0
- package/dist-types/components/menu/src/utils/listItemInteractions.d.ts.map +1 -0
- package/dist-types/components/menu/test/InteractiveListMixin.test.d.ts +2 -0
- package/dist-types/components/menu/test/InteractiveListMixin.test.d.ts.map +1 -0
- package/dist-types/components/menu/test/MoreButtonMenuMixin.test.d.ts +2 -0
- package/dist-types/components/menu/test/MoreButtonMenuMixin.test.d.ts.map +1 -0
- package/dist-types/components/menu/test/MultiLevelListMixin.test.d.ts +2 -0
- package/dist-types/components/menu/test/MultiLevelListMixin.test.d.ts.map +1 -0
- package/dist-types/components/menu/test/lion-menu-hybrid.test.d.ts +2 -0
- package/dist-types/components/menu/test/lion-menu-hybrid.test.d.ts.map +1 -0
- package/dist-types/components/menu/test/lion-menu.test.d.ts +2 -0
- package/dist-types/components/menu/test/lion-menu.test.d.ts.map +1 -0
- package/dist-types/components/menu/test/lion-toolbar.test.d.ts +2 -0
- package/dist-types/components/menu/test/lion-toolbar.test.d.ts.map +1 -0
- package/dist-types/components/menu/test/lion-tree.test.d.ts +2 -0
- package/dist-types/components/menu/test/lion-tree.test.d.ts.map +1 -0
- package/dist-types/components/menu/test-helpers/mimicKeyPress.d.ts +7 -0
- package/dist-types/components/menu/test-helpers/mimicKeyPress.d.ts.map +1 -0
- package/dist-types/components/menu/test-suites/InteractiveListMixin.suite.d.ts +14 -0
- package/dist-types/components/menu/test-suites/InteractiveListMixin.suite.d.ts.map +1 -0
- package/dist-types/components/menu/test-suites/LionMenu.suite.d.ts +9 -0
- package/dist-types/components/menu/test-suites/LionMenu.suite.d.ts.map +1 -0
- package/dist-types/components/menu/test-suites/LionMenuHybrid.suite.d.ts +5 -0
- package/dist-types/components/menu/test-suites/LionMenuHybrid.suite.d.ts.map +1 -0
- package/dist-types/components/menu/test-suites/MoreButtonMenuMixin.suite.d.ts +14 -0
- package/dist-types/components/menu/test-suites/MoreButtonMenuMixin.suite.d.ts.map +1 -0
- package/dist-types/components/menu/test-suites/MultiLevelListMixin.suite.d.ts +11 -0
- package/dist-types/components/menu/test-suites/MultiLevelListMixin.suite.d.ts.map +1 -0
- package/dist-types/components/navigation-bar/src/LionNavigationBar.d.ts +238 -0
- package/dist-types/components/navigation-bar/src/LionNavigationBar.d.ts.map +1 -0
- package/dist-types/components/navigation-bar/src/types.d.ts +85 -0
- package/dist-types/components/navigation-bar/src/types.d.ts.map +1 -0
- package/dist-types/components/overlays/src/OverlayController.d.ts +24 -12
- package/dist-types/components/overlays/src/OverlayController.d.ts.map +1 -1
- package/dist-types/components/overlays/src/OverlayMixin.d.ts.map +1 -1
- package/dist-types/components/overlays/src/configurations/visibility-trigger-partials/withHoverInteraction.d.ts.map +1 -1
- package/dist-types/components/overlays/src/utils/get-focusable-elements.d.ts.map +1 -1
- package/dist-types/components/overlays/src/utils/is-equal-config.d.ts.map +1 -1
- package/dist-types/components/overlays/types/ArrowMixinTypes.d.ts.map +1 -1
- package/dist-types/components/overlays/types/OverlayConfig.d.ts +12 -2
- package/dist-types/components/overlays/types/OverlayConfig.d.ts.map +1 -1
- package/dist-types/components/overlays/types/OverlayMixinTypes.d.ts +1 -0
- package/dist-types/components/overlays/types/OverlayMixinTypes.d.ts.map +1 -1
- package/dist-types/components/select-rich/src/LionSelectRich.d.ts +11 -3
- package/dist-types/components/select-rich/src/LionSelectRich.d.ts.map +1 -1
- package/dist-types/components/tooltip/src/LionTooltip.d.ts +1 -1
- package/dist-types/exports/define/lion-item.d.ts +2 -0
- package/dist-types/exports/define/lion-item.d.ts.map +1 -0
- package/dist-types/exports/define/lion-menu-overlay.d.ts +2 -0
- package/dist-types/exports/define/lion-menu-overlay.d.ts.map +1 -0
- package/dist-types/exports/define/lion-menu.d.ts +2 -0
- package/dist-types/exports/define/lion-menu.d.ts.map +1 -0
- package/dist-types/exports/define/lion-navigation-bar.d.ts +2 -0
- package/dist-types/exports/define/lion-navigation-bar.d.ts.map +1 -0
- package/dist-types/exports/define/lion-toolbar.d.ts +2 -0
- package/dist-types/exports/define/lion-toolbar.d.ts.map +1 -0
- package/dist-types/exports/define/lion-tree.d.ts +2 -0
- package/dist-types/exports/define/lion-tree.d.ts.map +1 -0
- package/dist-types/exports/input-file.d.ts +1 -1
- package/dist-types/exports/menu-test-suites.d.ts +4 -0
- package/dist-types/exports/menu-test-suites.d.ts.map +1 -0
- package/dist-types/exports/menu.d.ts +7 -0
- package/dist-types/exports/menu.d.ts.map +1 -0
- package/dist-types/exports/navigation-bar.d.ts +2 -0
- package/dist-types/exports/navigation-bar.d.ts.map +1 -0
- package/dist-types/exports/overlays.d.ts +3 -0
- package/dist-types/exports/overlays.d.ts.map +1 -1
- package/dist-types/tsconfig.tsbuildinfo +1 -1
- package/docs/components/checkbox-group/overview.md +2 -2
- package/docs/components/collapsible/overview.md +1 -1
- package/docs/components/combobox/api-table.md +21 -8
- package/docs/components/combobox/overview.md +1 -1
- package/docs/components/combobox/use-cases.md +1 -1
- package/docs/components/dialog/api-table.md +31 -6
- package/docs/components/dialog/overview.md +1 -1
- package/docs/components/fieldset/overview.md +5 -5
- package/docs/components/form/overview.md +3 -3
- package/docs/components/form/use-cases.md +2 -2
- package/docs/components/icon/use-cases.md +1 -1
- package/docs/components/input/overview.md +1 -1
- package/docs/components/input-amount/overview.md +3 -3
- package/docs/components/input-date/overview.md +3 -3
- package/docs/components/input-datepicker/api-table.md +21 -4
- package/docs/components/input-datepicker/overview.md +5 -5
- package/docs/components/input-email/api-table.md +1 -1
- package/docs/components/input-email/overview.md +2 -2
- package/docs/components/input-file/overview.md +1 -1
- package/docs/components/input-file/use-cases.md +0 -18
- package/docs/components/input-iban/overview.md +2 -2
- package/docs/components/input-range/overview.md +2 -2
- package/docs/components/input-stepper/overview.md +1 -1
- package/docs/components/input-tel/api-table.md +1 -1
- package/docs/components/input-tel/overview.md +1 -1
- package/docs/components/input-tel/use-cases.md +6 -6
- package/docs/components/input-tel-dropdown/api-table.md +1 -1
- package/docs/components/input-tel-dropdown/overview.md +1 -1
- package/docs/components/listbox/use-cases.md +1 -1
- package/docs/components/menu/api-table.md +460 -0
- package/docs/components/menu/applyMenuDemoStyles.js +173 -0
- package/docs/components/menu/extensions.md +262 -0
- package/docs/components/menu/index.md +13 -0
- package/docs/components/menu/overview.md +422 -0
- package/docs/components/menu/use-cases.md +77 -0
- package/docs/components/radio-group/overview.md +3 -3
- package/docs/components/select/use-cases.md +1 -1
- package/docs/components/select-rich/api-table.md +21 -5
- package/docs/components/select-rich/use-cases.md +2 -2
- package/docs/components/tabs/examples.md +1 -1
- package/docs/components/tooltip/api-table.md +36 -11
- package/docs/components/tooltip/use-cases.md +1 -34
- package/docs/fundamentals/index.md +4 -4
- package/docs/fundamentals/node-tools/publish-docs/overview.md +3 -3
- package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +2 -2
- package/docs/fundamentals/rationales/accessibility.md +1 -1
- package/docs/fundamentals/systems/core/SlotMixin.md +1 -1
- package/docs/fundamentals/systems/core/overview.md +1 -1
- package/docs/fundamentals/systems/form/formatting-and-parsing.md +4 -4
- package/docs/fundamentals/systems/form/model-value.md +1 -1
- package/docs/fundamentals/systems/form/overview.md +28 -28
- package/docs/fundamentals/systems/form/validate.md +2 -2
- package/docs/fundamentals/systems/localize/overview.md +4 -4
- package/docs/fundamentals/systems/overlays/api-table.md +36 -34
- package/docs/fundamentals/systems/overlays/configuration.md +2 -2
- package/docs/fundamentals/systems/overlays/overview.md +5 -5
- package/docs/fundamentals/systems/overlays/use-cases.md +2 -2
- package/docs/fundamentals/tools/helpers/overview.md +1 -1
- package/docs/fundamentals/tools/singleton-manager/overview.md +4 -4
- package/docs/guides/how-to/create-a-custom-field.md +5 -5
- package/docs/guides/how-to/create-a-form.md +4 -4
- package/docs/guides/how-to/extend-a-native-input.md +2 -2
- package/docs/guides/how-to/index.md +1 -1
- package/docs/guides/index.md +8 -8
- package/docs/guides/principles/index.md +5 -5
- package/docs/guides/principles/styling.md +1 -1
- package/exports/collapsible.js +1 -0
- package/exports/define/lion-item.js +3 -0
- package/exports/define/lion-menu-overlay.js +3 -0
- package/exports/define/lion-menu.js +3 -0
- package/exports/define/lion-navigation-bar.js +3 -0
- package/exports/define/lion-toolbar.js +3 -0
- package/exports/define/lion-tree.js +3 -0
- package/exports/input-file.js +1 -5
- package/exports/menu-test-suites.js +4 -0
- package/exports/menu.js +7 -0
- package/exports/navigation-bar.js +1 -0
- package/exports/overlays.js +6 -0
- package/input-file.js +1 -5
- package/menu-test-suites.js +4 -0
- package/menu.js +7 -0
- package/navigation-bar.js +1 -0
- package/overlays.js +6 -0
- package/package.json +2 -2
- package/components/calendar/test-suites/LionCalendar.suite.js +0 -79
- package/components/input-datepicker/test-suites/LionInputDatepicker.suite.js +0 -35
- package/dist-types/components/calendar/test-suites/LionCalendar.suite.d.ts +0 -5
- package/dist-types/components/calendar/test-suites/LionCalendar.suite.d.ts.map +0 -1
- package/dist-types/components/input-datepicker/test-suites/LionInputDatepicker.suite.d.ts +0 -7
- package/dist-types/components/input-datepicker/test-suites/LionInputDatepicker.suite.d.ts.map +0 -1
|
@@ -3,6 +3,7 @@ import { deepContains } from './utils/deep-contains.js';
|
|
|
3
3
|
import { overlayShadowDomStyle } from './overlayShadowDomStyle.js';
|
|
4
4
|
import { _adoptStyleUtils } from './utils/adopt-styles.js';
|
|
5
5
|
import { getFocusableElements } from './utils/get-focusable-elements.js';
|
|
6
|
+
import { isEqualConfig } from './utils/is-equal-config.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* @typedef {import('@lion/ui/types/overlays.js').OverlayPhase} OverlayPhase
|
|
@@ -32,27 +33,37 @@ import { getFocusableElements } from './utils/get-focusable-elements.js';
|
|
|
32
33
|
* `<slot name="my-content">` belonging to `<div slot="content"/>` will be wrapped with wrappingDialogNodeL1 and contentWrapperNodeL2
|
|
33
34
|
* inside shadow dom. With the help of temp markers, `<slot name="my-content">`'s original position will be respected.
|
|
34
35
|
*
|
|
35
|
-
* @param {{
|
|
36
|
+
* @param {{
|
|
37
|
+
* wrappingDialogNodeL1: HTMLDialogElement|HTMLDivElement;
|
|
38
|
+
* contentWrapperNodeL2:Element;
|
|
39
|
+
* contentNodeL3: Element;
|
|
40
|
+
* }} opts
|
|
36
41
|
*/
|
|
37
42
|
function rearrangeNodes({ wrappingDialogNodeL1, contentWrapperNodeL2, contentNodeL3 }) {
|
|
38
|
-
if
|
|
43
|
+
// if contentWrapperNode is provided by the user,
|
|
44
|
+
// we assume it lives in shadow dom around a slot.
|
|
45
|
+
const hasLegacyMethodOfProvidingWrapperNode = Boolean(contentWrapperNodeL2.isConnected);
|
|
46
|
+
// We could be initialized via a directive (in offline dom). It's important that we know about the parents,
|
|
47
|
+
// as we cannot deal with single content nodes
|
|
48
|
+
const hasContentNodeAttachmentPoints = Boolean(contentNodeL3.parentNode);
|
|
49
|
+
|
|
50
|
+
if (!hasLegacyMethodOfProvidingWrapperNode && !hasContentNodeAttachmentPoints) {
|
|
39
51
|
throw new Error(
|
|
40
|
-
'[OverlayController] Could not find a render target,
|
|
52
|
+
'[OverlayController] Could not find a render target, makes sure contentNode has a parent element (or contentWrapperNode is connected)',
|
|
41
53
|
);
|
|
42
54
|
}
|
|
43
55
|
|
|
56
|
+
/** @type {Node} */
|
|
44
57
|
let parentElement;
|
|
45
|
-
const tempMarker = document.createComment('
|
|
58
|
+
const tempMarker = document.createComment('overlay-insertion-marker');
|
|
46
59
|
|
|
47
|
-
if (
|
|
60
|
+
if (hasLegacyMethodOfProvidingWrapperNode) {
|
|
48
61
|
// This is the case when contentWrapperNode (living in shadow dom, wrapping <slot name="my-content-outlet">) is already provided via controller.
|
|
49
62
|
parentElement = contentWrapperNodeL2.parentElement || contentWrapperNodeL2.getRootNode();
|
|
50
63
|
parentElement.insertBefore(tempMarker, contentWrapperNodeL2);
|
|
51
64
|
// Wrap...
|
|
52
65
|
wrappingDialogNodeL1.appendChild(contentWrapperNodeL2);
|
|
53
|
-
}
|
|
54
|
-
// if contentNodeL3.isConnected
|
|
55
|
-
else {
|
|
66
|
+
} else {
|
|
56
67
|
const contentIsProjected = contentNodeL3.assignedSlot;
|
|
57
68
|
if (contentIsProjected) {
|
|
58
69
|
parentElement =
|
|
@@ -93,7 +104,22 @@ function rearrangeNodes({ wrappingDialogNodeL1, contentWrapperNodeL2, contentNod
|
|
|
93
104
|
* ```
|
|
94
105
|
*/
|
|
95
106
|
parentElement.insertBefore(wrappingDialogNodeL1, tempMarker);
|
|
96
|
-
|
|
107
|
+
|
|
108
|
+
return function cleanup() {
|
|
109
|
+
if (hasLegacyMethodOfProvidingWrapperNode) {
|
|
110
|
+
parentElement?.insertBefore(contentWrapperNodeL2, tempMarker);
|
|
111
|
+
} else {
|
|
112
|
+
parentElement?.insertBefore(contentNodeL3, tempMarker);
|
|
113
|
+
if (parentElement.contains(contentWrapperNodeL2)) {
|
|
114
|
+
contentWrapperNodeL2.remove();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
parentElement?.removeChild(tempMarker);
|
|
118
|
+
|
|
119
|
+
if (parentElement.contains(wrappingDialogNodeL1)) {
|
|
120
|
+
parentElement?.removeChild(wrappingDialogNodeL1);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
97
123
|
}
|
|
98
124
|
|
|
99
125
|
/**
|
|
@@ -106,6 +132,21 @@ async function preloadPopper() {
|
|
|
106
132
|
|
|
107
133
|
const childDialogsClosedInEventLoopWeakmap = new WeakMap();
|
|
108
134
|
|
|
135
|
+
/**
|
|
136
|
+
* @param {HTMLElement | null} el
|
|
137
|
+
* @param {string} selector
|
|
138
|
+
* @returns {HTMLElement | null}
|
|
139
|
+
*/
|
|
140
|
+
function deepClosest(el, selector) {
|
|
141
|
+
// @ts-ignore - comparing HTMLElement to document/window for safety
|
|
142
|
+
return (
|
|
143
|
+
// @ts-ignore - type comparison check
|
|
144
|
+
(el && el !== document && el !== window && el.closest(selector)) ||
|
|
145
|
+
// @ts-ignore - host property on ShadowRoot
|
|
146
|
+
deepClosest(el.getRootNode().host, selector)
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
109
150
|
/**
|
|
110
151
|
* OverlayController is the fundament for every single type of overlay. With the right
|
|
111
152
|
* configuration, it can be used to build (modal) dialogs, tooltips, dropdowns, popovers,
|
|
@@ -196,10 +237,25 @@ export class OverlayController extends EventTarget {
|
|
|
196
237
|
placement: 'center',
|
|
197
238
|
},
|
|
198
239
|
zIndex: 9999,
|
|
240
|
+
isActivated: true,
|
|
241
|
+
focusContentOnOpen: false,
|
|
242
|
+
// This means that content will have visually-hidden / sr-only styles. This is handy for:
|
|
243
|
+
// - hidden menus that should be "indexable" by screen readers (like the Links list in VO: https://support.apple.com/en-gb/guide/voiceover/mchlp2719/mac)
|
|
244
|
+
// - "more" menus that put content in a dropdown that do not fit in the current row
|
|
245
|
+
// - menus that should generally open on tab.
|
|
246
|
+
// @ts-ignore - hideVisually is an extension property
|
|
247
|
+
hideVisually: false,
|
|
248
|
+
requireConnectedNodes: true,
|
|
249
|
+
|
|
250
|
+
// hides children overlays when parent is closed...
|
|
251
|
+
syncChildrenCloseState: false,
|
|
252
|
+
// // In next major, we remove this prop. Now we disable it for backwards compatibility and enable it in the places we need it internally
|
|
253
|
+
// _shouldTeardownDomStructure: false,
|
|
199
254
|
};
|
|
200
255
|
|
|
201
256
|
/** @protected */
|
|
202
257
|
this._contentId = `overlay-content--${Math.random().toString(36).slice(2, 10)}`;
|
|
258
|
+
|
|
203
259
|
/** @private */
|
|
204
260
|
this.__originalAttrs = new Map();
|
|
205
261
|
/** @private */
|
|
@@ -220,6 +276,8 @@ export class OverlayController extends EventTarget {
|
|
|
220
276
|
this.__escKeyHandlerCalled = false;
|
|
221
277
|
}
|
|
222
278
|
|
|
279
|
+
__hasSetup = false;
|
|
280
|
+
|
|
223
281
|
/**
|
|
224
282
|
* The invokerNode
|
|
225
283
|
* @type {HTMLElement | undefined}
|
|
@@ -238,7 +296,7 @@ export class OverlayController extends EventTarget {
|
|
|
238
296
|
|
|
239
297
|
/**
|
|
240
298
|
* Determines the connection point in DOM (body vs next to invoker).
|
|
241
|
-
* @type {'global' | 'local' | undefined}
|
|
299
|
+
* @type {'global' | 'local' | 'custom' | undefined}
|
|
242
300
|
*/
|
|
243
301
|
get placementMode() {
|
|
244
302
|
return this.config?.placementMode;
|
|
@@ -463,17 +521,14 @@ export class OverlayController extends EventTarget {
|
|
|
463
521
|
* @param { OverlayConfig } cfgToAdd
|
|
464
522
|
*/
|
|
465
523
|
updateConfig(cfgToAdd) {
|
|
466
|
-
// Teardown all previous configs
|
|
467
|
-
this.teardown();
|
|
468
|
-
|
|
469
524
|
/**
|
|
470
525
|
* @type {OverlayConfig}
|
|
471
526
|
* @private
|
|
472
527
|
*/
|
|
473
|
-
|
|
528
|
+
const prevConfig = this.config;
|
|
474
529
|
|
|
475
530
|
/** @type {OverlayConfig} */
|
|
476
|
-
|
|
531
|
+
const newConfig = {
|
|
477
532
|
...this._defaultConfig, // our basic ingredients
|
|
478
533
|
...this.__sharedConfig, // the initial configured overlayController
|
|
479
534
|
...cfgToAdd, // the added config
|
|
@@ -489,12 +544,18 @@ export class OverlayController extends EventTarget {
|
|
|
489
544
|
},
|
|
490
545
|
};
|
|
491
546
|
|
|
547
|
+
const shouldUpdate = !this.__hasSetup || !isEqualConfig(prevConfig, newConfig);
|
|
548
|
+
if (!shouldUpdate) return;
|
|
549
|
+
// Teardown all previous configs
|
|
550
|
+
|
|
551
|
+
this.teardown();
|
|
552
|
+
|
|
553
|
+
this.config = newConfig;
|
|
554
|
+
|
|
492
555
|
/** @private */
|
|
493
556
|
this.__validateConfiguration(this.config);
|
|
494
557
|
/** @protected */
|
|
495
558
|
this._init();
|
|
496
|
-
/** @private */
|
|
497
|
-
this.__elementToFocusAfterHide = undefined;
|
|
498
559
|
|
|
499
560
|
if (!this.#isRegisteredOnManager()) {
|
|
500
561
|
this.manager.add(this);
|
|
@@ -516,7 +577,7 @@ export class OverlayController extends EventTarget {
|
|
|
516
577
|
'[OverlayController] You need to provide a .placementMode ("global"|"local")',
|
|
517
578
|
);
|
|
518
579
|
}
|
|
519
|
-
if (!['global', 'local'].includes(newConfig.placementMode)) {
|
|
580
|
+
if (!['global', 'local', 'custom'].includes(newConfig.placementMode)) {
|
|
520
581
|
throw new Error(
|
|
521
582
|
`[OverlayController] "${newConfig.placementMode}" is not a valid .placementMode, use ("global"|"local")`,
|
|
522
583
|
);
|
|
@@ -535,14 +596,23 @@ export class OverlayController extends EventTarget {
|
|
|
535
596
|
* @protected
|
|
536
597
|
*/
|
|
537
598
|
_init() {
|
|
538
|
-
if (!this.
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
599
|
+
if (!this.config.isActivated) return;
|
|
600
|
+
|
|
601
|
+
// TODO: should not be behind a flag when we are fully tearing down...
|
|
602
|
+
// TODO 2: When we move away from dialog (use popover to paint to top layer)
|
|
603
|
+
// and popper.js, (use popover and anchor positioning and popperjs as fallback, but we can put styles on contentNode),
|
|
604
|
+
// we dont need to create complex wrappers
|
|
605
|
+
// if (!this.__contentHasBeenInitialized) {
|
|
606
|
+
this.__initContentDomStructure();
|
|
607
|
+
// this.__contentHasBeenInitialized = true;
|
|
608
|
+
// }
|
|
609
|
+
this.__initVisibility();
|
|
542
610
|
|
|
543
611
|
// Reset all positioning styles (local, c.q. Popper) and classes (global)
|
|
544
|
-
this.contentWrapperNode.
|
|
545
|
-
|
|
612
|
+
if (this.contentWrapperNode !== this.contentNode) {
|
|
613
|
+
this.contentWrapperNode.removeAttribute('style');
|
|
614
|
+
this.contentWrapperNode.removeAttribute('class');
|
|
615
|
+
}
|
|
546
616
|
|
|
547
617
|
if (this.placementMode === 'local') {
|
|
548
618
|
// Lazily load Popper as soon as the first local overlay is used...
|
|
@@ -552,8 +622,27 @@ export class OverlayController extends EventTarget {
|
|
|
552
622
|
}
|
|
553
623
|
this.__handleOverlayStyles({ phase: 'init' });
|
|
554
624
|
this._handleFeatures({ phase: 'init' });
|
|
625
|
+
|
|
626
|
+
/** @private */
|
|
627
|
+
this.__elementToFocusAfterHide = undefined;
|
|
628
|
+
|
|
629
|
+
this.contentNode.dataset.content = '';
|
|
630
|
+
|
|
631
|
+
// Use event delegation to listen for clicks on close buttons...
|
|
632
|
+
this.contentNode.addEventListener('click', this.#hideOnCloseButtonClick);
|
|
633
|
+
|
|
634
|
+
this.__hasSetup = true;
|
|
555
635
|
}
|
|
556
636
|
|
|
637
|
+
#hideOnCloseButtonClick = (/** @type {{ target: any; }} */ ev) => {
|
|
638
|
+
const isOurCloseButton =
|
|
639
|
+
ev.target.hasAttribute('data-close') &&
|
|
640
|
+
deepClosest(ev.target, '[data-content]') === this.contentNode;
|
|
641
|
+
if (!isOurCloseButton) return;
|
|
642
|
+
|
|
643
|
+
this.hide();
|
|
644
|
+
};
|
|
645
|
+
|
|
557
646
|
/**
|
|
558
647
|
* @param {{ phase: OverlayPhase }} config
|
|
559
648
|
* @private
|
|
@@ -594,84 +683,108 @@ export class OverlayController extends EventTarget {
|
|
|
594
683
|
* @private
|
|
595
684
|
*/
|
|
596
685
|
__initContentDomStructure() {
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
686
|
+
if (this.placementMode !== 'custom') {
|
|
687
|
+
const wrappingDialogElement = document.createElement('dialog');
|
|
688
|
+
// We use a dialog for its visual capabilities: it renders to the top layer.
|
|
689
|
+
// A11y will depend on the type of overlay and is arranged on contentNode level.
|
|
690
|
+
// Also see: https://www.scottohara.me/blog/2019/03/05/open-dialog.html
|
|
691
|
+
//
|
|
692
|
+
// The role="dialog" is set on the contentNode (or another role), so role="none"
|
|
693
|
+
// is valid here, although AXE complains about this setup.
|
|
694
|
+
// For now we need to add `ignoredRules: ['aria-allowed-role']` in your AXE tests.
|
|
695
|
+
// see: https://lion.js.org/fundamentals/systems/overlays/rationale/#considerations
|
|
696
|
+
wrappingDialogElement.setAttribute('role', 'none');
|
|
697
|
+
wrappingDialogElement.setAttribute('data-overlay-outer-wrapper', '');
|
|
698
|
+
// N.B. position: fixed is needed to escape out of 'overflow: hidden'
|
|
699
|
+
// We give a high z-index for non-modal dialogs, so that we at least win from all siblings of our
|
|
700
|
+
// parent stacking context
|
|
701
|
+
// padding reset so we don't get a weird dialog visual square showing up
|
|
702
|
+
wrappingDialogElement.style.cssText = `display:none; z-index: ${this.config.zIndex}; padding: 0;`;
|
|
703
|
+
// @ts-ignore - 'custom' is a valid extension of placementMode
|
|
704
|
+
if (this.config.placementMode === 'custom') {
|
|
705
|
+
// The user should have full freedom to control the content node, so its wrapper nodes should remain neutral.
|
|
706
|
+
wrappingDialogElement.style.cssText += `position: static;`;
|
|
707
|
+
}
|
|
708
|
+
this.__wrappingDialogNode = wrappingDialogElement;
|
|
614
709
|
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
710
|
+
/**
|
|
711
|
+
* Based on the configuration of the developer, multiple scenarios are accounted for
|
|
712
|
+
* A. We already have a contentWrapperNode ()
|
|
713
|
+
*/
|
|
714
|
+
if (!this.config?.contentWrapperNode) {
|
|
715
|
+
this.__contentWrapperNode = document.createElement('div');
|
|
716
|
+
}
|
|
717
|
+
this.contentWrapperNode.setAttribute('data-id', 'content-wrapper');
|
|
718
|
+
// 'hack' that makes sure popperjs (that is applied one level lower) works correctly in deeply nested shadow roots
|
|
719
|
+
this.contentWrapperNode.style.transform = 'translateZ(0px)';
|
|
720
|
+
|
|
721
|
+
this.__rearrangeNodesCleanup = rearrangeNodes({
|
|
722
|
+
wrappingDialogNodeL1: wrappingDialogElement,
|
|
723
|
+
contentWrapperNodeL2: this.contentWrapperNode,
|
|
724
|
+
contentNodeL3: this.contentNode,
|
|
725
|
+
// requireConnectedNodes: Boolean(this.config.requireConnectedNodes),
|
|
726
|
+
});
|
|
727
|
+
wrappingDialogElement.open = true;
|
|
625
728
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
729
|
+
if (this.isTooltip) {
|
|
730
|
+
// needed to prevent tooltip getting focus in Safari and Firefox
|
|
731
|
+
wrappingDialogElement.setAttribute('tabindex', '-1');
|
|
732
|
+
}
|
|
733
|
+
this.contentWrapperNode.style.zIndex = '1';
|
|
734
|
+
if (getComputedStyle(this.contentNode).position === 'absolute') {
|
|
735
|
+
// Having a _contWrapperNode and a contentNode with 'position:absolute' results in
|
|
736
|
+
// computed height of 0...
|
|
737
|
+
this.contentNode.style.position = 'static';
|
|
738
|
+
}
|
|
632
739
|
|
|
633
|
-
|
|
634
|
-
//
|
|
635
|
-
|
|
740
|
+
// Here we prevent any interference of the native <dialog> element with the keyboard behavior
|
|
741
|
+
// as defined by the OverlayController. This is needed until we can configure `closedby="none"`
|
|
742
|
+
// on the native dialog for all browsers: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog#closedby
|
|
743
|
+
const hasClosedBySupport = HTMLDialogElement && 'closedBy' in HTMLDialogElement.prototype;
|
|
744
|
+
if (hasClosedBySupport) {
|
|
745
|
+
// @ts-ignore - closedBy is a newer property not in all TypeScript versions
|
|
746
|
+
wrappingDialogElement.closedBy = 'none';
|
|
747
|
+
} else {
|
|
748
|
+
wrappingDialogElement.addEventListener(
|
|
749
|
+
'keydown',
|
|
750
|
+
(/** @type {* & KeyboardEvent} */ event) => {
|
|
751
|
+
if (event.key === 'Escape') {
|
|
752
|
+
event.preventDefault();
|
|
753
|
+
}
|
|
754
|
+
},
|
|
755
|
+
);
|
|
756
|
+
wrappingDialogElement.addEventListener(
|
|
757
|
+
'keyup',
|
|
758
|
+
(/** @type {* & KeyboardEvent} */ event) => {
|
|
759
|
+
if (event.key === 'Escape') {
|
|
760
|
+
event.preventDefault();
|
|
761
|
+
}
|
|
762
|
+
},
|
|
763
|
+
);
|
|
764
|
+
wrappingDialogElement.addEventListener('cancel', event => {
|
|
765
|
+
event.stopPropagation();
|
|
766
|
+
});
|
|
767
|
+
wrappingDialogElement.addEventListener('close', event => {
|
|
768
|
+
event.stopPropagation();
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
} else {
|
|
772
|
+
// quick hack to make none-popper/global flows work...
|
|
773
|
+
this.__contentWrapperNode = this.contentNode;
|
|
774
|
+
this.__wrappingDialogNode = this.contentNode;
|
|
636
775
|
}
|
|
776
|
+
}
|
|
637
777
|
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
// Having a _contWrapperNode and a contentNode with 'position:absolute' results in
|
|
643
|
-
// computed height of 0...
|
|
644
|
-
this.contentNode.style.position = 'static';
|
|
645
|
-
}
|
|
778
|
+
__initVisibility() {
|
|
779
|
+
// TODO: allow defaultOpen?
|
|
780
|
+
/** @type {HTMLDialogElement} */ (this.__wrappingDialogNode).style.display = 'none';
|
|
781
|
+
}
|
|
646
782
|
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
// @ts-expect-error
|
|
653
|
-
wrappingDialogElement.closedBy = 'none';
|
|
654
|
-
} else {
|
|
655
|
-
wrappingDialogElement.addEventListener(
|
|
656
|
-
'keydown',
|
|
657
|
-
(/** @type {* & KeyboardEvent} */ event) => {
|
|
658
|
-
if (event.key === 'Escape') {
|
|
659
|
-
event.preventDefault();
|
|
660
|
-
}
|
|
661
|
-
},
|
|
662
|
-
);
|
|
663
|
-
wrappingDialogElement.addEventListener('keyup', (/** @type {* & KeyboardEvent} */ event) => {
|
|
664
|
-
if (event.key === 'Escape') {
|
|
665
|
-
event.preventDefault();
|
|
666
|
-
}
|
|
667
|
-
});
|
|
668
|
-
wrappingDialogElement.addEventListener('cancel', event => {
|
|
669
|
-
event.stopPropagation();
|
|
670
|
-
});
|
|
671
|
-
wrappingDialogElement.addEventListener('close', event => {
|
|
672
|
-
event.stopPropagation();
|
|
673
|
-
});
|
|
674
|
-
}
|
|
783
|
+
// Clean up the DOM structure, leaving it as we found it.
|
|
784
|
+
// TODO: __teardownContentDomStructure method... use Resettable (rename ro Restorable) found in VisibilitToggleCtrl
|
|
785
|
+
__teardownVisibility() {
|
|
786
|
+
// TODO: full structure. For now we just reset display prop...
|
|
787
|
+
/** @type {HTMLDialogElement} */ (this.__wrappingDialogNode).style.display = '';
|
|
675
788
|
}
|
|
676
789
|
|
|
677
790
|
/**
|
|
@@ -742,6 +855,7 @@ export class OverlayController extends EventTarget {
|
|
|
742
855
|
* @private
|
|
743
856
|
*/
|
|
744
857
|
__storeOriginalAttrs(node, attrs) {
|
|
858
|
+
/** @type {Record<string, string | null>} */
|
|
745
859
|
const attrMap = {};
|
|
746
860
|
attrs.forEach(attrName => {
|
|
747
861
|
attrMap[attrName] = node.getAttribute(attrName);
|
|
@@ -798,6 +912,7 @@ export class OverlayController extends EventTarget {
|
|
|
798
912
|
if ('HTMLDialogElement' in window && this.__wrappingDialogNode instanceof HTMLDialogElement) {
|
|
799
913
|
this.__wrappingDialogNode.open = true;
|
|
800
914
|
}
|
|
915
|
+
|
|
801
916
|
// @ts-ignore
|
|
802
917
|
this.__wrappingDialogNode.style.display = '';
|
|
803
918
|
this._keepBodySize({ phase: 'before-show' });
|
|
@@ -811,6 +926,14 @@ export class OverlayController extends EventTarget {
|
|
|
811
926
|
contentNode: this.contentNode,
|
|
812
927
|
});
|
|
813
928
|
}
|
|
929
|
+
|
|
930
|
+
// a styling/debug hook for open state
|
|
931
|
+
this.contentNode.setAttribute('data-open', '');
|
|
932
|
+
|
|
933
|
+
if (this.config.focusContentOnOpen) {
|
|
934
|
+
this.contentNode.focus({ preventScroll: true });
|
|
935
|
+
}
|
|
936
|
+
|
|
814
937
|
/** @type {function} */
|
|
815
938
|
(this._showResolve)();
|
|
816
939
|
}
|
|
@@ -843,6 +966,7 @@ export class OverlayController extends EventTarget {
|
|
|
843
966
|
await this.__createPopperInstance();
|
|
844
967
|
this._popper.forceUpdate();
|
|
845
968
|
}
|
|
969
|
+
// N.B. leave it up to the user if placementMode === 'custom'
|
|
846
970
|
}
|
|
847
971
|
|
|
848
972
|
/**
|
|
@@ -850,9 +974,7 @@ export class OverlayController extends EventTarget {
|
|
|
850
974
|
* @protected
|
|
851
975
|
*/
|
|
852
976
|
_keepBodySize({ phase }) {
|
|
853
|
-
if (!this.preventsScroll)
|
|
854
|
-
return;
|
|
855
|
-
}
|
|
977
|
+
if (!this.preventsScroll) return;
|
|
856
978
|
|
|
857
979
|
this.manager.requestToKeepBodySize({ phase });
|
|
858
980
|
}
|
|
@@ -862,6 +984,9 @@ export class OverlayController extends EventTarget {
|
|
|
862
984
|
* @event hide right after the overlay is hidden
|
|
863
985
|
*/
|
|
864
986
|
async hide() {
|
|
987
|
+
// Function like a no-op for dynamic edge cases...
|
|
988
|
+
if (!this.config.isActivated) return;
|
|
989
|
+
|
|
865
990
|
this._hideComplete = new Promise(resolve => {
|
|
866
991
|
this._hideResolve = resolve;
|
|
867
992
|
});
|
|
@@ -894,7 +1019,6 @@ export class OverlayController extends EventTarget {
|
|
|
894
1019
|
if ('HTMLDialogElement' in window && this.__wrappingDialogNode instanceof HTMLDialogElement) {
|
|
895
1020
|
this.__wrappingDialogNode.close();
|
|
896
1021
|
}
|
|
897
|
-
|
|
898
1022
|
// @ts-ignore
|
|
899
1023
|
this.__wrappingDialogNode.style.display = 'none';
|
|
900
1024
|
this._handleFeatures({ phase: 'hide' });
|
|
@@ -903,6 +1027,8 @@ export class OverlayController extends EventTarget {
|
|
|
903
1027
|
this._restoreFocus();
|
|
904
1028
|
}
|
|
905
1029
|
/** @type {function} */ (this._hideResolve)();
|
|
1030
|
+
|
|
1031
|
+
this.contentNode.removeAttribute('data-open');
|
|
906
1032
|
}
|
|
907
1033
|
|
|
908
1034
|
/**
|
|
@@ -1013,23 +1139,53 @@ export class OverlayController extends EventTarget {
|
|
|
1013
1139
|
if (this.visibilityTriggerFunction) {
|
|
1014
1140
|
this._handleVisibilityTriggers({ phase });
|
|
1015
1141
|
}
|
|
1142
|
+
if (this.config.syncChildrenCloseState) {
|
|
1143
|
+
this._handleSyncChildrenCloseState({ phase });
|
|
1144
|
+
}
|
|
1145
|
+
if (this.config.focusContentOnOpen) {
|
|
1146
|
+
this._handleFocusContentOnOpen({ phase });
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
/**
|
|
1151
|
+
* @param {{phase: OverlayPhase}} opts
|
|
1152
|
+
* @returns {void}
|
|
1153
|
+
*/
|
|
1154
|
+
_handleFocusContentOnOpen({ phase }) {
|
|
1155
|
+
if (phase === 'init') {
|
|
1156
|
+
this.contentNode?.setAttribute('tabindex', '-1');
|
|
1157
|
+
} else if (phase === 'teardown') {
|
|
1158
|
+
// TODO: capture initial attr, use Resettable mechanism of VisibilityToggleCtrl in whole Controller
|
|
1159
|
+
this.contentNode?.removeAttribute('tabindex');
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
/**
|
|
1164
|
+
* @param {{phase: OverlayPhase}} opts
|
|
1165
|
+
* @returns {void}
|
|
1166
|
+
*/
|
|
1167
|
+
_handleSyncChildrenCloseState({ phase }) {
|
|
1168
|
+
if (phase !== 'hide') return;
|
|
1169
|
+
|
|
1170
|
+
const visibleChildren = this.manager.shownList.filter(
|
|
1171
|
+
ctrl => ctrl !== this && deepContains(this.contentNode, ctrl.contentNode),
|
|
1172
|
+
);
|
|
1173
|
+
visibleChildren.forEach(ctrl => ctrl.hide());
|
|
1016
1174
|
}
|
|
1017
1175
|
|
|
1018
1176
|
/**
|
|
1019
1177
|
* @param {{ phase: OverlayPhase }} config
|
|
1020
1178
|
*/
|
|
1021
1179
|
_handleVisibilityTriggers({ phase }) {
|
|
1022
|
-
if (typeof this.visibilityTriggerFunction
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
}
|
|
1029
|
-
if (this.__visibilityTriggerHandler[phase]) {
|
|
1030
|
-
this.__visibilityTriggerHandler[phase]();
|
|
1031
|
-
}
|
|
1180
|
+
if (typeof this.visibilityTriggerFunction !== 'function') return;
|
|
1181
|
+
|
|
1182
|
+
// Here we initialize the __visibilityTriggerHandler of our invokerNode. It's important that we ONLY do this on init,
|
|
1183
|
+
// otherwise we risk not being able to properly clean up listeners...
|
|
1184
|
+
if (phase === 'init') {
|
|
1185
|
+
this.__visibilityTriggerHandler = this.visibilityTriggerFunction({ controller: this });
|
|
1032
1186
|
}
|
|
1187
|
+
// Here we run the appropriate lifecycle, if defined in our handler
|
|
1188
|
+
this.__visibilityTriggerHandler[phase]?.();
|
|
1033
1189
|
}
|
|
1034
1190
|
|
|
1035
1191
|
/**
|
|
@@ -1186,7 +1342,9 @@ export class OverlayController extends EventTarget {
|
|
|
1186
1342
|
if (phase === 'show') {
|
|
1187
1343
|
this.#handleShiftKeyPress();
|
|
1188
1344
|
this.#handleFocusInsideDialog();
|
|
1345
|
+
// @ts-ignore - HTMLDialogElement methods
|
|
1189
1346
|
this.__wrappingDialogNode?.close();
|
|
1347
|
+
// @ts-ignore - HTMLDialogElement methods
|
|
1190
1348
|
this.__wrappingDialogNode?.showModal();
|
|
1191
1349
|
/**
|
|
1192
1350
|
* At this moment `#handleFocusInsideDialog` should handle the focus.
|
|
@@ -1437,6 +1595,7 @@ export class OverlayController extends EventTarget {
|
|
|
1437
1595
|
}
|
|
1438
1596
|
|
|
1439
1597
|
teardown() {
|
|
1598
|
+
if (!this.__hasSetup) return;
|
|
1440
1599
|
this.__handleOverlayStyles({ phase: 'teardown' });
|
|
1441
1600
|
if (this.isShown) {
|
|
1442
1601
|
this._keepBodySize({ phase: 'teardown' });
|
|
@@ -1445,6 +1604,15 @@ export class OverlayController extends EventTarget {
|
|
|
1445
1604
|
if (this.#isRegisteredOnManager()) {
|
|
1446
1605
|
this.manager.remove(this);
|
|
1447
1606
|
}
|
|
1607
|
+
|
|
1608
|
+
this.contentNode?.removeEventListener('click', this.#hideOnCloseButtonClick);
|
|
1609
|
+
|
|
1610
|
+
// if (this.config._shouldTeardownDomStructure) {
|
|
1611
|
+
this.__rearrangeNodesCleanup?.();
|
|
1612
|
+
// }
|
|
1613
|
+
this.__teardownVisibility();
|
|
1614
|
+
|
|
1615
|
+
this.__hasSetup = false;
|
|
1448
1616
|
}
|
|
1449
1617
|
|
|
1450
1618
|
/** @private */
|