UNPKG

igniteui-webcomponents

Version:

Ignite UI for Web Components is a complete library of UI components, giving you the ability to build modern web applications using encapsulation and the concept of reusable components in a dependency-free approach.

165 lines 5.6 kB
import { findElementFromEventPath } from '../util.js'; export const arrowLeft = 'ArrowLeft'; export const arrowRight = 'ArrowRight'; export const arrowUp = 'ArrowUp'; export const arrowDown = 'ArrowDown'; export const enterKey = 'Enter'; export const spaceBar = ' '; export const escapeKey = 'Escape'; export const homeKey = 'Home'; export const endKey = 'End'; export const pageUpKey = 'PageUp'; export const pageDownKey = 'PageDown'; export const tabKey = 'Tab'; export const altKey = 'Alt'; export const ctrlKey = 'Ctrl'; export const metaKey = 'Meta'; export const shiftKey = 'Shift'; const Modifiers = new Map([altKey, ctrlKey, metaKey, shiftKey].map((key) => { const mod = key.toLowerCase(); return key === ctrlKey ? ['control', mod] : [mod, mod]; })); const defaultOptions = { skip: ['input', 'textarea', 'select'], }; function normalizeKeys(keys) { return (Array.isArray(keys) ? keys : [keys]).map((key) => key.toLowerCase()); } function isKeydown(event) { return event.type === 'keydown'; } function isKeyup(event) { return event.type === 'keyup'; } function isKeydownTrigger(triggers) { return triggers ? triggers.includes('keydown') || isKeydownRepeatTrigger(triggers) : false; } function isKeyupTrigger(triggers) { return triggers ? triggers.includes('keyup') : false; } function isKeydownRepeatTrigger(triggers) { return triggers ? triggers.includes('keydownRepeat') : false; } export function parseKeys(keys) { const parsed = normalizeKeys(keys); return { keys: parsed.filter((key) => !Modifiers.has(key)), modifiers: parsed.filter((key) => Modifiers.has(key)), }; } function createCombinationKey(keys, modifiers) { return Array.from(Modifiers.values()) .filter((mod) => modifiers.includes(mod)) .concat(keys) .join('+'); } class KeyBindingController { get _element() { if (this._observedElement) { return this._observedElement; } return this._ref ? this._ref.value : this._host; } observeElement(element) { element.addEventListener('keydown', this); element.addEventListener('keyup', this); this._observedElement = element; return { unsubscribe: () => { this._observedElement?.removeEventListener('keydown', this); this._observedElement?.removeEventListener('keyup', this); this._observedElement = undefined; }, }; } constructor(host, options) { this.bindings = new Map(); this.pressedKeys = new Set(); this._host = host; this._ref = options?.ref; this._options = { ...defaultOptions, ...options }; host.addController(this); } eventModifiersMatch(binding, event) { if (binding.options?.preventDefault) { event.preventDefault(); } if (binding.options?.stopPropagation) { event.stopPropagation(); } } bindingMatches(binding, event) { const triggers = binding.options?.triggers ?? ['keydown']; if (isKeydown(event) && isKeydownTrigger(triggers)) { return true; } if (isKeyup(event) && isKeyupTrigger(triggers)) { return true; } return false; } shouldSkip(event) { const skip = this._options?.skip; if (!findElementFromEventPath((e) => e === this._element, event)) { return true; } if (!skip) { return false; } return Array.isArray(skip) ? findElementFromEventPath(skip.join(), event) : skip.call(this._host, event.target, event); } handleEvent(event) { if (this.shouldSkip(event)) { return; } const key = event.key.toLowerCase(); Modifiers.has(key) ? this.pressedKeys.clear() : this.pressedKeys.add(key); const pendingKeys = Array.from(this.pressedKeys); const modifiers = Array.from(Modifiers.values()).filter((mod) => event[`${mod}Key`]); const binding = this.bindings.get(createCombinationKey(pendingKeys, modifiers)); if (binding && this.bindingMatches(binding, event)) { this.eventModifiersMatch(binding, event); binding.handler.call(this._host, event); if (isKeydownRepeatTrigger(binding.options?.triggers)) { this.pressedKeys.delete(key); } } if (isKeyup(event) && !Modifiers.has(key)) { this.pressedKeys.delete(key); } } set(key, handler, options) { const { keys, modifiers } = parseKeys(key); const combination = createCombinationKey(keys, modifiers); const _options = { ...this._options?.bindingDefaults, ...options }; this.bindings.set(combination, { keys, handler, options: _options, modifiers, }); return this; } setActivateHandler(handler, options) { for (const key of [enterKey, spaceBar]) { this.set(key, handler, options); } return this; } hostConnected() { this._host.addEventListener('keyup', this); this._host.addEventListener('keydown', this); } hostDisconnected() { this._host.removeEventListener('keyup', this); this._host.removeEventListener('keydown', this); } } export function addKeybindings(element, options) { return new KeyBindingController(element, options); } //# sourceMappingURL=key-bindings.js.map