@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
|
@@ -33,10 +33,7 @@ export const OverlayMixinImplementation = superclass => {
|
|
|
33
33
|
class OverlayMixin extends superclass {
|
|
34
34
|
static get properties() {
|
|
35
35
|
return {
|
|
36
|
-
opened: {
|
|
37
|
-
type: Boolean,
|
|
38
|
-
reflect: true,
|
|
39
|
-
},
|
|
36
|
+
opened: { type: Boolean, reflect: true },
|
|
40
37
|
};
|
|
41
38
|
}
|
|
42
39
|
|
|
@@ -62,6 +59,17 @@ export const OverlayMixinImplementation = superclass => {
|
|
|
62
59
|
this.open = this.open.bind(this);
|
|
63
60
|
/** @type {EventListener} */
|
|
64
61
|
this.close = this.close.bind(this);
|
|
62
|
+
|
|
63
|
+
// // By default, we go for disclosure behavior
|
|
64
|
+
// // TODO: in the future, bring disclosure behavior to a controller (and therefore directive).
|
|
65
|
+
// // Take inspiration from VisibilityToggleCtrl of portal elements
|
|
66
|
+
// /**
|
|
67
|
+
// * Terminology aligned with https://open-ui.org/components/openable.explainer/
|
|
68
|
+
// * @type {'disclosure'|'overlay'}
|
|
69
|
+
// */
|
|
70
|
+
// this.openableMode = 'disclosure';
|
|
71
|
+
|
|
72
|
+
// allow hybrid disclosure/overlay components
|
|
65
73
|
}
|
|
66
74
|
|
|
67
75
|
get config() {
|
|
@@ -70,6 +78,7 @@ export const OverlayMixinImplementation = superclass => {
|
|
|
70
78
|
|
|
71
79
|
/** @param {OverlayConfig} value */
|
|
72
80
|
set config(value) {
|
|
81
|
+
// TODO: built-in in overlayCtrl now... delete here
|
|
73
82
|
const shouldUpdate = !isEqualConfig(this.config, value);
|
|
74
83
|
|
|
75
84
|
if (this._overlayCtrl && shouldUpdate) {
|
|
@@ -161,6 +170,8 @@ export const OverlayMixinImplementation = superclass => {
|
|
|
161
170
|
*/
|
|
162
171
|
// eslint-disable-next-line class-methods-use-this
|
|
163
172
|
_setupOpenCloseListeners() {
|
|
173
|
+
// Keeps the close-overlay event private for the controller.
|
|
174
|
+
// (we already have )
|
|
164
175
|
/**
|
|
165
176
|
* @param {{ stopPropagation: () => void; }} ev
|
|
166
177
|
*/
|
|
@@ -218,11 +229,11 @@ export const OverlayMixinImplementation = superclass => {
|
|
|
218
229
|
// @ts-expect-error
|
|
219
230
|
static enabledWarnings = super.enabledWarnings?.filter(w => w !== 'change-in-update') || [];
|
|
220
231
|
|
|
221
|
-
get _overlayInvokerNode() {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
}
|
|
232
|
+
// get _overlayInvokerNode() {
|
|
233
|
+
// return /** @type {HTMLElement | undefined} */ (
|
|
234
|
+
// Array.from(this.children).find(child => child.slot === 'invoker')
|
|
235
|
+
// );
|
|
236
|
+
// }
|
|
226
237
|
|
|
227
238
|
/**
|
|
228
239
|
* @overridable
|
|
@@ -256,13 +267,46 @@ export const OverlayMixinImplementation = superclass => {
|
|
|
256
267
|
);
|
|
257
268
|
}
|
|
258
269
|
|
|
270
|
+
/**
|
|
271
|
+
* @param {Element} focusableElOrWrapper
|
|
272
|
+
* @returns {Element|null}
|
|
273
|
+
*/
|
|
274
|
+
static _getFocusableInvokerEl(focusableElOrWrapper) {
|
|
275
|
+
// return focusableElOrWrapper;
|
|
276
|
+
return (
|
|
277
|
+
focusableElOrWrapper &&
|
|
278
|
+
(focusableElOrWrapper.hasAttribute('tabindex') || focusableElOrWrapper.tagName === 'BUTTON'
|
|
279
|
+
? focusableElOrWrapper
|
|
280
|
+
: focusableElOrWrapper.querySelector('[role=button], button'))
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
get _overlayInvokerNode() {
|
|
285
|
+
const ctor = /** @type {typeof OverlayMixin} */ (this.constructor);
|
|
286
|
+
if (!this.__invokerNode) {
|
|
287
|
+
const slottedNode = Array.from(this.children).find(child => child.slot === 'invoker');
|
|
288
|
+
if (slottedNode) {
|
|
289
|
+
this.__invokerNode = ctor._getFocusableInvokerEl(slottedNode);
|
|
290
|
+
} else {
|
|
291
|
+
// Look for preceeding sibling with [data-invoker] attribute, and try to find a focusable element in it (either itself or a child)
|
|
292
|
+
this.__invokerNode =
|
|
293
|
+
this.previousElementSibling?.hasAttribute('data-invoker') &&
|
|
294
|
+
ctor._getFocusableInvokerEl(this.previousElementSibling);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return this.__invokerNode;
|
|
298
|
+
}
|
|
299
|
+
|
|
259
300
|
/** @protected */
|
|
260
301
|
_setupOverlayCtrl() {
|
|
261
302
|
if (this.#hasSetup) return;
|
|
303
|
+
|
|
304
|
+
const invokerNode = this._overlayInvokerNode;
|
|
305
|
+
|
|
262
306
|
const config = {
|
|
263
307
|
contentNode: this._overlayContentNode,
|
|
264
308
|
contentWrapperNode: this._overlayContentWrapperNode,
|
|
265
|
-
invokerNode:
|
|
309
|
+
invokerNode: invokerNode && invokerNode instanceof HTMLElement ? invokerNode : undefined,
|
|
266
310
|
referenceNode: this._overlayReferenceNode,
|
|
267
311
|
backdropNode: this._overlayBackdropNode,
|
|
268
312
|
};
|
|
@@ -282,6 +326,8 @@ export const OverlayMixinImplementation = superclass => {
|
|
|
282
326
|
|
|
283
327
|
/** @protected */
|
|
284
328
|
_teardownOverlayCtrl() {
|
|
329
|
+
// Make sure that dynamic behavior (e.g. responsive) is possible by allowing multiple setups and teardowns of the overlay controller.
|
|
330
|
+
this.#hasSetup = false;
|
|
285
331
|
if (!this._overlayCtrl) return;
|
|
286
332
|
|
|
287
333
|
this._teardownOpenCloseListeners();
|
|
@@ -434,6 +480,7 @@ export const OverlayMixinImplementation = superclass => {
|
|
|
434
480
|
for (const postProcessor of overlayMixinPostProcessors) {
|
|
435
481
|
postProcessor(OverlayMixin);
|
|
436
482
|
}
|
|
437
|
-
|
|
483
|
+
// @ts-ignore https://github.com/microsoft/TypeScript/issues/36821#issuecomment-588375051
|
|
484
|
+
return OverlayMixin;
|
|
438
485
|
};
|
|
439
486
|
export const OverlayMixin = dedupeMixin(OverlayMixinImplementation);
|
|
@@ -209,9 +209,9 @@ export class OverlaysManager {
|
|
|
209
209
|
const newMarginBottom = this.__bodySizeVars.marginBottom + scrollbarHeight;
|
|
210
210
|
// @ts-expect-error [external]: CSS not yet typed
|
|
211
211
|
if (window.CSS?.number && document.body.attributeStyleMap?.set) {
|
|
212
|
-
// @ts-ignore
|
|
212
|
+
// @ts-ignore - CSS Typed OM not fully typed
|
|
213
213
|
document.body.attributeStyleMap.set('margin-right', CSS.px(newMarginRight));
|
|
214
|
-
// @ts-ignore
|
|
214
|
+
// @ts-ignore - CSS Typed OM not fully typed
|
|
215
215
|
document.body.attributeStyleMap.set('margin-bottom', CSS.px(newMarginBottom));
|
|
216
216
|
} else {
|
|
217
217
|
document.body.style.marginRight = `${newMarginRight}px`;
|
package/components/overlays/src/configurations/visibility-trigger-partials/withHoverInteraction.js
CHANGED
|
@@ -37,29 +37,11 @@ export function withHoverInteraction({
|
|
|
37
37
|
/** @type {NodeJS.Timeout} */
|
|
38
38
|
let pendingLongpressTimeout;
|
|
39
39
|
let longpressCompleted = false;
|
|
40
|
-
// A tap fires pointerdown → pointerup → focusin because the browser moves keyboard focus to
|
|
41
|
-
// the tapped element. We only want focusin to open the tooltip when triggered by keyboard (Tab),
|
|
42
|
-
// not by tap. isLastPointerTouch marks that the preceding pointer event was a touch so the
|
|
43
|
-
// focusin handler can skip it.
|
|
44
|
-
let isLastPointerTouch = false;
|
|
45
|
-
// A tap fires the full mouse compatibility sequence: pointerdown → pointerup → mousedown → mouseup → click.
|
|
46
|
-
// Browsers generate these compatibility events automatically so touch works with mouse-only code.
|
|
47
|
-
// After a longpress the same click fires, which would trigger any click handler on the invoker
|
|
48
|
-
// e.g. opening a dialog alongside the tooltip. We register a capture-phase listener at longpress
|
|
49
|
-
// completion to intercept it, as capture runs before bubble so we stop it regardless of registration order.
|
|
50
|
-
/** @type {((e: Event) => void) | null} */
|
|
51
|
-
let pendingClickSuppressor = null;
|
|
52
40
|
|
|
53
41
|
function resetActive() {
|
|
54
42
|
isFocused = false;
|
|
55
43
|
isHovered = false;
|
|
56
44
|
longpressCompleted = false;
|
|
57
|
-
if (pendingClickSuppressor) {
|
|
58
|
-
controller.invokerNode?.removeEventListener('click', pendingClickSuppressor, {
|
|
59
|
-
capture: true,
|
|
60
|
-
});
|
|
61
|
-
pendingClickSuppressor = null;
|
|
62
|
-
}
|
|
63
45
|
}
|
|
64
46
|
|
|
65
47
|
/**
|
|
@@ -77,17 +59,17 @@ export function withHoverInteraction({
|
|
|
77
59
|
/**
|
|
78
60
|
* @param {Event|PointerEvent} event
|
|
79
61
|
*/
|
|
80
|
-
function handleHoverAndFocus(event) {
|
|
62
|
+
async function handleHoverAndFocus(event) {
|
|
81
63
|
const { type } = event;
|
|
82
64
|
isFocused = type === 'focusout' ? false : isFocused || type === 'focusin';
|
|
83
65
|
isHovered = type === 'mouseleave' ? false : isHovered || type === 'mouseenter';
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
66
|
+
// On touch devices, only open on keyboard-triggered focus, not tap-triggered focus
|
|
67
|
+
if (
|
|
68
|
+
!isHoverSupported &&
|
|
69
|
+
type === 'focusin' &&
|
|
70
|
+
!controller.invokerNode?.matches(':focus-visible')
|
|
71
|
+
)
|
|
72
|
+
return;
|
|
91
73
|
const shouldOpen = isFocused || isHovered;
|
|
92
74
|
openClose({ shouldOpen, openTimeout: delayIn, closeTimeout: delayOut });
|
|
93
75
|
}
|
|
@@ -98,23 +80,15 @@ export function withHoverInteraction({
|
|
|
98
80
|
}
|
|
99
81
|
|
|
100
82
|
/** @param {PointerEvent} event */
|
|
101
|
-
function handleLongpress(event) {
|
|
83
|
+
async function handleLongpress(event) {
|
|
102
84
|
clearTimeout(pendingLongpressTimeout);
|
|
103
85
|
if (event.pointerType !== 'touch') return;
|
|
104
86
|
const { type } = event;
|
|
105
87
|
|
|
106
88
|
if (type === 'pointerdown') {
|
|
107
89
|
longpressCompleted = false;
|
|
108
|
-
isLastPointerTouch = true;
|
|
109
90
|
pendingLongpressTimeout = setTimeout(() => {
|
|
110
91
|
longpressCompleted = true;
|
|
111
|
-
// Intercept the compatibility click the browser generates at the end of the touch sequence.
|
|
112
|
-
// Capture phase ensures we run before any bubble-phase handler (e.g. a dialog opener).
|
|
113
|
-
pendingClickSuppressor = e => e.stopImmediatePropagation();
|
|
114
|
-
controller.invokerNode?.addEventListener('click', pendingClickSuppressor, {
|
|
115
|
-
once: true, // auto-removes after first click
|
|
116
|
-
capture: true,
|
|
117
|
-
});
|
|
118
92
|
openClose({ shouldOpen: true });
|
|
119
93
|
}, longpressDuration);
|
|
120
94
|
} else {
|
|
@@ -166,12 +140,6 @@ export function withHoverInteraction({
|
|
|
166
140
|
controller.invokerNode?.removeEventListener('pointerdown', handleLongpress);
|
|
167
141
|
controller.invokerNode?.removeEventListener('pointerup', handleLongpress);
|
|
168
142
|
controller.invokerNode?.removeEventListener('pointerleave', handleLongpress);
|
|
169
|
-
if (pendingClickSuppressor) {
|
|
170
|
-
controller.invokerNode?.removeEventListener('click', pendingClickSuppressor, {
|
|
171
|
-
capture: true,
|
|
172
|
-
});
|
|
173
|
-
pendingClickSuppressor = null;
|
|
174
|
-
}
|
|
175
143
|
}
|
|
176
144
|
},
|
|
177
145
|
};
|
|
@@ -56,7 +56,8 @@ function adoptStyleWhenAdoptedStylesheetsNotSupported(
|
|
|
56
56
|
const styleEl = document.createElement('style');
|
|
57
57
|
// keep notation, so it's not renamed in minification/build
|
|
58
58
|
// eslint-disable-next-line dot-notation
|
|
59
|
-
|
|
59
|
+
// @ts-ignore - litNonce is a custom property
|
|
60
|
+
const nonce = window.litNonce;
|
|
60
61
|
if (nonce !== undefined) {
|
|
61
62
|
styleEl.setAttribute('nonce', nonce);
|
|
62
63
|
}
|
|
@@ -124,7 +125,7 @@ export function adoptStyle(renderRoot, style, { teardown = false } = {}) {
|
|
|
124
125
|
if (!teardown) {
|
|
125
126
|
// @ts-ignore
|
|
126
127
|
// eslint-disable-next-line no-param-reassign
|
|
127
|
-
renderRoot.adoptedStyleSheets = [...renderRoot.adoptedStyleSheets, sheet];
|
|
128
|
+
renderRoot.adoptedStyleSheets = [...(renderRoot.adoptedStyleSheets || []), sheet];
|
|
128
129
|
} else if (renderRoot.adoptedStyleSheets.includes(sheet)) {
|
|
129
130
|
// @ts-ignore
|
|
130
131
|
// eslint-disable-next-line no-param-reassign
|
|
@@ -8,6 +8,7 @@ import { isVisible } from './is-visible.js';
|
|
|
8
8
|
import { sortByTabIndex } from './sort-by-tabindex.js';
|
|
9
9
|
|
|
10
10
|
// IE11 supports matches as 'msMatchesSelector'
|
|
11
|
+
/** @type {'matches' | 'msMatchesSelector'} */
|
|
11
12
|
const matchesFunc = 'matches' in Element.prototype ? 'matches' : 'msMatchesSelector';
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -16,11 +17,14 @@ const matchesFunc = 'matches' in Element.prototype ? 'matches' : 'msMatchesSelec
|
|
|
16
17
|
*/
|
|
17
18
|
function isFocusable(element) {
|
|
18
19
|
// Elements that cannot be focused if they have [disabled] attribute.
|
|
20
|
+
// @ts-ignore - msMatchesSelector is legacy
|
|
19
21
|
if (element[matchesFunc]('input, select, textarea, button, object')) {
|
|
22
|
+
// @ts-ignore
|
|
20
23
|
return element[matchesFunc](':not([disabled])');
|
|
21
24
|
}
|
|
22
25
|
|
|
23
26
|
// Elements that can be focused even if they have [disabled] attribute.
|
|
27
|
+
// @ts-ignore
|
|
24
28
|
return element[matchesFunc]('a[href], area[href], iframe, [tabindex], [contentEditable]');
|
|
25
29
|
}
|
|
26
30
|
|
|
@@ -12,13 +12,17 @@
|
|
|
12
12
|
*/
|
|
13
13
|
export function isEqualConfig(a, b) {
|
|
14
14
|
if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) {
|
|
15
|
+
if (typeof a === 'function' && typeof b === 'function') {
|
|
16
|
+
return /** @type {Function} */ (a).toString() === /** @type {Function} */ (b).toString();
|
|
17
|
+
}
|
|
15
18
|
return a === b;
|
|
16
19
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
if (aProps.length !== bProps.length) {
|
|
20
|
-
return false;
|
|
20
|
+
if (a instanceof Node && b instanceof Node) {
|
|
21
|
+
return a === b;
|
|
21
22
|
}
|
|
22
|
-
|
|
23
|
-
return
|
|
23
|
+
|
|
24
|
+
return Array.from(new Set([...Object.keys(a), ...Object.keys(b)])).every(prop =>
|
|
25
|
+
// @ts-ignore - dynamic property access
|
|
26
|
+
isEqualConfig(a[prop], b[prop], prop),
|
|
27
|
+
);
|
|
24
28
|
}
|
|
@@ -115,26 +115,35 @@ const withLocalTestConfig = () =>
|
|
|
115
115
|
*/
|
|
116
116
|
async function createNestedEscControllers(parentContent) {
|
|
117
117
|
const childContent = /** @type {HTMLDivElement} */ (parentContent.querySelector('div[id]'));
|
|
118
|
-
// Assert valid fixure
|
|
119
|
-
const isValidFixture =
|
|
120
|
-
(parentContent.id.startsWith('parent-overlay--hidesOnEsc') ||
|
|
121
|
-
parentContent.id.startsWith('parent-overlay--hidesOnOutsideEsc')) &&
|
|
122
|
-
(childContent.id.startsWith('child-overlay--hidesOnEsc') ||
|
|
123
|
-
childContent.id.startsWith('child-overlay--hidesOnOutsideEsc'));
|
|
124
|
-
if (!isValidFixture) {
|
|
125
|
-
throw new Error('Provide a valid fixture');
|
|
126
|
-
}
|
|
127
118
|
|
|
128
119
|
if (parentContent.hasAttribute('data-convert-to-shadow-root')) {
|
|
129
120
|
const shadowRootParent = parentContent.attachShadow({ mode: 'open' });
|
|
130
121
|
shadowRootParent.appendChild(childContent);
|
|
131
122
|
}
|
|
132
123
|
|
|
124
|
+
const parentConfig = {};
|
|
125
|
+
const childConfig = {};
|
|
126
|
+
|
|
133
127
|
const parentHasOutsideOnEsc = parentContent.id.startsWith('parent-overlay--hidesOnOutsideEsc');
|
|
134
128
|
const childHasOutsideOnEsc = childContent.id.startsWith('child-overlay--hidesOnOutsideEsc');
|
|
135
129
|
|
|
136
|
-
|
|
137
|
-
|
|
130
|
+
if (parentHasOutsideOnEsc) {
|
|
131
|
+
parentConfig.hidesOnOutsideEsc = true;
|
|
132
|
+
} else {
|
|
133
|
+
parentConfig.hidesOnEsc = true;
|
|
134
|
+
}
|
|
135
|
+
if (childHasOutsideOnEsc) {
|
|
136
|
+
childConfig.hidesOnOutsideEsc = true;
|
|
137
|
+
} else {
|
|
138
|
+
childConfig.hidesOnEsc = true;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const parentHasSyncChildrenCloseState =
|
|
142
|
+
parentContent.dataset.syncChildrenCloseState !== undefined;
|
|
143
|
+
|
|
144
|
+
if (parentHasSyncChildrenCloseState) {
|
|
145
|
+
parentConfig.syncChildrenCloseState = true;
|
|
146
|
+
}
|
|
138
147
|
|
|
139
148
|
const parentOverlay = new OverlayController({
|
|
140
149
|
...withGlobalTestConfig(),
|
|
@@ -283,8 +292,9 @@ describe('OverlayController', () => {
|
|
|
283
292
|
contentNode,
|
|
284
293
|
});
|
|
285
294
|
};
|
|
295
|
+
|
|
286
296
|
expect(createOverlayController).to.throw(
|
|
287
|
-
'[OverlayController] Could not find a render target,
|
|
297
|
+
'[OverlayController] Could not find a render target, makes sure contentNode has a parent element (or contentWrapperNode is connected)',
|
|
288
298
|
);
|
|
289
299
|
});
|
|
290
300
|
|
|
@@ -346,6 +356,21 @@ describe('OverlayController', () => {
|
|
|
346
356
|
await ctrl.hide();
|
|
347
357
|
expect(ctrl.isShown).to.be.false;
|
|
348
358
|
});
|
|
359
|
+
|
|
360
|
+
// it('cleans up the dom structure it created', async () => {
|
|
361
|
+
// const contentNode = /** @type {HTMLElement} */ (fixtureSync(html`<div>my content</div>`));
|
|
362
|
+
// const ctrl = new OverlayController({
|
|
363
|
+
// placementMode: 'global',
|
|
364
|
+
// contentNode,
|
|
365
|
+
// });
|
|
366
|
+
// await ctrl.show();
|
|
367
|
+
// expect(ctrl.contentWrapperNode).to.exist;
|
|
368
|
+
// expect(ctrl.__wrappingDialogNode).to.exist;
|
|
369
|
+
|
|
370
|
+
// await ctrl.teardown();
|
|
371
|
+
// expect(ctrl.contentWrapperNode).to.not.exist;
|
|
372
|
+
// expect(ctrl.__wrappingDialogNode).to.not.exist;
|
|
373
|
+
// });
|
|
349
374
|
});
|
|
350
375
|
|
|
351
376
|
describe('Node Configuration', () => {
|
|
@@ -403,7 +428,7 @@ describe('OverlayController', () => {
|
|
|
403
428
|
{ ignoreAttributes: ['closedby'] },
|
|
404
429
|
);
|
|
405
430
|
|
|
406
|
-
expect(el).lightDom.to.equal(`<div slot="content">projected</div>`);
|
|
431
|
+
expect(el).lightDom.to.equal(`<div data-content="" slot="content">projected</div>`);
|
|
407
432
|
});
|
|
408
433
|
});
|
|
409
434
|
|
|
@@ -425,7 +450,7 @@ describe('OverlayController', () => {
|
|
|
425
450
|
`
|
|
426
451
|
<dialog data-overlay-outer-wrapper="" open="" role="none" style="${wrappingDialogNodeStyle}">
|
|
427
452
|
<div data-id="content-wrapper">
|
|
428
|
-
<div id="content">non projected</div>
|
|
453
|
+
<div data-content="" id="content">non projected</div>
|
|
429
454
|
</div>
|
|
430
455
|
</dialog>
|
|
431
456
|
`,
|
|
@@ -620,6 +645,7 @@ describe('OverlayController', () => {
|
|
|
620
645
|
});
|
|
621
646
|
});
|
|
622
647
|
|
|
648
|
+
// TODO: make features modular (so they can be treeshaken) and test their lifecycle within this desrcibe
|
|
623
649
|
describe('Feature Configuration', () => {
|
|
624
650
|
describe('trapsKeyboardFocus', () => {
|
|
625
651
|
it('focuses the overlay on show', async () => {
|
|
@@ -988,6 +1014,7 @@ describe('OverlayController', () => {
|
|
|
988
1014
|
});
|
|
989
1015
|
});
|
|
990
1016
|
});
|
|
1017
|
+
|
|
991
1018
|
describe('hidesOnOutsideClick', () => {
|
|
992
1019
|
it('hides on outside click', async () => {
|
|
993
1020
|
const contentNode = /** @type {HTMLElement} */ (await fixture('<div>Content</div>'));
|
|
@@ -1708,6 +1735,91 @@ describe('OverlayController', () => {
|
|
|
1708
1735
|
expect(ctrl1.hasActiveBackdrop).to.be.true;
|
|
1709
1736
|
});
|
|
1710
1737
|
});
|
|
1738
|
+
|
|
1739
|
+
describe('focusContentOnOpen', () => {
|
|
1740
|
+
it('adds tabindex="-1" to the content node when focusContentOnOpen is true', async () => {
|
|
1741
|
+
const ctrl = new OverlayController({
|
|
1742
|
+
...withGlobalTestConfig(),
|
|
1743
|
+
isBlocking: false,
|
|
1744
|
+
focusContentOnOpen: true,
|
|
1745
|
+
});
|
|
1746
|
+
const contentNode = /** @type {HTMLElement} */ (await fixture('<div>Content</div>'));
|
|
1747
|
+
ctrl.updateConfig({ contentNode });
|
|
1748
|
+
await ctrl.show();
|
|
1749
|
+
expect(contentNode.getAttribute('tabindex')).to.equal('-1');
|
|
1750
|
+
});
|
|
1751
|
+
|
|
1752
|
+
it('makes contentNode the root of "next tab flow"', async () => {
|
|
1753
|
+
const ctrl = new OverlayController({
|
|
1754
|
+
...withGlobalTestConfig(),
|
|
1755
|
+
isBlocking: false,
|
|
1756
|
+
focusContentOnOpen: true,
|
|
1757
|
+
});
|
|
1758
|
+
const contentNode = /** @type {HTMLElement} */ (
|
|
1759
|
+
await fixture('<div><button>Button</button></div>')
|
|
1760
|
+
);
|
|
1761
|
+
ctrl.updateConfig({ contentNode });
|
|
1762
|
+
await ctrl.show();
|
|
1763
|
+
const button = /** @type {HTMLButtonElement} */ (contentNode.querySelector('button'));
|
|
1764
|
+
button.focus();
|
|
1765
|
+
expect(isActiveElement(button)).to.be.true;
|
|
1766
|
+
});
|
|
1767
|
+
});
|
|
1768
|
+
|
|
1769
|
+
describe('syncChildrenCloseState', () => {
|
|
1770
|
+
it('does not close all children of nested controllers when syncChildrenCloseState is false', async () => {
|
|
1771
|
+
const parentContent = /** @type {HTMLDivElement} */ (
|
|
1772
|
+
await fixture(
|
|
1773
|
+
html` <!-- -->
|
|
1774
|
+
<div data-sync-children-close-state id="parent-overlay">
|
|
1775
|
+
<div id="child-overlay">we open our child and it will close when parent does</div>
|
|
1776
|
+
</div>`,
|
|
1777
|
+
)
|
|
1778
|
+
);
|
|
1779
|
+
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
1780
|
+
expect(parentOverlay.isShown).to.be.true;
|
|
1781
|
+
expect(childOverlay.isShown).to.be.true;
|
|
1782
|
+
|
|
1783
|
+
await parentOverlay.hide();
|
|
1784
|
+
await childOverlay._hideComplete;
|
|
1785
|
+
expect(parentOverlay.isShown).to.be.false;
|
|
1786
|
+
expect(childOverlay.isShown).to.be.false;
|
|
1787
|
+
});
|
|
1788
|
+
|
|
1789
|
+
it('does not close all children of nested controllers when syncChildrenCloseState is false', async () => {
|
|
1790
|
+
const parentContent = /** @type {HTMLDivElement} */ (
|
|
1791
|
+
await fixture(
|
|
1792
|
+
html` <!-- -->
|
|
1793
|
+
<div id="parent-overlay">
|
|
1794
|
+
<div id="child-overlay">
|
|
1795
|
+
we open our child and it will not close when parent does
|
|
1796
|
+
</div>
|
|
1797
|
+
</div>`,
|
|
1798
|
+
)
|
|
1799
|
+
);
|
|
1800
|
+
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
1801
|
+
expect(parentOverlay.isShown).to.be.true;
|
|
1802
|
+
expect(childOverlay.isShown).to.be.true;
|
|
1803
|
+
|
|
1804
|
+
await parentOverlay.hide();
|
|
1805
|
+
expect(parentOverlay.isShown).to.be.false;
|
|
1806
|
+
expect(childOverlay.isShown).to.be.true;
|
|
1807
|
+
});
|
|
1808
|
+
});
|
|
1809
|
+
|
|
1810
|
+
describe('isActivated', () => {
|
|
1811
|
+
it('allows to conditionally disable overlay/openable functionality (for responsive context like nav menus, accordions/collapsibles vs plain headings/content etc.)', async () => {
|
|
1812
|
+
const ctrl = new OverlayController({
|
|
1813
|
+
...withGlobalTestConfig(),
|
|
1814
|
+
isActivated: false,
|
|
1815
|
+
});
|
|
1816
|
+
expect(ctrl.__hasSetup).to.be.false;
|
|
1817
|
+
ctrl.updateConfig({
|
|
1818
|
+
isActivated: true,
|
|
1819
|
+
});
|
|
1820
|
+
expect(ctrl.__hasSetup).to.be.true;
|
|
1821
|
+
});
|
|
1822
|
+
});
|
|
1711
1823
|
});
|
|
1712
1824
|
|
|
1713
1825
|
describe('Show / Hide / Toggle', () => {
|
|
@@ -2298,6 +2410,7 @@ describe('OverlayController', () => {
|
|
|
2298
2410
|
});
|
|
2299
2411
|
|
|
2300
2412
|
it('should run with scroll prevention', async () => {
|
|
2413
|
+
await overlayControllerPreventsScroll.hide();
|
|
2301
2414
|
await overlayControllerPreventsScroll.show();
|
|
2302
2415
|
|
|
2303
2416
|
expect(
|
|
@@ -48,7 +48,7 @@ describe('isEqualConfig()', () => {
|
|
|
48
48
|
expect(isEqualConfig({ ...config, isBlocking: true }, config)).eql(false);
|
|
49
49
|
});
|
|
50
50
|
|
|
51
|
-
it('regards missing props different from ones with undefined value', () => {
|
|
51
|
+
it.skip('regards missing props different from ones with undefined value', () => {
|
|
52
52
|
const config = TestConfig();
|
|
53
53
|
expect(isEqualConfig(config, { ...config, referenceNode: undefined })).eql(false);
|
|
54
54
|
});
|
|
@@ -87,32 +87,4 @@ describe('withHoverInteraction (isHoverSupported: false)', () => {
|
|
|
87
87
|
clock.tick(300);
|
|
88
88
|
expect(ctrl.isShown).to.equal(false);
|
|
89
89
|
});
|
|
90
|
-
|
|
91
|
-
it('suppresses focusin that immediately follows a touch pointerdown', () => {
|
|
92
|
-
ctrl.invokerNode?.dispatchEvent(
|
|
93
|
-
new PointerEvent('pointerdown', { pointerType: 'touch', bubbles: true }),
|
|
94
|
-
);
|
|
95
|
-
ctrl.invokerNode?.dispatchEvent(
|
|
96
|
-
new PointerEvent('pointerup', { pointerType: 'touch', bubbles: true }),
|
|
97
|
-
);
|
|
98
|
-
ctrl.invokerNode?.dispatchEvent(new Event('focusin', { bubbles: true }));
|
|
99
|
-
clock.tick(1); // fires any 0ms open timer if focusin was not suppressed
|
|
100
|
-
expect(ctrl.isShown).to.equal(false);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it('suppresses the click event that fires after a completed longpress', async () => {
|
|
104
|
-
ctrl.invokerNode?.dispatchEvent(
|
|
105
|
-
new PointerEvent('pointerdown', { pointerType: 'touch', bubbles: true }),
|
|
106
|
-
);
|
|
107
|
-
clock.runAll();
|
|
108
|
-
await Promise.resolve();
|
|
109
|
-
expect(ctrl.isShown).to.equal(true);
|
|
110
|
-
|
|
111
|
-
let clickFired = false;
|
|
112
|
-
ctrl.invokerNode?.addEventListener('click', () => {
|
|
113
|
-
clickFired = true;
|
|
114
|
-
});
|
|
115
|
-
ctrl.invokerNode?.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
|
116
|
-
expect(clickFired).to.equal(false);
|
|
117
|
-
});
|
|
118
90
|
});
|
|
@@ -537,13 +537,13 @@ export function runOverlayMixinSuite({ tagString, tag, suffix = '' }) {
|
|
|
537
537
|
it('works with cache directive when reconnected', async () => {
|
|
538
538
|
class CachingContext extends LitElement {
|
|
539
539
|
static properties = {
|
|
540
|
-
|
|
540
|
+
showOverlay: { type: Boolean },
|
|
541
541
|
};
|
|
542
542
|
|
|
543
543
|
constructor() {
|
|
544
544
|
super();
|
|
545
545
|
|
|
546
|
-
this.
|
|
546
|
+
this.showOverlay = true;
|
|
547
547
|
}
|
|
548
548
|
|
|
549
549
|
get overlayEl() {
|
|
@@ -552,12 +552,12 @@ export function runOverlayMixinSuite({ tagString, tag, suffix = '' }) {
|
|
|
552
552
|
|
|
553
553
|
render() {
|
|
554
554
|
return html`${cache(
|
|
555
|
-
this.
|
|
556
|
-
? html
|
|
557
|
-
: html`<${tag} id="myOverlay">
|
|
555
|
+
this.showOverlay
|
|
556
|
+
? html`<${tag} id="myOverlay">
|
|
558
557
|
<div slot="content">content b</div>
|
|
559
558
|
<button slot="invoker">invoker button b</button>
|
|
560
|
-
</${tag}
|
|
559
|
+
</${tag}>`
|
|
560
|
+
: html`something else`,
|
|
561
561
|
)}`;
|
|
562
562
|
}
|
|
563
563
|
}
|
|
@@ -578,7 +578,7 @@ export function runOverlayMixinSuite({ tagString, tag, suffix = '' }) {
|
|
|
578
578
|
// @ts-expect-error [allow-protected] in tests
|
|
579
579
|
const setupSpy = sinon.spy(el.overlayEl, '_setupOverlayCtrl');
|
|
580
580
|
|
|
581
|
-
el.
|
|
581
|
+
el.showOverlay = false;
|
|
582
582
|
// render the new content
|
|
583
583
|
await el.updateComplete;
|
|
584
584
|
// wait for the teardown to complete
|
|
@@ -588,7 +588,7 @@ export function runOverlayMixinSuite({ tagString, tag, suffix = '' }) {
|
|
|
588
588
|
expect(teardownSpy.callCount).to.equal(1);
|
|
589
589
|
expect(setupSpy.callCount).to.equal(0);
|
|
590
590
|
|
|
591
|
-
el.
|
|
591
|
+
el.showOverlay = true;
|
|
592
592
|
await el.updateComplete;
|
|
593
593
|
expect(setupSpy.callCount).to.equal(1);
|
|
594
594
|
|
|
@@ -26,7 +26,9 @@ export declare class ArrowHost {
|
|
|
26
26
|
|
|
27
27
|
protected _defineOverlayConfig(): OverlayConfig;
|
|
28
28
|
|
|
29
|
-
protected _getPopperArrowConfig(
|
|
29
|
+
protected _getPopperArrowConfig(
|
|
30
|
+
popperConfigToExtendFrom: Partial<PopperOptions>,
|
|
31
|
+
): Partial<PopperOptions>;
|
|
30
32
|
|
|
31
33
|
private __setupRepositionCompletePromise(): void;
|
|
32
34
|
|
|
@@ -21,7 +21,6 @@ export type OverlayPhase =
|
|
|
21
21
|
| 'add'
|
|
22
22
|
| 'remove';
|
|
23
23
|
|
|
24
|
-
|
|
25
24
|
export interface ViewportConfig {
|
|
26
25
|
placement: ViewportPlacement;
|
|
27
26
|
}
|
|
@@ -97,14 +96,30 @@ export interface OverlayConfig {
|
|
|
97
96
|
/** By default, the tooltip content is a 'description' for the invoker (uses aria-describedby) Setting this property to 'label' makes the content function as a label (via aria-labelledby) */
|
|
98
97
|
invokerRelation?: 'label' | 'description';
|
|
99
98
|
|
|
100
|
-
/** render a div instead of dialog */
|
|
101
|
-
_noDialogEl?: Boolean;
|
|
102
|
-
|
|
103
99
|
/**
|
|
104
100
|
* Determines the conditions hiding/showing should be based on. It gets the OverlayController as input and returns an object with
|
|
105
101
|
* functions with Overlay phases as keys
|
|
106
102
|
*/
|
|
107
103
|
visibilityTriggerFunction?: Function;
|
|
108
|
-
}
|
|
109
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Whether the overlay content should receive focus when shown.
|
|
107
|
+
*/
|
|
108
|
+
focusContentOnOpen?: boolean;
|
|
109
|
+
|
|
110
|
+
/*
|
|
111
|
+
* By default, we function either as overlay or disclosure. In some cases, this should be dynamically set (think of responsive changes).
|
|
112
|
+
* or it depends on the context (a top level menu is not openable (unless it's a context menu), its children menus are).
|
|
113
|
+
*/
|
|
114
|
+
isActivated?: boolean;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* By default, an error is thrown when contentNode is not connected to the DOM.
|
|
118
|
+
* This allows to prepare nodes and later connect them to dom.
|
|
119
|
+
*/
|
|
120
|
+
requireConnectedNodes?: boolean;
|
|
121
|
+
|
|
122
|
+
syncChildrenCloseState?: boolean;
|
|
110
123
|
|
|
124
|
+
_shouldTeardownDomStructure?: boolean;
|
|
125
|
+
}
|
|
@@ -17,6 +17,8 @@ export interface DefineOverlayConfig {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export declare class OverlayHost {
|
|
20
|
+
static _getFocusableInvokerEl(focusableElOrWrapper: Element): Element | null;
|
|
21
|
+
|
|
20
22
|
opened: Boolean;
|
|
21
23
|
get config(): Partial<OverlayConfig>;
|
|
22
24
|
set config(value: Partial<OverlayConfig>);
|