@lion/ui 0.22.0 → 0.24.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/README.md +65 -0
- package/components/accordion/src/LionAccordion.js +31 -42
- package/components/accordion/test/lion-accordion.test.js +108 -134
- package/components/button/src/LionButton.js +9 -12
- package/components/button/src/LionButtonReset.js +0 -5
- package/components/button/src/LionButtonSubmit.js +7 -12
- package/components/button/test/demos.screenshots-test.js +50 -11
- package/components/button/test/lion-button.test.js +0 -1
- package/components/button/test-suites/LionButton.suite.js +135 -145
- package/components/button/test-suites/LionButtonReset.suite.js +54 -72
- package/components/button/test-suites/LionButtonSubmit.suite.js +49 -68
- package/components/calendar/src/LionCalendar.js +151 -104
- package/components/calendar/src/calendarStyle.js +0 -1
- package/components/calendar/src/utils/createMonth.js +3 -4
- package/components/calendar/src/utils/createMultipleMonth.js +15 -7
- package/components/calendar/src/utils/createWeek.js +0 -2
- package/components/calendar/src/utils/dataTemplate.js +8 -4
- package/components/calendar/src/utils/dayTemplate.js +0 -6
- package/components/calendar/src/utils/getDayMonthYear.js +6 -2
- package/components/calendar/test/demos.screenshots-test.js +40 -9
- package/components/calendar/test/lion-calendar.test.js +171 -282
- package/components/calendar/test/utils/createMonth.test.js +61 -22
- package/components/calendar/test/utils/createMultipleMonth.test.js +14 -7
- package/components/calendar/test/utils/createWeek.test.js +51 -17
- package/components/calendar/test/utils/dataTemplate.test.js +3 -4
- package/components/calendar/test/utils/dayTemplate.test.js +106 -34
- package/components/calendar/test/utils/getFirstDayNextMonth.test.js +0 -1
- package/components/calendar/test/utils/getLastDayPreviousMonth.test.js +0 -1
- package/components/calendar/test/utils/isSameDate.test.js +0 -1
- package/components/calendar/test/utils/snapshots/monthTemplate_en-GB_Sunday_2018-12.js +1 -2
- package/components/calendar/test-helpers/CalendarObject.js +31 -62
- package/components/calendar/test-helpers/DayObject.js +7 -15
- package/components/calendar/test-suites/LionCalendar.suite.js +7 -9
- package/components/checkbox-group/src/LionCheckboxIndeterminate.js +17 -30
- package/components/checkbox-group/test/lion-checkbox-group-integrations.test.js +0 -1
- package/components/checkbox-group/test/lion-checkbox-group.test.js +21 -16
- package/components/checkbox-group/test/lion-checkbox-indeterminate-integrations.test.js +3 -3
- package/components/checkbox-group/test/lion-checkbox-integrations.test.js +3 -2
- package/components/checkbox-group/test/lion-checkbox.test.js +30 -16
- package/components/checkbox-group/test-suites/CheckboxIndeterminate.suite.js +147 -191
- package/components/collapsible/src/LionCollapsible.js +10 -15
- package/components/collapsible/test/lion-collapsible.test.js +4 -18
- package/components/combobox/src/LionCombobox.js +45 -55
- package/components/combobox/src/utils/makeMatchingTextBold.js +2 -5
- package/components/combobox/src/validators.js +0 -1
- package/components/combobox/test/lion-combobox-integrations.test.js +6 -6
- package/components/combobox/test/lion-combobox.test.js +598 -860
- package/components/combobox/test/validators.test.js +6 -13
- package/components/combobox/test-helpers/combobox-helpers.js +24 -11
- package/components/core/src/DisabledMixin.js +61 -66
- package/components/core/src/DisabledWithTabIndexMixin.js +76 -83
- package/components/core/src/EventTargetShim.js +1 -4
- package/components/core/src/ScopedElementsMixin.js +4 -15
- package/components/core/src/ScopedStylesController.js +1 -5
- package/components/core/src/SlotMixin.js +236 -239
- package/components/core/src/browserDetection.js +5 -12
- package/components/core/test/DisabledMixin.test.js +24 -39
- package/components/core/test/DisabledWithTabIndexMixin.test.js +21 -34
- package/components/core/test/EventTargetShim.test.js +0 -8
- package/components/core/test/ScopedElementsMixin.test.js +22 -38
- package/components/core/test/ScopedStylesController.test.js +11 -20
- package/components/core/test/SlotMixin.test.js +102 -154
- package/components/core/test-helpers/getCachedFixture.js +5 -11
- package/components/core/types/SlotMixinTypes.ts +8 -3
- package/components/dialog/src/LionDialog.js +4 -3
- package/components/dialog/test/lion-dialog.integration.test.js +10 -20
- package/components/dialog/test/lion-dialog.test.js +48 -62
- package/components/dialog/test-helpers/test-router.js +4 -6
- package/components/drawer/src/LionDrawer.js +18 -34
- package/components/drawer/src/drawerStyle.js +0 -1
- package/components/drawer/test/lion-drawer.test.js +1 -17
- package/components/fieldset/test/lion-fieldset.test.js +6 -4
- package/components/form/src/LionForm.js +18 -13
- package/components/form/test/lion-form.test.js +22 -52
- package/components/form-core/src/FocusMixin.js +172 -174
- package/components/form-core/src/FormControlMixin.js +811 -813
- package/components/form-core/src/FormatMixin.js +537 -537
- package/components/form-core/src/InteractionStateMixin.js +196 -183
- package/components/form-core/src/LionField.js +9 -5
- package/components/form-core/src/NativeTextFieldMixin.js +114 -116
- package/components/form-core/src/choice-group/ChoiceGroupMixin.js +322 -357
- package/components/form-core/src/choice-group/ChoiceInputMixin.js +306 -296
- package/components/form-core/src/choice-group/CustomChoiceGroupMixin.js +114 -139
- package/components/form-core/src/form-group/FormElementsHaveNoError.js +0 -2
- package/components/form-core/src/form-group/FormGroupMixin.js +551 -557
- package/components/form-core/src/registration/FormRegisteringMixin.js +72 -71
- package/components/form-core/src/registration/FormRegistrarMixin.js +201 -217
- package/components/form-core/src/registration/FormRegistrarPortalMixin.js +31 -37
- package/components/form-core/src/utils/SyncUpdatableMixin.js +106 -117
- package/components/form-core/src/utils/getAriaElementsInRightDomOrder.js +1 -2
- package/components/form-core/src/validate/LionValidationFeedback.js +12 -8
- package/components/form-core/src/validate/Unparseable.js +4 -2
- package/components/form-core/src/validate/ValidateMixin.js +829 -883
- package/components/form-core/src/validate/Validator.js +3 -6
- package/components/form-core/src/validate/resultValidators/DefaultSuccess.js +1 -2
- package/components/form-core/src/validate/validators/DateValidators.js +0 -5
- package/components/form-core/src/validate/validators/NumberValidators.js +1 -5
- package/components/form-core/src/validate/validators/Required.js +1 -1
- package/components/form-core/src/validate/validators/StringValidators.js +1 -8
- package/components/form-core/test/FocusMixin.test.js +96 -82
- package/components/form-core/test/FormControlMixin.test.js +120 -176
- package/components/form-core/test/FormRegistrationMixins.test.js +0 -2
- package/components/form-core/test/FormatMixin.test.js +0 -1
- package/components/form-core/test/InteractionStateMixin.test.js +0 -1
- package/components/form-core/test/NativeTextFieldMixin.test.js +0 -1
- package/components/form-core/test/choice-group/ChoiceGroupMixin.test.js +0 -1
- package/components/form-core/test/choice-group/ChoiceInputMixin.test.js +0 -1
- package/components/form-core/test/choice-group/CustomChoiceGroupMixin.integrations.test.js +6 -8
- package/components/form-core/test/choice-group/CustomChoiceGroupMixin.test.js +0 -3
- package/components/form-core/test/form-group/FormGroupMixin.test.js +0 -1
- package/components/form-core/test/lion-field.test.js +88 -98
- package/components/form-core/test/utils/SyncUpdatableMixin.test.js +51 -65
- package/components/form-core/test/utils/getAriaElementsInRightDomOrder.test.js +3 -3
- package/components/form-core/test/validate/DateValidators.test.js +5 -27
- package/components/form-core/test/validate/NumberValidators.test.js +4 -16
- package/components/form-core/test/validate/Required.test.js +8 -21
- package/components/form-core/test/validate/ResultValidator.test.js +1 -2
- package/components/form-core/test/validate/StringValidators.test.js +4 -35
- package/components/form-core/test/validate/ValidateMixin.test.js +0 -1
- package/components/form-core/test/validate/ValidateMixinFeedbackPart.test.js +0 -1
- package/components/form-core/test/validate/Validator.test.js +39 -34
- package/components/form-core/test/validate/lion-validation-feedback.test.js +81 -43
- package/components/form-core/test-helpers/ExampleValidators.js +0 -5
- package/components/form-core/test-helpers/getFormControlMembers.js +2 -2
- package/components/form-core/test-helpers/mimicUserInput.js +5 -1
- package/components/form-core/test-suites/FormRegistrationMixins.suite.js +65 -122
- package/components/form-core/test-suites/FormatMixin.suite.js +202 -227
- package/components/form-core/test-suites/InteractionStateMixin.suite.js +47 -60
- package/components/form-core/test-suites/NativeTextFieldMixin.suite.js +8 -11
- package/components/form-core/test-suites/ValidateMixin.suite.js +280 -359
- package/components/form-core/test-suites/ValidateMixinFeedbackPart.suite.js +112 -163
- package/components/form-core/test-suites/choice-group/ChoiceGroupMixin.suite.js +185 -218
- package/components/form-core/test-suites/choice-group/ChoiceInputMixin.suite.js +116 -109
- package/components/form-core/test-suites/choice-group/CustomChoiceGroupMixin.suite.js +36 -70
- package/components/form-core/test-suites/form-group/FormGroupMixin-input.suite.js +57 -65
- package/components/form-core/test-suites/form-group/FormGroupMixin.suite.js +664 -523
- package/components/form-core/translations/bg-BG.js +0 -1
- package/components/form-core/translations/cs-CZ.js +0 -1
- package/components/form-core/translations/de-DE.js +0 -1
- package/components/form-core/translations/en-AU.js +0 -1
- package/components/form-core/translations/en-GB.js +0 -1
- package/components/form-core/translations/en-US.js +0 -1
- package/components/form-core/translations/es-ES.js +0 -1
- package/components/form-core/translations/fr-BE.js +0 -1
- package/components/form-core/translations/fr-FR.js +0 -1
- package/components/form-core/translations/hu-HU.js +0 -1
- package/components/form-core/translations/it-IT.js +0 -1
- package/components/form-core/translations/nl-BE.js +0 -1
- package/components/form-core/translations/nl-NL.js +0 -1
- package/components/form-core/translations/pl-PL.js +0 -1
- package/components/form-core/translations/ro-RO.js +0 -1
- package/components/form-core/translations/ru-RU.js +0 -1
- package/components/form-core/translations/sk-SK.js +0 -1
- package/components/form-core/translations/tr-TR.js +0 -1
- package/components/form-core/translations/uk-UA.js +0 -1
- package/components/form-core/types/choice-group/ChoiceGroupMixinTypes.ts +5 -0
- package/components/form-integrations/test/dialog-integrations.test.js +1 -4
- package/components/form-integrations/test/form-group-methods.test.js +28 -31
- package/components/form-integrations/test/form-integrations.test.js +27 -28
- package/components/form-integrations/test/form-validation-integrations.test.js +21 -29
- package/components/form-integrations/test/helpers/umbrella-form.js +3 -5
- package/components/form-integrations/test/model-value-consistency.test.js +75 -77
- package/components/form-integrations/test/model-value-event.test.js +10 -20
- package/components/helpers/src/SbActionLogger.js +13 -17
- package/components/helpers/src/SbLocaleSwitcher.js +5 -5
- package/components/helpers/src/sortEachDepth.js +0 -2
- package/components/helpers/test/renderLitAsNode.test.js +0 -4
- package/components/helpers/test/sb-action-logger.test.js +24 -55
- package/components/icon/src/IconManager.js +0 -2
- package/components/icon/src/LionIcon.js +2 -7
- package/components/icon/src/icons.js +0 -2
- package/components/icon/test/IconManager.test.js +0 -15
- package/components/icon/test/hammer.svg.js +3 -4
- package/components/icon/test/heart.svg.js +3 -4
- package/components/icon/test/lion-icon.test.js +14 -43
- package/components/input/src/LionInput.js +2 -8
- package/components/input/test/input-integrations.test.js +0 -5
- package/components/input/test/lion-input-integrations.test.js +0 -4
- package/components/input/test/lion-input.test.js +28 -58
- package/components/input/test-helpers/getInputMembers.js +2 -2
- package/components/input-amount/src/LionInputAmount.js +37 -26
- package/components/input-amount/src/formatters.js +4 -5
- package/components/input-amount/src/parsers.js +0 -3
- package/components/input-amount/test/formatters.test.js +102 -80
- package/components/input-amount/test/lion-input-amount-integrations.test.js +0 -4
- package/components/input-amount/test/lion-input-amount.test.js +155 -164
- package/components/input-amount/test/parsers.test.js +33 -17
- package/components/input-amount/test/preprocessors.test.js +0 -3
- package/components/input-amount-dropdown/src/LionInputAmountDropdown.js +49 -59
- package/components/input-amount-dropdown/src/currencyUtil.js +8 -7
- package/components/input-amount-dropdown/src/parsers.js +0 -1
- package/components/input-amount-dropdown/src/validators.js +0 -1
- package/components/input-amount-dropdown/test/LionInputAmountDropdown.test.js +34 -36
- package/components/input-amount-dropdown/test/lion-input-amount-dropdown-integrations.test.js +18 -13
- package/components/input-amount-dropdown/test-helpers/mimicUserChangingDropdown.js +5 -1
- package/components/input-amount-dropdown/test-suites/LionInputAmountDropdown.suite.js +132 -107
- package/components/input-date/src/LionInputDate.js +4 -3
- package/components/input-date/test/lion-input-date-integrations.test.js +0 -3
- package/components/input-date/test/lion-input-date.test.js +19 -32
- package/components/input-datepicker/src/LionInputDatepicker.js +17 -29
- package/components/input-datepicker/src/localizeNamespaceLoader.js +1 -2
- package/components/input-datepicker/test/lion-input-datepicker-integrations.test.js +0 -3
- package/components/input-datepicker/test/lion-input-datepicker.test.js +88 -153
- package/components/input-datepicker/test-helpers/DatepickerInputObject.js +9 -12
- package/components/input-datepicker/test-suites/LionInputDatepicker.suite.js +6 -4
- package/components/input-datepicker/translations/bg-BG.js +0 -1
- package/components/input-datepicker/translations/cs-CZ.js +0 -1
- package/components/input-datepicker/translations/de-DE.js +0 -1
- package/components/input-datepicker/translations/en-AU.js +0 -1
- package/components/input-datepicker/translations/en-GB.js +0 -1
- package/components/input-datepicker/translations/en-US.js +0 -1
- package/components/input-datepicker/translations/es-ES.js +0 -1
- package/components/input-datepicker/translations/fr-BE.js +0 -1
- package/components/input-datepicker/translations/fr-FR.js +0 -1
- package/components/input-datepicker/translations/hu-HU.js +0 -1
- package/components/input-datepicker/translations/it-IT.js +0 -1
- package/components/input-datepicker/translations/nl-BE.js +0 -1
- package/components/input-datepicker/translations/nl-NL.js +0 -1
- package/components/input-datepicker/translations/pl-PL.js +0 -1
- package/components/input-datepicker/translations/ro-RO.js +0 -1
- package/components/input-datepicker/translations/ru-RU.js +0 -1
- package/components/input-datepicker/translations/sk-SK.js +0 -1
- package/components/input-datepicker/translations/tr-TR.js +0 -1
- package/components/input-datepicker/translations/uk-UA.js +0 -1
- package/components/input-email/test/lion-input-email-integrations.test.js +0 -2
- package/components/input-email/test/lion-input-email.test.js +1 -7
- package/components/input-file/src/FileHandle.js +0 -3
- package/components/input-file/src/LionInputFile.js +85 -83
- package/components/input-file/src/LionSelectedFileList.js +12 -12
- package/components/input-file/src/validators.js +10 -9
- package/components/input-file/test/FileValidators.test.js +170 -80
- package/components/input-file/test/lion-input-file.test.js +160 -244
- package/components/input-file/test/lion-selected-file-list.test.js +13 -22
- package/components/input-file/translations/bg-BG.js +0 -1
- package/components/input-file/translations/cs-CZ.js +0 -1
- package/components/input-file/translations/de-DE.js +0 -1
- package/components/input-file/translations/en-AU.js +0 -1
- package/components/input-file/translations/en-GB.js +0 -1
- package/components/input-file/translations/en-PH.js +0 -1
- package/components/input-file/translations/en-US.js +0 -1
- package/components/input-file/translations/en.js +2 -1
- package/components/input-file/translations/es-ES.js +0 -1
- package/components/input-file/translations/fr-BE.js +0 -1
- package/components/input-file/translations/fr-FR.js +0 -1
- package/components/input-file/translations/hu-HU.js +0 -1
- package/components/input-file/translations/id-ID.js +0 -1
- package/components/input-file/translations/id.js +2 -1
- package/components/input-file/translations/it-IT.js +0 -1
- package/components/input-file/translations/nl-BE.js +0 -1
- package/components/input-file/translations/nl-NL.js +0 -1
- package/components/input-file/translations/pl-PL.js +0 -1
- package/components/input-file/translations/ro-RO.js +0 -1
- package/components/input-file/translations/ru-RU.js +0 -1
- package/components/input-file/translations/sk-SK.js +0 -1
- package/components/input-file/translations/uk-UA.js +0 -1
- package/components/input-file/translations/zh-CN.js +0 -1
- package/components/input-iban/src/validators.js +6 -11
- package/components/input-iban/test/formatters.test.js +0 -3
- package/components/input-iban/test/lion-input-iban-integrations.test.js +0 -2
- package/components/input-iban/test/lion-input-iban.test.js +1 -9
- package/components/input-iban/test/parsers.test.js +0 -2
- package/components/input-iban/test/validators.test.js +0 -12
- package/components/input-iban/translations/bg-BG.js +0 -1
- package/components/input-iban/translations/cs-CZ.js +0 -1
- package/components/input-iban/translations/de-DE.js +0 -1
- package/components/input-iban/translations/en-AU.js +0 -1
- package/components/input-iban/translations/en-GB.js +0 -1
- package/components/input-iban/translations/en-US.js +0 -1
- package/components/input-iban/translations/es-ES.js +0 -1
- package/components/input-iban/translations/fr-BE.js +0 -1
- package/components/input-iban/translations/fr-FR.js +0 -1
- package/components/input-iban/translations/hu-HU.js +0 -1
- package/components/input-iban/translations/it-IT.js +0 -1
- package/components/input-iban/translations/nl-BE.js +0 -1
- package/components/input-iban/translations/nl-NL.js +0 -1
- package/components/input-iban/translations/pl-PL.js +0 -1
- package/components/input-iban/translations/ro-RO.js +0 -1
- package/components/input-iban/translations/ru-RU.js +0 -1
- package/components/input-iban/translations/sk-SK.js +0 -1
- package/components/input-iban/translations/uk-UA.js +0 -1
- package/components/input-range/src/LionInputRange.js +18 -19
- package/components/input-range/test/lion-input-range.test.js +23 -48
- package/components/input-range/translations/bg-BG.js +0 -1
- package/components/input-range/translations/cs-CZ.js +0 -1
- package/components/input-range/translations/de-DE.js +0 -1
- package/components/input-range/translations/en-AU.js +0 -1
- package/components/input-range/translations/en-GB.js +0 -1
- package/components/input-range/translations/en-PH.js +0 -1
- package/components/input-range/translations/en-US.js +0 -1
- package/components/input-range/translations/es-ES.js +0 -1
- package/components/input-range/translations/fr-BE.js +0 -1
- package/components/input-range/translations/fr-FR.js +0 -1
- package/components/input-range/translations/hu-HU.js +0 -1
- package/components/input-range/translations/it-IT.js +0 -1
- package/components/input-range/translations/nl-BE.js +0 -1
- package/components/input-range/translations/nl-NL.js +0 -1
- package/components/input-range/translations/pl-PL.js +0 -1
- package/components/input-range/translations/ro-RO.js +0 -1
- package/components/input-range/translations/ru-RU.js +0 -1
- package/components/input-range/translations/sk-SK.js +0 -1
- package/components/input-range/translations/uk-UA.js +0 -1
- package/components/input-range/translations/zh-CN.js +0 -1
- package/components/input-stepper/src/LionInputStepper.js +19 -38
- package/components/input-stepper/test/lion-input-stepper-integrations.test.js +0 -1
- package/components/input-stepper/test/lion-input-stepper.test.js +0 -1
- package/components/input-stepper/test-suites/lion-input-stepper.integration.suite.js +0 -2
- package/components/input-stepper/test-suites/lion-input-stepper.suite.js +56 -105
- package/components/input-stepper/translations/bg-BG.js +0 -1
- package/components/input-stepper/translations/cs-CZ.js +0 -1
- package/components/input-stepper/translations/de-DE.js +0 -1
- package/components/input-stepper/translations/en-AU.js +0 -1
- package/components/input-stepper/translations/en-GB.js +0 -1
- package/components/input-stepper/translations/en-US.js +0 -1
- package/components/input-stepper/translations/es-ES.js +0 -1
- package/components/input-stepper/translations/fr-BE.js +0 -1
- package/components/input-stepper/translations/fr-FR.js +0 -1
- package/components/input-stepper/translations/hu-HU.js +0 -1
- package/components/input-stepper/translations/it-IT.js +0 -1
- package/components/input-stepper/translations/nl-BE.js +0 -1
- package/components/input-stepper/translations/nl-NL.js +0 -1
- package/components/input-stepper/translations/pl-PL.js +0 -1
- package/components/input-stepper/translations/ro-RO.js +0 -1
- package/components/input-stepper/translations/ru-RU.js +0 -1
- package/components/input-stepper/translations/sk-SK.js +0 -1
- package/components/input-stepper/translations/uk-UA.js +0 -1
- package/components/input-tel/src/LionInputTel.js +53 -37
- package/components/input-tel/src/PhoneUtilManager.js +6 -4
- package/components/input-tel/src/formatters.js +12 -10
- package/components/input-tel/src/parsers.js +3 -3
- package/components/input-tel/src/preprocessors.js +15 -7
- package/components/input-tel/src/validators.js +4 -6
- package/components/input-tel/test/LionInputTel.test.js +4 -2
- package/components/input-tel/test/formatters.test.js +22 -10
- package/components/input-tel/test/parsers.test.js +40 -11
- package/components/input-tel/test/preprocessors.test.js +24 -13
- package/components/input-tel/test/validators.test.js +15 -13
- package/components/input-tel/test-helpers/mockPhoneUtilManager.js +7 -6
- package/components/input-tel/test-suites/LionInputTel.suite.js +33 -73
- package/components/input-tel/translations/bg-BG.js +0 -1
- package/components/input-tel/translations/cs-CZ.js +0 -1
- package/components/input-tel/translations/de-DE.js +0 -1
- package/components/input-tel/translations/en-AU.js +0 -1
- package/components/input-tel/translations/en-GB.js +0 -1
- package/components/input-tel/translations/en-US.js +0 -1
- package/components/input-tel/translations/es-ES.js +0 -1
- package/components/input-tel/translations/fr-BE.js +0 -1
- package/components/input-tel/translations/fr-FR.js +0 -1
- package/components/input-tel/translations/hu-HU.js +0 -1
- package/components/input-tel/translations/it-IT.js +0 -1
- package/components/input-tel/translations/nl-BE.js +0 -1
- package/components/input-tel/translations/nl-NL.js +0 -1
- package/components/input-tel/translations/pl-PL.js +0 -1
- package/components/input-tel/translations/ro-RO.js +0 -1
- package/components/input-tel/translations/ru-RU.js +0 -1
- package/components/input-tel/translations/sk-SK.js +0 -1
- package/components/input-tel/translations/uk-UA.js +0 -1
- package/components/input-tel-dropdown/src/LionInputTelDropdown.js +10 -28
- package/components/input-tel-dropdown/src/regionCodeToLocale.js +3 -1
- package/components/input-tel-dropdown/test/LionInputTelDropdown.test.js +31 -38
- package/components/input-tel-dropdown/test/regionCodeToLocale.test.js +0 -1
- package/components/input-tel-dropdown/test-helpers/mimicUserChangingDropdown.js +5 -1
- package/components/input-tel-dropdown/test-suites/LionInputTelDropdown--parentheses.suite.js +16 -11
- package/components/input-tel-dropdown/test-suites/LionInputTelDropdown.suite.js +54 -79
- package/components/listbox/src/LionListbox.js +4 -1
- package/components/listbox/src/LionOption.js +8 -7
- package/components/listbox/src/LionOptions.js +0 -3
- package/components/listbox/src/ListboxMixin.js +801 -819
- package/components/listbox/test/lion-listbox.test.js +0 -1
- package/components/listbox/test/lion-option.test.js +53 -64
- package/components/listbox/test/lion-options.test.js +3 -4
- package/components/listbox/test-helpers/getListboxMembers.js +6 -3
- package/components/listbox/test-suites/ListboxMixin.suite.js +101 -261
- package/components/listbox/types/ListboxMixinTypes.ts +7 -1
- package/components/localize/src/LocalizeManager.js +40 -40
- package/components/localize/src/LocalizeMixin.js +130 -157
- package/components/localize/src/date/formatDate.js +1 -5
- package/components/localize/src/date/getDateFormatBasedOnLocale.js +5 -3
- package/components/localize/src/date/getMonthNames.js +3 -5
- package/components/localize/src/date/getWeekdayNames.js +1 -5
- package/components/localize/src/date/parseDate.js +5 -20
- package/components/localize/src/date/utils/normalizeIntlDate.js +0 -7
- package/components/localize/src/getLocalizeManager.js +0 -3
- package/components/localize/src/number/formatNumber.js +3 -7
- package/components/localize/src/number/formatNumberToParts.js +52 -18
- package/components/localize/src/number/getCurrencyName.js +5 -5
- package/components/localize/src/number/getFractionDigits.js +4 -4
- package/components/localize/src/number/getSeparatorsFromNumber.js +1 -3
- package/components/localize/src/number/parseNumber.js +0 -3
- package/components/localize/src/number/utils/normalize-format-number-to-parts/forceAddGroupSeparators.js +0 -1
- package/components/localize/src/number/utils/normalize-format-number-to-parts/forceSpaceBetweenCurrencyCodeAndNumber.js +4 -1
- package/components/localize/test/LocalizeManager.test.js +385 -278
- package/components/localize/test/LocalizeMixin.test.js +28 -112
- package/components/localize/test/date/formatDate.test.js +18 -48
- package/components/localize/test/date/getDateFormatBasedOnLocale.test.js +0 -3
- package/components/localize/test/date/getMonthNames.test.js +27 -12
- package/components/localize/test/date/getWeekdayNames.test.js +93 -49
- package/components/localize/test/date/normalizeDateTime.test.js +0 -2
- package/components/localize/test/date/parseDate.test.js +12 -16
- package/components/localize/test/getLocalizeManager.test.js +0 -3
- package/components/localize/test/isLocalizeESModule.test.js +32 -13
- package/components/localize/test/localize.test.js +0 -4
- package/components/localize/test/number/formatNumber.test.js +215 -106
- package/components/localize/test/number/formatNumberToParts.test.js +31 -38
- package/components/localize/test/number/getCurrencyName.test.js +20 -6
- package/components/localize/test/number/getDecimalSeparator.test.js +5 -4
- package/components/localize/test/number/getFractionDigits.test.js +0 -2
- package/components/localize/test/number/getGroupSeparator.test.js +0 -2
- package/components/localize/test/number/getSeparatorsFromNumber.test.js +5 -3
- package/components/localize/test/number/parseNumber.test.js +123 -56
- package/components/localize/test/side-effect-free-entrypoint.test.js +0 -6
- package/components/localize/test-helpers/fake-imports.js +11 -6
- package/components/localize/test-helpers/localizeTearDown.js +0 -1
- package/components/menu/README.md +360 -0
- package/components/menu/src/InteractiveListMixin.js +866 -0
- package/components/menu/src/LionMenu.js +423 -0
- package/components/menu/src/MoreButtonMenuMixin.js +272 -0
- package/components/menu/src/MultiLevelListMixin.js +306 -0
- package/components/menu/src/utils/isInView.js +25 -0
- package/components/menu/src/utils/listItemInteractions.js +124 -0
- package/components/menu/test/InteractiveListMixin.test.js +2 -0
- package/components/menu/test/MoreButtonMenuMixin.test.js +5 -0
- package/components/menu/test/MultiLevelListMixin.test.js +2 -0
- package/components/menu/test/lion-menu-interactions.test.js +2 -0
- package/components/menu/test/lion-menu.test.js +18 -0
- package/components/menu/test-helpers/mimicKeyPress.js +19 -0
- package/components/menu/test-suites/InteractiveListMixin.suite.js +498 -0
- package/components/menu/test-suites/LionMenu.suite.js +107 -0
- package/components/menu/test-suites/LionMenuInteractions.suite.js +561 -0
- package/components/menu/test-suites/MoreButtonMenuMixin.suite.js +365 -0
- package/components/menu/test-suites/MultiLevelListMixin.suite.js +291 -0
- package/components/menu/types/InteractiveListMixinTypes.ts +126 -0
- package/components/menu/types/MoreButtonMenuMixinTypes.ts +51 -0
- package/components/menu/types/MultiLevelListMixinTypes.ts +28 -0
- package/components/menu/types/OverlayWithListInvokerMixinTypes.ts +61 -0
- package/components/overlays/NEXT.md +49 -0
- package/components/overlays/src/ArrowMixin.js +111 -127
- package/components/overlays/src/OverlayController.js +440 -246
- package/components/overlays/src/OverlayMixin.js +130 -68
- package/components/overlays/src/OverlaysManager.js +30 -32
- package/components/overlays/src/configurations/visibility-trigger-partials/withClickInteraction.js +0 -1
- package/components/overlays/src/configurations/visibility-trigger-partials/withHoverInteraction.js +11 -11
- package/components/overlays/src/configurations/withBottomSheetConfig.js +12 -13
- package/components/overlays/src/configurations/withDropdownConfig.js +4 -2
- package/components/overlays/src/configurations/withModalDialogConfig.js +12 -13
- package/components/overlays/src/configurations/withPopoverConfig.js +27 -25
- package/components/overlays/src/configurations/withTooltipConfig.js +15 -13
- package/components/overlays/src/overlayDocumentStyle.js +1 -1
- package/components/overlays/src/overlayShadowDomStyle.js +0 -1
- package/components/overlays/src/singleton.js +0 -2
- package/components/overlays/src/utils/adopt-styles.js +19 -19
- package/components/overlays/src/utils/deep-contains.js +7 -6
- package/components/overlays/src/utils/get-focusable-elements.js +7 -10
- package/components/overlays/src/utils/inert-siblings.js +2 -4
- package/components/overlays/src/utils/is-equal-config.js +14 -6
- package/components/overlays/src/utils/is-visible.js +0 -1
- package/components/overlays/src/utils/simulate-tab.js +1 -4
- package/components/overlays/src/utils/sort-by-tabindex.js +2 -4
- package/components/overlays/test/ArrowMixin.test.js +18 -30
- package/components/overlays/test/OverlayController.test.js +551 -533
- package/components/overlays/test/OverlayMixin.test.js +0 -2
- package/components/overlays/test/OverlaysManager.test.js +30 -35
- package/components/overlays/test/global-positioning.test.js +6 -10
- package/components/overlays/test/local-positioning.test.js +101 -103
- package/components/overlays/test/utils-tests/active-element.test.js +12 -27
- package/components/overlays/test/utils-tests/adopt-styles.test.js +25 -56
- package/components/overlays/test/utils-tests/deep-contains.test.js +73 -74
- package/components/overlays/test/utils-tests/get-focusable-elements.test.js +6 -23
- package/components/overlays/test/utils-tests/is-equal-config.test.js +32 -13
- package/components/overlays/test/utils-tests/visibility.test.js +44 -79
- package/components/overlays/test-helpers/createShadowHost.js +5 -3
- package/components/overlays/test-helpers/normalizeTransformStyle.js +2 -4
- package/components/overlays/test-suites/OverlayMixin.suite.js +159 -188
- package/components/overlays/test-suites/WithHoverInteraction.suite.js +96 -79
- package/components/overlays/translations/bg-BG.js +0 -1
- package/components/overlays/translations/cs-CZ.js +0 -1
- package/components/overlays/translations/de-DE.js +0 -1
- package/components/overlays/translations/en-AU.js +0 -1
- package/components/overlays/translations/en-GB.js +0 -1
- package/components/overlays/translations/en-US.js +0 -1
- package/components/overlays/translations/es-ES.js +0 -1
- package/components/overlays/translations/fr-BE.js +0 -1
- package/components/overlays/translations/fr-FR.js +0 -1
- package/components/overlays/translations/hu-HU.js +0 -1
- package/components/overlays/translations/it-IT.js +0 -1
- package/components/overlays/translations/nl-BE.js +0 -1
- package/components/overlays/translations/nl-NL.js +0 -1
- package/components/overlays/translations/pl-PL.js +0 -1
- package/components/overlays/translations/ro-RO.js +0 -1
- package/components/overlays/translations/ru-RU.js +0 -1
- package/components/overlays/translations/sk-SK.js +0 -1
- package/components/overlays/translations/tr-TR.js +0 -1
- package/components/overlays/translations/uk-UA.js +0 -1
- package/components/overlays/types/ArrowMixinTypes.ts +1 -3
- package/components/overlays/types/OverlayConfig.ts +20 -5
- package/components/overlays/types/OverlayMixinTypes.ts +2 -0
- package/components/pagination/src/LionPagination.js +9 -12
- package/components/pagination/test/lion-pagination.test.js +18 -50
- package/components/progress-indicator/src/LionProgressIndicator.js +10 -12
- package/components/progress-indicator/test/lion-progress-indicator.test.js +1 -22
- package/components/radio-group/src/LionRadioGroup.js +1 -2
- package/components/radio-group/test/lion-radio-group-integrations.test.js +0 -1
- package/components/radio-group/test/lion-radio-group.test.js +27 -27
- package/components/radio-group/test/lion-radio-integrations.test.js +3 -2
- package/components/radio-group/test/lion-radio.test.js +30 -16
- package/components/select/src/LionSelect.js +12 -13
- package/components/select/test/lion-select.test.js +7 -12
- package/components/select-rich/src/LionSelectInvoker.js +18 -11
- package/components/select-rich/src/LionSelectRich.js +32 -43
- package/components/select-rich/test/demos.screenshots-test.js +40 -9
- package/components/select-rich/test/lion-select-invoker.test.js +26 -43
- package/components/select-rich/test/lion-select-listbox-suite-integration.test.js +3 -3
- package/components/select-rich/test/lion-select-rich-dialog-integration.test.js +4 -9
- package/components/select-rich/test/lion-select-rich-interaction.test.js +154 -101
- package/components/select-rich/test/lion-select-rich-upgrade.test.js +26 -0
- package/components/select-rich/test/lion-select-rich.test.js +153 -195
- package/components/select-rich/test-helpers/getSelectRichMembers.js +4 -1
- package/components/steps/src/LionStep.js +21 -12
- package/components/steps/src/LionSteps.js +25 -25
- package/components/steps/test/lion-step.test.js +18 -25
- package/components/steps/test/lion-steps.test.js +45 -78
- package/components/switch/src/LionSwitch.js +2 -7
- package/components/switch/src/LionSwitchButton.js +5 -6
- package/components/switch/test/lion-switch-button.test.js +16 -28
- package/components/switch/test/lion-switch.test.js +17 -31
- package/components/tabs/src/LionTabs.js +25 -28
- package/components/tabs/test/lion-tabs.test.js +156 -154
- package/components/textarea/src/LionTextarea.js +4 -23
- package/components/textarea/test/lion-textarea-integrations.test.js +0 -5
- package/components/textarea/test/lion-textarea.test.js +2 -28
- package/components/tooltip/src/LionTooltip.js +6 -6
- package/components/tooltip/test/lion-tooltip.test.js +75 -102
- package/components/validate-messages/src/getLocalizedMessage.js +8 -7
- package/components/validate-messages/src/loadDefaultFeedbackMessages.js +3 -1
- package/components/validate-messages/src/loadDefaultFeedbackMessagesNoSideEffects.js +9 -5
- package/components/validate-messages/src/per-entrypoint/loadComboboxMessagesNoSideEffects.js +5 -2
- package/components/validate-messages/src/per-entrypoint/loadFormCoreMessagesNoSideEffects.js +99 -35
- package/components/validate-messages/src/per-entrypoint/loadInputTelMessagesNoSideEffects.js +4 -3
- package/components/validate-messages/test/loadDefaultFeedbackMessages.test.js +5 -3
- package/components/validate-messages/test/loadDefaultFeedbackMessagesNoSideEffects.test.js +80 -45
- package/components/validate-messages/translations/bg-BG.js +0 -1
- package/components/validate-messages/translations/cs-CZ.js +0 -1
- package/components/validate-messages/translations/de-DE.js +0 -1
- package/components/validate-messages/translations/en-AU.js +0 -1
- package/components/validate-messages/translations/en-GB.js +0 -1
- package/components/validate-messages/translations/en-PH.js +0 -1
- package/components/validate-messages/translations/en-US.js +0 -1
- package/components/validate-messages/translations/es-ES.js +0 -1
- package/components/validate-messages/translations/fr-BE.js +0 -1
- package/components/validate-messages/translations/fr-FR.js +0 -1
- package/components/validate-messages/translations/hu-HU.js +0 -1
- package/components/validate-messages/translations/it-IT.js +0 -1
- package/components/validate-messages/translations/nl-BE.js +0 -1
- package/components/validate-messages/translations/nl-NL.js +0 -1
- package/components/validate-messages/translations/pl-PL.js +0 -1
- package/components/validate-messages/translations/ro-RO.js +0 -1
- package/components/validate-messages/translations/ru-RU.js +0 -1
- package/components/validate-messages/translations/sk-SK.js +0 -1
- package/components/validate-messages/translations/tr-TR.js +0 -1
- package/components/validate-messages/translations/uk-UA.js +0 -1
- package/custom-elements.json +3312 -206
- package/dist-types/components/combobox/src/LionCombobox.d.ts +1 -1
- package/dist-types/components/combobox/src/LionCombobox.d.ts.map +1 -1
- package/dist-types/components/core/src/SlotMixin.d.ts +6 -1
- package/dist-types/components/core/src/SlotMixin.d.ts.map +1 -1
- package/dist-types/components/core/types/SlotMixinTypes.d.ts +5 -1
- package/dist-types/components/core/types/SlotMixinTypes.d.ts.map +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/LionField.d.ts +3 -1
- package/dist-types/components/form-core/src/LionField.d.ts.map +1 -1
- package/dist-types/components/form-core/src/choice-group/ChoiceGroupMixin.d.ts.map +1 -1
- package/dist-types/components/form-core/types/choice-group/ChoiceGroupMixinTypes.d.ts +5 -0
- package/dist-types/components/form-core/types/choice-group/ChoiceGroupMixinTypes.d.ts.map +1 -1
- package/dist-types/components/input-amount/src/LionInputAmount.d.ts +3 -1
- package/dist-types/components/input-amount/src/LionInputAmount.d.ts.map +1 -1
- package/dist-types/components/input-amount/src/formatters.d.ts +6 -4
- package/dist-types/components/input-amount/src/formatters.d.ts.map +1 -1
- package/dist-types/components/input-datepicker/src/LionInputDatepicker.d.ts +1 -1
- package/dist-types/components/input-tel/src/LionInputTel.d.ts +6 -6
- package/dist-types/components/input-tel/src/LionInputTel.d.ts.map +1 -1
- package/dist-types/components/input-tel/src/PhoneUtilManager.d.ts +2 -2
- package/dist-types/components/input-tel/src/PhoneUtilManager.d.ts.map +1 -1
- package/dist-types/components/input-tel/src/formatters.d.ts +2 -2
- package/dist-types/components/input-tel/src/formatters.d.ts.map +1 -1
- package/dist-types/components/input-tel/src/preprocessors.d.ts +2 -2
- package/dist-types/components/input-tel/src/preprocessors.d.ts.map +1 -1
- package/dist-types/components/input-tel/test/validators.test.d.ts +1 -1
- package/dist-types/components/input-tel/test/validators.test.d.ts.map +1 -1
- package/dist-types/components/listbox/src/LionOption.d.ts +5 -2
- package/dist-types/components/listbox/src/LionOption.d.ts.map +1 -1
- package/dist-types/components/listbox/src/ListboxMixin.d.ts.map +1 -1
- package/dist-types/components/listbox/types/ListboxMixinTypes.d.ts +7 -1
- package/dist-types/components/listbox/types/ListboxMixinTypes.d.ts.map +1 -1
- package/dist-types/components/menu/src/InteractiveListMixin.d.ts +35 -0
- package/dist-types/components/menu/src/InteractiveListMixin.d.ts.map +1 -0
- package/dist-types/components/menu/src/LionMenu.d.ts +129 -0
- package/dist-types/components/menu/src/LionMenu.d.ts.map +1 -0
- package/dist-types/components/menu/src/MoreButtonMenuMixin.d.ts +8 -0
- package/dist-types/components/menu/src/MoreButtonMenuMixin.d.ts.map +1 -0
- package/dist-types/components/menu/src/MultiLevelListMixin.d.ts +7 -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-interactions.test.d.ts +2 -0
- package/dist-types/components/menu/test/lion-menu-interactions.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-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 +11 -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/LionMenuInteractions.suite.d.ts +5 -0
- package/dist-types/components/menu/test-suites/LionMenuInteractions.suite.d.ts.map +1 -0
- package/dist-types/components/menu/test-suites/MoreButtonMenuMixin.suite.d.ts +11 -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/menu/types/InteractiveListMixinTypes.d.ts +72 -0
- package/dist-types/components/menu/types/InteractiveListMixinTypes.d.ts.map +1 -0
- package/dist-types/components/menu/types/MoreButtonMenuMixinTypes.d.ts +30 -0
- package/dist-types/components/menu/types/MoreButtonMenuMixinTypes.d.ts.map +1 -0
- package/dist-types/components/menu/types/MultiLevelListMixinTypes.d.ts +16 -0
- package/dist-types/components/menu/types/MultiLevelListMixinTypes.d.ts.map +1 -0
- package/dist-types/components/menu/types/OverlayWithListInvokerMixinTypes.d.ts +35 -0
- package/dist-types/components/menu/types/OverlayWithListInvokerMixinTypes.d.ts.map +1 -0
- package/dist-types/components/overlays/src/OverlayController.d.ts +22 -5
- 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/OverlaysManager.d.ts.map +1 -1
- package/dist-types/components/overlays/src/overlayDocumentStyle.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/LionSelectInvoker.d.ts +3 -1
- package/dist-types/components/select-rich/src/LionSelectInvoker.d.ts.map +1 -1
- package/dist-types/components/select-rich/src/LionSelectRich.d.ts +13 -2
- package/dist-types/components/select-rich/src/LionSelectRich.d.ts.map +1 -1
- package/dist-types/components/select-rich/test/lion-select-rich-interaction.test.d.ts.map +1 -1
- package/dist-types/components/select-rich/test/lion-select-rich-upgrade.test.d.ts +2 -0
- package/dist-types/components/select-rich/test/lion-select-rich-upgrade.test.d.ts.map +1 -0
- 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.d.ts +2 -0
- package/dist-types/exports/define/lion-menu.d.ts.map +1 -0
- package/dist-types/exports/define/lion-menuitem.d.ts +2 -0
- package/dist-types/exports/define/lion-menuitem.d.ts.map +1 -0
- 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 +3 -0
- package/dist-types/exports/menu.d.ts.map +1 -0
- package/dist-types/exports/overlays.d.ts +6 -0
- package/dist-types/exports/overlays.d.ts.map +1 -1
- package/dist-types/tsconfig.tsbuildinfo +1 -1
- package/docs/components/accordion/overview.md +2 -2
- package/docs/components/accordion/reference.md +2 -2
- package/docs/components/accordion/use-cases.md +2 -2
- package/docs/components/button/examples.md +2 -2
- package/docs/components/button/extensions.md +2 -2
- package/docs/components/button/overview.md +2 -2
- package/docs/components/button/use-cases.md +2 -2
- package/docs/components/calendar/overview.md +2 -2
- package/docs/components/calendar/use-cases.md +2 -2
- package/docs/components/checkbox-group/overview.md +4 -4
- package/docs/components/checkbox-group/use-cases.md +2 -2
- package/docs/components/collapsible/examples.md +2 -2
- package/docs/components/collapsible/overview.md +3 -3
- package/docs/components/collapsible/use-cases.md +2 -2
- package/docs/components/combobox/api-table.md +53 -39
- package/docs/components/combobox/extensions.md +2 -2
- package/docs/components/combobox/overview.md +3 -3
- package/docs/components/combobox/use-cases.md +3 -3
- package/docs/components/dialog/api-table.md +32 -6
- package/docs/components/dialog/overview.md +3 -3
- package/docs/components/dialog/use-cases.md +2 -2
- package/docs/components/drawer/overview.md +2 -2
- package/docs/components/drawer/use-cases.md +2 -2
- package/docs/components/fieldset/overview.md +7 -7
- package/docs/components/fieldset/use-cases.md +2 -2
- package/docs/components/form/overview.md +5 -5
- package/docs/components/form/use-cases.md +4 -4
- package/docs/components/icon/overview.md +2 -2
- package/docs/components/icon/use-cases.md +3 -3
- package/docs/components/input/overview.md +3 -3
- package/docs/components/input/use-cases.md +2 -2
- package/docs/components/input-amount/api-table.md +9 -7
- package/docs/components/input-amount/overview.md +5 -5
- package/docs/components/input-amount/use-cases.md +17 -6
- package/docs/components/input-amount-dropdown/api-table.md +2 -0
- package/docs/components/input-amount-dropdown/use-cases.md +2 -2
- package/docs/components/input-date/overview.md +5 -5
- package/docs/components/input-date/use-cases.md +2 -2
- package/docs/components/input-datepicker/api-table.md +63 -45
- package/docs/components/input-datepicker/overview.md +7 -7
- package/docs/components/input-datepicker/use-cases.md +2 -2
- package/docs/components/input-email/overview.md +4 -4
- package/docs/components/input-email/use-cases.md +2 -2
- package/docs/components/input-file/overview.md +3 -3
- package/docs/components/input-file/use-cases.md +2 -2
- package/docs/components/input-iban/overview.md +4 -4
- package/docs/components/input-iban/use-cases.md +2 -2
- package/docs/components/input-range/overview.md +4 -4
- package/docs/components/input-range/use-cases.md +2 -2
- package/docs/components/input-stepper/overview.md +3 -3
- package/docs/components/input-stepper/use-cases.md +2 -2
- package/docs/components/input-tel/overview.md +3 -3
- package/docs/components/input-tel/use-cases.md +8 -8
- package/docs/components/input-tel-dropdown/extensions.md +2 -2
- package/docs/components/input-tel-dropdown/overview.md +3 -3
- package/docs/components/input-tel-dropdown/use-cases.md +2 -2
- package/docs/components/listbox/overview.md +2 -2
- package/docs/components/listbox/use-cases.md +3 -3
- package/docs/components/menu/api-table.md +44 -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/migration.md +129 -0
- package/docs/components/menu/overview.md +448 -0
- package/docs/components/menu/src/DemoNavigationBar.js +441 -0
- package/docs/components/menu/src/DemoSpinButton.js +215 -0
- package/docs/components/menu/src/DemoToolbar.js +101 -0
- package/docs/components/menu/src/DemoTree.js +55 -0
- package/docs/components/menu/src/navigation-bar-types.js +41 -0
- package/docs/components/menu/use-cases.md +74 -0
- package/docs/components/pagination/overview.md +2 -2
- package/docs/components/pagination/use-cases.md +2 -2
- package/docs/components/progress-indicator/examples.md +2 -2
- package/docs/components/progress-indicator/overview.md +2 -2
- package/docs/components/radio-group/overview.md +5 -5
- package/docs/components/radio-group/use-cases.md +2 -2
- package/docs/components/select/overview.md +2 -2
- package/docs/components/select/use-cases.md +3 -3
- package/docs/components/select-rich/api-table.md +51 -33
- package/docs/components/select-rich/examples.md +2 -2
- package/docs/components/select-rich/overview.md +2 -2
- package/docs/components/select-rich/use-cases.md +4 -4
- package/docs/components/steps/overview.md +2 -2
- package/docs/components/steps/use-cases.md +2 -2
- package/docs/components/switch/overview.md +2 -2
- package/docs/components/switch/reference.md +2 -2
- package/docs/components/switch/use-cases.md +2 -2
- package/docs/components/tabs/examples.md +3 -3
- package/docs/components/tabs/overview.md +2 -2
- package/docs/components/tabs/use-cases.md +2 -2
- package/docs/components/textarea/overview.md +2 -2
- package/docs/components/textarea/use-cases.md +2 -2
- package/docs/components/tooltip/api-table.md +33 -7
- package/docs/components/tooltip/examples.md +2 -2
- package/docs/components/tooltip/overview.md +2 -2
- package/docs/components/tooltip/use-cases.md +2 -2
- package/docs/fundamentals/index.md +4 -4
- package/docs/fundamentals/node-tools/babel-plugin-extend-docs/index.md +2 -2
- package/docs/fundamentals/node-tools/babel-plugin-extend-docs/overview.md +2 -2
- package/docs/fundamentals/node-tools/providence-analytics/index.md +2 -2
- package/docs/fundamentals/node-tools/providence-analytics/overview.md +3 -3
- package/docs/fundamentals/node-tools/publish-docs/index.md +2 -2
- package/docs/fundamentals/node-tools/publish-docs/overview.md +5 -5
- package/docs/fundamentals/node-tools/remark-extend/index.md +2 -2
- package/docs/fundamentals/node-tools/remark-extend/overview.md +2 -2
- package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/index.md +2 -2
- package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +4 -4
- package/docs/fundamentals/rationales/TypeScript.md +62 -2
- package/docs/fundamentals/rationales/accessibility.md +5 -5
- package/docs/fundamentals/rationales/side-effects.md +2 -2
- package/docs/fundamentals/rationales/versioning.md +2 -2
- package/docs/fundamentals/systems/core/SlotMixin.md +3 -3
- package/docs/fundamentals/systems/core/index.md +2 -2
- package/docs/fundamentals/systems/core/overview.md +3 -3
- package/docs/fundamentals/systems/form/formatting-and-parsing.md +6 -6
- package/docs/fundamentals/systems/form/index.md +2 -2
- package/docs/fundamentals/systems/form/interaction-states.md +2 -2
- package/docs/fundamentals/systems/form/model-value.md +3 -3
- package/docs/fundamentals/systems/form/overview.md +30 -30
- package/docs/fundamentals/systems/form/styling.md +2 -2
- package/docs/fundamentals/systems/form/use-cases.md +2 -2
- package/docs/fundamentals/systems/form/validate.md +4 -4
- package/docs/fundamentals/systems/icon/index.md +2 -2
- package/docs/fundamentals/systems/icon/overview.md +2 -2
- package/docs/fundamentals/systems/localize/dates.md +2 -2
- package/docs/fundamentals/systems/localize/index.md +2 -2
- package/docs/fundamentals/systems/localize/numbers.md +2 -2
- package/docs/fundamentals/systems/localize/overview.md +6 -6
- package/docs/fundamentals/systems/localize/rationale.md +2 -2
- package/docs/fundamentals/systems/localize/text.md +2 -2
- package/docs/fundamentals/systems/localize/use-cases.md +2 -2
- package/docs/fundamentals/systems/overlays/_edge-cases.md +2 -2
- package/docs/fundamentals/systems/overlays/api-table.md +46 -43
- package/docs/fundamentals/systems/overlays/configuration.md +4 -4
- package/docs/fundamentals/systems/overlays/index.md +2 -2
- package/docs/fundamentals/systems/overlays/overview.md +7 -7
- package/docs/fundamentals/systems/overlays/rationale.md +2 -2
- package/docs/fundamentals/systems/overlays/use-cases.md +4 -4
- package/docs/fundamentals/tools/ajax/index.md +2 -2
- package/docs/fundamentals/tools/ajax/overview.md +2 -2
- package/docs/fundamentals/tools/ajax/use-cases.md +2 -2
- package/docs/fundamentals/tools/helpers/action-logger.md +2 -2
- package/docs/fundamentals/tools/helpers/index.md +2 -2
- package/docs/fundamentals/tools/helpers/overview.md +3 -3
- package/docs/fundamentals/tools/singleton-manager/example-complex/index.md +2 -2
- package/docs/fundamentals/tools/singleton-manager/example-fail/index.md +2 -2
- package/docs/fundamentals/tools/singleton-manager/example-success/index.md +2 -2
- package/docs/fundamentals/tools/singleton-manager/index.md +2 -2
- package/docs/fundamentals/tools/singleton-manager/overview.md +6 -6
- package/docs/guides/how-to/create-a-custom-field.md +7 -7
- package/docs/guides/how-to/create-a-form.md +6 -6
- package/docs/guides/how-to/extend-a-native-input.md +4 -4
- package/docs/guides/how-to/get-started.md +2 -2
- package/docs/guides/how-to/index.md +1 -1
- package/docs/guides/index.md +8 -8
- package/docs/guides/principles/definitions-and-terms.md +2 -2
- package/docs/guides/principles/index.md +5 -5
- package/docs/guides/principles/scoped-elements.md +2 -2
- package/docs/guides/principles/styling.md +3 -3
- package/docs/guides/principles/subclasser-apis.md +2 -2
- package/exports/define/lion-accordion.js +0 -1
- package/exports/define/lion-button-reset.js +0 -1
- package/exports/define/lion-button-submit.js +0 -1
- package/exports/define/lion-button.js +0 -1
- package/exports/define/lion-calendar.js +0 -1
- package/exports/define/lion-checkbox-group.js +0 -1
- package/exports/define/lion-checkbox-indeterminate.js +0 -1
- package/exports/define/lion-checkbox.js +0 -1
- package/exports/define/lion-collapsible.js +0 -1
- package/exports/define/lion-combobox.js +0 -1
- package/exports/define/lion-dialog.js +0 -1
- package/exports/define/lion-drawer.js +0 -1
- package/exports/define/lion-field.js +0 -1
- package/exports/define/lion-fieldset.js +0 -1
- package/exports/define/lion-form.js +0 -1
- package/exports/define/lion-icon.js +0 -1
- package/exports/define/lion-input-amount-dropdown.js +0 -1
- package/exports/define/lion-input-amount.js +0 -1
- package/exports/define/lion-input-date.js +0 -1
- package/exports/define/lion-input-datepicker.js +0 -1
- package/exports/define/lion-input-email.js +0 -1
- package/exports/define/lion-input-file.js +0 -1
- package/exports/define/lion-input-iban.js +0 -1
- package/exports/define/lion-input-range.js +0 -1
- package/exports/define/lion-input-stepper.js +0 -1
- package/exports/define/lion-input-tel-dropdown.js +0 -1
- package/exports/define/lion-input-tel.js +0 -1
- package/exports/define/lion-input.js +0 -1
- package/exports/define/lion-item.js +2 -0
- package/exports/define/lion-listbox.js +0 -1
- package/exports/define/lion-menu.js +2 -0
- package/exports/define/lion-menuitem.js +2 -0
- package/exports/define/lion-option.js +0 -1
- package/exports/define/lion-options.js +0 -1
- package/exports/define/lion-pagination.js +0 -1
- package/exports/define/lion-progress-indicator.js +0 -1
- package/exports/define/lion-radio-group.js +0 -1
- package/exports/define/lion-radio.js +0 -1
- package/exports/define/lion-select-invoker.js +0 -1
- package/exports/define/lion-select-rich.js +0 -1
- package/exports/define/lion-select.js +0 -1
- package/exports/define/lion-selected-file-list.js +0 -1
- package/exports/define/lion-step.js +0 -1
- package/exports/define/lion-steps.js +0 -1
- package/exports/define/lion-switch-button.js +0 -1
- package/exports/define/lion-switch.js +0 -1
- package/exports/define/lion-tabs.js +0 -1
- package/exports/define/lion-textarea.js +0 -1
- package/exports/define/lion-tooltip.js +0 -1
- package/exports/define/lion-validation-feedback.js +0 -1
- package/exports/define-helpers/sb-action-logger.js +0 -1
- package/exports/define-helpers/sb-locale-switcher.js +0 -1
- package/exports/form-core.js +0 -8
- package/exports/localize-no-side-effects.js +0 -1
- package/exports/localize.js +0 -2
- package/exports/menu-test-suites.js +4 -0
- package/exports/menu.js +3 -0
- package/exports/overlays.js +6 -4
- package/generated/awesome-phonenumber/LICENSE +22 -0
- package/generated/awesome-phonenumber/LICENSE.closure-library +176 -0
- package/generated/awesome-phonenumber/LICENSE.libphonenumber +176 -0
- package/generated/awesome-phonenumber/checksums.json +6 -0
- package/generated/awesome-phonenumber/index-esm.mjs +817 -0
- package/generated/awesome-phonenumber/index.d.ts +227 -0
- package/generated/awesome-phonenumber/index.js +45 -0
- package/generated/awesome-phonenumber/lib/index.js +710 -0
- package/generated/awesome-phonenumber/package.json +9 -0
- package/generated/awesome-phonenumber/provenance.json +13 -0
- package/menu-test-suites.js +4 -0
- package/menu.js +3 -0
- package/overlays.js +6 -0
- package/package.json +35 -6
- package/vscode.html-custom-data.json +76 -8
- package/web-types.json +202 -17
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
html,
|
|
15
15
|
waitUntil,
|
|
16
16
|
} from '@open-wc/testing';
|
|
17
|
-
|
|
18
17
|
import { isActiveElement } from '../../core/test-helpers/isActiveElement.js';
|
|
19
18
|
import { createShadowHost } from '../test-helpers/createShadowHost.js';
|
|
20
19
|
import { _adoptStyleUtils } from '../src/utils/adopt-styles.js';
|
|
@@ -45,7 +44,9 @@ async function mimicEscapePress(element) {
|
|
|
45
44
|
}
|
|
46
45
|
|
|
47
46
|
// Send the event
|
|
48
|
-
await sendKeys({
|
|
47
|
+
await sendKeys({
|
|
48
|
+
press: 'Escape',
|
|
49
|
+
});
|
|
49
50
|
// Wait for at least a microtask, so that possible property effects are performed
|
|
50
51
|
await aTimeout(0);
|
|
51
52
|
}
|
|
@@ -55,7 +56,7 @@ async function mimicEscapePress(element) {
|
|
|
55
56
|
* @returns {boolean}
|
|
56
57
|
*/
|
|
57
58
|
function isRegisteredOnManager(ctrlToFind) {
|
|
58
|
-
return Boolean(ctrlToFind.manager?.list?.find(ctrl => ctrlToFind === ctrl));
|
|
59
|
+
return Boolean(ctrlToFind.manager?.list?.find((ctrl) => ctrlToFind === ctrl));
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
/**
|
|
@@ -84,7 +85,7 @@ function getProtectedMembers(overlayControllerEl) {
|
|
|
84
85
|
/**
|
|
85
86
|
* @param {HTMLElement} element
|
|
86
87
|
* */
|
|
87
|
-
const isInViewport = element => {
|
|
88
|
+
const isInViewport = (element) => {
|
|
88
89
|
const rect = element.getBoundingClientRect();
|
|
89
90
|
return (
|
|
90
91
|
rect.top >= 0 &&
|
|
@@ -93,49 +94,49 @@ const isInViewport = element => {
|
|
|
93
94
|
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
|
|
94
95
|
);
|
|
95
96
|
};
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
/** @type {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
invokerNode: /** @type {HTMLElement} */ (
|
|
108
|
-
fixtureSync(html` <div role="button" style="width: 100px; height: 20px;">Invoker</div> `)
|
|
109
|
-
),
|
|
110
|
-
});
|
|
97
|
+
const withGlobalTestConfig = () => /** @type {OverlayConfig} */ ({
|
|
98
|
+
placementMode: 'global',
|
|
99
|
+
contentNode: /** @type {HTMLElement} */ fixtureSync(html`<div>my content</div>`),
|
|
100
|
+
});
|
|
101
|
+
const withLocalTestConfig = () => /** @type {OverlayConfig} */ ({
|
|
102
|
+
placementMode: 'local',
|
|
103
|
+
contentNode: /** @type {HTMLElement} */ fixtureSync(html`<div>my content</div>`),
|
|
104
|
+
invokerNode:
|
|
105
|
+
/** @type {HTMLElement} */
|
|
106
|
+
fixtureSync(html` <div role="button" style="width: 100px; height: 20px;">Invoker</div> `),
|
|
107
|
+
});
|
|
111
108
|
|
|
112
109
|
/**
|
|
113
110
|
* @param {HTMLDivElement} parentContent
|
|
114
111
|
* @returns {Promise<{parentOverlay: OverlayController; childOverlay: OverlayController}>}
|
|
115
112
|
*/
|
|
116
113
|
async function createNestedEscControllers(parentContent) {
|
|
117
|
-
const childContent = /** @type {HTMLDivElement} */
|
|
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
|
-
|
|
114
|
+
const childContent = /** @type {HTMLDivElement} */ parentContent.querySelector('div[id]');
|
|
128
115
|
if (parentContent.hasAttribute('data-convert-to-shadow-root')) {
|
|
129
|
-
const shadowRootParent = parentContent.attachShadow({
|
|
116
|
+
const shadowRootParent = parentContent.attachShadow({
|
|
117
|
+
mode: 'open',
|
|
118
|
+
});
|
|
130
119
|
shadowRootParent.appendChild(childContent);
|
|
131
120
|
}
|
|
132
|
-
|
|
121
|
+
const parentConfig = {};
|
|
122
|
+
const childConfig = {};
|
|
133
123
|
const parentHasOutsideOnEsc = parentContent.id.startsWith('parent-overlay--hidesOnOutsideEsc');
|
|
134
124
|
const childHasOutsideOnEsc = childContent.id.startsWith('child-overlay--hidesOnOutsideEsc');
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
125
|
+
if (parentHasOutsideOnEsc) {
|
|
126
|
+
parentConfig.hidesOnOutsideEsc = true;
|
|
127
|
+
} else {
|
|
128
|
+
parentConfig.hidesOnEsc = true;
|
|
129
|
+
}
|
|
130
|
+
if (childHasOutsideOnEsc) {
|
|
131
|
+
childConfig.hidesOnOutsideEsc = true;
|
|
132
|
+
} else {
|
|
133
|
+
childConfig.hidesOnEsc = true;
|
|
134
|
+
}
|
|
135
|
+
const parentHasSyncChildrenCloseState =
|
|
136
|
+
parentContent.dataset.syncChildrenCloseState !== undefined;
|
|
137
|
+
if (parentHasSyncChildrenCloseState) {
|
|
138
|
+
parentConfig.syncChildrenCloseState = true;
|
|
139
|
+
}
|
|
139
140
|
const parentOverlay = new OverlayController({
|
|
140
141
|
...withGlobalTestConfig(),
|
|
141
142
|
contentNode: parentContent,
|
|
@@ -146,19 +147,18 @@ async function createNestedEscControllers(parentContent) {
|
|
|
146
147
|
contentNode: childContent,
|
|
147
148
|
...childConfig,
|
|
148
149
|
});
|
|
149
|
-
|
|
150
150
|
await parentOverlay.show();
|
|
151
151
|
await childOverlay.show();
|
|
152
|
-
|
|
153
|
-
|
|
152
|
+
return {
|
|
153
|
+
parentOverlay,
|
|
154
|
+
childOverlay,
|
|
155
|
+
};
|
|
154
156
|
}
|
|
155
|
-
|
|
156
157
|
afterEach(() => {
|
|
157
158
|
overlays.teardown();
|
|
158
159
|
// clean document.body from the DOM nodes left by previous tests
|
|
159
160
|
document.body.innerHTML = '';
|
|
160
161
|
});
|
|
161
|
-
|
|
162
162
|
describe('OverlayController', () => {
|
|
163
163
|
describe('Init', () => {
|
|
164
164
|
it('adds OverlayController instance to OverlayManager', async () => {
|
|
@@ -168,7 +168,6 @@ describe('OverlayController', () => {
|
|
|
168
168
|
expect(ctrl.manager).to.equal(overlays);
|
|
169
169
|
expect(overlays.list).to.include(ctrl);
|
|
170
170
|
});
|
|
171
|
-
|
|
172
171
|
it('prepares a content node wrapper', async () => {
|
|
173
172
|
const ctrl = new OverlayController({
|
|
174
173
|
...withGlobalTestConfig(),
|
|
@@ -176,12 +175,11 @@ describe('OverlayController', () => {
|
|
|
176
175
|
expect(ctrl.content).not.to.be.undefined;
|
|
177
176
|
expect(ctrl.contentNode.parentElement).to.equal(ctrl.contentWrapperNode);
|
|
178
177
|
});
|
|
179
|
-
|
|
180
178
|
describe('Stylesheets', () => {
|
|
181
179
|
it('calls adoptStyles', async () => {
|
|
182
180
|
const spy = sinon.spy(_adoptStyleUtils, 'adoptStyle');
|
|
183
181
|
const { shadowHost, cleanupShadowHost } = createShadowHost();
|
|
184
|
-
const contentNode = /** @type {HTMLElement} */
|
|
182
|
+
const contentNode = /** @type {HTMLElement} */ await fixture('<div>contentful</div>');
|
|
185
183
|
shadowHost.appendChild(contentNode);
|
|
186
184
|
new OverlayController({
|
|
187
185
|
...withLocalTestConfig(),
|
|
@@ -191,7 +189,6 @@ describe('OverlayController', () => {
|
|
|
191
189
|
cleanupShadowHost();
|
|
192
190
|
});
|
|
193
191
|
});
|
|
194
|
-
|
|
195
192
|
describe('Z-index on local overlays', () => {
|
|
196
193
|
/** @type {HTMLElement} */
|
|
197
194
|
let contentNode;
|
|
@@ -201,7 +198,8 @@ describe('OverlayController', () => {
|
|
|
201
198
|
*/
|
|
202
199
|
async function createZNode(zIndexVal, { mode } = {}) {
|
|
203
200
|
if (mode === 'global') {
|
|
204
|
-
contentNode =
|
|
201
|
+
contentNode =
|
|
202
|
+
/** @type {HTMLElement} */
|
|
205
203
|
await fixture(html`
|
|
206
204
|
<div class="z-index--${zIndexVal}">
|
|
207
205
|
<style>
|
|
@@ -211,69 +209,92 @@ describe('OverlayController', () => {
|
|
|
211
209
|
</style>
|
|
212
210
|
I should be on top
|
|
213
211
|
</div>
|
|
214
|
-
`)
|
|
215
|
-
);
|
|
212
|
+
`);
|
|
216
213
|
}
|
|
217
214
|
if (mode === 'inline') {
|
|
218
|
-
contentNode =
|
|
219
|
-
|
|
220
|
-
|
|
215
|
+
contentNode =
|
|
216
|
+
/** @type {HTMLElement} */
|
|
217
|
+
await fixture(html` <div>I should be on top</div> `);
|
|
221
218
|
contentNode.style.zIndex = zIndexVal;
|
|
222
219
|
}
|
|
223
220
|
return contentNode;
|
|
224
221
|
}
|
|
225
|
-
|
|
226
222
|
it('sets a z-index to make sure overlay is painted on top of siblings', async () => {
|
|
227
223
|
const ctrl = new OverlayController({
|
|
228
224
|
...withLocalTestConfig(),
|
|
229
|
-
contentNode: await createZNode('auto', {
|
|
225
|
+
contentNode: await createZNode('auto', {
|
|
226
|
+
mode: 'global',
|
|
227
|
+
}),
|
|
230
228
|
});
|
|
231
229
|
await ctrl.show();
|
|
232
230
|
// @ts-expect-error find out why config would/could be undfined
|
|
233
231
|
expect(ctrl.content.style.zIndex).to.equal(`${ctrl.config.zIndex + 1}`);
|
|
234
|
-
ctrl.updateConfig({
|
|
232
|
+
ctrl.updateConfig({
|
|
233
|
+
contentNode: await createZNode('auto', {
|
|
234
|
+
mode: 'inline',
|
|
235
|
+
}),
|
|
236
|
+
});
|
|
235
237
|
await ctrl.show();
|
|
236
238
|
// @ts-expect-error find out why config would/could be undfined
|
|
237
239
|
expect(ctrl.content.style.zIndex).to.equal(`${ctrl.config.zIndex + 1}`);
|
|
238
|
-
|
|
239
|
-
|
|
240
|
+
ctrl.updateConfig({
|
|
241
|
+
contentNode: await createZNode('0', {
|
|
242
|
+
mode: 'global',
|
|
243
|
+
}),
|
|
244
|
+
});
|
|
240
245
|
await ctrl.show();
|
|
241
246
|
// @ts-expect-error find out why config would/could be undfined
|
|
242
247
|
expect(ctrl.content.style.zIndex).to.equal(`${ctrl.config.zIndex + 1}`);
|
|
243
|
-
ctrl.updateConfig({
|
|
248
|
+
ctrl.updateConfig({
|
|
249
|
+
contentNode: await createZNode('0', {
|
|
250
|
+
mode: 'inline',
|
|
251
|
+
}),
|
|
252
|
+
});
|
|
244
253
|
await ctrl.show();
|
|
245
254
|
// @ts-expect-error find out why config would/could be undfined
|
|
246
255
|
expect(ctrl.content.style.zIndex).to.equal(`${ctrl.config.zIndex + 1}`);
|
|
247
256
|
});
|
|
248
|
-
|
|
249
257
|
it.skip("doesn't set a z-index when contentNode already has >= 1", async () => {
|
|
250
258
|
const ctrl = new OverlayController({
|
|
251
259
|
...withLocalTestConfig(),
|
|
252
|
-
contentNode: await createZNode('1', {
|
|
260
|
+
contentNode: await createZNode('1', {
|
|
261
|
+
mode: 'global',
|
|
262
|
+
}),
|
|
253
263
|
});
|
|
254
264
|
await ctrl.show();
|
|
255
265
|
expect(ctrl.content.style.zIndex).to.equal('');
|
|
256
|
-
ctrl.updateConfig({
|
|
266
|
+
ctrl.updateConfig({
|
|
267
|
+
contentNode: await createZNode('auto', {
|
|
268
|
+
mode: 'inline',
|
|
269
|
+
}),
|
|
270
|
+
});
|
|
257
271
|
await ctrl.show();
|
|
258
272
|
expect(ctrl.content.style.zIndex).to.equal('');
|
|
259
|
-
|
|
260
|
-
|
|
273
|
+
ctrl.updateConfig({
|
|
274
|
+
contentNode: await createZNode('2', {
|
|
275
|
+
mode: 'global',
|
|
276
|
+
}),
|
|
277
|
+
});
|
|
261
278
|
await ctrl.show();
|
|
262
279
|
expect(ctrl.content.style.zIndex).to.equal('');
|
|
263
|
-
ctrl.updateConfig({
|
|
280
|
+
ctrl.updateConfig({
|
|
281
|
+
contentNode: await createZNode('2', {
|
|
282
|
+
mode: 'inline',
|
|
283
|
+
}),
|
|
284
|
+
});
|
|
264
285
|
await ctrl.show();
|
|
265
286
|
expect(ctrl.content.style.zIndex).to.equal('');
|
|
266
287
|
});
|
|
267
|
-
|
|
268
288
|
it("doesn't touch the value of .contentNode", async () => {
|
|
269
289
|
const ctrl = new OverlayController({
|
|
270
290
|
...withLocalTestConfig(),
|
|
271
|
-
contentNode: await createZNode('auto', {
|
|
291
|
+
contentNode: await createZNode('auto', {
|
|
292
|
+
mode: 'global',
|
|
293
|
+
}),
|
|
272
294
|
});
|
|
273
295
|
expect(ctrl.contentNode.style.zIndex).to.equal('');
|
|
274
296
|
});
|
|
275
297
|
});
|
|
276
|
-
|
|
277
298
|
describe('Offline content', () => {
|
|
278
299
|
it('throws when passing a content node that was created "offline"', async () => {
|
|
279
300
|
const contentNode = document.createElement('div');
|
|
@@ -284,12 +305,11 @@ describe('OverlayController', () => {
|
|
|
284
305
|
});
|
|
285
306
|
};
|
|
286
307
|
expect(createOverlayController).to.throw(
|
|
287
|
-
'[OverlayController] Could not find a render target,
|
|
308
|
+
'[OverlayController] Could not find a render target, makes sure contentNode has a parent element (or contentWrapperNode is connected)',
|
|
288
309
|
);
|
|
289
310
|
});
|
|
290
|
-
|
|
291
311
|
it('succeeds when passing a content node that was created "online"', async () => {
|
|
292
|
-
const contentNode = /** @type {HTMLElement} */
|
|
312
|
+
const contentNode = /** @type {HTMLElement} */ fixtureSync('<div>');
|
|
293
313
|
const overlay = new OverlayController({
|
|
294
314
|
...withLocalTestConfig(),
|
|
295
315
|
contentNode,
|
|
@@ -303,16 +323,12 @@ describe('OverlayController', () => {
|
|
|
303
323
|
describe('Teardown', () => {
|
|
304
324
|
it('unregisters itself from overlayManager', async () => {
|
|
305
325
|
const ctrl = new OverlayController(withGlobalTestConfig());
|
|
306
|
-
|
|
307
326
|
expect(isRegisteredOnManager(ctrl)).to.be.true;
|
|
308
|
-
|
|
309
327
|
ctrl.teardown();
|
|
310
|
-
|
|
311
328
|
expect(isRegisteredOnManager(ctrl)).to.be.false;
|
|
312
329
|
});
|
|
313
|
-
|
|
314
330
|
it('handles removal from DOM gracefully when overlay is open', async () => {
|
|
315
|
-
const contentNode = /** @type {HTMLElement} */
|
|
331
|
+
const contentNode = /** @type {HTMLElement} */ fixtureSync(html`<div>my content</div>`);
|
|
316
332
|
const ctrl = new OverlayController({
|
|
317
333
|
placementMode: 'global',
|
|
318
334
|
contentNode,
|
|
@@ -330,7 +346,6 @@ describe('OverlayController', () => {
|
|
|
330
346
|
// Teardown should complete without errors
|
|
331
347
|
expect(isRegisteredOnManager(ctrl)).to.be.false;
|
|
332
348
|
});
|
|
333
|
-
|
|
334
349
|
it('does not throw when hide() is called after teardown() on a shown controller', async () => {
|
|
335
350
|
const ctrl = new OverlayController({
|
|
336
351
|
...withGlobalTestConfig(),
|
|
@@ -346,12 +361,24 @@ describe('OverlayController', () => {
|
|
|
346
361
|
await ctrl.hide();
|
|
347
362
|
expect(ctrl.isShown).to.be.false;
|
|
348
363
|
});
|
|
364
|
+
it('cleans up the dom structure it created', async () => {
|
|
365
|
+
const contentNode = /** @type {HTMLElement} */ fixtureSync(html`<div>my content</div>`);
|
|
366
|
+
const ctrl = new OverlayController({
|
|
367
|
+
placementMode: 'global',
|
|
368
|
+
contentNode,
|
|
369
|
+
});
|
|
370
|
+
await ctrl.show();
|
|
371
|
+
expect(ctrl.contentWrapperNode).to.exist;
|
|
372
|
+
expect(ctrl.__wrappingDialogNode).to.exist;
|
|
373
|
+
await ctrl.teardown();
|
|
374
|
+
expect(ctrl.contentWrapperNode).to.not.exist;
|
|
375
|
+
expect(ctrl.__wrappingDialogNode).to.not.exist;
|
|
376
|
+
});
|
|
349
377
|
});
|
|
350
|
-
|
|
351
378
|
describe('Node Configuration', () => {
|
|
352
379
|
describe('Content', async () => {
|
|
353
380
|
it('accepts a .contentNode for displaying content of the overlay', async () => {
|
|
354
|
-
const myContentNode = /** @type {HTMLElement} */
|
|
381
|
+
const myContentNode = /** @type {HTMLElement} */ fixtureSync('<p>direct node</p>');
|
|
355
382
|
const ctrl = new OverlayController({
|
|
356
383
|
...withGlobalTestConfig(),
|
|
357
384
|
contentNode: myContentNode,
|
|
@@ -359,7 +386,6 @@ describe('OverlayController', () => {
|
|
|
359
386
|
expect(ctrl.contentNode).to.have.trimmed.text('direct node');
|
|
360
387
|
expect(ctrl.contentNode).to.equal(myContentNode);
|
|
361
388
|
});
|
|
362
|
-
|
|
363
389
|
describe('Embedded dom structure', async () => {
|
|
364
390
|
describe('When projected in shadow dom', async () => {
|
|
365
391
|
it('wraps a .contentWrapperNode for style application and a <dialog role="none"> for top layer paints', async () => {
|
|
@@ -367,27 +393,25 @@ describe('OverlayController', () => {
|
|
|
367
393
|
class extends HTMLElement {
|
|
368
394
|
constructor() {
|
|
369
395
|
super();
|
|
370
|
-
this.attachShadow({
|
|
396
|
+
this.attachShadow({
|
|
397
|
+
mode: 'open',
|
|
398
|
+
});
|
|
371
399
|
}
|
|
372
|
-
|
|
373
400
|
connectedCallback() {
|
|
374
401
|
/** @type {ShadowRoot} */
|
|
375
|
-
|
|
402
|
+
this.shadowRoot.innerHTML = '<slot name="content"></slot>';
|
|
376
403
|
this.innerHTML = '<div slot="content">projected</div>';
|
|
377
404
|
}
|
|
378
405
|
},
|
|
379
406
|
);
|
|
380
|
-
|
|
381
|
-
const
|
|
382
|
-
const myContentNode = /** @type {HTMLElement} */ (el.querySelector('[slot=content]'));
|
|
407
|
+
const el = /** @type {HTMLElement} */ fixtureSync(`<${tagString}></${tagString}>`);
|
|
408
|
+
const myContentNode = /** @type {HTMLElement} */ el.querySelector('[slot=content]');
|
|
383
409
|
const ctrl = new OverlayController({
|
|
384
410
|
...withGlobalTestConfig(),
|
|
385
411
|
contentNode: myContentNode,
|
|
386
412
|
});
|
|
387
|
-
|
|
388
413
|
expect(ctrl.contentNode.assignedSlot?.parentElement).to.equal(ctrl.contentWrapperNode);
|
|
389
414
|
expect(ctrl.contentWrapperNode.parentElement?.tagName).to.equal('DIALOG');
|
|
390
|
-
|
|
391
415
|
normalizeOverlayContentWapper(ctrl.contentWrapperNode);
|
|
392
416
|
|
|
393
417
|
// The total dom structure created...
|
|
@@ -400,24 +424,23 @@ describe('OverlayController', () => {
|
|
|
400
424
|
</div>
|
|
401
425
|
</dialog>
|
|
402
426
|
`,
|
|
403
|
-
{
|
|
427
|
+
{
|
|
428
|
+
ignoreAttributes: ['closedby'],
|
|
429
|
+
},
|
|
404
430
|
);
|
|
405
|
-
|
|
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
|
-
|
|
410
434
|
describe('When in light dom', async () => {
|
|
411
435
|
it('wraps a .contentWrapperNode for style application and a <dialog role="none"> for top layer paints', async () => {
|
|
412
436
|
const el = fixtureSync('<section><div id="content">non projected</div></section>');
|
|
413
|
-
const myContentNode = /** @type {HTMLElement} */
|
|
437
|
+
const myContentNode = /** @type {HTMLElement} */ el.querySelector('#content');
|
|
414
438
|
const ctrl = new OverlayController({
|
|
415
439
|
...withGlobalTestConfig(),
|
|
416
440
|
contentNode: myContentNode,
|
|
417
441
|
});
|
|
418
442
|
expect(ctrl.contentNode.parentElement).to.equal(ctrl.contentWrapperNode);
|
|
419
443
|
expect(ctrl.contentWrapperNode.parentElement?.tagName).to.equal('DIALOG');
|
|
420
|
-
|
|
421
444
|
normalizeOverlayContentWapper(ctrl.contentWrapperNode);
|
|
422
445
|
|
|
423
446
|
// The total dom structure created...
|
|
@@ -425,43 +448,126 @@ describe('OverlayController', () => {
|
|
|
425
448
|
`
|
|
426
449
|
<dialog data-overlay-outer-wrapper="" open="" role="none" style="${wrappingDialogNodeStyle}">
|
|
427
450
|
<div data-id="content-wrapper">
|
|
428
|
-
<div id="content">non projected</div>
|
|
451
|
+
<div data-content="" id="content">non projected</div>
|
|
429
452
|
</div>
|
|
430
453
|
</dialog>
|
|
431
454
|
`,
|
|
432
|
-
{
|
|
455
|
+
{
|
|
456
|
+
ignoreAttributes: ['closedby'],
|
|
457
|
+
},
|
|
433
458
|
);
|
|
434
459
|
});
|
|
435
460
|
});
|
|
436
|
-
|
|
461
|
+
describe('When .contentWrapperNode is provided in a host that is not connected yet', () => {
|
|
462
|
+
/** @param {{ nested?: boolean }} [opts] */
|
|
463
|
+
function createDisconnectedHost({ nested = false } = {}) {
|
|
464
|
+
const host = document.createElement('div');
|
|
465
|
+
const shadowRoot = host.attachShadow({
|
|
466
|
+
mode: 'open',
|
|
467
|
+
});
|
|
468
|
+
const wrapper = document.createElement('div');
|
|
469
|
+
wrapper.setAttribute('data-id', 'content-wrapper');
|
|
470
|
+
wrapper.innerHTML = '<slot name="content"></slot>';
|
|
471
|
+
if (nested) {
|
|
472
|
+
const section = document.createElement('section');
|
|
473
|
+
section.appendChild(wrapper);
|
|
474
|
+
shadowRoot.appendChild(section);
|
|
475
|
+
} else {
|
|
476
|
+
shadowRoot.appendChild(wrapper);
|
|
477
|
+
}
|
|
478
|
+
const content = document.createElement('div');
|
|
479
|
+
content.slot = 'content';
|
|
480
|
+
content.textContent = 'projected';
|
|
481
|
+
host.appendChild(content);
|
|
482
|
+
return {
|
|
483
|
+
host,
|
|
484
|
+
shadowRoot,
|
|
485
|
+
wrapper,
|
|
486
|
+
content,
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
it('does not throw and keeps the projected slot inside the wrapper', async () => {
|
|
490
|
+
const { host, shadowRoot, wrapper, content } = createDisconnectedHost();
|
|
491
|
+
expect(wrapper.isConnected).to.be.false;
|
|
492
|
+
const slot = /** @type {HTMLSlotElement} */ content.assignedSlot;
|
|
493
|
+
const ctrl = new OverlayController({
|
|
494
|
+
...withGlobalTestConfig(),
|
|
495
|
+
contentNode: content,
|
|
496
|
+
contentWrapperNode: wrapper,
|
|
497
|
+
});
|
|
498
|
+
expect(ctrl.contentWrapperNode).to.equal(wrapper);
|
|
499
|
+
expect(wrapper.parentElement?.tagName).to.equal('DIALOG');
|
|
500
|
+
expect(slot.parentElement).to.equal(wrapper);
|
|
501
|
+
expect(content.parentElement).to.equal(host);
|
|
502
|
+
expect(shadowRoot.querySelectorAll('slot').length).to.equal(1);
|
|
503
|
+
});
|
|
504
|
+
it('restores the same relocated slot at its original position on teardown', async () => {
|
|
505
|
+
const { host, shadowRoot, wrapper, content } = createDisconnectedHost({
|
|
506
|
+
nested: true,
|
|
507
|
+
});
|
|
508
|
+
const section = /** @type {HTMLElement} */ shadowRoot.querySelector('section');
|
|
509
|
+
const slot = /** @type {HTMLSlotElement} */ content.assignedSlot;
|
|
510
|
+
const ctrl = new OverlayController({
|
|
511
|
+
...withGlobalTestConfig(),
|
|
512
|
+
contentNode: content,
|
|
513
|
+
contentWrapperNode: wrapper,
|
|
514
|
+
});
|
|
515
|
+
ctrl.teardown();
|
|
516
|
+
expect(content.parentElement).to.equal(host);
|
|
517
|
+
expect(wrapper.parentElement).to.equal(section);
|
|
518
|
+
expect(slot.parentElement).to.equal(wrapper);
|
|
519
|
+
expect(shadowRoot.querySelector('dialog')).to.be.null;
|
|
520
|
+
expect(shadowRoot.querySelector('slot')).to.equal(slot);
|
|
521
|
+
});
|
|
522
|
+
it('survives repeated updateConfig calls and keeps slot ownership', async () => {
|
|
523
|
+
const { host, shadowRoot, wrapper, content } = createDisconnectedHost();
|
|
524
|
+
const slot = /** @type {HTMLSlotElement} */ content.assignedSlot;
|
|
525
|
+
const ctrl = new OverlayController({
|
|
526
|
+
...withGlobalTestConfig(),
|
|
527
|
+
contentNode: content,
|
|
528
|
+
contentWrapperNode: wrapper,
|
|
529
|
+
});
|
|
530
|
+
expect(() =>
|
|
531
|
+
ctrl.updateConfig({
|
|
532
|
+
trapsKeyboardFocus: true,
|
|
533
|
+
}),
|
|
534
|
+
).to.not.throw();
|
|
535
|
+
expect(() =>
|
|
536
|
+
ctrl.updateConfig({
|
|
537
|
+
trapsKeyboardFocus: false,
|
|
538
|
+
}),
|
|
539
|
+
).to.not.throw();
|
|
540
|
+
expect(content.parentElement).to.equal(host);
|
|
541
|
+
expect(shadowRoot.querySelectorAll('slot').length).to.equal(1);
|
|
542
|
+
expect(shadowRoot.querySelector('slot')).to.equal(slot);
|
|
543
|
+
expect(wrapper.contains(slot)).to.be.true;
|
|
544
|
+
});
|
|
545
|
+
});
|
|
437
546
|
describe('When .contenWrapperNode provided', async () => {
|
|
438
547
|
it('keeps the .contentWrapperNode for style application and wraps a <dialog role="none"> for top layer paints', async () => {
|
|
439
548
|
const tagString = defineCE(
|
|
440
549
|
class extends HTMLElement {
|
|
441
550
|
constructor() {
|
|
442
551
|
super();
|
|
443
|
-
this.attachShadow({
|
|
552
|
+
this.attachShadow({
|
|
553
|
+
mode: 'open',
|
|
554
|
+
});
|
|
444
555
|
}
|
|
445
|
-
|
|
446
556
|
connectedCallback() {
|
|
447
557
|
/** @type {ShadowRoot} */
|
|
448
|
-
|
|
558
|
+
this.shadowRoot.innerHTML = '<div><slot name="content"></slot></div>';
|
|
449
559
|
this.innerHTML = '<div slot="content">projected</div>';
|
|
450
560
|
}
|
|
451
561
|
},
|
|
452
562
|
);
|
|
453
|
-
|
|
454
|
-
const
|
|
455
|
-
const
|
|
456
|
-
const myContentWrapper = /** @type {HTMLElement} */ (
|
|
457
|
-
el.shadowRoot?.querySelector('div')
|
|
458
|
-
);
|
|
563
|
+
const el = /** @type {HTMLElement} */ fixtureSync(`<${tagString}></${tagString}>`);
|
|
564
|
+
const myContentNode = /** @type {HTMLElement} */ el.querySelector('[slot=content]');
|
|
565
|
+
const myContentWrapper = /** @type {HTMLElement} */ el.shadowRoot?.querySelector('div');
|
|
459
566
|
const ctrl = new OverlayController({
|
|
460
567
|
...withGlobalTestConfig(),
|
|
461
568
|
contentNode: myContentNode,
|
|
462
569
|
contentWrapperNode: myContentWrapper,
|
|
463
570
|
});
|
|
464
|
-
|
|
465
571
|
normalizeOverlayContentWapper(ctrl.contentWrapperNode);
|
|
466
572
|
|
|
467
573
|
// The total dom structure created...
|
|
@@ -473,21 +579,23 @@ describe('OverlayController', () => {
|
|
|
473
579
|
</div>
|
|
474
580
|
</dialog>
|
|
475
581
|
`,
|
|
476
|
-
{
|
|
582
|
+
{
|
|
583
|
+
ignoreAttributes: ['closedby'],
|
|
584
|
+
},
|
|
477
585
|
);
|
|
478
586
|
});
|
|
479
|
-
|
|
480
587
|
it("uses the .contentWrapperNode as container for Popper's arrow", async () => {
|
|
481
588
|
const tagString = defineCE(
|
|
482
589
|
class extends HTMLElement {
|
|
483
590
|
constructor() {
|
|
484
591
|
super();
|
|
485
|
-
this.attachShadow({
|
|
592
|
+
this.attachShadow({
|
|
593
|
+
mode: 'open',
|
|
594
|
+
});
|
|
486
595
|
}
|
|
487
|
-
|
|
488
596
|
connectedCallback() {
|
|
489
597
|
/** @type {ShadowRoot} */
|
|
490
|
-
|
|
598
|
+
this.shadowRoot.innerHTML = `
|
|
491
599
|
<div>
|
|
492
600
|
<div id="arrow"></div>
|
|
493
601
|
<slot name="content"></slot>
|
|
@@ -496,18 +604,14 @@ describe('OverlayController', () => {
|
|
|
496
604
|
}
|
|
497
605
|
},
|
|
498
606
|
);
|
|
499
|
-
|
|
500
|
-
const
|
|
501
|
-
const
|
|
502
|
-
const myContentWrapper = /** @type {HTMLElement} */ (
|
|
503
|
-
el.shadowRoot?.querySelector('div')
|
|
504
|
-
);
|
|
607
|
+
const el = /** @type {HTMLElement} */ fixtureSync(`<${tagString}></${tagString}>`);
|
|
608
|
+
const myContentNode = /** @type {HTMLElement} */ el.querySelector('[slot=content]');
|
|
609
|
+
const myContentWrapper = /** @type {HTMLElement} */ el.shadowRoot?.querySelector('div');
|
|
505
610
|
const ctrl = new OverlayController({
|
|
506
611
|
...withLocalTestConfig(),
|
|
507
612
|
contentNode: myContentNode,
|
|
508
613
|
contentWrapperNode: myContentWrapper,
|
|
509
614
|
});
|
|
510
|
-
|
|
511
615
|
normalizeOverlayContentWapper(ctrl.contentWrapperNode);
|
|
512
616
|
|
|
513
617
|
// The total dom structure created...
|
|
@@ -520,16 +624,17 @@ describe('OverlayController', () => {
|
|
|
520
624
|
</div>
|
|
521
625
|
</dialog>
|
|
522
626
|
`,
|
|
523
|
-
{
|
|
627
|
+
{
|
|
628
|
+
ignoreAttributes: ['closedby'],
|
|
629
|
+
},
|
|
524
630
|
);
|
|
525
631
|
});
|
|
526
632
|
});
|
|
527
633
|
});
|
|
528
634
|
});
|
|
529
|
-
|
|
530
635
|
describe('Invoker / Reference', async () => {
|
|
531
636
|
it('accepts a .invokerNode to directly set invoker', async () => {
|
|
532
|
-
const myInvokerNode = /** @type {HTMLElement} */
|
|
637
|
+
const myInvokerNode = /** @type {HTMLElement} */ fixtureSync('<button>invoke</button>');
|
|
533
638
|
const ctrl = new OverlayController({
|
|
534
639
|
...withGlobalTestConfig(),
|
|
535
640
|
invokerNode: myInvokerNode,
|
|
@@ -537,10 +642,9 @@ describe('OverlayController', () => {
|
|
|
537
642
|
expect(ctrl.invokerNode).to.equal(myInvokerNode);
|
|
538
643
|
expect(ctrl.referenceNode).to.equal(undefined);
|
|
539
644
|
});
|
|
540
|
-
|
|
541
645
|
it('accepts a .referenceNode as positioning anchor different from .invokerNode', async () => {
|
|
542
|
-
const myInvokerNode = /** @type {HTMLElement} */
|
|
543
|
-
const myReferenceNode = /** @type {HTMLElement} */
|
|
646
|
+
const myInvokerNode = /** @type {HTMLElement} */ fixtureSync('<button>invoke</button>');
|
|
647
|
+
const myReferenceNode = /** @type {HTMLElement} */ fixtureSync('<div>anchor</div>');
|
|
544
648
|
const ctrl = new OverlayController({
|
|
545
649
|
...withGlobalTestConfig(),
|
|
546
650
|
invokerNode: myInvokerNode,
|
|
@@ -550,33 +654,30 @@ describe('OverlayController', () => {
|
|
|
550
654
|
expect(ctrl.invokerNode).to.not.equal(ctrl.referenceNode);
|
|
551
655
|
});
|
|
552
656
|
});
|
|
553
|
-
|
|
554
657
|
describe('Backdrop', () => {
|
|
555
658
|
it('creates a .backdropNode inside <dialog> for guaranteed top layer paints and positioning opportunities', async () => {
|
|
556
659
|
const tagString = defineCE(
|
|
557
660
|
class extends HTMLElement {
|
|
558
661
|
constructor() {
|
|
559
662
|
super();
|
|
560
|
-
this.attachShadow({
|
|
663
|
+
this.attachShadow({
|
|
664
|
+
mode: 'open',
|
|
665
|
+
});
|
|
561
666
|
}
|
|
562
|
-
|
|
563
667
|
connectedCallback() {
|
|
564
668
|
/** @type {ShadowRoot} */
|
|
565
|
-
|
|
669
|
+
this.shadowRoot.innerHTML = '<slot name="content"></slot>';
|
|
566
670
|
this.innerHTML = '<div slot="content">projected</div>';
|
|
567
671
|
}
|
|
568
672
|
},
|
|
569
673
|
);
|
|
570
|
-
|
|
571
|
-
const
|
|
572
|
-
const myContentNode = /** @type {HTMLElement} */ (el.querySelector('[slot=content]'));
|
|
573
|
-
|
|
674
|
+
const el = /** @type {HTMLElement} */ fixtureSync(`<${tagString}></${tagString}>`);
|
|
675
|
+
const myContentNode = /** @type {HTMLElement} */ el.querySelector('[slot=content]');
|
|
574
676
|
const ctrl = new OverlayController({
|
|
575
677
|
...withGlobalTestConfig(),
|
|
576
678
|
contentNode: myContentNode,
|
|
577
679
|
hasBackdrop: true,
|
|
578
680
|
});
|
|
579
|
-
|
|
580
681
|
normalizeOverlayContentWapper(ctrl.contentWrapperNode);
|
|
581
682
|
|
|
582
683
|
// The total dom structure created...
|
|
@@ -590,36 +691,35 @@ describe('OverlayController', () => {
|
|
|
590
691
|
</div>
|
|
591
692
|
</dialog>
|
|
592
693
|
`,
|
|
593
|
-
{
|
|
694
|
+
{
|
|
695
|
+
ignoreAttributes: ['closedby'],
|
|
696
|
+
},
|
|
594
697
|
);
|
|
595
698
|
});
|
|
596
699
|
});
|
|
597
|
-
|
|
598
700
|
describe('When contentWrapperNode needs to be provided for correct arrow positioning', () => {
|
|
599
701
|
it('uses contentWrapperNode as provided for local positioning', async () => {
|
|
600
|
-
const el =
|
|
702
|
+
const el =
|
|
703
|
+
/** @type {HTMLElement} */
|
|
601
704
|
await fixture(html`
|
|
602
705
|
<div id="contentWrapperNode">
|
|
603
706
|
<div id="contentNode"></div>
|
|
604
707
|
<my-arrow></my-arrow>
|
|
605
708
|
</div>
|
|
606
|
-
`)
|
|
607
|
-
);
|
|
608
|
-
|
|
609
|
-
const contentNode = /** @type {HTMLElement} */ (el.querySelector('#contentNode'));
|
|
709
|
+
`);
|
|
710
|
+
const contentNode = /** @type {HTMLElement} */ el.querySelector('#contentNode');
|
|
610
711
|
const contentWrapperNode = el;
|
|
611
|
-
|
|
612
712
|
const ctrl = new OverlayController({
|
|
613
713
|
...withLocalTestConfig(),
|
|
614
714
|
contentNode,
|
|
615
715
|
contentWrapperNode,
|
|
616
716
|
});
|
|
617
|
-
|
|
618
717
|
expect(ctrl.contentWrapperNode).to.equal(contentWrapperNode);
|
|
619
718
|
});
|
|
620
719
|
});
|
|
621
720
|
});
|
|
622
721
|
|
|
722
|
+
// TODO: make features modular (so they can be treeshaken) and test their lifecycle within this desrcibe
|
|
623
723
|
describe('Feature Configuration', () => {
|
|
624
724
|
describe('trapsKeyboardFocus', () => {
|
|
625
725
|
it('focuses the overlay on show', async () => {
|
|
@@ -630,27 +730,28 @@ describe('OverlayController', () => {
|
|
|
630
730
|
await ctrl.show();
|
|
631
731
|
expect(isActiveElement(ctrl.contentNode)).to.be.true;
|
|
632
732
|
});
|
|
633
|
-
|
|
634
733
|
it('keeps focus within the overlay e.g. you can not tab out by accident', async () => {
|
|
635
|
-
const contentNode =
|
|
636
|
-
|
|
637
|
-
|
|
734
|
+
const contentNode =
|
|
735
|
+
/** @type {HTMLElement} */
|
|
736
|
+
await fixture(html` <div><input id="input1" /><input id="input2" /></div> `);
|
|
638
737
|
const ctrl = new OverlayController({
|
|
639
738
|
...withGlobalTestConfig(),
|
|
640
739
|
trapsKeyboardFocus: true,
|
|
641
740
|
contentNode,
|
|
642
741
|
});
|
|
643
742
|
await ctrl.show();
|
|
644
|
-
|
|
645
743
|
await fixture(html`<button>click me</button>`);
|
|
646
744
|
const input1 = ctrl.contentNode.querySelectorAll('input')[0];
|
|
647
745
|
const input2 = ctrl.contentNode.querySelectorAll('input')[1];
|
|
648
746
|
input2.focus();
|
|
649
|
-
await sendKeys({
|
|
650
|
-
|
|
747
|
+
await sendKeys({
|
|
748
|
+
press: 'Tab',
|
|
749
|
+
});
|
|
651
750
|
if (browserDetection.isChrome) {
|
|
652
751
|
expect(isActiveElement(document.body)).to.be.true;
|
|
653
|
-
await sendKeys({
|
|
752
|
+
await sendKeys({
|
|
753
|
+
press: 'Tab',
|
|
754
|
+
});
|
|
654
755
|
expect(isActiveElement(input1)).to.be.true;
|
|
655
756
|
}
|
|
656
757
|
if (browserDetection.isFirefox) {
|
|
@@ -658,37 +759,40 @@ describe('OverlayController', () => {
|
|
|
658
759
|
// once we focus on the latest focusable element, `input2` in this case,
|
|
659
760
|
// any further Tab presses keeps the focus on `input2` element
|
|
660
761
|
expect(isActiveElement(input2)).to.be.true;
|
|
661
|
-
await sendKeys({
|
|
762
|
+
await sendKeys({
|
|
763
|
+
press: 'Tab',
|
|
764
|
+
});
|
|
662
765
|
expect(isActiveElement(input2)).to.be.true;
|
|
663
766
|
}
|
|
664
767
|
if (browserDetection.isMacSafari) {
|
|
665
768
|
expect(isActiveElement(document.body)).to.be.true;
|
|
666
|
-
await sendKeys({
|
|
769
|
+
await sendKeys({
|
|
770
|
+
press: 'Tab',
|
|
771
|
+
});
|
|
667
772
|
expect(isActiveElement(ctrl.contentNode)).to.be.true;
|
|
668
|
-
await sendKeys({
|
|
773
|
+
await sendKeys({
|
|
774
|
+
press: 'Tab',
|
|
775
|
+
});
|
|
669
776
|
expect(isActiveElement(input1)).to.be.true;
|
|
670
777
|
}
|
|
671
778
|
});
|
|
672
|
-
|
|
673
779
|
it('focuses the element with [autofocus] when dialog gets opened', async () => {
|
|
674
|
-
const contentNode =
|
|
675
|
-
|
|
676
|
-
|
|
780
|
+
const contentNode =
|
|
781
|
+
/** @type {HTMLElement} */
|
|
782
|
+
await fixture(html` <div><input id="input1" /><input id="input2" autofocus /></div> `);
|
|
677
783
|
const ctrl = new OverlayController({
|
|
678
784
|
...withGlobalTestConfig(),
|
|
679
785
|
trapsKeyboardFocus: true,
|
|
680
786
|
contentNode,
|
|
681
787
|
});
|
|
682
788
|
await ctrl.show();
|
|
683
|
-
|
|
684
789
|
const input2 = ctrl.contentNode.querySelectorAll('input')[1];
|
|
685
790
|
expect(isActiveElement(input2)).to.be.true;
|
|
686
791
|
});
|
|
687
|
-
|
|
688
792
|
it('focuses the contentNode when dialog gets opened and there is no [autofocus]', async () => {
|
|
689
|
-
const contentNode =
|
|
690
|
-
|
|
691
|
-
|
|
793
|
+
const contentNode =
|
|
794
|
+
/** @type {HTMLElement} */
|
|
795
|
+
await fixture(html` <div><input id="input1" /><input id="input2" /></div> `);
|
|
692
796
|
const ctrl = new OverlayController({
|
|
693
797
|
...withGlobalTestConfig(),
|
|
694
798
|
trapsKeyboardFocus: true,
|
|
@@ -697,57 +801,48 @@ describe('OverlayController', () => {
|
|
|
697
801
|
await ctrl.show();
|
|
698
802
|
expect(isActiveElement(contentNode)).to.be.true;
|
|
699
803
|
});
|
|
700
|
-
|
|
701
804
|
it('allows to move the focus outside of the overlay if trapsKeyboardFocus is disabled', async () => {
|
|
702
|
-
const contentNode = /** @type {HTMLElement} */
|
|
703
|
-
|
|
805
|
+
const contentNode = /** @type {HTMLElement} */ await fixture(html`<div><input /></div>`);
|
|
704
806
|
const ctrl = new OverlayController({
|
|
705
807
|
...withGlobalTestConfig(),
|
|
706
808
|
contentNode,
|
|
707
809
|
trapsKeyboardFocus: false,
|
|
708
810
|
});
|
|
709
811
|
// add element to dom to allow focus
|
|
710
|
-
/** @type {HTMLElement} */
|
|
812
|
+
/** @type {HTMLElement} */
|
|
813
|
+
await fixture(html`${ctrl.content}`);
|
|
711
814
|
await ctrl.show();
|
|
712
|
-
|
|
713
|
-
const
|
|
714
|
-
const input = /** @type {HTMLInputElement} */ (ctrl.contentNode.querySelector('input'));
|
|
715
|
-
|
|
815
|
+
const elOutside = /** @type {HTMLElement} */ await fixture(html`<input />`);
|
|
816
|
+
const input = /** @type {HTMLInputElement} */ ctrl.contentNode.querySelector('input');
|
|
716
817
|
input.focus();
|
|
717
818
|
simulateTab();
|
|
718
|
-
|
|
719
819
|
expect(isActiveElement(elOutside)).to.be.true;
|
|
720
820
|
});
|
|
721
|
-
|
|
722
821
|
it('keeps focus within overlay with multiple overlays with all traps on true', async () => {
|
|
723
822
|
const ctrl0 = new OverlayController({
|
|
724
823
|
...withGlobalTestConfig(),
|
|
725
824
|
trapsKeyboardFocus: true,
|
|
726
825
|
});
|
|
727
|
-
|
|
728
826
|
const ctrl1 = new OverlayController({
|
|
729
827
|
...withGlobalTestConfig(),
|
|
730
828
|
trapsKeyboardFocus: true,
|
|
731
829
|
});
|
|
732
|
-
|
|
733
830
|
await ctrl0.show();
|
|
734
831
|
await ctrl1.show();
|
|
735
832
|
expect(isActiveElement(ctrl1.contentNode)).to.be.true;
|
|
736
|
-
|
|
737
833
|
await ctrl1.hide();
|
|
738
834
|
expect(isActiveElement(ctrl0.contentNode)).to.be.true;
|
|
739
835
|
});
|
|
740
|
-
|
|
741
836
|
it('warns when contentNode is a host for a shadowRoot', async () => {
|
|
742
837
|
const warnSpy = sinon.spy(console, 'warn');
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
838
|
+
const contentNode = /** @type {HTMLDivElement} */ await fixture(html` <div></div> `);
|
|
839
|
+
contentNode.attachShadow({
|
|
840
|
+
mode: 'open',
|
|
841
|
+
});
|
|
842
|
+
const shadowRootContentNode =
|
|
843
|
+
/** @type {HTMLElement} */
|
|
844
|
+
await fixture(html` <div><input id="input1" /><input id="input2" /></div> `);
|
|
749
845
|
contentNode.shadowRoot?.appendChild(shadowRootContentNode);
|
|
750
|
-
|
|
751
846
|
const ctrl = new OverlayController({
|
|
752
847
|
...withGlobalTestConfig(),
|
|
753
848
|
trapsKeyboardFocus: true,
|
|
@@ -762,7 +857,6 @@ describe('OverlayController', () => {
|
|
|
762
857
|
warnSpy.restore();
|
|
763
858
|
});
|
|
764
859
|
});
|
|
765
|
-
|
|
766
860
|
describe('hidesOnEsc', () => {
|
|
767
861
|
it('hides on [Escape] press', async () => {
|
|
768
862
|
const ctrl = new OverlayController({
|
|
@@ -773,7 +867,6 @@ describe('OverlayController', () => {
|
|
|
773
867
|
await mimicEscapePress(ctrl.contentNode);
|
|
774
868
|
expect(ctrl.isShown).to.be.false;
|
|
775
869
|
});
|
|
776
|
-
|
|
777
870
|
it('stays shown on [Escape] press with `.hidesOnEsc` set to false', async () => {
|
|
778
871
|
const ctrl = new OverlayController({
|
|
779
872
|
...withGlobalTestConfig(),
|
|
@@ -783,7 +876,6 @@ describe('OverlayController', () => {
|
|
|
783
876
|
await mimicEscapePress(ctrl.contentNode);
|
|
784
877
|
expect(ctrl.isShown).to.be.true;
|
|
785
878
|
});
|
|
786
|
-
|
|
787
879
|
it('stays shown on [Escape] press on outside element', async () => {
|
|
788
880
|
const ctrl = new OverlayController({
|
|
789
881
|
...withGlobalTestConfig(),
|
|
@@ -793,7 +885,6 @@ describe('OverlayController', () => {
|
|
|
793
885
|
await mimicEscapePress(document);
|
|
794
886
|
expect(ctrl.isShown).to.be.true;
|
|
795
887
|
});
|
|
796
|
-
|
|
797
888
|
it('stays shown on [Escape] press with modal <dialog> and `.hidesOnEsc` is false', async () => {
|
|
798
889
|
const ctrl = new OverlayController({
|
|
799
890
|
...withGlobalTestConfig(),
|
|
@@ -804,25 +895,21 @@ describe('OverlayController', () => {
|
|
|
804
895
|
await mimicEscapePress(ctrl.contentNode);
|
|
805
896
|
expect(ctrl.isShown).to.be.true;
|
|
806
897
|
});
|
|
807
|
-
|
|
808
898
|
it('parent stays shown on [Escape] press in a nested overlay', async () => {
|
|
809
|
-
const parentContent =
|
|
899
|
+
const parentContent =
|
|
900
|
+
/** @type {HTMLDivElement} */
|
|
810
901
|
await fixture(
|
|
811
902
|
html` <!-- -->
|
|
812
903
|
<div id="parent-overlay--hidesOnEsc">
|
|
813
904
|
<div id="child-overlay--hidesOnEsc">we press [Escape] here</div>
|
|
814
905
|
</div>`,
|
|
815
|
-
)
|
|
816
|
-
);
|
|
906
|
+
);
|
|
817
907
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
818
|
-
|
|
819
908
|
await mimicEscapePress(childOverlay.contentNode);
|
|
820
|
-
|
|
821
909
|
expect(parentOverlay.isShown).to.be.true;
|
|
822
910
|
expect(childOverlay.isShown).to.be.false;
|
|
823
911
|
});
|
|
824
912
|
});
|
|
825
|
-
|
|
826
913
|
describe('hidesOnOutsideEsc', () => {
|
|
827
914
|
it('hides on [Escape] press on outside element', async () => {
|
|
828
915
|
const ctrl = new OverlayController({
|
|
@@ -833,7 +920,6 @@ describe('OverlayController', () => {
|
|
|
833
920
|
await mimicEscapePress(document);
|
|
834
921
|
expect(ctrl.isShown).to.be.false;
|
|
835
922
|
});
|
|
836
|
-
|
|
837
923
|
it('stays shown on [Escape] press on inside element', async () => {
|
|
838
924
|
const ctrl = new OverlayController({
|
|
839
925
|
...withGlobalTestConfig(),
|
|
@@ -843,146 +929,133 @@ describe('OverlayController', () => {
|
|
|
843
929
|
await mimicEscapePress(ctrl.contentNode);
|
|
844
930
|
expect(ctrl.isShown).to.be.true;
|
|
845
931
|
});
|
|
846
|
-
|
|
847
932
|
it('stays shown on [Escape] press in a nested overlay', async () => {
|
|
848
|
-
const parentContent =
|
|
933
|
+
const parentContent =
|
|
934
|
+
/** @type {HTMLDivElement} */
|
|
849
935
|
await fixture(
|
|
850
936
|
html` <!-- -->
|
|
851
937
|
<div id="parent-overlay--hidesOnOutsideEsc">
|
|
852
938
|
<div id="child-overlay--hidesOnOutsideEsc">we press [Escape] here</div>
|
|
853
939
|
</div>`,
|
|
854
|
-
)
|
|
855
|
-
);
|
|
940
|
+
);
|
|
856
941
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
857
|
-
mimicEscapePress(childOverlay.contentNode);
|
|
858
|
-
|
|
942
|
+
await mimicEscapePress(childOverlay.contentNode);
|
|
859
943
|
expect(parentOverlay.isShown).to.be.true;
|
|
860
944
|
expect(childOverlay.isShown).to.be.true;
|
|
861
945
|
});
|
|
862
946
|
});
|
|
863
|
-
|
|
864
947
|
describe('Nested hidesOnEsc / hidesOnOutsideEsc', () => {
|
|
865
948
|
describe('Parent has hidesOnEsc and child has hidesOnOutsideEsc', () => {
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
it.skip('on [Escape] press in child overlay: parent hides, child stays shown', async () => {
|
|
870
|
-
const parentContent = /** @type {HTMLDivElement} */ (
|
|
949
|
+
it('on [Escape] press in child overlay: parent hides, child stays shown', async () => {
|
|
950
|
+
const parentContent =
|
|
951
|
+
/** @type {HTMLDivElement} */
|
|
871
952
|
await fixture(
|
|
872
953
|
html` <!-- -->
|
|
873
954
|
<div id="parent-overlay--hidesOnEsc">
|
|
874
955
|
<div id="child-overlay--hidesOnOutsideEsc">we press [Escape] here</div>
|
|
875
956
|
</div>`,
|
|
876
|
-
)
|
|
877
|
-
);
|
|
957
|
+
);
|
|
878
958
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
879
959
|
await mimicEscapePress(childOverlay.contentNode);
|
|
880
|
-
await
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
960
|
+
await childOverlay._showComplete;
|
|
961
|
+
await parentOverlay._showComplete;
|
|
962
|
+
await childOverlay._hideComplete;
|
|
963
|
+
await parentOverlay._hideComplete;
|
|
964
|
+
if (!childOverlay.isShown) {
|
|
965
|
+
await waitUntil(() => childOverlay.isShown);
|
|
966
|
+
}
|
|
967
|
+
if (parentOverlay.isShown) {
|
|
968
|
+
await waitUntil(() => !parentOverlay.isShown);
|
|
969
|
+
}
|
|
886
970
|
await childOverlay.teardown();
|
|
887
971
|
await parentOverlay.teardown();
|
|
888
972
|
});
|
|
889
|
-
|
|
890
973
|
it('on [Escape] press outside overlays: parent stays shown, child hides', async () => {
|
|
891
|
-
const parentContent =
|
|
974
|
+
const parentContent =
|
|
975
|
+
/** @type {HTMLDivElement} */
|
|
892
976
|
await fixture(
|
|
893
977
|
html` <!-- we press [Escape] here -->
|
|
894
978
|
<div id="parent-overlay--hidesOnEsc">
|
|
895
979
|
<div id="child-overlay--hidesOnOutsideEsc"></div>
|
|
896
980
|
</div>`,
|
|
897
|
-
)
|
|
898
|
-
);
|
|
981
|
+
);
|
|
899
982
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
900
983
|
await mimicEscapePress(document);
|
|
901
|
-
|
|
902
984
|
expect(parentOverlay.isShown).to.be.true;
|
|
903
985
|
expect(childOverlay.isShown).to.be.false;
|
|
904
986
|
});
|
|
905
|
-
|
|
906
987
|
it('on [Escape] press in parent overlay: parent is hidden, child is hidden', async () => {
|
|
907
|
-
const parentContent =
|
|
988
|
+
const parentContent =
|
|
989
|
+
/** @type {HTMLDivElement} */
|
|
908
990
|
await fixture(
|
|
909
991
|
html` <!-- -->
|
|
910
992
|
<div id="parent-overlay--hidesOnEsc">
|
|
911
993
|
we press [Escape] here
|
|
912
994
|
<div id="child-overlay--hidesOnOutsideEsc"></div>
|
|
913
995
|
</div>`,
|
|
914
|
-
)
|
|
915
|
-
);
|
|
996
|
+
);
|
|
916
997
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
917
998
|
await mimicEscapePress(parentContent);
|
|
918
|
-
|
|
919
999
|
expect(parentOverlay.isShown).to.be.false;
|
|
920
1000
|
expect(childOverlay.isShown).to.be.false;
|
|
921
1001
|
});
|
|
922
1002
|
});
|
|
923
1003
|
describe('Parent has hidesOnOutsideEsc and child has hidesOnEsc', () => {
|
|
924
1004
|
it('on [Escape] press in child overlay: parent stays shown, child hides', async () => {
|
|
925
|
-
const parentContent =
|
|
1005
|
+
const parentContent =
|
|
1006
|
+
/** @type {HTMLDivElement} */
|
|
926
1007
|
await fixture(
|
|
927
1008
|
html` <!-- -->
|
|
928
1009
|
<div id="parent-overlay--hidesOnOutsideEsc">
|
|
929
1010
|
<div id="child-overlay--hidesOnEsc">we press [Escape] here</div>
|
|
930
1011
|
</div>`,
|
|
931
|
-
)
|
|
932
|
-
);
|
|
1012
|
+
);
|
|
933
1013
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
934
1014
|
await mimicEscapePress(childOverlay.contentNode);
|
|
935
|
-
|
|
936
1015
|
expect(parentOverlay.isShown).to.be.true;
|
|
937
1016
|
expect(childOverlay.isShown).to.be.false;
|
|
938
1017
|
});
|
|
939
|
-
|
|
940
1018
|
it('on [Escape] press outside overlays: parent hides, child stays shown', async () => {
|
|
941
|
-
const parentContent =
|
|
1019
|
+
const parentContent =
|
|
1020
|
+
/** @type {HTMLDivElement} */
|
|
942
1021
|
await fixture(
|
|
943
1022
|
html` <!-- we press [Escape] here -->
|
|
944
1023
|
<div id="parent-overlay--hidesOnOutsideEsc">
|
|
945
1024
|
<div id="child-overlay--hidesOnEsc"></div>
|
|
946
1025
|
</div>`,
|
|
947
|
-
)
|
|
948
|
-
);
|
|
1026
|
+
);
|
|
949
1027
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
950
1028
|
await mimicEscapePress(document);
|
|
951
|
-
|
|
952
1029
|
expect(parentOverlay.isShown).to.be.false;
|
|
953
1030
|
expect(childOverlay.isShown).to.be.true;
|
|
954
1031
|
});
|
|
955
|
-
|
|
956
1032
|
it('on [Escape] press in parent overlay: parent hides, child stays shown', async () => {
|
|
957
|
-
const parentContent =
|
|
1033
|
+
const parentContent =
|
|
1034
|
+
/** @type {HTMLDivElement} */
|
|
958
1035
|
await fixture(
|
|
959
1036
|
html` <!-- we press [Escape] here -->
|
|
960
1037
|
<div id="parent-overlay--hidesOnOutsideEsc">
|
|
961
1038
|
<div id="child-overlay--hidesOnEsc"></div>
|
|
962
1039
|
</div>`,
|
|
963
|
-
)
|
|
964
|
-
);
|
|
1040
|
+
);
|
|
965
1041
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
966
1042
|
await mimicEscapePress(document);
|
|
967
|
-
|
|
968
1043
|
expect(parentOverlay.isShown).to.be.false;
|
|
969
1044
|
expect(childOverlay.isShown).to.be.true;
|
|
970
1045
|
});
|
|
971
1046
|
});
|
|
972
|
-
|
|
973
1047
|
describe('With shadow dom', () => {
|
|
974
1048
|
it('on [Escape] press in child overlay in shadow root: parent hides, child stays shown', async () => {
|
|
975
|
-
const parentContent =
|
|
1049
|
+
const parentContent =
|
|
1050
|
+
/** @type {HTMLDivElement} */
|
|
976
1051
|
await fixture(
|
|
977
1052
|
html` <!-- -->
|
|
978
1053
|
<div id="parent-overlay--hidesOnEsc" data-convert-to-shadow-root>
|
|
979
1054
|
<div id="child-overlay--hidesOnOutsideEsc">we press [Escape] here</div>
|
|
980
1055
|
</div>`,
|
|
981
|
-
)
|
|
982
|
-
);
|
|
1056
|
+
);
|
|
983
1057
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
984
1058
|
await mimicEscapePress(childOverlay.contentNode);
|
|
985
|
-
|
|
986
1059
|
expect(parentOverlay.isShown).to.be.false;
|
|
987
1060
|
expect(childOverlay.isShown).to.be.true;
|
|
988
1061
|
});
|
|
@@ -990,7 +1063,7 @@ describe('OverlayController', () => {
|
|
|
990
1063
|
});
|
|
991
1064
|
describe('hidesOnOutsideClick', () => {
|
|
992
1065
|
it('hides on outside click', async () => {
|
|
993
|
-
const contentNode = /** @type {HTMLElement} */
|
|
1066
|
+
const contentNode = /** @type {HTMLElement} */ await fixture('<div>Content</div>');
|
|
994
1067
|
const ctrl = new OverlayController({
|
|
995
1068
|
...withGlobalTestConfig(),
|
|
996
1069
|
hidesOnOutsideClick: true,
|
|
@@ -1000,16 +1073,16 @@ describe('OverlayController', () => {
|
|
|
1000
1073
|
mimicClick(document.body);
|
|
1001
1074
|
await aTimeout(0);
|
|
1002
1075
|
expect(ctrl.isShown).to.be.false;
|
|
1003
|
-
|
|
1004
1076
|
await ctrl.show();
|
|
1005
|
-
await mimicClick(document.body, {
|
|
1077
|
+
await mimicClick(document.body, {
|
|
1078
|
+
isAsync: true,
|
|
1079
|
+
});
|
|
1006
1080
|
await aTimeout(0);
|
|
1007
1081
|
expect(ctrl.isShown).to.be.false;
|
|
1008
1082
|
});
|
|
1009
|
-
|
|
1010
1083
|
it('doesn\'t hide on "inside" click', async () => {
|
|
1011
|
-
const invokerNode = /** @type {HTMLElement} */
|
|
1012
|
-
const contentNode = /** @type {HTMLElement} */
|
|
1084
|
+
const invokerNode = /** @type {HTMLElement} */ await fixture('<button>Invoker</button>');
|
|
1085
|
+
const contentNode = /** @type {HTMLElement} */ await fixture('<div>Content</div>');
|
|
1013
1086
|
const ctrl = new OverlayController({
|
|
1014
1087
|
...withGlobalTestConfig(),
|
|
1015
1088
|
hidesOnOutsideClick: true,
|
|
@@ -1026,12 +1099,13 @@ describe('OverlayController', () => {
|
|
|
1026
1099
|
// Don't hide on inside (content) click
|
|
1027
1100
|
ctrl.contentNode.click();
|
|
1028
1101
|
await aTimeout(0);
|
|
1029
|
-
|
|
1030
1102
|
expect(ctrl.isShown).to.be.true;
|
|
1031
1103
|
|
|
1032
1104
|
// Don't hide on inside mousedown & outside mouseup
|
|
1033
|
-
await mimicClick(ctrl.contentNode, {
|
|
1034
|
-
|
|
1105
|
+
await mimicClick(ctrl.contentNode, {
|
|
1106
|
+
releaseElement: document.body,
|
|
1107
|
+
isAsync: true,
|
|
1108
|
+
});
|
|
1035
1109
|
await aTimeout(0);
|
|
1036
1110
|
expect(ctrl.isShown).to.be.true;
|
|
1037
1111
|
|
|
@@ -1041,48 +1115,46 @@ describe('OverlayController', () => {
|
|
|
1041
1115
|
await ctrl.show();
|
|
1042
1116
|
expect(ctrl.isShown).to.be.true;
|
|
1043
1117
|
});
|
|
1044
|
-
|
|
1045
1118
|
it('only hides when both mousedown and mouseup events are outside', async () => {
|
|
1046
|
-
const contentNode = /** @type {HTMLElement} */
|
|
1119
|
+
const contentNode = /** @type {HTMLElement} */ await fixture('<div>Content</div>');
|
|
1047
1120
|
const ctrl = new OverlayController({
|
|
1048
1121
|
...withGlobalTestConfig(),
|
|
1049
1122
|
hidesOnOutsideClick: true,
|
|
1050
1123
|
contentNode,
|
|
1051
|
-
invokerNode:
|
|
1124
|
+
invokerNode:
|
|
1125
|
+
/** @type {HTMLElement} */
|
|
1052
1126
|
fixtureSync(html`
|
|
1053
1127
|
<div role="button" style="width: 100px; height: 20px;">Invoker</div>
|
|
1054
|
-
`)
|
|
1055
|
-
),
|
|
1128
|
+
`),
|
|
1056
1129
|
});
|
|
1057
1130
|
await ctrl.show();
|
|
1058
|
-
mimicClick(document.body, {
|
|
1131
|
+
mimicClick(document.body, {
|
|
1132
|
+
releaseElement: contentNode,
|
|
1133
|
+
});
|
|
1059
1134
|
await aTimeout(0);
|
|
1060
1135
|
expect(ctrl.isShown).to.be.true;
|
|
1061
|
-
|
|
1062
|
-
|
|
1136
|
+
mimicClick(contentNode, {
|
|
1137
|
+
releaseElement: document.body,
|
|
1138
|
+
});
|
|
1063
1139
|
await aTimeout(0);
|
|
1064
1140
|
expect(ctrl.isShown).to.be.true;
|
|
1065
|
-
|
|
1066
1141
|
mimicClick(document.body, {
|
|
1067
|
-
releaseElement: /** @type {HTMLElement} */
|
|
1142
|
+
releaseElement: /** @type {HTMLElement} */ ctrl.invokerNode,
|
|
1068
1143
|
});
|
|
1069
1144
|
await aTimeout(0);
|
|
1070
1145
|
expect(ctrl.isShown).to.be.true;
|
|
1071
|
-
|
|
1072
|
-
mimicClick(/** @type {HTMLElement} */ (ctrl.invokerNode), {
|
|
1146
|
+
mimicClick(/** @type {HTMLElement} */ ctrl.invokerNode, {
|
|
1073
1147
|
releaseElement: document.body,
|
|
1074
1148
|
});
|
|
1075
1149
|
await aTimeout(0);
|
|
1076
1150
|
expect(ctrl.isShown).to.be.true;
|
|
1077
|
-
|
|
1078
1151
|
mimicClick(document.body);
|
|
1079
1152
|
await aTimeout(0);
|
|
1080
1153
|
expect(ctrl.isShown).to.be.false;
|
|
1081
1154
|
});
|
|
1082
|
-
|
|
1083
1155
|
it('doesn\'t hide on "inside sub shadow dom" click', async () => {
|
|
1084
|
-
const invokerNode = /** @type {HTMLElement} */
|
|
1085
|
-
const contentNode = /** @type {HTMLElement} */
|
|
1156
|
+
const invokerNode = /** @type {HTMLElement} */ await fixture('<button>Invoker</button>');
|
|
1157
|
+
const contentNode = /** @type {HTMLElement} */ await fixture('<div>Content</div>');
|
|
1086
1158
|
const ctrl = new OverlayController({
|
|
1087
1159
|
...withGlobalTestConfig(),
|
|
1088
1160
|
hidesOnOutsideClick: true,
|
|
@@ -1096,25 +1168,26 @@ describe('OverlayController', () => {
|
|
|
1096
1168
|
class extends HTMLElement {
|
|
1097
1169
|
constructor() {
|
|
1098
1170
|
super();
|
|
1099
|
-
this.attachShadow({
|
|
1171
|
+
this.attachShadow({
|
|
1172
|
+
mode: 'open',
|
|
1173
|
+
});
|
|
1100
1174
|
}
|
|
1101
|
-
|
|
1102
1175
|
connectedCallback() {
|
|
1103
1176
|
/** @type {ShadowRoot} */
|
|
1104
|
-
|
|
1177
|
+
this.shadowRoot.innerHTML = '<div><button>click me</button></div>';
|
|
1105
1178
|
}
|
|
1106
1179
|
},
|
|
1107
1180
|
);
|
|
1108
1181
|
const tag = unsafeStatic(tagString);
|
|
1109
1182
|
ctrl.updateConfig({
|
|
1110
|
-
contentNode:
|
|
1183
|
+
contentNode:
|
|
1184
|
+
/** @type {HTMLElement} */
|
|
1111
1185
|
await fixture(html`
|
|
1112
1186
|
<div>
|
|
1113
1187
|
<div>Content</div>
|
|
1114
1188
|
<${tag}></${tag}>
|
|
1115
1189
|
</div>
|
|
1116
|
-
`)
|
|
1117
|
-
),
|
|
1190
|
+
`),
|
|
1118
1191
|
});
|
|
1119
1192
|
await ctrl.show();
|
|
1120
1193
|
|
|
@@ -1122,7 +1195,6 @@ describe('OverlayController', () => {
|
|
|
1122
1195
|
/** @type {ShadowRoot} */
|
|
1123
1196
|
// @ts-expect-error
|
|
1124
1197
|
ctrl.contentNode.querySelector(tagString).shadowRoot.querySelector('button').click();
|
|
1125
|
-
|
|
1126
1198
|
await aTimeout(0);
|
|
1127
1199
|
expect(ctrl.isShown).to.be.true;
|
|
1128
1200
|
|
|
@@ -1132,12 +1204,11 @@ describe('OverlayController', () => {
|
|
|
1132
1204
|
await ctrl.show();
|
|
1133
1205
|
expect(ctrl.isShown).to.be.true;
|
|
1134
1206
|
});
|
|
1135
|
-
|
|
1136
1207
|
it('works with 3rd party code using "event.stopPropagation()" on bubble phase', async () => {
|
|
1137
|
-
const invokerNode =
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
const contentNode = /** @type {HTMLElement} */
|
|
1208
|
+
const invokerNode =
|
|
1209
|
+
/** @type {HTMLElement} */
|
|
1210
|
+
await fixture('<div role="button">Invoker</div>');
|
|
1211
|
+
const contentNode = /** @type {HTMLElement} */ await fixture('<div>Content</div>');
|
|
1141
1212
|
const ctrl = new OverlayController({
|
|
1142
1213
|
...withLocalTestConfig(),
|
|
1143
1214
|
hidesOnOutsideClick: true,
|
|
@@ -1145,22 +1216,17 @@ describe('OverlayController', () => {
|
|
|
1145
1216
|
invokerNode,
|
|
1146
1217
|
});
|
|
1147
1218
|
const stopProp = (/** @type {Event} */ e) => e.stopPropagation();
|
|
1148
|
-
const dom = await fixture(
|
|
1149
|
-
`
|
|
1219
|
+
const dom = await fixture(`
|
|
1150
1220
|
<div>
|
|
1151
1221
|
<div id="popup">${invokerNode}${contentNode}</div>
|
|
1152
1222
|
<div id="third-party-noise" @click="${stopProp}" @mousedown="${stopProp}" @mouseup="${stopProp}">
|
|
1153
1223
|
This element prevents our handlers from reaching the document click handler.
|
|
1154
1224
|
</div>
|
|
1155
1225
|
</div>
|
|
1156
|
-
|
|
1157
|
-
);
|
|
1158
|
-
|
|
1226
|
+
`);
|
|
1159
1227
|
await ctrl.show();
|
|
1160
1228
|
expect(ctrl.isShown).to.equal(true);
|
|
1161
|
-
|
|
1162
|
-
const noiseEl = /** @type {HTMLElement} */ (dom.querySelector('#third-party-noise'));
|
|
1163
|
-
|
|
1229
|
+
const noiseEl = /** @type {HTMLElement} */ dom.querySelector('#third-party-noise');
|
|
1164
1230
|
mimicClick(noiseEl);
|
|
1165
1231
|
await aTimeout(0);
|
|
1166
1232
|
expect(ctrl.isShown).to.equal(false);
|
|
@@ -1169,12 +1235,11 @@ describe('OverlayController', () => {
|
|
|
1169
1235
|
await ctrl.show();
|
|
1170
1236
|
expect(ctrl.isShown).to.equal(true);
|
|
1171
1237
|
});
|
|
1172
|
-
|
|
1173
1238
|
it('works with 3rd party code using "event.stopPropagation()" on capture phase', async () => {
|
|
1174
|
-
const invokerNode =
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
const contentNode = /** @type {HTMLElement} */
|
|
1239
|
+
const invokerNode =
|
|
1240
|
+
/** @type {HTMLElement} */
|
|
1241
|
+
await fixture(html`<div role="button">Invoker</div>`);
|
|
1242
|
+
const contentNode = /** @type {HTMLElement} */ await fixture('<div>Content</div>');
|
|
1178
1243
|
const ctrl = new OverlayController({
|
|
1179
1244
|
...withLocalTestConfig(),
|
|
1180
1245
|
hidesOnOutsideClick: true,
|
|
@@ -1182,7 +1247,8 @@ describe('OverlayController', () => {
|
|
|
1182
1247
|
invokerNode,
|
|
1183
1248
|
});
|
|
1184
1249
|
const stopProp = (/** @type {Event} */ e) => e.stopPropagation();
|
|
1185
|
-
const dom =
|
|
1250
|
+
const dom =
|
|
1251
|
+
/** @type {HTMLElement} */
|
|
1186
1252
|
await fixture(`
|
|
1187
1253
|
<div>
|
|
1188
1254
|
<div id="popup">${invokerNode}${ctrl.content}</div>
|
|
@@ -1190,18 +1256,13 @@ describe('OverlayController', () => {
|
|
|
1190
1256
|
This element prevents our handlers from reaching the document click handler.
|
|
1191
1257
|
</div>
|
|
1192
1258
|
</div>
|
|
1193
|
-
`)
|
|
1194
|
-
);
|
|
1195
|
-
|
|
1196
|
-
const noiseEl = /** @type {HTMLElement} */ (dom.querySelector('#third-party-noise'));
|
|
1197
|
-
|
|
1259
|
+
`);
|
|
1260
|
+
const noiseEl = /** @type {HTMLElement} */ dom.querySelector('#third-party-noise');
|
|
1198
1261
|
noiseEl.addEventListener('click', stopProp, true);
|
|
1199
1262
|
noiseEl.addEventListener('mousedown', stopProp, true);
|
|
1200
1263
|
noiseEl.addEventListener('mouseup', stopProp, true);
|
|
1201
|
-
|
|
1202
1264
|
await ctrl.show();
|
|
1203
1265
|
expect(ctrl.isShown).to.equal(true);
|
|
1204
|
-
|
|
1205
1266
|
mimicClick(noiseEl);
|
|
1206
1267
|
await aTimeout(0);
|
|
1207
1268
|
expect(ctrl.isShown).to.equal(false);
|
|
@@ -1210,17 +1271,16 @@ describe('OverlayController', () => {
|
|
|
1210
1271
|
await ctrl.show();
|
|
1211
1272
|
expect(ctrl.isShown).to.equal(true);
|
|
1212
1273
|
});
|
|
1213
|
-
|
|
1214
1274
|
it('doesn\'t hide on "inside label" click', async () => {
|
|
1215
|
-
const contentNode =
|
|
1275
|
+
const contentNode =
|
|
1276
|
+
/** @type {HTMLElement} */
|
|
1216
1277
|
await fixture(`
|
|
1217
1278
|
<div>
|
|
1218
1279
|
<label for="test">test</label>
|
|
1219
1280
|
<input id="test">
|
|
1220
1281
|
Content
|
|
1221
|
-
</div>`)
|
|
1222
|
-
);
|
|
1223
|
-
const labelNode = /** @type {HTMLElement} */ (contentNode.querySelector('label[for=test]'));
|
|
1282
|
+
</div>`);
|
|
1283
|
+
const labelNode = /** @type {HTMLElement} */ contentNode.querySelector('label[for=test]');
|
|
1224
1284
|
const ctrl = new OverlayController({
|
|
1225
1285
|
...withGlobalTestConfig(),
|
|
1226
1286
|
hidesOnOutsideClick: true,
|
|
@@ -1231,27 +1291,22 @@ describe('OverlayController', () => {
|
|
|
1231
1291
|
// Don't hide on label click
|
|
1232
1292
|
labelNode.click();
|
|
1233
1293
|
await aTimeout(0);
|
|
1234
|
-
|
|
1235
1294
|
expect(ctrl.isShown).to.be.true;
|
|
1236
1295
|
});
|
|
1237
|
-
|
|
1238
1296
|
it('hides when window is blurred (useful for iframes)', async () => {
|
|
1239
1297
|
const ctrl = new OverlayController({
|
|
1240
1298
|
...withGlobalTestConfig(),
|
|
1241
1299
|
hidesOnOutsideClick: true,
|
|
1242
1300
|
});
|
|
1243
1301
|
await ctrl.show();
|
|
1244
|
-
|
|
1245
1302
|
window.dispatchEvent(new Event('blur'));
|
|
1246
1303
|
await aTimeout(0);
|
|
1247
|
-
|
|
1248
1304
|
expect(ctrl.isShown).to.be.false;
|
|
1249
1305
|
});
|
|
1250
1306
|
});
|
|
1251
|
-
|
|
1252
1307
|
describe('elementToFocusAfterHide', () => {
|
|
1253
1308
|
it('focuses body when hiding by default', async () => {
|
|
1254
|
-
const contentNode = /** @type {HTMLElement} */
|
|
1309
|
+
const contentNode = /** @type {HTMLElement} */ await fixture('<div><input /></div>');
|
|
1255
1310
|
const ctrl = new OverlayController({
|
|
1256
1311
|
...withGlobalTestConfig(),
|
|
1257
1312
|
viewportConfig: {
|
|
@@ -1259,90 +1314,78 @@ describe('OverlayController', () => {
|
|
|
1259
1314
|
},
|
|
1260
1315
|
contentNode,
|
|
1261
1316
|
});
|
|
1262
|
-
|
|
1263
1317
|
await ctrl.show();
|
|
1264
|
-
const input = /** @type {HTMLInputElement} */
|
|
1318
|
+
const input = /** @type {HTMLInputElement} */ contentNode.querySelector('input');
|
|
1265
1319
|
input.focus();
|
|
1266
1320
|
expect(isActiveElement(input)).to.be.true;
|
|
1267
|
-
|
|
1268
1321
|
await ctrl.hide();
|
|
1269
1322
|
expect(isActiveElement(document.body)).to.be.true;
|
|
1270
1323
|
});
|
|
1271
|
-
|
|
1272
1324
|
it('supports elementToFocusAfterHide option to focus it when hiding', async () => {
|
|
1273
|
-
const input = /** @type {HTMLElement} */
|
|
1274
|
-
const contentNode =
|
|
1275
|
-
|
|
1276
|
-
|
|
1325
|
+
const input = /** @type {HTMLElement} */ await fixture('<input />');
|
|
1326
|
+
const contentNode =
|
|
1327
|
+
/** @type {HTMLElement} */
|
|
1328
|
+
await fixture('<div><textarea></textarea></div>');
|
|
1277
1329
|
const ctrl = new OverlayController({
|
|
1278
1330
|
...withGlobalTestConfig(),
|
|
1279
1331
|
elementToFocusAfterHide: input,
|
|
1280
1332
|
contentNode,
|
|
1281
1333
|
});
|
|
1282
|
-
|
|
1283
1334
|
await ctrl.show();
|
|
1284
|
-
const textarea = /** @type {HTMLTextAreaElement} */
|
|
1335
|
+
const textarea = /** @type {HTMLTextAreaElement} */ contentNode.querySelector('textarea');
|
|
1285
1336
|
textarea.focus();
|
|
1286
1337
|
expect(isActiveElement(textarea)).to.be.true;
|
|
1287
|
-
|
|
1288
1338
|
await ctrl.hide();
|
|
1289
1339
|
expect(isActiveElement(input)).to.be.true;
|
|
1290
1340
|
expect(isInViewport(input)).to.be.true;
|
|
1291
1341
|
});
|
|
1292
|
-
|
|
1293
1342
|
it('supports elementToFocusAfterHide option when shadowRoot involved', async () => {
|
|
1294
|
-
const input = /** @type {HTMLElement} */
|
|
1295
|
-
const contentNode =
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1343
|
+
const input = /** @type {HTMLElement} */ await fixture('<input />');
|
|
1344
|
+
const contentNode =
|
|
1345
|
+
/** @type {HTMLElement} */
|
|
1346
|
+
await fixture('<div><textarea></textarea></div>');
|
|
1299
1347
|
const shadowHost = document.createElement('div');
|
|
1300
|
-
shadowHost.attachShadow({
|
|
1301
|
-
|
|
1348
|
+
shadowHost.attachShadow({
|
|
1349
|
+
mode: 'open',
|
|
1350
|
+
});
|
|
1351
|
+
/** @type {ShadowRoot} */
|
|
1352
|
+
shadowHost.shadowRoot.innerHTML = `<slot></slot>`;
|
|
1302
1353
|
shadowHost.appendChild(contentNode);
|
|
1303
1354
|
document.body.appendChild(shadowHost);
|
|
1304
|
-
|
|
1305
1355
|
const ctrl = new OverlayController({
|
|
1306
1356
|
...withGlobalTestConfig(),
|
|
1307
1357
|
elementToFocusAfterHide: input,
|
|
1308
1358
|
contentNode,
|
|
1309
1359
|
});
|
|
1310
|
-
|
|
1311
1360
|
await ctrl.show();
|
|
1312
|
-
const textarea = /** @type {HTMLTextAreaElement} */
|
|
1361
|
+
const textarea = /** @type {HTMLTextAreaElement} */ contentNode.querySelector('textarea');
|
|
1313
1362
|
textarea.focus();
|
|
1314
1363
|
expect(isActiveElement(textarea)).to.be.true;
|
|
1315
|
-
|
|
1316
1364
|
await ctrl.hide();
|
|
1317
1365
|
expect(isActiveElement(input)).to.be.true;
|
|
1318
|
-
|
|
1319
1366
|
document.body.removeChild(shadowHost);
|
|
1320
1367
|
});
|
|
1321
|
-
|
|
1322
1368
|
it(`only sets focus when outside world didn't take over already`, async () => {
|
|
1323
|
-
const input = /** @type {HTMLElement} */
|
|
1324
|
-
const outsideButton = /** @type {HTMLButtonElement} */
|
|
1325
|
-
const contentNode = /** @type {HTMLElement} */
|
|
1369
|
+
const input = /** @type {HTMLElement} */ await fixture('<input />');
|
|
1370
|
+
const outsideButton = /** @type {HTMLButtonElement} */ await fixture('<button></button>');
|
|
1371
|
+
const contentNode = /** @type {HTMLElement} */ await fixture('<div>/div>');
|
|
1326
1372
|
const ctrl = new OverlayController({
|
|
1327
1373
|
...withGlobalTestConfig(),
|
|
1328
1374
|
elementToFocusAfterHide: input,
|
|
1329
1375
|
contentNode,
|
|
1330
1376
|
});
|
|
1331
|
-
|
|
1332
1377
|
await ctrl.show();
|
|
1333
1378
|
// an outside element has taken over focus
|
|
1334
1379
|
outsideButton.focus();
|
|
1335
1380
|
expect(isActiveElement(outsideButton)).to.be.true;
|
|
1336
|
-
|
|
1337
1381
|
await ctrl.hide();
|
|
1338
1382
|
expect(isActiveElement(outsideButton)).to.be.true;
|
|
1339
1383
|
});
|
|
1340
|
-
|
|
1341
1384
|
it('allows to set elementToFocusAfterHide on show', async () => {
|
|
1342
|
-
const input = /** @type {HTMLElement} */
|
|
1343
|
-
const contentNode =
|
|
1344
|
-
|
|
1345
|
-
|
|
1385
|
+
const input = /** @type {HTMLElement} */ await fixture('<input />');
|
|
1386
|
+
const contentNode =
|
|
1387
|
+
/** @type {HTMLElement} */
|
|
1388
|
+
await fixture('<div><textarea></textarea></div>');
|
|
1346
1389
|
const ctrl = new OverlayController({
|
|
1347
1390
|
...withGlobalTestConfig(),
|
|
1348
1391
|
viewportConfig: {
|
|
@@ -1350,31 +1393,25 @@ describe('OverlayController', () => {
|
|
|
1350
1393
|
},
|
|
1351
1394
|
contentNode,
|
|
1352
1395
|
});
|
|
1353
|
-
|
|
1354
1396
|
await ctrl.show(input);
|
|
1355
|
-
const textarea = /** @type {HTMLTextAreaElement} */
|
|
1397
|
+
const textarea = /** @type {HTMLTextAreaElement} */ contentNode.querySelector('textarea');
|
|
1356
1398
|
textarea.focus();
|
|
1357
1399
|
expect(isActiveElement(textarea)).to.be.true;
|
|
1358
|
-
|
|
1359
1400
|
await ctrl.hide();
|
|
1360
1401
|
expect(isActiveElement(input)).to.be.true;
|
|
1361
1402
|
});
|
|
1362
1403
|
});
|
|
1363
|
-
|
|
1364
1404
|
describe('preventsScroll', () => {
|
|
1365
1405
|
it('prevent scrolling the background', async () => {
|
|
1366
1406
|
const ctrl = new OverlayController({
|
|
1367
1407
|
...withGlobalTestConfig(),
|
|
1368
1408
|
preventsScroll: true,
|
|
1369
1409
|
});
|
|
1370
|
-
|
|
1371
1410
|
await ctrl.show();
|
|
1372
1411
|
expect(Array.from(document.body.classList)).to.contain('overlays-scroll-lock');
|
|
1373
|
-
|
|
1374
1412
|
await ctrl.hide();
|
|
1375
1413
|
expect(Array.from(document.body.classList)).to.not.contain('overlays-scroll-lock');
|
|
1376
1414
|
});
|
|
1377
|
-
|
|
1378
1415
|
it('keeps preventing of scrolling when multiple overlays are opened and closed', async () => {
|
|
1379
1416
|
const ctrl0 = new OverlayController({
|
|
1380
1417
|
...withGlobalTestConfig(),
|
|
@@ -1384,13 +1421,11 @@ describe('OverlayController', () => {
|
|
|
1384
1421
|
...withGlobalTestConfig(),
|
|
1385
1422
|
preventsScroll: true,
|
|
1386
1423
|
});
|
|
1387
|
-
|
|
1388
1424
|
await ctrl0.show();
|
|
1389
1425
|
await ctrl1.show();
|
|
1390
1426
|
await ctrl1.hide();
|
|
1391
1427
|
expect(Array.from(document.body.classList)).to.contain('overlays-scroll-lock');
|
|
1392
1428
|
});
|
|
1393
|
-
|
|
1394
1429
|
it('does not accumulate body margins when nested overlays have preventsScroll', async () => {
|
|
1395
1430
|
const ctrl0 = new OverlayController({
|
|
1396
1431
|
...withGlobalTestConfig(),
|
|
@@ -1400,45 +1435,35 @@ describe('OverlayController', () => {
|
|
|
1400
1435
|
...withGlobalTestConfig(),
|
|
1401
1436
|
preventsScroll: true,
|
|
1402
1437
|
});
|
|
1403
|
-
|
|
1404
1438
|
const originalMarginRight = document.body.style.marginRight;
|
|
1405
|
-
|
|
1406
1439
|
await ctrl0.show();
|
|
1407
1440
|
const marginAfterFirst = document.body.style.marginRight;
|
|
1408
|
-
|
|
1409
1441
|
await ctrl1.show();
|
|
1410
1442
|
const marginAfterSecond = document.body.style.marginRight;
|
|
1411
1443
|
|
|
1412
1444
|
// The margin should NOT increase further when second overlay opens
|
|
1413
1445
|
expect(marginAfterSecond).to.equal(marginAfterFirst);
|
|
1414
|
-
|
|
1415
1446
|
await ctrl1.hide();
|
|
1416
1447
|
// After hiding second, first still prevents scroll — margin stays
|
|
1417
1448
|
expect(document.body.style.marginRight).to.equal(marginAfterFirst);
|
|
1418
|
-
|
|
1419
1449
|
await ctrl0.hide();
|
|
1420
1450
|
// After hiding all, original margin is restored
|
|
1421
1451
|
expect(document.body.style.marginRight).to.equal(originalMarginRight);
|
|
1422
1452
|
});
|
|
1423
|
-
|
|
1424
1453
|
it('restores body margin when overlay with preventsScroll is torn down while shown', async () => {
|
|
1425
1454
|
const ctrl = new OverlayController({
|
|
1426
1455
|
...withGlobalTestConfig(),
|
|
1427
1456
|
preventsScroll: true,
|
|
1428
1457
|
});
|
|
1429
|
-
|
|
1430
1458
|
const originalMarginRight = document.body.style.marginRight;
|
|
1431
|
-
|
|
1432
1459
|
await ctrl.show();
|
|
1433
1460
|
const marginAfterShow = document.body.style.marginRight;
|
|
1434
1461
|
// Margin should be set after show
|
|
1435
1462
|
expect(marginAfterShow).to.not.equal(originalMarginRight);
|
|
1436
|
-
|
|
1437
1463
|
ctrl.teardown();
|
|
1438
1464
|
// Margin should be restored after teardown
|
|
1439
1465
|
expect(document.body.style.marginRight).to.equal(originalMarginRight);
|
|
1440
1466
|
});
|
|
1441
|
-
|
|
1442
1467
|
it('does not break body margin when teardown() is called on a hidden overlay', async () => {
|
|
1443
1468
|
const ctrl0 = new OverlayController({
|
|
1444
1469
|
...withGlobalTestConfig(),
|
|
@@ -1448,7 +1473,6 @@ describe('OverlayController', () => {
|
|
|
1448
1473
|
...withGlobalTestConfig(),
|
|
1449
1474
|
preventsScroll: true,
|
|
1450
1475
|
});
|
|
1451
|
-
|
|
1452
1476
|
const originalMarginRight = document.body.style.marginRight;
|
|
1453
1477
|
|
|
1454
1478
|
// Show first overlay
|
|
@@ -1466,13 +1490,11 @@ describe('OverlayController', () => {
|
|
|
1466
1490
|
// Now margin should be restored
|
|
1467
1491
|
expect(document.body.style.marginRight).to.equal(originalMarginRight);
|
|
1468
1492
|
});
|
|
1469
|
-
|
|
1470
1493
|
it('does not break body margin when updateConfig() is called on a hidden overlay', async () => {
|
|
1471
1494
|
const ctrl = new OverlayController({
|
|
1472
1495
|
...withGlobalTestConfig(),
|
|
1473
1496
|
preventsScroll: true,
|
|
1474
1497
|
});
|
|
1475
|
-
|
|
1476
1498
|
const originalMarginRight = document.body.style.marginRight;
|
|
1477
1499
|
|
|
1478
1500
|
// updateConfig calls teardown internally
|
|
@@ -1494,7 +1516,6 @@ describe('OverlayController', () => {
|
|
|
1494
1516
|
expect(document.body.style.marginRight).to.equal(originalMarginRight);
|
|
1495
1517
|
});
|
|
1496
1518
|
});
|
|
1497
|
-
|
|
1498
1519
|
describe('hasBackdrop', () => {
|
|
1499
1520
|
it('has no backdrop by default', async () => {
|
|
1500
1521
|
const ctrl = new OverlayController({
|
|
@@ -1503,7 +1524,6 @@ describe('OverlayController', () => {
|
|
|
1503
1524
|
await ctrl.show();
|
|
1504
1525
|
expect(ctrl.backdropNode).to.be.undefined;
|
|
1505
1526
|
});
|
|
1506
|
-
|
|
1507
1527
|
it('supports a backdrop option', async () => {
|
|
1508
1528
|
const ctrl = new OverlayController({
|
|
1509
1529
|
...withGlobalTestConfig(),
|
|
@@ -1512,7 +1532,6 @@ describe('OverlayController', () => {
|
|
|
1512
1532
|
await ctrl.show();
|
|
1513
1533
|
expect(ctrl.backdropNode).to.be.undefined;
|
|
1514
1534
|
await ctrl.hide();
|
|
1515
|
-
|
|
1516
1535
|
const controllerWithBackdrop = new OverlayController({
|
|
1517
1536
|
...withGlobalTestConfig(),
|
|
1518
1537
|
hasBackdrop: true,
|
|
@@ -1520,7 +1539,6 @@ describe('OverlayController', () => {
|
|
|
1520
1539
|
await controllerWithBackdrop.show();
|
|
1521
1540
|
expect(controllerWithBackdrop.backdropNode).to.have.class('overlays__backdrop');
|
|
1522
1541
|
});
|
|
1523
|
-
|
|
1524
1542
|
it('reenables the backdrop when shown/hidden/shown', async () => {
|
|
1525
1543
|
const ctrl = new OverlayController({
|
|
1526
1544
|
...withGlobalTestConfig(),
|
|
@@ -1532,7 +1550,6 @@ describe('OverlayController', () => {
|
|
|
1532
1550
|
await ctrl.show();
|
|
1533
1551
|
expect(ctrl.backdropNode).to.have.class('overlays__backdrop');
|
|
1534
1552
|
});
|
|
1535
|
-
|
|
1536
1553
|
it('adds and stacks backdrops if .hasBackdrop is enabled', async () => {
|
|
1537
1554
|
const ctrl0 = new OverlayController({
|
|
1538
1555
|
...withGlobalTestConfig(),
|
|
@@ -1540,7 +1557,6 @@ describe('OverlayController', () => {
|
|
|
1540
1557
|
});
|
|
1541
1558
|
await ctrl0.show();
|
|
1542
1559
|
expect(ctrl0.backdropNode).to.have.class('overlays__backdrop');
|
|
1543
|
-
|
|
1544
1560
|
const ctrl1 = new OverlayController({
|
|
1545
1561
|
...withGlobalTestConfig(),
|
|
1546
1562
|
hasBackdrop: false,
|
|
@@ -1548,19 +1564,16 @@ describe('OverlayController', () => {
|
|
|
1548
1564
|
await ctrl1.show();
|
|
1549
1565
|
expect(ctrl0.backdropNode).to.have.class('overlays__backdrop');
|
|
1550
1566
|
expect(ctrl1.backdropNode).to.be.undefined;
|
|
1551
|
-
|
|
1552
1567
|
const ctrl2 = new OverlayController({
|
|
1553
1568
|
...withGlobalTestConfig(),
|
|
1554
1569
|
hasBackdrop: true,
|
|
1555
1570
|
});
|
|
1556
1571
|
await ctrl2.show();
|
|
1557
|
-
|
|
1558
1572
|
expect(ctrl0.backdropNode).to.have.class('overlays__backdrop');
|
|
1559
1573
|
expect(ctrl1.backdropNode).to.be.undefined;
|
|
1560
1574
|
expect(ctrl2.backdropNode).to.have.class('overlays__backdrop');
|
|
1561
1575
|
});
|
|
1562
1576
|
});
|
|
1563
|
-
|
|
1564
1577
|
describe('locally placed overlay with hasBackdrop', () => {
|
|
1565
1578
|
it('has no backdrop by default', async () => {
|
|
1566
1579
|
const ctrl = new OverlayController({
|
|
@@ -1569,7 +1582,6 @@ describe('OverlayController', () => {
|
|
|
1569
1582
|
await ctrl.show();
|
|
1570
1583
|
expect(ctrl.backdropNode).to.be.undefined;
|
|
1571
1584
|
});
|
|
1572
|
-
|
|
1573
1585
|
it('supports a backdrop option', async () => {
|
|
1574
1586
|
const ctrl = new OverlayController({
|
|
1575
1587
|
...withLocalTestConfig(),
|
|
@@ -1578,10 +1590,8 @@ describe('OverlayController', () => {
|
|
|
1578
1590
|
await ctrl.show();
|
|
1579
1591
|
expect(ctrl.backdropNode).to.be.undefined;
|
|
1580
1592
|
await ctrl.hide();
|
|
1581
|
-
|
|
1582
1593
|
const backdropNode = document.createElement('div');
|
|
1583
1594
|
backdropNode.classList.add('custom-backdrop');
|
|
1584
|
-
|
|
1585
1595
|
const controllerWithBackdrop = new OverlayController({
|
|
1586
1596
|
...withLocalTestConfig(),
|
|
1587
1597
|
hasBackdrop: true,
|
|
@@ -1590,11 +1600,9 @@ describe('OverlayController', () => {
|
|
|
1590
1600
|
await controllerWithBackdrop.show();
|
|
1591
1601
|
expect(controllerWithBackdrop.backdropNode).to.have.class('custom-backdrop');
|
|
1592
1602
|
});
|
|
1593
|
-
|
|
1594
1603
|
it('reenables the backdrop when shown/hidden/shown', async () => {
|
|
1595
1604
|
const backdropNode = document.createElement('div');
|
|
1596
1605
|
backdropNode.classList.add('custom-backdrop');
|
|
1597
|
-
|
|
1598
1606
|
const ctrl = new OverlayController({
|
|
1599
1607
|
...withLocalTestConfig(),
|
|
1600
1608
|
hasBackdrop: true,
|
|
@@ -1606,11 +1614,9 @@ describe('OverlayController', () => {
|
|
|
1606
1614
|
await ctrl.show();
|
|
1607
1615
|
expect(ctrl.backdropNode).to.have.class('custom-backdrop');
|
|
1608
1616
|
});
|
|
1609
|
-
|
|
1610
1617
|
it('adds and stacks backdrops if .hasBackdrop is enabled', async () => {
|
|
1611
1618
|
const backdropNode = document.createElement('div');
|
|
1612
1619
|
backdropNode.classList.add('custom-backdrop-zero');
|
|
1613
|
-
|
|
1614
1620
|
const ctrl0 = new OverlayController({
|
|
1615
1621
|
...withLocalTestConfig(),
|
|
1616
1622
|
hasBackdrop: true,
|
|
@@ -1618,7 +1624,6 @@ describe('OverlayController', () => {
|
|
|
1618
1624
|
});
|
|
1619
1625
|
await ctrl0.show();
|
|
1620
1626
|
expect(ctrl0.backdropNode).to.have.class('custom-backdrop-zero');
|
|
1621
|
-
|
|
1622
1627
|
const ctrl1 = new OverlayController({
|
|
1623
1628
|
...withLocalTestConfig(),
|
|
1624
1629
|
hasBackdrop: false,
|
|
@@ -1626,23 +1631,19 @@ describe('OverlayController', () => {
|
|
|
1626
1631
|
await ctrl1.show();
|
|
1627
1632
|
expect(ctrl0.backdropNode).to.have.class('custom-backdrop-zero');
|
|
1628
1633
|
expect(ctrl1.backdropNode).to.be.undefined;
|
|
1629
|
-
|
|
1630
1634
|
const anotherBackdropNode = document.createElement('div');
|
|
1631
1635
|
anotherBackdropNode.classList.add('custom-backdrop-two');
|
|
1632
|
-
|
|
1633
1636
|
const ctrl2 = new OverlayController({
|
|
1634
1637
|
...withLocalTestConfig(),
|
|
1635
1638
|
hasBackdrop: true,
|
|
1636
1639
|
backdropNode: anotherBackdropNode,
|
|
1637
1640
|
});
|
|
1638
1641
|
await ctrl2.show();
|
|
1639
|
-
|
|
1640
1642
|
expect(ctrl0.backdropNode).to.have.class('custom-backdrop-zero');
|
|
1641
1643
|
expect(ctrl1.backdropNode).to.be.undefined;
|
|
1642
1644
|
expect(ctrl2.backdropNode).to.have.class('custom-backdrop-two');
|
|
1643
1645
|
});
|
|
1644
1646
|
});
|
|
1645
|
-
|
|
1646
1647
|
describe('isBlocking', () => {
|
|
1647
1648
|
it('prevents showing of other overlays', async () => {
|
|
1648
1649
|
const ctrl0 = new OverlayController({
|
|
@@ -1661,30 +1662,25 @@ describe('OverlayController', () => {
|
|
|
1661
1662
|
...withGlobalTestConfig(),
|
|
1662
1663
|
isBlocking: false,
|
|
1663
1664
|
});
|
|
1664
|
-
|
|
1665
1665
|
await ctrl0.show();
|
|
1666
1666
|
await ctrl1.show();
|
|
1667
1667
|
await ctrl2.show(); // blocking
|
|
1668
1668
|
expect(ctrl0.__wrappingDialogNode).to.not.be.displayed;
|
|
1669
1669
|
expect(ctrl1.__wrappingDialogNode).to.not.be.displayed;
|
|
1670
1670
|
expect(ctrl2.__wrappingDialogNode).to.be.displayed;
|
|
1671
|
-
|
|
1672
1671
|
await ctrl3.show();
|
|
1673
1672
|
await ctrl3._showComplete;
|
|
1674
1673
|
expect(ctrl3.__wrappingDialogNode).to.be.displayed;
|
|
1675
|
-
|
|
1676
1674
|
await ctrl2.hide();
|
|
1677
1675
|
await ctrl2._hideComplete;
|
|
1678
1676
|
expect(ctrl0.__wrappingDialogNode).to.be.displayed;
|
|
1679
1677
|
expect(ctrl1.__wrappingDialogNode).to.be.displayed;
|
|
1680
|
-
|
|
1681
1678
|
await ctrl2.show(); // blocking
|
|
1682
1679
|
expect(ctrl0.__wrappingDialogNode).to.not.be.displayed;
|
|
1683
1680
|
expect(ctrl1.__wrappingDialogNode).to.not.be.displayed;
|
|
1684
1681
|
expect(ctrl2.__wrappingDialogNode).to.be.displayed;
|
|
1685
1682
|
expect(ctrl3.__wrappingDialogNode).to.not.be.displayed;
|
|
1686
1683
|
});
|
|
1687
|
-
|
|
1688
1684
|
it('keeps backdrop status when used in combination with blocking', async () => {
|
|
1689
1685
|
const ctrl0 = new OverlayController({
|
|
1690
1686
|
...withGlobalTestConfig(),
|
|
@@ -1692,7 +1688,6 @@ describe('OverlayController', () => {
|
|
|
1692
1688
|
hasBackdrop: true,
|
|
1693
1689
|
});
|
|
1694
1690
|
await ctrl0.show();
|
|
1695
|
-
|
|
1696
1691
|
const ctrl1 = new OverlayController({
|
|
1697
1692
|
...withGlobalTestConfig(),
|
|
1698
1693
|
isBlocking: false,
|
|
@@ -1702,14 +1697,100 @@ describe('OverlayController', () => {
|
|
|
1702
1697
|
await ctrl1.hide();
|
|
1703
1698
|
expect(ctrl0.hasActiveBackdrop).to.be.true;
|
|
1704
1699
|
expect(ctrl1.hasActiveBackdrop).to.be.false;
|
|
1705
|
-
|
|
1706
1700
|
await ctrl1.show();
|
|
1707
1701
|
expect(ctrl0.hasActiveBackdrop).to.be.true;
|
|
1708
1702
|
expect(ctrl1.hasActiveBackdrop).to.be.true;
|
|
1709
1703
|
});
|
|
1710
1704
|
});
|
|
1711
|
-
|
|
1705
|
+
describe('elementToFocusOnShow', () => {
|
|
1706
|
+
it('adds tabindex="-1" to the content node when elementToFocusOnShow is true', async () => {
|
|
1707
|
+
const ctrl = new OverlayController({
|
|
1708
|
+
...withGlobalTestConfig(),
|
|
1709
|
+
isBlocking: false,
|
|
1710
|
+
elementToFocusOnShow: true,
|
|
1711
|
+
});
|
|
1712
|
+
const contentNode = /** @type {HTMLElement} */ await fixture('<div>Content</div>');
|
|
1713
|
+
ctrl.updateConfig({
|
|
1714
|
+
contentNode,
|
|
1715
|
+
});
|
|
1716
|
+
await ctrl.show();
|
|
1717
|
+
expect(contentNode.getAttribute('tabindex')).to.equal('-1');
|
|
1718
|
+
});
|
|
1719
|
+
it('makes contentNode the root of "next tab flow"', async () => {
|
|
1720
|
+
const ctrl = new OverlayController({
|
|
1721
|
+
...withGlobalTestConfig(),
|
|
1722
|
+
isBlocking: false,
|
|
1723
|
+
elementToFocusOnShow: true,
|
|
1724
|
+
});
|
|
1725
|
+
const contentNode =
|
|
1726
|
+
/** @type {HTMLElement} */
|
|
1727
|
+
await fixture('<div><button>Button</button></div>');
|
|
1728
|
+
ctrl.updateConfig({
|
|
1729
|
+
contentNode,
|
|
1730
|
+
});
|
|
1731
|
+
await ctrl.show();
|
|
1732
|
+
const button = /** @type {HTMLButtonElement} */ contentNode.querySelector('button');
|
|
1733
|
+
button.focus();
|
|
1734
|
+
expect(isActiveElement(button)).to.be.true;
|
|
1735
|
+
});
|
|
1736
|
+
});
|
|
1737
|
+
describe('syncChildrenCloseState', () => {
|
|
1738
|
+
it('does not close all children of nested controllers when syncChildrenCloseState is false', async () => {
|
|
1739
|
+
const parentContent =
|
|
1740
|
+
/** @type {HTMLDivElement} */
|
|
1741
|
+
await fixture(
|
|
1742
|
+
html` <!-- -->
|
|
1743
|
+
<div data-sync-children-close-state id="parent-overlay">
|
|
1744
|
+
<div id="child-overlay">we open our child and it will close when parent does</div>
|
|
1745
|
+
</div>`,
|
|
1746
|
+
);
|
|
1747
|
+
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
1748
|
+
expect(parentOverlay.isShown).to.be.true;
|
|
1749
|
+
expect(childOverlay.isShown).to.be.true;
|
|
1750
|
+
await parentOverlay.hide();
|
|
1751
|
+
await childOverlay._hideComplete;
|
|
1752
|
+
expect(parentOverlay.isShown).to.be.false;
|
|
1753
|
+
expect(childOverlay.isShown).to.be.false;
|
|
1754
|
+
});
|
|
1755
|
+
it('does not close all children of nested controllers when syncChildrenCloseState is false', async () => {
|
|
1756
|
+
const parentContent =
|
|
1757
|
+
/** @type {HTMLDivElement} */
|
|
1758
|
+
await fixture(
|
|
1759
|
+
html` <!-- -->
|
|
1760
|
+
<div id="parent-overlay">
|
|
1761
|
+
<div id="child-overlay">
|
|
1762
|
+
we open our child and it will not close when parent does
|
|
1763
|
+
</div>
|
|
1764
|
+
</div>`,
|
|
1765
|
+
);
|
|
1766
|
+
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
1767
|
+
expect(parentOverlay.isShown).to.be.true;
|
|
1768
|
+
expect(childOverlay.isShown).to.be.true;
|
|
1769
|
+
await parentOverlay.hide();
|
|
1770
|
+
expect(parentOverlay.isShown).to.be.false;
|
|
1771
|
+
expect(childOverlay.isShown).to.be.true;
|
|
1772
|
+
});
|
|
1773
|
+
});
|
|
1774
|
+
describe('isActivated', () => {
|
|
1775
|
+
it('allows to conditionally disable overlay/openable functionality (for responsive context like nav menus, accordions/collapsibles vs plain headings/content etc.)', async () => {
|
|
1776
|
+
const ctrl = new OverlayController({
|
|
1777
|
+
...withGlobalTestConfig(),
|
|
1778
|
+
isActivated: false,
|
|
1779
|
+
});
|
|
1780
|
+
expect(ctrl.__hasSetup).to.be.false;
|
|
1781
|
+
ctrl.updateConfig({
|
|
1782
|
+
isActivated: true,
|
|
1783
|
+
});
|
|
1784
|
+
expect(ctrl.__hasSetup).to.be.true;
|
|
1785
|
+
});
|
|
1786
|
+
});
|
|
1712
1787
|
|
|
1788
|
+
// TODO
|
|
1789
|
+
describe('hideVisually', () => {});
|
|
1790
|
+
|
|
1791
|
+
// TODO
|
|
1792
|
+
describe('requireConnectedNodes', () => {});
|
|
1793
|
+
});
|
|
1713
1794
|
describe('Show / Hide / Toggle', () => {
|
|
1714
1795
|
it('has .isShown which defaults to false', async () => {
|
|
1715
1796
|
const ctrl = new OverlayController({
|
|
@@ -1717,7 +1798,6 @@ describe('OverlayController', () => {
|
|
|
1717
1798
|
});
|
|
1718
1799
|
expect(ctrl.isShown).to.be.false;
|
|
1719
1800
|
});
|
|
1720
|
-
|
|
1721
1801
|
it('has async show() which shows the overlay', async () => {
|
|
1722
1802
|
const ctrl = new OverlayController({
|
|
1723
1803
|
...withGlobalTestConfig(),
|
|
@@ -1726,55 +1806,44 @@ describe('OverlayController', () => {
|
|
|
1726
1806
|
expect(ctrl.isShown).to.be.true;
|
|
1727
1807
|
expect(ctrl.show()).to.be.instanceOf(Promise);
|
|
1728
1808
|
});
|
|
1729
|
-
|
|
1730
1809
|
it('has async hide() which hides the overlay', async () => {
|
|
1731
1810
|
const ctrl = new OverlayController({
|
|
1732
1811
|
...withGlobalTestConfig(),
|
|
1733
1812
|
});
|
|
1734
|
-
|
|
1735
1813
|
await ctrl.hide();
|
|
1736
1814
|
expect(ctrl.isShown).to.be.false;
|
|
1737
1815
|
expect(ctrl.hide()).to.be.instanceOf(Promise);
|
|
1738
1816
|
});
|
|
1739
|
-
|
|
1740
1817
|
it('fires "show" event once overlay becomes shown', async () => {
|
|
1741
1818
|
const showSpy = sinon.spy();
|
|
1742
1819
|
const ctrl = new OverlayController({
|
|
1743
1820
|
...withGlobalTestConfig(),
|
|
1744
1821
|
});
|
|
1745
|
-
|
|
1746
1822
|
ctrl.addEventListener('show', showSpy);
|
|
1747
1823
|
await ctrl.show();
|
|
1748
1824
|
expect(showSpy.callCount).to.equal(1);
|
|
1749
1825
|
await ctrl.show();
|
|
1750
1826
|
expect(showSpy.callCount).to.equal(1);
|
|
1751
1827
|
});
|
|
1752
|
-
|
|
1753
1828
|
it('fires "before-show" event right before overlay becomes shown', async () => {
|
|
1754
1829
|
const ctrl = new OverlayController({
|
|
1755
1830
|
...withGlobalTestConfig(),
|
|
1756
1831
|
});
|
|
1757
|
-
|
|
1758
1832
|
const eventSpy = sinon.spy();
|
|
1759
|
-
|
|
1760
1833
|
ctrl.addEventListener('before-show', eventSpy);
|
|
1761
1834
|
ctrl.addEventListener('show', eventSpy);
|
|
1762
|
-
|
|
1763
1835
|
await ctrl.show();
|
|
1764
1836
|
expect(eventSpy.getCall(0).args[0].type).to.equal('before-show');
|
|
1765
1837
|
expect(eventSpy.getCall(1).args[0].type).to.equal('show');
|
|
1766
|
-
|
|
1767
1838
|
expect(eventSpy.callCount).to.equal(2);
|
|
1768
1839
|
await ctrl.show();
|
|
1769
1840
|
expect(eventSpy.callCount).to.equal(2);
|
|
1770
1841
|
});
|
|
1771
|
-
|
|
1772
1842
|
it('fires "hide" event once overlay becomes hidden', async () => {
|
|
1773
1843
|
const hideSpy = sinon.spy();
|
|
1774
1844
|
const ctrl = new OverlayController({
|
|
1775
1845
|
...withGlobalTestConfig(),
|
|
1776
1846
|
});
|
|
1777
|
-
|
|
1778
1847
|
ctrl.addEventListener('hide', hideSpy);
|
|
1779
1848
|
await ctrl.show();
|
|
1780
1849
|
await ctrl.hide();
|
|
@@ -1782,38 +1851,29 @@ describe('OverlayController', () => {
|
|
|
1782
1851
|
await ctrl.hide();
|
|
1783
1852
|
expect(hideSpy.callCount).to.equal(1);
|
|
1784
1853
|
});
|
|
1785
|
-
|
|
1786
1854
|
it('fires "before-hide" event right before overlay becomes hidden', async () => {
|
|
1787
1855
|
const ctrl = new OverlayController({
|
|
1788
1856
|
...withGlobalTestConfig(),
|
|
1789
1857
|
});
|
|
1790
|
-
|
|
1791
1858
|
const eventSpy = sinon.spy();
|
|
1792
|
-
|
|
1793
1859
|
ctrl.addEventListener('before-hide', eventSpy);
|
|
1794
1860
|
ctrl.addEventListener('hide', eventSpy);
|
|
1795
|
-
|
|
1796
1861
|
await ctrl.show();
|
|
1797
1862
|
await ctrl.hide();
|
|
1798
1863
|
expect(eventSpy.getCall(0).args[0].type).to.equal('before-hide');
|
|
1799
1864
|
expect(eventSpy.getCall(1).args[0].type).to.equal('hide');
|
|
1800
|
-
|
|
1801
1865
|
expect(eventSpy.callCount).to.equal(2);
|
|
1802
1866
|
await ctrl.hide();
|
|
1803
1867
|
expect(eventSpy.callCount).to.equal(2);
|
|
1804
1868
|
});
|
|
1805
|
-
|
|
1806
1869
|
it('can be toggled', async () => {
|
|
1807
1870
|
const ctrl = new OverlayController({
|
|
1808
1871
|
...withGlobalTestConfig(),
|
|
1809
1872
|
});
|
|
1810
|
-
|
|
1811
1873
|
await ctrl.toggle();
|
|
1812
1874
|
expect(ctrl.isShown).to.be.true;
|
|
1813
|
-
|
|
1814
1875
|
await ctrl.toggle();
|
|
1815
1876
|
expect(ctrl.isShown).to.be.false;
|
|
1816
|
-
|
|
1817
1877
|
await ctrl.toggle();
|
|
1818
1878
|
expect(ctrl.isShown).to.be.true;
|
|
1819
1879
|
|
|
@@ -1822,7 +1882,6 @@ describe('OverlayController', () => {
|
|
|
1822
1882
|
// check for show
|
|
1823
1883
|
expect(ctrl.toggle()).to.be.instanceOf(Promise);
|
|
1824
1884
|
});
|
|
1825
|
-
|
|
1826
1885
|
it('makes sure the latest shown overlay is visible', async () => {
|
|
1827
1886
|
const ctrl0 = new OverlayController({
|
|
1828
1887
|
...withGlobalTestConfig(),
|
|
@@ -1833,18 +1892,14 @@ describe('OverlayController', () => {
|
|
|
1833
1892
|
await ctrl0.show();
|
|
1834
1893
|
const rect = ctrl0.contentNode.getBoundingClientRect();
|
|
1835
1894
|
const getTopEl = () => document.elementFromPoint(Math.ceil(rect.left), Math.ceil(rect.top));
|
|
1836
|
-
|
|
1837
1895
|
await ctrl0.show();
|
|
1838
1896
|
expect(getTopEl()).to.equal(ctrl0.contentNode);
|
|
1839
|
-
|
|
1840
1897
|
await ctrl1.show();
|
|
1841
1898
|
expect(getTopEl()).to.equal(ctrl1.contentNode);
|
|
1842
|
-
|
|
1843
1899
|
await ctrl0.show();
|
|
1844
1900
|
expect(getTopEl()).to.equal(ctrl0.contentNode);
|
|
1845
1901
|
});
|
|
1846
|
-
|
|
1847
|
-
it('awaits a "transitionHide" hook before hiding for real', done => {
|
|
1902
|
+
it('awaits a "transitionHide" hook before hiding for real', (done) => {
|
|
1848
1903
|
const ctrl = new OverlayController({
|
|
1849
1904
|
...withGlobalTestConfig(),
|
|
1850
1905
|
});
|
|
@@ -1853,12 +1908,10 @@ describe('OverlayController', () => {
|
|
|
1853
1908
|
/** @type {{ (): void; (value?: void | PromiseLike<void> | undefined): void; }} */
|
|
1854
1909
|
let hideTransitionFinished;
|
|
1855
1910
|
ctrl.transitionHide = () =>
|
|
1856
|
-
new Promise(resolve => {
|
|
1911
|
+
new Promise((resolve) => {
|
|
1857
1912
|
hideTransitionFinished = resolve;
|
|
1858
1913
|
});
|
|
1859
|
-
|
|
1860
1914
|
ctrl.hide();
|
|
1861
|
-
|
|
1862
1915
|
expect(getComputedStyle(ctrl.content).display).to.equal('block');
|
|
1863
1916
|
setTimeout(() => {
|
|
1864
1917
|
hideTransitionFinished();
|
|
@@ -1868,8 +1921,7 @@ describe('OverlayController', () => {
|
|
|
1868
1921
|
}, 0);
|
|
1869
1922
|
}, 0);
|
|
1870
1923
|
});
|
|
1871
|
-
|
|
1872
|
-
it('awaits a "transitionShow" hook before finishing the show method', done => {
|
|
1924
|
+
it('awaits a "transitionShow" hook before finishing the show method', (done) => {
|
|
1873
1925
|
const ctrl = new OverlayController({
|
|
1874
1926
|
...withGlobalTestConfig(),
|
|
1875
1927
|
});
|
|
@@ -1877,17 +1929,16 @@ describe('OverlayController', () => {
|
|
|
1877
1929
|
/** @type {{ (): void; (value?: void | PromiseLike<void> | undefined): void; }} */
|
|
1878
1930
|
let showTransitionFinished;
|
|
1879
1931
|
ctrl.transitionShow = () =>
|
|
1880
|
-
new Promise(resolve => {
|
|
1932
|
+
new Promise((resolve) => {
|
|
1881
1933
|
showTransitionFinished = resolve;
|
|
1882
1934
|
});
|
|
1883
1935
|
ctrl.show();
|
|
1884
|
-
|
|
1885
1936
|
let showIsDone = false;
|
|
1886
1937
|
|
|
1887
|
-
/** @type {Promise<void>} */
|
|
1938
|
+
/** @type {Promise<void>} */
|
|
1939
|
+
ctrl._showComplete.then(() => {
|
|
1888
1940
|
showIsDone = true;
|
|
1889
1941
|
});
|
|
1890
|
-
|
|
1891
1942
|
expect(showIsDone).to.be.false;
|
|
1892
1943
|
setTimeout(() => {
|
|
1893
1944
|
showTransitionFinished();
|
|
@@ -1898,27 +1949,23 @@ describe('OverlayController', () => {
|
|
|
1898
1949
|
}, 0);
|
|
1899
1950
|
});
|
|
1900
1951
|
});
|
|
1901
|
-
|
|
1902
1952
|
describe('Update Configuration', () => {
|
|
1903
1953
|
it('reinitializes content', async () => {
|
|
1904
1954
|
const ctrl = new OverlayController({
|
|
1905
1955
|
...withLocalTestConfig(),
|
|
1906
|
-
contentNode: /** @type {HTMLElement} */
|
|
1956
|
+
contentNode: /** @type {HTMLElement} */ await fixture(html`<div>content1</div>`),
|
|
1907
1957
|
});
|
|
1908
1958
|
await ctrl.show(); // Popper adds inline styles
|
|
1909
1959
|
expect(ctrl.content.style.transform).not.to.be.undefined;
|
|
1910
1960
|
expect(ctrl.contentNode.textContent).to.include('content1');
|
|
1911
|
-
|
|
1912
1961
|
ctrl.updateConfig({
|
|
1913
1962
|
placementMode: 'local',
|
|
1914
|
-
contentNode: /** @type {HTMLElement} */
|
|
1963
|
+
contentNode: /** @type {HTMLElement} */ await fixture(html`<div>content2</div>`),
|
|
1915
1964
|
});
|
|
1916
1965
|
expect(ctrl.contentNode.textContent).to.include('content2');
|
|
1917
1966
|
});
|
|
1918
|
-
|
|
1919
1967
|
it('respects the initial config provided to new OverlayController(initialConfig)', async () => {
|
|
1920
|
-
const contentNode = /** @type {HTMLElement} */
|
|
1921
|
-
|
|
1968
|
+
const contentNode = /** @type {HTMLElement} */ fixtureSync(html`<div>my content</div>`);
|
|
1922
1969
|
const ctrl = new OverlayController({
|
|
1923
1970
|
// This is the shared config
|
|
1924
1971
|
placementMode: 'global',
|
|
@@ -1937,46 +1984,44 @@ describe('OverlayController', () => {
|
|
|
1937
1984
|
|
|
1938
1985
|
// Currently not working, enable again when we fix updateConfig
|
|
1939
1986
|
it.skip('allows for updating viewport config placement only, while keeping the content shown', async () => {
|
|
1940
|
-
const contentNode = /** @type {HTMLElement} */
|
|
1941
|
-
|
|
1987
|
+
const contentNode = /** @type {HTMLElement} */ fixtureSync(html`<div>my content</div>`);
|
|
1942
1988
|
const ctrl = new OverlayController({
|
|
1943
1989
|
// This is the shared config
|
|
1944
1990
|
placementMode: 'global',
|
|
1945
1991
|
handlesAccessibility: true,
|
|
1946
1992
|
contentNode,
|
|
1947
1993
|
});
|
|
1948
|
-
|
|
1949
1994
|
ctrl.show();
|
|
1950
1995
|
expect(ctrl.contentWrapperNode.classList.contains('overlays__overlay-container--center'));
|
|
1951
1996
|
expect(ctrl.isShown).to.be.true;
|
|
1952
|
-
|
|
1953
|
-
|
|
1997
|
+
ctrl.updateConfig({
|
|
1998
|
+
viewportConfig: {
|
|
1999
|
+
placement: 'top-right',
|
|
2000
|
+
},
|
|
2001
|
+
});
|
|
1954
2002
|
expect(ctrl.contentWrapperNode.classList.contains('overlays__overlay-container--top-right'));
|
|
1955
2003
|
expect(ctrl.isShown).to.be.true;
|
|
1956
2004
|
});
|
|
1957
|
-
|
|
1958
2005
|
it('disables backdrop when switching to hasBackrop "false"', async () => {
|
|
1959
2006
|
const ctrl = new OverlayController({
|
|
1960
2007
|
...withLocalTestConfig(),
|
|
1961
|
-
contentNode: /** @type {HTMLElement} */
|
|
2008
|
+
contentNode: /** @type {HTMLElement} */ await fixture(html`<div>content1</div>`),
|
|
1962
2009
|
hasBackdrop: true,
|
|
1963
2010
|
});
|
|
1964
2011
|
await ctrl.show(); // Popper adds inline styles
|
|
1965
2012
|
expect(ctrl.backdropNode).not.to.be.undefined;
|
|
1966
2013
|
expect(Array.from(ctrl.backdropNode.classList)).to.include('overlays__backdrop--visible');
|
|
1967
|
-
|
|
1968
2014
|
ctrl.updateConfig({
|
|
1969
2015
|
hasBackdrop: false,
|
|
1970
2016
|
});
|
|
1971
2017
|
expect(Array.from(ctrl.backdropNode.classList)).to.not.include('overlays__backdrop--visible');
|
|
1972
2018
|
});
|
|
1973
2019
|
});
|
|
1974
|
-
|
|
1975
2020
|
describe('Accessibility', () => {
|
|
1976
2021
|
it('synchronizes [aria-expanded] on invoker', async () => {
|
|
1977
|
-
const invokerNode =
|
|
1978
|
-
|
|
1979
|
-
|
|
2022
|
+
const invokerNode =
|
|
2023
|
+
/** @type {HTMLElement} */
|
|
2024
|
+
await fixture('<div role="button">invoker</div>');
|
|
1980
2025
|
const ctrl = new OverlayController({
|
|
1981
2026
|
...withLocalTestConfig(),
|
|
1982
2027
|
handlesAccessibility: true,
|
|
@@ -1988,11 +2033,10 @@ describe('OverlayController', () => {
|
|
|
1988
2033
|
await ctrl.hide();
|
|
1989
2034
|
expect(ctrl.invokerNode?.getAttribute('aria-expanded')).to.equal('false');
|
|
1990
2035
|
});
|
|
1991
|
-
|
|
1992
2036
|
it('does not synchronize [aria-expanded] on invoker when the overlay is modal', async () => {
|
|
1993
|
-
const invokerNode =
|
|
1994
|
-
|
|
1995
|
-
|
|
2037
|
+
const invokerNode =
|
|
2038
|
+
/** @type {HTMLElement} */
|
|
2039
|
+
await fixture('<div role="button">invoker</div>');
|
|
1996
2040
|
const ctrl = new OverlayController({
|
|
1997
2041
|
...withLocalTestConfig(),
|
|
1998
2042
|
trapsKeyboardFocus: true,
|
|
@@ -2005,7 +2049,6 @@ describe('OverlayController', () => {
|
|
|
2005
2049
|
await ctrl.hide();
|
|
2006
2050
|
expect(ctrl.invokerNode?.getAttribute('aria-expanded')).to.equal(null);
|
|
2007
2051
|
});
|
|
2008
|
-
|
|
2009
2052
|
it('creates unique id for content', async () => {
|
|
2010
2053
|
const ctrl = new OverlayController({
|
|
2011
2054
|
...withLocalTestConfig(),
|
|
@@ -2014,11 +2057,10 @@ describe('OverlayController', () => {
|
|
|
2014
2057
|
const { contentId } = getProtectedMembers(ctrl);
|
|
2015
2058
|
expect(ctrl.contentNode.id).to.contain(contentId);
|
|
2016
2059
|
});
|
|
2017
|
-
|
|
2018
2060
|
it('preserves content id when present', async () => {
|
|
2019
|
-
const contentNode =
|
|
2020
|
-
|
|
2021
|
-
|
|
2061
|
+
const contentNode =
|
|
2062
|
+
/** @type {HTMLElement} */
|
|
2063
|
+
await fixture('<div id="preserved">content</div>');
|
|
2022
2064
|
const ctrl = new OverlayController({
|
|
2023
2065
|
...withLocalTestConfig(),
|
|
2024
2066
|
handlesAccessibility: true,
|
|
@@ -2026,11 +2068,10 @@ describe('OverlayController', () => {
|
|
|
2026
2068
|
});
|
|
2027
2069
|
expect(ctrl.contentNode.id).to.contain('preserved');
|
|
2028
2070
|
});
|
|
2029
|
-
|
|
2030
2071
|
it('adds [role=dialog] on content', async () => {
|
|
2031
|
-
const invokerNode =
|
|
2032
|
-
|
|
2033
|
-
|
|
2072
|
+
const invokerNode =
|
|
2073
|
+
/** @type {HTMLElement} */
|
|
2074
|
+
await fixture('<div role="button">invoker</div>');
|
|
2034
2075
|
const ctrl = new OverlayController({
|
|
2035
2076
|
...withLocalTestConfig(),
|
|
2036
2077
|
handlesAccessibility: true,
|
|
@@ -2038,14 +2079,13 @@ describe('OverlayController', () => {
|
|
|
2038
2079
|
});
|
|
2039
2080
|
expect(ctrl.contentNode.getAttribute('role')).to.equal('dialog');
|
|
2040
2081
|
});
|
|
2041
|
-
|
|
2042
2082
|
it('preserves [role] on content when present', async () => {
|
|
2043
|
-
const invokerNode =
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
const contentNode =
|
|
2047
|
-
|
|
2048
|
-
|
|
2083
|
+
const invokerNode =
|
|
2084
|
+
/** @type {HTMLElement} */
|
|
2085
|
+
await fixture('<div role="button">invoker</div>');
|
|
2086
|
+
const contentNode =
|
|
2087
|
+
/** @type {HTMLElement} */
|
|
2088
|
+
await fixture('<div role="menu">invoker</div>');
|
|
2049
2089
|
const ctrl = new OverlayController({
|
|
2050
2090
|
...withLocalTestConfig(),
|
|
2051
2091
|
handlesAccessibility: true,
|
|
@@ -2054,7 +2094,6 @@ describe('OverlayController', () => {
|
|
|
2054
2094
|
});
|
|
2055
2095
|
expect(ctrl.contentNode.getAttribute('role')).to.equal('menu');
|
|
2056
2096
|
});
|
|
2057
|
-
|
|
2058
2097
|
it('allows to not provide an invokerNode', async () => {
|
|
2059
2098
|
let properlyInstantiated = false;
|
|
2060
2099
|
try {
|
|
@@ -2065,7 +2104,7 @@ describe('OverlayController', () => {
|
|
|
2065
2104
|
});
|
|
2066
2105
|
properlyInstantiated = true;
|
|
2067
2106
|
} catch (e) {
|
|
2068
|
-
throw new Error(/** @type {Error} */
|
|
2107
|
+
throw new Error(/** @type {Error} */ e.message);
|
|
2069
2108
|
}
|
|
2070
2109
|
expect(properlyInstantiated).to.be.true;
|
|
2071
2110
|
});
|
|
@@ -2073,28 +2112,25 @@ describe('OverlayController', () => {
|
|
|
2073
2112
|
// TODO: check if we covered all functionality. "Inertness" should be handled by the platform with a modal overlay...
|
|
2074
2113
|
it.skip('adds attributes inert and aria-hidden="true" on all siblings of rootNode if an overlay is shown', async () => {});
|
|
2075
2114
|
it.skip('disables pointer events and selection on inert elements', async () => {});
|
|
2076
|
-
|
|
2077
2115
|
describe('Alert dialog', () => {
|
|
2078
2116
|
it('sets role="alertdialog" when isAlertDialog is set', async () => {
|
|
2079
|
-
const invokerNode =
|
|
2080
|
-
|
|
2081
|
-
|
|
2117
|
+
const invokerNode =
|
|
2118
|
+
/** @type {HTMLElement} */
|
|
2119
|
+
await fixture('<div role="button">invoker</div>');
|
|
2082
2120
|
const ctrl = new OverlayController({
|
|
2083
2121
|
...withLocalTestConfig(),
|
|
2084
2122
|
handlesAccessibility: true,
|
|
2085
2123
|
isAlertDialog: true,
|
|
2086
2124
|
invokerNode,
|
|
2087
2125
|
});
|
|
2088
|
-
|
|
2089
2126
|
expect(ctrl.contentNode?.getAttribute('role')).to.equal('alertdialog');
|
|
2090
2127
|
});
|
|
2091
2128
|
});
|
|
2092
|
-
|
|
2093
2129
|
describe('Tooltip', () => {
|
|
2094
2130
|
it('adds [aria-describedby] on invoker', async () => {
|
|
2095
|
-
const invokerNode =
|
|
2096
|
-
|
|
2097
|
-
|
|
2131
|
+
const invokerNode =
|
|
2132
|
+
/** @type {HTMLElement} */
|
|
2133
|
+
await fixture('<div role="button">invoker</div>');
|
|
2098
2134
|
const ctrl = new OverlayController({
|
|
2099
2135
|
...withLocalTestConfig(),
|
|
2100
2136
|
handlesAccessibility: true,
|
|
@@ -2102,14 +2138,12 @@ describe('OverlayController', () => {
|
|
|
2102
2138
|
invokerNode,
|
|
2103
2139
|
});
|
|
2104
2140
|
const { contentId } = getProtectedMembers(ctrl);
|
|
2105
|
-
|
|
2106
2141
|
expect(ctrl.invokerNode?.getAttribute('aria-describedby')).to.equal(contentId);
|
|
2107
2142
|
});
|
|
2108
|
-
|
|
2109
2143
|
it('adds [aria-labelledby] on invoker when invokerRelation is label', async () => {
|
|
2110
|
-
const invokerNode =
|
|
2111
|
-
|
|
2112
|
-
|
|
2144
|
+
const invokerNode =
|
|
2145
|
+
/** @type {HTMLElement} */
|
|
2146
|
+
await fixture('<div role="button">invoker</div>');
|
|
2113
2147
|
const ctrl = new OverlayController({
|
|
2114
2148
|
...withLocalTestConfig(),
|
|
2115
2149
|
handlesAccessibility: true,
|
|
@@ -2118,15 +2152,13 @@ describe('OverlayController', () => {
|
|
|
2118
2152
|
invokerNode,
|
|
2119
2153
|
});
|
|
2120
2154
|
const { contentId } = getProtectedMembers(ctrl);
|
|
2121
|
-
|
|
2122
2155
|
expect(ctrl.invokerNode?.getAttribute('aria-describedby')).to.equal(null);
|
|
2123
2156
|
expect(ctrl.invokerNode?.getAttribute('aria-labelledby')).to.equal(contentId);
|
|
2124
2157
|
});
|
|
2125
|
-
|
|
2126
2158
|
it('adds [role=tooltip] on content', async () => {
|
|
2127
|
-
const invokerNode =
|
|
2128
|
-
|
|
2129
|
-
|
|
2159
|
+
const invokerNode =
|
|
2160
|
+
/** @type {HTMLElement} */
|
|
2161
|
+
await fixture('<div role="button">invoker</div>');
|
|
2130
2162
|
const ctrl = new OverlayController({
|
|
2131
2163
|
...withLocalTestConfig(),
|
|
2132
2164
|
handlesAccessibility: true,
|
|
@@ -2135,11 +2167,10 @@ describe('OverlayController', () => {
|
|
|
2135
2167
|
});
|
|
2136
2168
|
expect(ctrl.contentNode.getAttribute('role')).to.equal('tooltip');
|
|
2137
2169
|
});
|
|
2138
|
-
|
|
2139
2170
|
it('adds tabindex="-1" to the wrappingDialog element', async () => {
|
|
2140
|
-
const invokerNode =
|
|
2141
|
-
|
|
2142
|
-
|
|
2171
|
+
const invokerNode =
|
|
2172
|
+
/** @type {HTMLElement} */
|
|
2173
|
+
await fixture('<div role="button">invoker</div>');
|
|
2143
2174
|
const ctrl = new OverlayController({
|
|
2144
2175
|
...withLocalTestConfig(),
|
|
2145
2176
|
handlesAccessibility: true,
|
|
@@ -2148,12 +2179,11 @@ describe('OverlayController', () => {
|
|
|
2148
2179
|
});
|
|
2149
2180
|
expect(ctrl.__wrappingDialogNode?.getAttribute('tabindex')).to.equal('-1');
|
|
2150
2181
|
});
|
|
2151
|
-
|
|
2152
2182
|
describe('Teardown', () => {
|
|
2153
2183
|
it('restores [role] on dialog content', async () => {
|
|
2154
|
-
const invokerNode =
|
|
2155
|
-
|
|
2156
|
-
|
|
2184
|
+
const invokerNode =
|
|
2185
|
+
/** @type {HTMLElement} */
|
|
2186
|
+
await fixture('<div role="button">invoker</div>');
|
|
2157
2187
|
const ctrl = new OverlayController({
|
|
2158
2188
|
...withLocalTestConfig(),
|
|
2159
2189
|
handlesAccessibility: true,
|
|
@@ -2163,14 +2193,13 @@ describe('OverlayController', () => {
|
|
|
2163
2193
|
ctrl.teardown();
|
|
2164
2194
|
expect(ctrl.contentNode.getAttribute('role')).to.equal(null);
|
|
2165
2195
|
});
|
|
2166
|
-
|
|
2167
2196
|
it('restores [role] on tooltip content', async () => {
|
|
2168
|
-
const invokerNode =
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
const contentNode =
|
|
2172
|
-
|
|
2173
|
-
|
|
2197
|
+
const invokerNode =
|
|
2198
|
+
/** @type {HTMLElement} */
|
|
2199
|
+
await fixture('<div role="button">invoker</div>');
|
|
2200
|
+
const contentNode =
|
|
2201
|
+
/** @type {HTMLElement} */
|
|
2202
|
+
await fixture('<div role="presentation">content</div>');
|
|
2174
2203
|
const ctrl = new OverlayController({
|
|
2175
2204
|
...withLocalTestConfig(),
|
|
2176
2205
|
handlesAccessibility: true,
|
|
@@ -2182,14 +2211,13 @@ describe('OverlayController', () => {
|
|
|
2182
2211
|
ctrl.teardown();
|
|
2183
2212
|
expect(contentNode.getAttribute('role')).to.equal('presentation');
|
|
2184
2213
|
});
|
|
2185
|
-
|
|
2186
2214
|
it('restores [aria-describedby] on content', async () => {
|
|
2187
|
-
const invokerNode =
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
const contentNode =
|
|
2191
|
-
|
|
2192
|
-
|
|
2215
|
+
const invokerNode =
|
|
2216
|
+
/** @type {HTMLElement} */
|
|
2217
|
+
await fixture('<div role="button">invoker</div>');
|
|
2218
|
+
const contentNode =
|
|
2219
|
+
/** @type {HTMLElement} */
|
|
2220
|
+
await fixture('<div role="presentation">content</div>');
|
|
2193
2221
|
const ctrl = new OverlayController({
|
|
2194
2222
|
...withLocalTestConfig(),
|
|
2195
2223
|
handlesAccessibility: true,
|
|
@@ -2201,14 +2229,13 @@ describe('OverlayController', () => {
|
|
|
2201
2229
|
ctrl.teardown();
|
|
2202
2230
|
expect(invokerNode.getAttribute('aria-describedby')).to.equal(null);
|
|
2203
2231
|
});
|
|
2204
|
-
|
|
2205
2232
|
it('restores [aria-labelledby] on content', async () => {
|
|
2206
|
-
const invokerNode =
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
const contentNode =
|
|
2210
|
-
|
|
2211
|
-
|
|
2233
|
+
const invokerNode =
|
|
2234
|
+
/** @type {HTMLElement} */
|
|
2235
|
+
await fixture('<div role="button">invoker</div>');
|
|
2236
|
+
const contentNode =
|
|
2237
|
+
/** @type {HTMLElement} */
|
|
2238
|
+
await fixture('<div role="presentation">content</div>');
|
|
2212
2239
|
const ctrl = new OverlayController({
|
|
2213
2240
|
...withLocalTestConfig(),
|
|
2214
2241
|
handlesAccessibility: true,
|
|
@@ -2224,7 +2251,6 @@ describe('OverlayController', () => {
|
|
|
2224
2251
|
});
|
|
2225
2252
|
});
|
|
2226
2253
|
});
|
|
2227
|
-
|
|
2228
2254
|
describe('Exception handling', () => {
|
|
2229
2255
|
it('throws if no .placementMode gets passed on', async () => {
|
|
2230
2256
|
const contentNode = document.createElement('div');
|
|
@@ -2236,7 +2262,6 @@ describe('OverlayController', () => {
|
|
|
2236
2262
|
});
|
|
2237
2263
|
}).to.throw('[OverlayController] You need to provide a .placementMode ("global"|"local")');
|
|
2238
2264
|
});
|
|
2239
|
-
|
|
2240
2265
|
it('throws if invalid .placementMode gets passed on', async () => {
|
|
2241
2266
|
expect(() => {
|
|
2242
2267
|
new OverlayController({
|
|
@@ -2247,7 +2272,6 @@ describe('OverlayController', () => {
|
|
|
2247
2272
|
'[OverlayController] "invalid" is not a valid .placementMode, use ("global"|"local")',
|
|
2248
2273
|
);
|
|
2249
2274
|
});
|
|
2250
|
-
|
|
2251
2275
|
it('throws if no .contentNode gets passed on', async () => {
|
|
2252
2276
|
expect(() => {
|
|
2253
2277
|
new OverlayController({
|
|
@@ -2255,7 +2279,6 @@ describe('OverlayController', () => {
|
|
|
2255
2279
|
});
|
|
2256
2280
|
}).to.throw('[OverlayController] You need to provide a .contentNode');
|
|
2257
2281
|
});
|
|
2258
|
-
|
|
2259
2282
|
it('throws if handlesAccessibility is false for a tooltip', async () => {
|
|
2260
2283
|
const contentNode = document.createElement('div');
|
|
2261
2284
|
document.body.appendChild(contentNode);
|
|
@@ -2271,7 +2294,6 @@ describe('OverlayController', () => {
|
|
|
2271
2294
|
);
|
|
2272
2295
|
});
|
|
2273
2296
|
});
|
|
2274
|
-
|
|
2275
2297
|
describe('run _keepBodySize only with scroll prevention', () => {
|
|
2276
2298
|
/**
|
|
2277
2299
|
* @type {OverlayController}
|
|
@@ -2280,15 +2302,12 @@ describe('OverlayController', () => {
|
|
|
2280
2302
|
...withLocalTestConfig(),
|
|
2281
2303
|
preventsScroll: false,
|
|
2282
2304
|
});
|
|
2283
|
-
|
|
2284
2305
|
const overlayControllerPreventsScroll = new OverlayController({
|
|
2285
2306
|
...withLocalTestConfig(),
|
|
2286
2307
|
preventsScroll: true,
|
|
2287
2308
|
});
|
|
2288
|
-
|
|
2289
2309
|
it('should not run with scroll prevention', async () => {
|
|
2290
2310
|
await overlayControllerNoPrevent.show();
|
|
2291
|
-
|
|
2292
2311
|
expect(
|
|
2293
2312
|
overlayControllerNoPrevent.manager.__forTesting.bodySizeVars.marginRightInline,
|
|
2294
2313
|
).to.equal(undefined);
|
|
@@ -2296,10 +2315,9 @@ describe('OverlayController', () => {
|
|
|
2296
2315
|
undefined,
|
|
2297
2316
|
);
|
|
2298
2317
|
});
|
|
2299
|
-
|
|
2300
2318
|
it('should run with scroll prevention', async () => {
|
|
2319
|
+
await overlayControllerPreventsScroll.hide();
|
|
2301
2320
|
await overlayControllerPreventsScroll.show();
|
|
2302
|
-
|
|
2303
2321
|
expect(
|
|
2304
2322
|
overlayControllerPreventsScroll.manager.__forTesting.bodySizeVars.marginRightInline,
|
|
2305
2323
|
).to.not.equal(undefined);
|