import { guard, createEvent, Event, Store, Target, sample, createStore, Unit, } from 'effector'; import { validateHotkey } from './utils/validate-hotkey'; export const keyup = createEvent(); export const keydown = createEvent(); export const keypress = createEvent(); export const $isShiftDown = createStore(false); export const $isCtrlDown = createStore(false); export const $isAltDown = createStore(false); $isShiftDown.on([keyup, keydown], (prev, evt) => evt.shiftKey); $isCtrlDown.on([keyup, keydown], (prev, evt) => evt.ctrlKey); $isAltDown.on([keyup, keydown], (prev, evt) => evt.altKey); const keyEvents = { keyup, keydown, keypress, }; interface hotkeyT { (key: KeyboardEvent['key'], type?: keyof typeof keyEvents): Event< KeyboardEvent >; (params: { key: KeyboardEvent['key']; type?: keyof typeof keyEvents; filter?: Store; target?: Target; }): Event; } /** Returns `Event` that gets triggered when a certain key pressed (or keyup/keydown events triggered) */ export const hotkey: hotkeyT = (...args) => { const normalizedParams = typeof args[0] === 'string' ? { key: args[0], type: args[1] } : { key: args[0].key, type: args[0].type, filter: args[0].filter, target: args[0].target, }; let keyTriggered = guard({ clock: keyEvents[normalizedParams.type || 'keyup'], filter: validateHotkey(normalizedParams.key), }) as Event; if (normalizedParams.filter) { keyTriggered = guard({ clock: keyTriggered, filter: normalizedParams.filter as Store, }); } if (normalizedParams.target) { // @ts-expect-error sample({ // @ts-expect-error clock: keyTriggered, // @ts-expect-error target: normalizedParams.target, }); } return keyTriggered; }; if (typeof document !== 'undefined') { document.addEventListener('keyup', evt => keyup(evt)); document.addEventListener('keydown', evt => keydown(evt)); document.addEventListener('keypress', evt => keypress(evt)); }