@m3e/core 1.0.0-rc.1
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/LICENSE +22 -0
- package/NOTICE.md +8 -0
- package/README.md +59 -0
- package/cem.config.mjs +16 -0
- package/demo/index.html +58 -0
- package/dist/a11y.js +1431 -0
- package/dist/a11y.js.map +1 -0
- package/dist/a11y.min.js +87 -0
- package/dist/a11y.min.js.map +1 -0
- package/dist/anchoring.js +1748 -0
- package/dist/anchoring.js.map +1 -0
- package/dist/anchoring.min.js +7 -0
- package/dist/anchoring.min.js.map +1 -0
- package/dist/bidi.js +106 -0
- package/dist/bidi.js.map +1 -0
- package/dist/bidi.min.js +16 -0
- package/dist/bidi.min.js.map +1 -0
- package/dist/css-custom-data.json +257 -0
- package/dist/custom-elements.json +13504 -0
- package/dist/html-custom-data.json +199 -0
- package/dist/index.js +4342 -0
- package/dist/index.js.map +1 -0
- package/dist/index.min.js +520 -0
- package/dist/index.min.js.map +1 -0
- package/dist/layout.js +64 -0
- package/dist/layout.js.map +1 -0
- package/dist/layout.min.js +15 -0
- package/dist/layout.min.js.map +1 -0
- package/dist/platform.js +56 -0
- package/dist/platform.js.map +1 -0
- package/dist/platform.min.js +15 -0
- package/dist/platform.min.js.map +1 -0
- package/dist/src/a11y/AriaDescriber.d.ts +31 -0
- package/dist/src/a11y/AriaDescriber.d.ts.map +1 -0
- package/dist/src/a11y/FocusTrapElement.d.ts +25 -0
- package/dist/src/a11y/FocusTrapElement.d.ts.map +1 -0
- package/dist/src/a11y/InteractivityChecker.d.ts +22 -0
- package/dist/src/a11y/InteractivityChecker.d.ts.map +1 -0
- package/dist/src/a11y/LiveAnnouncer.d.ts +56 -0
- package/dist/src/a11y/LiveAnnouncer.d.ts.map +1 -0
- package/dist/src/a11y/aria-reference.d.ts +30 -0
- package/dist/src/a11y/aria-reference.d.ts.map +1 -0
- package/dist/src/a11y/index.d.ts +8 -0
- package/dist/src/a11y/index.d.ts.map +1 -0
- package/dist/src/a11y/keycodes/KeyCode.d.ts +118 -0
- package/dist/src/a11y/keycodes/KeyCode.d.ts.map +1 -0
- package/dist/src/a11y/keycodes/ModifierKeys.d.ts +5 -0
- package/dist/src/a11y/keycodes/ModifierKeys.d.ts.map +1 -0
- package/dist/src/a11y/keycodes/getKeyCode.d.ts +7 -0
- package/dist/src/a11y/keycodes/getKeyCode.d.ts.map +1 -0
- package/dist/src/a11y/keycodes/hasModifierKey.d.ts +9 -0
- package/dist/src/a11y/keycodes/hasModifierKey.d.ts.map +1 -0
- package/dist/src/a11y/keycodes/index.d.ts +6 -0
- package/dist/src/a11y/keycodes/index.d.ts.map +1 -0
- package/dist/src/a11y/keycodes/isModifierAllowed.d.ts +9 -0
- package/dist/src/a11y/keycodes/isModifierAllowed.d.ts.map +1 -0
- package/dist/src/a11y/list-key/FocusKeyManager.d.ts +17 -0
- package/dist/src/a11y/list-key/FocusKeyManager.d.ts.map +1 -0
- package/dist/src/a11y/list-key/ListKeyManager.d.ts +114 -0
- package/dist/src/a11y/list-key/ListKeyManager.d.ts.map +1 -0
- package/dist/src/a11y/list-key/ListManager.d.ts +37 -0
- package/dist/src/a11y/list-key/ListManager.d.ts.map +1 -0
- package/dist/src/a11y/list-key/RadioKeyManager.d.ts +20 -0
- package/dist/src/a11y/list-key/RadioKeyManager.d.ts.map +1 -0
- package/dist/src/a11y/list-key/RovingTabIndexManager.d.ts +22 -0
- package/dist/src/a11y/list-key/RovingTabIndexManager.d.ts.map +1 -0
- package/dist/src/a11y/list-key/SelectionManager.d.ts +46 -0
- package/dist/src/a11y/list-key/SelectionManager.d.ts.map +1 -0
- package/dist/src/a11y/list-key/Typeahead.d.ts +64 -0
- package/dist/src/a11y/list-key/Typeahead.d.ts.map +1 -0
- package/dist/src/a11y/list-key/index.d.ts +8 -0
- package/dist/src/a11y/list-key/index.d.ts.map +1 -0
- package/dist/src/a11y/visuallyHide.d.ts +6 -0
- package/dist/src/a11y/visuallyHide.d.ts.map +1 -0
- package/dist/src/anchoring/AnchorOptions.d.ts +15 -0
- package/dist/src/anchoring/AnchorOptions.d.ts.map +1 -0
- package/dist/src/anchoring/AnchorPosition.d.ts +3 -0
- package/dist/src/anchoring/AnchorPosition.d.ts.map +1 -0
- package/dist/src/anchoring/index.d.ts +4 -0
- package/dist/src/anchoring/index.d.ts.map +1 -0
- package/dist/src/anchoring/positionAnchor.d.ts +12 -0
- package/dist/src/anchoring/positionAnchor.d.ts.map +1 -0
- package/dist/src/bidi/Directionality.d.ts +27 -0
- package/dist/src/bidi/Directionality.d.ts.map +1 -0
- package/dist/src/bidi/index.d.ts +2 -0
- package/dist/src/bidi/index.d.ts.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/layout/Breakpoint.d.ts +26 -0
- package/dist/src/layout/Breakpoint.d.ts.map +1 -0
- package/dist/src/layout/BreakpointObserver.d.ts +18 -0
- package/dist/src/layout/BreakpointObserver.d.ts.map +1 -0
- package/dist/src/layout/index.d.ts +3 -0
- package/dist/src/layout/index.d.ts.map +1 -0
- package/dist/src/platform/Platform.d.ts +34 -0
- package/dist/src/platform/Platform.d.ts.map +1 -0
- package/dist/src/platform/index.d.ts +2 -0
- package/dist/src/platform/index.d.ts.map +1 -0
- package/dist/src/shared/controllers/FocusController.d.ts +30 -0
- package/dist/src/shared/controllers/FocusController.d.ts.map +1 -0
- package/dist/src/shared/controllers/HoverController.d.ts +40 -0
- package/dist/src/shared/controllers/HoverController.d.ts.map +1 -0
- package/dist/src/shared/controllers/IntersectionController.d.ts +40 -0
- package/dist/src/shared/controllers/IntersectionController.d.ts.map +1 -0
- package/dist/src/shared/controllers/LongPressController.d.ts +32 -0
- package/dist/src/shared/controllers/LongPressController.d.ts.map +1 -0
- package/dist/src/shared/controllers/MonitorControllerBase.d.ts +62 -0
- package/dist/src/shared/controllers/MonitorControllerBase.d.ts.map +1 -0
- package/dist/src/shared/controllers/MutationController.d.ts +37 -0
- package/dist/src/shared/controllers/MutationController.d.ts.map +1 -0
- package/dist/src/shared/controllers/PressedController.d.ts +45 -0
- package/dist/src/shared/controllers/PressedController.d.ts.map +1 -0
- package/dist/src/shared/controllers/ResizeController.d.ts +40 -0
- package/dist/src/shared/controllers/ResizeController.d.ts.map +1 -0
- package/dist/src/shared/controllers/ScrollController.d.ts +34 -0
- package/dist/src/shared/controllers/ScrollController.d.ts.map +1 -0
- package/dist/src/shared/controllers/index.d.ts +9 -0
- package/dist/src/shared/controllers/index.d.ts.map +1 -0
- package/dist/src/shared/decorators/debounce.d.ts +7 -0
- package/dist/src/shared/decorators/debounce.d.ts.map +1 -0
- package/dist/src/shared/decorators/index.d.ts +2 -0
- package/dist/src/shared/decorators/index.d.ts.map +1 -0
- package/dist/src/shared/directives/index.d.ts +2 -0
- package/dist/src/shared/directives/index.d.ts.map +1 -0
- package/dist/src/shared/directives/safeStyleMap.d.ts +44 -0
- package/dist/src/shared/directives/safeStyleMap.d.ts.map +1 -0
- package/dist/src/shared/index.d.ts +8 -0
- package/dist/src/shared/index.d.ts.map +1 -0
- package/dist/src/shared/mixins/AttachInternals.d.ts +24 -0
- package/dist/src/shared/mixins/AttachInternals.d.ts.map +1 -0
- package/dist/src/shared/mixins/Checked.d.ts +24 -0
- package/dist/src/shared/mixins/Checked.d.ts.map +1 -0
- package/dist/src/shared/mixins/CheckedIndeterminate.d.ts +25 -0
- package/dist/src/shared/mixins/CheckedIndeterminate.d.ts.map +1 -0
- package/dist/src/shared/mixins/CheckedOrSelected.d.ts +23 -0
- package/dist/src/shared/mixins/CheckedOrSelected.d.ts.map +1 -0
- package/dist/src/shared/mixins/ConstraintValidation.d.ts +48 -0
- package/dist/src/shared/mixins/ConstraintValidation.d.ts.map +1 -0
- package/dist/src/shared/mixins/Constructor.d.ts +3 -0
- package/dist/src/shared/mixins/Constructor.d.ts.map +1 -0
- package/dist/src/shared/mixins/Dirty.d.ts +27 -0
- package/dist/src/shared/mixins/Dirty.d.ts.map +1 -0
- package/dist/src/shared/mixins/Disabled.d.ts +25 -0
- package/dist/src/shared/mixins/Disabled.d.ts.map +1 -0
- package/dist/src/shared/mixins/DisabledInteractive.d.ts +25 -0
- package/dist/src/shared/mixins/DisabledInteractive.d.ts.map +1 -0
- package/dist/src/shared/mixins/EventAttribute.d.ts +11 -0
- package/dist/src/shared/mixins/EventAttribute.d.ts.map +1 -0
- package/dist/src/shared/mixins/Focusable.d.ts +11 -0
- package/dist/src/shared/mixins/Focusable.d.ts.map +1 -0
- package/dist/src/shared/mixins/FormAssociated.d.ts +34 -0
- package/dist/src/shared/mixins/FormAssociated.d.ts.map +1 -0
- package/dist/src/shared/mixins/FormSubmitter.d.ts +31 -0
- package/dist/src/shared/mixins/FormSubmitter.d.ts.map +1 -0
- package/dist/src/shared/mixins/HtmlFor.d.ts +30 -0
- package/dist/src/shared/mixins/HtmlFor.d.ts.map +1 -0
- package/dist/src/shared/mixins/KeyboardClick.d.ts +11 -0
- package/dist/src/shared/mixins/KeyboardClick.d.ts.map +1 -0
- package/dist/src/shared/mixins/Labelled.d.ts +22 -0
- package/dist/src/shared/mixins/Labelled.d.ts.map +1 -0
- package/dist/src/shared/mixins/LinkButton.d.ts +36 -0
- package/dist/src/shared/mixins/LinkButton.d.ts.map +1 -0
- package/dist/src/shared/mixins/ReadOnly.d.ts +25 -0
- package/dist/src/shared/mixins/ReadOnly.d.ts.map +1 -0
- package/dist/src/shared/mixins/Required.d.ts +26 -0
- package/dist/src/shared/mixins/Required.d.ts.map +1 -0
- package/dist/src/shared/mixins/RequiredConstraintValidation.d.ts +21 -0
- package/dist/src/shared/mixins/RequiredConstraintValidation.d.ts.map +1 -0
- package/dist/src/shared/mixins/Role.d.ts +13 -0
- package/dist/src/shared/mixins/Role.d.ts.map +1 -0
- package/dist/src/shared/mixins/Selected.d.ts +24 -0
- package/dist/src/shared/mixins/Selected.d.ts.map +1 -0
- package/dist/src/shared/mixins/Touched.d.ts +27 -0
- package/dist/src/shared/mixins/Touched.d.ts.map +1 -0
- package/dist/src/shared/mixins/Vertical.d.ts +24 -0
- package/dist/src/shared/mixins/Vertical.d.ts.map +1 -0
- package/dist/src/shared/mixins/hasKeys.d.ts +9 -0
- package/dist/src/shared/mixins/hasKeys.d.ts.map +1 -0
- package/dist/src/shared/mixins/index.d.ts +25 -0
- package/dist/src/shared/mixins/index.d.ts.map +1 -0
- package/dist/src/shared/primitives/CollapsibleElement.d.ts +58 -0
- package/dist/src/shared/primitives/CollapsibleElement.d.ts.map +1 -0
- package/dist/src/shared/primitives/ElevationElement.d.ts +88 -0
- package/dist/src/shared/primitives/ElevationElement.d.ts.map +1 -0
- package/dist/src/shared/primitives/ElevationLevel.d.ts +3 -0
- package/dist/src/shared/primitives/ElevationLevel.d.ts.map +1 -0
- package/dist/src/shared/primitives/ElevationToken.d.ts +15 -0
- package/dist/src/shared/primitives/ElevationToken.d.ts.map +1 -0
- package/dist/src/shared/primitives/FocusRingElement.d.ts +78 -0
- package/dist/src/shared/primitives/FocusRingElement.d.ts.map +1 -0
- package/dist/src/shared/primitives/FocusRingToken.d.ts +17 -0
- package/dist/src/shared/primitives/FocusRingToken.d.ts.map +1 -0
- package/dist/src/shared/primitives/PseudoCheckboxElement.d.ts +50 -0
- package/dist/src/shared/primitives/PseudoCheckboxElement.d.ts.map +1 -0
- package/dist/src/shared/primitives/PseudoRadioElement.d.ts +41 -0
- package/dist/src/shared/primitives/PseudoRadioElement.d.ts.map +1 -0
- package/dist/src/shared/primitives/RippleElement.d.ts +110 -0
- package/dist/src/shared/primitives/RippleElement.d.ts.map +1 -0
- package/dist/src/shared/primitives/RippleToken.d.ts +12 -0
- package/dist/src/shared/primitives/RippleToken.d.ts.map +1 -0
- package/dist/src/shared/primitives/ScrollContainerElement.d.ts +64 -0
- package/dist/src/shared/primitives/ScrollContainerElement.d.ts.map +1 -0
- package/dist/src/shared/primitives/ScrollDividers.d.ts +3 -0
- package/dist/src/shared/primitives/ScrollDividers.d.ts.map +1 -0
- package/dist/src/shared/primitives/SlideElement.d.ts +48 -0
- package/dist/src/shared/primitives/SlideElement.d.ts.map +1 -0
- package/dist/src/shared/primitives/StateLayerElement.d.ts +77 -0
- package/dist/src/shared/primitives/StateLayerElement.d.ts.map +1 -0
- package/dist/src/shared/primitives/StateLayerToken.d.ts +13 -0
- package/dist/src/shared/primitives/StateLayerToken.d.ts.map +1 -0
- package/dist/src/shared/primitives/TextOverflowElement.d.ts +39 -0
- package/dist/src/shared/primitives/TextOverflowElement.d.ts.map +1 -0
- package/dist/src/shared/primitives/index.d.ts +13 -0
- package/dist/src/shared/primitives/index.d.ts.map +1 -0
- package/dist/src/shared/tokens/ColorToken.d.ts +96 -0
- package/dist/src/shared/tokens/ColorToken.d.ts.map +1 -0
- package/dist/src/shared/tokens/DensityToken.d.ts +15 -0
- package/dist/src/shared/tokens/DensityToken.d.ts.map +1 -0
- package/dist/src/shared/tokens/DesignToken.d.ts +366 -0
- package/dist/src/shared/tokens/DesignToken.d.ts.map +1 -0
- package/dist/src/shared/tokens/ElevationToken.d.ts +16 -0
- package/dist/src/shared/tokens/ElevationToken.d.ts.map +1 -0
- package/dist/src/shared/tokens/MotionToken.d.ts +69 -0
- package/dist/src/shared/tokens/MotionToken.d.ts.map +1 -0
- package/dist/src/shared/tokens/ScrollbarToken.d.ts +10 -0
- package/dist/src/shared/tokens/ScrollbarToken.d.ts.map +1 -0
- package/dist/src/shared/tokens/ShapeToken.d.ts +79 -0
- package/dist/src/shared/tokens/ShapeToken.d.ts.map +1 -0
- package/dist/src/shared/tokens/StateToken.d.ts +10 -0
- package/dist/src/shared/tokens/StateToken.d.ts.map +1 -0
- package/dist/src/shared/tokens/TypescaleToken.d.ts +220 -0
- package/dist/src/shared/tokens/TypescaleToken.d.ts.map +1 -0
- package/dist/src/shared/tokens/index.d.ts +2 -0
- package/dist/src/shared/tokens/index.d.ts.map +1 -0
- package/dist/src/shared/utils/getTextContent.d.ts +8 -0
- package/dist/src/shared/utils/getTextContent.d.ts.map +1 -0
- package/dist/src/shared/utils/guid.d.ts +6 -0
- package/dist/src/shared/utils/guid.d.ts.map +1 -0
- package/dist/src/shared/utils/hasAssignedNodes.d.ts +7 -0
- package/dist/src/shared/utils/hasAssignedNodes.d.ts.map +1 -0
- package/dist/src/shared/utils/index.d.ts +6 -0
- package/dist/src/shared/utils/index.d.ts.map +1 -0
- package/dist/src/shared/utils/prefersReducedMotion.d.ts +6 -0
- package/dist/src/shared/utils/prefersReducedMotion.d.ts.map +1 -0
- package/dist/src/shared/utils/scrollIntoViewIfNeeded.d.ts +8 -0
- package/dist/src/shared/utils/scrollIntoViewIfNeeded.d.ts.map +1 -0
- package/eslint.config.mjs +21 -0
- package/package.json +87 -0
- package/rollup.config.js +132 -0
- package/src/a11y/AriaDescriber.ts +130 -0
- package/src/a11y/FocusTrapElement.ts +136 -0
- package/src/a11y/InteractivityChecker.ts +62 -0
- package/src/a11y/LiveAnnouncer.ts +143 -0
- package/src/a11y/aria-reference.ts +51 -0
- package/src/a11y/index.ts +8 -0
- package/src/a11y/keycodes/KeyCode.ts +128 -0
- package/src/a11y/keycodes/ModifierKeys.ts +5 -0
- package/src/a11y/keycodes/getKeyCode.ts +8 -0
- package/src/a11y/keycodes/hasModifierKey.ts +11 -0
- package/src/a11y/keycodes/index.ts +5 -0
- package/src/a11y/keycodes/isModifierAllowed.ts +12 -0
- package/src/a11y/list-key/FocusKeyManager.ts +25 -0
- package/src/a11y/list-key/ListKeyManager.ts +350 -0
- package/src/a11y/list-key/ListManager.ts +66 -0
- package/src/a11y/list-key/RadioKeyManager.ts +49 -0
- package/src/a11y/list-key/RovingTabIndexManager.ts +56 -0
- package/src/a11y/list-key/SelectionManager.ts +132 -0
- package/src/a11y/list-key/Typeahead.ts +131 -0
- package/src/a11y/list-key/index.ts +7 -0
- package/src/a11y/visuallyHide.ts +18 -0
- package/src/anchoring/AnchorOptions.ts +19 -0
- package/src/anchoring/AnchorPosition.ts +14 -0
- package/src/anchoring/index.ts +3 -0
- package/src/anchoring/positionAnchor.ts +53 -0
- package/src/bidi/Directionality.ts +85 -0
- package/src/bidi/index.ts +1 -0
- package/src/index.ts +1 -0
- package/src/layout/Breakpoint.ts +26 -0
- package/src/layout/BreakpointObserver.ts +44 -0
- package/src/layout/index.ts +2 -0
- package/src/platform/Platform.ts +67 -0
- package/src/platform/index.ts +1 -0
- package/src/shared/controllers/FocusController.ts +60 -0
- package/src/shared/controllers/HoverController.ts +140 -0
- package/src/shared/controllers/IntersectionController.ts +81 -0
- package/src/shared/controllers/LongPressController.ts +87 -0
- package/src/shared/controllers/MonitorControllerBase.ts +99 -0
- package/src/shared/controllers/MutationController.ts +89 -0
- package/src/shared/controllers/PressedController.ts +137 -0
- package/src/shared/controllers/ResizeController.ts +83 -0
- package/src/shared/controllers/ScrollController.ts +100 -0
- package/src/shared/controllers/index.ts +8 -0
- package/src/shared/decorators/debounce.ts +19 -0
- package/src/shared/decorators/index.ts +1 -0
- package/src/shared/directives/index.ts +1 -0
- package/src/shared/directives/safeStyleMap.ts +108 -0
- package/src/shared/index.ts +7 -0
- package/src/shared/mixins/AttachInternals.ts +48 -0
- package/src/shared/mixins/Checked.ts +50 -0
- package/src/shared/mixins/CheckedIndeterminate.ts +47 -0
- package/src/shared/mixins/CheckedOrSelected.ts +36 -0
- package/src/shared/mixins/ConstraintValidation.ts +213 -0
- package/src/shared/mixins/Constructor.ts +2 -0
- package/src/shared/mixins/Dirty.ts +71 -0
- package/src/shared/mixins/Disabled.ts +49 -0
- package/src/shared/mixins/DisabledInteractive.ts +78 -0
- package/src/shared/mixins/EventAttribute.ts +25 -0
- package/src/shared/mixins/Focusable.ts +52 -0
- package/src/shared/mixins/FormAssociated.ts +152 -0
- package/src/shared/mixins/FormSubmitter.ts +123 -0
- package/src/shared/mixins/HtmlFor.ts +89 -0
- package/src/shared/mixins/KeyboardClick.ts +46 -0
- package/src/shared/mixins/Labelled.ts +88 -0
- package/src/shared/mixins/LinkButton.ts +169 -0
- package/src/shared/mixins/ReadOnly.ts +48 -0
- package/src/shared/mixins/Required.ts +50 -0
- package/src/shared/mixins/RequiredConstraintValidation.ts +45 -0
- package/src/shared/mixins/Role.ts +134 -0
- package/src/shared/mixins/Selected.ts +50 -0
- package/src/shared/mixins/Touched.ts +71 -0
- package/src/shared/mixins/Vertical.ts +44 -0
- package/src/shared/mixins/hasKeys.ts +10 -0
- package/src/shared/mixins/index.ts +24 -0
- package/src/shared/primitives/CollapsibleElement.ts +227 -0
- package/src/shared/primitives/ElevationElement.ts +254 -0
- package/src/shared/primitives/ElevationLevel.ts +2 -0
- package/src/shared/primitives/ElevationToken.ts +18 -0
- package/src/shared/primitives/FocusRingElement.ts +199 -0
- package/src/shared/primitives/FocusRingToken.ts +24 -0
- package/src/shared/primitives/PseudoCheckboxElement.ts +116 -0
- package/src/shared/primitives/PseudoRadioElement.ts +83 -0
- package/src/shared/primitives/RippleElement.ts +289 -0
- package/src/shared/primitives/RippleToken.ts +15 -0
- package/src/shared/primitives/ScrollContainerElement.ts +151 -0
- package/src/shared/primitives/ScrollDividers.ts +2 -0
- package/src/shared/primitives/SlideElement.ts +128 -0
- package/src/shared/primitives/StateLayerElement.ts +191 -0
- package/src/shared/primitives/StateLayerToken.ts +16 -0
- package/src/shared/primitives/TextOverflowElement.ts +60 -0
- package/src/shared/primitives/index.ts +12 -0
- package/src/shared/tokens/ColorToken.ts +142 -0
- package/src/shared/tokens/DensityToken.ts +23 -0
- package/src/shared/tokens/DesignToken.ts +35 -0
- package/src/shared/tokens/ElevationToken.ts +115 -0
- package/src/shared/tokens/MotionToken.ts +107 -0
- package/src/shared/tokens/ScrollbarToken.ts +13 -0
- package/src/shared/tokens/ShapeToken.ts +138 -0
- package/src/shared/tokens/StateToken.ts +13 -0
- package/src/shared/tokens/TypescaleToken.ts +230 -0
- package/src/shared/tokens/index.ts +1 -0
- package/src/shared/utils/getTextContent.ts +31 -0
- package/src/shared/utils/guid.ts +11 -0
- package/src/shared/utils/hasAssignedNodes.ts +8 -0
- package/src/shared/utils/index.ts +5 -0
- package/src/shared/utils/prefersReducedMotion.ts +9 -0
- package/src/shared/utils/scrollIntoViewIfNeeded.ts +18 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { css, CSSResultGroup, html, LitElement } from "lit";
|
|
2
|
+
import { customElement, query } from "lit/decorators.js";
|
|
3
|
+
|
|
4
|
+
import { Disabled } from "../shared/mixins/Disabled";
|
|
5
|
+
import { Role } from "../shared/mixins/Role";
|
|
6
|
+
|
|
7
|
+
import { M3eInteractivityChecker } from "./InteractivityChecker";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A non-visual element used to trap focus within nested content.
|
|
11
|
+
* @tag m3e-focus-trap
|
|
12
|
+
*
|
|
13
|
+
* @slot - Renders content for which to trap focus.
|
|
14
|
+
*
|
|
15
|
+
* @attr disabled - Disables the focus trap.
|
|
16
|
+
*/
|
|
17
|
+
@customElement("m3e-focus-trap")
|
|
18
|
+
export class M3eFocusTrapElement extends Disabled(Role(LitElement, "none")) {
|
|
19
|
+
/** The styles of the element. */
|
|
20
|
+
static override styles: CSSResultGroup = css`
|
|
21
|
+
:host {
|
|
22
|
+
display: contents;
|
|
23
|
+
}
|
|
24
|
+
.trap {
|
|
25
|
+
outline: none;
|
|
26
|
+
}
|
|
27
|
+
`;
|
|
28
|
+
|
|
29
|
+
/** @private */ @query(".trap") private readonly _firstTrap!: HTMLElement | null;
|
|
30
|
+
|
|
31
|
+
/** @inheritdoc */
|
|
32
|
+
protected override render(): unknown {
|
|
33
|
+
const trap = html`<div
|
|
34
|
+
class="trap"
|
|
35
|
+
.inert="${this.disabled}"
|
|
36
|
+
tabindex="0"
|
|
37
|
+
aria-hidden="true"
|
|
38
|
+
@focus="${this.#onFocus}"
|
|
39
|
+
></div>`;
|
|
40
|
+
return html`${trap}<slot></slot>${trap}`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** @private */
|
|
44
|
+
#onFocus(e: FocusEvent): void {
|
|
45
|
+
const [first, last] = this.#getFirstAndLastFocusableChild();
|
|
46
|
+
const isFirst = e?.target === this._firstTrap;
|
|
47
|
+
const fromFirst = e.relatedTarget === first;
|
|
48
|
+
const fromLast = e.relatedTarget === last;
|
|
49
|
+
const fromOutside = !fromFirst && !fromLast;
|
|
50
|
+
|
|
51
|
+
if ((!isFirst && fromLast) || (isFirst && fromOutside)) {
|
|
52
|
+
first?.focus();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if ((isFirst && fromFirst) || (!isFirst && fromOutside)) {
|
|
56
|
+
last?.focus();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** @private */
|
|
61
|
+
#getFirstAndLastFocusableChild(): [HTMLElement | null, HTMLElement | null] {
|
|
62
|
+
let first: HTMLElement | null = null;
|
|
63
|
+
let last: HTMLElement | null = null;
|
|
64
|
+
|
|
65
|
+
this.#walkTree(this, [], (element, parents) => {
|
|
66
|
+
if (
|
|
67
|
+
M3eInteractivityChecker.isFocusable(element, parents) &&
|
|
68
|
+
element instanceof HTMLElement &&
|
|
69
|
+
element.tabIndex >= 0
|
|
70
|
+
) {
|
|
71
|
+
first = first ?? element;
|
|
72
|
+
last = element;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
return [first, last];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** @private */
|
|
80
|
+
#walkTree(
|
|
81
|
+
root: Element,
|
|
82
|
+
parents: readonly Element[],
|
|
83
|
+
callback: (element: Element, parents: readonly Element[]) => void
|
|
84
|
+
): void {
|
|
85
|
+
parents = [...parents, root];
|
|
86
|
+
|
|
87
|
+
for (const node of root.childNodes) {
|
|
88
|
+
if (node.nodeType !== Node.ELEMENT_NODE) continue;
|
|
89
|
+
const element = <HTMLElement>node;
|
|
90
|
+
|
|
91
|
+
callback(element, parents);
|
|
92
|
+
|
|
93
|
+
if (element.shadowRoot) {
|
|
94
|
+
this.#walkShadowRoot(element, parents, callback);
|
|
95
|
+
} else if (element instanceof HTMLSlotElement) {
|
|
96
|
+
this.#walkSlot(element, parents, callback);
|
|
97
|
+
} else if (element.hasChildNodes()) {
|
|
98
|
+
this.#walkTree(element, parents, callback);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** @private */
|
|
104
|
+
#walkShadowRoot(
|
|
105
|
+
root: Element,
|
|
106
|
+
parents: readonly Element[],
|
|
107
|
+
callback: (element: Element, parents: readonly Element[]) => void
|
|
108
|
+
): void {
|
|
109
|
+
for (const node of root.shadowRoot?.childNodes ?? []) {
|
|
110
|
+
if (node.nodeType !== Node.ELEMENT_NODE) continue;
|
|
111
|
+
const element = <HTMLElement>node;
|
|
112
|
+
callback(element, parents);
|
|
113
|
+
if (!element.hasChildNodes()) continue;
|
|
114
|
+
this.#walkTree(element, parents, callback);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** @private */
|
|
119
|
+
#walkSlot(
|
|
120
|
+
slot: HTMLSlotElement,
|
|
121
|
+
parents: readonly Element[],
|
|
122
|
+
callback: (element: Element, parents: readonly Element[]) => void
|
|
123
|
+
) {
|
|
124
|
+
for (const node of slot.assignedElements()) {
|
|
125
|
+
callback(node, parents);
|
|
126
|
+
if (!node.hasChildNodes()) continue;
|
|
127
|
+
this.#walkTree(node, parents, callback);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
declare global {
|
|
133
|
+
interface HTMLElementTagNameMap {
|
|
134
|
+
"m3e-focus-trap": M3eFocusTrapElement;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/** Utility for checking the interactivity of an element, such as whether it is focusable. */
|
|
2
|
+
export class M3eInteractivityChecker {
|
|
3
|
+
/**
|
|
4
|
+
* Determines whether a given element can receive focus.
|
|
5
|
+
* @param {Element} element The element to test.
|
|
6
|
+
* @param {readonly Element[]} [parents = undefined] The known parent elements to test. The default value is `undefined`.
|
|
7
|
+
* @returns {boolean} Whether `element` can receive focus.
|
|
8
|
+
*/
|
|
9
|
+
static isFocusable(element: Element, parents?: readonly Element[]): boolean {
|
|
10
|
+
if (
|
|
11
|
+
element.matches(
|
|
12
|
+
":is(button,input,select,textarea,object,:is(a,area)[href],[tabindex],[contenteditable=true]):not(:disabled,[disabled])"
|
|
13
|
+
)
|
|
14
|
+
) {
|
|
15
|
+
return !this.#cannotFocusParent(parents);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (
|
|
19
|
+
!element.localName.includes("-") ||
|
|
20
|
+
!element.matches(":not(:disabled,[disabled])") ||
|
|
21
|
+
element.getAttribute("aria-disabled") === "true"
|
|
22
|
+
) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (element.shadowRoot?.delegatesFocus) {
|
|
27
|
+
return !this.#cannotFocusParent(parents);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static #cannotFocusParent(parents?: readonly Element[]): boolean {
|
|
34
|
+
return parents?.some((x) => x.matches(":is([aria-hidden='true'],:disabled,[disabled])")) ?? false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Finds interactive elements that descend from the specified element.
|
|
39
|
+
* @param {HTMLElement} element The `HTMLElement` to search.
|
|
40
|
+
* @returns {HTMLElement[]} The interactive elements that descend from `element`.
|
|
41
|
+
*/
|
|
42
|
+
static findInteractiveElements(element: HTMLElement): HTMLElement[] {
|
|
43
|
+
const elements = new Array<HTMLElement>();
|
|
44
|
+
const walker = element.ownerDocument.createTreeWalker(element, NodeFilter.SHOW_ELEMENT);
|
|
45
|
+
|
|
46
|
+
for (let node = walker.nextNode(); node; node = walker.nextNode()) {
|
|
47
|
+
const element = <HTMLElement>walker.currentNode;
|
|
48
|
+
if (this.isFocusable(element)) {
|
|
49
|
+
elements.push(element);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return elements;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
declare global {
|
|
58
|
+
/** Utility for checking the interactivity of an element, such as whether it is focusable. */
|
|
59
|
+
var M3eInteractivityChecker: M3eInteractivityChecker;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
globalThis.M3eInteractivityChecker = M3eInteractivityChecker;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapted from Angular Material CDK Live Announcer
|
|
3
|
+
* Source: https://github.com/angular/components/blob/main/src/cdk/a11y/live-announcer/live-announcer.ts
|
|
4
|
+
*
|
|
5
|
+
* @license MIT
|
|
6
|
+
* Copyright (c) 2025 Google LLC
|
|
7
|
+
* See LICENSE file in the project root for full license text.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { isServer } from "lit";
|
|
11
|
+
|
|
12
|
+
import { addAriaReferencedId } from "./aria-reference";
|
|
13
|
+
import { visuallyHide } from "./visuallyHide";
|
|
14
|
+
|
|
15
|
+
/** Specifies the possible politeness levels in which to announce messages. */
|
|
16
|
+
export type ARIALivePoliteness = "off" | "polite" | "assertive";
|
|
17
|
+
|
|
18
|
+
/** Utility for announcing messages to screen readers. */
|
|
19
|
+
export class M3eLiveAnnouncer {
|
|
20
|
+
/** @private */ static #nextId = 0;
|
|
21
|
+
/** @private */ static #liveElement?: HTMLElement;
|
|
22
|
+
/** @private */ static #previousTimeout: number;
|
|
23
|
+
/** @private */ static #currentPromise?: Promise<void>;
|
|
24
|
+
/** @private */ static #currentResolve?: () => void;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Announces the specified message to screen readers.
|
|
28
|
+
* @param {string} message The message to announce.
|
|
29
|
+
* @returns {Promise<void>} A `Promise` that resolves when `message` is added to the DOM.
|
|
30
|
+
*/
|
|
31
|
+
static announce(message: string): Promise<void>;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Announces the specified message to screen readers.
|
|
35
|
+
* @param {string} message The message to announce.
|
|
36
|
+
* @param {ARIALivePoliteness | undefined} politeness The politeness in which to announce `message`.
|
|
37
|
+
* @returns {Promise<void>} A `Promise` that resolves when `message` is added to the DOM.
|
|
38
|
+
*/
|
|
39
|
+
static announce(message: string, politeness?: ARIALivePoliteness): Promise<void>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Announces the specified message to screen readers.
|
|
43
|
+
* @param {string} message The message to announce.
|
|
44
|
+
* @param {number | undefined} duration The duration, in milliseconds, after which to clear the announcement. Note
|
|
45
|
+
* that this takes effect after the message has been added to the DOM, which can be up to
|
|
46
|
+
* 100ms after `announce` has been called.
|
|
47
|
+
* @returns {Promise<void>} A `Promise` that resolves when `message` is added to the DOM.
|
|
48
|
+
*/
|
|
49
|
+
static announce(message: string, duration?: number): Promise<void>;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Announces the specified message to screen readers.
|
|
53
|
+
* @param {string} message The message to announce.
|
|
54
|
+
* @param {ARIALivePoliteness | undefined} politeness The politeness in which to announce `message`.
|
|
55
|
+
* @param {number | undefined} duration The duration, in milliseconds, after which to clear the announcement. Note
|
|
56
|
+
* that this takes effect after the message has been added to the DOM, which can be up to 100ms after `announce` has been called.
|
|
57
|
+
* @returns {Promise<void>} A `Promise` that resolves when `message` is added to the DOM.
|
|
58
|
+
*/
|
|
59
|
+
static announce(message: string, politeness?: ARIALivePoliteness, duration?: number): Promise<void>;
|
|
60
|
+
|
|
61
|
+
static announce(message: string, ...args: any[]): Promise<void> {
|
|
62
|
+
if (isServer) {
|
|
63
|
+
return Promise.resolve();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this.#liveElement = this.#liveElement ?? this.#createLiveElement();
|
|
67
|
+
|
|
68
|
+
let politeness: ARIALivePoliteness | undefined;
|
|
69
|
+
let duration: number | undefined;
|
|
70
|
+
|
|
71
|
+
if (args.length === 1 && typeof args[0] === "number") {
|
|
72
|
+
duration = args[0];
|
|
73
|
+
} else {
|
|
74
|
+
[politeness, duration] = args;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
this.clear();
|
|
78
|
+
clearTimeout(this.#previousTimeout);
|
|
79
|
+
|
|
80
|
+
this.#liveElement.setAttribute("aria-live", politeness ?? "polite");
|
|
81
|
+
|
|
82
|
+
for (const modal of document.querySelectorAll("m3e-dialog")) {
|
|
83
|
+
addAriaReferencedId(modal, "aria-owns", this.#liveElement.id);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
this.#currentPromise = this.#currentPromise ?? new Promise((resolve) => (this.#currentResolve = resolve));
|
|
87
|
+
clearTimeout(this.#previousTimeout);
|
|
88
|
+
|
|
89
|
+
this.#previousTimeout = setTimeout(() => {
|
|
90
|
+
if (!this.#liveElement) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
this.#liveElement.textContent = message;
|
|
95
|
+
if (duration !== undefined) {
|
|
96
|
+
this.#previousTimeout = setTimeout(() => this.clear(), duration);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
this.#currentResolve?.();
|
|
100
|
+
this.#currentPromise = this.#currentResolve = undefined;
|
|
101
|
+
}, 100);
|
|
102
|
+
|
|
103
|
+
return this.#currentPromise;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Clears the current text from the announcer element. Can be used to prevent
|
|
108
|
+
* screen readers from reading the text out again while the user is going
|
|
109
|
+
* through page landmarks.
|
|
110
|
+
*/
|
|
111
|
+
static clear() {
|
|
112
|
+
if (this.#liveElement) {
|
|
113
|
+
this.#liveElement.textContent = "";
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** @private */
|
|
118
|
+
static #createLiveElement(): HTMLElement {
|
|
119
|
+
const prev = document.getElementsByClassName("m3e-live-announcer");
|
|
120
|
+
for (let i = 0; i < prev.length; i++) {
|
|
121
|
+
prev[i].remove();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const liveAnnouncer = document.createElement("div");
|
|
125
|
+
liveAnnouncer.classList.add("m3e-live-announcer");
|
|
126
|
+
liveAnnouncer.setAttribute("aria-atomic", "true");
|
|
127
|
+
liveAnnouncer.setAttribute("aria-live", "polite");
|
|
128
|
+
liveAnnouncer.id = `m3e-live-announcer-${this.#nextId++}`;
|
|
129
|
+
|
|
130
|
+
visuallyHide(liveAnnouncer.style);
|
|
131
|
+
|
|
132
|
+
document.body.append(liveAnnouncer);
|
|
133
|
+
|
|
134
|
+
return liveAnnouncer;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
declare global {
|
|
139
|
+
/** Utility for announcing messages to screen readers. */
|
|
140
|
+
var M3eLiveAnnouncer: M3eLiveAnnouncer;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
globalThis.M3eLiveAnnouncer = M3eLiveAnnouncer;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapted from Angular Material CDK AriaDescriber
|
|
3
|
+
* Source: https://github.com/angular/components/blob/main/src/cdk/a11y/aria-describer/aria-reference.ts
|
|
4
|
+
*
|
|
5
|
+
* @license MIT
|
|
6
|
+
* Copyright (c) 2025 Google LLC
|
|
7
|
+
* See LICENSE file in the project root for full license text.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Gets a list of IDs referenced by an element for the specified ARIA attribute.
|
|
12
|
+
* @param {Element} element The element from which to get referenced IDs.
|
|
13
|
+
* @param {`aria-${string}`} attribute The ARIA attribute from which to get referenced IDs.
|
|
14
|
+
* @returns {string[]} a list of IDs referenced by `element` for `attribute`.
|
|
15
|
+
*/
|
|
16
|
+
export function getAriaReferenceIds(element: Element, attribute: `aria-${string}`): string[] {
|
|
17
|
+
return element.getAttribute(attribute)?.match(/\S+/g) ?? [];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Adds an ID to the list of IDs referenced by an element for a given ARIA attribute.
|
|
22
|
+
* @param {Element} element The element to which to add a referenced ID.
|
|
23
|
+
* @param {`aria-${string}`} attribute The ARIA attribute to which to add an ID.
|
|
24
|
+
* @param {string} id The ID to add.
|
|
25
|
+
*/
|
|
26
|
+
export function addAriaReferencedId(element: Element, attribute: `aria-${string}`, id: string): void {
|
|
27
|
+
id = id.trim();
|
|
28
|
+
|
|
29
|
+
const ids = getAriaReferenceIds(element, attribute);
|
|
30
|
+
if (!ids.some((existingId) => existingId.trim() === id)) {
|
|
31
|
+
ids.push(id);
|
|
32
|
+
element.setAttribute(attribute, ids.join(" "));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Removes an ID from a list of IDs referenced by an element for the specified ARIA attribute.
|
|
38
|
+
* @param {Element} element The element from which to remove an ID.
|
|
39
|
+
* @param {`aria-${string}`} attribute The ARIA attribute from which to remove an ID.
|
|
40
|
+
* @param {string} id The ID to remove.
|
|
41
|
+
*/
|
|
42
|
+
export function removeAriaReferencedId(element: Element, attribute: `aria-${string}`, id: string): void {
|
|
43
|
+
id = id.trim();
|
|
44
|
+
const ids = getAriaReferenceIds(element, attribute).filter((val) => val !== id);
|
|
45
|
+
|
|
46
|
+
if (ids.length > 0) {
|
|
47
|
+
element.setAttribute(attribute, ids.join(" "));
|
|
48
|
+
} else {
|
|
49
|
+
element.removeAttribute(attribute);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/** Specifies known key code values. */
|
|
2
|
+
export enum KeyCode {
|
|
3
|
+
Backspace = 8,
|
|
4
|
+
Tab = 9,
|
|
5
|
+
Enter = 13,
|
|
6
|
+
Shift = 16,
|
|
7
|
+
Ctrl = 17,
|
|
8
|
+
Alt = 18,
|
|
9
|
+
PauseBreak = 19,
|
|
10
|
+
CapsLock = 20,
|
|
11
|
+
Escape = 27,
|
|
12
|
+
Space = 32,
|
|
13
|
+
PageUp = 33,
|
|
14
|
+
PageDown = 34,
|
|
15
|
+
End = 35,
|
|
16
|
+
Home = 36,
|
|
17
|
+
|
|
18
|
+
LeftArrow = 37,
|
|
19
|
+
UpArrow = 38,
|
|
20
|
+
RightArrow = 39,
|
|
21
|
+
DownArrow = 40,
|
|
22
|
+
|
|
23
|
+
Insert = 45,
|
|
24
|
+
Delete = 46,
|
|
25
|
+
|
|
26
|
+
Zero = 48,
|
|
27
|
+
ClosedParen = Zero,
|
|
28
|
+
One = 49,
|
|
29
|
+
ExclamationMark = One,
|
|
30
|
+
Two = 50,
|
|
31
|
+
AtSign = Two,
|
|
32
|
+
Three = 51,
|
|
33
|
+
PoundSign = Three,
|
|
34
|
+
Hash = PoundSign,
|
|
35
|
+
Four = 52,
|
|
36
|
+
DollarSign = Four,
|
|
37
|
+
Five = 53,
|
|
38
|
+
PercentSign = Five,
|
|
39
|
+
Six = 54,
|
|
40
|
+
Caret = Six,
|
|
41
|
+
Hat = Caret,
|
|
42
|
+
Seven = 55,
|
|
43
|
+
Ampersand = Seven,
|
|
44
|
+
Eight = 56,
|
|
45
|
+
Star = Eight,
|
|
46
|
+
Asterik = Star,
|
|
47
|
+
Nine = 57,
|
|
48
|
+
OpenParen = Nine,
|
|
49
|
+
|
|
50
|
+
A = 65,
|
|
51
|
+
B = 66,
|
|
52
|
+
C = 67,
|
|
53
|
+
D = 68,
|
|
54
|
+
E = 69,
|
|
55
|
+
F = 70,
|
|
56
|
+
G = 71,
|
|
57
|
+
H = 72,
|
|
58
|
+
I = 73,
|
|
59
|
+
J = 74,
|
|
60
|
+
K = 75,
|
|
61
|
+
L = 76,
|
|
62
|
+
M = 77,
|
|
63
|
+
N = 78,
|
|
64
|
+
O = 79,
|
|
65
|
+
P = 80,
|
|
66
|
+
Q = 81,
|
|
67
|
+
R = 82,
|
|
68
|
+
S = 83,
|
|
69
|
+
T = 84,
|
|
70
|
+
U = 85,
|
|
71
|
+
V = 86,
|
|
72
|
+
W = 87,
|
|
73
|
+
X = 88,
|
|
74
|
+
Y = 89,
|
|
75
|
+
Z = 90,
|
|
76
|
+
|
|
77
|
+
LeftWindowKey = 91,
|
|
78
|
+
RightWindowKey = 92,
|
|
79
|
+
SelectKey = 93,
|
|
80
|
+
|
|
81
|
+
Numpad0 = 96,
|
|
82
|
+
Numpad1 = 97,
|
|
83
|
+
Numpad2 = 98,
|
|
84
|
+
Numpad3 = 99,
|
|
85
|
+
Numpad4 = 100,
|
|
86
|
+
Numpad5 = 101,
|
|
87
|
+
Numpad6 = 102,
|
|
88
|
+
Numpad7 = 103,
|
|
89
|
+
Numpad8 = 104,
|
|
90
|
+
Numpad9 = 105,
|
|
91
|
+
|
|
92
|
+
Multiply = 106,
|
|
93
|
+
Add = 107,
|
|
94
|
+
Subtract = 109,
|
|
95
|
+
DecimalPoint = 110,
|
|
96
|
+
Divide = 111,
|
|
97
|
+
|
|
98
|
+
F1 = 112,
|
|
99
|
+
F2 = 113,
|
|
100
|
+
F3 = 114,
|
|
101
|
+
F4 = 115,
|
|
102
|
+
F5 = 116,
|
|
103
|
+
F6 = 117,
|
|
104
|
+
F7 = 118,
|
|
105
|
+
F8 = 119,
|
|
106
|
+
F9 = 120,
|
|
107
|
+
F10 = 121,
|
|
108
|
+
F11 = 122,
|
|
109
|
+
F12 = 123,
|
|
110
|
+
|
|
111
|
+
NumLock = 144,
|
|
112
|
+
ScrollLock = 145,
|
|
113
|
+
|
|
114
|
+
SemiColon = 186,
|
|
115
|
+
Equals = 187,
|
|
116
|
+
Comma = 188,
|
|
117
|
+
Dash = 189,
|
|
118
|
+
Period = 190,
|
|
119
|
+
UnderScore = Dash,
|
|
120
|
+
PlusSign = Equals,
|
|
121
|
+
ForwardSlash = 191,
|
|
122
|
+
Tilde = 192,
|
|
123
|
+
GraveAccent = Tilde,
|
|
124
|
+
|
|
125
|
+
OpenBracket = 219,
|
|
126
|
+
ClosedBracket = 221,
|
|
127
|
+
Quote = 222,
|
|
128
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves the key code for the specified `KeyboardEvent`.
|
|
3
|
+
* @param {KeyboardEvent} e The `KeyboardEvent` for which to resolve the key code.
|
|
4
|
+
* @returns {number} The key code for `e`.
|
|
5
|
+
*/
|
|
6
|
+
export function getKeyCode(e: KeyboardEvent): number {
|
|
7
|
+
return e.which || e.charCode || e.keyCode;
|
|
8
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ModifierKey } from "./ModifierKeys";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Determines whether a modifier key is pressed.
|
|
5
|
+
* @param {KeyboardEvent} e The `KeyboardEvent` to test.
|
|
6
|
+
* @param {ModifierKey[]} modifiers The modifier keys to test.
|
|
7
|
+
* @returns {boolean} A value indicating whether a modifier key is pressed.
|
|
8
|
+
*/
|
|
9
|
+
export function hasModifierKey(e: KeyboardEvent, ...modifiers: ModifierKey[]): boolean {
|
|
10
|
+
return modifiers.length ? modifiers.some((x) => e[`${x}Key`]) : e.altKey || e.shiftKey || e.ctrlKey || e.metaKey;
|
|
11
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { hasModifierKey } from "./hasModifierKey";
|
|
2
|
+
import { ModifierKey, ModifierKeys } from "./ModifierKeys";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Determines whether the specified modifier keys are allowed.
|
|
6
|
+
* @param {KeyboardEvent} e The `KeyboardEvent` to test.
|
|
7
|
+
* @param {ModifierKey[]} modifiers The allowed modifier keys.
|
|
8
|
+
* @returns {boolean} A value indicating whether `modifiers` are allowed.
|
|
9
|
+
*/
|
|
10
|
+
export function isModifierAllowed(e: KeyboardEvent, ...modifiers: ModifierKey[]): boolean {
|
|
11
|
+
return ModifierKeys.every((x) => !hasModifierKey(e, x) || modifiers.includes(x));
|
|
12
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ListKeyManager } from "./ListKeyManager";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Utility for managing keyboard events for selectable lists whose items directly receive focus.
|
|
5
|
+
* @template T The type of managed item.
|
|
6
|
+
*/
|
|
7
|
+
export class FocusKeyManager<T extends HTMLElement> extends ListKeyManager<T> {
|
|
8
|
+
/** @private */ #focusOptions?: FocusOptions;
|
|
9
|
+
|
|
10
|
+
/** @inheritdoc */
|
|
11
|
+
override setActiveItem(item: T | null | undefined): void {
|
|
12
|
+
super.setActiveItem(item);
|
|
13
|
+
item?.focus(this.#focusOptions);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Configures the key manager with options used to focus items.
|
|
18
|
+
* @param {FocusOptions} options Options used to focus items.
|
|
19
|
+
* @returns {FocusKeyManager<T>} The configured key manager.
|
|
20
|
+
*/
|
|
21
|
+
withOptions(options: FocusOptions): this {
|
|
22
|
+
this.#focusOptions = options;
|
|
23
|
+
return this;
|
|
24
|
+
}
|
|
25
|
+
}
|