@lion/ui 0.23.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 +50 -20
- 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 +35 -53
- 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 +576 -869
- 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 -364
- 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-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 +20 -20
- package/components/input-amount/src/formatters.js +0 -3
- package/components/input-amount/src/parsers.js +0 -3
- package/components/input-amount/test/formatters.test.js +24 -16
- package/components/input-amount/test/lion-input-amount-integrations.test.js +0 -4
- package/components/input-amount/test/lion-input-amount.test.js +123 -147
- 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 +7 -14
- 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 +786 -820
- 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/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/src/InteractiveListMixin.js +637 -638
- package/components/menu/src/LionMenu.js +46 -59
- package/components/menu/src/MoreButtonMenuMixin.js +215 -238
- package/components/menu/src/MultiLevelListMixin.js +240 -246
- package/components/menu/src/utils/isInView.js +0 -1
- package/components/menu/src/utils/listItemInteractions.js +4 -4
- package/components/menu/test/InteractiveListMixin.test.js +0 -1
- package/components/menu/test/MoreButtonMenuMixin.test.js +3 -2
- package/components/menu/test/MultiLevelListMixin.test.js +0 -1
- package/components/menu/test/lion-menu-interactions.test.js +0 -1
- package/components/menu/test/lion-menu.test.js +6 -2
- package/components/menu/test-helpers/mimicKeyPress.js +12 -2
- package/components/menu/test-suites/InteractiveListMixin.suite.js +4 -43
- package/components/menu/test-suites/LionMenu.suite.js +1 -8
- package/components/menu/test-suites/LionMenuInteractions.suite.js +22 -44
- package/components/menu/test-suites/MoreButtonMenuMixin.suite.js +34 -41
- package/components/menu/test-suites/MultiLevelListMixin.suite.js +5 -23
- package/components/overlays/src/ArrowMixin.js +111 -127
- package/components/overlays/src/OverlayController.js +166 -151
- package/components/overlays/src/OverlayMixin.js +61 -63
- 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 +18 -18
- 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 +2 -3
- 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 +375 -555
- 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 +152 -181
- 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/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 +20 -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 +116 -116
- package/components/select-rich/test/lion-select-rich-upgrade.test.js +3 -7
- 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 +191 -56
- 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/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/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/overlays/src/OverlaysManager.d.ts.map +1 -1
- package/dist-types/components/overlays/src/overlayDocumentStyle.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 +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/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/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/overview.md +5 -5
- package/docs/components/input-amount/use-cases.md +2 -2
- 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/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/extensions.md +2 -2
- package/docs/components/menu/migration.md +2 -2
- package/docs/components/menu/overview.md +2 -2
- package/docs/components/menu/use-cases.md +1 -1
- 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/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/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 +2 -2
- 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/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 +0 -1
- package/exports/define/lion-listbox.js +0 -1
- package/exports/define/lion-menu.js +0 -1
- package/exports/define/lion-menuitem.js +0 -1
- 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/overlays.js +0 -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/package.json +32 -10
- package/web-types.json +1 -1
- package/vendor/README.md +0 -61
- package/vendor/awesome-phonenumber-7.9.0-tlouisse.libphonenumber-9.0.41.tgz +0 -0
|
@@ -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,40 +94,34 @@ 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
|
-
|
|
114
|
+
const childContent = /** @type {HTMLDivElement} */ parentContent.querySelector('div[id]');
|
|
119
115
|
if (parentContent.hasAttribute('data-convert-to-shadow-root')) {
|
|
120
|
-
const shadowRootParent = parentContent.attachShadow({
|
|
116
|
+
const shadowRootParent = parentContent.attachShadow({
|
|
117
|
+
mode: 'open',
|
|
118
|
+
});
|
|
121
119
|
shadowRootParent.appendChild(childContent);
|
|
122
120
|
}
|
|
123
|
-
|
|
124
121
|
const parentConfig = {};
|
|
125
122
|
const childConfig = {};
|
|
126
|
-
|
|
127
123
|
const parentHasOutsideOnEsc = parentContent.id.startsWith('parent-overlay--hidesOnOutsideEsc');
|
|
128
124
|
const childHasOutsideOnEsc = childContent.id.startsWith('child-overlay--hidesOnOutsideEsc');
|
|
129
|
-
|
|
130
125
|
if (parentHasOutsideOnEsc) {
|
|
131
126
|
parentConfig.hidesOnOutsideEsc = true;
|
|
132
127
|
} else {
|
|
@@ -137,14 +132,11 @@ async function createNestedEscControllers(parentContent) {
|
|
|
137
132
|
} else {
|
|
138
133
|
childConfig.hidesOnEsc = true;
|
|
139
134
|
}
|
|
140
|
-
|
|
141
135
|
const parentHasSyncChildrenCloseState =
|
|
142
136
|
parentContent.dataset.syncChildrenCloseState !== undefined;
|
|
143
|
-
|
|
144
137
|
if (parentHasSyncChildrenCloseState) {
|
|
145
138
|
parentConfig.syncChildrenCloseState = true;
|
|
146
139
|
}
|
|
147
|
-
|
|
148
140
|
const parentOverlay = new OverlayController({
|
|
149
141
|
...withGlobalTestConfig(),
|
|
150
142
|
contentNode: parentContent,
|
|
@@ -155,19 +147,18 @@ async function createNestedEscControllers(parentContent) {
|
|
|
155
147
|
contentNode: childContent,
|
|
156
148
|
...childConfig,
|
|
157
149
|
});
|
|
158
|
-
|
|
159
150
|
await parentOverlay.show();
|
|
160
151
|
await childOverlay.show();
|
|
161
|
-
|
|
162
|
-
|
|
152
|
+
return {
|
|
153
|
+
parentOverlay,
|
|
154
|
+
childOverlay,
|
|
155
|
+
};
|
|
163
156
|
}
|
|
164
|
-
|
|
165
157
|
afterEach(() => {
|
|
166
158
|
overlays.teardown();
|
|
167
159
|
// clean document.body from the DOM nodes left by previous tests
|
|
168
160
|
document.body.innerHTML = '';
|
|
169
161
|
});
|
|
170
|
-
|
|
171
162
|
describe('OverlayController', () => {
|
|
172
163
|
describe('Init', () => {
|
|
173
164
|
it('adds OverlayController instance to OverlayManager', async () => {
|
|
@@ -177,7 +168,6 @@ describe('OverlayController', () => {
|
|
|
177
168
|
expect(ctrl.manager).to.equal(overlays);
|
|
178
169
|
expect(overlays.list).to.include(ctrl);
|
|
179
170
|
});
|
|
180
|
-
|
|
181
171
|
it('prepares a content node wrapper', async () => {
|
|
182
172
|
const ctrl = new OverlayController({
|
|
183
173
|
...withGlobalTestConfig(),
|
|
@@ -185,12 +175,11 @@ describe('OverlayController', () => {
|
|
|
185
175
|
expect(ctrl.content).not.to.be.undefined;
|
|
186
176
|
expect(ctrl.contentNode.parentElement).to.equal(ctrl.contentWrapperNode);
|
|
187
177
|
});
|
|
188
|
-
|
|
189
178
|
describe('Stylesheets', () => {
|
|
190
179
|
it('calls adoptStyles', async () => {
|
|
191
180
|
const spy = sinon.spy(_adoptStyleUtils, 'adoptStyle');
|
|
192
181
|
const { shadowHost, cleanupShadowHost } = createShadowHost();
|
|
193
|
-
const contentNode = /** @type {HTMLElement} */
|
|
182
|
+
const contentNode = /** @type {HTMLElement} */ await fixture('<div>contentful</div>');
|
|
194
183
|
shadowHost.appendChild(contentNode);
|
|
195
184
|
new OverlayController({
|
|
196
185
|
...withLocalTestConfig(),
|
|
@@ -200,7 +189,6 @@ describe('OverlayController', () => {
|
|
|
200
189
|
cleanupShadowHost();
|
|
201
190
|
});
|
|
202
191
|
});
|
|
203
|
-
|
|
204
192
|
describe('Z-index on local overlays', () => {
|
|
205
193
|
/** @type {HTMLElement} */
|
|
206
194
|
let contentNode;
|
|
@@ -210,7 +198,8 @@ describe('OverlayController', () => {
|
|
|
210
198
|
*/
|
|
211
199
|
async function createZNode(zIndexVal, { mode } = {}) {
|
|
212
200
|
if (mode === 'global') {
|
|
213
|
-
contentNode =
|
|
201
|
+
contentNode =
|
|
202
|
+
/** @type {HTMLElement} */
|
|
214
203
|
await fixture(html`
|
|
215
204
|
<div class="z-index--${zIndexVal}">
|
|
216
205
|
<style>
|
|
@@ -220,69 +209,92 @@ describe('OverlayController', () => {
|
|
|
220
209
|
</style>
|
|
221
210
|
I should be on top
|
|
222
211
|
</div>
|
|
223
|
-
`)
|
|
224
|
-
);
|
|
212
|
+
`);
|
|
225
213
|
}
|
|
226
214
|
if (mode === 'inline') {
|
|
227
|
-
contentNode =
|
|
228
|
-
|
|
229
|
-
|
|
215
|
+
contentNode =
|
|
216
|
+
/** @type {HTMLElement} */
|
|
217
|
+
await fixture(html` <div>I should be on top</div> `);
|
|
230
218
|
contentNode.style.zIndex = zIndexVal;
|
|
231
219
|
}
|
|
232
220
|
return contentNode;
|
|
233
221
|
}
|
|
234
|
-
|
|
235
222
|
it('sets a z-index to make sure overlay is painted on top of siblings', async () => {
|
|
236
223
|
const ctrl = new OverlayController({
|
|
237
224
|
...withLocalTestConfig(),
|
|
238
|
-
contentNode: await createZNode('auto', {
|
|
225
|
+
contentNode: await createZNode('auto', {
|
|
226
|
+
mode: 'global',
|
|
227
|
+
}),
|
|
239
228
|
});
|
|
240
229
|
await ctrl.show();
|
|
241
230
|
// @ts-expect-error find out why config would/could be undfined
|
|
242
231
|
expect(ctrl.content.style.zIndex).to.equal(`${ctrl.config.zIndex + 1}`);
|
|
243
|
-
ctrl.updateConfig({
|
|
232
|
+
ctrl.updateConfig({
|
|
233
|
+
contentNode: await createZNode('auto', {
|
|
234
|
+
mode: 'inline',
|
|
235
|
+
}),
|
|
236
|
+
});
|
|
244
237
|
await ctrl.show();
|
|
245
238
|
// @ts-expect-error find out why config would/could be undfined
|
|
246
239
|
expect(ctrl.content.style.zIndex).to.equal(`${ctrl.config.zIndex + 1}`);
|
|
247
|
-
|
|
248
|
-
|
|
240
|
+
ctrl.updateConfig({
|
|
241
|
+
contentNode: await createZNode('0', {
|
|
242
|
+
mode: 'global',
|
|
243
|
+
}),
|
|
244
|
+
});
|
|
249
245
|
await ctrl.show();
|
|
250
246
|
// @ts-expect-error find out why config would/could be undfined
|
|
251
247
|
expect(ctrl.content.style.zIndex).to.equal(`${ctrl.config.zIndex + 1}`);
|
|
252
|
-
ctrl.updateConfig({
|
|
248
|
+
ctrl.updateConfig({
|
|
249
|
+
contentNode: await createZNode('0', {
|
|
250
|
+
mode: 'inline',
|
|
251
|
+
}),
|
|
252
|
+
});
|
|
253
253
|
await ctrl.show();
|
|
254
254
|
// @ts-expect-error find out why config would/could be undfined
|
|
255
255
|
expect(ctrl.content.style.zIndex).to.equal(`${ctrl.config.zIndex + 1}`);
|
|
256
256
|
});
|
|
257
|
-
|
|
258
257
|
it.skip("doesn't set a z-index when contentNode already has >= 1", async () => {
|
|
259
258
|
const ctrl = new OverlayController({
|
|
260
259
|
...withLocalTestConfig(),
|
|
261
|
-
contentNode: await createZNode('1', {
|
|
260
|
+
contentNode: await createZNode('1', {
|
|
261
|
+
mode: 'global',
|
|
262
|
+
}),
|
|
262
263
|
});
|
|
263
264
|
await ctrl.show();
|
|
264
265
|
expect(ctrl.content.style.zIndex).to.equal('');
|
|
265
|
-
ctrl.updateConfig({
|
|
266
|
+
ctrl.updateConfig({
|
|
267
|
+
contentNode: await createZNode('auto', {
|
|
268
|
+
mode: 'inline',
|
|
269
|
+
}),
|
|
270
|
+
});
|
|
266
271
|
await ctrl.show();
|
|
267
272
|
expect(ctrl.content.style.zIndex).to.equal('');
|
|
268
|
-
|
|
269
|
-
|
|
273
|
+
ctrl.updateConfig({
|
|
274
|
+
contentNode: await createZNode('2', {
|
|
275
|
+
mode: 'global',
|
|
276
|
+
}),
|
|
277
|
+
});
|
|
270
278
|
await ctrl.show();
|
|
271
279
|
expect(ctrl.content.style.zIndex).to.equal('');
|
|
272
|
-
ctrl.updateConfig({
|
|
280
|
+
ctrl.updateConfig({
|
|
281
|
+
contentNode: await createZNode('2', {
|
|
282
|
+
mode: 'inline',
|
|
283
|
+
}),
|
|
284
|
+
});
|
|
273
285
|
await ctrl.show();
|
|
274
286
|
expect(ctrl.content.style.zIndex).to.equal('');
|
|
275
287
|
});
|
|
276
|
-
|
|
277
288
|
it("doesn't touch the value of .contentNode", async () => {
|
|
278
289
|
const ctrl = new OverlayController({
|
|
279
290
|
...withLocalTestConfig(),
|
|
280
|
-
contentNode: await createZNode('auto', {
|
|
291
|
+
contentNode: await createZNode('auto', {
|
|
292
|
+
mode: 'global',
|
|
293
|
+
}),
|
|
281
294
|
});
|
|
282
295
|
expect(ctrl.contentNode.style.zIndex).to.equal('');
|
|
283
296
|
});
|
|
284
297
|
});
|
|
285
|
-
|
|
286
298
|
describe('Offline content', () => {
|
|
287
299
|
it('throws when passing a content node that was created "offline"', async () => {
|
|
288
300
|
const contentNode = document.createElement('div');
|
|
@@ -292,14 +304,12 @@ describe('OverlayController', () => {
|
|
|
292
304
|
contentNode,
|
|
293
305
|
});
|
|
294
306
|
};
|
|
295
|
-
|
|
296
307
|
expect(createOverlayController).to.throw(
|
|
297
308
|
'[OverlayController] Could not find a render target, makes sure contentNode has a parent element (or contentWrapperNode is connected)',
|
|
298
309
|
);
|
|
299
310
|
});
|
|
300
|
-
|
|
301
311
|
it('succeeds when passing a content node that was created "online"', async () => {
|
|
302
|
-
const contentNode = /** @type {HTMLElement} */
|
|
312
|
+
const contentNode = /** @type {HTMLElement} */ fixtureSync('<div>');
|
|
303
313
|
const overlay = new OverlayController({
|
|
304
314
|
...withLocalTestConfig(),
|
|
305
315
|
contentNode,
|
|
@@ -313,16 +323,12 @@ describe('OverlayController', () => {
|
|
|
313
323
|
describe('Teardown', () => {
|
|
314
324
|
it('unregisters itself from overlayManager', async () => {
|
|
315
325
|
const ctrl = new OverlayController(withGlobalTestConfig());
|
|
316
|
-
|
|
317
326
|
expect(isRegisteredOnManager(ctrl)).to.be.true;
|
|
318
|
-
|
|
319
327
|
ctrl.teardown();
|
|
320
|
-
|
|
321
328
|
expect(isRegisteredOnManager(ctrl)).to.be.false;
|
|
322
329
|
});
|
|
323
|
-
|
|
324
330
|
it('handles removal from DOM gracefully when overlay is open', async () => {
|
|
325
|
-
const contentNode = /** @type {HTMLElement} */
|
|
331
|
+
const contentNode = /** @type {HTMLElement} */ fixtureSync(html`<div>my content</div>`);
|
|
326
332
|
const ctrl = new OverlayController({
|
|
327
333
|
placementMode: 'global',
|
|
328
334
|
contentNode,
|
|
@@ -340,7 +346,6 @@ describe('OverlayController', () => {
|
|
|
340
346
|
// Teardown should complete without errors
|
|
341
347
|
expect(isRegisteredOnManager(ctrl)).to.be.false;
|
|
342
348
|
});
|
|
343
|
-
|
|
344
349
|
it('does not throw when hide() is called after teardown() on a shown controller', async () => {
|
|
345
350
|
const ctrl = new OverlayController({
|
|
346
351
|
...withGlobalTestConfig(),
|
|
@@ -356,9 +361,8 @@ describe('OverlayController', () => {
|
|
|
356
361
|
await ctrl.hide();
|
|
357
362
|
expect(ctrl.isShown).to.be.false;
|
|
358
363
|
});
|
|
359
|
-
|
|
360
364
|
it('cleans up the dom structure it created', async () => {
|
|
361
|
-
const contentNode = /** @type {HTMLElement} */
|
|
365
|
+
const contentNode = /** @type {HTMLElement} */ fixtureSync(html`<div>my content</div>`);
|
|
362
366
|
const ctrl = new OverlayController({
|
|
363
367
|
placementMode: 'global',
|
|
364
368
|
contentNode,
|
|
@@ -366,17 +370,15 @@ describe('OverlayController', () => {
|
|
|
366
370
|
await ctrl.show();
|
|
367
371
|
expect(ctrl.contentWrapperNode).to.exist;
|
|
368
372
|
expect(ctrl.__wrappingDialogNode).to.exist;
|
|
369
|
-
|
|
370
373
|
await ctrl.teardown();
|
|
371
374
|
expect(ctrl.contentWrapperNode).to.not.exist;
|
|
372
375
|
expect(ctrl.__wrappingDialogNode).to.not.exist;
|
|
373
376
|
});
|
|
374
377
|
});
|
|
375
|
-
|
|
376
378
|
describe('Node Configuration', () => {
|
|
377
379
|
describe('Content', async () => {
|
|
378
380
|
it('accepts a .contentNode for displaying content of the overlay', async () => {
|
|
379
|
-
const myContentNode = /** @type {HTMLElement} */
|
|
381
|
+
const myContentNode = /** @type {HTMLElement} */ fixtureSync('<p>direct node</p>');
|
|
380
382
|
const ctrl = new OverlayController({
|
|
381
383
|
...withGlobalTestConfig(),
|
|
382
384
|
contentNode: myContentNode,
|
|
@@ -384,7 +386,6 @@ describe('OverlayController', () => {
|
|
|
384
386
|
expect(ctrl.contentNode).to.have.trimmed.text('direct node');
|
|
385
387
|
expect(ctrl.contentNode).to.equal(myContentNode);
|
|
386
388
|
});
|
|
387
|
-
|
|
388
389
|
describe('Embedded dom structure', async () => {
|
|
389
390
|
describe('When projected in shadow dom', async () => {
|
|
390
391
|
it('wraps a .contentWrapperNode for style application and a <dialog role="none"> for top layer paints', async () => {
|
|
@@ -392,27 +393,25 @@ describe('OverlayController', () => {
|
|
|
392
393
|
class extends HTMLElement {
|
|
393
394
|
constructor() {
|
|
394
395
|
super();
|
|
395
|
-
this.attachShadow({
|
|
396
|
+
this.attachShadow({
|
|
397
|
+
mode: 'open',
|
|
398
|
+
});
|
|
396
399
|
}
|
|
397
|
-
|
|
398
400
|
connectedCallback() {
|
|
399
401
|
/** @type {ShadowRoot} */
|
|
400
|
-
|
|
402
|
+
this.shadowRoot.innerHTML = '<slot name="content"></slot>';
|
|
401
403
|
this.innerHTML = '<div slot="content">projected</div>';
|
|
402
404
|
}
|
|
403
405
|
},
|
|
404
406
|
);
|
|
405
|
-
|
|
406
|
-
const
|
|
407
|
-
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]');
|
|
408
409
|
const ctrl = new OverlayController({
|
|
409
410
|
...withGlobalTestConfig(),
|
|
410
411
|
contentNode: myContentNode,
|
|
411
412
|
});
|
|
412
|
-
|
|
413
413
|
expect(ctrl.contentNode.assignedSlot?.parentElement).to.equal(ctrl.contentWrapperNode);
|
|
414
414
|
expect(ctrl.contentWrapperNode.parentElement?.tagName).to.equal('DIALOG');
|
|
415
|
-
|
|
416
415
|
normalizeOverlayContentWapper(ctrl.contentWrapperNode);
|
|
417
416
|
|
|
418
417
|
// The total dom structure created...
|
|
@@ -425,24 +424,23 @@ describe('OverlayController', () => {
|
|
|
425
424
|
</div>
|
|
426
425
|
</dialog>
|
|
427
426
|
`,
|
|
428
|
-
{
|
|
427
|
+
{
|
|
428
|
+
ignoreAttributes: ['closedby'],
|
|
429
|
+
},
|
|
429
430
|
);
|
|
430
|
-
|
|
431
431
|
expect(el).lightDom.to.equal(`<div data-content="" slot="content">projected</div>`);
|
|
432
432
|
});
|
|
433
433
|
});
|
|
434
|
-
|
|
435
434
|
describe('When in light dom', async () => {
|
|
436
435
|
it('wraps a .contentWrapperNode for style application and a <dialog role="none"> for top layer paints', async () => {
|
|
437
436
|
const el = fixtureSync('<section><div id="content">non projected</div></section>');
|
|
438
|
-
const myContentNode = /** @type {HTMLElement} */
|
|
437
|
+
const myContentNode = /** @type {HTMLElement} */ el.querySelector('#content');
|
|
439
438
|
const ctrl = new OverlayController({
|
|
440
439
|
...withGlobalTestConfig(),
|
|
441
440
|
contentNode: myContentNode,
|
|
442
441
|
});
|
|
443
442
|
expect(ctrl.contentNode.parentElement).to.equal(ctrl.contentWrapperNode);
|
|
444
443
|
expect(ctrl.contentWrapperNode.parentElement?.tagName).to.equal('DIALOG');
|
|
445
|
-
|
|
446
444
|
normalizeOverlayContentWapper(ctrl.contentWrapperNode);
|
|
447
445
|
|
|
448
446
|
// The total dom structure created...
|
|
@@ -454,16 +452,19 @@ describe('OverlayController', () => {
|
|
|
454
452
|
</div>
|
|
455
453
|
</dialog>
|
|
456
454
|
`,
|
|
457
|
-
{
|
|
455
|
+
{
|
|
456
|
+
ignoreAttributes: ['closedby'],
|
|
457
|
+
},
|
|
458
458
|
);
|
|
459
459
|
});
|
|
460
460
|
});
|
|
461
|
-
|
|
462
461
|
describe('When .contentWrapperNode is provided in a host that is not connected yet', () => {
|
|
463
462
|
/** @param {{ nested?: boolean }} [opts] */
|
|
464
463
|
function createDisconnectedHost({ nested = false } = {}) {
|
|
465
464
|
const host = document.createElement('div');
|
|
466
|
-
const shadowRoot = host.attachShadow({
|
|
465
|
+
const shadowRoot = host.attachShadow({
|
|
466
|
+
mode: 'open',
|
|
467
|
+
});
|
|
467
468
|
const wrapper = document.createElement('div');
|
|
468
469
|
wrapper.setAttribute('data-id', 'content-wrapper');
|
|
469
470
|
wrapper.innerHTML = '<slot name="content"></slot>';
|
|
@@ -478,93 +479,95 @@ describe('OverlayController', () => {
|
|
|
478
479
|
content.slot = 'content';
|
|
479
480
|
content.textContent = 'projected';
|
|
480
481
|
host.appendChild(content);
|
|
481
|
-
return {
|
|
482
|
+
return {
|
|
483
|
+
host,
|
|
484
|
+
shadowRoot,
|
|
485
|
+
wrapper,
|
|
486
|
+
content,
|
|
487
|
+
};
|
|
482
488
|
}
|
|
483
|
-
|
|
484
489
|
it('does not throw and keeps the projected slot inside the wrapper', async () => {
|
|
485
490
|
const { host, shadowRoot, wrapper, content } = createDisconnectedHost();
|
|
486
491
|
expect(wrapper.isConnected).to.be.false;
|
|
487
|
-
const slot = /** @type {HTMLSlotElement} */
|
|
488
|
-
|
|
492
|
+
const slot = /** @type {HTMLSlotElement} */ content.assignedSlot;
|
|
489
493
|
const ctrl = new OverlayController({
|
|
490
494
|
...withGlobalTestConfig(),
|
|
491
495
|
contentNode: content,
|
|
492
496
|
contentWrapperNode: wrapper,
|
|
493
497
|
});
|
|
494
|
-
|
|
495
498
|
expect(ctrl.contentWrapperNode).to.equal(wrapper);
|
|
496
499
|
expect(wrapper.parentElement?.tagName).to.equal('DIALOG');
|
|
497
500
|
expect(slot.parentElement).to.equal(wrapper);
|
|
498
501
|
expect(content.parentElement).to.equal(host);
|
|
499
502
|
expect(shadowRoot.querySelectorAll('slot').length).to.equal(1);
|
|
500
503
|
});
|
|
501
|
-
|
|
502
504
|
it('restores the same relocated slot at its original position on teardown', async () => {
|
|
503
|
-
const { host, shadowRoot, wrapper, content } = createDisconnectedHost({
|
|
504
|
-
|
|
505
|
-
|
|
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;
|
|
506
510
|
const ctrl = new OverlayController({
|
|
507
511
|
...withGlobalTestConfig(),
|
|
508
512
|
contentNode: content,
|
|
509
513
|
contentWrapperNode: wrapper,
|
|
510
514
|
});
|
|
511
|
-
|
|
512
515
|
ctrl.teardown();
|
|
513
|
-
|
|
514
516
|
expect(content.parentElement).to.equal(host);
|
|
515
517
|
expect(wrapper.parentElement).to.equal(section);
|
|
516
518
|
expect(slot.parentElement).to.equal(wrapper);
|
|
517
519
|
expect(shadowRoot.querySelector('dialog')).to.be.null;
|
|
518
520
|
expect(shadowRoot.querySelector('slot')).to.equal(slot);
|
|
519
521
|
});
|
|
520
|
-
|
|
521
522
|
it('survives repeated updateConfig calls and keeps slot ownership', async () => {
|
|
522
523
|
const { host, shadowRoot, wrapper, content } = createDisconnectedHost();
|
|
523
|
-
const slot = /** @type {HTMLSlotElement} */
|
|
524
|
+
const slot = /** @type {HTMLSlotElement} */ content.assignedSlot;
|
|
524
525
|
const ctrl = new OverlayController({
|
|
525
526
|
...withGlobalTestConfig(),
|
|
526
527
|
contentNode: content,
|
|
527
528
|
contentWrapperNode: wrapper,
|
|
528
529
|
});
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
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();
|
|
533
540
|
expect(content.parentElement).to.equal(host);
|
|
534
541
|
expect(shadowRoot.querySelectorAll('slot').length).to.equal(1);
|
|
535
542
|
expect(shadowRoot.querySelector('slot')).to.equal(slot);
|
|
536
543
|
expect(wrapper.contains(slot)).to.be.true;
|
|
537
544
|
});
|
|
538
545
|
});
|
|
539
|
-
|
|
540
546
|
describe('When .contenWrapperNode provided', async () => {
|
|
541
547
|
it('keeps the .contentWrapperNode for style application and wraps a <dialog role="none"> for top layer paints', async () => {
|
|
542
548
|
const tagString = defineCE(
|
|
543
549
|
class extends HTMLElement {
|
|
544
550
|
constructor() {
|
|
545
551
|
super();
|
|
546
|
-
this.attachShadow({
|
|
552
|
+
this.attachShadow({
|
|
553
|
+
mode: 'open',
|
|
554
|
+
});
|
|
547
555
|
}
|
|
548
|
-
|
|
549
556
|
connectedCallback() {
|
|
550
557
|
/** @type {ShadowRoot} */
|
|
551
|
-
|
|
558
|
+
this.shadowRoot.innerHTML = '<div><slot name="content"></slot></div>';
|
|
552
559
|
this.innerHTML = '<div slot="content">projected</div>';
|
|
553
560
|
}
|
|
554
561
|
},
|
|
555
562
|
);
|
|
556
|
-
|
|
557
|
-
const
|
|
558
|
-
const
|
|
559
|
-
const myContentWrapper = /** @type {HTMLElement} */ (
|
|
560
|
-
el.shadowRoot?.querySelector('div')
|
|
561
|
-
);
|
|
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');
|
|
562
566
|
const ctrl = new OverlayController({
|
|
563
567
|
...withGlobalTestConfig(),
|
|
564
568
|
contentNode: myContentNode,
|
|
565
569
|
contentWrapperNode: myContentWrapper,
|
|
566
570
|
});
|
|
567
|
-
|
|
568
571
|
normalizeOverlayContentWapper(ctrl.contentWrapperNode);
|
|
569
572
|
|
|
570
573
|
// The total dom structure created...
|
|
@@ -576,21 +579,23 @@ describe('OverlayController', () => {
|
|
|
576
579
|
</div>
|
|
577
580
|
</dialog>
|
|
578
581
|
`,
|
|
579
|
-
{
|
|
582
|
+
{
|
|
583
|
+
ignoreAttributes: ['closedby'],
|
|
584
|
+
},
|
|
580
585
|
);
|
|
581
586
|
});
|
|
582
|
-
|
|
583
587
|
it("uses the .contentWrapperNode as container for Popper's arrow", async () => {
|
|
584
588
|
const tagString = defineCE(
|
|
585
589
|
class extends HTMLElement {
|
|
586
590
|
constructor() {
|
|
587
591
|
super();
|
|
588
|
-
this.attachShadow({
|
|
592
|
+
this.attachShadow({
|
|
593
|
+
mode: 'open',
|
|
594
|
+
});
|
|
589
595
|
}
|
|
590
|
-
|
|
591
596
|
connectedCallback() {
|
|
592
597
|
/** @type {ShadowRoot} */
|
|
593
|
-
|
|
598
|
+
this.shadowRoot.innerHTML = `
|
|
594
599
|
<div>
|
|
595
600
|
<div id="arrow"></div>
|
|
596
601
|
<slot name="content"></slot>
|
|
@@ -599,18 +604,14 @@ describe('OverlayController', () => {
|
|
|
599
604
|
}
|
|
600
605
|
},
|
|
601
606
|
);
|
|
602
|
-
|
|
603
|
-
const
|
|
604
|
-
const
|
|
605
|
-
const myContentWrapper = /** @type {HTMLElement} */ (
|
|
606
|
-
el.shadowRoot?.querySelector('div')
|
|
607
|
-
);
|
|
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');
|
|
608
610
|
const ctrl = new OverlayController({
|
|
609
611
|
...withLocalTestConfig(),
|
|
610
612
|
contentNode: myContentNode,
|
|
611
613
|
contentWrapperNode: myContentWrapper,
|
|
612
614
|
});
|
|
613
|
-
|
|
614
615
|
normalizeOverlayContentWapper(ctrl.contentWrapperNode);
|
|
615
616
|
|
|
616
617
|
// The total dom structure created...
|
|
@@ -623,16 +624,17 @@ describe('OverlayController', () => {
|
|
|
623
624
|
</div>
|
|
624
625
|
</dialog>
|
|
625
626
|
`,
|
|
626
|
-
{
|
|
627
|
+
{
|
|
628
|
+
ignoreAttributes: ['closedby'],
|
|
629
|
+
},
|
|
627
630
|
);
|
|
628
631
|
});
|
|
629
632
|
});
|
|
630
633
|
});
|
|
631
634
|
});
|
|
632
|
-
|
|
633
635
|
describe('Invoker / Reference', async () => {
|
|
634
636
|
it('accepts a .invokerNode to directly set invoker', async () => {
|
|
635
|
-
const myInvokerNode = /** @type {HTMLElement} */
|
|
637
|
+
const myInvokerNode = /** @type {HTMLElement} */ fixtureSync('<button>invoke</button>');
|
|
636
638
|
const ctrl = new OverlayController({
|
|
637
639
|
...withGlobalTestConfig(),
|
|
638
640
|
invokerNode: myInvokerNode,
|
|
@@ -640,10 +642,9 @@ describe('OverlayController', () => {
|
|
|
640
642
|
expect(ctrl.invokerNode).to.equal(myInvokerNode);
|
|
641
643
|
expect(ctrl.referenceNode).to.equal(undefined);
|
|
642
644
|
});
|
|
643
|
-
|
|
644
645
|
it('accepts a .referenceNode as positioning anchor different from .invokerNode', async () => {
|
|
645
|
-
const myInvokerNode = /** @type {HTMLElement} */
|
|
646
|
-
const myReferenceNode = /** @type {HTMLElement} */
|
|
646
|
+
const myInvokerNode = /** @type {HTMLElement} */ fixtureSync('<button>invoke</button>');
|
|
647
|
+
const myReferenceNode = /** @type {HTMLElement} */ fixtureSync('<div>anchor</div>');
|
|
647
648
|
const ctrl = new OverlayController({
|
|
648
649
|
...withGlobalTestConfig(),
|
|
649
650
|
invokerNode: myInvokerNode,
|
|
@@ -653,33 +654,30 @@ describe('OverlayController', () => {
|
|
|
653
654
|
expect(ctrl.invokerNode).to.not.equal(ctrl.referenceNode);
|
|
654
655
|
});
|
|
655
656
|
});
|
|
656
|
-
|
|
657
657
|
describe('Backdrop', () => {
|
|
658
658
|
it('creates a .backdropNode inside <dialog> for guaranteed top layer paints and positioning opportunities', async () => {
|
|
659
659
|
const tagString = defineCE(
|
|
660
660
|
class extends HTMLElement {
|
|
661
661
|
constructor() {
|
|
662
662
|
super();
|
|
663
|
-
this.attachShadow({
|
|
663
|
+
this.attachShadow({
|
|
664
|
+
mode: 'open',
|
|
665
|
+
});
|
|
664
666
|
}
|
|
665
|
-
|
|
666
667
|
connectedCallback() {
|
|
667
668
|
/** @type {ShadowRoot} */
|
|
668
|
-
|
|
669
|
+
this.shadowRoot.innerHTML = '<slot name="content"></slot>';
|
|
669
670
|
this.innerHTML = '<div slot="content">projected</div>';
|
|
670
671
|
}
|
|
671
672
|
},
|
|
672
673
|
);
|
|
673
|
-
|
|
674
|
-
const
|
|
675
|
-
const myContentNode = /** @type {HTMLElement} */ (el.querySelector('[slot=content]'));
|
|
676
|
-
|
|
674
|
+
const el = /** @type {HTMLElement} */ fixtureSync(`<${tagString}></${tagString}>`);
|
|
675
|
+
const myContentNode = /** @type {HTMLElement} */ el.querySelector('[slot=content]');
|
|
677
676
|
const ctrl = new OverlayController({
|
|
678
677
|
...withGlobalTestConfig(),
|
|
679
678
|
contentNode: myContentNode,
|
|
680
679
|
hasBackdrop: true,
|
|
681
680
|
});
|
|
682
|
-
|
|
683
681
|
normalizeOverlayContentWapper(ctrl.contentWrapperNode);
|
|
684
682
|
|
|
685
683
|
// The total dom structure created...
|
|
@@ -693,31 +691,29 @@ describe('OverlayController', () => {
|
|
|
693
691
|
</div>
|
|
694
692
|
</dialog>
|
|
695
693
|
`,
|
|
696
|
-
{
|
|
694
|
+
{
|
|
695
|
+
ignoreAttributes: ['closedby'],
|
|
696
|
+
},
|
|
697
697
|
);
|
|
698
698
|
});
|
|
699
699
|
});
|
|
700
|
-
|
|
701
700
|
describe('When contentWrapperNode needs to be provided for correct arrow positioning', () => {
|
|
702
701
|
it('uses contentWrapperNode as provided for local positioning', async () => {
|
|
703
|
-
const el =
|
|
702
|
+
const el =
|
|
703
|
+
/** @type {HTMLElement} */
|
|
704
704
|
await fixture(html`
|
|
705
705
|
<div id="contentWrapperNode">
|
|
706
706
|
<div id="contentNode"></div>
|
|
707
707
|
<my-arrow></my-arrow>
|
|
708
708
|
</div>
|
|
709
|
-
`)
|
|
710
|
-
);
|
|
711
|
-
|
|
712
|
-
const contentNode = /** @type {HTMLElement} */ (el.querySelector('#contentNode'));
|
|
709
|
+
`);
|
|
710
|
+
const contentNode = /** @type {HTMLElement} */ el.querySelector('#contentNode');
|
|
713
711
|
const contentWrapperNode = el;
|
|
714
|
-
|
|
715
712
|
const ctrl = new OverlayController({
|
|
716
713
|
...withLocalTestConfig(),
|
|
717
714
|
contentNode,
|
|
718
715
|
contentWrapperNode,
|
|
719
716
|
});
|
|
720
|
-
|
|
721
717
|
expect(ctrl.contentWrapperNode).to.equal(contentWrapperNode);
|
|
722
718
|
});
|
|
723
719
|
});
|
|
@@ -734,27 +730,28 @@ describe('OverlayController', () => {
|
|
|
734
730
|
await ctrl.show();
|
|
735
731
|
expect(isActiveElement(ctrl.contentNode)).to.be.true;
|
|
736
732
|
});
|
|
737
|
-
|
|
738
733
|
it('keeps focus within the overlay e.g. you can not tab out by accident', async () => {
|
|
739
|
-
const contentNode =
|
|
740
|
-
|
|
741
|
-
|
|
734
|
+
const contentNode =
|
|
735
|
+
/** @type {HTMLElement} */
|
|
736
|
+
await fixture(html` <div><input id="input1" /><input id="input2" /></div> `);
|
|
742
737
|
const ctrl = new OverlayController({
|
|
743
738
|
...withGlobalTestConfig(),
|
|
744
739
|
trapsKeyboardFocus: true,
|
|
745
740
|
contentNode,
|
|
746
741
|
});
|
|
747
742
|
await ctrl.show();
|
|
748
|
-
|
|
749
743
|
await fixture(html`<button>click me</button>`);
|
|
750
744
|
const input1 = ctrl.contentNode.querySelectorAll('input')[0];
|
|
751
745
|
const input2 = ctrl.contentNode.querySelectorAll('input')[1];
|
|
752
746
|
input2.focus();
|
|
753
|
-
await sendKeys({
|
|
754
|
-
|
|
747
|
+
await sendKeys({
|
|
748
|
+
press: 'Tab',
|
|
749
|
+
});
|
|
755
750
|
if (browserDetection.isChrome) {
|
|
756
751
|
expect(isActiveElement(document.body)).to.be.true;
|
|
757
|
-
await sendKeys({
|
|
752
|
+
await sendKeys({
|
|
753
|
+
press: 'Tab',
|
|
754
|
+
});
|
|
758
755
|
expect(isActiveElement(input1)).to.be.true;
|
|
759
756
|
}
|
|
760
757
|
if (browserDetection.isFirefox) {
|
|
@@ -762,37 +759,40 @@ describe('OverlayController', () => {
|
|
|
762
759
|
// once we focus on the latest focusable element, `input2` in this case,
|
|
763
760
|
// any further Tab presses keeps the focus on `input2` element
|
|
764
761
|
expect(isActiveElement(input2)).to.be.true;
|
|
765
|
-
await sendKeys({
|
|
762
|
+
await sendKeys({
|
|
763
|
+
press: 'Tab',
|
|
764
|
+
});
|
|
766
765
|
expect(isActiveElement(input2)).to.be.true;
|
|
767
766
|
}
|
|
768
767
|
if (browserDetection.isMacSafari) {
|
|
769
768
|
expect(isActiveElement(document.body)).to.be.true;
|
|
770
|
-
await sendKeys({
|
|
769
|
+
await sendKeys({
|
|
770
|
+
press: 'Tab',
|
|
771
|
+
});
|
|
771
772
|
expect(isActiveElement(ctrl.contentNode)).to.be.true;
|
|
772
|
-
await sendKeys({
|
|
773
|
+
await sendKeys({
|
|
774
|
+
press: 'Tab',
|
|
775
|
+
});
|
|
773
776
|
expect(isActiveElement(input1)).to.be.true;
|
|
774
777
|
}
|
|
775
778
|
});
|
|
776
|
-
|
|
777
779
|
it('focuses the element with [autofocus] when dialog gets opened', async () => {
|
|
778
|
-
const contentNode =
|
|
779
|
-
|
|
780
|
-
|
|
780
|
+
const contentNode =
|
|
781
|
+
/** @type {HTMLElement} */
|
|
782
|
+
await fixture(html` <div><input id="input1" /><input id="input2" autofocus /></div> `);
|
|
781
783
|
const ctrl = new OverlayController({
|
|
782
784
|
...withGlobalTestConfig(),
|
|
783
785
|
trapsKeyboardFocus: true,
|
|
784
786
|
contentNode,
|
|
785
787
|
});
|
|
786
788
|
await ctrl.show();
|
|
787
|
-
|
|
788
789
|
const input2 = ctrl.contentNode.querySelectorAll('input')[1];
|
|
789
790
|
expect(isActiveElement(input2)).to.be.true;
|
|
790
791
|
});
|
|
791
|
-
|
|
792
792
|
it('focuses the contentNode when dialog gets opened and there is no [autofocus]', async () => {
|
|
793
|
-
const contentNode =
|
|
794
|
-
|
|
795
|
-
|
|
793
|
+
const contentNode =
|
|
794
|
+
/** @type {HTMLElement} */
|
|
795
|
+
await fixture(html` <div><input id="input1" /><input id="input2" /></div> `);
|
|
796
796
|
const ctrl = new OverlayController({
|
|
797
797
|
...withGlobalTestConfig(),
|
|
798
798
|
trapsKeyboardFocus: true,
|
|
@@ -801,57 +801,48 @@ describe('OverlayController', () => {
|
|
|
801
801
|
await ctrl.show();
|
|
802
802
|
expect(isActiveElement(contentNode)).to.be.true;
|
|
803
803
|
});
|
|
804
|
-
|
|
805
804
|
it('allows to move the focus outside of the overlay if trapsKeyboardFocus is disabled', async () => {
|
|
806
|
-
const contentNode = /** @type {HTMLElement} */
|
|
807
|
-
|
|
805
|
+
const contentNode = /** @type {HTMLElement} */ await fixture(html`<div><input /></div>`);
|
|
808
806
|
const ctrl = new OverlayController({
|
|
809
807
|
...withGlobalTestConfig(),
|
|
810
808
|
contentNode,
|
|
811
809
|
trapsKeyboardFocus: false,
|
|
812
810
|
});
|
|
813
811
|
// add element to dom to allow focus
|
|
814
|
-
/** @type {HTMLElement} */
|
|
812
|
+
/** @type {HTMLElement} */
|
|
813
|
+
await fixture(html`${ctrl.content}`);
|
|
815
814
|
await ctrl.show();
|
|
816
|
-
|
|
817
|
-
const
|
|
818
|
-
const input = /** @type {HTMLInputElement} */ (ctrl.contentNode.querySelector('input'));
|
|
819
|
-
|
|
815
|
+
const elOutside = /** @type {HTMLElement} */ await fixture(html`<input />`);
|
|
816
|
+
const input = /** @type {HTMLInputElement} */ ctrl.contentNode.querySelector('input');
|
|
820
817
|
input.focus();
|
|
821
818
|
simulateTab();
|
|
822
|
-
|
|
823
819
|
expect(isActiveElement(elOutside)).to.be.true;
|
|
824
820
|
});
|
|
825
|
-
|
|
826
821
|
it('keeps focus within overlay with multiple overlays with all traps on true', async () => {
|
|
827
822
|
const ctrl0 = new OverlayController({
|
|
828
823
|
...withGlobalTestConfig(),
|
|
829
824
|
trapsKeyboardFocus: true,
|
|
830
825
|
});
|
|
831
|
-
|
|
832
826
|
const ctrl1 = new OverlayController({
|
|
833
827
|
...withGlobalTestConfig(),
|
|
834
828
|
trapsKeyboardFocus: true,
|
|
835
829
|
});
|
|
836
|
-
|
|
837
830
|
await ctrl0.show();
|
|
838
831
|
await ctrl1.show();
|
|
839
832
|
expect(isActiveElement(ctrl1.contentNode)).to.be.true;
|
|
840
|
-
|
|
841
833
|
await ctrl1.hide();
|
|
842
834
|
expect(isActiveElement(ctrl0.contentNode)).to.be.true;
|
|
843
835
|
});
|
|
844
|
-
|
|
845
836
|
it('warns when contentNode is a host for a shadowRoot', async () => {
|
|
846
837
|
const warnSpy = sinon.spy(console, 'warn');
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
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> `);
|
|
853
845
|
contentNode.shadowRoot?.appendChild(shadowRootContentNode);
|
|
854
|
-
|
|
855
846
|
const ctrl = new OverlayController({
|
|
856
847
|
...withGlobalTestConfig(),
|
|
857
848
|
trapsKeyboardFocus: true,
|
|
@@ -866,7 +857,6 @@ describe('OverlayController', () => {
|
|
|
866
857
|
warnSpy.restore();
|
|
867
858
|
});
|
|
868
859
|
});
|
|
869
|
-
|
|
870
860
|
describe('hidesOnEsc', () => {
|
|
871
861
|
it('hides on [Escape] press', async () => {
|
|
872
862
|
const ctrl = new OverlayController({
|
|
@@ -877,7 +867,6 @@ describe('OverlayController', () => {
|
|
|
877
867
|
await mimicEscapePress(ctrl.contentNode);
|
|
878
868
|
expect(ctrl.isShown).to.be.false;
|
|
879
869
|
});
|
|
880
|
-
|
|
881
870
|
it('stays shown on [Escape] press with `.hidesOnEsc` set to false', async () => {
|
|
882
871
|
const ctrl = new OverlayController({
|
|
883
872
|
...withGlobalTestConfig(),
|
|
@@ -887,7 +876,6 @@ describe('OverlayController', () => {
|
|
|
887
876
|
await mimicEscapePress(ctrl.contentNode);
|
|
888
877
|
expect(ctrl.isShown).to.be.true;
|
|
889
878
|
});
|
|
890
|
-
|
|
891
879
|
it('stays shown on [Escape] press on outside element', async () => {
|
|
892
880
|
const ctrl = new OverlayController({
|
|
893
881
|
...withGlobalTestConfig(),
|
|
@@ -897,7 +885,6 @@ describe('OverlayController', () => {
|
|
|
897
885
|
await mimicEscapePress(document);
|
|
898
886
|
expect(ctrl.isShown).to.be.true;
|
|
899
887
|
});
|
|
900
|
-
|
|
901
888
|
it('stays shown on [Escape] press with modal <dialog> and `.hidesOnEsc` is false', async () => {
|
|
902
889
|
const ctrl = new OverlayController({
|
|
903
890
|
...withGlobalTestConfig(),
|
|
@@ -908,25 +895,21 @@ describe('OverlayController', () => {
|
|
|
908
895
|
await mimicEscapePress(ctrl.contentNode);
|
|
909
896
|
expect(ctrl.isShown).to.be.true;
|
|
910
897
|
});
|
|
911
|
-
|
|
912
898
|
it('parent stays shown on [Escape] press in a nested overlay', async () => {
|
|
913
|
-
const parentContent =
|
|
899
|
+
const parentContent =
|
|
900
|
+
/** @type {HTMLDivElement} */
|
|
914
901
|
await fixture(
|
|
915
902
|
html` <!-- -->
|
|
916
903
|
<div id="parent-overlay--hidesOnEsc">
|
|
917
904
|
<div id="child-overlay--hidesOnEsc">we press [Escape] here</div>
|
|
918
905
|
</div>`,
|
|
919
|
-
)
|
|
920
|
-
);
|
|
906
|
+
);
|
|
921
907
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
922
|
-
|
|
923
908
|
await mimicEscapePress(childOverlay.contentNode);
|
|
924
|
-
|
|
925
909
|
expect(parentOverlay.isShown).to.be.true;
|
|
926
910
|
expect(childOverlay.isShown).to.be.false;
|
|
927
911
|
});
|
|
928
912
|
});
|
|
929
|
-
|
|
930
913
|
describe('hidesOnOutsideEsc', () => {
|
|
931
914
|
it('hides on [Escape] press on outside element', async () => {
|
|
932
915
|
const ctrl = new OverlayController({
|
|
@@ -937,7 +920,6 @@ describe('OverlayController', () => {
|
|
|
937
920
|
await mimicEscapePress(document);
|
|
938
921
|
expect(ctrl.isShown).to.be.false;
|
|
939
922
|
});
|
|
940
|
-
|
|
941
923
|
it('stays shown on [Escape] press on inside element', async () => {
|
|
942
924
|
const ctrl = new OverlayController({
|
|
943
925
|
...withGlobalTestConfig(),
|
|
@@ -947,35 +929,32 @@ describe('OverlayController', () => {
|
|
|
947
929
|
await mimicEscapePress(ctrl.contentNode);
|
|
948
930
|
expect(ctrl.isShown).to.be.true;
|
|
949
931
|
});
|
|
950
|
-
|
|
951
932
|
it('stays shown on [Escape] press in a nested overlay', async () => {
|
|
952
|
-
const parentContent =
|
|
933
|
+
const parentContent =
|
|
934
|
+
/** @type {HTMLDivElement} */
|
|
953
935
|
await fixture(
|
|
954
936
|
html` <!-- -->
|
|
955
937
|
<div id="parent-overlay--hidesOnOutsideEsc">
|
|
956
938
|
<div id="child-overlay--hidesOnOutsideEsc">we press [Escape] here</div>
|
|
957
939
|
</div>`,
|
|
958
|
-
)
|
|
959
|
-
);
|
|
940
|
+
);
|
|
960
941
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
961
942
|
await mimicEscapePress(childOverlay.contentNode);
|
|
962
|
-
|
|
963
943
|
expect(parentOverlay.isShown).to.be.true;
|
|
964
944
|
expect(childOverlay.isShown).to.be.true;
|
|
965
945
|
});
|
|
966
946
|
});
|
|
967
|
-
|
|
968
947
|
describe('Nested hidesOnEsc / hidesOnOutsideEsc', () => {
|
|
969
948
|
describe('Parent has hidesOnEsc and child has hidesOnOutsideEsc', () => {
|
|
970
949
|
it('on [Escape] press in child overlay: parent hides, child stays shown', async () => {
|
|
971
|
-
const parentContent =
|
|
950
|
+
const parentContent =
|
|
951
|
+
/** @type {HTMLDivElement} */
|
|
972
952
|
await fixture(
|
|
973
953
|
html` <!-- -->
|
|
974
954
|
<div id="parent-overlay--hidesOnEsc">
|
|
975
955
|
<div id="child-overlay--hidesOnOutsideEsc">we press [Escape] here</div>
|
|
976
956
|
</div>`,
|
|
977
|
-
)
|
|
978
|
-
);
|
|
957
|
+
);
|
|
979
958
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
980
959
|
await mimicEscapePress(childOverlay.contentNode);
|
|
981
960
|
await childOverlay._showComplete;
|
|
@@ -991,112 +970,100 @@ describe('OverlayController', () => {
|
|
|
991
970
|
await childOverlay.teardown();
|
|
992
971
|
await parentOverlay.teardown();
|
|
993
972
|
});
|
|
994
|
-
|
|
995
973
|
it('on [Escape] press outside overlays: parent stays shown, child hides', async () => {
|
|
996
|
-
const parentContent =
|
|
974
|
+
const parentContent =
|
|
975
|
+
/** @type {HTMLDivElement} */
|
|
997
976
|
await fixture(
|
|
998
977
|
html` <!-- we press [Escape] here -->
|
|
999
978
|
<div id="parent-overlay--hidesOnEsc">
|
|
1000
979
|
<div id="child-overlay--hidesOnOutsideEsc"></div>
|
|
1001
980
|
</div>`,
|
|
1002
|
-
)
|
|
1003
|
-
);
|
|
981
|
+
);
|
|
1004
982
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
1005
983
|
await mimicEscapePress(document);
|
|
1006
|
-
|
|
1007
984
|
expect(parentOverlay.isShown).to.be.true;
|
|
1008
985
|
expect(childOverlay.isShown).to.be.false;
|
|
1009
986
|
});
|
|
1010
|
-
|
|
1011
987
|
it('on [Escape] press in parent overlay: parent is hidden, child is hidden', async () => {
|
|
1012
|
-
const parentContent =
|
|
988
|
+
const parentContent =
|
|
989
|
+
/** @type {HTMLDivElement} */
|
|
1013
990
|
await fixture(
|
|
1014
991
|
html` <!-- -->
|
|
1015
992
|
<div id="parent-overlay--hidesOnEsc">
|
|
1016
993
|
we press [Escape] here
|
|
1017
994
|
<div id="child-overlay--hidesOnOutsideEsc"></div>
|
|
1018
995
|
</div>`,
|
|
1019
|
-
)
|
|
1020
|
-
);
|
|
996
|
+
);
|
|
1021
997
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
1022
998
|
await mimicEscapePress(parentContent);
|
|
1023
|
-
|
|
1024
999
|
expect(parentOverlay.isShown).to.be.false;
|
|
1025
1000
|
expect(childOverlay.isShown).to.be.false;
|
|
1026
1001
|
});
|
|
1027
1002
|
});
|
|
1028
1003
|
describe('Parent has hidesOnOutsideEsc and child has hidesOnEsc', () => {
|
|
1029
1004
|
it('on [Escape] press in child overlay: parent stays shown, child hides', async () => {
|
|
1030
|
-
const parentContent =
|
|
1005
|
+
const parentContent =
|
|
1006
|
+
/** @type {HTMLDivElement} */
|
|
1031
1007
|
await fixture(
|
|
1032
1008
|
html` <!-- -->
|
|
1033
1009
|
<div id="parent-overlay--hidesOnOutsideEsc">
|
|
1034
1010
|
<div id="child-overlay--hidesOnEsc">we press [Escape] here</div>
|
|
1035
1011
|
</div>`,
|
|
1036
|
-
)
|
|
1037
|
-
);
|
|
1012
|
+
);
|
|
1038
1013
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
1039
1014
|
await mimicEscapePress(childOverlay.contentNode);
|
|
1040
|
-
|
|
1041
1015
|
expect(parentOverlay.isShown).to.be.true;
|
|
1042
1016
|
expect(childOverlay.isShown).to.be.false;
|
|
1043
1017
|
});
|
|
1044
|
-
|
|
1045
1018
|
it('on [Escape] press outside overlays: parent hides, child stays shown', async () => {
|
|
1046
|
-
const parentContent =
|
|
1019
|
+
const parentContent =
|
|
1020
|
+
/** @type {HTMLDivElement} */
|
|
1047
1021
|
await fixture(
|
|
1048
1022
|
html` <!-- we press [Escape] here -->
|
|
1049
1023
|
<div id="parent-overlay--hidesOnOutsideEsc">
|
|
1050
1024
|
<div id="child-overlay--hidesOnEsc"></div>
|
|
1051
1025
|
</div>`,
|
|
1052
|
-
)
|
|
1053
|
-
);
|
|
1026
|
+
);
|
|
1054
1027
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
1055
1028
|
await mimicEscapePress(document);
|
|
1056
|
-
|
|
1057
1029
|
expect(parentOverlay.isShown).to.be.false;
|
|
1058
1030
|
expect(childOverlay.isShown).to.be.true;
|
|
1059
1031
|
});
|
|
1060
|
-
|
|
1061
1032
|
it('on [Escape] press in parent overlay: parent hides, child stays shown', async () => {
|
|
1062
|
-
const parentContent =
|
|
1033
|
+
const parentContent =
|
|
1034
|
+
/** @type {HTMLDivElement} */
|
|
1063
1035
|
await fixture(
|
|
1064
1036
|
html` <!-- we press [Escape] here -->
|
|
1065
1037
|
<div id="parent-overlay--hidesOnOutsideEsc">
|
|
1066
1038
|
<div id="child-overlay--hidesOnEsc"></div>
|
|
1067
1039
|
</div>`,
|
|
1068
|
-
)
|
|
1069
|
-
);
|
|
1040
|
+
);
|
|
1070
1041
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
1071
1042
|
await mimicEscapePress(document);
|
|
1072
|
-
|
|
1073
1043
|
expect(parentOverlay.isShown).to.be.false;
|
|
1074
1044
|
expect(childOverlay.isShown).to.be.true;
|
|
1075
1045
|
});
|
|
1076
1046
|
});
|
|
1077
|
-
|
|
1078
1047
|
describe('With shadow dom', () => {
|
|
1079
1048
|
it('on [Escape] press in child overlay in shadow root: parent hides, child stays shown', async () => {
|
|
1080
|
-
const parentContent =
|
|
1049
|
+
const parentContent =
|
|
1050
|
+
/** @type {HTMLDivElement} */
|
|
1081
1051
|
await fixture(
|
|
1082
1052
|
html` <!-- -->
|
|
1083
1053
|
<div id="parent-overlay--hidesOnEsc" data-convert-to-shadow-root>
|
|
1084
1054
|
<div id="child-overlay--hidesOnOutsideEsc">we press [Escape] here</div>
|
|
1085
1055
|
</div>`,
|
|
1086
|
-
)
|
|
1087
|
-
);
|
|
1056
|
+
);
|
|
1088
1057
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
1089
1058
|
await mimicEscapePress(childOverlay.contentNode);
|
|
1090
|
-
|
|
1091
1059
|
expect(parentOverlay.isShown).to.be.false;
|
|
1092
1060
|
expect(childOverlay.isShown).to.be.true;
|
|
1093
1061
|
});
|
|
1094
1062
|
});
|
|
1095
1063
|
});
|
|
1096
|
-
|
|
1097
1064
|
describe('hidesOnOutsideClick', () => {
|
|
1098
1065
|
it('hides on outside click', async () => {
|
|
1099
|
-
const contentNode = /** @type {HTMLElement} */
|
|
1066
|
+
const contentNode = /** @type {HTMLElement} */ await fixture('<div>Content</div>');
|
|
1100
1067
|
const ctrl = new OverlayController({
|
|
1101
1068
|
...withGlobalTestConfig(),
|
|
1102
1069
|
hidesOnOutsideClick: true,
|
|
@@ -1106,16 +1073,16 @@ describe('OverlayController', () => {
|
|
|
1106
1073
|
mimicClick(document.body);
|
|
1107
1074
|
await aTimeout(0);
|
|
1108
1075
|
expect(ctrl.isShown).to.be.false;
|
|
1109
|
-
|
|
1110
1076
|
await ctrl.show();
|
|
1111
|
-
await mimicClick(document.body, {
|
|
1077
|
+
await mimicClick(document.body, {
|
|
1078
|
+
isAsync: true,
|
|
1079
|
+
});
|
|
1112
1080
|
await aTimeout(0);
|
|
1113
1081
|
expect(ctrl.isShown).to.be.false;
|
|
1114
1082
|
});
|
|
1115
|
-
|
|
1116
1083
|
it('doesn\'t hide on "inside" click', async () => {
|
|
1117
|
-
const invokerNode = /** @type {HTMLElement} */
|
|
1118
|
-
const contentNode = /** @type {HTMLElement} */
|
|
1084
|
+
const invokerNode = /** @type {HTMLElement} */ await fixture('<button>Invoker</button>');
|
|
1085
|
+
const contentNode = /** @type {HTMLElement} */ await fixture('<div>Content</div>');
|
|
1119
1086
|
const ctrl = new OverlayController({
|
|
1120
1087
|
...withGlobalTestConfig(),
|
|
1121
1088
|
hidesOnOutsideClick: true,
|
|
@@ -1132,12 +1099,13 @@ describe('OverlayController', () => {
|
|
|
1132
1099
|
// Don't hide on inside (content) click
|
|
1133
1100
|
ctrl.contentNode.click();
|
|
1134
1101
|
await aTimeout(0);
|
|
1135
|
-
|
|
1136
1102
|
expect(ctrl.isShown).to.be.true;
|
|
1137
1103
|
|
|
1138
1104
|
// Don't hide on inside mousedown & outside mouseup
|
|
1139
|
-
await mimicClick(ctrl.contentNode, {
|
|
1140
|
-
|
|
1105
|
+
await mimicClick(ctrl.contentNode, {
|
|
1106
|
+
releaseElement: document.body,
|
|
1107
|
+
isAsync: true,
|
|
1108
|
+
});
|
|
1141
1109
|
await aTimeout(0);
|
|
1142
1110
|
expect(ctrl.isShown).to.be.true;
|
|
1143
1111
|
|
|
@@ -1147,48 +1115,46 @@ describe('OverlayController', () => {
|
|
|
1147
1115
|
await ctrl.show();
|
|
1148
1116
|
expect(ctrl.isShown).to.be.true;
|
|
1149
1117
|
});
|
|
1150
|
-
|
|
1151
1118
|
it('only hides when both mousedown and mouseup events are outside', async () => {
|
|
1152
|
-
const contentNode = /** @type {HTMLElement} */
|
|
1119
|
+
const contentNode = /** @type {HTMLElement} */ await fixture('<div>Content</div>');
|
|
1153
1120
|
const ctrl = new OverlayController({
|
|
1154
1121
|
...withGlobalTestConfig(),
|
|
1155
1122
|
hidesOnOutsideClick: true,
|
|
1156
1123
|
contentNode,
|
|
1157
|
-
invokerNode:
|
|
1124
|
+
invokerNode:
|
|
1125
|
+
/** @type {HTMLElement} */
|
|
1158
1126
|
fixtureSync(html`
|
|
1159
1127
|
<div role="button" style="width: 100px; height: 20px;">Invoker</div>
|
|
1160
|
-
`)
|
|
1161
|
-
),
|
|
1128
|
+
`),
|
|
1162
1129
|
});
|
|
1163
1130
|
await ctrl.show();
|
|
1164
|
-
mimicClick(document.body, {
|
|
1131
|
+
mimicClick(document.body, {
|
|
1132
|
+
releaseElement: contentNode,
|
|
1133
|
+
});
|
|
1165
1134
|
await aTimeout(0);
|
|
1166
1135
|
expect(ctrl.isShown).to.be.true;
|
|
1167
|
-
|
|
1168
|
-
|
|
1136
|
+
mimicClick(contentNode, {
|
|
1137
|
+
releaseElement: document.body,
|
|
1138
|
+
});
|
|
1169
1139
|
await aTimeout(0);
|
|
1170
1140
|
expect(ctrl.isShown).to.be.true;
|
|
1171
|
-
|
|
1172
1141
|
mimicClick(document.body, {
|
|
1173
|
-
releaseElement: /** @type {HTMLElement} */
|
|
1142
|
+
releaseElement: /** @type {HTMLElement} */ ctrl.invokerNode,
|
|
1174
1143
|
});
|
|
1175
1144
|
await aTimeout(0);
|
|
1176
1145
|
expect(ctrl.isShown).to.be.true;
|
|
1177
|
-
|
|
1178
|
-
mimicClick(/** @type {HTMLElement} */ (ctrl.invokerNode), {
|
|
1146
|
+
mimicClick(/** @type {HTMLElement} */ ctrl.invokerNode, {
|
|
1179
1147
|
releaseElement: document.body,
|
|
1180
1148
|
});
|
|
1181
1149
|
await aTimeout(0);
|
|
1182
1150
|
expect(ctrl.isShown).to.be.true;
|
|
1183
|
-
|
|
1184
1151
|
mimicClick(document.body);
|
|
1185
1152
|
await aTimeout(0);
|
|
1186
1153
|
expect(ctrl.isShown).to.be.false;
|
|
1187
1154
|
});
|
|
1188
|
-
|
|
1189
1155
|
it('doesn\'t hide on "inside sub shadow dom" click', async () => {
|
|
1190
|
-
const invokerNode = /** @type {HTMLElement} */
|
|
1191
|
-
const contentNode = /** @type {HTMLElement} */
|
|
1156
|
+
const invokerNode = /** @type {HTMLElement} */ await fixture('<button>Invoker</button>');
|
|
1157
|
+
const contentNode = /** @type {HTMLElement} */ await fixture('<div>Content</div>');
|
|
1192
1158
|
const ctrl = new OverlayController({
|
|
1193
1159
|
...withGlobalTestConfig(),
|
|
1194
1160
|
hidesOnOutsideClick: true,
|
|
@@ -1202,25 +1168,26 @@ describe('OverlayController', () => {
|
|
|
1202
1168
|
class extends HTMLElement {
|
|
1203
1169
|
constructor() {
|
|
1204
1170
|
super();
|
|
1205
|
-
this.attachShadow({
|
|
1171
|
+
this.attachShadow({
|
|
1172
|
+
mode: 'open',
|
|
1173
|
+
});
|
|
1206
1174
|
}
|
|
1207
|
-
|
|
1208
1175
|
connectedCallback() {
|
|
1209
1176
|
/** @type {ShadowRoot} */
|
|
1210
|
-
|
|
1177
|
+
this.shadowRoot.innerHTML = '<div><button>click me</button></div>';
|
|
1211
1178
|
}
|
|
1212
1179
|
},
|
|
1213
1180
|
);
|
|
1214
1181
|
const tag = unsafeStatic(tagString);
|
|
1215
1182
|
ctrl.updateConfig({
|
|
1216
|
-
contentNode:
|
|
1183
|
+
contentNode:
|
|
1184
|
+
/** @type {HTMLElement} */
|
|
1217
1185
|
await fixture(html`
|
|
1218
1186
|
<div>
|
|
1219
1187
|
<div>Content</div>
|
|
1220
1188
|
<${tag}></${tag}>
|
|
1221
1189
|
</div>
|
|
1222
|
-
`)
|
|
1223
|
-
),
|
|
1190
|
+
`),
|
|
1224
1191
|
});
|
|
1225
1192
|
await ctrl.show();
|
|
1226
1193
|
|
|
@@ -1228,7 +1195,6 @@ describe('OverlayController', () => {
|
|
|
1228
1195
|
/** @type {ShadowRoot} */
|
|
1229
1196
|
// @ts-expect-error
|
|
1230
1197
|
ctrl.contentNode.querySelector(tagString).shadowRoot.querySelector('button').click();
|
|
1231
|
-
|
|
1232
1198
|
await aTimeout(0);
|
|
1233
1199
|
expect(ctrl.isShown).to.be.true;
|
|
1234
1200
|
|
|
@@ -1238,12 +1204,11 @@ describe('OverlayController', () => {
|
|
|
1238
1204
|
await ctrl.show();
|
|
1239
1205
|
expect(ctrl.isShown).to.be.true;
|
|
1240
1206
|
});
|
|
1241
|
-
|
|
1242
1207
|
it('works with 3rd party code using "event.stopPropagation()" on bubble phase', async () => {
|
|
1243
|
-
const invokerNode =
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
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>');
|
|
1247
1212
|
const ctrl = new OverlayController({
|
|
1248
1213
|
...withLocalTestConfig(),
|
|
1249
1214
|
hidesOnOutsideClick: true,
|
|
@@ -1251,22 +1216,17 @@ describe('OverlayController', () => {
|
|
|
1251
1216
|
invokerNode,
|
|
1252
1217
|
});
|
|
1253
1218
|
const stopProp = (/** @type {Event} */ e) => e.stopPropagation();
|
|
1254
|
-
const dom = await fixture(
|
|
1255
|
-
`
|
|
1219
|
+
const dom = await fixture(`
|
|
1256
1220
|
<div>
|
|
1257
1221
|
<div id="popup">${invokerNode}${contentNode}</div>
|
|
1258
1222
|
<div id="third-party-noise" @click="${stopProp}" @mousedown="${stopProp}" @mouseup="${stopProp}">
|
|
1259
1223
|
This element prevents our handlers from reaching the document click handler.
|
|
1260
1224
|
</div>
|
|
1261
1225
|
</div>
|
|
1262
|
-
|
|
1263
|
-
);
|
|
1264
|
-
|
|
1226
|
+
`);
|
|
1265
1227
|
await ctrl.show();
|
|
1266
1228
|
expect(ctrl.isShown).to.equal(true);
|
|
1267
|
-
|
|
1268
|
-
const noiseEl = /** @type {HTMLElement} */ (dom.querySelector('#third-party-noise'));
|
|
1269
|
-
|
|
1229
|
+
const noiseEl = /** @type {HTMLElement} */ dom.querySelector('#third-party-noise');
|
|
1270
1230
|
mimicClick(noiseEl);
|
|
1271
1231
|
await aTimeout(0);
|
|
1272
1232
|
expect(ctrl.isShown).to.equal(false);
|
|
@@ -1275,12 +1235,11 @@ describe('OverlayController', () => {
|
|
|
1275
1235
|
await ctrl.show();
|
|
1276
1236
|
expect(ctrl.isShown).to.equal(true);
|
|
1277
1237
|
});
|
|
1278
|
-
|
|
1279
1238
|
it('works with 3rd party code using "event.stopPropagation()" on capture phase', async () => {
|
|
1280
|
-
const invokerNode =
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
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>');
|
|
1284
1243
|
const ctrl = new OverlayController({
|
|
1285
1244
|
...withLocalTestConfig(),
|
|
1286
1245
|
hidesOnOutsideClick: true,
|
|
@@ -1288,7 +1247,8 @@ describe('OverlayController', () => {
|
|
|
1288
1247
|
invokerNode,
|
|
1289
1248
|
});
|
|
1290
1249
|
const stopProp = (/** @type {Event} */ e) => e.stopPropagation();
|
|
1291
|
-
const dom =
|
|
1250
|
+
const dom =
|
|
1251
|
+
/** @type {HTMLElement} */
|
|
1292
1252
|
await fixture(`
|
|
1293
1253
|
<div>
|
|
1294
1254
|
<div id="popup">${invokerNode}${ctrl.content}</div>
|
|
@@ -1296,18 +1256,13 @@ describe('OverlayController', () => {
|
|
|
1296
1256
|
This element prevents our handlers from reaching the document click handler.
|
|
1297
1257
|
</div>
|
|
1298
1258
|
</div>
|
|
1299
|
-
`)
|
|
1300
|
-
);
|
|
1301
|
-
|
|
1302
|
-
const noiseEl = /** @type {HTMLElement} */ (dom.querySelector('#third-party-noise'));
|
|
1303
|
-
|
|
1259
|
+
`);
|
|
1260
|
+
const noiseEl = /** @type {HTMLElement} */ dom.querySelector('#third-party-noise');
|
|
1304
1261
|
noiseEl.addEventListener('click', stopProp, true);
|
|
1305
1262
|
noiseEl.addEventListener('mousedown', stopProp, true);
|
|
1306
1263
|
noiseEl.addEventListener('mouseup', stopProp, true);
|
|
1307
|
-
|
|
1308
1264
|
await ctrl.show();
|
|
1309
1265
|
expect(ctrl.isShown).to.equal(true);
|
|
1310
|
-
|
|
1311
1266
|
mimicClick(noiseEl);
|
|
1312
1267
|
await aTimeout(0);
|
|
1313
1268
|
expect(ctrl.isShown).to.equal(false);
|
|
@@ -1316,17 +1271,16 @@ describe('OverlayController', () => {
|
|
|
1316
1271
|
await ctrl.show();
|
|
1317
1272
|
expect(ctrl.isShown).to.equal(true);
|
|
1318
1273
|
});
|
|
1319
|
-
|
|
1320
1274
|
it('doesn\'t hide on "inside label" click', async () => {
|
|
1321
|
-
const contentNode =
|
|
1275
|
+
const contentNode =
|
|
1276
|
+
/** @type {HTMLElement} */
|
|
1322
1277
|
await fixture(`
|
|
1323
1278
|
<div>
|
|
1324
1279
|
<label for="test">test</label>
|
|
1325
1280
|
<input id="test">
|
|
1326
1281
|
Content
|
|
1327
|
-
</div>`)
|
|
1328
|
-
);
|
|
1329
|
-
const labelNode = /** @type {HTMLElement} */ (contentNode.querySelector('label[for=test]'));
|
|
1282
|
+
</div>`);
|
|
1283
|
+
const labelNode = /** @type {HTMLElement} */ contentNode.querySelector('label[for=test]');
|
|
1330
1284
|
const ctrl = new OverlayController({
|
|
1331
1285
|
...withGlobalTestConfig(),
|
|
1332
1286
|
hidesOnOutsideClick: true,
|
|
@@ -1337,27 +1291,22 @@ describe('OverlayController', () => {
|
|
|
1337
1291
|
// Don't hide on label click
|
|
1338
1292
|
labelNode.click();
|
|
1339
1293
|
await aTimeout(0);
|
|
1340
|
-
|
|
1341
1294
|
expect(ctrl.isShown).to.be.true;
|
|
1342
1295
|
});
|
|
1343
|
-
|
|
1344
1296
|
it('hides when window is blurred (useful for iframes)', async () => {
|
|
1345
1297
|
const ctrl = new OverlayController({
|
|
1346
1298
|
...withGlobalTestConfig(),
|
|
1347
1299
|
hidesOnOutsideClick: true,
|
|
1348
1300
|
});
|
|
1349
1301
|
await ctrl.show();
|
|
1350
|
-
|
|
1351
1302
|
window.dispatchEvent(new Event('blur'));
|
|
1352
1303
|
await aTimeout(0);
|
|
1353
|
-
|
|
1354
1304
|
expect(ctrl.isShown).to.be.false;
|
|
1355
1305
|
});
|
|
1356
1306
|
});
|
|
1357
|
-
|
|
1358
1307
|
describe('elementToFocusAfterHide', () => {
|
|
1359
1308
|
it('focuses body when hiding by default', async () => {
|
|
1360
|
-
const contentNode = /** @type {HTMLElement} */
|
|
1309
|
+
const contentNode = /** @type {HTMLElement} */ await fixture('<div><input /></div>');
|
|
1361
1310
|
const ctrl = new OverlayController({
|
|
1362
1311
|
...withGlobalTestConfig(),
|
|
1363
1312
|
viewportConfig: {
|
|
@@ -1365,90 +1314,78 @@ describe('OverlayController', () => {
|
|
|
1365
1314
|
},
|
|
1366
1315
|
contentNode,
|
|
1367
1316
|
});
|
|
1368
|
-
|
|
1369
1317
|
await ctrl.show();
|
|
1370
|
-
const input = /** @type {HTMLInputElement} */
|
|
1318
|
+
const input = /** @type {HTMLInputElement} */ contentNode.querySelector('input');
|
|
1371
1319
|
input.focus();
|
|
1372
1320
|
expect(isActiveElement(input)).to.be.true;
|
|
1373
|
-
|
|
1374
1321
|
await ctrl.hide();
|
|
1375
1322
|
expect(isActiveElement(document.body)).to.be.true;
|
|
1376
1323
|
});
|
|
1377
|
-
|
|
1378
1324
|
it('supports elementToFocusAfterHide option to focus it when hiding', async () => {
|
|
1379
|
-
const input = /** @type {HTMLElement} */
|
|
1380
|
-
const contentNode =
|
|
1381
|
-
|
|
1382
|
-
|
|
1325
|
+
const input = /** @type {HTMLElement} */ await fixture('<input />');
|
|
1326
|
+
const contentNode =
|
|
1327
|
+
/** @type {HTMLElement} */
|
|
1328
|
+
await fixture('<div><textarea></textarea></div>');
|
|
1383
1329
|
const ctrl = new OverlayController({
|
|
1384
1330
|
...withGlobalTestConfig(),
|
|
1385
1331
|
elementToFocusAfterHide: input,
|
|
1386
1332
|
contentNode,
|
|
1387
1333
|
});
|
|
1388
|
-
|
|
1389
1334
|
await ctrl.show();
|
|
1390
|
-
const textarea = /** @type {HTMLTextAreaElement} */
|
|
1335
|
+
const textarea = /** @type {HTMLTextAreaElement} */ contentNode.querySelector('textarea');
|
|
1391
1336
|
textarea.focus();
|
|
1392
1337
|
expect(isActiveElement(textarea)).to.be.true;
|
|
1393
|
-
|
|
1394
1338
|
await ctrl.hide();
|
|
1395
1339
|
expect(isActiveElement(input)).to.be.true;
|
|
1396
1340
|
expect(isInViewport(input)).to.be.true;
|
|
1397
1341
|
});
|
|
1398
|
-
|
|
1399
1342
|
it('supports elementToFocusAfterHide option when shadowRoot involved', async () => {
|
|
1400
|
-
const input = /** @type {HTMLElement} */
|
|
1401
|
-
const contentNode =
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1343
|
+
const input = /** @type {HTMLElement} */ await fixture('<input />');
|
|
1344
|
+
const contentNode =
|
|
1345
|
+
/** @type {HTMLElement} */
|
|
1346
|
+
await fixture('<div><textarea></textarea></div>');
|
|
1405
1347
|
const shadowHost = document.createElement('div');
|
|
1406
|
-
shadowHost.attachShadow({
|
|
1407
|
-
|
|
1348
|
+
shadowHost.attachShadow({
|
|
1349
|
+
mode: 'open',
|
|
1350
|
+
});
|
|
1351
|
+
/** @type {ShadowRoot} */
|
|
1352
|
+
shadowHost.shadowRoot.innerHTML = `<slot></slot>`;
|
|
1408
1353
|
shadowHost.appendChild(contentNode);
|
|
1409
1354
|
document.body.appendChild(shadowHost);
|
|
1410
|
-
|
|
1411
1355
|
const ctrl = new OverlayController({
|
|
1412
1356
|
...withGlobalTestConfig(),
|
|
1413
1357
|
elementToFocusAfterHide: input,
|
|
1414
1358
|
contentNode,
|
|
1415
1359
|
});
|
|
1416
|
-
|
|
1417
1360
|
await ctrl.show();
|
|
1418
|
-
const textarea = /** @type {HTMLTextAreaElement} */
|
|
1361
|
+
const textarea = /** @type {HTMLTextAreaElement} */ contentNode.querySelector('textarea');
|
|
1419
1362
|
textarea.focus();
|
|
1420
1363
|
expect(isActiveElement(textarea)).to.be.true;
|
|
1421
|
-
|
|
1422
1364
|
await ctrl.hide();
|
|
1423
1365
|
expect(isActiveElement(input)).to.be.true;
|
|
1424
|
-
|
|
1425
1366
|
document.body.removeChild(shadowHost);
|
|
1426
1367
|
});
|
|
1427
|
-
|
|
1428
1368
|
it(`only sets focus when outside world didn't take over already`, async () => {
|
|
1429
|
-
const input = /** @type {HTMLElement} */
|
|
1430
|
-
const outsideButton = /** @type {HTMLButtonElement} */
|
|
1431
|
-
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>');
|
|
1432
1372
|
const ctrl = new OverlayController({
|
|
1433
1373
|
...withGlobalTestConfig(),
|
|
1434
1374
|
elementToFocusAfterHide: input,
|
|
1435
1375
|
contentNode,
|
|
1436
1376
|
});
|
|
1437
|
-
|
|
1438
1377
|
await ctrl.show();
|
|
1439
1378
|
// an outside element has taken over focus
|
|
1440
1379
|
outsideButton.focus();
|
|
1441
1380
|
expect(isActiveElement(outsideButton)).to.be.true;
|
|
1442
|
-
|
|
1443
1381
|
await ctrl.hide();
|
|
1444
1382
|
expect(isActiveElement(outsideButton)).to.be.true;
|
|
1445
1383
|
});
|
|
1446
|
-
|
|
1447
1384
|
it('allows to set elementToFocusAfterHide on show', async () => {
|
|
1448
|
-
const input = /** @type {HTMLElement} */
|
|
1449
|
-
const contentNode =
|
|
1450
|
-
|
|
1451
|
-
|
|
1385
|
+
const input = /** @type {HTMLElement} */ await fixture('<input />');
|
|
1386
|
+
const contentNode =
|
|
1387
|
+
/** @type {HTMLElement} */
|
|
1388
|
+
await fixture('<div><textarea></textarea></div>');
|
|
1452
1389
|
const ctrl = new OverlayController({
|
|
1453
1390
|
...withGlobalTestConfig(),
|
|
1454
1391
|
viewportConfig: {
|
|
@@ -1456,31 +1393,25 @@ describe('OverlayController', () => {
|
|
|
1456
1393
|
},
|
|
1457
1394
|
contentNode,
|
|
1458
1395
|
});
|
|
1459
|
-
|
|
1460
1396
|
await ctrl.show(input);
|
|
1461
|
-
const textarea = /** @type {HTMLTextAreaElement} */
|
|
1397
|
+
const textarea = /** @type {HTMLTextAreaElement} */ contentNode.querySelector('textarea');
|
|
1462
1398
|
textarea.focus();
|
|
1463
1399
|
expect(isActiveElement(textarea)).to.be.true;
|
|
1464
|
-
|
|
1465
1400
|
await ctrl.hide();
|
|
1466
1401
|
expect(isActiveElement(input)).to.be.true;
|
|
1467
1402
|
});
|
|
1468
1403
|
});
|
|
1469
|
-
|
|
1470
1404
|
describe('preventsScroll', () => {
|
|
1471
1405
|
it('prevent scrolling the background', async () => {
|
|
1472
1406
|
const ctrl = new OverlayController({
|
|
1473
1407
|
...withGlobalTestConfig(),
|
|
1474
1408
|
preventsScroll: true,
|
|
1475
1409
|
});
|
|
1476
|
-
|
|
1477
1410
|
await ctrl.show();
|
|
1478
1411
|
expect(Array.from(document.body.classList)).to.contain('overlays-scroll-lock');
|
|
1479
|
-
|
|
1480
1412
|
await ctrl.hide();
|
|
1481
1413
|
expect(Array.from(document.body.classList)).to.not.contain('overlays-scroll-lock');
|
|
1482
1414
|
});
|
|
1483
|
-
|
|
1484
1415
|
it('keeps preventing of scrolling when multiple overlays are opened and closed', async () => {
|
|
1485
1416
|
const ctrl0 = new OverlayController({
|
|
1486
1417
|
...withGlobalTestConfig(),
|
|
@@ -1490,13 +1421,11 @@ describe('OverlayController', () => {
|
|
|
1490
1421
|
...withGlobalTestConfig(),
|
|
1491
1422
|
preventsScroll: true,
|
|
1492
1423
|
});
|
|
1493
|
-
|
|
1494
1424
|
await ctrl0.show();
|
|
1495
1425
|
await ctrl1.show();
|
|
1496
1426
|
await ctrl1.hide();
|
|
1497
1427
|
expect(Array.from(document.body.classList)).to.contain('overlays-scroll-lock');
|
|
1498
1428
|
});
|
|
1499
|
-
|
|
1500
1429
|
it('does not accumulate body margins when nested overlays have preventsScroll', async () => {
|
|
1501
1430
|
const ctrl0 = new OverlayController({
|
|
1502
1431
|
...withGlobalTestConfig(),
|
|
@@ -1506,45 +1435,35 @@ describe('OverlayController', () => {
|
|
|
1506
1435
|
...withGlobalTestConfig(),
|
|
1507
1436
|
preventsScroll: true,
|
|
1508
1437
|
});
|
|
1509
|
-
|
|
1510
1438
|
const originalMarginRight = document.body.style.marginRight;
|
|
1511
|
-
|
|
1512
1439
|
await ctrl0.show();
|
|
1513
1440
|
const marginAfterFirst = document.body.style.marginRight;
|
|
1514
|
-
|
|
1515
1441
|
await ctrl1.show();
|
|
1516
1442
|
const marginAfterSecond = document.body.style.marginRight;
|
|
1517
1443
|
|
|
1518
1444
|
// The margin should NOT increase further when second overlay opens
|
|
1519
1445
|
expect(marginAfterSecond).to.equal(marginAfterFirst);
|
|
1520
|
-
|
|
1521
1446
|
await ctrl1.hide();
|
|
1522
1447
|
// After hiding second, first still prevents scroll — margin stays
|
|
1523
1448
|
expect(document.body.style.marginRight).to.equal(marginAfterFirst);
|
|
1524
|
-
|
|
1525
1449
|
await ctrl0.hide();
|
|
1526
1450
|
// After hiding all, original margin is restored
|
|
1527
1451
|
expect(document.body.style.marginRight).to.equal(originalMarginRight);
|
|
1528
1452
|
});
|
|
1529
|
-
|
|
1530
1453
|
it('restores body margin when overlay with preventsScroll is torn down while shown', async () => {
|
|
1531
1454
|
const ctrl = new OverlayController({
|
|
1532
1455
|
...withGlobalTestConfig(),
|
|
1533
1456
|
preventsScroll: true,
|
|
1534
1457
|
});
|
|
1535
|
-
|
|
1536
1458
|
const originalMarginRight = document.body.style.marginRight;
|
|
1537
|
-
|
|
1538
1459
|
await ctrl.show();
|
|
1539
1460
|
const marginAfterShow = document.body.style.marginRight;
|
|
1540
1461
|
// Margin should be set after show
|
|
1541
1462
|
expect(marginAfterShow).to.not.equal(originalMarginRight);
|
|
1542
|
-
|
|
1543
1463
|
ctrl.teardown();
|
|
1544
1464
|
// Margin should be restored after teardown
|
|
1545
1465
|
expect(document.body.style.marginRight).to.equal(originalMarginRight);
|
|
1546
1466
|
});
|
|
1547
|
-
|
|
1548
1467
|
it('does not break body margin when teardown() is called on a hidden overlay', async () => {
|
|
1549
1468
|
const ctrl0 = new OverlayController({
|
|
1550
1469
|
...withGlobalTestConfig(),
|
|
@@ -1554,7 +1473,6 @@ describe('OverlayController', () => {
|
|
|
1554
1473
|
...withGlobalTestConfig(),
|
|
1555
1474
|
preventsScroll: true,
|
|
1556
1475
|
});
|
|
1557
|
-
|
|
1558
1476
|
const originalMarginRight = document.body.style.marginRight;
|
|
1559
1477
|
|
|
1560
1478
|
// Show first overlay
|
|
@@ -1572,13 +1490,11 @@ describe('OverlayController', () => {
|
|
|
1572
1490
|
// Now margin should be restored
|
|
1573
1491
|
expect(document.body.style.marginRight).to.equal(originalMarginRight);
|
|
1574
1492
|
});
|
|
1575
|
-
|
|
1576
1493
|
it('does not break body margin when updateConfig() is called on a hidden overlay', async () => {
|
|
1577
1494
|
const ctrl = new OverlayController({
|
|
1578
1495
|
...withGlobalTestConfig(),
|
|
1579
1496
|
preventsScroll: true,
|
|
1580
1497
|
});
|
|
1581
|
-
|
|
1582
1498
|
const originalMarginRight = document.body.style.marginRight;
|
|
1583
1499
|
|
|
1584
1500
|
// updateConfig calls teardown internally
|
|
@@ -1600,7 +1516,6 @@ describe('OverlayController', () => {
|
|
|
1600
1516
|
expect(document.body.style.marginRight).to.equal(originalMarginRight);
|
|
1601
1517
|
});
|
|
1602
1518
|
});
|
|
1603
|
-
|
|
1604
1519
|
describe('hasBackdrop', () => {
|
|
1605
1520
|
it('has no backdrop by default', async () => {
|
|
1606
1521
|
const ctrl = new OverlayController({
|
|
@@ -1609,7 +1524,6 @@ describe('OverlayController', () => {
|
|
|
1609
1524
|
await ctrl.show();
|
|
1610
1525
|
expect(ctrl.backdropNode).to.be.undefined;
|
|
1611
1526
|
});
|
|
1612
|
-
|
|
1613
1527
|
it('supports a backdrop option', async () => {
|
|
1614
1528
|
const ctrl = new OverlayController({
|
|
1615
1529
|
...withGlobalTestConfig(),
|
|
@@ -1618,7 +1532,6 @@ describe('OverlayController', () => {
|
|
|
1618
1532
|
await ctrl.show();
|
|
1619
1533
|
expect(ctrl.backdropNode).to.be.undefined;
|
|
1620
1534
|
await ctrl.hide();
|
|
1621
|
-
|
|
1622
1535
|
const controllerWithBackdrop = new OverlayController({
|
|
1623
1536
|
...withGlobalTestConfig(),
|
|
1624
1537
|
hasBackdrop: true,
|
|
@@ -1626,7 +1539,6 @@ describe('OverlayController', () => {
|
|
|
1626
1539
|
await controllerWithBackdrop.show();
|
|
1627
1540
|
expect(controllerWithBackdrop.backdropNode).to.have.class('overlays__backdrop');
|
|
1628
1541
|
});
|
|
1629
|
-
|
|
1630
1542
|
it('reenables the backdrop when shown/hidden/shown', async () => {
|
|
1631
1543
|
const ctrl = new OverlayController({
|
|
1632
1544
|
...withGlobalTestConfig(),
|
|
@@ -1638,7 +1550,6 @@ describe('OverlayController', () => {
|
|
|
1638
1550
|
await ctrl.show();
|
|
1639
1551
|
expect(ctrl.backdropNode).to.have.class('overlays__backdrop');
|
|
1640
1552
|
});
|
|
1641
|
-
|
|
1642
1553
|
it('adds and stacks backdrops if .hasBackdrop is enabled', async () => {
|
|
1643
1554
|
const ctrl0 = new OverlayController({
|
|
1644
1555
|
...withGlobalTestConfig(),
|
|
@@ -1646,7 +1557,6 @@ describe('OverlayController', () => {
|
|
|
1646
1557
|
});
|
|
1647
1558
|
await ctrl0.show();
|
|
1648
1559
|
expect(ctrl0.backdropNode).to.have.class('overlays__backdrop');
|
|
1649
|
-
|
|
1650
1560
|
const ctrl1 = new OverlayController({
|
|
1651
1561
|
...withGlobalTestConfig(),
|
|
1652
1562
|
hasBackdrop: false,
|
|
@@ -1654,19 +1564,16 @@ describe('OverlayController', () => {
|
|
|
1654
1564
|
await ctrl1.show();
|
|
1655
1565
|
expect(ctrl0.backdropNode).to.have.class('overlays__backdrop');
|
|
1656
1566
|
expect(ctrl1.backdropNode).to.be.undefined;
|
|
1657
|
-
|
|
1658
1567
|
const ctrl2 = new OverlayController({
|
|
1659
1568
|
...withGlobalTestConfig(),
|
|
1660
1569
|
hasBackdrop: true,
|
|
1661
1570
|
});
|
|
1662
1571
|
await ctrl2.show();
|
|
1663
|
-
|
|
1664
1572
|
expect(ctrl0.backdropNode).to.have.class('overlays__backdrop');
|
|
1665
1573
|
expect(ctrl1.backdropNode).to.be.undefined;
|
|
1666
1574
|
expect(ctrl2.backdropNode).to.have.class('overlays__backdrop');
|
|
1667
1575
|
});
|
|
1668
1576
|
});
|
|
1669
|
-
|
|
1670
1577
|
describe('locally placed overlay with hasBackdrop', () => {
|
|
1671
1578
|
it('has no backdrop by default', async () => {
|
|
1672
1579
|
const ctrl = new OverlayController({
|
|
@@ -1675,7 +1582,6 @@ describe('OverlayController', () => {
|
|
|
1675
1582
|
await ctrl.show();
|
|
1676
1583
|
expect(ctrl.backdropNode).to.be.undefined;
|
|
1677
1584
|
});
|
|
1678
|
-
|
|
1679
1585
|
it('supports a backdrop option', async () => {
|
|
1680
1586
|
const ctrl = new OverlayController({
|
|
1681
1587
|
...withLocalTestConfig(),
|
|
@@ -1684,10 +1590,8 @@ describe('OverlayController', () => {
|
|
|
1684
1590
|
await ctrl.show();
|
|
1685
1591
|
expect(ctrl.backdropNode).to.be.undefined;
|
|
1686
1592
|
await ctrl.hide();
|
|
1687
|
-
|
|
1688
1593
|
const backdropNode = document.createElement('div');
|
|
1689
1594
|
backdropNode.classList.add('custom-backdrop');
|
|
1690
|
-
|
|
1691
1595
|
const controllerWithBackdrop = new OverlayController({
|
|
1692
1596
|
...withLocalTestConfig(),
|
|
1693
1597
|
hasBackdrop: true,
|
|
@@ -1696,11 +1600,9 @@ describe('OverlayController', () => {
|
|
|
1696
1600
|
await controllerWithBackdrop.show();
|
|
1697
1601
|
expect(controllerWithBackdrop.backdropNode).to.have.class('custom-backdrop');
|
|
1698
1602
|
});
|
|
1699
|
-
|
|
1700
1603
|
it('reenables the backdrop when shown/hidden/shown', async () => {
|
|
1701
1604
|
const backdropNode = document.createElement('div');
|
|
1702
1605
|
backdropNode.classList.add('custom-backdrop');
|
|
1703
|
-
|
|
1704
1606
|
const ctrl = new OverlayController({
|
|
1705
1607
|
...withLocalTestConfig(),
|
|
1706
1608
|
hasBackdrop: true,
|
|
@@ -1712,11 +1614,9 @@ describe('OverlayController', () => {
|
|
|
1712
1614
|
await ctrl.show();
|
|
1713
1615
|
expect(ctrl.backdropNode).to.have.class('custom-backdrop');
|
|
1714
1616
|
});
|
|
1715
|
-
|
|
1716
1617
|
it('adds and stacks backdrops if .hasBackdrop is enabled', async () => {
|
|
1717
1618
|
const backdropNode = document.createElement('div');
|
|
1718
1619
|
backdropNode.classList.add('custom-backdrop-zero');
|
|
1719
|
-
|
|
1720
1620
|
const ctrl0 = new OverlayController({
|
|
1721
1621
|
...withLocalTestConfig(),
|
|
1722
1622
|
hasBackdrop: true,
|
|
@@ -1724,7 +1624,6 @@ describe('OverlayController', () => {
|
|
|
1724
1624
|
});
|
|
1725
1625
|
await ctrl0.show();
|
|
1726
1626
|
expect(ctrl0.backdropNode).to.have.class('custom-backdrop-zero');
|
|
1727
|
-
|
|
1728
1627
|
const ctrl1 = new OverlayController({
|
|
1729
1628
|
...withLocalTestConfig(),
|
|
1730
1629
|
hasBackdrop: false,
|
|
@@ -1732,23 +1631,19 @@ describe('OverlayController', () => {
|
|
|
1732
1631
|
await ctrl1.show();
|
|
1733
1632
|
expect(ctrl0.backdropNode).to.have.class('custom-backdrop-zero');
|
|
1734
1633
|
expect(ctrl1.backdropNode).to.be.undefined;
|
|
1735
|
-
|
|
1736
1634
|
const anotherBackdropNode = document.createElement('div');
|
|
1737
1635
|
anotherBackdropNode.classList.add('custom-backdrop-two');
|
|
1738
|
-
|
|
1739
1636
|
const ctrl2 = new OverlayController({
|
|
1740
1637
|
...withLocalTestConfig(),
|
|
1741
1638
|
hasBackdrop: true,
|
|
1742
1639
|
backdropNode: anotherBackdropNode,
|
|
1743
1640
|
});
|
|
1744
1641
|
await ctrl2.show();
|
|
1745
|
-
|
|
1746
1642
|
expect(ctrl0.backdropNode).to.have.class('custom-backdrop-zero');
|
|
1747
1643
|
expect(ctrl1.backdropNode).to.be.undefined;
|
|
1748
1644
|
expect(ctrl2.backdropNode).to.have.class('custom-backdrop-two');
|
|
1749
1645
|
});
|
|
1750
1646
|
});
|
|
1751
|
-
|
|
1752
1647
|
describe('isBlocking', () => {
|
|
1753
1648
|
it('prevents showing of other overlays', async () => {
|
|
1754
1649
|
const ctrl0 = new OverlayController({
|
|
@@ -1767,30 +1662,25 @@ describe('OverlayController', () => {
|
|
|
1767
1662
|
...withGlobalTestConfig(),
|
|
1768
1663
|
isBlocking: false,
|
|
1769
1664
|
});
|
|
1770
|
-
|
|
1771
1665
|
await ctrl0.show();
|
|
1772
1666
|
await ctrl1.show();
|
|
1773
1667
|
await ctrl2.show(); // blocking
|
|
1774
1668
|
expect(ctrl0.__wrappingDialogNode).to.not.be.displayed;
|
|
1775
1669
|
expect(ctrl1.__wrappingDialogNode).to.not.be.displayed;
|
|
1776
1670
|
expect(ctrl2.__wrappingDialogNode).to.be.displayed;
|
|
1777
|
-
|
|
1778
1671
|
await ctrl3.show();
|
|
1779
1672
|
await ctrl3._showComplete;
|
|
1780
1673
|
expect(ctrl3.__wrappingDialogNode).to.be.displayed;
|
|
1781
|
-
|
|
1782
1674
|
await ctrl2.hide();
|
|
1783
1675
|
await ctrl2._hideComplete;
|
|
1784
1676
|
expect(ctrl0.__wrappingDialogNode).to.be.displayed;
|
|
1785
1677
|
expect(ctrl1.__wrappingDialogNode).to.be.displayed;
|
|
1786
|
-
|
|
1787
1678
|
await ctrl2.show(); // blocking
|
|
1788
1679
|
expect(ctrl0.__wrappingDialogNode).to.not.be.displayed;
|
|
1789
1680
|
expect(ctrl1.__wrappingDialogNode).to.not.be.displayed;
|
|
1790
1681
|
expect(ctrl2.__wrappingDialogNode).to.be.displayed;
|
|
1791
1682
|
expect(ctrl3.__wrappingDialogNode).to.not.be.displayed;
|
|
1792
1683
|
});
|
|
1793
|
-
|
|
1794
1684
|
it('keeps backdrop status when used in combination with blocking', async () => {
|
|
1795
1685
|
const ctrl0 = new OverlayController({
|
|
1796
1686
|
...withGlobalTestConfig(),
|
|
@@ -1798,7 +1688,6 @@ describe('OverlayController', () => {
|
|
|
1798
1688
|
hasBackdrop: true,
|
|
1799
1689
|
});
|
|
1800
1690
|
await ctrl0.show();
|
|
1801
|
-
|
|
1802
1691
|
const ctrl1 = new OverlayController({
|
|
1803
1692
|
...withGlobalTestConfig(),
|
|
1804
1693
|
isBlocking: false,
|
|
@@ -1808,13 +1697,11 @@ describe('OverlayController', () => {
|
|
|
1808
1697
|
await ctrl1.hide();
|
|
1809
1698
|
expect(ctrl0.hasActiveBackdrop).to.be.true;
|
|
1810
1699
|
expect(ctrl1.hasActiveBackdrop).to.be.false;
|
|
1811
|
-
|
|
1812
1700
|
await ctrl1.show();
|
|
1813
1701
|
expect(ctrl0.hasActiveBackdrop).to.be.true;
|
|
1814
1702
|
expect(ctrl1.hasActiveBackdrop).to.be.true;
|
|
1815
1703
|
});
|
|
1816
1704
|
});
|
|
1817
|
-
|
|
1818
1705
|
describe('elementToFocusOnShow', () => {
|
|
1819
1706
|
it('adds tabindex="-1" to the content node when elementToFocusOnShow is true', async () => {
|
|
1820
1707
|
const ctrl = new OverlayController({
|
|
@@ -1822,51 +1709,52 @@ describe('OverlayController', () => {
|
|
|
1822
1709
|
isBlocking: false,
|
|
1823
1710
|
elementToFocusOnShow: true,
|
|
1824
1711
|
});
|
|
1825
|
-
const contentNode = /** @type {HTMLElement} */
|
|
1826
|
-
ctrl.updateConfig({
|
|
1712
|
+
const contentNode = /** @type {HTMLElement} */ await fixture('<div>Content</div>');
|
|
1713
|
+
ctrl.updateConfig({
|
|
1714
|
+
contentNode,
|
|
1715
|
+
});
|
|
1827
1716
|
await ctrl.show();
|
|
1828
1717
|
expect(contentNode.getAttribute('tabindex')).to.equal('-1');
|
|
1829
1718
|
});
|
|
1830
|
-
|
|
1831
1719
|
it('makes contentNode the root of "next tab flow"', async () => {
|
|
1832
1720
|
const ctrl = new OverlayController({
|
|
1833
1721
|
...withGlobalTestConfig(),
|
|
1834
1722
|
isBlocking: false,
|
|
1835
1723
|
elementToFocusOnShow: true,
|
|
1836
1724
|
});
|
|
1837
|
-
const contentNode =
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
ctrl.updateConfig({
|
|
1725
|
+
const contentNode =
|
|
1726
|
+
/** @type {HTMLElement} */
|
|
1727
|
+
await fixture('<div><button>Button</button></div>');
|
|
1728
|
+
ctrl.updateConfig({
|
|
1729
|
+
contentNode,
|
|
1730
|
+
});
|
|
1841
1731
|
await ctrl.show();
|
|
1842
|
-
const button = /** @type {HTMLButtonElement} */
|
|
1732
|
+
const button = /** @type {HTMLButtonElement} */ contentNode.querySelector('button');
|
|
1843
1733
|
button.focus();
|
|
1844
1734
|
expect(isActiveElement(button)).to.be.true;
|
|
1845
1735
|
});
|
|
1846
1736
|
});
|
|
1847
|
-
|
|
1848
1737
|
describe('syncChildrenCloseState', () => {
|
|
1849
1738
|
it('does not close all children of nested controllers when syncChildrenCloseState is false', async () => {
|
|
1850
|
-
const parentContent =
|
|
1739
|
+
const parentContent =
|
|
1740
|
+
/** @type {HTMLDivElement} */
|
|
1851
1741
|
await fixture(
|
|
1852
1742
|
html` <!-- -->
|
|
1853
1743
|
<div data-sync-children-close-state id="parent-overlay">
|
|
1854
1744
|
<div id="child-overlay">we open our child and it will close when parent does</div>
|
|
1855
1745
|
</div>`,
|
|
1856
|
-
)
|
|
1857
|
-
);
|
|
1746
|
+
);
|
|
1858
1747
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
1859
1748
|
expect(parentOverlay.isShown).to.be.true;
|
|
1860
1749
|
expect(childOverlay.isShown).to.be.true;
|
|
1861
|
-
|
|
1862
1750
|
await parentOverlay.hide();
|
|
1863
1751
|
await childOverlay._hideComplete;
|
|
1864
1752
|
expect(parentOverlay.isShown).to.be.false;
|
|
1865
1753
|
expect(childOverlay.isShown).to.be.false;
|
|
1866
1754
|
});
|
|
1867
|
-
|
|
1868
1755
|
it('does not close all children of nested controllers when syncChildrenCloseState is false', async () => {
|
|
1869
|
-
const parentContent =
|
|
1756
|
+
const parentContent =
|
|
1757
|
+
/** @type {HTMLDivElement} */
|
|
1870
1758
|
await fixture(
|
|
1871
1759
|
html` <!-- -->
|
|
1872
1760
|
<div id="parent-overlay">
|
|
@@ -1874,18 +1762,15 @@ describe('OverlayController', () => {
|
|
|
1874
1762
|
we open our child and it will not close when parent does
|
|
1875
1763
|
</div>
|
|
1876
1764
|
</div>`,
|
|
1877
|
-
)
|
|
1878
|
-
);
|
|
1765
|
+
);
|
|
1879
1766
|
const { parentOverlay, childOverlay } = await createNestedEscControllers(parentContent);
|
|
1880
1767
|
expect(parentOverlay.isShown).to.be.true;
|
|
1881
1768
|
expect(childOverlay.isShown).to.be.true;
|
|
1882
|
-
|
|
1883
1769
|
await parentOverlay.hide();
|
|
1884
1770
|
expect(parentOverlay.isShown).to.be.false;
|
|
1885
1771
|
expect(childOverlay.isShown).to.be.true;
|
|
1886
1772
|
});
|
|
1887
1773
|
});
|
|
1888
|
-
|
|
1889
1774
|
describe('isActivated', () => {
|
|
1890
1775
|
it('allows to conditionally disable overlay/openable functionality (for responsive context like nav menus, accordions/collapsibles vs plain headings/content etc.)', async () => {
|
|
1891
1776
|
const ctrl = new OverlayController({
|
|
@@ -1906,7 +1791,6 @@ describe('OverlayController', () => {
|
|
|
1906
1791
|
// TODO
|
|
1907
1792
|
describe('requireConnectedNodes', () => {});
|
|
1908
1793
|
});
|
|
1909
|
-
|
|
1910
1794
|
describe('Show / Hide / Toggle', () => {
|
|
1911
1795
|
it('has .isShown which defaults to false', async () => {
|
|
1912
1796
|
const ctrl = new OverlayController({
|
|
@@ -1914,7 +1798,6 @@ describe('OverlayController', () => {
|
|
|
1914
1798
|
});
|
|
1915
1799
|
expect(ctrl.isShown).to.be.false;
|
|
1916
1800
|
});
|
|
1917
|
-
|
|
1918
1801
|
it('has async show() which shows the overlay', async () => {
|
|
1919
1802
|
const ctrl = new OverlayController({
|
|
1920
1803
|
...withGlobalTestConfig(),
|
|
@@ -1923,55 +1806,44 @@ describe('OverlayController', () => {
|
|
|
1923
1806
|
expect(ctrl.isShown).to.be.true;
|
|
1924
1807
|
expect(ctrl.show()).to.be.instanceOf(Promise);
|
|
1925
1808
|
});
|
|
1926
|
-
|
|
1927
1809
|
it('has async hide() which hides the overlay', async () => {
|
|
1928
1810
|
const ctrl = new OverlayController({
|
|
1929
1811
|
...withGlobalTestConfig(),
|
|
1930
1812
|
});
|
|
1931
|
-
|
|
1932
1813
|
await ctrl.hide();
|
|
1933
1814
|
expect(ctrl.isShown).to.be.false;
|
|
1934
1815
|
expect(ctrl.hide()).to.be.instanceOf(Promise);
|
|
1935
1816
|
});
|
|
1936
|
-
|
|
1937
1817
|
it('fires "show" event once overlay becomes shown', async () => {
|
|
1938
1818
|
const showSpy = sinon.spy();
|
|
1939
1819
|
const ctrl = new OverlayController({
|
|
1940
1820
|
...withGlobalTestConfig(),
|
|
1941
1821
|
});
|
|
1942
|
-
|
|
1943
1822
|
ctrl.addEventListener('show', showSpy);
|
|
1944
1823
|
await ctrl.show();
|
|
1945
1824
|
expect(showSpy.callCount).to.equal(1);
|
|
1946
1825
|
await ctrl.show();
|
|
1947
1826
|
expect(showSpy.callCount).to.equal(1);
|
|
1948
1827
|
});
|
|
1949
|
-
|
|
1950
1828
|
it('fires "before-show" event right before overlay becomes shown', async () => {
|
|
1951
1829
|
const ctrl = new OverlayController({
|
|
1952
1830
|
...withGlobalTestConfig(),
|
|
1953
1831
|
});
|
|
1954
|
-
|
|
1955
1832
|
const eventSpy = sinon.spy();
|
|
1956
|
-
|
|
1957
1833
|
ctrl.addEventListener('before-show', eventSpy);
|
|
1958
1834
|
ctrl.addEventListener('show', eventSpy);
|
|
1959
|
-
|
|
1960
1835
|
await ctrl.show();
|
|
1961
1836
|
expect(eventSpy.getCall(0).args[0].type).to.equal('before-show');
|
|
1962
1837
|
expect(eventSpy.getCall(1).args[0].type).to.equal('show');
|
|
1963
|
-
|
|
1964
1838
|
expect(eventSpy.callCount).to.equal(2);
|
|
1965
1839
|
await ctrl.show();
|
|
1966
1840
|
expect(eventSpy.callCount).to.equal(2);
|
|
1967
1841
|
});
|
|
1968
|
-
|
|
1969
1842
|
it('fires "hide" event once overlay becomes hidden', async () => {
|
|
1970
1843
|
const hideSpy = sinon.spy();
|
|
1971
1844
|
const ctrl = new OverlayController({
|
|
1972
1845
|
...withGlobalTestConfig(),
|
|
1973
1846
|
});
|
|
1974
|
-
|
|
1975
1847
|
ctrl.addEventListener('hide', hideSpy);
|
|
1976
1848
|
await ctrl.show();
|
|
1977
1849
|
await ctrl.hide();
|
|
@@ -1979,38 +1851,29 @@ describe('OverlayController', () => {
|
|
|
1979
1851
|
await ctrl.hide();
|
|
1980
1852
|
expect(hideSpy.callCount).to.equal(1);
|
|
1981
1853
|
});
|
|
1982
|
-
|
|
1983
1854
|
it('fires "before-hide" event right before overlay becomes hidden', async () => {
|
|
1984
1855
|
const ctrl = new OverlayController({
|
|
1985
1856
|
...withGlobalTestConfig(),
|
|
1986
1857
|
});
|
|
1987
|
-
|
|
1988
1858
|
const eventSpy = sinon.spy();
|
|
1989
|
-
|
|
1990
1859
|
ctrl.addEventListener('before-hide', eventSpy);
|
|
1991
1860
|
ctrl.addEventListener('hide', eventSpy);
|
|
1992
|
-
|
|
1993
1861
|
await ctrl.show();
|
|
1994
1862
|
await ctrl.hide();
|
|
1995
1863
|
expect(eventSpy.getCall(0).args[0].type).to.equal('before-hide');
|
|
1996
1864
|
expect(eventSpy.getCall(1).args[0].type).to.equal('hide');
|
|
1997
|
-
|
|
1998
1865
|
expect(eventSpy.callCount).to.equal(2);
|
|
1999
1866
|
await ctrl.hide();
|
|
2000
1867
|
expect(eventSpy.callCount).to.equal(2);
|
|
2001
1868
|
});
|
|
2002
|
-
|
|
2003
1869
|
it('can be toggled', async () => {
|
|
2004
1870
|
const ctrl = new OverlayController({
|
|
2005
1871
|
...withGlobalTestConfig(),
|
|
2006
1872
|
});
|
|
2007
|
-
|
|
2008
1873
|
await ctrl.toggle();
|
|
2009
1874
|
expect(ctrl.isShown).to.be.true;
|
|
2010
|
-
|
|
2011
1875
|
await ctrl.toggle();
|
|
2012
1876
|
expect(ctrl.isShown).to.be.false;
|
|
2013
|
-
|
|
2014
1877
|
await ctrl.toggle();
|
|
2015
1878
|
expect(ctrl.isShown).to.be.true;
|
|
2016
1879
|
|
|
@@ -2019,7 +1882,6 @@ describe('OverlayController', () => {
|
|
|
2019
1882
|
// check for show
|
|
2020
1883
|
expect(ctrl.toggle()).to.be.instanceOf(Promise);
|
|
2021
1884
|
});
|
|
2022
|
-
|
|
2023
1885
|
it('makes sure the latest shown overlay is visible', async () => {
|
|
2024
1886
|
const ctrl0 = new OverlayController({
|
|
2025
1887
|
...withGlobalTestConfig(),
|
|
@@ -2030,18 +1892,14 @@ describe('OverlayController', () => {
|
|
|
2030
1892
|
await ctrl0.show();
|
|
2031
1893
|
const rect = ctrl0.contentNode.getBoundingClientRect();
|
|
2032
1894
|
const getTopEl = () => document.elementFromPoint(Math.ceil(rect.left), Math.ceil(rect.top));
|
|
2033
|
-
|
|
2034
1895
|
await ctrl0.show();
|
|
2035
1896
|
expect(getTopEl()).to.equal(ctrl0.contentNode);
|
|
2036
|
-
|
|
2037
1897
|
await ctrl1.show();
|
|
2038
1898
|
expect(getTopEl()).to.equal(ctrl1.contentNode);
|
|
2039
|
-
|
|
2040
1899
|
await ctrl0.show();
|
|
2041
1900
|
expect(getTopEl()).to.equal(ctrl0.contentNode);
|
|
2042
1901
|
});
|
|
2043
|
-
|
|
2044
|
-
it('awaits a "transitionHide" hook before hiding for real', done => {
|
|
1902
|
+
it('awaits a "transitionHide" hook before hiding for real', (done) => {
|
|
2045
1903
|
const ctrl = new OverlayController({
|
|
2046
1904
|
...withGlobalTestConfig(),
|
|
2047
1905
|
});
|
|
@@ -2050,12 +1908,10 @@ describe('OverlayController', () => {
|
|
|
2050
1908
|
/** @type {{ (): void; (value?: void | PromiseLike<void> | undefined): void; }} */
|
|
2051
1909
|
let hideTransitionFinished;
|
|
2052
1910
|
ctrl.transitionHide = () =>
|
|
2053
|
-
new Promise(resolve => {
|
|
1911
|
+
new Promise((resolve) => {
|
|
2054
1912
|
hideTransitionFinished = resolve;
|
|
2055
1913
|
});
|
|
2056
|
-
|
|
2057
1914
|
ctrl.hide();
|
|
2058
|
-
|
|
2059
1915
|
expect(getComputedStyle(ctrl.content).display).to.equal('block');
|
|
2060
1916
|
setTimeout(() => {
|
|
2061
1917
|
hideTransitionFinished();
|
|
@@ -2065,8 +1921,7 @@ describe('OverlayController', () => {
|
|
|
2065
1921
|
}, 0);
|
|
2066
1922
|
}, 0);
|
|
2067
1923
|
});
|
|
2068
|
-
|
|
2069
|
-
it('awaits a "transitionShow" hook before finishing the show method', done => {
|
|
1924
|
+
it('awaits a "transitionShow" hook before finishing the show method', (done) => {
|
|
2070
1925
|
const ctrl = new OverlayController({
|
|
2071
1926
|
...withGlobalTestConfig(),
|
|
2072
1927
|
});
|
|
@@ -2074,17 +1929,16 @@ describe('OverlayController', () => {
|
|
|
2074
1929
|
/** @type {{ (): void; (value?: void | PromiseLike<void> | undefined): void; }} */
|
|
2075
1930
|
let showTransitionFinished;
|
|
2076
1931
|
ctrl.transitionShow = () =>
|
|
2077
|
-
new Promise(resolve => {
|
|
1932
|
+
new Promise((resolve) => {
|
|
2078
1933
|
showTransitionFinished = resolve;
|
|
2079
1934
|
});
|
|
2080
1935
|
ctrl.show();
|
|
2081
|
-
|
|
2082
1936
|
let showIsDone = false;
|
|
2083
1937
|
|
|
2084
|
-
/** @type {Promise<void>} */
|
|
1938
|
+
/** @type {Promise<void>} */
|
|
1939
|
+
ctrl._showComplete.then(() => {
|
|
2085
1940
|
showIsDone = true;
|
|
2086
1941
|
});
|
|
2087
|
-
|
|
2088
1942
|
expect(showIsDone).to.be.false;
|
|
2089
1943
|
setTimeout(() => {
|
|
2090
1944
|
showTransitionFinished();
|
|
@@ -2095,27 +1949,23 @@ describe('OverlayController', () => {
|
|
|
2095
1949
|
}, 0);
|
|
2096
1950
|
});
|
|
2097
1951
|
});
|
|
2098
|
-
|
|
2099
1952
|
describe('Update Configuration', () => {
|
|
2100
1953
|
it('reinitializes content', async () => {
|
|
2101
1954
|
const ctrl = new OverlayController({
|
|
2102
1955
|
...withLocalTestConfig(),
|
|
2103
|
-
contentNode: /** @type {HTMLElement} */
|
|
1956
|
+
contentNode: /** @type {HTMLElement} */ await fixture(html`<div>content1</div>`),
|
|
2104
1957
|
});
|
|
2105
1958
|
await ctrl.show(); // Popper adds inline styles
|
|
2106
1959
|
expect(ctrl.content.style.transform).not.to.be.undefined;
|
|
2107
1960
|
expect(ctrl.contentNode.textContent).to.include('content1');
|
|
2108
|
-
|
|
2109
1961
|
ctrl.updateConfig({
|
|
2110
1962
|
placementMode: 'local',
|
|
2111
|
-
contentNode: /** @type {HTMLElement} */
|
|
1963
|
+
contentNode: /** @type {HTMLElement} */ await fixture(html`<div>content2</div>`),
|
|
2112
1964
|
});
|
|
2113
1965
|
expect(ctrl.contentNode.textContent).to.include('content2');
|
|
2114
1966
|
});
|
|
2115
|
-
|
|
2116
1967
|
it('respects the initial config provided to new OverlayController(initialConfig)', async () => {
|
|
2117
|
-
const contentNode = /** @type {HTMLElement} */
|
|
2118
|
-
|
|
1968
|
+
const contentNode = /** @type {HTMLElement} */ fixtureSync(html`<div>my content</div>`);
|
|
2119
1969
|
const ctrl = new OverlayController({
|
|
2120
1970
|
// This is the shared config
|
|
2121
1971
|
placementMode: 'global',
|
|
@@ -2134,46 +1984,44 @@ describe('OverlayController', () => {
|
|
|
2134
1984
|
|
|
2135
1985
|
// Currently not working, enable again when we fix updateConfig
|
|
2136
1986
|
it.skip('allows for updating viewport config placement only, while keeping the content shown', async () => {
|
|
2137
|
-
const contentNode = /** @type {HTMLElement} */
|
|
2138
|
-
|
|
1987
|
+
const contentNode = /** @type {HTMLElement} */ fixtureSync(html`<div>my content</div>`);
|
|
2139
1988
|
const ctrl = new OverlayController({
|
|
2140
1989
|
// This is the shared config
|
|
2141
1990
|
placementMode: 'global',
|
|
2142
1991
|
handlesAccessibility: true,
|
|
2143
1992
|
contentNode,
|
|
2144
1993
|
});
|
|
2145
|
-
|
|
2146
1994
|
ctrl.show();
|
|
2147
1995
|
expect(ctrl.contentWrapperNode.classList.contains('overlays__overlay-container--center'));
|
|
2148
1996
|
expect(ctrl.isShown).to.be.true;
|
|
2149
|
-
|
|
2150
|
-
|
|
1997
|
+
ctrl.updateConfig({
|
|
1998
|
+
viewportConfig: {
|
|
1999
|
+
placement: 'top-right',
|
|
2000
|
+
},
|
|
2001
|
+
});
|
|
2151
2002
|
expect(ctrl.contentWrapperNode.classList.contains('overlays__overlay-container--top-right'));
|
|
2152
2003
|
expect(ctrl.isShown).to.be.true;
|
|
2153
2004
|
});
|
|
2154
|
-
|
|
2155
2005
|
it('disables backdrop when switching to hasBackrop "false"', async () => {
|
|
2156
2006
|
const ctrl = new OverlayController({
|
|
2157
2007
|
...withLocalTestConfig(),
|
|
2158
|
-
contentNode: /** @type {HTMLElement} */
|
|
2008
|
+
contentNode: /** @type {HTMLElement} */ await fixture(html`<div>content1</div>`),
|
|
2159
2009
|
hasBackdrop: true,
|
|
2160
2010
|
});
|
|
2161
2011
|
await ctrl.show(); // Popper adds inline styles
|
|
2162
2012
|
expect(ctrl.backdropNode).not.to.be.undefined;
|
|
2163
2013
|
expect(Array.from(ctrl.backdropNode.classList)).to.include('overlays__backdrop--visible');
|
|
2164
|
-
|
|
2165
2014
|
ctrl.updateConfig({
|
|
2166
2015
|
hasBackdrop: false,
|
|
2167
2016
|
});
|
|
2168
2017
|
expect(Array.from(ctrl.backdropNode.classList)).to.not.include('overlays__backdrop--visible');
|
|
2169
2018
|
});
|
|
2170
2019
|
});
|
|
2171
|
-
|
|
2172
2020
|
describe('Accessibility', () => {
|
|
2173
2021
|
it('synchronizes [aria-expanded] on invoker', async () => {
|
|
2174
|
-
const invokerNode =
|
|
2175
|
-
|
|
2176
|
-
|
|
2022
|
+
const invokerNode =
|
|
2023
|
+
/** @type {HTMLElement} */
|
|
2024
|
+
await fixture('<div role="button">invoker</div>');
|
|
2177
2025
|
const ctrl = new OverlayController({
|
|
2178
2026
|
...withLocalTestConfig(),
|
|
2179
2027
|
handlesAccessibility: true,
|
|
@@ -2185,11 +2033,10 @@ describe('OverlayController', () => {
|
|
|
2185
2033
|
await ctrl.hide();
|
|
2186
2034
|
expect(ctrl.invokerNode?.getAttribute('aria-expanded')).to.equal('false');
|
|
2187
2035
|
});
|
|
2188
|
-
|
|
2189
2036
|
it('does not synchronize [aria-expanded] on invoker when the overlay is modal', async () => {
|
|
2190
|
-
const invokerNode =
|
|
2191
|
-
|
|
2192
|
-
|
|
2037
|
+
const invokerNode =
|
|
2038
|
+
/** @type {HTMLElement} */
|
|
2039
|
+
await fixture('<div role="button">invoker</div>');
|
|
2193
2040
|
const ctrl = new OverlayController({
|
|
2194
2041
|
...withLocalTestConfig(),
|
|
2195
2042
|
trapsKeyboardFocus: true,
|
|
@@ -2202,7 +2049,6 @@ describe('OverlayController', () => {
|
|
|
2202
2049
|
await ctrl.hide();
|
|
2203
2050
|
expect(ctrl.invokerNode?.getAttribute('aria-expanded')).to.equal(null);
|
|
2204
2051
|
});
|
|
2205
|
-
|
|
2206
2052
|
it('creates unique id for content', async () => {
|
|
2207
2053
|
const ctrl = new OverlayController({
|
|
2208
2054
|
...withLocalTestConfig(),
|
|
@@ -2211,11 +2057,10 @@ describe('OverlayController', () => {
|
|
|
2211
2057
|
const { contentId } = getProtectedMembers(ctrl);
|
|
2212
2058
|
expect(ctrl.contentNode.id).to.contain(contentId);
|
|
2213
2059
|
});
|
|
2214
|
-
|
|
2215
2060
|
it('preserves content id when present', async () => {
|
|
2216
|
-
const contentNode =
|
|
2217
|
-
|
|
2218
|
-
|
|
2061
|
+
const contentNode =
|
|
2062
|
+
/** @type {HTMLElement} */
|
|
2063
|
+
await fixture('<div id="preserved">content</div>');
|
|
2219
2064
|
const ctrl = new OverlayController({
|
|
2220
2065
|
...withLocalTestConfig(),
|
|
2221
2066
|
handlesAccessibility: true,
|
|
@@ -2223,11 +2068,10 @@ describe('OverlayController', () => {
|
|
|
2223
2068
|
});
|
|
2224
2069
|
expect(ctrl.contentNode.id).to.contain('preserved');
|
|
2225
2070
|
});
|
|
2226
|
-
|
|
2227
2071
|
it('adds [role=dialog] on content', async () => {
|
|
2228
|
-
const invokerNode =
|
|
2229
|
-
|
|
2230
|
-
|
|
2072
|
+
const invokerNode =
|
|
2073
|
+
/** @type {HTMLElement} */
|
|
2074
|
+
await fixture('<div role="button">invoker</div>');
|
|
2231
2075
|
const ctrl = new OverlayController({
|
|
2232
2076
|
...withLocalTestConfig(),
|
|
2233
2077
|
handlesAccessibility: true,
|
|
@@ -2235,14 +2079,13 @@ describe('OverlayController', () => {
|
|
|
2235
2079
|
});
|
|
2236
2080
|
expect(ctrl.contentNode.getAttribute('role')).to.equal('dialog');
|
|
2237
2081
|
});
|
|
2238
|
-
|
|
2239
2082
|
it('preserves [role] on content when present', async () => {
|
|
2240
|
-
const invokerNode =
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
const contentNode =
|
|
2244
|
-
|
|
2245
|
-
|
|
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>');
|
|
2246
2089
|
const ctrl = new OverlayController({
|
|
2247
2090
|
...withLocalTestConfig(),
|
|
2248
2091
|
handlesAccessibility: true,
|
|
@@ -2251,7 +2094,6 @@ describe('OverlayController', () => {
|
|
|
2251
2094
|
});
|
|
2252
2095
|
expect(ctrl.contentNode.getAttribute('role')).to.equal('menu');
|
|
2253
2096
|
});
|
|
2254
|
-
|
|
2255
2097
|
it('allows to not provide an invokerNode', async () => {
|
|
2256
2098
|
let properlyInstantiated = false;
|
|
2257
2099
|
try {
|
|
@@ -2262,7 +2104,7 @@ describe('OverlayController', () => {
|
|
|
2262
2104
|
});
|
|
2263
2105
|
properlyInstantiated = true;
|
|
2264
2106
|
} catch (e) {
|
|
2265
|
-
throw new Error(/** @type {Error} */
|
|
2107
|
+
throw new Error(/** @type {Error} */ e.message);
|
|
2266
2108
|
}
|
|
2267
2109
|
expect(properlyInstantiated).to.be.true;
|
|
2268
2110
|
});
|
|
@@ -2270,28 +2112,25 @@ describe('OverlayController', () => {
|
|
|
2270
2112
|
// TODO: check if we covered all functionality. "Inertness" should be handled by the platform with a modal overlay...
|
|
2271
2113
|
it.skip('adds attributes inert and aria-hidden="true" on all siblings of rootNode if an overlay is shown', async () => {});
|
|
2272
2114
|
it.skip('disables pointer events and selection on inert elements', async () => {});
|
|
2273
|
-
|
|
2274
2115
|
describe('Alert dialog', () => {
|
|
2275
2116
|
it('sets role="alertdialog" when isAlertDialog is set', async () => {
|
|
2276
|
-
const invokerNode =
|
|
2277
|
-
|
|
2278
|
-
|
|
2117
|
+
const invokerNode =
|
|
2118
|
+
/** @type {HTMLElement} */
|
|
2119
|
+
await fixture('<div role="button">invoker</div>');
|
|
2279
2120
|
const ctrl = new OverlayController({
|
|
2280
2121
|
...withLocalTestConfig(),
|
|
2281
2122
|
handlesAccessibility: true,
|
|
2282
2123
|
isAlertDialog: true,
|
|
2283
2124
|
invokerNode,
|
|
2284
2125
|
});
|
|
2285
|
-
|
|
2286
2126
|
expect(ctrl.contentNode?.getAttribute('role')).to.equal('alertdialog');
|
|
2287
2127
|
});
|
|
2288
2128
|
});
|
|
2289
|
-
|
|
2290
2129
|
describe('Tooltip', () => {
|
|
2291
2130
|
it('adds [aria-describedby] on invoker', async () => {
|
|
2292
|
-
const invokerNode =
|
|
2293
|
-
|
|
2294
|
-
|
|
2131
|
+
const invokerNode =
|
|
2132
|
+
/** @type {HTMLElement} */
|
|
2133
|
+
await fixture('<div role="button">invoker</div>');
|
|
2295
2134
|
const ctrl = new OverlayController({
|
|
2296
2135
|
...withLocalTestConfig(),
|
|
2297
2136
|
handlesAccessibility: true,
|
|
@@ -2299,14 +2138,12 @@ describe('OverlayController', () => {
|
|
|
2299
2138
|
invokerNode,
|
|
2300
2139
|
});
|
|
2301
2140
|
const { contentId } = getProtectedMembers(ctrl);
|
|
2302
|
-
|
|
2303
2141
|
expect(ctrl.invokerNode?.getAttribute('aria-describedby')).to.equal(contentId);
|
|
2304
2142
|
});
|
|
2305
|
-
|
|
2306
2143
|
it('adds [aria-labelledby] on invoker when invokerRelation is label', async () => {
|
|
2307
|
-
const invokerNode =
|
|
2308
|
-
|
|
2309
|
-
|
|
2144
|
+
const invokerNode =
|
|
2145
|
+
/** @type {HTMLElement} */
|
|
2146
|
+
await fixture('<div role="button">invoker</div>');
|
|
2310
2147
|
const ctrl = new OverlayController({
|
|
2311
2148
|
...withLocalTestConfig(),
|
|
2312
2149
|
handlesAccessibility: true,
|
|
@@ -2315,15 +2152,13 @@ describe('OverlayController', () => {
|
|
|
2315
2152
|
invokerNode,
|
|
2316
2153
|
});
|
|
2317
2154
|
const { contentId } = getProtectedMembers(ctrl);
|
|
2318
|
-
|
|
2319
2155
|
expect(ctrl.invokerNode?.getAttribute('aria-describedby')).to.equal(null);
|
|
2320
2156
|
expect(ctrl.invokerNode?.getAttribute('aria-labelledby')).to.equal(contentId);
|
|
2321
2157
|
});
|
|
2322
|
-
|
|
2323
2158
|
it('adds [role=tooltip] on content', async () => {
|
|
2324
|
-
const invokerNode =
|
|
2325
|
-
|
|
2326
|
-
|
|
2159
|
+
const invokerNode =
|
|
2160
|
+
/** @type {HTMLElement} */
|
|
2161
|
+
await fixture('<div role="button">invoker</div>');
|
|
2327
2162
|
const ctrl = new OverlayController({
|
|
2328
2163
|
...withLocalTestConfig(),
|
|
2329
2164
|
handlesAccessibility: true,
|
|
@@ -2332,11 +2167,10 @@ describe('OverlayController', () => {
|
|
|
2332
2167
|
});
|
|
2333
2168
|
expect(ctrl.contentNode.getAttribute('role')).to.equal('tooltip');
|
|
2334
2169
|
});
|
|
2335
|
-
|
|
2336
2170
|
it('adds tabindex="-1" to the wrappingDialog element', async () => {
|
|
2337
|
-
const invokerNode =
|
|
2338
|
-
|
|
2339
|
-
|
|
2171
|
+
const invokerNode =
|
|
2172
|
+
/** @type {HTMLElement} */
|
|
2173
|
+
await fixture('<div role="button">invoker</div>');
|
|
2340
2174
|
const ctrl = new OverlayController({
|
|
2341
2175
|
...withLocalTestConfig(),
|
|
2342
2176
|
handlesAccessibility: true,
|
|
@@ -2345,12 +2179,11 @@ describe('OverlayController', () => {
|
|
|
2345
2179
|
});
|
|
2346
2180
|
expect(ctrl.__wrappingDialogNode?.getAttribute('tabindex')).to.equal('-1');
|
|
2347
2181
|
});
|
|
2348
|
-
|
|
2349
2182
|
describe('Teardown', () => {
|
|
2350
2183
|
it('restores [role] on dialog content', async () => {
|
|
2351
|
-
const invokerNode =
|
|
2352
|
-
|
|
2353
|
-
|
|
2184
|
+
const invokerNode =
|
|
2185
|
+
/** @type {HTMLElement} */
|
|
2186
|
+
await fixture('<div role="button">invoker</div>');
|
|
2354
2187
|
const ctrl = new OverlayController({
|
|
2355
2188
|
...withLocalTestConfig(),
|
|
2356
2189
|
handlesAccessibility: true,
|
|
@@ -2360,14 +2193,13 @@ describe('OverlayController', () => {
|
|
|
2360
2193
|
ctrl.teardown();
|
|
2361
2194
|
expect(ctrl.contentNode.getAttribute('role')).to.equal(null);
|
|
2362
2195
|
});
|
|
2363
|
-
|
|
2364
2196
|
it('restores [role] on tooltip content', async () => {
|
|
2365
|
-
const invokerNode =
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
const contentNode =
|
|
2369
|
-
|
|
2370
|
-
|
|
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>');
|
|
2371
2203
|
const ctrl = new OverlayController({
|
|
2372
2204
|
...withLocalTestConfig(),
|
|
2373
2205
|
handlesAccessibility: true,
|
|
@@ -2379,14 +2211,13 @@ describe('OverlayController', () => {
|
|
|
2379
2211
|
ctrl.teardown();
|
|
2380
2212
|
expect(contentNode.getAttribute('role')).to.equal('presentation');
|
|
2381
2213
|
});
|
|
2382
|
-
|
|
2383
2214
|
it('restores [aria-describedby] on content', async () => {
|
|
2384
|
-
const invokerNode =
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
const contentNode =
|
|
2388
|
-
|
|
2389
|
-
|
|
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>');
|
|
2390
2221
|
const ctrl = new OverlayController({
|
|
2391
2222
|
...withLocalTestConfig(),
|
|
2392
2223
|
handlesAccessibility: true,
|
|
@@ -2398,14 +2229,13 @@ describe('OverlayController', () => {
|
|
|
2398
2229
|
ctrl.teardown();
|
|
2399
2230
|
expect(invokerNode.getAttribute('aria-describedby')).to.equal(null);
|
|
2400
2231
|
});
|
|
2401
|
-
|
|
2402
2232
|
it('restores [aria-labelledby] on content', async () => {
|
|
2403
|
-
const invokerNode =
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
const contentNode =
|
|
2407
|
-
|
|
2408
|
-
|
|
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>');
|
|
2409
2239
|
const ctrl = new OverlayController({
|
|
2410
2240
|
...withLocalTestConfig(),
|
|
2411
2241
|
handlesAccessibility: true,
|
|
@@ -2421,7 +2251,6 @@ describe('OverlayController', () => {
|
|
|
2421
2251
|
});
|
|
2422
2252
|
});
|
|
2423
2253
|
});
|
|
2424
|
-
|
|
2425
2254
|
describe('Exception handling', () => {
|
|
2426
2255
|
it('throws if no .placementMode gets passed on', async () => {
|
|
2427
2256
|
const contentNode = document.createElement('div');
|
|
@@ -2433,7 +2262,6 @@ describe('OverlayController', () => {
|
|
|
2433
2262
|
});
|
|
2434
2263
|
}).to.throw('[OverlayController] You need to provide a .placementMode ("global"|"local")');
|
|
2435
2264
|
});
|
|
2436
|
-
|
|
2437
2265
|
it('throws if invalid .placementMode gets passed on', async () => {
|
|
2438
2266
|
expect(() => {
|
|
2439
2267
|
new OverlayController({
|
|
@@ -2444,7 +2272,6 @@ describe('OverlayController', () => {
|
|
|
2444
2272
|
'[OverlayController] "invalid" is not a valid .placementMode, use ("global"|"local")',
|
|
2445
2273
|
);
|
|
2446
2274
|
});
|
|
2447
|
-
|
|
2448
2275
|
it('throws if no .contentNode gets passed on', async () => {
|
|
2449
2276
|
expect(() => {
|
|
2450
2277
|
new OverlayController({
|
|
@@ -2452,7 +2279,6 @@ describe('OverlayController', () => {
|
|
|
2452
2279
|
});
|
|
2453
2280
|
}).to.throw('[OverlayController] You need to provide a .contentNode');
|
|
2454
2281
|
});
|
|
2455
|
-
|
|
2456
2282
|
it('throws if handlesAccessibility is false for a tooltip', async () => {
|
|
2457
2283
|
const contentNode = document.createElement('div');
|
|
2458
2284
|
document.body.appendChild(contentNode);
|
|
@@ -2468,7 +2294,6 @@ describe('OverlayController', () => {
|
|
|
2468
2294
|
);
|
|
2469
2295
|
});
|
|
2470
2296
|
});
|
|
2471
|
-
|
|
2472
2297
|
describe('run _keepBodySize only with scroll prevention', () => {
|
|
2473
2298
|
/**
|
|
2474
2299
|
* @type {OverlayController}
|
|
@@ -2477,15 +2302,12 @@ describe('OverlayController', () => {
|
|
|
2477
2302
|
...withLocalTestConfig(),
|
|
2478
2303
|
preventsScroll: false,
|
|
2479
2304
|
});
|
|
2480
|
-
|
|
2481
2305
|
const overlayControllerPreventsScroll = new OverlayController({
|
|
2482
2306
|
...withLocalTestConfig(),
|
|
2483
2307
|
preventsScroll: true,
|
|
2484
2308
|
});
|
|
2485
|
-
|
|
2486
2309
|
it('should not run with scroll prevention', async () => {
|
|
2487
2310
|
await overlayControllerNoPrevent.show();
|
|
2488
|
-
|
|
2489
2311
|
expect(
|
|
2490
2312
|
overlayControllerNoPrevent.manager.__forTesting.bodySizeVars.marginRightInline,
|
|
2491
2313
|
).to.equal(undefined);
|
|
@@ -2493,11 +2315,9 @@ describe('OverlayController', () => {
|
|
|
2493
2315
|
undefined,
|
|
2494
2316
|
);
|
|
2495
2317
|
});
|
|
2496
|
-
|
|
2497
2318
|
it('should run with scroll prevention', async () => {
|
|
2498
2319
|
await overlayControllerPreventsScroll.hide();
|
|
2499
2320
|
await overlayControllerPreventsScroll.show();
|
|
2500
|
-
|
|
2501
2321
|
expect(
|
|
2502
2322
|
overlayControllerPreventsScroll.manager.__forTesting.bodySizeVars.marginRightInline,
|
|
2503
2323
|
).to.not.equal(undefined);
|