igniteui-webcomponents 7.3.1 → 7.4.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/CHANGELOG.md +72 -1
- package/animations/easings.d.ts +21 -31
- package/animations/easings.js +21 -34
- package/animations/easings.js.map +1 -1
- package/animations/player.d.ts +8 -16
- package/animations/player.js +5 -8
- package/animations/player.js.map +1 -1
- package/animations/view-transition.d.ts +10 -10
- package/animations/view-transition.js +26 -37
- package/animations/view-transition.js.map +1 -1
- package/components/avatar/themes/avatar.base.css.js +1 -1
- package/components/avatar/themes/avatar.base.css.js.map +1 -1
- package/components/badge/themes/badge.base.css.js +1 -1
- package/components/badge/themes/badge.base.css.js.map +1 -1
- package/components/banner/themes/banner.base.css.js +1 -1
- package/components/banner/themes/banner.base.css.js.map +1 -1
- package/components/banner/themes/shared/banner.indigo.css.js +1 -1
- package/components/banner/themes/shared/banner.indigo.css.js.map +1 -1
- package/components/breadcrumb/breadcrumb.d.ts +74 -0
- package/components/breadcrumb/breadcrumb.js +107 -0
- package/components/breadcrumb/breadcrumb.js.map +1 -0
- package/components/breadcrumb/breadcrumbs.d.ts +60 -0
- package/components/breadcrumb/breadcrumbs.js +50 -0
- package/components/breadcrumb/breadcrumbs.js.map +1 -0
- package/components/breadcrumb/themes/breadcrumb.base.css.d.ts +1 -0
- package/components/breadcrumb/themes/breadcrumb.base.css.js +3 -0
- package/components/breadcrumb/themes/breadcrumb.base.css.js.map +1 -0
- package/components/breadcrumb/themes/breadcrumbs.base.css.d.ts +1 -0
- package/components/breadcrumb/themes/breadcrumbs.base.css.js +3 -0
- package/components/breadcrumb/themes/breadcrumbs.base.css.js.map +1 -0
- package/components/breadcrumb/themes/dark/breadcrumb.bootstrap.css.d.ts +1 -0
- package/components/breadcrumb/themes/dark/breadcrumb.bootstrap.css.js +3 -0
- package/components/breadcrumb/themes/dark/breadcrumb.bootstrap.css.js.map +1 -0
- package/components/breadcrumb/themes/dark/breadcrumb.fluent.css.d.ts +1 -0
- package/components/breadcrumb/themes/dark/breadcrumb.fluent.css.js +3 -0
- package/components/breadcrumb/themes/dark/breadcrumb.fluent.css.js.map +1 -0
- package/components/breadcrumb/themes/dark/breadcrumb.indigo.css.d.ts +1 -0
- package/components/breadcrumb/themes/dark/breadcrumb.indigo.css.js +3 -0
- package/components/breadcrumb/themes/dark/breadcrumb.indigo.css.js.map +1 -0
- package/components/breadcrumb/themes/dark/breadcrumb.material.css.d.ts +1 -0
- package/components/breadcrumb/themes/dark/breadcrumb.material.css.js +3 -0
- package/components/breadcrumb/themes/dark/breadcrumb.material.css.js.map +1 -0
- package/components/breadcrumb/themes/light/breadcrumb.bootstrap.css.d.ts +1 -0
- package/components/breadcrumb/themes/light/breadcrumb.bootstrap.css.js +3 -0
- package/components/breadcrumb/themes/light/breadcrumb.bootstrap.css.js.map +1 -0
- package/components/breadcrumb/themes/light/breadcrumb.fluent.css.d.ts +1 -0
- package/components/breadcrumb/themes/light/breadcrumb.fluent.css.js +3 -0
- package/components/breadcrumb/themes/light/breadcrumb.fluent.css.js.map +1 -0
- package/components/breadcrumb/themes/light/breadcrumb.indigo.css.d.ts +1 -0
- package/components/breadcrumb/themes/light/breadcrumb.indigo.css.js +3 -0
- package/components/breadcrumb/themes/light/breadcrumb.indigo.css.js.map +1 -0
- package/components/breadcrumb/themes/light/breadcrumb.material.css.d.ts +1 -0
- package/components/breadcrumb/themes/light/breadcrumb.material.css.js +3 -0
- package/components/breadcrumb/themes/light/breadcrumb.material.css.js.map +1 -0
- package/components/breadcrumb/themes/light/breadcrumb.shared.css.d.ts +1 -0
- package/components/breadcrumb/themes/light/breadcrumb.shared.css.js +3 -0
- package/components/breadcrumb/themes/light/breadcrumb.shared.css.js.map +1 -0
- package/components/breadcrumb/themes/shared/breadcrumb.bootstrap.css.d.ts +1 -0
- package/components/breadcrumb/themes/shared/breadcrumb.bootstrap.css.js +3 -0
- package/components/breadcrumb/themes/shared/breadcrumb.bootstrap.css.js.map +1 -0
- package/components/breadcrumb/themes/shared/breadcrumb.common.css.d.ts +1 -0
- package/components/breadcrumb/themes/shared/breadcrumb.common.css.js +3 -0
- package/components/breadcrumb/themes/shared/breadcrumb.common.css.js.map +1 -0
- package/components/breadcrumb/themes/shared/breadcrumb.fluent.css.d.ts +1 -0
- package/components/breadcrumb/themes/shared/breadcrumb.fluent.css.js +3 -0
- package/components/breadcrumb/themes/shared/breadcrumb.fluent.css.js.map +1 -0
- package/components/breadcrumb/themes/shared/breadcrumb.indigo.css.d.ts +1 -0
- package/components/breadcrumb/themes/shared/breadcrumb.indigo.css.js +3 -0
- package/components/breadcrumb/themes/shared/breadcrumb.indigo.css.js.map +1 -0
- package/components/breadcrumb/themes/shared/breadcrumb.material.css.d.ts +1 -0
- package/components/breadcrumb/themes/shared/breadcrumb.material.css.js +3 -0
- package/components/breadcrumb/themes/shared/breadcrumb.material.css.js.map +1 -0
- package/components/breadcrumb/themes/themes.d.ts +2 -0
- package/components/breadcrumb/themes/themes.js +50 -0
- package/components/breadcrumb/themes/themes.js.map +1 -0
- package/components/button/button.d.ts +0 -2
- package/components/button/button.js.map +1 -1
- package/components/button-group/button-group.d.ts +42 -12
- package/components/button-group/button-group.js +82 -34
- package/components/button-group/button-group.js.map +1 -1
- package/components/button-group/toggle-button.d.ts +6 -1
- package/components/button-group/toggle-button.js +28 -2
- package/components/button-group/toggle-button.js.map +1 -1
- package/components/calendar/base.d.ts +7 -2
- package/components/calendar/base.js +10 -4
- package/components/calendar/base.js.map +1 -1
- package/components/calendar/calendar.d.ts +6 -3
- package/components/calendar/calendar.js +41 -14
- package/components/calendar/calendar.js.map +1 -1
- package/components/calendar/days-view/days-view.d.ts +5 -8
- package/components/calendar/days-view/days-view.js +7 -16
- package/components/calendar/days-view/days-view.js.map +1 -1
- package/components/calendar/helpers.d.ts +13 -0
- package/components/calendar/helpers.js +15 -0
- package/components/calendar/helpers.js.map +1 -1
- package/components/calendar/themes/calendar.base.css.js +1 -1
- package/components/calendar/themes/calendar.base.css.js.map +1 -1
- package/components/calendar/themes/days-view.base.css.js +1 -1
- package/components/calendar/themes/days-view.base.css.js.map +1 -1
- package/components/calendar/themes/shared/bootstrap/calendar.bootstrap.css.js +1 -1
- package/components/calendar/themes/shared/bootstrap/calendar.bootstrap.css.js.map +1 -1
- package/components/calendar/themes/shared/bootstrap/days-view.bootstrap.css.js +1 -1
- package/components/calendar/themes/shared/bootstrap/days-view.bootstrap.css.js.map +1 -1
- package/components/calendar/themes/shared/fluent/days-view.fluent.css.js +1 -1
- package/components/calendar/themes/shared/fluent/days-view.fluent.css.js.map +1 -1
- package/components/calendar/themes/shared/indigo/calendar.indigo.css.js +1 -1
- package/components/calendar/themes/shared/indigo/calendar.indigo.css.js.map +1 -1
- package/components/calendar/themes/shared/indigo/days-view.indigo.css.js +1 -1
- package/components/calendar/themes/shared/indigo/days-view.indigo.css.js.map +1 -1
- package/components/calendar/themes/shared/material/days-view.material.css.js +1 -1
- package/components/calendar/themes/shared/material/days-view.material.css.js.map +1 -1
- package/components/calendar/themes/year-month-view.base.css.js +1 -1
- package/components/calendar/themes/year-month-view.base.css.js.map +1 -1
- package/components/card/themes/container.base.css.js +1 -1
- package/components/card/themes/container.base.css.js.map +1 -1
- package/components/carousel/carousel-indicator.js +1 -0
- package/components/carousel/carousel-indicator.js.map +1 -1
- package/components/carousel/carousel-slide.d.ts +1 -1
- package/components/carousel/carousel-slide.js.map +1 -1
- package/components/carousel/carousel.d.ts +3 -3
- package/components/carousel/carousel.js.map +1 -1
- package/components/carousel/themes/carousel.base.css.js +1 -1
- package/components/carousel/themes/carousel.base.css.js.map +1 -1
- package/components/carousel/themes/shared/carousel.indigo.css.js +1 -1
- package/components/carousel/themes/shared/carousel.indigo.css.js.map +1 -1
- package/components/chat/chat-input.d.ts +1 -2
- package/components/chat/chat-input.js +1 -1
- package/components/chat/chat-input.js.map +1 -1
- package/components/chat/chat-state.d.ts +8 -9
- package/components/chat/chat-state.js.map +1 -1
- package/components/chat/chat.d.ts +1 -3
- package/components/chat/chat.js +2 -2
- package/components/chat/chat.js.map +1 -1
- package/components/chat/message-attachments.d.ts +6 -15
- package/components/chat/message-attachments.js.map +1 -1
- package/components/chat/themes/chat.base.css.js +1 -1
- package/components/chat/themes/chat.base.css.js.map +1 -1
- package/components/chat/themes/message.base.css.js +1 -1
- package/components/chat/themes/message.base.css.js.map +1 -1
- package/components/chat/utils.d.ts +0 -1
- package/components/chat/utils.js +1 -1
- package/components/chat/utils.js.map +1 -1
- package/components/checkbox/checkbox-base.d.ts +1 -1
- package/components/checkbox/checkbox.js +1 -1
- package/components/checkbox/checkbox.js.map +1 -1
- package/components/checkbox/themes/checkbox.base.css.js +1 -1
- package/components/checkbox/themes/checkbox.base.css.js.map +1 -1
- package/components/checkbox/themes/shared/checkbox/checkbox.bootstrap.css.js +1 -1
- package/components/checkbox/themes/shared/checkbox/checkbox.bootstrap.css.js.map +1 -1
- package/components/checkbox/themes/shared/checkbox/checkbox.fluent.css.js +1 -1
- package/components/checkbox/themes/shared/checkbox/checkbox.fluent.css.js.map +1 -1
- package/components/checkbox/themes/shared/switch/switch.bootstrap.css.js +1 -1
- package/components/checkbox/themes/shared/switch/switch.bootstrap.css.js.map +1 -1
- package/components/checkbox/themes/shared/switch/switch.fluent.css.js +1 -1
- package/components/checkbox/themes/shared/switch/switch.fluent.css.js.map +1 -1
- package/components/checkbox/themes/shared/switch/switch.indigo.css.js +1 -1
- package/components/checkbox/themes/shared/switch/switch.indigo.css.js.map +1 -1
- package/components/checkbox/themes/shared/switch/switch.material.css.js +1 -1
- package/components/checkbox/themes/shared/switch/switch.material.css.js.map +1 -1
- package/components/checkbox/themes/switch.base.css.js +1 -1
- package/components/checkbox/themes/switch.base.css.js.map +1 -1
- package/components/chip/chip.d.ts +2 -2
- package/components/chip/chip.js.map +1 -1
- package/components/color-picker/color-picker.d.ts +35 -34
- package/components/color-picker/color-picker.js +9 -4
- package/components/color-picker/color-picker.js.map +1 -1
- package/components/color-picker/common.d.ts +0 -2
- package/components/color-picker/common.js +2 -2
- package/components/color-picker/common.js.map +1 -1
- package/components/color-picker/converters.js.map +1 -1
- package/components/color-picker/picker-canvas.js.map +1 -1
- package/components/color-picker/themes/color-picker.base.css.js +1 -1
- package/components/color-picker/themes/color-picker.base.css.js.map +1 -1
- package/components/combo/combo.d.ts +18 -20
- package/components/combo/combo.js +8 -2
- package/components/combo/combo.js.map +1 -1
- package/components/combo/controllers/data.d.ts +7 -10
- package/components/combo/controllers/data.js.map +1 -1
- package/components/combo/themes/combo-item.base.css.js +1 -1
- package/components/combo/themes/combo-item.base.css.js.map +1 -1
- package/components/combo/themes/combo.base.css.js +1 -1
- package/components/combo/themes/combo.base.css.js.map +1 -1
- package/components/combo/themes/shared/combo.bootstrap.css.js +1 -1
- package/components/combo/themes/shared/combo.bootstrap.css.js.map +1 -1
- package/components/date-picker/date-picker.base.d.ts +33 -29
- package/components/date-picker/date-picker.base.js +15 -4
- package/components/date-picker/date-picker.base.js.map +1 -1
- package/components/date-picker/date-picker.d.ts +1 -1
- package/components/date-picker/date-picker.js +5 -3
- package/components/date-picker/date-picker.js.map +1 -1
- package/components/date-picker/themes/date-picker.base.css.js +1 -1
- package/components/date-picker/themes/date-picker.base.css.js.map +1 -1
- package/components/date-range-picker/date-range-input.d.ts +0 -2
- package/components/date-range-picker/date-range-input.js +0 -6
- package/components/date-range-picker/date-range-input.js.map +1 -1
- package/components/date-range-picker/date-range-picker.base.css.js +1 -1
- package/components/date-range-picker/date-range-picker.base.css.js.map +1 -1
- package/components/date-range-picker/date-range-picker.d.ts +22 -31
- package/components/date-range-picker/date-range-picker.js +7 -7
- package/components/date-range-picker/date-range-picker.js.map +1 -1
- package/components/date-range-picker/i18n.d.ts +21 -0
- package/components/date-range-picker/i18n.js +10 -0
- package/components/date-range-picker/i18n.js.map +1 -0
- package/components/date-range-picker/predefined-ranges-area.base.css.js +1 -1
- package/components/date-range-picker/predefined-ranges-area.base.css.js.map +1 -1
- package/components/date-range-picker/predefined-ranges-area.d.ts +3 -3
- package/components/date-range-picker/predefined-ranges-area.js +2 -5
- package/components/date-range-picker/predefined-ranges-area.js.map +1 -1
- package/components/date-range-picker/validators.d.ts +0 -4
- package/components/date-range-picker/validators.js +4 -4
- package/components/date-range-picker/validators.js.map +1 -1
- package/components/date-time-input/date-time-input.base.d.ts +39 -37
- package/components/date-time-input/date-time-input.base.js +6 -0
- package/components/date-time-input/date-time-input.base.js.map +1 -1
- package/components/date-time-input/date-time-input.d.ts +1 -11
- package/components/date-time-input/date-time-input.js +0 -6
- package/components/date-time-input/date-time-input.js.map +1 -1
- package/components/date-time-input/datetime-mask-parser.d.ts +0 -10
- package/components/date-time-input/datetime-mask-parser.js +1 -1
- package/components/date-time-input/datetime-mask-parser.js.map +1 -1
- package/components/dialog/dialog.js.map +1 -1
- package/components/divider/themes/divider.base.css.js +1 -1
- package/components/divider/themes/divider.base.css.js.map +1 -1
- package/components/dropdown/dropdown-group.d.ts +2 -10
- package/components/dropdown/dropdown-group.js +2 -27
- package/components/dropdown/dropdown-group.js.map +1 -1
- package/components/dropdown/dropdown.d.ts +17 -23
- package/components/dropdown/dropdown.js +5 -17
- package/components/dropdown/dropdown.js.map +1 -1
- package/components/dropdown/themes/dropdown-item.base.css.js +1 -1
- package/components/dropdown/themes/dropdown-item.base.css.js.map +1 -1
- package/components/dropdown/themes/dropdown.base.css.js +1 -1
- package/components/dropdown/themes/dropdown.base.css.js.map +1 -1
- package/components/file-input/file-input.d.ts +2 -2
- package/components/file-input/file-input.js.map +1 -1
- package/components/file-input/themes/file-input.base.css.js +1 -1
- package/components/file-input/themes/file-input.base.css.js.map +1 -1
- package/components/file-input/themes/shared/file-input.bootstrap.css.js +1 -1
- package/components/file-input/themes/shared/file-input.bootstrap.css.js.map +1 -1
- package/components/icon/icon.d.ts +1 -1
- package/components/icon/icon.registry.d.ts +6 -6
- package/components/icon/icon.registry.js.map +1 -1
- package/components/input/input.d.ts +3 -3
- package/components/input/input.js.map +1 -1
- package/components/input/themes/shared/input.indigo.css.js +1 -1
- package/components/input/themes/shared/input.indigo.css.js.map +1 -1
- package/components/input/themes/shared/input.material.css.js +1 -1
- package/components/input/themes/shared/input.material.css.js.map +1 -1
- package/components/list/themes/item.base.css.js +1 -1
- package/components/list/themes/item.base.css.js.map +1 -1
- package/components/mask-input/mask-history.d.ts +22 -18
- package/components/mask-input/mask-history.js.map +1 -1
- package/components/mask-input/mask-input.d.ts +1 -1
- package/components/mask-input/mask-parser.d.ts +11 -13
- package/components/mask-input/mask-parser.js.map +1 -1
- package/components/nav-drawer/themes/item.base.css.js +1 -1
- package/components/nav-drawer/themes/item.base.css.js.map +1 -1
- package/components/popover/popover.d.ts +45 -34
- package/components/popover/popover.js +54 -122
- package/components/popover/popover.js.map +1 -1
- package/components/popover/position/arrow.d.ts +19 -0
- package/components/popover/position/arrow.js +33 -0
- package/components/popover/position/arrow.js.map +1 -0
- package/components/popover/position/floating.d.ts +40 -0
- package/components/popover/position/floating.js +146 -0
- package/components/popover/position/floating.js.map +1 -0
- package/components/popover/position/native.d.ts +45 -0
- package/components/popover/position/native.js +158 -0
- package/components/popover/position/native.js.map +1 -0
- package/components/popover/position/strategy.d.ts +37 -0
- package/components/popover/position/strategy.js +21 -0
- package/components/popover/position/strategy.js.map +1 -0
- package/components/popover/position/types.d.ts +26 -0
- package/components/popover/position/types.js +15 -0
- package/components/popover/position/types.js.map +1 -0
- package/components/popover/themes/light/popover.base.css.js +1 -1
- package/components/popover/themes/light/popover.base.css.js.map +1 -1
- package/components/progress/circular-progress.d.ts +0 -5
- package/components/progress/circular-progress.js.map +1 -1
- package/components/progress/themes/linear/linear.progress.base.css.js +1 -1
- package/components/progress/themes/linear/linear.progress.base.css.js.map +1 -1
- package/components/progress/themes/linear/shared/linear.progress.bootstrap.css.d.ts +1 -0
- package/components/progress/themes/linear/shared/linear.progress.bootstrap.css.js +3 -0
- package/components/progress/themes/linear/shared/linear.progress.bootstrap.css.js.map +1 -0
- package/components/progress/themes/linear/themes.js +3 -2
- package/components/progress/themes/linear/themes.js.map +1 -1
- package/components/qr-code/qr-code.d.ts +29 -2
- package/components/qr-code/qr-code.js +56 -13
- package/components/qr-code/qr-code.js.map +1 -1
- package/components/qr-code/renderer/export.d.ts +28 -0
- package/components/qr-code/renderer/export.js +120 -0
- package/components/qr-code/renderer/export.js.map +1 -0
- package/components/qr-code/types.d.ts +26 -0
- package/components/qr-code/types.js.map +1 -1
- package/components/radio/radio.d.ts +4 -4
- package/components/radio/radio.js +17 -14
- package/components/radio/radio.js.map +1 -1
- package/components/radio/themes/radio.base.css.js +1 -1
- package/components/radio/themes/radio.base.css.js.map +1 -1
- package/components/radio/themes/shared/radio.bootstrap.css.js +1 -1
- package/components/radio/themes/shared/radio.bootstrap.css.js.map +1 -1
- package/components/radio/themes/shared/radio.indigo.css.js +1 -1
- package/components/radio/themes/shared/radio.indigo.css.js.map +1 -1
- package/components/radio-group/radio-group.js.map +1 -1
- package/components/rating/rating.d.ts +6 -6
- package/components/rating/rating.js.map +1 -1
- package/components/select/select-group.d.ts +5 -10
- package/components/select/select-group.js +10 -34
- package/components/select/select-group.js.map +1 -1
- package/components/select/select.d.ts +12 -20
- package/components/select/select.js +4 -14
- package/components/select/select.js.map +1 -1
- package/components/select/themes/select.base.css.js +1 -1
- package/components/select/themes/select.base.css.js.map +1 -1
- package/components/select/themes/shared/select.bootstrap.css.js +1 -1
- package/components/select/themes/shared/select.bootstrap.css.js.map +1 -1
- package/components/slider/themes/shared/slider.material.css.js +1 -1
- package/components/slider/themes/shared/slider.material.css.js.map +1 -1
- package/components/slider/themes/slider.base.css.js +1 -1
- package/components/slider/themes/slider.base.css.js.map +1 -1
- package/components/snackbar/themes/snackbar.base.css.js +1 -1
- package/components/snackbar/themes/snackbar.base.css.js.map +1 -1
- package/components/splitter/splitter.d.ts +6 -6
- package/components/splitter/splitter.js.map +1 -1
- package/components/splitter/themes/splitter.base.css.js +1 -1
- package/components/splitter/themes/splitter.base.css.js.map +1 -1
- package/components/stepper/themes/step/step.base.css.js +1 -1
- package/components/stepper/themes/step/step.base.css.js.map +1 -1
- package/components/tabs/themes/shared/tab/tab.bootstrap.css.js +1 -1
- package/components/tabs/themes/shared/tab/tab.bootstrap.css.js.map +1 -1
- package/components/tabs/themes/shared/tab/tab.fluent.css.js +1 -1
- package/components/tabs/themes/shared/tab/tab.fluent.css.js.map +1 -1
- package/components/tabs/themes/shared/tab/tab.indigo.css.js +1 -1
- package/components/tabs/themes/shared/tab/tab.indigo.css.js.map +1 -1
- package/components/tabs/themes/shared/tab/tab.material.css.js +1 -1
- package/components/tabs/themes/shared/tab/tab.material.css.js.map +1 -1
- package/components/tabs/themes/shared/tabs/tabs.fluent.css.js +1 -1
- package/components/tabs/themes/shared/tabs/tabs.fluent.css.js.map +1 -1
- package/components/tabs/themes/shared/tabs/tabs.indigo.css.js +1 -1
- package/components/tabs/themes/shared/tabs/tabs.indigo.css.js.map +1 -1
- package/components/tabs/themes/shared/tabs/tabs.material.css.js +1 -1
- package/components/tabs/themes/shared/tabs/tabs.material.css.js.map +1 -1
- package/components/tabs/themes/tab.base.css.js +1 -1
- package/components/tabs/themes/tab.base.css.js.map +1 -1
- package/components/textarea/textarea.d.ts +1 -1
- package/components/textarea/textarea.js.map +1 -1
- package/components/textarea/themes/shared/textarea.bootstrap.css.js +1 -1
- package/components/textarea/themes/shared/textarea.bootstrap.css.js.map +1 -1
- package/components/textarea/themes/shared/textarea.common.css.js +1 -1
- package/components/textarea/themes/shared/textarea.common.css.js.map +1 -1
- package/components/textarea/themes/shared/textarea.fluent.css.js +1 -1
- package/components/textarea/themes/shared/textarea.fluent.css.js.map +1 -1
- package/components/textarea/themes/shared/textarea.indigo.css.js +1 -1
- package/components/textarea/themes/shared/textarea.indigo.css.js.map +1 -1
- package/components/textarea/themes/shared/textarea.material.css.js +1 -1
- package/components/textarea/themes/shared/textarea.material.css.js.map +1 -1
- package/components/tile-manager/themes/tile.base.css.js +1 -1
- package/components/tile-manager/themes/tile.base.css.js.map +1 -1
- package/components/tile-manager/tile-manager.d.ts +6 -7
- package/components/tile-manager/tile-manager.js.map +1 -1
- package/components/tile-manager/tile.d.ts +3 -3
- package/components/tile-manager/tile.js.map +1 -1
- package/components/toast/themes/toast.base.css.js +1 -1
- package/components/toast/themes/toast.base.css.js.map +1 -1
- package/components/toast/toast.d.ts +0 -2
- package/components/toast/toast.js.map +1 -1
- package/components/tooltip/controller.js.map +1 -1
- package/components/tooltip/service.js +4 -5
- package/components/tooltip/service.js.map +1 -1
- package/components/tooltip/themes/tooltip.base.css.js +1 -1
- package/components/tooltip/themes/tooltip.base.css.js.map +1 -1
- package/components/tooltip/tooltip.d.ts +34 -13
- package/components/tooltip/tooltip.js +8 -4
- package/components/tooltip/tooltip.js.map +1 -1
- package/components/tree/themes/item.base.css.js +1 -1
- package/components/tree/themes/item.base.css.js.map +1 -1
- package/components/tree/tree-item.d.ts +6 -6
- package/components/tree/tree-item.js.map +1 -1
- package/components/tree/tree.navigation.d.ts +5 -6
- package/components/tree/tree.navigation.js.map +1 -1
- package/components/tree/tree.selection.js.map +1 -1
- package/components/types.d.ts +1 -1
- package/components/types.js.map +1 -1
- package/components/validation-container/themes/validator.base.css.js +1 -1
- package/components/validation-container/themes/validator.base.css.js.map +1 -1
- package/components/validation-container/validation-container.d.ts +10 -12
- package/components/validation-container/validation-container.js +14 -17
- package/components/validation-container/validation-container.js.map +1 -1
- package/components/virtualization/engine.d.ts +5 -5
- package/components/virtualization/engine.js.map +1 -1
- package/components/virtualization/virtualization.d.ts +61 -63
- package/components/virtualization/virtualization.js +6 -5
- package/components/virtualization/virtualization.js.map +1 -1
- package/custom-elements.json +16769 -19698
- package/igniteui-webcomponents.css-data.json +2 -2
- package/igniteui-webcomponents.html-data.json +1 -1
- package/index.d.ts +3 -1
- package/index.js +2 -0
- package/index.js.map +1 -1
- package/internals/abort-handler.d.ts +13 -25
- package/internals/abort-handler.js +4 -6
- package/internals/abort-handler.js.map +1 -1
- package/internals/context.d.ts +13 -7
- package/internals/context.js +2 -1
- package/internals/context.js.map +1 -1
- package/internals/controllers/adopt-styles.d.ts +19 -20
- package/internals/controllers/adopt-styles.js +3 -8
- package/internals/controllers/adopt-styles.js.map +1 -1
- package/internals/controllers/aria-projection.d.ts +56 -55
- package/internals/controllers/aria-projection.js +14 -15
- package/internals/controllers/aria-projection.js.map +1 -1
- package/internals/controllers/async-consumer.js.map +1 -1
- package/internals/controllers/command.d.ts +15 -30
- package/internals/controllers/command.js +2 -7
- package/internals/controllers/command.js.map +1 -1
- package/internals/controllers/context-provider.d.ts +7 -13
- package/internals/controllers/context-provider.js.map +1 -1
- package/internals/controllers/focus-ring.d.ts +10 -30
- package/internals/controllers/focus-ring.js +6 -12
- package/internals/controllers/focus-ring.js.map +1 -1
- package/internals/controllers/fullscreen.d.ts +7 -23
- package/internals/controllers/fullscreen.js +3 -9
- package/internals/controllers/fullscreen.js.map +1 -1
- package/internals/controllers/gestures.d.ts +10 -29
- package/internals/controllers/gestures.js +1 -3
- package/internals/controllers/gestures.js.map +1 -1
- package/internals/controllers/group.d.ts +13 -30
- package/internals/controllers/group.js.map +1 -1
- package/internals/controllers/host-listeners.d.ts +28 -0
- package/internals/controllers/host-listeners.js +27 -0
- package/internals/controllers/host-listeners.js.map +1 -0
- package/internals/controllers/id-resolver.d.ts +8 -9
- package/internals/controllers/id-resolver.js +6 -14
- package/internals/controllers/id-resolver.js.map +1 -1
- package/internals/controllers/internals.d.ts +53 -104
- package/internals/controllers/internals.js +40 -13
- package/internals/controllers/internals.js.map +1 -1
- package/internals/controllers/key-bindings.d.ts +61 -158
- package/internals/controllers/key-bindings.js +68 -67
- package/internals/controllers/key-bindings.js.map +1 -1
- package/internals/controllers/keys.d.ts +32 -0
- package/internals/controllers/keys.js +20 -0
- package/internals/controllers/keys.js.map +1 -0
- package/internals/controllers/mutation-observer.d.ts +14 -37
- package/internals/controllers/mutation-observer.js +1 -1
- package/internals/controllers/mutation-observer.js.map +1 -1
- package/internals/controllers/resize-observer.d.ts +9 -19
- package/internals/controllers/resize-observer.js.map +1 -1
- package/internals/controllers/root-click.d.ts +11 -42
- package/internals/controllers/root-click.js +4 -6
- package/internals/controllers/root-click.js.map +1 -1
- package/internals/controllers/roving-focus.d.ts +16 -35
- package/internals/controllers/roving-focus.js.map +1 -1
- package/internals/controllers/slot.d.ts +25 -54
- package/internals/controllers/slot.js +6 -6
- package/internals/controllers/slot.js.map +1 -1
- package/internals/controllers/toggle.d.ts +44 -48
- package/internals/controllers/toggle.js.map +1 -1
- package/internals/date/compare.js.map +1 -1
- package/internals/date/converters.d.ts +10 -7
- package/internals/date/converters.js.map +1 -1
- package/internals/date/model.d.ts +9 -16
- package/internals/date/model.js +22 -25
- package/internals/date/model.js.map +1 -1
- package/internals/decorators/blazorAdditionalDependencies.d.ts +4 -2
- package/internals/decorators/blazorAdditionalDependencies.js.map +1 -1
- package/internals/decorators/blazorDeepImport.d.ts +1 -3
- package/internals/decorators/blazorDeepImport.js.map +1 -1
- package/internals/decorators/blazorInclude.d.ts +3 -2
- package/internals/decorators/blazorInclude.js.map +1 -1
- package/internals/decorators/blazorIndirectRender.d.ts +1 -3
- package/internals/decorators/blazorIndirectRender.js.map +1 -1
- package/internals/decorators/blazorSuppressComponent.d.ts +1 -3
- package/internals/decorators/blazorSuppressComponent.js.map +1 -1
- package/internals/decorators/coerced-property.d.ts +14 -20
- package/internals/decorators/coerced-property.js.map +1 -1
- package/internals/decorators/shadow-options.d.ts +2 -5
- package/internals/decorators/shadow-options.js.map +1 -1
- package/internals/definitions/defineAllComponents.js +6 -0
- package/internals/definitions/defineAllComponents.js.map +1 -1
- package/internals/directives/drag.d.ts +51 -81
- package/internals/directives/drag.js +27 -89
- package/internals/directives/drag.js.map +1 -1
- package/internals/directives/pointer-operation.d.ts +75 -0
- package/internals/directives/pointer-operation.js +92 -0
- package/internals/directives/pointer-operation.js.map +1 -0
- package/internals/directives/resize.d.ts +36 -64
- package/internals/directives/resize.js +18 -85
- package/internals/directives/resize.js.map +1 -1
- package/internals/i18n/EN/calendar.resources.d.ts +8 -2
- package/internals/i18n/EN/calendar.resources.js +2 -2
- package/internals/i18n/EN/calendar.resources.js.map +1 -1
- package/internals/i18n/EN/chat.resources.d.ts +8 -2
- package/internals/i18n/EN/chat.resources.js +3 -10
- package/internals/i18n/EN/chat.resources.js.map +1 -1
- package/internals/i18n/EN/date-picker.resources.d.ts +6 -4
- package/internals/i18n/EN/date-picker.resources.js +1 -7
- package/internals/i18n/EN/date-picker.resources.js.map +1 -1
- package/internals/i18n/EN/date-range-picker.resources.d.ts +9 -2
- package/internals/i18n/EN/date-range-picker.resources.js +2 -2
- package/internals/i18n/EN/date-range-picker.resources.js.map +1 -1
- package/internals/i18n/i18n-controller.d.ts +44 -46
- package/internals/i18n/i18n-controller.js +46 -33
- package/internals/i18n/i18n-controller.js.map +1 -1
- package/internals/i18n/utils.d.ts +9 -4
- package/internals/i18n/utils.js +4 -27
- package/internals/i18n/utils.js.map +1 -1
- package/internals/mixins/alert.d.ts +10 -25
- package/internals/mixins/alert.js.map +1 -1
- package/internals/mixins/combo-box.d.ts +21 -11
- package/internals/mixins/combo-box.js +16 -22
- package/internals/mixins/combo-box.js.map +1 -1
- package/internals/mixins/event-emitter.js +9 -11
- package/internals/mixins/event-emitter.js.map +1 -1
- package/internals/mixins/forms/associated-required.d.ts +4 -4
- package/internals/mixins/forms/associated-required.js.map +1 -1
- package/internals/mixins/forms/associated.d.ts +4 -2
- package/internals/mixins/forms/associated.js +8 -19
- package/internals/mixins/forms/associated.js.map +1 -1
- package/internals/mixins/forms/form-transformers.js.map +1 -1
- package/internals/mixins/forms/types.d.ts +24 -80
- package/internals/mixins/forms/types.js.map +1 -1
- package/internals/mixins/group.d.ts +18 -0
- package/internals/mixins/group.js +37 -0
- package/internals/mixins/group.js.map +1 -0
- package/internals/mixins/i18n.d.ts +10 -16
- package/internals/mixins/i18n.js.map +1 -1
- package/internals/mixins/mask-behavior.d.ts +8 -22
- package/internals/mixins/mask-behavior.js +1 -2
- package/internals/mixins/mask-behavior.js.map +1 -1
- package/internals/mixins/option.d.ts +1 -2
- package/internals/mixins/option.js +2 -1
- package/internals/mixins/option.js.map +1 -1
- package/internals/part-map.d.ts +4 -2
- package/internals/part-map.js +1 -1
- package/internals/part-map.js.map +1 -1
- package/internals/templates/input-shell.d.ts +8 -17
- package/internals/templates/input-shell.js +4 -1
- package/internals/templates/input-shell.js.map +1 -1
- package/internals/templates/masked-input.d.ts +7 -8
- package/internals/templates/masked-input.js.map +1 -1
- package/internals/templates/slotted-icon.d.ts +7 -12
- package/internals/templates/slotted-icon.js.map +1 -1
- package/internals/templates/toggle-shell.d.ts +6 -7
- package/internals/templates/toggle-shell.js.map +1 -1
- package/internals/timing.d.ts +5 -14
- package/internals/timing.js.map +1 -1
- package/internals/utils/arrays.d.ts +21 -21
- package/internals/utils/arrays.js +14 -0
- package/internals/utils/arrays.js.map +1 -1
- package/internals/utils/dom.d.ts +51 -39
- package/internals/utils/dom.js +1 -2
- package/internals/utils/dom.js.map +1 -1
- package/internals/utils/events.d.ts +29 -16
- package/internals/utils/events.js +9 -1
- package/internals/utils/events.js.map +1 -1
- package/internals/utils/lit.d.ts +5 -2
- package/internals/utils/lit.js.map +1 -1
- package/internals/utils/math.d.ts +8 -6
- package/internals/utils/math.js.map +1 -1
- package/internals/utils/objects.d.ts +3 -20
- package/internals/utils/objects.js +1 -39
- package/internals/utils/objects.js.map +1 -1
- package/internals/utils/strings.d.ts +9 -11
- package/internals/utils/strings.js.map +1 -1
- package/internals/utils/types.d.ts +16 -3
- package/internals/utils/types.js +3 -0
- package/internals/utils/types.js.map +1 -1
- package/internals/validators.d.ts +9 -8
- package/internals/validators.js +12 -6
- package/internals/validators.js.map +1 -1
- package/package.json +1 -1
- package/skills/README.md +3 -0
- package/skills/igniteui-wc-figma-to-app/SKILL.md +907 -0
- package/skills/igniteui-wc-figma-to-app/references/asset-extraction.md +363 -0
- package/skills/igniteui-wc-figma-to-app/references/design-token-bridge.md +407 -0
- package/skills/igniteui-wc-figma-to-app/references/figma-component-map.md +325 -0
- package/skills/igniteui-wc-figma-to-app/references/mcp-setup.md +409 -0
- package/skills/igniteui-wc-figma-to-app/references/validation-patterns.md +376 -0
- package/skills/igniteui-wc-generate-from-image-design/references/gotchas.md +21 -0
- package/skills/igniteui-wc-integrate-with-framework/SKILL.md +4 -3
- package/skills/igniteui-wc-integrate-with-framework/references/vanilla-js.md +14 -0
- package/skills/igniteui-wc-migrate-grid-lite-to-premium/SKILL.md +12 -2
- package/theming/config.d.ts +14 -5
- package/theming/config.js +38 -18
- package/theming/config.js.map +1 -1
- package/theming/context.d.ts +1 -23
- package/theming/context.js.map +1 -1
- package/theming/theming-controller.d.ts +2 -32
- package/theming/theming-controller.js +15 -21
- package/theming/theming-controller.js.map +1 -1
- package/theming/theming-event.d.ts +0 -7
- package/theming/theming-event.js +0 -13
- package/theming/theming-event.js.map +1 -1
- package/theming/types.d.ts +1 -8
- package/theming/types.js.map +1 -1
- package/web-types.json +3 -3
- package/animations/presets/slide/index.d.ts +0 -3
- package/animations/presets/slide/index.js +0 -16
- package/animations/presets/slide/index.js.map +0 -1
- package/internals/controllers/root-scroll.d.ts +0 -31
- package/internals/controllers/root-scroll.js +0 -71
- package/internals/controllers/root-scroll.js.map +0 -1
- package/theming/utils.d.ts +0 -11
- package/theming/utils.js +0 -20
- package/theming/utils.js.map +0 -1
|
@@ -1,56 +1,42 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ReactiveControllerHost } from 'lit';
|
|
2
2
|
import type { Ref } from 'lit/directives/ref.js';
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export declare const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
export declare
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
3
|
+
export * from './keys.js';
|
|
4
|
+
/**
|
|
5
|
+
* {@link MODIFIER_ENTRIES} as a name to event property lookup.
|
|
6
|
+
* @internal Used by the keyboard simulation helper of the test suite.
|
|
7
|
+
*/
|
|
8
|
+
export declare const MODIFIER_EVENT_KEYS: Record<string, string>;
|
|
9
|
+
/**
|
|
10
|
+
* Splits the keys into modifiers (Alt, Control, Meta, Shift) and normal keys,
|
|
11
|
+
* in lower case.
|
|
12
|
+
*
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
export declare function parseKeys(inputKeys: string | string[]): {
|
|
16
|
+
keys: string[];
|
|
17
|
+
modifiers: string[];
|
|
18
|
+
};
|
|
19
19
|
type KeyBindingHandler = (event: KeyboardEvent) => void;
|
|
20
20
|
type KeyBindingObserverCleanup = {
|
|
21
21
|
unsubscribe: () => void;
|
|
22
22
|
};
|
|
23
23
|
/**
|
|
24
|
-
* Whether the
|
|
25
|
-
*
|
|
26
|
-
* @param node - The event target
|
|
27
|
-
* @param event - The event object
|
|
24
|
+
* Whether the controller must ignore the current event.
|
|
28
25
|
*
|
|
29
|
-
*
|
|
26
|
+
* @param node - The target of the event.
|
|
27
|
+
* @param event - The event.
|
|
30
28
|
*/
|
|
31
29
|
type KeyBindingSkipCallback = (node: Element, event: KeyboardEvent) => boolean;
|
|
32
|
-
/**
|
|
33
|
-
* The event type which will trigger the bound handler.
|
|
34
|
-
*/
|
|
30
|
+
/** The event type that starts the bound handler. */
|
|
35
31
|
type KeyBindingTrigger = 'keydown' | 'keyup';
|
|
36
|
-
/**
|
|
37
|
-
* Configuration object for the controller.
|
|
38
|
-
* @hidden
|
|
39
|
-
*/
|
|
32
|
+
/** @hidden */
|
|
40
33
|
interface KeyBindingControllerOptions {
|
|
41
|
-
/**
|
|
42
|
-
* By default, the controller listens for keypress events in the context of the host element.
|
|
43
|
-
* If you pass a `ref`, you can limit the observation to a certain DOM part of the host scope.
|
|
44
|
-
*/
|
|
34
|
+
/** The element to observe. Defaults to the host element. */
|
|
45
35
|
ref?: Ref;
|
|
46
36
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* that match one of the selectors.
|
|
51
|
-
* Otherwise you can pass a {@link KeyBindingSkipCallback} function.
|
|
52
|
-
*
|
|
53
|
-
* Defaults to `['input', 'textarea', 'select']`.
|
|
37
|
+
* The key presses that the controller ignores. CSS selectors match against
|
|
38
|
+
* the composed path of the event; a {@link KeyBindingSkipCallback} decides
|
|
39
|
+
* per event instead. Defaults to `['input', 'textarea', 'select']`.
|
|
54
40
|
*
|
|
55
41
|
* @example
|
|
56
42
|
* ```ts
|
|
@@ -66,177 +52,94 @@ interface KeyBindingControllerOptions {
|
|
|
66
52
|
* ```
|
|
67
53
|
*/
|
|
68
54
|
skip?: string[] | KeyBindingSkipCallback;
|
|
69
|
-
/**
|
|
70
|
-
* A set of KeyBindingOptions configuration which is applied to every handler
|
|
71
|
-
* that is added to the controller.
|
|
72
|
-
*
|
|
73
|
-
* Any additional KeyBindingOptions values passed when `set` is called
|
|
74
|
-
* will be merged with `bindingDefaults`.
|
|
75
|
-
*/
|
|
55
|
+
/** Default options for every binding. A `set` call merges over them. */
|
|
76
56
|
bindingDefaults?: KeyBindingOptions;
|
|
77
57
|
}
|
|
78
|
-
/**
|
|
79
|
-
* Configuration object for customizing the behavior of
|
|
80
|
-
* the registered handler.
|
|
81
|
-
*/
|
|
82
58
|
interface KeyBindingOptions {
|
|
83
|
-
/**
|
|
84
|
-
* The event type(s) on which the handler will be invoked.
|
|
85
|
-
*
|
|
86
|
-
* Defaults to `keydown` if not set.
|
|
87
|
-
*/
|
|
59
|
+
/** The event types that start the handler. Defaults to `keydown`. */
|
|
88
60
|
triggers?: KeyBindingTrigger[];
|
|
89
|
-
/**
|
|
90
|
-
* Whether the handler should fire on auto-repeated keydown events (i.e. when a key is held down).
|
|
91
|
-
*
|
|
92
|
-
* Defaults to `false`.
|
|
93
|
-
*/
|
|
61
|
+
/** Whether the handler runs for a repeated keydown. Defaults to `false`. */
|
|
94
62
|
repeat?: boolean;
|
|
95
|
-
/**
|
|
96
|
-
* Whether to call `preventDefault` on the target event before the handler is invoked.
|
|
97
|
-
*/
|
|
63
|
+
/** Whether to call `preventDefault` before the handler runs. */
|
|
98
64
|
preventDefault?: boolean;
|
|
99
|
-
/**
|
|
100
|
-
* Whether to call `stopPropagation` on the target event before the handler is invoked.
|
|
101
|
-
*/
|
|
65
|
+
/** Whether to call `stopPropagation` before the handler runs. */
|
|
102
66
|
stopPropagation?: boolean;
|
|
103
67
|
}
|
|
104
|
-
/** {@link MODIFIER_ENTRIES} as a lookup of modifier name to event property. */
|
|
105
|
-
export declare const MODIFIER_EVENT_KEYS: Record<string, string>;
|
|
106
68
|
/**
|
|
107
|
-
*
|
|
108
|
-
* comparing `event.key` directly - the key names of this module are lowercase,
|
|
109
|
-
* while real events carry the canonical casing (e.g. `Enter`).
|
|
110
|
-
*/
|
|
111
|
-
export declare function isKey(event: KeyboardEvent, key: string): boolean;
|
|
112
|
-
/**
|
|
113
|
-
* A controller for managing key bindings on a host element. It allows you to register handlers for specific key combinations,
|
|
114
|
-
* with support for modifier keys and event options such as `preventDefault` and `stopPropagation`.
|
|
115
|
-
*
|
|
116
|
-
* The controller listens for keyboard events on the host element (or an optionally specified element) and invokes the appropriate handlers
|
|
117
|
-
* when the registered key combinations are detected.
|
|
69
|
+
* Manages the key bindings of a host element.
|
|
118
70
|
* @hidden
|
|
119
71
|
*/
|
|
120
|
-
declare class KeyBindingController
|
|
72
|
+
declare class KeyBindingController {
|
|
73
|
+
/** Base configuration, shared between instances. Never written to. */
|
|
121
74
|
private static readonly _defaultOptions;
|
|
122
75
|
private readonly _host;
|
|
123
76
|
private readonly _ref?;
|
|
124
|
-
private readonly _abortHandle;
|
|
125
77
|
private readonly _bindings;
|
|
126
78
|
private readonly _allowedKeys;
|
|
127
79
|
private readonly _pressedKeys;
|
|
128
|
-
private readonly
|
|
129
|
-
private readonly _skipSelector
|
|
80
|
+
private readonly _bindingDefaults;
|
|
81
|
+
private readonly _skipSelector?;
|
|
82
|
+
private readonly _skipCallback?;
|
|
130
83
|
private _observedElement?;
|
|
131
84
|
private get _element();
|
|
132
85
|
constructor(host: ReactiveControllerHost & Element, options?: KeyBindingControllerOptions);
|
|
133
|
-
/**
|
|
134
|
-
* Applies the event modifiers specified in the binding options to the provided keyboard event.
|
|
135
|
-
* If `preventDefault` is set, it calls `event.preventDefault()`.
|
|
136
|
-
* If `stopPropagation` is set, it calls `event.stopPropagation()`.
|
|
137
|
-
*/
|
|
86
|
+
/** Applies the event options of the binding to the keyboard event. */
|
|
138
87
|
private _applyEventModifiers;
|
|
139
|
-
/**
|
|
140
|
-
* Determines whether the provided keyboard event matches the specified key binding,
|
|
141
|
-
* taking into account the event type and the binding's trigger options.
|
|
142
|
-
*/
|
|
88
|
+
/** Whether the event type matches the triggers of the binding. */
|
|
143
89
|
private _bindingMatches;
|
|
144
90
|
/**
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
* and if it matches any of the skip conditions defined in the controller's options.
|
|
91
|
+
* Whether to ignore the event. The key has no binding, the event missed the
|
|
92
|
+
* observed element, or the skip configuration agrees.
|
|
148
93
|
*/
|
|
149
94
|
private _shouldSkip;
|
|
150
|
-
/** @internal */
|
|
151
|
-
hostConnected(): void;
|
|
152
|
-
/** @internal */
|
|
153
|
-
hostDisconnected(): void;
|
|
154
95
|
/**
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
* This is necessary to prevent "stuck" keys when the user switches to another application
|
|
158
|
-
* or tab while holding down a key.
|
|
96
|
+
* Clears the pressed keys on a global blur. No keyup arrives if the user
|
|
97
|
+
* moves to a different application or tab with a key down.
|
|
159
98
|
*/
|
|
160
99
|
private _handleGlobalBlur;
|
|
161
|
-
/**
|
|
162
|
-
* Handles keyboard events on the observed element.
|
|
163
|
-
*
|
|
164
|
-
* It checks if the event should be skipped based on the controller's configuration,
|
|
165
|
-
* and if not, it determines if there is a registered handler for the combination of pressed keys and active modifiers.
|
|
166
|
-
*
|
|
167
|
-
* If a matching handler is found, it applies the specified event modifiers and invokes the handler.
|
|
168
|
-
* It also manages the internal state of currently pressed keys to accurately detect key combinations.
|
|
169
|
-
*
|
|
170
|
-
*/
|
|
100
|
+
/** Handles a keyboard event on the observed element. */
|
|
171
101
|
private _handleKeyEvent;
|
|
172
102
|
/** @internal */
|
|
173
103
|
handleEvent(event: KeyboardEvent | FocusEvent): void;
|
|
174
104
|
/**
|
|
175
|
-
* Registers a
|
|
176
|
-
*
|
|
177
|
-
* The `key` parameter can be a single key or an array of keys, and can include modifier keys (e.g., 'ctrl+s', ['shift', 'a']).
|
|
178
|
-
* The `handler` is a function that will be called when the specified key combination is detected.
|
|
179
|
-
* The `bindingOptions` allow you to customize the behavior of the binding, such as which event types trigger the handler,
|
|
180
|
-
* whether it should fire on auto-repeated keydown events, and whether to call `preventDefault` or `stopPropagation`.
|
|
181
|
-
*
|
|
182
|
-
* The method returns the controller instance to allow for method chaining.
|
|
105
|
+
* Registers a binding for a key or a combination, such as `['shift', 'a']`.
|
|
106
|
+
* Returns the controller, for chaining.
|
|
183
107
|
*/
|
|
184
108
|
set(key: string | string[], handler: KeyBindingHandler, bindingOptions?: KeyBindingOptions): this;
|
|
185
109
|
/**
|
|
186
|
-
* Registers
|
|
187
|
-
*
|
|
188
|
-
* This is a common pattern for activating buttons or interactive elements, and this method provides a convenient way to set up such bindings.
|
|
189
|
-
*
|
|
190
|
-
* The method accepts optional `KeyBindingOptions` which are applied to both the Enter key and Space bar bindings.
|
|
191
|
-
* It returns the controller instance to allow for method chaining.
|
|
192
|
-
*
|
|
110
|
+
* Registers `handler` for both the Enter key and the Space bar. Returns the
|
|
111
|
+
* controller, for chaining.
|
|
193
112
|
*/
|
|
194
113
|
setActivateHandler(handler: KeyBindingHandler, options?: KeyBindingOptions): this;
|
|
195
114
|
/**
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
* Returns an object with an `unsubscribe` function which should be called when the observing of keyboard
|
|
200
|
-
* events on the `element` should cease.
|
|
115
|
+
* Listens for keyboard events on any page element, with the configuration
|
|
116
|
+
* and the handlers of this controller. Call `unsubscribe` to stop.
|
|
201
117
|
*/
|
|
202
118
|
observeElement(element: Element): KeyBindingObserverCleanup;
|
|
203
119
|
}
|
|
204
120
|
/**
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
* Modifiers are keys like Alt, Ctrl, Meta and Shift which modify the behavior of other keys when pressed in combination.
|
|
208
|
-
* Regular keys are all other keys which trigger the bound handler when pressed.
|
|
209
|
-
*
|
|
210
|
-
* The returned `keys` and `modifiers` are normalized to lowercase for consistency.
|
|
211
|
-
*
|
|
212
|
-
* @internal
|
|
213
|
-
*
|
|
214
|
-
* @param inputKeys - The key or keys to parse, provided as a string or an array of strings.
|
|
215
|
-
* @returns An object containing the separated `keys` and `modifiers`.
|
|
216
|
-
*/
|
|
217
|
-
export declare function parseKeys(inputKeys: string | string[]): {
|
|
218
|
-
keys: string[];
|
|
219
|
-
modifiers: string[];
|
|
220
|
-
};
|
|
221
|
-
/**
|
|
222
|
-
* Controller factory function which creates a {@link KeyBindingController} instance and attaches it to the provided host.
|
|
121
|
+
* Creates a {@link KeyBindingController}, and adds it to the given host.
|
|
223
122
|
*
|
|
224
|
-
* @param element - The host element
|
|
225
|
-
* @param options -
|
|
226
|
-
* @returns The
|
|
123
|
+
* @param element - The host element of the controller.
|
|
124
|
+
* @param options - The configuration of the controller.
|
|
125
|
+
* @returns The new controller.
|
|
227
126
|
*
|
|
228
127
|
* @example
|
|
229
128
|
* ```ts
|
|
230
129
|
* class MyComponent extends LitElement {
|
|
130
|
+
* // `skip` ignores the key presses that come from these elements.
|
|
131
|
+
* // `bindingDefaults` applies to each binding of the controller.
|
|
231
132
|
* private _keyBindings = addKeybindings(this, {
|
|
232
|
-
* skip: ['input', 'textarea'],
|
|
233
|
-
* bindingDefaults: { preventDefault: true },
|
|
133
|
+
* skip: ['input', 'textarea'],
|
|
134
|
+
* bindingDefaults: { preventDefault: true },
|
|
234
135
|
* });
|
|
235
136
|
*
|
|
236
137
|
* constructor() {
|
|
237
138
|
* super();
|
|
238
|
-
*
|
|
139
|
+
* // A combination is an array of key names, not one joined string.
|
|
140
|
+
* this._keyBindings.set([ctrlKey, 's'], this._handleSave);
|
|
239
141
|
* }
|
|
142
|
+
* }
|
|
240
143
|
* ```
|
|
241
144
|
*/
|
|
242
145
|
export declare function addKeybindings(element: ReactiveControllerHost & Element, options?: KeyBindingControllerOptions): KeyBindingController;
|
|
@@ -1,24 +1,10 @@
|
|
|
1
1
|
import { createAbortHandle } from '../abort-handler.js';
|
|
2
2
|
import { asArray, partition } from '../utils/arrays.js';
|
|
3
3
|
import { isElement } from '../utils/dom.js';
|
|
4
|
-
import { toMerged } from '../utils/objects.js';
|
|
5
4
|
import { isFunction } from '../utils/types.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export
|
|
9
|
-
export const arrowDown = 'ArrowDown';
|
|
10
|
-
export const enterKey = 'Enter';
|
|
11
|
-
export const spaceBar = ' ';
|
|
12
|
-
export const escapeKey = 'Escape';
|
|
13
|
-
export const homeKey = 'Home';
|
|
14
|
-
export const endKey = 'End';
|
|
15
|
-
export const pageUpKey = 'PageUp';
|
|
16
|
-
export const pageDownKey = 'PageDown';
|
|
17
|
-
export const tabKey = 'Tab';
|
|
18
|
-
export const altKey = 'Alt';
|
|
19
|
-
export const ctrlKey = 'Control';
|
|
20
|
-
export const metaKey = 'Meta';
|
|
21
|
-
export const shiftKey = 'Shift';
|
|
5
|
+
import { addHostListeners } from './host-listeners.js';
|
|
6
|
+
import { enterKey, spaceBar } from './keys.js';
|
|
7
|
+
export * from './keys.js';
|
|
22
8
|
const MODIFIER_ENTRIES = [
|
|
23
9
|
['alt', 'altKey'],
|
|
24
10
|
['control', 'ctrlKey'],
|
|
@@ -28,17 +14,9 @@ const MODIFIER_ENTRIES = [
|
|
|
28
14
|
const ALL_MODIFIER_VALUES = MODIFIER_ENTRIES.map(([name]) => name);
|
|
29
15
|
const MODIFIERS = new Set(ALL_MODIFIER_VALUES);
|
|
30
16
|
export const MODIFIER_EVENT_KEYS = Object.fromEntries(MODIFIER_ENTRIES);
|
|
31
|
-
function
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
export function isKey(event, key) {
|
|
35
|
-
return event.key.toLowerCase() === key.toLowerCase();
|
|
36
|
-
}
|
|
37
|
-
function isKeydown(event) {
|
|
38
|
-
return event.type === 'keydown';
|
|
39
|
-
}
|
|
40
|
-
function isKeyup(event) {
|
|
41
|
-
return event.type === 'keyup';
|
|
17
|
+
export function parseKeys(inputKeys) {
|
|
18
|
+
const [modifiers, keys] = partition(asArray(inputKeys).map((key) => key.toLowerCase()), (key) => MODIFIERS.has(key));
|
|
19
|
+
return { keys, modifiers };
|
|
42
20
|
}
|
|
43
21
|
function sortModifiers(modifiers) {
|
|
44
22
|
return ALL_MODIFIER_VALUES.filter((mod) => modifiers.includes(mod));
|
|
@@ -52,9 +30,18 @@ function getActiveModifiers(event) {
|
|
|
52
30
|
}
|
|
53
31
|
return active;
|
|
54
32
|
}
|
|
33
|
+
function hasModifiers(event) {
|
|
34
|
+
return event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
|
|
35
|
+
}
|
|
55
36
|
function createCombinationKey(keys, modifiers) {
|
|
56
37
|
return modifiers.concat(keys.length > 1 ? keys.toSorted() : keys).join('+');
|
|
57
38
|
}
|
|
39
|
+
function isKeydown(event) {
|
|
40
|
+
return event.type === 'keydown';
|
|
41
|
+
}
|
|
42
|
+
function isKeyup(event) {
|
|
43
|
+
return event.type === 'keyup';
|
|
44
|
+
}
|
|
58
45
|
class KeyBindingController {
|
|
59
46
|
static { this._defaultOptions = {
|
|
60
47
|
skip: ['input', 'textarea', 'select'],
|
|
@@ -67,17 +54,29 @@ class KeyBindingController {
|
|
|
67
54
|
return this._ref?.value || this._host;
|
|
68
55
|
}
|
|
69
56
|
constructor(host, options) {
|
|
70
|
-
this._abortHandle = createAbortHandle();
|
|
71
57
|
this._bindings = new Map();
|
|
72
58
|
this._allowedKeys = new Set();
|
|
73
59
|
this._pressedKeys = new Set();
|
|
60
|
+
const defaults = KeyBindingController._defaultOptions;
|
|
61
|
+
const skip = options?.skip ?? defaults.skip;
|
|
74
62
|
this._host = host;
|
|
75
63
|
this._ref = options?.ref;
|
|
76
|
-
this.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
|
|
64
|
+
this._bindingDefaults = {
|
|
65
|
+
...defaults.bindingDefaults,
|
|
66
|
+
...options?.bindingDefaults,
|
|
67
|
+
};
|
|
68
|
+
if (isFunction(skip)) {
|
|
69
|
+
this._skipCallback = skip;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
this._skipSelector = skip.join(',');
|
|
73
|
+
}
|
|
74
|
+
addHostListeners(host, { events: ['keyup', 'keydown'], listener: this });
|
|
75
|
+
addHostListeners(host, {
|
|
76
|
+
target: globalThis,
|
|
77
|
+
events: ['blur'],
|
|
78
|
+
listener: this,
|
|
79
|
+
});
|
|
81
80
|
}
|
|
82
81
|
_applyEventModifiers(binding, event) {
|
|
83
82
|
if (binding.options?.preventDefault) {
|
|
@@ -101,29 +100,28 @@ class KeyBindingController {
|
|
|
101
100
|
if (!this._allowedKeys.has(key)) {
|
|
102
101
|
return true;
|
|
103
102
|
}
|
|
104
|
-
const path = event.composedPath();
|
|
105
103
|
const element = this._element;
|
|
106
|
-
if (!path.some((node) => node === element)) {
|
|
107
|
-
return true;
|
|
108
|
-
}
|
|
109
104
|
const selector = this._skipSelector;
|
|
110
|
-
|
|
111
|
-
|
|
105
|
+
const needsContainmentCheck = element !== this._host;
|
|
106
|
+
if (needsContainmentCheck || selector) {
|
|
107
|
+
let reachedElement = false;
|
|
108
|
+
for (const node of event.composedPath()) {
|
|
109
|
+
if (node === element) {
|
|
110
|
+
reachedElement = true;
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
if (selector && isElement(node) && node.matches(selector)) {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (needsContainmentCheck && !reachedElement) {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
112
120
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
? skip.call(this._host, event.target, event)
|
|
121
|
+
return this._skipCallback
|
|
122
|
+
? this._skipCallback.call(this._host, event.target, event)
|
|
116
123
|
: false;
|
|
117
124
|
}
|
|
118
|
-
hostConnected() {
|
|
119
|
-
const { signal } = this._abortHandle;
|
|
120
|
-
this._host.addEventListener('keyup', this, { signal });
|
|
121
|
-
this._host.addEventListener('keydown', this, { signal });
|
|
122
|
-
globalThis.addEventListener('blur', this, { signal });
|
|
123
|
-
}
|
|
124
|
-
hostDisconnected() {
|
|
125
|
-
this._abortHandle.abort();
|
|
126
|
-
}
|
|
127
125
|
_handleGlobalBlur() {
|
|
128
126
|
this._pressedKeys.clear();
|
|
129
127
|
}
|
|
@@ -139,11 +137,17 @@ class KeyBindingController {
|
|
|
139
137
|
if (!isModifier) {
|
|
140
138
|
this._pressedKeys.add(key);
|
|
141
139
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
140
|
+
let binding;
|
|
141
|
+
if (!isModifier && !hasModifiers(event) && this._pressedKeys.size === 1) {
|
|
142
|
+
binding = this._bindings.get(key);
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
const activeModifiers = getActiveModifiers(event);
|
|
146
|
+
const combination = createCombinationKey(Array.from(this._pressedKeys), activeModifiers);
|
|
147
|
+
binding = this._bindings.get(combination);
|
|
148
|
+
if (!binding && this._pressedKeys.size > 1) {
|
|
149
|
+
binding = this._bindings.get(createCombinationKey([key], activeModifiers));
|
|
150
|
+
}
|
|
147
151
|
}
|
|
148
152
|
if (binding && this._bindingMatches(binding, event)) {
|
|
149
153
|
this._applyEventModifiers(binding, event);
|
|
@@ -167,11 +171,11 @@ class KeyBindingController {
|
|
|
167
171
|
set(key, handler, bindingOptions) {
|
|
168
172
|
const { keys, modifiers } = parseKeys(key);
|
|
169
173
|
const combination = createCombinationKey(keys, sortModifiers(modifiers));
|
|
170
|
-
const options =
|
|
174
|
+
const options = { ...this._bindingDefaults, ...bindingOptions };
|
|
171
175
|
for (const each of [...keys, ...modifiers]) {
|
|
172
176
|
this._allowedKeys.add(each);
|
|
173
177
|
}
|
|
174
|
-
this._bindings.set(combination, {
|
|
178
|
+
this._bindings.set(combination, { handler, options });
|
|
175
179
|
return this;
|
|
176
180
|
}
|
|
177
181
|
setActivateHandler(handler, options) {
|
|
@@ -180,13 +184,14 @@ class KeyBindingController {
|
|
|
180
184
|
return this;
|
|
181
185
|
}
|
|
182
186
|
observeElement(element) {
|
|
183
|
-
|
|
184
|
-
|
|
187
|
+
const handle = createAbortHandle();
|
|
188
|
+
const { signal } = handle;
|
|
189
|
+
element.addEventListener('keydown', this, { signal });
|
|
190
|
+
element.addEventListener('keyup', this, { signal });
|
|
185
191
|
this._observedElement = element;
|
|
186
192
|
return {
|
|
187
193
|
unsubscribe: () => {
|
|
188
|
-
|
|
189
|
-
element.removeEventListener('keyup', this);
|
|
194
|
+
handle.abort();
|
|
190
195
|
if (this._observedElement === element) {
|
|
191
196
|
this._observedElement = undefined;
|
|
192
197
|
}
|
|
@@ -194,10 +199,6 @@ class KeyBindingController {
|
|
|
194
199
|
};
|
|
195
200
|
}
|
|
196
201
|
}
|
|
197
|
-
export function parseKeys(inputKeys) {
|
|
198
|
-
const [modifiers, keys] = partition(normalizeKeys(inputKeys), (key) => MODIFIERS.has(key));
|
|
199
|
-
return { keys, modifiers };
|
|
200
|
-
}
|
|
201
202
|
export function addKeybindings(element, options) {
|
|
202
203
|
return new KeyBindingController(element, options);
|
|
203
204
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"key-bindings.js","sourceRoot":"","sources":["../../../src/internals/controllers/key-bindings.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController, ReactiveControllerHost } from 'lit';\nimport type { Ref } from 'lit/directives/ref.js';\nimport { createAbortHandle } from '../abort-handler.js';\nimport { asArray, partition } from '../utils/arrays.js';\nimport { isElement } from '../utils/dom.js';\nimport { toMerged } from '../utils/objects.js';\nimport { isFunction } from '../utils/types.js';\n\n//#region Keys and modifiers\n\n/* Common keys */\nexport const arrowLeft = 'ArrowLeft' as const;\nexport const arrowRight = 'ArrowRight' as const;\nexport const arrowUp = 'ArrowUp' as const;\nexport const arrowDown = 'ArrowDown' as const;\nexport const enterKey = 'Enter' as const;\nexport const spaceBar = ' ' as const;\nexport const escapeKey = 'Escape' as const;\nexport const homeKey = 'Home' as const;\nexport const endKey = 'End' as const;\nexport const pageUpKey = 'PageUp' as const;\nexport const pageDownKey = 'PageDown' as const;\nexport const tabKey = 'Tab' as const;\n\n/* Modifiers */\nexport const altKey = 'Alt' as const;\nexport const ctrlKey = 'Control' as const;\nexport const metaKey = 'Meta' as const;\nexport const shiftKey = 'Shift' as const;\n\n//#endregion\n\n//#region Types\n\n/* Types */\ntype KeyBindingHandler = (event: KeyboardEvent) => void;\ntype KeyBindingObserverCleanup = { unsubscribe: () => void };\n\n/**\n * Whether the current event should be ignored by the controller.\n *\n * @param node - The event target\n * @param event - The event object\n *\n * When `true` is returned, the current event is ignored.\n */\ntype KeyBindingSkipCallback = (node: Element, event: KeyboardEvent) => boolean;\n\n/**\n * The event type which will trigger the bound handler.\n */\ntype KeyBindingTrigger = 'keydown' | 'keyup';\n\n/**\n * Configuration object for the controller.\n * @hidden\n */\ninterface KeyBindingControllerOptions {\n /**\n * By default, the controller listens for keypress events in the context of the host element.\n * If you pass a `ref`, you can limit the observation to a certain DOM part of the host scope.\n */\n ref?: Ref;\n /**\n * Option to ignore key press events.\n *\n * If passed an array of CSS selectors, it will ignore key presses originating from elements in the event composed path\n * that match one of the selectors.\n * Otherwise you can pass a {@link KeyBindingSkipCallback} function.\n *\n * Defaults to `['input', 'textarea', 'select']`.\n *\n * @example\n * ```ts\n * {\n * // Skip events originating from elements with `readonly` attribute\n * skip: ['[readonly]']\n * }\n * ...\n * {\n * // Same as above but with a callback\n * skip: (node: Element) => node.hasAttribute('readonly')\n * }\n * ```\n */\n skip?: string[] | KeyBindingSkipCallback;\n /**\n * A set of KeyBindingOptions configuration which is applied to every handler\n * that is added to the controller.\n *\n * Any additional KeyBindingOptions values passed when `set` is called\n * will be merged with `bindingDefaults`.\n */\n bindingDefaults?: KeyBindingOptions;\n}\n\n/**\n * Configuration object for customizing the behavior of\n * the registered handler.\n */\ninterface KeyBindingOptions {\n /**\n * The event type(s) on which the handler will be invoked.\n *\n * Defaults to `keydown` if not set.\n */\n triggers?: KeyBindingTrigger[];\n /**\n * Whether the handler should fire on auto-repeated keydown events (i.e. when a key is held down).\n *\n * Defaults to `false`.\n */\n repeat?: boolean;\n /**\n * Whether to call `preventDefault` on the target event before the handler is invoked.\n */\n preventDefault?: boolean;\n /**\n * Whether to call `stopPropagation` on the target event before the handler is invoked.\n */\n stopPropagation?: boolean;\n}\n\n/** @hidden */\ninterface KeyBinding {\n keys: string[];\n handler: KeyBindingHandler;\n options?: KeyBindingOptions;\n modifiers: string[];\n}\n\n//#endregion\n\n//#region Internal functions and constants\n\n/**\n * Every modifier, paired with the `KeyboardEvent` boolean property it is read\n * from - `ctrlKey` is the property for the `'control'` modifier, not `'controlKey'`.\n *\n * Kept in alphabetical order: combination keys sort their modifiers, and every\n * derived collection below inherits that order for free.\n */\nconst MODIFIER_ENTRIES = [\n ['alt', 'altKey'],\n ['control', 'ctrlKey'],\n ['meta', 'metaKey'],\n ['shift', 'shiftKey'],\n] as const satisfies ReadonlyArray<readonly [string, keyof KeyboardEvent]>;\n\nconst ALL_MODIFIER_VALUES = MODIFIER_ENTRIES.map(([name]) => name);\nconst MODIFIERS = new Set<string>(ALL_MODIFIER_VALUES);\n\n/** {@link MODIFIER_ENTRIES} as a lookup of modifier name to event property. */\nexport const MODIFIER_EVENT_KEYS: Record<string, string> =\n Object.fromEntries(MODIFIER_ENTRIES);\n\nfunction normalizeKeys(keys: string | string[]): string[] {\n return asArray(keys).map((key) => key.toLowerCase());\n}\n\n/**\n * Whether the event's key matches `key`, case-insensitively. Prefer this over\n * comparing `event.key` directly - the key names of this module are lowercase,\n * while real events carry the canonical casing (e.g. `Enter`).\n */\nexport function isKey(event: KeyboardEvent, key: string): boolean {\n return event.key.toLowerCase() === key.toLowerCase();\n}\n\nfunction isKeydown(event: Event): boolean {\n return event.type === 'keydown';\n}\n\nfunction isKeyup(event: Event): boolean {\n return event.type === 'keyup';\n}\n\n/** Sorts `modifiers` alphabetically, by filtering the already sorted source. */\nfunction sortModifiers(modifiers: string[]): string[] {\n return ALL_MODIFIER_VALUES.filter((mod) => modifiers.includes(mod));\n}\n\n/** Returns the modifiers active for `event`, already sorted. */\nfunction getActiveModifiers(event: KeyboardEvent): string[] {\n const active: string[] = [];\n\n for (const [name, property] of MODIFIER_ENTRIES) {\n if (event[property]) {\n active.push(name);\n }\n }\n\n return active;\n}\n\n/**\n * Creates a normalized combination key string from the provided keys and modifiers.\n *\n * The combination key is a string that uniquely identifies a specific combination of keys and modifiers.\n * It is created by sorting the keys and modifiers alphabetically and joining them with a '+' separator.\n *\n * `modifiers` must already be sorted - see {@link sortModifiers} and {@link getActiveModifiers}.\n */\nfunction createCombinationKey(keys: string[], modifiers: string[]): string {\n return modifiers.concat(keys.length > 1 ? keys.toSorted() : keys).join('+');\n}\n\n//#endregion\n\n/**\n * A controller for managing key bindings on a host element. It allows you to register handlers for specific key combinations,\n * with support for modifier keys and event options such as `preventDefault` and `stopPropagation`.\n *\n * The controller listens for keyboard events on the host element (or an optionally specified element) and invokes the appropriate handlers\n * when the registered key combinations are detected.\n * @hidden\n */\nclass KeyBindingController implements ReactiveController {\n //#region Private properties and state\n\n private static readonly _defaultOptions: KeyBindingControllerOptions = {\n skip: ['input', 'textarea', 'select'],\n bindingDefaults: { preventDefault: true },\n };\n\n private readonly _host: ReactiveControllerHost & Element;\n private readonly _ref?: Ref;\n private readonly _abortHandle = createAbortHandle();\n\n private readonly _bindings = new Map<string, KeyBinding>();\n private readonly _allowedKeys = new Set<string>();\n private readonly _pressedKeys = new Set<string>();\n\n private readonly _options: KeyBindingControllerOptions;\n private readonly _skipSelector: string | undefined;\n\n private _observedElement?: Element;\n\n private get _element(): Element {\n if (this._observedElement) {\n return this._observedElement;\n }\n return this._ref?.value || this._host;\n }\n\n //#endregion\n\n constructor(\n host: ReactiveControllerHost & Element,\n options?: KeyBindingControllerOptions\n ) {\n this._host = host;\n this._ref = options?.ref;\n this._options = toMerged(\n KeyBindingController._defaultOptions,\n options ?? {}\n );\n\n if (Array.isArray(this._options.skip)) {\n this._skipSelector = this._options.skip.join(',');\n }\n\n host.addController(this);\n }\n\n //#region Private API\n\n /**\n * Applies the event modifiers specified in the binding options to the provided keyboard event.\n * If `preventDefault` is set, it calls `event.preventDefault()`.\n * If `stopPropagation` is set, it calls `event.stopPropagation()`.\n */\n private _applyEventModifiers(\n binding: KeyBinding,\n event: KeyboardEvent\n ): void {\n if (binding.options?.preventDefault) {\n event.preventDefault();\n }\n\n if (binding.options?.stopPropagation) {\n event.stopPropagation();\n }\n }\n\n /**\n * Determines whether the provided keyboard event matches the specified key binding,\n * taking into account the event type and the binding's trigger options.\n */\n private _bindingMatches(binding: KeyBinding, event: KeyboardEvent): boolean {\n const triggers = binding.options?.triggers ?? ['keydown'];\n\n if (isKeydown(event) && triggers.includes('keydown')) {\n return !event.repeat || Boolean(binding.options?.repeat);\n }\n\n if (isKeyup(event) && triggers.includes('keyup')) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Determines whether the provided event should be ignored based on the controller's configuration and the event's context.\n * The method checks if the event's key is among the allowed keys, if the event originated from within the controller's scope,\n * and if it matches any of the skip conditions defined in the controller's options.\n */\n private _shouldSkip(event: KeyboardEvent, key: string): boolean {\n if (!this._allowedKeys.has(key)) {\n return true;\n }\n\n const path = event.composedPath();\n const element = this._element;\n\n if (!path.some((node) => node === element)) {\n return true;\n }\n\n const selector = this._skipSelector;\n\n if (selector) {\n return path.some((node) => isElement(node) && node.matches(selector));\n }\n\n const skip = this._options.skip;\n\n return isFunction(skip)\n ? skip.call(this._host, event.target as Element, event)\n : false;\n }\n\n //#endregion\n\n //#region Controller lifecycle\n\n /** @internal */\n public hostConnected(): void {\n const { signal } = this._abortHandle;\n this._host.addEventListener('keyup', this, { signal });\n this._host.addEventListener('keydown', this, { signal });\n globalThis.addEventListener('blur', this, { signal });\n }\n\n /** @internal */\n public hostDisconnected(): void {\n this._abortHandle.abort();\n }\n\n //#endregion\n\n //#region Event handling\n\n /**\n * Handles the global blur event to clear the internal state of pressed keys.\n *\n * This is necessary to prevent \"stuck\" keys when the user switches to another application\n * or tab while holding down a key.\n */\n private _handleGlobalBlur(): void {\n this._pressedKeys.clear();\n }\n\n /**\n * Handles keyboard events on the observed element.\n *\n * It checks if the event should be skipped based on the controller's configuration,\n * and if not, it determines if there is a registered handler for the combination of pressed keys and active modifiers.\n *\n * If a matching handler is found, it applies the specified event modifiers and invokes the handler.\n * It also manages the internal state of currently pressed keys to accurately detect key combinations.\n *\n */\n private _handleKeyEvent(event: KeyboardEvent): void {\n const key = event.key.toLowerCase();\n const isModifier = MODIFIERS.has(key);\n\n if (this._shouldSkip(event, key)) {\n // Always clean up on keyup regardless of whether the event is otherwise skipped.\n if (!isModifier && isKeyup(event)) {\n this._pressedKeys.delete(key);\n }\n return;\n }\n\n if (!isModifier) {\n this._pressedKeys.add(key);\n }\n\n const activeModifiers = getActiveModifiers(event);\n\n const combination = createCombinationKey(\n Array.from(this._pressedKeys),\n activeModifiers\n );\n let binding = this._bindings.get(combination);\n\n // When multiple non-modifier keys are simultaneously in _pressedKeys (due to overlapping\n // key presses, e.g. pressing ArrowUp before ArrowDown's keyup fires), the full combination\n // won't match any single-key binding. Fall back to just the current key + modifiers so that\n // single-key bindings continue to fire even when other keys are still \"held\".\n if (!binding && this._pressedKeys.size > 1) {\n binding = this._bindings.get(\n createCombinationKey([key], activeModifiers)\n );\n }\n\n if (binding && this._bindingMatches(binding, event)) {\n this._applyEventModifiers(binding, event);\n binding.handler.call(this._host, event);\n }\n\n if (!isModifier && isKeyup(event)) {\n this._pressedKeys.delete(key);\n }\n }\n\n /** @internal */\n public handleEvent(event: KeyboardEvent | FocusEvent): void {\n switch (event.type) {\n case 'keydown':\n case 'keyup':\n this._handleKeyEvent(event as KeyboardEvent);\n break;\n case 'blur':\n this._handleGlobalBlur();\n break;\n }\n }\n\n //#endregion\n\n //#region Public API\n\n /**\n * Registers a key binding with the specified key(s), handler function, and optional configuration.\n *\n * The `key` parameter can be a single key or an array of keys, and can include modifier keys (e.g., 'ctrl+s', ['shift', 'a']).\n * The `handler` is a function that will be called when the specified key combination is detected.\n * The `bindingOptions` allow you to customize the behavior of the binding, such as which event types trigger the handler,\n * whether it should fire on auto-repeated keydown events, and whether to call `preventDefault` or `stopPropagation`.\n *\n * The method returns the controller instance to allow for method chaining.\n */\n public set(\n key: string | string[],\n handler: KeyBindingHandler,\n bindingOptions?: KeyBindingOptions\n ): this {\n const { keys, modifiers } = parseKeys(key);\n const combination = createCombinationKey(keys, sortModifiers(modifiers));\n const options = toMerged(\n this._options.bindingDefaults!,\n bindingOptions ?? {}\n );\n\n for (const each of [...keys, ...modifiers]) {\n this._allowedKeys.add(each);\n }\n\n this._bindings.set(combination, { keys, handler, options, modifiers });\n\n return this;\n }\n\n /**\n * Registers the provided handler function to be called when either the Enter key or Space bar is pressed.\n *\n * This is a common pattern for activating buttons or interactive elements, and this method provides a convenient way to set up such bindings.\n *\n * The method accepts optional `KeyBindingOptions` which are applied to both the Enter key and Space bar bindings.\n * It returns the controller instance to allow for method chaining.\n *\n */\n public setActivateHandler(\n handler: KeyBindingHandler,\n options?: KeyBindingOptions\n ): this {\n this.set(enterKey, handler, options);\n this.set(spaceBar, handler, options);\n\n return this;\n }\n\n /**\n * Sets the controller to listen for keyboard events on an arbitrary `element` in the page context.\n * All the configuration and event handlers are applied as well.\n *\n * Returns an object with an `unsubscribe` function which should be called when the observing of keyboard\n * events on the `element` should cease.\n */\n public observeElement(element: Element): KeyBindingObserverCleanup {\n element.addEventListener('keydown', this);\n element.addEventListener('keyup', this);\n this._observedElement = element;\n\n return {\n unsubscribe: () => {\n element.removeEventListener('keydown', this);\n element.removeEventListener('keyup', this);\n if (this._observedElement === element) {\n this._observedElement = undefined;\n }\n },\n };\n }\n\n //#endregion\n}\n\n/**\n * Parses the provided key(s) and separates them into modifiers and regular keys.\n *\n * Modifiers are keys like Alt, Ctrl, Meta and Shift which modify the behavior of other keys when pressed in combination.\n * Regular keys are all other keys which trigger the bound handler when pressed.\n *\n * The returned `keys` and `modifiers` are normalized to lowercase for consistency.\n *\n * @internal\n *\n * @param inputKeys - The key or keys to parse, provided as a string or an array of strings.\n * @returns An object containing the separated `keys` and `modifiers`.\n */\nexport function parseKeys(inputKeys: string | string[]): {\n keys: string[];\n modifiers: string[];\n} {\n const [modifiers, keys] = partition(normalizeKeys(inputKeys), (key) =>\n MODIFIERS.has(key)\n );\n return { keys, modifiers };\n}\n\n/**\n * Controller factory function which creates a {@link KeyBindingController} instance and attaches it to the provided host.\n *\n * @param element - The host element to which the controller will be attached.\n * @param options - Optional configuration for the controller.\n * @returns The created {@link KeyBindingController} instance.\n *\n * @example\n * ```ts\n * class MyComponent extends LitElement {\n * private _keyBindings = addKeybindings(this, {\n * skip: ['input', 'textarea'], // Optional: Skip key events originating from these elements\n * bindingDefaults: { preventDefault: true }, // Optional: Default options for all bindings\n * });\n *\n * constructor() {\n * super();\n * this._keyBindings.set('ctrl+s', this._handleSave); // Register a key binding\n * }\n * ```\n */\nexport function addKeybindings(\n element: ReactiveControllerHost & Element,\n options?: KeyBindingControllerOptions\n): KeyBindingController {\n return new KeyBindingController(element, options);\n}\n\nexport type {\n KeyBindingController,\n KeyBindingControllerOptions,\n KeyBindingHandler,\n KeyBindingObserverCleanup,\n KeyBindingOptions,\n KeyBindingSkipCallback,\n KeyBindingTrigger,\n};\n"]}
|
|
1
|
+
{"version":3,"file":"key-bindings.js","sourceRoot":"","sources":["../../../src/internals/controllers/key-bindings.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveControllerHost } from 'lit';\nimport type { Ref } from 'lit/directives/ref.js';\nimport { createAbortHandle } from '../abort-handler.js';\nimport { asArray, partition } from '../utils/arrays.js';\nimport { isElement } from '../utils/dom.js';\nimport { isFunction } from '../utils/types.js';\nimport { addHostListeners } from './host-listeners.js';\nimport { enterKey, spaceBar } from './keys.js';\n\n// Re-exported from `./keys.js`, so a consumer keeps a single import.\nexport * from './keys.js';\n\n//#region Modifiers and combination keys\n\n/**\n * Each modifier and the `KeyboardEvent` property it reads; `control` maps to\n * `ctrlKey`. The alphabetical order is what a combination key inherits.\n */\nconst MODIFIER_ENTRIES = [\n ['alt', 'altKey'],\n ['control', 'ctrlKey'],\n ['meta', 'metaKey'],\n ['shift', 'shiftKey'],\n] as const satisfies ReadonlyArray<readonly [string, keyof KeyboardEvent]>;\n\nconst ALL_MODIFIER_VALUES = MODIFIER_ENTRIES.map(([name]) => name);\nconst MODIFIERS = new Set<string>(ALL_MODIFIER_VALUES);\n\n/**\n * {@link MODIFIER_ENTRIES} as a name to event property lookup.\n * @internal Used by the keyboard simulation helper of the test suite.\n */\nexport const MODIFIER_EVENT_KEYS: Record<string, string> =\n Object.fromEntries(MODIFIER_ENTRIES);\n\n/**\n * Splits the keys into modifiers (Alt, Control, Meta, Shift) and normal keys,\n * in lower case.\n *\n * @internal\n */\nexport function parseKeys(inputKeys: string | string[]): {\n keys: string[];\n modifiers: string[];\n} {\n const [modifiers, keys] = partition(\n asArray(inputKeys).map((key) => key.toLowerCase()),\n (key) => MODIFIERS.has(key)\n );\n return { keys, modifiers };\n}\n\n/** Sorts `modifiers` alphabetically. */\nfunction sortModifiers(modifiers: string[]): string[] {\n return ALL_MODIFIER_VALUES.filter((mod) => modifiers.includes(mod));\n}\n\n/** Returns the modifiers active for `event`, already sorted. */\nfunction getActiveModifiers(event: KeyboardEvent): string[] {\n const active: string[] = [];\n\n for (const [name, property] of MODIFIER_ENTRIES) {\n if (event[property]) {\n active.push(name);\n }\n }\n\n return active;\n}\n\n/** Whether `event` carries at least one active modifier. */\nfunction hasModifiers(event: KeyboardEvent): boolean {\n return event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;\n}\n\n/**\n * Joins keys and modifiers into a `+` separated combination key, sorted\n * alphabetically. `modifiers` must already be sorted; see\n * {@link sortModifiers} and {@link getActiveModifiers}.\n */\nfunction createCombinationKey(keys: string[], modifiers: string[]): string {\n return modifiers.concat(keys.length > 1 ? keys.toSorted() : keys).join('+');\n}\n\n//#endregion\n\n//#region Types\n\ntype KeyBindingHandler = (event: KeyboardEvent) => void;\ntype KeyBindingObserverCleanup = { unsubscribe: () => void };\n\n/**\n * Whether the controller must ignore the current event.\n *\n * @param node - The target of the event.\n * @param event - The event.\n */\ntype KeyBindingSkipCallback = (node: Element, event: KeyboardEvent) => boolean;\n\n/** The event type that starts the bound handler. */\ntype KeyBindingTrigger = 'keydown' | 'keyup';\n\n/** @hidden */\ninterface KeyBindingControllerOptions {\n /** The element to observe. Defaults to the host element. */\n ref?: Ref;\n /**\n * The key presses that the controller ignores. CSS selectors match against\n * the composed path of the event; a {@link KeyBindingSkipCallback} decides\n * per event instead. Defaults to `['input', 'textarea', 'select']`.\n *\n * @example\n * ```ts\n * {\n * // Skip events originating from elements with `readonly` attribute\n * skip: ['[readonly]']\n * }\n * ...\n * {\n * // Same as above but with a callback\n * skip: (node: Element) => node.hasAttribute('readonly')\n * }\n * ```\n */\n skip?: string[] | KeyBindingSkipCallback;\n /** Default options for every binding. A `set` call merges over them. */\n bindingDefaults?: KeyBindingOptions;\n}\n\ninterface KeyBindingOptions {\n /** The event types that start the handler. Defaults to `keydown`. */\n triggers?: KeyBindingTrigger[];\n /** Whether the handler runs for a repeated keydown. Defaults to `false`. */\n repeat?: boolean;\n /** Whether to call `preventDefault` before the handler runs. */\n preventDefault?: boolean;\n /** Whether to call `stopPropagation` before the handler runs. */\n stopPropagation?: boolean;\n}\n\n/** A registered binding. The key of the binding map holds the combination. */\ninterface KeyBinding {\n handler: KeyBindingHandler;\n options?: KeyBindingOptions;\n}\n\n//#endregion\n\n//#region Internal functions and constants\n\nfunction isKeydown(event: Event): boolean {\n return event.type === 'keydown';\n}\n\nfunction isKeyup(event: Event): boolean {\n return event.type === 'keyup';\n}\n\n//#endregion\n\n/**\n * Manages the key bindings of a host element.\n * @hidden\n */\nclass KeyBindingController {\n //#region Private properties and state\n\n /** Base configuration, shared between instances. Never written to. */\n private static readonly _defaultOptions = {\n skip: ['input', 'textarea', 'select'],\n bindingDefaults: { preventDefault: true },\n } satisfies KeyBindingControllerOptions;\n\n private readonly _host: ReactiveControllerHost & Element;\n private readonly _ref?: Ref;\n\n private readonly _bindings = new Map<string, KeyBinding>();\n private readonly _allowedKeys = new Set<string>();\n private readonly _pressedKeys = new Set<string>();\n\n private readonly _bindingDefaults: KeyBindingOptions;\n private readonly _skipSelector?: string;\n private readonly _skipCallback?: KeyBindingSkipCallback;\n\n private _observedElement?: Element;\n\n private get _element(): Element {\n if (this._observedElement) {\n return this._observedElement;\n }\n return this._ref?.value || this._host;\n }\n\n //#endregion\n\n constructor(\n host: ReactiveControllerHost & Element,\n options?: KeyBindingControllerOptions\n ) {\n const defaults = KeyBindingController._defaultOptions;\n const skip = options?.skip ?? defaults.skip;\n\n this._host = host;\n this._ref = options?.ref;\n\n // Host options merge over the defaults instead of replacing them.\n this._bindingDefaults = {\n ...defaults.bindingDefaults,\n ...options?.bindingDefaults,\n };\n\n if (isFunction(skip)) {\n this._skipCallback = skip;\n } else {\n this._skipSelector = skip.join(',');\n }\n\n addHostListeners(host, { events: ['keyup', 'keydown'], listener: this });\n addHostListeners(host, {\n target: globalThis,\n events: ['blur'],\n listener: this,\n });\n }\n\n //#region Private API\n\n /** Applies the event options of the binding to the keyboard event. */\n private _applyEventModifiers(\n binding: KeyBinding,\n event: KeyboardEvent\n ): void {\n if (binding.options?.preventDefault) {\n event.preventDefault();\n }\n\n if (binding.options?.stopPropagation) {\n event.stopPropagation();\n }\n }\n\n /** Whether the event type matches the triggers of the binding. */\n private _bindingMatches(binding: KeyBinding, event: KeyboardEvent): boolean {\n const triggers = binding.options?.triggers ?? ['keydown'];\n\n if (isKeydown(event) && triggers.includes('keydown')) {\n return !event.repeat || Boolean(binding.options?.repeat);\n }\n\n if (isKeyup(event) && triggers.includes('keyup')) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Whether to ignore the event. The key has no binding, the event missed the\n * observed element, or the skip configuration agrees.\n */\n private _shouldSkip(event: KeyboardEvent, key: string): boolean {\n if (!this._allowedKeys.has(key)) {\n return true;\n }\n\n const element = this._element;\n const selector = this._skipSelector;\n\n // The host carries the listeners. Only a `ref` puts the observed element\n // deeper in the tree, where the path must confirm containment.\n const needsContainmentCheck = element !== this._host;\n\n if (needsContainmentCheck || selector) {\n // The path runs target first, so the scan stops at the observed element.\n let reachedElement = false;\n\n for (const node of event.composedPath()) {\n if (node === element) {\n reachedElement = true;\n break;\n }\n\n if (selector && isElement(node) && node.matches(selector)) {\n return true;\n }\n }\n\n if (needsContainmentCheck && !reachedElement) {\n return true;\n }\n }\n\n return this._skipCallback\n ? this._skipCallback.call(this._host, event.target as Element, event)\n : false;\n }\n\n //#endregion\n\n //#region Event handling\n\n /**\n * Clears the pressed keys on a global blur. No keyup arrives if the user\n * moves to a different application or tab with a key down.\n */\n private _handleGlobalBlur(): void {\n this._pressedKeys.clear();\n }\n\n /** Handles a keyboard event on the observed element. */\n private _handleKeyEvent(event: KeyboardEvent): void {\n const key = event.key.toLowerCase();\n const isModifier = MODIFIERS.has(key);\n\n if (this._shouldSkip(event, key)) {\n // A keyup always cleans up the key, also for an event that it skips.\n if (!isModifier && isKeyup(event)) {\n this._pressedKeys.delete(key);\n }\n return;\n }\n\n if (!isModifier) {\n this._pressedKeys.add(key);\n }\n\n let binding: KeyBinding | undefined;\n\n if (!isModifier && !hasModifiers(event) && this._pressedKeys.size === 1) {\n // Fast path: one key, no modifier. The combination is the key itself,\n // so the lookup builds no arrays or strings.\n binding = this._bindings.get(key);\n } else {\n const activeModifiers = getActiveModifiers(event);\n\n const combination = createCombinationKey(\n Array.from(this._pressedKeys),\n activeModifiers\n );\n binding = this._bindings.get(combination);\n\n // Overlapping presses leave several regular keys down, so the full\n // combination matches no single-key binding. Fall back to the current\n // key, so its binding still runs while another key stays down.\n if (!binding && this._pressedKeys.size > 1) {\n binding = this._bindings.get(\n createCombinationKey([key], activeModifiers)\n );\n }\n }\n\n if (binding && this._bindingMatches(binding, event)) {\n this._applyEventModifiers(binding, event);\n binding.handler.call(this._host, event);\n }\n\n if (!isModifier && isKeyup(event)) {\n this._pressedKeys.delete(key);\n }\n }\n\n /** @internal */\n public handleEvent(event: KeyboardEvent | FocusEvent): void {\n switch (event.type) {\n case 'keydown':\n case 'keyup':\n this._handleKeyEvent(event as KeyboardEvent);\n break;\n case 'blur':\n this._handleGlobalBlur();\n break;\n }\n }\n\n //#endregion\n\n //#region Public API\n\n /**\n * Registers a binding for a key or a combination, such as `['shift', 'a']`.\n * Returns the controller, for chaining.\n */\n public set(\n key: string | string[],\n handler: KeyBindingHandler,\n bindingOptions?: KeyBindingOptions\n ): this {\n const { keys, modifiers } = parseKeys(key);\n const combination = createCombinationKey(keys, sortModifiers(modifiers));\n const options = { ...this._bindingDefaults, ...bindingOptions };\n\n for (const each of [...keys, ...modifiers]) {\n this._allowedKeys.add(each);\n }\n\n this._bindings.set(combination, { handler, options });\n\n return this;\n }\n\n /**\n * Registers `handler` for both the Enter key and the Space bar. Returns the\n * controller, for chaining.\n */\n public setActivateHandler(\n handler: KeyBindingHandler,\n options?: KeyBindingOptions\n ): this {\n this.set(enterKey, handler, options);\n this.set(spaceBar, handler, options);\n\n return this;\n }\n\n /**\n * Listens for keyboard events on any page element, with the configuration\n * and the handlers of this controller. Call `unsubscribe` to stop.\n */\n public observeElement(element: Element): KeyBindingObserverCleanup {\n const handle = createAbortHandle();\n const { signal } = handle;\n\n element.addEventListener('keydown', this, { signal });\n element.addEventListener('keyup', this, { signal });\n this._observedElement = element;\n\n return {\n unsubscribe: () => {\n handle.abort();\n\n if (this._observedElement === element) {\n this._observedElement = undefined;\n }\n },\n };\n }\n\n //#endregion\n}\n\n/**\n * Creates a {@link KeyBindingController}, and adds it to the given host.\n *\n * @param element - The host element of the controller.\n * @param options - The configuration of the controller.\n * @returns The new controller.\n *\n * @example\n * ```ts\n * class MyComponent extends LitElement {\n * // `skip` ignores the key presses that come from these elements.\n * // `bindingDefaults` applies to each binding of the controller.\n * private _keyBindings = addKeybindings(this, {\n * skip: ['input', 'textarea'],\n * bindingDefaults: { preventDefault: true },\n * });\n *\n * constructor() {\n * super();\n * // A combination is an array of key names, not one joined string.\n * this._keyBindings.set([ctrlKey, 's'], this._handleSave);\n * }\n * }\n * ```\n */\nexport function addKeybindings(\n element: ReactiveControllerHost & Element,\n options?: KeyBindingControllerOptions\n): KeyBindingController {\n return new KeyBindingController(element, options);\n}\n\nexport type {\n KeyBindingController,\n KeyBindingControllerOptions,\n KeyBindingHandler,\n KeyBindingObserverCleanup,\n KeyBindingOptions,\n KeyBindingSkipCallback,\n KeyBindingTrigger,\n};\n"]}
|