@brr-dev/hotkey
Version:
A simple, lightweight library for binding hotkeys using Vanilla JS, with no external dependencies.
1 lines • 6.33 kB
Source Map (JSON)
{"version":3,"sources":["../src/isMacOS.ts","../src/HotKeyMap.ts","../src/HotKey.ts"],"sourcesContent":["/*\n * @author Brandon Ramirez <brandon@brr.dev>\n * @copyright Copyright (c) 2024\n */\n\n/// <reference types=\"user-agent-data-types\" />\n\nlet _userIsOnMac: boolean;\n\nexport function isMacOS() {\n if (_userIsOnMac === undefined) {\n // Attempt to use the experimental navigator userAgentData object\n if (navigator.userAgentData) {\n _userIsOnMac = navigator.userAgentData.platform === 'macOS';\n } else {\n _userIsOnMac = /mac/i.test(\n navigator.userAgent ?? navigator.platform,\n );\n }\n }\n\n return _userIsOnMac;\n}\n","/*\n * @author Brandon Ramirez <brandon@brr.dev>\n * @copyright Copyright (c) 2024\n */\n\nimport { HotKey } from './HotKey';\n\nclass _HotKeyMap extends Map<HTMLElement, Set<HotKey>> {\n addHotKey(hotkey: HotKey): void {\n this._getCollectionForTarget(hotkey.target).add(hotkey);\n }\n\n removeHotKey(hotkey: HotKey): void {\n if (this.has(hotkey.target)) {\n this.get(hotkey.target)?.delete(hotkey);\n }\n }\n\n private _getCollectionForTarget(target: HTMLElement): Set<HotKey> {\n let hotkeys;\n\n if (this.has(target)) {\n hotkeys = this.get(target) as Set<HotKey>;\n } else {\n hotkeys = new Set<HotKey>();\n this.set(target, hotkeys);\n\n // We need to register the event handler when the set is created\n this._registerEventHandler(target, hotkeys);\n }\n\n return hotkeys;\n }\n\n private _registerEventHandler(\n target: HTMLElement,\n hotkeys: Set<HotKey>,\n ): void {\n target.addEventListener('keydown', function (event) {\n hotkeys.forEach((hotkey) => {\n if (hotkey.satisfiesEvent(event)) {\n try {\n hotkey.callback(event);\n } catch (error) {\n console.warn('Failed to run HotKey');\n console.error(error);\n }\n }\n });\n });\n }\n}\n\nexport default new _HotKeyMap();\n","/*\n * @author Brandon Ramirez <brandon@brr.dev>\n * @copyright Copyright (c) 2024\n */\n\nimport { HotKeyCallback, HotKeyOptions } from './HotKey.types';\nimport { isMacOS } from './isMacOS';\nimport HotKeyMap from './HotKeyMap';\n\nexport class HotKey {\n public key: string;\n public alt: boolean;\n public ctrl: boolean;\n public shift: boolean;\n public target: HTMLElement;\n public callback: HotKeyCallback;\n\n /**\n * Create a new HotKey binding with the given options.\n */\n constructor(options: HotKeyOptions) {\n if (!options.callback) {\n throw new Error('Missing callback for new HotKey');\n }\n\n if (!options.key) {\n throw new Error('Missing key for new HotKey');\n }\n\n this.key = options.key;\n this.callback = options.callback;\n\n this.alt = options.alt ?? false;\n this.ctrl = options.ctrl ?? false;\n this.shift = options.shift ?? false;\n\n this.target = options.target ?? document.body;\n\n // Register the new HotKey after creating it\n HotKeyMap.addHotKey(this);\n }\n\n unbind() {\n HotKeyMap.removeHotKey(this);\n }\n\n satisfiesEvent(event: KeyboardEvent): boolean {\n const isMac = isMacOS();\n\n return (\n this.key === _fixKeyCasing(event.key) &&\n this.shift === event.shiftKey &&\n // Check for the ctrlKey (Control) on Mac, altKey (Alt) on windows\n this.alt === (isMac ? event.ctrlKey : event.altKey) &&\n // Check for the metaKey (Command) on Mac, ctrlKey (Ctrl) on windows\n this.ctrl === (isMac ? event.metaKey : event.ctrlKey)\n );\n }\n\n toString() {\n let str = this.key;\n\n const isMac = isMacOS();\n\n if (this.shift) str = 'Shift + ' + str;\n if (this.ctrl) str = (isMac ? 'Cmd' : 'Ctrl') + ' + ' + str;\n if (this.alt) str = (isMac ? 'Ctrl' : 'Alt') + ' + ' + str;\n\n return str;\n }\n}\n\nfunction _fixKeyCasing(key: string): string {\n return key.charAt(0).toUpperCase() + key.slice(1);\n}\n"],"mappings":";AAOA,IAAI;AAEG,SAAS,UAAU;AAT1B;AAUI,MAAI,iBAAiB,QAAW;AAE5B,QAAI,UAAU,eAAe;AACzB,qBAAe,UAAU,cAAc,aAAa;AAAA,IACxD,OAAO;AACH,qBAAe,OAAO;AAAA,SAClB,eAAU,cAAV,YAAuB,UAAU;AAAA,MACrC;AAAA,IACJ;AAAA,EACJ;AAEA,SAAO;AACX;;;ACfA,IAAM,aAAN,cAAyB,IAA8B;AAAA,EACnD,UAAU,QAAsB;AAC5B,SAAK,wBAAwB,OAAO,MAAM,EAAE,IAAI,MAAM;AAAA,EAC1D;AAAA,EAEA,aAAa,QAAsB;AAZvC;AAaQ,QAAI,KAAK,IAAI,OAAO,MAAM,GAAG;AACzB,iBAAK,IAAI,OAAO,MAAM,MAAtB,mBAAyB,OAAO;AAAA,IACpC;AAAA,EACJ;AAAA,EAEQ,wBAAwB,QAAkC;AAC9D,QAAI;AAEJ,QAAI,KAAK,IAAI,MAAM,GAAG;AAClB,gBAAU,KAAK,IAAI,MAAM;AAAA,IAC7B,OAAO;AACH,gBAAU,oBAAI,IAAY;AAC1B,WAAK,IAAI,QAAQ,OAAO;AAGxB,WAAK,sBAAsB,QAAQ,OAAO;AAAA,IAC9C;AAEA,WAAO;AAAA,EACX;AAAA,EAEQ,sBACJ,QACA,SACI;AACJ,WAAO,iBAAiB,WAAW,SAAU,OAAO;AAChD,cAAQ,QAAQ,CAAC,WAAW;AACxB,YAAI,OAAO,eAAe,KAAK,GAAG;AAC9B,cAAI;AACA,mBAAO,SAAS,KAAK;AAAA,UACzB,SAAS,OAAO;AACZ,oBAAQ,KAAK,sBAAsB;AACnC,oBAAQ,MAAM,KAAK;AAAA,UACvB;AAAA,QACJ;AAAA,MACJ,CAAC;AAAA,IACL,CAAC;AAAA,EACL;AACJ;AAEA,IAAO,oBAAQ,IAAI,WAAW;;;AC5CvB,IAAM,SAAN,MAAa;AAAA;AAAA;AAAA;AAAA,EAWhB,YAAY,SAAwB;AApBxC;AAqBQ,QAAI,CAAC,QAAQ,UAAU;AACnB,YAAM,IAAI,MAAM,iCAAiC;AAAA,IACrD;AAEA,QAAI,CAAC,QAAQ,KAAK;AACd,YAAM,IAAI,MAAM,4BAA4B;AAAA,IAChD;AAEA,SAAK,MAAM,QAAQ;AACnB,SAAK,WAAW,QAAQ;AAExB,SAAK,OAAM,aAAQ,QAAR,YAAe;AAC1B,SAAK,QAAO,aAAQ,SAAR,YAAgB;AAC5B,SAAK,SAAQ,aAAQ,UAAR,YAAiB;AAE9B,SAAK,UAAS,aAAQ,WAAR,YAAkB,SAAS;AAGzC,sBAAU,UAAU,IAAI;AAAA,EAC5B;AAAA,EAEA,SAAS;AACL,sBAAU,aAAa,IAAI;AAAA,EAC/B;AAAA,EAEA,eAAe,OAA+B;AAC1C,UAAM,QAAQ,QAAQ;AAEtB,WACI,KAAK,QAAQ,cAAc,MAAM,GAAG,KACpC,KAAK,UAAU,MAAM;AAAA,IAErB,KAAK,SAAS,QAAQ,MAAM,UAAU,MAAM;AAAA,IAE5C,KAAK,UAAU,QAAQ,MAAM,UAAU,MAAM;AAAA,EAErD;AAAA,EAEA,WAAW;AACP,QAAI,MAAM,KAAK;AAEf,UAAM,QAAQ,QAAQ;AAEtB,QAAI,KAAK,MAAO,OAAM,aAAa;AACnC,QAAI,KAAK,KAAM,QAAO,QAAQ,QAAQ,UAAU,QAAQ;AACxD,QAAI,KAAK,IAAK,QAAO,QAAQ,SAAS,SAAS,QAAQ;AAEvD,WAAO;AAAA,EACX;AACJ;AAEA,SAAS,cAAc,KAAqB;AACxC,SAAO,IAAI,OAAO,CAAC,EAAE,YAAY,IAAI,IAAI,MAAM,CAAC;AACpD;","names":[]}