keybuddy 0.7.0 → 0.8.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/index.cjs ADDED
@@ -0,0 +1,3 @@
1
+ /* keybuddy - Modern keyboard shortcuts library */
2
+ "use strict";var w=Object.defineProperty;var V=Object.getOwnPropertyDescriptor;var W=Object.getOwnPropertyNames;var Y=Object.prototype.hasOwnProperty;var $=(e,o)=>{for(var t in o)w(e,t,{get:o[t],enumerable:!0})},J=(e,o,t,p)=>{if(o&&typeof o=="object"||typeof o=="function")for(let u of W(o))!Y.call(e,u)&&u!==t&&w(e,u,{get:()=>o[u],enumerable:!(p=V(o,u))||p.enumerable});return e};var X=e=>J(w({},"__esModule",{value:!0}),e);var ye={};$(ye,{DEFAULT_SCOPE:()=>g,MODS:()=>i,SPECIAL:()=>m,bindKey:()=>le,createKeybuddy:()=>L,default:()=>ue,destroy:()=>ie,getBoundKeys:()=>ce,getHandlers:()=>de,getScope:()=>ne,isBound:()=>ae,setScope:()=>re,unbindAll:()=>se,unbindKey:()=>pe,unbindScope:()=>oe,unsafeUnbindKey:()=>fe});module.exports=X(ye);var g="all",i={SHIFT:1,ALT:2,CTRL:4,META:8},A={"\u21E7":i.SHIFT,shift:i.SHIFT,"\u2325":i.ALT,alt:i.ALT,option:i.ALT,"\u2303":i.CTRL,ctrl:i.CTRL,control:i.CTRL,"\u2318":i.META,cmd:i.META,command:i.META},m={backspace:"Backspace",tab:"Tab",clear:"Clear",enter:"Enter",return:"Enter",esc:"Escape",escape:"Escape",space:" ",left:"ArrowLeft",up:"ArrowUp",right:"ArrowRight",down:"ArrowDown",del:"Delete",delete:"Delete",home:"Home",end:"End",pageup:"PageUp",pagedown:"PageDown",comma:",",".":".","/":"/","`":"`","-":"-","=":"=",";":";","'":"'","[":"[","]":"]","\\":"\\",Meta:"Meta",MetaLeft:"Meta",MetaRight:"Meta",OS:"Meta",ContextMenu:"Meta",ArrowLeft:"ArrowLeft",ArrowUp:"ArrowUp",ArrowRight:"ArrowRight",ArrowDown:"ArrowDown",Backspace:"Backspace",Tab:"Tab",Clear:"Clear",Enter:"Enter",Escape:"Escape",Delete:"Delete",Home:"Home",End:"End",PageUp:"PageUp",PageDown:"PageDown"},C="CapsLock";var E=e=>(m[e]||e).toLowerCase(),z={shift:!0,alt:!0,control:!0,meta:!0},P=e=>e in z,D=e=>{let o=0;return e.shiftKey&&(o|=i.SHIFT),e.altKey&&(o|=i.ALT),e.ctrlKey&&(o|=i.CTRL),e.metaKey&&(o|=i.META),o};var G=e=>e.reduce((o,t)=>(t in A?o.mods|=A[t]:o.special.push((m[t]||t).toLowerCase()),o),{mods:0,special:[]}),Q=e=>{let t=e.replace(/\s/g,"").split(",");return t[t.length-1]===""&&(t[t.length-2]+=","),t},b=e=>Q(e).map(t=>{let p=t.split("+"),u=p[p.length-1];return{key:E(u),shortcut:G(p)}});var I=typeof navigator<"u"&&navigator.userAgent.includes("Firefox"),F=e=>e.isContentEditable||e.tagName==="INPUT"||e.tagName==="SELECT"||e.tagName==="TEXTAREA",K=(e,o)=>{if(e.length!==o.length)return!1;for(let t=0;t<e.length;t++)if(e[t]!==o[t])return!1;return!0};var Z=e=>e&&!F(e.target),v=new WeakMap;function L(e,o=Z){let t={},p=new Set,u="all",h=0,U=(n,r,d=()=>{},{skipOther:c}={skipOther:!1})=>{let s=typeof r=="function"?"all":r,a=typeof r=="function"?r:d;b(n).forEach(({key:l,shortcut:f})=>{t[l]||(t[l]=[]),t[l].push({scope:s,method:a,shortcut:f,skipOther:c})})},M=(n,r,d="all")=>{b(n).forEach(({key:c,shortcut:s})=>{let a=t[c];if(Array.isArray(a)){let l=t[c].filter(({scope:f,method:y,shortcut:S})=>!(f===d&&S.mods===s.mods&&K(S.special,s.special)&&(r===null||y===r)));l.length?t[c]=l:delete t[c]}})},R=(n,r,d=()=>{})=>{M(n,typeof r=="function"?r:d,typeof r=="function"?"all":r)},N=(n,r)=>M(n,null,r),T=n=>{let r=E(n.key);if(!o(n)||I&&r===C||(h=D(n),!P(r)&&!p.has(r)&&p.add(r),!(r in t)))return;let c=t[r].filter(({scope:a,shortcut:{special:l,mods:f}})=>a!==u?!1:K(l,Array.from(p))&&f===h),s=c.find(a=>a.skipOther);s?s.method(n):c.forEach(({method:a})=>{a(n)})},k=n=>{let r=E(n.key);n.key&&n.key.toLowerCase()==="meta"?p.clear():p.delete(r)},B=n=>{Object.keys(t).forEach(r=>{let d=r,c=t[d].filter(({scope:s})=>s!==n);c.length?t[d]=c:delete t[d]})},_=n=>{u=n},j=()=>{t={},p.clear()},H=()=>{p.clear()},q=()=>{if(p.clear(),t={},e){let n=v.get(e);n&&(e.removeEventListener("keydown",n.dispatch),e.removeEventListener("keyup",n.cleanUp),n.window.removeEventListener("focus",n.reset),v.delete(e))}},x=e.defaultView||window;return v.set(e,{dispatch:T,cleanUp:k,reset:H,window:x}),e.addEventListener("keydown",T),e.addEventListener("keyup",k),x.addEventListener("focus",H),{bind:U,unbind:R,unsafeUnbind:N,unbindScope:B,setScope:_,unbindAll:j,getScope:()=>u,destroy:q,isBound:(n,r)=>{let d=r?.scope||u;return b(n).some(({key:s,shortcut:a})=>{let l=t[s];return l?l.some(f=>f.scope===d&&f.shortcut.mods===a.mods&&K(f.shortcut.special,a.special)):!1})},getBoundKeys:n=>{let r=n?.scope||u,d=new Set;return Object.values(t).forEach(c=>{c.forEach(s=>{if(s.scope===r){let a=[];s.shortcut.mods&i.CTRL&&a.push("ctrl"),s.shortcut.mods&i.ALT&&a.push("alt"),s.shortcut.mods&i.SHIFT&&a.push("shift"),s.shortcut.mods&i.META&&a.push("cmd");let l=s.shortcut.special.join("+")||"",f=[...a,l].filter(Boolean).join("+");f&&d.add(f)}})}),Array.from(d)},getHandlers:(n,r)=>{let d=r?.scope||u,c=b(n),s=[];return c.forEach(({key:a,shortcut:l})=>{let f=t[a];f&&f.forEach(y=>{y.scope===d&&y.shortcut.mods===l.mods&&K(y.shortcut.special,l.special)&&s.push(y.method)})}),s}}}var{bind:O,unbind:ee,unsafeUnbind:te,getScope:ne,setScope:re,unbindScope:oe,unbindAll:se,destroy:ie,isBound:ae,getBoundKeys:ce,getHandlers:de}=L(document),le=O,pe=ee,fe=te;var ue=O;0&&(module.exports={DEFAULT_SCOPE,MODS,SPECIAL,bindKey,createKeybuddy,destroy,getBoundKeys,getHandlers,getScope,isBound,setScope,unbindAll,unbindKey,unbindScope,unsafeUnbindKey});
3
+ //# sourceMappingURL=index.cjs.map
package/index.cjs.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/helpers/keyboard.ts","../src/helpers/keymap.ts","../src/helpers/utils.ts","../src/keybuddy.ts"],"sourcesContent":["import { DEFAULT_SCOPE } from './constants';\nimport { createKeybuddy } from './keybuddy';\n\nexport { createKeybuddy };\n\nconst {\n bind,\n unbind,\n unsafeUnbind,\n getScope,\n setScope,\n unbindScope,\n unbindAll,\n destroy,\n isBound,\n getBoundKeys,\n getHandlers,\n} = createKeybuddy(document);\n\nexport const bindKey = bind;\nexport const unbindKey = unbind;\nexport const unsafeUnbindKey = unsafeUnbind;\n\nexport {\n setScope,\n unbindScope,\n unbindAll,\n getScope,\n destroy,\n isBound,\n getBoundKeys,\n getHandlers,\n DEFAULT_SCOPE,\n};\nexport type { KeyString } from './constants';\nexport { MODS, SPECIAL } from './constants';\n\nexport default bind;\n","export const DEFAULT_SCOPE = 'all';\n\ndeclare const KeyStringBrand: unique symbol;\n\nexport type KeyString = string & { readonly [KeyStringBrand]: true };\n\nexport const MODS = {\n SHIFT: 0b0001, // 1\n ALT: 0b0010, // 2\n CTRL: 0b0100, // 4\n META: 0b1000, // 8\n} as const;\n\n// Map string modifier names to bitwise flags for parsing\nexport type ModifierNames = {\n '⇧': number;\n shift: number;\n '⌥': number;\n alt: number;\n option: number;\n '⌃': number;\n ctrl: number;\n control: number;\n '⌘': number;\n cmd: number;\n command: number;\n};\n\nexport const MODIFIERS: ModifierNames = {\n '⇧': MODS.SHIFT,\n shift: MODS.SHIFT,\n '⌥': MODS.ALT,\n alt: MODS.ALT,\n option: MODS.ALT,\n '⌃': MODS.CTRL,\n ctrl: MODS.CTRL,\n control: MODS.CTRL,\n '⌘': MODS.META,\n cmd: MODS.META,\n command: MODS.META,\n};\n\nexport const SPECIAL: { [key: string]: string } = {\n backspace: 'Backspace',\n tab: 'Tab',\n clear: 'Clear',\n enter: 'Enter',\n return: 'Enter',\n esc: 'Escape',\n escape: 'Escape',\n space: ' ',\n left: 'ArrowLeft',\n up: 'ArrowUp',\n right: 'ArrowRight',\n down: 'ArrowDown',\n del: 'Delete',\n delete: 'Delete',\n home: 'Home',\n end: 'End',\n pageup: 'PageUp',\n pagedown: 'PageDown',\n comma: ',',\n '.': '.',\n '/': '/',\n '`': '`',\n '-': '-',\n '=': '=',\n ';': ';',\n \"'\": \"'\",\n '[': '[',\n ']': ']',\n '\\\\': '\\\\',\n // Normalize Meta key variants\n Meta: 'Meta',\n MetaLeft: 'Meta',\n MetaRight: 'Meta',\n OS: 'Meta', // Some browsers use OS instead of Meta\n ContextMenu: 'Meta', // Right-click context menu key sometimes acts as Meta\n // Add identity mappings for already-normalized keys\n ArrowLeft: 'ArrowLeft',\n ArrowUp: 'ArrowUp',\n ArrowRight: 'ArrowRight',\n ArrowDown: 'ArrowDown',\n Backspace: 'Backspace',\n Tab: 'Tab',\n Clear: 'Clear',\n Enter: 'Enter',\n Escape: 'Escape',\n Delete: 'Delete',\n Home: 'Home',\n End: 'End',\n PageUp: 'PageUp',\n PageDown: 'PageDown',\n};\n\nexport const CAPS_LOCK_KEY = 'CapsLock';\n","import { KeyString, MODS, SPECIAL } from '../constants';\n\nexport const getKeyIdentifier = (key: string): KeyString => {\n return (SPECIAL[key] || key).toLowerCase() as KeyString;\n};\n\nconst MODIFIER_KEYS: Record<string, true> = {\n shift: true,\n alt: true,\n control: true,\n meta: true,\n};\n\nexport const isModifierKey = (key: string): boolean => key in MODIFIER_KEYS;\n\nexport const updateModifiers = (e: KeyboardEvent): number => {\n let modifiers = 0;\n if (e.shiftKey) modifiers |= MODS.SHIFT;\n if (e.altKey) modifiers |= MODS.ALT;\n if (e.ctrlKey) modifiers |= MODS.CTRL;\n if (e.metaKey) modifiers |= MODS.META;\n return modifiers;\n};\n","import { KeyString, MODIFIERS, ModifierNames, SPECIAL } from '../constants';\nimport { getKeyIdentifier } from './keyboard';\n\nexport interface ParsedShortcut {\n mods: number; // Bitwise flag for modifiers\n special: string[];\n}\nexport interface KeyMap {\n key: KeyString;\n shortcut: ParsedShortcut;\n}\n\nconst getMods = (keys: string[]): ParsedShortcut =>\n keys.reduce(\n (acc, key) => {\n if (key in MODIFIERS) {\n acc.mods |= MODIFIERS[key as keyof ModifierNames];\n } else {\n acc.special.push((SPECIAL[key] || key).toLowerCase());\n }\n return acc;\n },\n {\n mods: 0, // Start with no modifiers\n special: [],\n } as ParsedShortcut,\n );\n\nconst getCombinations = (keysStr: string): string[] => {\n const cleanKeys = keysStr.replace(/\\s/g, '');\n const keys = cleanKeys.split(',');\n if (keys[keys.length - 1] === '') {\n keys[keys.length - 2] += ',';\n }\n\n return keys;\n};\n\nexport const getKeyMap = (keysStr: string): KeyMap[] => {\n const keymap = getCombinations(keysStr);\n return keymap.map((keyCmd) => {\n const keys = keyCmd.split('+');\n const key = keys[keys.length - 1];\n const keyIdentifier = getKeyIdentifier(key);\n\n return {\n key: keyIdentifier,\n shortcut: getMods(keys),\n };\n });\n};\n","export const invariant = (\n condition: boolean,\n message: string,\n ...args: unknown[]\n) => {\n if (\n typeof process !== 'undefined' &&\n process.env &&\n process.env.NODE_ENV === 'development' &&\n !condition\n ) {\n throw new Error(\n `Invariant failed: ${message}${args.length ? ` ${JSON.stringify(args)}` : ''}`,\n );\n }\n};\n\nexport const isFirefox =\n typeof navigator !== 'undefined' && navigator.userAgent.includes('Firefox');\n\nexport const isEditable = (el: HTMLElement): boolean =>\n el.isContentEditable ||\n el.tagName === 'INPUT' ||\n el.tagName === 'SELECT' ||\n el.tagName === 'TEXTAREA';\n\nexport const isEqArray = (\n arr1: (string | number)[],\n arr2: (string | number)[],\n): boolean => {\n if (arr1.length !== arr2.length) return false;\n\n for (let i = 0; i < arr1.length; i++) {\n if (arr1[i] !== arr2[i]) return false;\n }\n\n return true;\n};\n","import { CAPS_LOCK_KEY, DEFAULT_SCOPE, KeyString, MODS } from './constants';\nimport { getKeyIdentifier, isModifierKey, updateModifiers } from './helpers/keyboard';\nimport { getKeyMap, ParsedShortcut } from './helpers/keymap';\nimport { invariant, isEditable, isEqArray, isFirefox } from './helpers/utils';\n\ntype KeyHandler = (e: KeyboardEvent) => void;\ntype FilterFn = (el: KeyboardEvent) => boolean;\n\ninterface Handler {\n scope: string;\n method: KeyHandler;\n shortcut: ParsedShortcut;\n skipOther: boolean;\n}\n\nconst defaultFilter = (e: KeyboardEvent): boolean =>\n e && !isEditable(e.target as HTMLElement);\n\nconst documentListeners = new WeakMap<\n Document,\n {\n dispatch: (e: KeyboardEvent) => void;\n cleanUp: (e: KeyboardEvent) => void;\n reset: () => void;\n window: Window & typeof globalThis;\n }\n>();\n\nexport function createKeybuddy(\n doc: Document,\n filterFn: FilterFn = defaultFilter,\n) {\n let handlers: { [key: KeyString]: Handler[] } = {};\n const downKeys: Set<KeyString> = new Set();\n let activeScope = DEFAULT_SCOPE;\n\n let modifiers = 0;\n\n const bindKey = (\n keysStr: string,\n scopeOrMethod: string | KeyHandler,\n methodOrNull: KeyHandler = () => {},\n {\n skipOther,\n }: {\n skipOther: boolean;\n } = {\n skipOther: false,\n },\n ): void => {\n const scope: string =\n typeof scopeOrMethod === 'function' ? DEFAULT_SCOPE : scopeOrMethod;\n const method: KeyHandler =\n typeof scopeOrMethod === 'function' ? scopeOrMethod : methodOrNull;\n\n getKeyMap(keysStr).forEach(({ key, shortcut }) => {\n if (!handlers[key]) {\n handlers[key] = [];\n }\n const handler = handlers[key];\n if (process.env.NODE_ENV === 'development') {\n if (skipOther) {\n const action = handler.find((i) => i.skipOther);\n invariant(\n !action,\n \"Conflicting 'skipOther' property with action\",\n action,\n );\n }\n }\n\n handler.push({\n scope,\n method,\n shortcut,\n skipOther,\n });\n });\n };\n\n const unbindKeyProcess = (\n keysStr: string,\n deleteMethod: null | KeyHandler,\n deleteScope: string = DEFAULT_SCOPE,\n ): void => {\n getKeyMap(keysStr).forEach(({ key, shortcut }) => {\n const handler = handlers[key];\n if (Array.isArray(handler)) {\n const handler = handlers[key].filter(\n ({ scope, method, shortcut: methodShortcut }: Handler) =>\n !(\n scope === deleteScope &&\n methodShortcut.mods === shortcut.mods &&\n isEqArray(methodShortcut.special, shortcut.special) &&\n (deleteMethod === null ? true : method === deleteMethod)\n ),\n );\n if (handler.length) {\n handlers[key] = handler;\n } else {\n delete handlers[key];\n }\n }\n });\n };\n\n const unbindKey = (\n keysStr: string,\n scopeOrMethod: string | KeyHandler,\n methodOrNull: KeyHandler = () => {},\n ) => {\n const deleteScope: string =\n typeof scopeOrMethod === 'function' ? DEFAULT_SCOPE : scopeOrMethod;\n const deleteMethod: KeyHandler =\n typeof scopeOrMethod === 'function' ? scopeOrMethod : methodOrNull;\n unbindKeyProcess(keysStr, deleteMethod, deleteScope);\n };\n\n const unsafeUnbindKey = (keysStr: string, scope?: string) =>\n unbindKeyProcess(keysStr, null, scope);\n\n const dispatch = (e: KeyboardEvent) => {\n const key = getKeyIdentifier(e.key);\n\n if (!filterFn(e)) {\n return;\n }\n\n if (isFirefox && key === CAPS_LOCK_KEY) {\n return;\n }\n\n modifiers = updateModifiers(e);\n\n const isModifier = isModifierKey(key);\n if (!isModifier && !downKeys.has(key)) {\n downKeys.add(key);\n }\n\n if (!(key in handlers)) {\n return;\n }\n\n const currentHandlers = handlers[key].filter(\n ({ scope, shortcut: { special, mods } }) => {\n if (scope !== activeScope) {\n return false;\n }\n\n return isEqArray(special, Array.from(downKeys)) && mods === modifiers;\n },\n );\n\n const primaryAction: Handler | undefined = currentHandlers.find(\n (action) => action.skipOther,\n );\n\n console.log('has it?', primaryAction, currentHandlers);\n if (primaryAction) {\n primaryAction.method(e);\n } else {\n currentHandlers.forEach(({ method }) => {\n method(e);\n });\n }\n };\n\n const cleanUp = (e: KeyboardEvent) => {\n const key = getKeyIdentifier(e.key);\n\n if (e.key && e.key.toLowerCase() === 'meta') {\n downKeys.clear();\n } else {\n downKeys.delete(key);\n }\n };\n\n const unbindScope = (deleteScope: string): void => {\n Object.keys(handlers).forEach((key) => {\n const keyString = key as KeyString;\n const handler = handlers[keyString].filter(\n ({ scope }: Handler) => scope !== deleteScope,\n );\n if (handler.length) {\n handlers[keyString] = handler;\n } else {\n delete handlers[keyString];\n }\n });\n };\n\n const setScope = (scope: string): void => {\n activeScope = scope;\n };\n\n const unbindAll = (): void => {\n handlers = {};\n downKeys.clear();\n };\n\n const reset = (): void => {\n downKeys.clear();\n };\n\n const destroy = (): void => {\n downKeys.clear();\n handlers = {};\n if (doc) {\n const listeners = documentListeners.get(doc);\n if (listeners) {\n doc.removeEventListener('keydown', listeners.dispatch);\n doc.removeEventListener('keyup', listeners.cleanUp);\n listeners.window.removeEventListener('focus', listeners.reset);\n documentListeners.delete(doc);\n }\n }\n };\n\n const win = (doc.defaultView || window) as Window & typeof globalThis;\n\n documentListeners.set(doc, { dispatch, cleanUp, reset, window: win });\n doc.addEventListener('keydown', dispatch);\n doc.addEventListener('keyup', cleanUp);\n win.addEventListener('focus', reset);\n\n const getScope = () => activeScope;\n\n const isBound = (keysStr: string, options?: { scope?: string }): boolean => {\n const scope = options?.scope || activeScope;\n const keyMaps = getKeyMap(keysStr);\n\n return keyMaps.some(({ key, shortcut }) => {\n const keyHandlers = handlers[key];\n if (!keyHandlers) return false;\n\n return keyHandlers.some(\n (h) =>\n h.scope === scope &&\n h.shortcut.mods === shortcut.mods &&\n isEqArray(h.shortcut.special, shortcut.special),\n );\n });\n };\n\n const getBoundKeys = (options?: { scope?: string }): string[] => {\n const scope = options?.scope || activeScope;\n const keys = new Set<string>();\n\n Object.values(handlers).forEach((handlerList) => {\n handlerList.forEach((handler) => {\n if (handler.scope === scope) {\n const modParts: string[] = [];\n if (handler.shortcut.mods & MODS.CTRL) modParts.push('ctrl');\n if (handler.shortcut.mods & MODS.ALT) modParts.push('alt');\n if (handler.shortcut.mods & MODS.SHIFT) modParts.push('shift');\n if (handler.shortcut.mods & MODS.META) modParts.push('cmd');\n\n const keyPart = handler.shortcut.special.join('+') || '';\n const fullKey = [...modParts, keyPart].filter(Boolean).join('+');\n if (fullKey) keys.add(fullKey);\n }\n });\n });\n\n return Array.from(keys);\n };\n\n const getHandlers = (\n keysStr: string,\n options?: { scope?: string },\n ): KeyHandler[] => {\n const scope = options?.scope || activeScope;\n const keyMaps = getKeyMap(keysStr);\n const result: KeyHandler[] = [];\n\n keyMaps.forEach(({ key, shortcut }) => {\n const keyHandlers = handlers[key];\n if (!keyHandlers) return;\n\n keyHandlers.forEach((h) => {\n if (\n h.scope === scope &&\n h.shortcut.mods === shortcut.mods &&\n isEqArray(h.shortcut.special, shortcut.special)\n ) {\n result.push(h.method);\n }\n });\n });\n\n return result;\n };\n\n return {\n bind: bindKey,\n unbind: unbindKey,\n unsafeUnbind: unsafeUnbindKey,\n unbindScope,\n setScope,\n unbindAll,\n getScope,\n destroy,\n isBound,\n getBoundKeys,\n getHandlers,\n };\n}\n"],"mappings":"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","names":["src_exports","__export","DEFAULT_SCOPE","MODS","SPECIAL","bindKey","createKeybuddy","src_default","destroy","getBoundKeys","getHandlers","getScope","isBound","setScope","unbindAll","unbindKey","unbindScope","unsafeUnbindKey","__toCommonJS","DEFAULT_SCOPE","MODS","MODIFIERS","SPECIAL","CAPS_LOCK_KEY","getKeyIdentifier","key","SPECIAL","MODIFIER_KEYS","isModifierKey","updateModifiers","modifiers","MODS","getMods","keys","acc","key","MODIFIERS","SPECIAL","getCombinations","keysStr","getKeyMap","keyCmd","getKeyIdentifier","isFirefox","isEditable","el","isEqArray","arr1","arr2","i","defaultFilter","isEditable","documentListeners","createKeybuddy","doc","filterFn","handlers","downKeys","activeScope","modifiers","bindKey","keysStr","scopeOrMethod","methodOrNull","skipOther","scope","method","getKeyMap","key","shortcut","unbindKeyProcess","deleteMethod","deleteScope","handler","methodShortcut","isEqArray","unbindKey","unsafeUnbindKey","dispatch","e","getKeyIdentifier","isFirefox","CAPS_LOCK_KEY","updateModifiers","isModifierKey","currentHandlers","special","mods","primaryAction","action","cleanUp","unbindScope","keyString","setScope","unbindAll","reset","destroy","listeners","win","options","keyHandlers","h","keys","handlerList","modParts","MODS","keyPart","fullKey","keyMaps","result","bind","unbind","unsafeUnbind","getScope","setScope","unbindScope","unbindAll","destroy","isBound","getBoundKeys","getHandlers","createKeybuddy","bindKey","unbindKey","unsafeUnbindKey","src_default","bind"]}
package/index.global.js CHANGED
@@ -1,3 +1,3 @@
1
1
  /* keybuddy - Modern keyboard shortcuts library */
2
- "use strict";var keybuddy=(()=>{var A=Object.defineProperty;var q=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var W=Object.prototype.hasOwnProperty;var $=(e,o)=>{for(var t in o)A(e,t,{get:o[t],enumerable:!0})},Y=(e,o,t,p)=>{if(o&&typeof o=="object"||typeof o=="function")for(let u of V(o))!W.call(e,u)&&u!==t&&A(e,u,{get:()=>o[u],enumerable:!(p=q(o,u))||p.enumerable});return e};var J=e=>Y(A({},"__esModule",{value:!0}),e);var fe={};$(fe,{DEFAULT_SCOPE:()=>g,MODS:()=>s,SPECIAL:()=>m,bindKey:()=>ce,createKeybuddy:()=>T,default:()=>pe,destroy:()=>oe,getBoundKeys:()=>ie,getHandlers:()=>ae,getScope:()=>ee,isBound:()=>se,setScope:()=>te,unbindAll:()=>re,unbindKey:()=>de,unbindScope:()=>ne,unsafeUnbindKey:()=>le});var g="all",s={SHIFT:1,ALT:2,CTRL:4,META:8},w={"\u21E7":s.SHIFT,shift:s.SHIFT,"\u2325":s.ALT,alt:s.ALT,option:s.ALT,"\u2303":s.CTRL,ctrl:s.CTRL,control:s.CTRL,"\u2318":s.META,cmd:s.META,command:s.META},m={backspace:"Backspace",tab:"Tab",clear:"Clear",enter:"Enter",return:"Enter",esc:"Escape",escape:"Escape",space:" ",left:"ArrowLeft",up:"ArrowUp",right:"ArrowRight",down:"ArrowDown",del:"Delete",delete:"Delete",home:"Home",end:"End",pageup:"PageUp",pagedown:"PageDown",comma:",",".":".","/":"/","`":"`","-":"-","=":"=",";":";","'":"'","[":"[","]":"]","\\":"\\",Meta:"Meta",MetaLeft:"Meta",MetaRight:"Meta",OS:"Meta",ContextMenu:"Meta",ArrowLeft:"ArrowLeft",ArrowUp:"ArrowUp",ArrowRight:"ArrowRight",ArrowDown:"ArrowDown",Backspace:"Backspace",Tab:"Tab",Clear:"Clear",Enter:"Enter",Escape:"Escape",Delete:"Delete",Home:"Home",End:"End",PageUp:"PageUp",PageDown:"PageDown"},P="CapsLock";var E=e=>m[e]||e.toUpperCase(),D=e=>{let o=0;return e.shiftKey&&(o|=s.SHIFT),e.altKey&&(o|=s.ALT),e.ctrlKey&&(o|=s.CTRL),e.metaKey&&(o|=s.META),o};var X=e=>e.reduce((o,t)=>(t in w?o.mods|=w[t]:o.special.push(m[t]||t.toUpperCase()),o),{mods:0,special:[]}),z=e=>{let t=e.replace(/\s/g,"").split(",");return t[t.length-1]===""&&(t[t.length-2]+=","),t},K=e=>z(e).map(t=>{let p=t.split("+"),u=p[p.length-1];return{key:E(u),shortcut:X(p)}});var I=typeof navigator<"u"&&navigator.userAgent.includes("Firefox"),F=e=>e.isContentEditable||e.tagName==="INPUT"||e.tagName==="SELECT"||e.tagName==="TEXTAREA",b=(e,o)=>{if(e.length!==o.length)return!1;for(let t=0;t<e.length;t++)if(e[t]!==o[t])return!1;return!0};var G=e=>e&&!F(e.target),v=new WeakMap;function T(e,o=G){let t={},p=new Set,u="all",h=0,O=(r,n,d=()=>{},{skipOther:c}={skipOther:!1})=>{let i=typeof n=="function"?"all":n,a=typeof n=="function"?n:d;K(r).forEach(({key:l,shortcut:f})=>{t[l]||(t[l]=[]),t[l].push({scope:i,method:a,shortcut:f,skipOther:c})})},L=(r,n,d="all")=>{K(r).forEach(({key:c,shortcut:i})=>{let a=t[c];if(Array.isArray(a)){let l=t[c].filter(({scope:f,method:y,shortcut:S})=>!(f===d&&S.mods===i.mods&&b(S.special,i.special)&&(n===null||y===n)));l.length?t[c]=l:delete t[c]}})},R=(r,n,d=()=>{})=>{L(r,typeof n=="function"?n:d,typeof n=="function"?"all":n)},N=(r,n)=>L(r,null,n),k=r=>{let n=E(r.key);if(!o(r)||I&&n===P||(h=D(r),!(n==="SHIFT"||n==="ALT"||n==="CTRL"||n==="META")&&!p.has(n)&&p.add(n),!(n in t)))return;let c=t[n].filter(({scope:a,shortcut:{special:l,mods:f}})=>a!==u?!1:b(l,Array.from(p))&&f===h),i=c.find(a=>a.skipOther);i?i.method(r):c.forEach(({method:a})=>{a(r)})},M=r=>{let n=E(r.key);r.key&&r.key.toLowerCase()==="meta"?p.clear():p.delete(n)},B=r=>{Object.keys(t).forEach(n=>{let d=n,c=t[d].filter(({scope:i})=>i!==r);c.length?t[d]=c:delete t[d]})},_=r=>{u=r},j=()=>{t={},p.clear()},H=()=>{p.clear()},C=()=>{if(p.clear(),t={},e){let r=v.get(e);r&&(e.removeEventListener("keydown",r.dispatch),e.removeEventListener("keyup",r.cleanUp),r.window.removeEventListener("focus",r.reset),v.delete(e))}};C();let x=e.defaultView||window;return v.set(e,{dispatch:k,cleanUp:M,reset:H,window:x}),e.addEventListener("keydown",k),e.addEventListener("keyup",M),x.addEventListener("focus",H),{bind:O,unbind:R,unsafeUnbind:N,unbindScope:B,setScope:_,unbindAll:j,getScope:()=>u,destroy:C,isBound:(r,n)=>{let d=n?.scope||u;return K(r).some(({key:i,shortcut:a})=>{let l=t[i];return l?l.some(f=>f.scope===d&&f.shortcut.mods===a.mods&&b(f.shortcut.special,a.special)):!1})},getBoundKeys:r=>{let n=r?.scope||u,d=new Set;return Object.values(t).forEach(c=>{c.forEach(i=>{if(i.scope===n){let a=[];i.shortcut.mods&s.CTRL&&a.push("ctrl"),i.shortcut.mods&s.ALT&&a.push("alt"),i.shortcut.mods&s.SHIFT&&a.push("shift"),i.shortcut.mods&s.META&&a.push("cmd");let l=i.shortcut.special.join("+")||"",f=[...a,l].filter(Boolean).join("+");f&&d.add(f)}})}),Array.from(d)},getHandlers:(r,n)=>{let d=n?.scope||u,c=K(r),i=[];return c.forEach(({key:a,shortcut:l})=>{let f=t[a];f&&f.forEach(y=>{y.scope===d&&y.shortcut.mods===l.mods&&b(y.shortcut.special,l.special)&&i.push(y.method)})}),i}}}var{bind:U,unbind:Q,unsafeUnbind:Z,getScope:ee,setScope:te,unbindScope:ne,unbindAll:re,destroy:oe,isBound:se,getBoundKeys:ie,getHandlers:ae}=T(document),ce=U,de=Q,le=Z;var pe=U;return J(fe);})();
2
+ "use strict";var keybuddy=(()=>{var w=Object.defineProperty;var V=Object.getOwnPropertyDescriptor;var W=Object.getOwnPropertyNames;var Y=Object.prototype.hasOwnProperty;var $=(e,o)=>{for(var t in o)w(e,t,{get:o[t],enumerable:!0})},J=(e,o,t,p)=>{if(o&&typeof o=="object"||typeof o=="function")for(let u of W(o))!Y.call(e,u)&&u!==t&&w(e,u,{get:()=>o[u],enumerable:!(p=V(o,u))||p.enumerable});return e};var X=e=>J(w({},"__esModule",{value:!0}),e);var ye={};$(ye,{DEFAULT_SCOPE:()=>g,MODS:()=>i,SPECIAL:()=>m,bindKey:()=>le,createKeybuddy:()=>L,default:()=>ue,destroy:()=>ie,getBoundKeys:()=>ce,getHandlers:()=>de,getScope:()=>ne,isBound:()=>ae,setScope:()=>re,unbindAll:()=>se,unbindKey:()=>pe,unbindScope:()=>oe,unsafeUnbindKey:()=>fe});var g="all",i={SHIFT:1,ALT:2,CTRL:4,META:8},A={"\u21E7":i.SHIFT,shift:i.SHIFT,"\u2325":i.ALT,alt:i.ALT,option:i.ALT,"\u2303":i.CTRL,ctrl:i.CTRL,control:i.CTRL,"\u2318":i.META,cmd:i.META,command:i.META},m={backspace:"Backspace",tab:"Tab",clear:"Clear",enter:"Enter",return:"Enter",esc:"Escape",escape:"Escape",space:" ",left:"ArrowLeft",up:"ArrowUp",right:"ArrowRight",down:"ArrowDown",del:"Delete",delete:"Delete",home:"Home",end:"End",pageup:"PageUp",pagedown:"PageDown",comma:",",".":".","/":"/","`":"`","-":"-","=":"=",";":";","'":"'","[":"[","]":"]","\\":"\\",Meta:"Meta",MetaLeft:"Meta",MetaRight:"Meta",OS:"Meta",ContextMenu:"Meta",ArrowLeft:"ArrowLeft",ArrowUp:"ArrowUp",ArrowRight:"ArrowRight",ArrowDown:"ArrowDown",Backspace:"Backspace",Tab:"Tab",Clear:"Clear",Enter:"Enter",Escape:"Escape",Delete:"Delete",Home:"Home",End:"End",PageUp:"PageUp",PageDown:"PageDown"},C="CapsLock";var E=e=>(m[e]||e).toLowerCase(),z={shift:!0,alt:!0,control:!0,meta:!0},P=e=>e in z,D=e=>{let o=0;return e.shiftKey&&(o|=i.SHIFT),e.altKey&&(o|=i.ALT),e.ctrlKey&&(o|=i.CTRL),e.metaKey&&(o|=i.META),o};var G=e=>e.reduce((o,t)=>(t in A?o.mods|=A[t]:o.special.push((m[t]||t).toLowerCase()),o),{mods:0,special:[]}),Q=e=>{let t=e.replace(/\s/g,"").split(",");return t[t.length-1]===""&&(t[t.length-2]+=","),t},b=e=>Q(e).map(t=>{let p=t.split("+"),u=p[p.length-1];return{key:E(u),shortcut:G(p)}});var I=typeof navigator<"u"&&navigator.userAgent.includes("Firefox"),F=e=>e.isContentEditable||e.tagName==="INPUT"||e.tagName==="SELECT"||e.tagName==="TEXTAREA",K=(e,o)=>{if(e.length!==o.length)return!1;for(let t=0;t<e.length;t++)if(e[t]!==o[t])return!1;return!0};var Z=e=>e&&!F(e.target),v=new WeakMap;function L(e,o=Z){let t={},p=new Set,u="all",h=0,U=(n,r,d=()=>{},{skipOther:c}={skipOther:!1})=>{let s=typeof r=="function"?"all":r,a=typeof r=="function"?r:d;b(n).forEach(({key:l,shortcut:f})=>{t[l]||(t[l]=[]),t[l].push({scope:s,method:a,shortcut:f,skipOther:c})})},M=(n,r,d="all")=>{b(n).forEach(({key:c,shortcut:s})=>{let a=t[c];if(Array.isArray(a)){let l=t[c].filter(({scope:f,method:y,shortcut:S})=>!(f===d&&S.mods===s.mods&&K(S.special,s.special)&&(r===null||y===r)));l.length?t[c]=l:delete t[c]}})},R=(n,r,d=()=>{})=>{M(n,typeof r=="function"?r:d,typeof r=="function"?"all":r)},N=(n,r)=>M(n,null,r),T=n=>{let r=E(n.key);if(!o(n)||I&&r===C||(h=D(n),!P(r)&&!p.has(r)&&p.add(r),!(r in t)))return;let c=t[r].filter(({scope:a,shortcut:{special:l,mods:f}})=>a!==u?!1:K(l,Array.from(p))&&f===h),s=c.find(a=>a.skipOther);s?s.method(n):c.forEach(({method:a})=>{a(n)})},k=n=>{let r=E(n.key);n.key&&n.key.toLowerCase()==="meta"?p.clear():p.delete(r)},B=n=>{Object.keys(t).forEach(r=>{let d=r,c=t[d].filter(({scope:s})=>s!==n);c.length?t[d]=c:delete t[d]})},_=n=>{u=n},j=()=>{t={},p.clear()},H=()=>{p.clear()},q=()=>{if(p.clear(),t={},e){let n=v.get(e);n&&(e.removeEventListener("keydown",n.dispatch),e.removeEventListener("keyup",n.cleanUp),n.window.removeEventListener("focus",n.reset),v.delete(e))}},x=e.defaultView||window;return v.set(e,{dispatch:T,cleanUp:k,reset:H,window:x}),e.addEventListener("keydown",T),e.addEventListener("keyup",k),x.addEventListener("focus",H),{bind:U,unbind:R,unsafeUnbind:N,unbindScope:B,setScope:_,unbindAll:j,getScope:()=>u,destroy:q,isBound:(n,r)=>{let d=r?.scope||u;return b(n).some(({key:s,shortcut:a})=>{let l=t[s];return l?l.some(f=>f.scope===d&&f.shortcut.mods===a.mods&&K(f.shortcut.special,a.special)):!1})},getBoundKeys:n=>{let r=n?.scope||u,d=new Set;return Object.values(t).forEach(c=>{c.forEach(s=>{if(s.scope===r){let a=[];s.shortcut.mods&i.CTRL&&a.push("ctrl"),s.shortcut.mods&i.ALT&&a.push("alt"),s.shortcut.mods&i.SHIFT&&a.push("shift"),s.shortcut.mods&i.META&&a.push("cmd");let l=s.shortcut.special.join("+")||"",f=[...a,l].filter(Boolean).join("+");f&&d.add(f)}})}),Array.from(d)},getHandlers:(n,r)=>{let d=r?.scope||u,c=b(n),s=[];return c.forEach(({key:a,shortcut:l})=>{let f=t[a];f&&f.forEach(y=>{y.scope===d&&y.shortcut.mods===l.mods&&K(y.shortcut.special,l.special)&&s.push(y.method)})}),s}}}var{bind:O,unbind:ee,unsafeUnbind:te,getScope:ne,setScope:re,unbindScope:oe,unbindAll:se,destroy:ie,isBound:ae,getBoundKeys:ce,getHandlers:de}=L(document),le=O,pe=ee,fe=te;var ue=O;return X(ye);})();
3
3
  //# sourceMappingURL=index.global.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/helpers/keyboard.ts","../src/helpers/keymap.ts","../src/helpers/utils.ts","../src/keybuddy.ts"],"sourcesContent":["import { DEFAULT_SCOPE } from './constants';\nimport { createKeybuddy } from './keybuddy';\n\nexport { createKeybuddy };\n\nconst {\n bind,\n unbind,\n unsafeUnbind,\n getScope,\n setScope,\n unbindScope,\n unbindAll,\n destroy,\n isBound,\n getBoundKeys,\n getHandlers,\n} = createKeybuddy(document);\n\nexport const bindKey = bind;\nexport const unbindKey = unbind;\nexport const unsafeUnbindKey = unsafeUnbind;\n\nexport {\n setScope,\n unbindScope,\n unbindAll,\n getScope,\n destroy,\n isBound,\n getBoundKeys,\n getHandlers,\n DEFAULT_SCOPE,\n};\nexport type { KeyString } from './constants';\nexport { MODS, SPECIAL } from './constants';\n\nexport default bind;\n","export const DEFAULT_SCOPE = 'all';\n\ndeclare const KeyStringBrand: unique symbol;\n\nexport type KeyString = string & { readonly [KeyStringBrand]: true };\n\nexport const MODS = {\n SHIFT: 0b0001, // 1\n ALT: 0b0010, // 2\n CTRL: 0b0100, // 4\n META: 0b1000, // 8\n} as const;\n\n// Map string modifier names to bitwise flags for parsing\nexport type ModifierNames = {\n '⇧': number;\n shift: number;\n '⌥': number;\n alt: number;\n option: number;\n '⌃': number;\n ctrl: number;\n control: number;\n '⌘': number;\n cmd: number;\n command: number;\n};\n\nexport const MODIFIERS: ModifierNames = {\n '⇧': MODS.SHIFT,\n shift: MODS.SHIFT,\n '⌥': MODS.ALT,\n alt: MODS.ALT,\n option: MODS.ALT,\n '⌃': MODS.CTRL,\n ctrl: MODS.CTRL,\n control: MODS.CTRL,\n '⌘': MODS.META,\n cmd: MODS.META,\n command: MODS.META,\n};\n\nexport const SPECIAL: { [key: string]: string } = {\n backspace: 'Backspace',\n tab: 'Tab',\n clear: 'Clear',\n enter: 'Enter',\n return: 'Enter',\n esc: 'Escape',\n escape: 'Escape',\n space: ' ',\n left: 'ArrowLeft',\n up: 'ArrowUp',\n right: 'ArrowRight',\n down: 'ArrowDown',\n del: 'Delete',\n delete: 'Delete',\n home: 'Home',\n end: 'End',\n pageup: 'PageUp',\n pagedown: 'PageDown',\n comma: ',',\n '.': '.',\n '/': '/',\n '`': '`',\n '-': '-',\n '=': '=',\n ';': ';',\n \"'\": \"'\",\n '[': '[',\n ']': ']',\n '\\\\': '\\\\',\n // Normalize Meta key variants\n Meta: 'Meta',\n MetaLeft: 'Meta',\n MetaRight: 'Meta',\n OS: 'Meta', // Some browsers use OS instead of Meta\n ContextMenu: 'Meta', // Right-click context menu key sometimes acts as Meta\n // Add identity mappings for already-normalized keys\n ArrowLeft: 'ArrowLeft',\n ArrowUp: 'ArrowUp',\n ArrowRight: 'ArrowRight',\n ArrowDown: 'ArrowDown',\n Backspace: 'Backspace',\n Tab: 'Tab',\n Clear: 'Clear',\n Enter: 'Enter',\n Escape: 'Escape',\n Delete: 'Delete',\n Home: 'Home',\n End: 'End',\n PageUp: 'PageUp',\n PageDown: 'PageDown',\n};\n\nexport const CAPS_LOCK_KEY = 'CapsLock';\n","import { KeyString, MODS, SPECIAL } from '../constants';\n\nexport const getKeyIdentifier = (key: string): KeyString => {\n return (SPECIAL[key] || key.toUpperCase()) as KeyString;\n};\n\nexport const updateModifiers = (e: KeyboardEvent): number => {\n let modifiers = 0;\n if (e.shiftKey) modifiers |= MODS.SHIFT;\n if (e.altKey) modifiers |= MODS.ALT;\n if (e.ctrlKey) modifiers |= MODS.CTRL;\n if (e.metaKey) modifiers |= MODS.META;\n return modifiers;\n};\n","import { KeyString, MODIFIERS, ModifierNames, SPECIAL } from '../constants';\nimport { getKeyIdentifier } from './keyboard';\n\nexport interface ParsedShortcut {\n mods: number; // Bitwise flag for modifiers\n special: string[];\n}\nexport interface KeyMap {\n key: KeyString;\n shortcut: ParsedShortcut;\n}\n\nconst getMods = (keys: string[]): ParsedShortcut =>\n keys.reduce(\n (acc, key) => {\n if (key in MODIFIERS) {\n acc.mods |= MODIFIERS[key as keyof ModifierNames];\n } else {\n acc.special.push(SPECIAL[key] || key.toUpperCase());\n }\n return acc;\n },\n {\n mods: 0, // Start with no modifiers\n special: [],\n } as ParsedShortcut,\n );\n\nconst getCombinations = (keysStr: string): string[] => {\n const cleanKeys = keysStr.replace(/\\s/g, '');\n const keys = cleanKeys.split(',');\n if (keys[keys.length - 1] === '') {\n keys[keys.length - 2] += ',';\n }\n\n return keys;\n};\n\nexport const getKeyMap = (keysStr: string): KeyMap[] => {\n const keymap = getCombinations(keysStr);\n return keymap.map((keyCmd) => {\n const keys = keyCmd.split('+');\n const key = keys[keys.length - 1];\n const keyIdentifier = getKeyIdentifier(key);\n\n return {\n key: keyIdentifier,\n shortcut: getMods(keys),\n };\n });\n};\n","export const invariant = (\n condition: boolean,\n message: string,\n ...args: unknown[]\n) => {\n if (\n typeof process !== 'undefined' &&\n process.env &&\n process.env.NODE_ENV === 'development' &&\n !condition\n ) {\n throw new Error(\n `Invariant failed: ${message}${args.length ? ` ${JSON.stringify(args)}` : ''}`,\n );\n }\n};\n\nexport const isFirefox =\n typeof navigator !== 'undefined' && navigator.userAgent.includes('Firefox');\n\nexport const isEditable = (el: HTMLElement): boolean =>\n el.isContentEditable ||\n el.tagName === 'INPUT' ||\n el.tagName === 'SELECT' ||\n el.tagName === 'TEXTAREA';\n\nexport const isEqArray = (\n arr1: (string | number)[],\n arr2: (string | number)[],\n): boolean => {\n if (arr1.length !== arr2.length) return false;\n\n for (let i = 0; i < arr1.length; i++) {\n if (arr1[i] !== arr2[i]) return false;\n }\n\n return true;\n};\n","import { CAPS_LOCK_KEY, DEFAULT_SCOPE, KeyString, MODS } from './constants';\nimport { getKeyIdentifier, updateModifiers } from './helpers/keyboard';\nimport { getKeyMap, ParsedShortcut } from './helpers/keymap';\nimport { invariant, isEditable, isEqArray, isFirefox } from './helpers/utils';\n\ntype KeyHandler = (e: KeyboardEvent) => void;\ntype FilterFn = (el: KeyboardEvent) => boolean;\n\ninterface Handler {\n scope: string;\n method: KeyHandler;\n shortcut: ParsedShortcut;\n skipOther: boolean;\n}\n\nconst defaultFilter = (e: KeyboardEvent): boolean =>\n e && !isEditable(e.target as HTMLElement);\n\nconst documentListeners = new WeakMap<\n Document,\n {\n dispatch: (e: KeyboardEvent) => void;\n cleanUp: (e: KeyboardEvent) => void;\n reset: () => void;\n window: Window & typeof globalThis;\n }\n>();\n\nexport function createKeybuddy(\n doc: Document,\n filterFn: FilterFn = defaultFilter,\n) {\n let handlers: { [key: KeyString]: Handler[] } = {};\n const downKeys: Set<KeyString> = new Set();\n let activeScope = DEFAULT_SCOPE;\n\n let modifiers = 0;\n\n const bindKey = (\n keysStr: string,\n scopeOrMethod: string | KeyHandler,\n methodOrNull: KeyHandler = () => {},\n {\n skipOther,\n }: {\n skipOther: boolean;\n } = {\n skipOther: false,\n },\n ): void => {\n const scope: string =\n typeof scopeOrMethod === 'function' ? DEFAULT_SCOPE : scopeOrMethod;\n const method: KeyHandler =\n typeof scopeOrMethod === 'function' ? scopeOrMethod : methodOrNull;\n\n getKeyMap(keysStr).forEach(({ key, shortcut }) => {\n if (!handlers[key]) {\n handlers[key] = [];\n }\n const handler = handlers[key];\n if (process.env.NODE_ENV === 'development') {\n if (skipOther) {\n const action = handler.find((i) => i.skipOther);\n invariant(\n !action,\n \"Conflicting 'skipOther' property with action\",\n action,\n );\n }\n }\n\n handler.push({\n scope,\n method,\n shortcut,\n skipOther,\n });\n });\n };\n\n const unbindKeyProcess = (\n keysStr: string,\n deleteMethod: null | KeyHandler,\n deleteScope: string = DEFAULT_SCOPE,\n ): void => {\n getKeyMap(keysStr).forEach(({ key, shortcut }) => {\n const handler = handlers[key];\n if (Array.isArray(handler)) {\n const handler = handlers[key].filter(\n ({ scope, method, shortcut: methodShortcut }: Handler) =>\n !(\n scope === deleteScope &&\n methodShortcut.mods === shortcut.mods &&\n isEqArray(methodShortcut.special, shortcut.special) &&\n (deleteMethod === null ? true : method === deleteMethod)\n ),\n );\n if (handler.length) {\n handlers[key] = handler;\n } else {\n delete handlers[key];\n }\n }\n });\n };\n\n const unbindKey = (\n keysStr: string,\n scopeOrMethod: string | KeyHandler,\n methodOrNull: KeyHandler = () => {},\n ) => {\n const deleteScope: string =\n typeof scopeOrMethod === 'function' ? DEFAULT_SCOPE : scopeOrMethod;\n const deleteMethod: KeyHandler =\n typeof scopeOrMethod === 'function' ? scopeOrMethod : methodOrNull;\n unbindKeyProcess(keysStr, deleteMethod, deleteScope);\n };\n\n const unsafeUnbindKey = (keysStr: string, scope?: string) =>\n unbindKeyProcess(keysStr, null, scope);\n\n const dispatch = (e: KeyboardEvent) => {\n const key = getKeyIdentifier(e.key);\n\n if (!filterFn(e)) {\n return;\n }\n\n if (isFirefox && key === CAPS_LOCK_KEY) {\n return;\n }\n\n modifiers = updateModifiers(e);\n\n const isModifierKey =\n key === ('SHIFT' as KeyString) ||\n key === ('ALT' as KeyString) ||\n key === ('CTRL' as KeyString) ||\n key === ('META' as KeyString);\n if (!isModifierKey && !downKeys.has(key)) {\n downKeys.add(key);\n }\n\n if (!(key in handlers)) {\n return;\n }\n\n const currentHandlers = handlers[key].filter(\n ({ scope, shortcut: { special, mods } }) => {\n if (scope !== activeScope) {\n return false;\n }\n\n return isEqArray(special, Array.from(downKeys)) && mods === modifiers;\n },\n );\n\n const primaryAction: Handler | undefined = currentHandlers.find(\n (action) => action.skipOther,\n );\n if (primaryAction) {\n primaryAction.method(e);\n } else {\n currentHandlers.forEach(({ method }) => {\n method(e);\n });\n }\n };\n\n const cleanUp = (e: KeyboardEvent) => {\n const key = getKeyIdentifier(e.key);\n\n if (e.key && e.key.toLowerCase() === 'meta') {\n downKeys.clear();\n } else {\n downKeys.delete(key);\n }\n };\n\n const unbindScope = (deleteScope: string): void => {\n Object.keys(handlers).forEach((key) => {\n const keyString = key as KeyString;\n const handler = handlers[keyString].filter(\n ({ scope }: Handler) => scope !== deleteScope,\n );\n if (handler.length) {\n handlers[keyString] = handler;\n } else {\n delete handlers[keyString];\n }\n });\n };\n\n const setScope = (scope: string): void => {\n activeScope = scope;\n };\n\n const unbindAll = (): void => {\n handlers = {};\n downKeys.clear();\n };\n\n const reset = (): void => {\n downKeys.clear();\n };\n\n const destroy = (): void => {\n downKeys.clear();\n handlers = {};\n if (doc) {\n const listeners = documentListeners.get(doc);\n if (listeners) {\n doc.removeEventListener('keydown', listeners.dispatch);\n doc.removeEventListener('keyup', listeners.cleanUp);\n listeners.window.removeEventListener('focus', listeners.reset);\n documentListeners.delete(doc);\n }\n }\n };\n\n destroy();\n\n const win = (doc.defaultView || window) as Window & typeof globalThis;\n\n documentListeners.set(doc, { dispatch, cleanUp, reset, window: win });\n doc.addEventListener('keydown', dispatch);\n doc.addEventListener('keyup', cleanUp);\n win.addEventListener('focus', reset);\n\n const getScope = () => activeScope;\n\n const isBound = (keysStr: string, options?: { scope?: string }): boolean => {\n const scope = options?.scope || activeScope;\n const keyMaps = getKeyMap(keysStr);\n\n return keyMaps.some(({ key, shortcut }) => {\n const keyHandlers = handlers[key];\n if (!keyHandlers) return false;\n\n return keyHandlers.some(\n (h) =>\n h.scope === scope &&\n h.shortcut.mods === shortcut.mods &&\n isEqArray(h.shortcut.special, shortcut.special),\n );\n });\n };\n\n const getBoundKeys = (options?: { scope?: string }): string[] => {\n const scope = options?.scope || activeScope;\n const keys = new Set<string>();\n\n Object.values(handlers).forEach((handlerList) => {\n handlerList.forEach((handler) => {\n if (handler.scope === scope) {\n const modParts: string[] = [];\n if (handler.shortcut.mods & MODS.CTRL) modParts.push('ctrl');\n if (handler.shortcut.mods & MODS.ALT) modParts.push('alt');\n if (handler.shortcut.mods & MODS.SHIFT) modParts.push('shift');\n if (handler.shortcut.mods & MODS.META) modParts.push('cmd');\n\n const keyPart = handler.shortcut.special.join('+') || '';\n const fullKey = [...modParts, keyPart].filter(Boolean).join('+');\n if (fullKey) keys.add(fullKey);\n }\n });\n });\n\n return Array.from(keys);\n };\n\n const getHandlers = (\n keysStr: string,\n options?: { scope?: string },\n ): KeyHandler[] => {\n const scope = options?.scope || activeScope;\n const keyMaps = getKeyMap(keysStr);\n const result: KeyHandler[] = [];\n\n keyMaps.forEach(({ key, shortcut }) => {\n const keyHandlers = handlers[key];\n if (!keyHandlers) return;\n\n keyHandlers.forEach((h) => {\n if (\n h.scope === scope &&\n h.shortcut.mods === shortcut.mods &&\n isEqArray(h.shortcut.special, shortcut.special)\n ) {\n result.push(h.method);\n }\n });\n });\n\n return result;\n };\n\n return {\n bind: bindKey,\n unbind: unbindKey,\n unsafeUnbind: unsafeUnbindKey,\n unbindScope,\n setScope,\n unbindAll,\n getScope,\n destroy,\n isBound,\n getBoundKeys,\n getHandlers,\n };\n}\n"],"mappings":";4bAAA,IAAAA,GAAA,GAAAC,EAAAD,GAAA,mBAAAE,EAAA,SAAAC,EAAA,YAAAC,EAAA,YAAAC,GAAA,mBAAAC,EAAA,YAAAC,GAAA,YAAAC,GAAA,iBAAAC,GAAA,gBAAAC,GAAA,aAAAC,GAAA,YAAAC,GAAA,aAAAC,GAAA,cAAAC,GAAA,cAAAC,GAAA,gBAAAC,GAAA,oBAAAC,KCAO,IAAMC,EAAgB,MAMhBC,EAAO,CAClB,MAAO,EACP,IAAK,EACL,KAAM,EACN,KAAM,CACR,EAiBaC,EAA2B,CACtC,SAAKD,EAAK,MACV,MAAOA,EAAK,MACZ,SAAKA,EAAK,IACV,IAAKA,EAAK,IACV,OAAQA,EAAK,IACb,SAAKA,EAAK,KACV,KAAMA,EAAK,KACX,QAASA,EAAK,KACd,SAAKA,EAAK,KACV,IAAKA,EAAK,KACV,QAASA,EAAK,IAChB,EAEaE,EAAqC,CAChD,UAAW,YACX,IAAK,MACL,MAAO,QACP,MAAO,QACP,OAAQ,QACR,IAAK,SACL,OAAQ,SACR,MAAO,IACP,KAAM,YACN,GAAI,UACJ,MAAO,aACP,KAAM,YACN,IAAK,SACL,OAAQ,SACR,KAAM,OACN,IAAK,MACL,OAAQ,SACR,SAAU,WACV,MAAO,IACP,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,KAAM,KAEN,KAAM,OACN,SAAU,OACV,UAAW,OACX,GAAI,OACJ,YAAa,OAEb,UAAW,YACX,QAAS,UACT,WAAY,aACZ,UAAW,YACX,UAAW,YACX,IAAK,MACL,MAAO,QACP,MAAO,QACP,OAAQ,SACR,OAAQ,SACR,KAAM,OACN,IAAK,MACL,OAAQ,SACR,SAAU,UACZ,EAEaC,EAAgB,WC7FtB,IAAMC,EAAoBC,GACvBC,EAAQD,CAAG,GAAKA,EAAI,YAAY,EAG7BE,EAAmB,GAA6B,CAC3D,IAAIC,EAAY,EAChB,OAAI,EAAE,WAAUA,GAAaC,EAAK,OAC9B,EAAE,SAAQD,GAAaC,EAAK,KAC5B,EAAE,UAASD,GAAaC,EAAK,MAC7B,EAAE,UAASD,GAAaC,EAAK,MAC1BD,CACT,ECDA,IAAME,EAAWC,GACfA,EAAK,OACH,CAACC,EAAKC,KACAA,KAAOC,EACTF,EAAI,MAAQE,EAAUD,CAA0B,EAEhDD,EAAI,QAAQ,KAAKG,EAAQF,CAAG,GAAKA,EAAI,YAAY,CAAC,EAE7CD,GAET,CACE,KAAM,EACN,QAAS,CAAC,CACZ,CACF,EAEII,EAAmBC,GAA8B,CAErD,IAAMN,EADYM,EAAQ,QAAQ,MAAO,EAAE,EACpB,MAAM,GAAG,EAChC,OAAIN,EAAKA,EAAK,OAAS,CAAC,IAAM,KAC5BA,EAAKA,EAAK,OAAS,CAAC,GAAK,KAGpBA,CACT,EAEaO,EAAaD,GACTD,EAAgBC,CAAO,EACxB,IAAKE,GAAW,CAC5B,IAAMR,EAAOQ,EAAO,MAAM,GAAG,EACvBN,EAAMF,EAAKA,EAAK,OAAS,CAAC,EAGhC,MAAO,CACL,IAHoBS,EAAiBP,CAAG,EAIxC,SAAUH,EAAQC,CAAI,CACxB,CACF,CAAC,EChCI,IAAMU,EACX,OAAO,UAAc,KAAe,UAAU,UAAU,SAAS,SAAS,EAE/DC,EAAcC,GACzBA,EAAG,mBACHA,EAAG,UAAY,SACfA,EAAG,UAAY,UACfA,EAAG,UAAY,WAEJC,EAAY,CACvBC,EACAC,IACY,CACZ,GAAID,EAAK,SAAWC,EAAK,OAAQ,MAAO,GAExC,QAASC,EAAI,EAAGA,EAAIF,EAAK,OAAQE,IAC/B,GAAIF,EAAKE,CAAC,IAAMD,EAAKC,CAAC,EAAG,MAAO,GAGlC,MAAO,EACT,ECtBA,IAAMC,EAAiB,GACrB,GAAK,CAACC,EAAW,EAAE,MAAqB,EAEpCC,EAAoB,IAAI,QAUvB,SAASC,EACdC,EACAC,EAAqBL,EACrB,CACA,IAAIM,EAA4C,CAAC,EAC3CC,EAA2B,IAAI,IACjCC,EAAc,MAEdC,EAAY,EAEVC,EAAU,CACdC,EACAC,EACAC,EAA2B,IAAM,CAAC,EAClC,CACE,UAAAC,CACF,EAEI,CACF,UAAW,EACb,IACS,CACT,IAAMC,EACJ,OAAOH,GAAkB,WAAa,MAAgBA,EAClDI,EACJ,OAAOJ,GAAkB,WAAaA,EAAgBC,EAExDI,EAAUN,CAAO,EAAE,QAAQ,CAAC,CAAE,IAAAO,EAAK,SAAAC,CAAS,IAAM,CAC3Cb,EAASY,CAAG,IACfZ,EAASY,CAAG,EAAI,CAAC,GAEHZ,EAASY,CAAG,EAYpB,KAAK,CACX,MAAAH,EACA,OAAAC,EACA,SAAAG,EACA,UAAAL,CACF,CAAC,CACH,CAAC,CACH,EAEMM,EAAmB,CACvBT,EACAU,EACAC,EAAsB,QACb,CACTL,EAAUN,CAAO,EAAE,QAAQ,CAAC,CAAE,IAAAO,EAAK,SAAAC,CAAS,IAAM,CAChD,IAAMI,EAAUjB,EAASY,CAAG,EAC5B,GAAI,MAAM,QAAQK,CAAO,EAAG,CAC1B,IAAMA,EAAUjB,EAASY,CAAG,EAAE,OAC5B,CAAC,CAAE,MAAAH,EAAO,OAAAC,EAAQ,SAAUQ,CAAe,IACzC,EACET,IAAUO,GACVE,EAAe,OAASL,EAAS,MACjCM,EAAUD,EAAe,QAASL,EAAS,OAAO,IACjDE,IAAiB,MAAcL,IAAWK,GAEjD,EACIE,EAAQ,OACVjB,EAASY,CAAG,EAAIK,EAEhB,OAAOjB,EAASY,CAAG,CAEvB,CACF,CAAC,CACH,EAEMQ,EAAY,CAChBf,EACAC,EACAC,EAA2B,IAAM,CAAC,IAC/B,CAKHO,EAAiBT,EADf,OAAOC,GAAkB,WAAaA,EAAgBC,EAFtD,OAAOD,GAAkB,WAAa,MAAgBA,CAGL,CACrD,EAEMe,EAAkB,CAAChB,EAAiBI,IACxCK,EAAiBT,EAAS,KAAMI,CAAK,EAEjCa,EAAYC,GAAqB,CACrC,IAAMX,EAAMY,EAAiBD,EAAE,GAAG,EAqBlC,GAnBI,CAACxB,EAASwB,CAAC,GAIXE,GAAab,IAAQc,IAIzBvB,EAAYwB,EAAgBJ,CAAC,EAOzB,EAJFX,IAAS,SACTA,IAAS,OACTA,IAAS,QACTA,IAAS,SACW,CAACX,EAAS,IAAIW,CAAG,GACrCX,EAAS,IAAIW,CAAG,EAGd,EAAEA,KAAOZ,IACX,OAGF,IAAM4B,EAAkB5B,EAASY,CAAG,EAAE,OACpC,CAAC,CAAE,MAAAH,EAAO,SAAU,CAAE,QAAAoB,EAAS,KAAAC,CAAK,CAAE,IAChCrB,IAAUP,EACL,GAGFiB,EAAUU,EAAS,MAAM,KAAK5B,CAAQ,CAAC,GAAK6B,IAAS3B,CAEhE,EAEM4B,EAAqCH,EAAgB,KACxDI,GAAWA,EAAO,SACrB,EACID,EACFA,EAAc,OAAOR,CAAC,EAEtBK,EAAgB,QAAQ,CAAC,CAAE,OAAAlB,CAAO,IAAM,CACtCA,EAAOa,CAAC,CACV,CAAC,CAEL,EAEMU,EAAWV,GAAqB,CACpC,IAAMX,EAAMY,EAAiBD,EAAE,GAAG,EAE9BA,EAAE,KAAOA,EAAE,IAAI,YAAY,IAAM,OACnCtB,EAAS,MAAM,EAEfA,EAAS,OAAOW,CAAG,CAEvB,EAEMsB,EAAelB,GAA8B,CACjD,OAAO,KAAKhB,CAAQ,EAAE,QAASY,GAAQ,CACrC,IAAMuB,EAAYvB,EACZK,EAAUjB,EAASmC,CAAS,EAAE,OAClC,CAAC,CAAE,MAAA1B,CAAM,IAAeA,IAAUO,CACpC,EACIC,EAAQ,OACVjB,EAASmC,CAAS,EAAIlB,EAEtB,OAAOjB,EAASmC,CAAS,CAE7B,CAAC,CACH,EAEMC,EAAY3B,GAAwB,CACxCP,EAAcO,CAChB,EAEM4B,EAAY,IAAY,CAC5BrC,EAAW,CAAC,EACZC,EAAS,MAAM,CACjB,EAEMqC,EAAQ,IAAY,CACxBrC,EAAS,MAAM,CACjB,EAEMsC,EAAU,IAAY,CAG1B,GAFAtC,EAAS,MAAM,EACfD,EAAW,CAAC,EACRF,EAAK,CACP,IAAM0C,EAAY5C,EAAkB,IAAIE,CAAG,EACvC0C,IACF1C,EAAI,oBAAoB,UAAW0C,EAAU,QAAQ,EACrD1C,EAAI,oBAAoB,QAAS0C,EAAU,OAAO,EAClDA,EAAU,OAAO,oBAAoB,QAASA,EAAU,KAAK,EAC7D5C,EAAkB,OAAOE,CAAG,EAEhC,CACF,EAEAyC,EAAQ,EAER,IAAME,EAAO3C,EAAI,aAAe,OAEhC,OAAAF,EAAkB,IAAIE,EAAK,CAAE,SAAAwB,EAAU,QAAAW,EAAS,MAAAK,EAAO,OAAQG,CAAI,CAAC,EACpE3C,EAAI,iBAAiB,UAAWwB,CAAQ,EACxCxB,EAAI,iBAAiB,QAASmC,CAAO,EACrCQ,EAAI,iBAAiB,QAASH,CAAK,EAsE5B,CACL,KAAMlC,EACN,OAAQgB,EACR,aAAcC,EACd,YAAAa,EACA,SAAAE,EACA,UAAAC,EACA,SA3Ee,IAAMnC,EA4ErB,QAAAqC,EACA,QA3Ec,CAAClC,EAAiBqC,IAA0C,CAC1E,IAAMjC,EAAQiC,GAAS,OAASxC,EAGhC,OAFgBS,EAAUN,CAAO,EAElB,KAAK,CAAC,CAAE,IAAAO,EAAK,SAAAC,CAAS,IAAM,CACzC,IAAM8B,EAAc3C,EAASY,CAAG,EAChC,OAAK+B,EAEEA,EAAY,KAChBC,GACCA,EAAE,QAAUnC,GACZmC,EAAE,SAAS,OAAS/B,EAAS,MAC7BM,EAAUyB,EAAE,SAAS,QAAS/B,EAAS,OAAO,CAClD,EAPyB,EAQ3B,CAAC,CACH,EA6DE,aA3DoB6B,GAA2C,CAC/D,IAAMjC,EAAQiC,GAAS,OAASxC,EAC1B2C,EAAO,IAAI,IAEjB,cAAO,OAAO7C,CAAQ,EAAE,QAAS8C,GAAgB,CAC/CA,EAAY,QAAS7B,GAAY,CAC/B,GAAIA,EAAQ,QAAUR,EAAO,CAC3B,IAAMsC,EAAqB,CAAC,EACxB9B,EAAQ,SAAS,KAAO+B,EAAK,MAAMD,EAAS,KAAK,MAAM,EACvD9B,EAAQ,SAAS,KAAO+B,EAAK,KAAKD,EAAS,KAAK,KAAK,EACrD9B,EAAQ,SAAS,KAAO+B,EAAK,OAAOD,EAAS,KAAK,OAAO,EACzD9B,EAAQ,SAAS,KAAO+B,EAAK,MAAMD,EAAS,KAAK,KAAK,EAE1D,IAAME,EAAUhC,EAAQ,SAAS,QAAQ,KAAK,GAAG,GAAK,GAChDiC,EAAU,CAAC,GAAGH,EAAUE,CAAO,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,EAC3DC,GAASL,EAAK,IAAIK,CAAO,CAC/B,CACF,CAAC,CACH,CAAC,EAEM,MAAM,KAAKL,CAAI,CACxB,EAuCE,YArCkB,CAClBxC,EACAqC,IACiB,CACjB,IAAMjC,EAAQiC,GAAS,OAASxC,EAC1BiD,EAAUxC,EAAUN,CAAO,EAC3B+C,EAAuB,CAAC,EAE9B,OAAAD,EAAQ,QAAQ,CAAC,CAAE,IAAAvC,EAAK,SAAAC,CAAS,IAAM,CACrC,IAAM8B,EAAc3C,EAASY,CAAG,EAC3B+B,GAELA,EAAY,QAASC,GAAM,CAEvBA,EAAE,QAAUnC,GACZmC,EAAE,SAAS,OAAS/B,EAAS,MAC7BM,EAAUyB,EAAE,SAAS,QAAS/B,EAAS,OAAO,GAE9CuC,EAAO,KAAKR,EAAE,MAAM,CAExB,CAAC,CACH,CAAC,EAEMQ,CACT,CAcA,CACF,CLjTA,GAAM,CACJ,KAAAC,EACA,OAAAC,EACA,aAAAC,EACA,SAAAC,GACA,SAAAC,GACA,YAAAC,GACA,UAAAC,GACA,QAAAC,GACA,QAAAC,GACA,aAAAC,GACA,YAAAC,EACF,EAAIC,EAAe,QAAQ,EAEdC,GAAUZ,EACVa,GAAYZ,EACZa,GAAkBZ,EAgB/B,IAAOa,GAAQC","names":["src_exports","__export","DEFAULT_SCOPE","MODS","SPECIAL","bindKey","createKeybuddy","src_default","destroy","getBoundKeys","getHandlers","getScope","isBound","setScope","unbindAll","unbindKey","unbindScope","unsafeUnbindKey","DEFAULT_SCOPE","MODS","MODIFIERS","SPECIAL","CAPS_LOCK_KEY","getKeyIdentifier","key","SPECIAL","updateModifiers","modifiers","MODS","getMods","keys","acc","key","MODIFIERS","SPECIAL","getCombinations","keysStr","getKeyMap","keyCmd","getKeyIdentifier","isFirefox","isEditable","el","isEqArray","arr1","arr2","i","defaultFilter","isEditable","documentListeners","createKeybuddy","doc","filterFn","handlers","downKeys","activeScope","modifiers","bindKey","keysStr","scopeOrMethod","methodOrNull","skipOther","scope","method","getKeyMap","key","shortcut","unbindKeyProcess","deleteMethod","deleteScope","handler","methodShortcut","isEqArray","unbindKey","unsafeUnbindKey","dispatch","e","getKeyIdentifier","isFirefox","CAPS_LOCK_KEY","updateModifiers","currentHandlers","special","mods","primaryAction","action","cleanUp","unbindScope","keyString","setScope","unbindAll","reset","destroy","listeners","win","options","keyHandlers","h","keys","handlerList","modParts","MODS","keyPart","fullKey","keyMaps","result","bind","unbind","unsafeUnbind","getScope","setScope","unbindScope","unbindAll","destroy","isBound","getBoundKeys","getHandlers","createKeybuddy","bindKey","unbindKey","unsafeUnbindKey","src_default","bind"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/helpers/keyboard.ts","../src/helpers/keymap.ts","../src/helpers/utils.ts","../src/keybuddy.ts"],"sourcesContent":["import { DEFAULT_SCOPE } from './constants';\nimport { createKeybuddy } from './keybuddy';\n\nexport { createKeybuddy };\n\nconst {\n bind,\n unbind,\n unsafeUnbind,\n getScope,\n setScope,\n unbindScope,\n unbindAll,\n destroy,\n isBound,\n getBoundKeys,\n getHandlers,\n} = createKeybuddy(document);\n\nexport const bindKey = bind;\nexport const unbindKey = unbind;\nexport const unsafeUnbindKey = unsafeUnbind;\n\nexport {\n setScope,\n unbindScope,\n unbindAll,\n getScope,\n destroy,\n isBound,\n getBoundKeys,\n getHandlers,\n DEFAULT_SCOPE,\n};\nexport type { KeyString } from './constants';\nexport { MODS, SPECIAL } from './constants';\n\nexport default bind;\n","export const DEFAULT_SCOPE = 'all';\n\ndeclare const KeyStringBrand: unique symbol;\n\nexport type KeyString = string & { readonly [KeyStringBrand]: true };\n\nexport const MODS = {\n SHIFT: 0b0001, // 1\n ALT: 0b0010, // 2\n CTRL: 0b0100, // 4\n META: 0b1000, // 8\n} as const;\n\n// Map string modifier names to bitwise flags for parsing\nexport type ModifierNames = {\n '⇧': number;\n shift: number;\n '⌥': number;\n alt: number;\n option: number;\n '⌃': number;\n ctrl: number;\n control: number;\n '⌘': number;\n cmd: number;\n command: number;\n};\n\nexport const MODIFIERS: ModifierNames = {\n '⇧': MODS.SHIFT,\n shift: MODS.SHIFT,\n '⌥': MODS.ALT,\n alt: MODS.ALT,\n option: MODS.ALT,\n '⌃': MODS.CTRL,\n ctrl: MODS.CTRL,\n control: MODS.CTRL,\n '⌘': MODS.META,\n cmd: MODS.META,\n command: MODS.META,\n};\n\nexport const SPECIAL: { [key: string]: string } = {\n backspace: 'Backspace',\n tab: 'Tab',\n clear: 'Clear',\n enter: 'Enter',\n return: 'Enter',\n esc: 'Escape',\n escape: 'Escape',\n space: ' ',\n left: 'ArrowLeft',\n up: 'ArrowUp',\n right: 'ArrowRight',\n down: 'ArrowDown',\n del: 'Delete',\n delete: 'Delete',\n home: 'Home',\n end: 'End',\n pageup: 'PageUp',\n pagedown: 'PageDown',\n comma: ',',\n '.': '.',\n '/': '/',\n '`': '`',\n '-': '-',\n '=': '=',\n ';': ';',\n \"'\": \"'\",\n '[': '[',\n ']': ']',\n '\\\\': '\\\\',\n // Normalize Meta key variants\n Meta: 'Meta',\n MetaLeft: 'Meta',\n MetaRight: 'Meta',\n OS: 'Meta', // Some browsers use OS instead of Meta\n ContextMenu: 'Meta', // Right-click context menu key sometimes acts as Meta\n // Add identity mappings for already-normalized keys\n ArrowLeft: 'ArrowLeft',\n ArrowUp: 'ArrowUp',\n ArrowRight: 'ArrowRight',\n ArrowDown: 'ArrowDown',\n Backspace: 'Backspace',\n Tab: 'Tab',\n Clear: 'Clear',\n Enter: 'Enter',\n Escape: 'Escape',\n Delete: 'Delete',\n Home: 'Home',\n End: 'End',\n PageUp: 'PageUp',\n PageDown: 'PageDown',\n};\n\nexport const CAPS_LOCK_KEY = 'CapsLock';\n","import { KeyString, MODS, SPECIAL } from '../constants';\n\nexport const getKeyIdentifier = (key: string): KeyString => {\n return (SPECIAL[key] || key).toLowerCase() as KeyString;\n};\n\nconst MODIFIER_KEYS: Record<string, true> = {\n shift: true,\n alt: true,\n control: true,\n meta: true,\n};\n\nexport const isModifierKey = (key: string): boolean => key in MODIFIER_KEYS;\n\nexport const updateModifiers = (e: KeyboardEvent): number => {\n let modifiers = 0;\n if (e.shiftKey) modifiers |= MODS.SHIFT;\n if (e.altKey) modifiers |= MODS.ALT;\n if (e.ctrlKey) modifiers |= MODS.CTRL;\n if (e.metaKey) modifiers |= MODS.META;\n return modifiers;\n};\n","import { KeyString, MODIFIERS, ModifierNames, SPECIAL } from '../constants';\nimport { getKeyIdentifier } from './keyboard';\n\nexport interface ParsedShortcut {\n mods: number; // Bitwise flag for modifiers\n special: string[];\n}\nexport interface KeyMap {\n key: KeyString;\n shortcut: ParsedShortcut;\n}\n\nconst getMods = (keys: string[]): ParsedShortcut =>\n keys.reduce(\n (acc, key) => {\n if (key in MODIFIERS) {\n acc.mods |= MODIFIERS[key as keyof ModifierNames];\n } else {\n acc.special.push((SPECIAL[key] || key).toLowerCase());\n }\n return acc;\n },\n {\n mods: 0, // Start with no modifiers\n special: [],\n } as ParsedShortcut,\n );\n\nconst getCombinations = (keysStr: string): string[] => {\n const cleanKeys = keysStr.replace(/\\s/g, '');\n const keys = cleanKeys.split(',');\n if (keys[keys.length - 1] === '') {\n keys[keys.length - 2] += ',';\n }\n\n return keys;\n};\n\nexport const getKeyMap = (keysStr: string): KeyMap[] => {\n const keymap = getCombinations(keysStr);\n return keymap.map((keyCmd) => {\n const keys = keyCmd.split('+');\n const key = keys[keys.length - 1];\n const keyIdentifier = getKeyIdentifier(key);\n\n return {\n key: keyIdentifier,\n shortcut: getMods(keys),\n };\n });\n};\n","export const invariant = (\n condition: boolean,\n message: string,\n ...args: unknown[]\n) => {\n if (\n typeof process !== 'undefined' &&\n process.env &&\n process.env.NODE_ENV === 'development' &&\n !condition\n ) {\n throw new Error(\n `Invariant failed: ${message}${args.length ? ` ${JSON.stringify(args)}` : ''}`,\n );\n }\n};\n\nexport const isFirefox =\n typeof navigator !== 'undefined' && navigator.userAgent.includes('Firefox');\n\nexport const isEditable = (el: HTMLElement): boolean =>\n el.isContentEditable ||\n el.tagName === 'INPUT' ||\n el.tagName === 'SELECT' ||\n el.tagName === 'TEXTAREA';\n\nexport const isEqArray = (\n arr1: (string | number)[],\n arr2: (string | number)[],\n): boolean => {\n if (arr1.length !== arr2.length) return false;\n\n for (let i = 0; i < arr1.length; i++) {\n if (arr1[i] !== arr2[i]) return false;\n }\n\n return true;\n};\n","import { CAPS_LOCK_KEY, DEFAULT_SCOPE, KeyString, MODS } from './constants';\nimport { getKeyIdentifier, isModifierKey, updateModifiers } from './helpers/keyboard';\nimport { getKeyMap, ParsedShortcut } from './helpers/keymap';\nimport { invariant, isEditable, isEqArray, isFirefox } from './helpers/utils';\n\ntype KeyHandler = (e: KeyboardEvent) => void;\ntype FilterFn = (el: KeyboardEvent) => boolean;\n\ninterface Handler {\n scope: string;\n method: KeyHandler;\n shortcut: ParsedShortcut;\n skipOther: boolean;\n}\n\nconst defaultFilter = (e: KeyboardEvent): boolean =>\n e && !isEditable(e.target as HTMLElement);\n\nconst documentListeners = new WeakMap<\n Document,\n {\n dispatch: (e: KeyboardEvent) => void;\n cleanUp: (e: KeyboardEvent) => void;\n reset: () => void;\n window: Window & typeof globalThis;\n }\n>();\n\nexport function createKeybuddy(\n doc: Document,\n filterFn: FilterFn = defaultFilter,\n) {\n let handlers: { [key: KeyString]: Handler[] } = {};\n const downKeys: Set<KeyString> = new Set();\n let activeScope = DEFAULT_SCOPE;\n\n let modifiers = 0;\n\n const bindKey = (\n keysStr: string,\n scopeOrMethod: string | KeyHandler,\n methodOrNull: KeyHandler = () => {},\n {\n skipOther,\n }: {\n skipOther: boolean;\n } = {\n skipOther: false,\n },\n ): void => {\n const scope: string =\n typeof scopeOrMethod === 'function' ? DEFAULT_SCOPE : scopeOrMethod;\n const method: KeyHandler =\n typeof scopeOrMethod === 'function' ? scopeOrMethod : methodOrNull;\n\n getKeyMap(keysStr).forEach(({ key, shortcut }) => {\n if (!handlers[key]) {\n handlers[key] = [];\n }\n const handler = handlers[key];\n if (process.env.NODE_ENV === 'development') {\n if (skipOther) {\n const action = handler.find((i) => i.skipOther);\n invariant(\n !action,\n \"Conflicting 'skipOther' property with action\",\n action,\n );\n }\n }\n\n handler.push({\n scope,\n method,\n shortcut,\n skipOther,\n });\n });\n };\n\n const unbindKeyProcess = (\n keysStr: string,\n deleteMethod: null | KeyHandler,\n deleteScope: string = DEFAULT_SCOPE,\n ): void => {\n getKeyMap(keysStr).forEach(({ key, shortcut }) => {\n const handler = handlers[key];\n if (Array.isArray(handler)) {\n const handler = handlers[key].filter(\n ({ scope, method, shortcut: methodShortcut }: Handler) =>\n !(\n scope === deleteScope &&\n methodShortcut.mods === shortcut.mods &&\n isEqArray(methodShortcut.special, shortcut.special) &&\n (deleteMethod === null ? true : method === deleteMethod)\n ),\n );\n if (handler.length) {\n handlers[key] = handler;\n } else {\n delete handlers[key];\n }\n }\n });\n };\n\n const unbindKey = (\n keysStr: string,\n scopeOrMethod: string | KeyHandler,\n methodOrNull: KeyHandler = () => {},\n ) => {\n const deleteScope: string =\n typeof scopeOrMethod === 'function' ? DEFAULT_SCOPE : scopeOrMethod;\n const deleteMethod: KeyHandler =\n typeof scopeOrMethod === 'function' ? scopeOrMethod : methodOrNull;\n unbindKeyProcess(keysStr, deleteMethod, deleteScope);\n };\n\n const unsafeUnbindKey = (keysStr: string, scope?: string) =>\n unbindKeyProcess(keysStr, null, scope);\n\n const dispatch = (e: KeyboardEvent) => {\n const key = getKeyIdentifier(e.key);\n\n if (!filterFn(e)) {\n return;\n }\n\n if (isFirefox && key === CAPS_LOCK_KEY) {\n return;\n }\n\n modifiers = updateModifiers(e);\n\n const isModifier = isModifierKey(key);\n if (!isModifier && !downKeys.has(key)) {\n downKeys.add(key);\n }\n\n if (!(key in handlers)) {\n return;\n }\n\n const currentHandlers = handlers[key].filter(\n ({ scope, shortcut: { special, mods } }) => {\n if (scope !== activeScope) {\n return false;\n }\n\n return isEqArray(special, Array.from(downKeys)) && mods === modifiers;\n },\n );\n\n const primaryAction: Handler | undefined = currentHandlers.find(\n (action) => action.skipOther,\n );\n\n console.log('has it?', primaryAction, currentHandlers);\n if (primaryAction) {\n primaryAction.method(e);\n } else {\n currentHandlers.forEach(({ method }) => {\n method(e);\n });\n }\n };\n\n const cleanUp = (e: KeyboardEvent) => {\n const key = getKeyIdentifier(e.key);\n\n if (e.key && e.key.toLowerCase() === 'meta') {\n downKeys.clear();\n } else {\n downKeys.delete(key);\n }\n };\n\n const unbindScope = (deleteScope: string): void => {\n Object.keys(handlers).forEach((key) => {\n const keyString = key as KeyString;\n const handler = handlers[keyString].filter(\n ({ scope }: Handler) => scope !== deleteScope,\n );\n if (handler.length) {\n handlers[keyString] = handler;\n } else {\n delete handlers[keyString];\n }\n });\n };\n\n const setScope = (scope: string): void => {\n activeScope = scope;\n };\n\n const unbindAll = (): void => {\n handlers = {};\n downKeys.clear();\n };\n\n const reset = (): void => {\n downKeys.clear();\n };\n\n const destroy = (): void => {\n downKeys.clear();\n handlers = {};\n if (doc) {\n const listeners = documentListeners.get(doc);\n if (listeners) {\n doc.removeEventListener('keydown', listeners.dispatch);\n doc.removeEventListener('keyup', listeners.cleanUp);\n listeners.window.removeEventListener('focus', listeners.reset);\n documentListeners.delete(doc);\n }\n }\n };\n\n const win = (doc.defaultView || window) as Window & typeof globalThis;\n\n documentListeners.set(doc, { dispatch, cleanUp, reset, window: win });\n doc.addEventListener('keydown', dispatch);\n doc.addEventListener('keyup', cleanUp);\n win.addEventListener('focus', reset);\n\n const getScope = () => activeScope;\n\n const isBound = (keysStr: string, options?: { scope?: string }): boolean => {\n const scope = options?.scope || activeScope;\n const keyMaps = getKeyMap(keysStr);\n\n return keyMaps.some(({ key, shortcut }) => {\n const keyHandlers = handlers[key];\n if (!keyHandlers) return false;\n\n return keyHandlers.some(\n (h) =>\n h.scope === scope &&\n h.shortcut.mods === shortcut.mods &&\n isEqArray(h.shortcut.special, shortcut.special),\n );\n });\n };\n\n const getBoundKeys = (options?: { scope?: string }): string[] => {\n const scope = options?.scope || activeScope;\n const keys = new Set<string>();\n\n Object.values(handlers).forEach((handlerList) => {\n handlerList.forEach((handler) => {\n if (handler.scope === scope) {\n const modParts: string[] = [];\n if (handler.shortcut.mods & MODS.CTRL) modParts.push('ctrl');\n if (handler.shortcut.mods & MODS.ALT) modParts.push('alt');\n if (handler.shortcut.mods & MODS.SHIFT) modParts.push('shift');\n if (handler.shortcut.mods & MODS.META) modParts.push('cmd');\n\n const keyPart = handler.shortcut.special.join('+') || '';\n const fullKey = [...modParts, keyPart].filter(Boolean).join('+');\n if (fullKey) keys.add(fullKey);\n }\n });\n });\n\n return Array.from(keys);\n };\n\n const getHandlers = (\n keysStr: string,\n options?: { scope?: string },\n ): KeyHandler[] => {\n const scope = options?.scope || activeScope;\n const keyMaps = getKeyMap(keysStr);\n const result: KeyHandler[] = [];\n\n keyMaps.forEach(({ key, shortcut }) => {\n const keyHandlers = handlers[key];\n if (!keyHandlers) return;\n\n keyHandlers.forEach((h) => {\n if (\n h.scope === scope &&\n h.shortcut.mods === shortcut.mods &&\n isEqArray(h.shortcut.special, shortcut.special)\n ) {\n result.push(h.method);\n }\n });\n });\n\n return result;\n };\n\n return {\n bind: bindKey,\n unbind: unbindKey,\n unsafeUnbind: unsafeUnbindKey,\n unbindScope,\n setScope,\n unbindAll,\n getScope,\n destroy,\n isBound,\n getBoundKeys,\n getHandlers,\n };\n}\n"],"mappings":";4bAAA,IAAAA,GAAA,GAAAC,EAAAD,GAAA,mBAAAE,EAAA,SAAAC,EAAA,YAAAC,EAAA,YAAAC,GAAA,mBAAAC,EAAA,YAAAC,GAAA,YAAAC,GAAA,iBAAAC,GAAA,gBAAAC,GAAA,aAAAC,GAAA,YAAAC,GAAA,aAAAC,GAAA,cAAAC,GAAA,cAAAC,GAAA,gBAAAC,GAAA,oBAAAC,KCAO,IAAMC,EAAgB,MAMhBC,EAAO,CAClB,MAAO,EACP,IAAK,EACL,KAAM,EACN,KAAM,CACR,EAiBaC,EAA2B,CACtC,SAAKD,EAAK,MACV,MAAOA,EAAK,MACZ,SAAKA,EAAK,IACV,IAAKA,EAAK,IACV,OAAQA,EAAK,IACb,SAAKA,EAAK,KACV,KAAMA,EAAK,KACX,QAASA,EAAK,KACd,SAAKA,EAAK,KACV,IAAKA,EAAK,KACV,QAASA,EAAK,IAChB,EAEaE,EAAqC,CAChD,UAAW,YACX,IAAK,MACL,MAAO,QACP,MAAO,QACP,OAAQ,QACR,IAAK,SACL,OAAQ,SACR,MAAO,IACP,KAAM,YACN,GAAI,UACJ,MAAO,aACP,KAAM,YACN,IAAK,SACL,OAAQ,SACR,KAAM,OACN,IAAK,MACL,OAAQ,SACR,SAAU,WACV,MAAO,IACP,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,KAAM,KAEN,KAAM,OACN,SAAU,OACV,UAAW,OACX,GAAI,OACJ,YAAa,OAEb,UAAW,YACX,QAAS,UACT,WAAY,aACZ,UAAW,YACX,UAAW,YACX,IAAK,MACL,MAAO,QACP,MAAO,QACP,OAAQ,SACR,OAAQ,SACR,KAAM,OACN,IAAK,MACL,OAAQ,SACR,SAAU,UACZ,EAEaC,EAAgB,WC7FtB,IAAMC,EAAoBC,IACvBC,EAAQD,CAAG,GAAKA,GAAK,YAAY,EAGrCE,EAAsC,CAC1C,MAAO,GACP,IAAK,GACL,QAAS,GACT,KAAM,EACR,EAEaC,EAAiBH,GAAyBA,KAAOE,EAEjDE,EAAmB,GAA6B,CAC3D,IAAIC,EAAY,EAChB,OAAI,EAAE,WAAUA,GAAaC,EAAK,OAC9B,EAAE,SAAQD,GAAaC,EAAK,KAC5B,EAAE,UAASD,GAAaC,EAAK,MAC7B,EAAE,UAASD,GAAaC,EAAK,MAC1BD,CACT,ECVA,IAAME,EAAWC,GACfA,EAAK,OACH,CAACC,EAAKC,KACAA,KAAOC,EACTF,EAAI,MAAQE,EAAUD,CAA0B,EAEhDD,EAAI,QAAQ,MAAMG,EAAQF,CAAG,GAAKA,GAAK,YAAY,CAAC,EAE/CD,GAET,CACE,KAAM,EACN,QAAS,CAAC,CACZ,CACF,EAEII,EAAmBC,GAA8B,CAErD,IAAMN,EADYM,EAAQ,QAAQ,MAAO,EAAE,EACpB,MAAM,GAAG,EAChC,OAAIN,EAAKA,EAAK,OAAS,CAAC,IAAM,KAC5BA,EAAKA,EAAK,OAAS,CAAC,GAAK,KAGpBA,CACT,EAEaO,EAAaD,GACTD,EAAgBC,CAAO,EACxB,IAAKE,GAAW,CAC5B,IAAMR,EAAOQ,EAAO,MAAM,GAAG,EACvBN,EAAMF,EAAKA,EAAK,OAAS,CAAC,EAGhC,MAAO,CACL,IAHoBS,EAAiBP,CAAG,EAIxC,SAAUH,EAAQC,CAAI,CACxB,CACF,CAAC,EChCI,IAAMU,EACX,OAAO,UAAc,KAAe,UAAU,UAAU,SAAS,SAAS,EAE/DC,EAAcC,GACzBA,EAAG,mBACHA,EAAG,UAAY,SACfA,EAAG,UAAY,UACfA,EAAG,UAAY,WAEJC,EAAY,CACvBC,EACAC,IACY,CACZ,GAAID,EAAK,SAAWC,EAAK,OAAQ,MAAO,GAExC,QAASC,EAAI,EAAGA,EAAIF,EAAK,OAAQE,IAC/B,GAAIF,EAAKE,CAAC,IAAMD,EAAKC,CAAC,EAAG,MAAO,GAGlC,MAAO,EACT,ECtBA,IAAMC,EAAiB,GACrB,GAAK,CAACC,EAAW,EAAE,MAAqB,EAEpCC,EAAoB,IAAI,QAUvB,SAASC,EACdC,EACAC,EAAqBL,EACrB,CACA,IAAIM,EAA4C,CAAC,EAC3CC,EAA2B,IAAI,IACjCC,EAAc,MAEdC,EAAY,EAEVC,EAAU,CACdC,EACAC,EACAC,EAA2B,IAAM,CAAC,EAClC,CACE,UAAAC,CACF,EAEI,CACF,UAAW,EACb,IACS,CACT,IAAMC,EACJ,OAAOH,GAAkB,WAAa,MAAgBA,EAClDI,EACJ,OAAOJ,GAAkB,WAAaA,EAAgBC,EAExDI,EAAUN,CAAO,EAAE,QAAQ,CAAC,CAAE,IAAAO,EAAK,SAAAC,CAAS,IAAM,CAC3Cb,EAASY,CAAG,IACfZ,EAASY,CAAG,EAAI,CAAC,GAEHZ,EAASY,CAAG,EAYpB,KAAK,CACX,MAAAH,EACA,OAAAC,EACA,SAAAG,EACA,UAAAL,CACF,CAAC,CACH,CAAC,CACH,EAEMM,EAAmB,CACvBT,EACAU,EACAC,EAAsB,QACb,CACTL,EAAUN,CAAO,EAAE,QAAQ,CAAC,CAAE,IAAAO,EAAK,SAAAC,CAAS,IAAM,CAChD,IAAMI,EAAUjB,EAASY,CAAG,EAC5B,GAAI,MAAM,QAAQK,CAAO,EAAG,CAC1B,IAAMA,EAAUjB,EAASY,CAAG,EAAE,OAC5B,CAAC,CAAE,MAAAH,EAAO,OAAAC,EAAQ,SAAUQ,CAAe,IACzC,EACET,IAAUO,GACVE,EAAe,OAASL,EAAS,MACjCM,EAAUD,EAAe,QAASL,EAAS,OAAO,IACjDE,IAAiB,MAAcL,IAAWK,GAEjD,EACIE,EAAQ,OACVjB,EAASY,CAAG,EAAIK,EAEhB,OAAOjB,EAASY,CAAG,CAEvB,CACF,CAAC,CACH,EAEMQ,EAAY,CAChBf,EACAC,EACAC,EAA2B,IAAM,CAAC,IAC/B,CAKHO,EAAiBT,EADf,OAAOC,GAAkB,WAAaA,EAAgBC,EAFtD,OAAOD,GAAkB,WAAa,MAAgBA,CAGL,CACrD,EAEMe,EAAkB,CAAChB,EAAiBI,IACxCK,EAAiBT,EAAS,KAAMI,CAAK,EAEjCa,EAAYC,GAAqB,CACrC,IAAMX,EAAMY,EAAiBD,EAAE,GAAG,EAiBlC,GAfI,CAACxB,EAASwB,CAAC,GAIXE,GAAab,IAAQc,IAIzBvB,EAAYwB,EAAgBJ,CAAC,EAGzB,CADeK,EAAchB,CAAG,GACjB,CAACX,EAAS,IAAIW,CAAG,GAClCX,EAAS,IAAIW,CAAG,EAGd,EAAEA,KAAOZ,IACX,OAGF,IAAM6B,EAAkB7B,EAASY,CAAG,EAAE,OACpC,CAAC,CAAE,MAAAH,EAAO,SAAU,CAAE,QAAAqB,EAAS,KAAAC,CAAK,CAAE,IAChCtB,IAAUP,EACL,GAGFiB,EAAUW,EAAS,MAAM,KAAK7B,CAAQ,CAAC,GAAK8B,IAAS5B,CAEhE,EAEM6B,EAAqCH,EAAgB,KACxDI,GAAWA,EAAO,SACrB,EAGID,EACFA,EAAc,OAAOT,CAAC,EAEtBM,EAAgB,QAAQ,CAAC,CAAE,OAAAnB,CAAO,IAAM,CACtCA,EAAOa,CAAC,CACV,CAAC,CAEL,EAEMW,EAAWX,GAAqB,CACpC,IAAMX,EAAMY,EAAiBD,EAAE,GAAG,EAE9BA,EAAE,KAAOA,EAAE,IAAI,YAAY,IAAM,OACnCtB,EAAS,MAAM,EAEfA,EAAS,OAAOW,CAAG,CAEvB,EAEMuB,EAAenB,GAA8B,CACjD,OAAO,KAAKhB,CAAQ,EAAE,QAASY,GAAQ,CACrC,IAAMwB,EAAYxB,EACZK,EAAUjB,EAASoC,CAAS,EAAE,OAClC,CAAC,CAAE,MAAA3B,CAAM,IAAeA,IAAUO,CACpC,EACIC,EAAQ,OACVjB,EAASoC,CAAS,EAAInB,EAEtB,OAAOjB,EAASoC,CAAS,CAE7B,CAAC,CACH,EAEMC,EAAY5B,GAAwB,CACxCP,EAAcO,CAChB,EAEM6B,EAAY,IAAY,CAC5BtC,EAAW,CAAC,EACZC,EAAS,MAAM,CACjB,EAEMsC,EAAQ,IAAY,CACxBtC,EAAS,MAAM,CACjB,EAEMuC,EAAU,IAAY,CAG1B,GAFAvC,EAAS,MAAM,EACfD,EAAW,CAAC,EACRF,EAAK,CACP,IAAM2C,EAAY7C,EAAkB,IAAIE,CAAG,EACvC2C,IACF3C,EAAI,oBAAoB,UAAW2C,EAAU,QAAQ,EACrD3C,EAAI,oBAAoB,QAAS2C,EAAU,OAAO,EAClDA,EAAU,OAAO,oBAAoB,QAASA,EAAU,KAAK,EAC7D7C,EAAkB,OAAOE,CAAG,EAEhC,CACF,EAEM4C,EAAO5C,EAAI,aAAe,OAEhC,OAAAF,EAAkB,IAAIE,EAAK,CAAE,SAAAwB,EAAU,QAAAY,EAAS,MAAAK,EAAO,OAAQG,CAAI,CAAC,EACpE5C,EAAI,iBAAiB,UAAWwB,CAAQ,EACxCxB,EAAI,iBAAiB,QAASoC,CAAO,EACrCQ,EAAI,iBAAiB,QAASH,CAAK,EAsE5B,CACL,KAAMnC,EACN,OAAQgB,EACR,aAAcC,EACd,YAAAc,EACA,SAAAE,EACA,UAAAC,EACA,SA3Ee,IAAMpC,EA4ErB,QAAAsC,EACA,QA3Ec,CAACnC,EAAiBsC,IAA0C,CAC1E,IAAMlC,EAAQkC,GAAS,OAASzC,EAGhC,OAFgBS,EAAUN,CAAO,EAElB,KAAK,CAAC,CAAE,IAAAO,EAAK,SAAAC,CAAS,IAAM,CACzC,IAAM+B,EAAc5C,EAASY,CAAG,EAChC,OAAKgC,EAEEA,EAAY,KAChBC,GACCA,EAAE,QAAUpC,GACZoC,EAAE,SAAS,OAAShC,EAAS,MAC7BM,EAAU0B,EAAE,SAAS,QAAShC,EAAS,OAAO,CAClD,EAPyB,EAQ3B,CAAC,CACH,EA6DE,aA3DoB8B,GAA2C,CAC/D,IAAMlC,EAAQkC,GAAS,OAASzC,EAC1B4C,EAAO,IAAI,IAEjB,cAAO,OAAO9C,CAAQ,EAAE,QAAS+C,GAAgB,CAC/CA,EAAY,QAAS9B,GAAY,CAC/B,GAAIA,EAAQ,QAAUR,EAAO,CAC3B,IAAMuC,EAAqB,CAAC,EACxB/B,EAAQ,SAAS,KAAOgC,EAAK,MAAMD,EAAS,KAAK,MAAM,EACvD/B,EAAQ,SAAS,KAAOgC,EAAK,KAAKD,EAAS,KAAK,KAAK,EACrD/B,EAAQ,SAAS,KAAOgC,EAAK,OAAOD,EAAS,KAAK,OAAO,EACzD/B,EAAQ,SAAS,KAAOgC,EAAK,MAAMD,EAAS,KAAK,KAAK,EAE1D,IAAME,EAAUjC,EAAQ,SAAS,QAAQ,KAAK,GAAG,GAAK,GAChDkC,EAAU,CAAC,GAAGH,EAAUE,CAAO,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,EAC3DC,GAASL,EAAK,IAAIK,CAAO,CAC/B,CACF,CAAC,CACH,CAAC,EAEM,MAAM,KAAKL,CAAI,CACxB,EAuCE,YArCkB,CAClBzC,EACAsC,IACiB,CACjB,IAAMlC,EAAQkC,GAAS,OAASzC,EAC1BkD,EAAUzC,EAAUN,CAAO,EAC3BgD,EAAuB,CAAC,EAE9B,OAAAD,EAAQ,QAAQ,CAAC,CAAE,IAAAxC,EAAK,SAAAC,CAAS,IAAM,CACrC,IAAM+B,EAAc5C,EAASY,CAAG,EAC3BgC,GAELA,EAAY,QAASC,GAAM,CAEvBA,EAAE,QAAUpC,GACZoC,EAAE,SAAS,OAAShC,EAAS,MAC7BM,EAAU0B,EAAE,SAAS,QAAShC,EAAS,OAAO,GAE9CwC,EAAO,KAAKR,EAAE,MAAM,CAExB,CAAC,CACH,CAAC,EAEMQ,CACT,CAcA,CACF,CL7SA,GAAM,CACJ,KAAAC,EACA,OAAAC,GACA,aAAAC,GACA,SAAAC,GACA,SAAAC,GACA,YAAAC,GACA,UAAAC,GACA,QAAAC,GACA,QAAAC,GACA,aAAAC,GACA,YAAAC,EACF,EAAIC,EAAe,QAAQ,EAEdC,GAAUZ,EACVa,GAAYZ,GACZa,GAAkBZ,GAgB/B,IAAOa,GAAQC","names":["src_exports","__export","DEFAULT_SCOPE","MODS","SPECIAL","bindKey","createKeybuddy","src_default","destroy","getBoundKeys","getHandlers","getScope","isBound","setScope","unbindAll","unbindKey","unbindScope","unsafeUnbindKey","DEFAULT_SCOPE","MODS","MODIFIERS","SPECIAL","CAPS_LOCK_KEY","getKeyIdentifier","key","SPECIAL","MODIFIER_KEYS","isModifierKey","updateModifiers","modifiers","MODS","getMods","keys","acc","key","MODIFIERS","SPECIAL","getCombinations","keysStr","getKeyMap","keyCmd","getKeyIdentifier","isFirefox","isEditable","el","isEqArray","arr1","arr2","i","defaultFilter","isEditable","documentListeners","createKeybuddy","doc","filterFn","handlers","downKeys","activeScope","modifiers","bindKey","keysStr","scopeOrMethod","methodOrNull","skipOther","scope","method","getKeyMap","key","shortcut","unbindKeyProcess","deleteMethod","deleteScope","handler","methodShortcut","isEqArray","unbindKey","unsafeUnbindKey","dispatch","e","getKeyIdentifier","isFirefox","CAPS_LOCK_KEY","updateModifiers","isModifierKey","currentHandlers","special","mods","primaryAction","action","cleanUp","unbindScope","keyString","setScope","unbindAll","reset","destroy","listeners","win","options","keyHandlers","h","keys","handlerList","modParts","MODS","keyPart","fullKey","keyMaps","result","bind","unbind","unsafeUnbind","getScope","setScope","unbindScope","unbindAll","destroy","isBound","getBoundKeys","getHandlers","createKeybuddy","bindKey","unbindKey","unsafeUnbindKey","src_default","bind"]}
package/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  /* keybuddy - Modern keyboard shortcuts library */
2
- "use strict";var A=Object.defineProperty;var q=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var W=Object.prototype.hasOwnProperty;var $=(e,o)=>{for(var t in o)A(e,t,{get:o[t],enumerable:!0})},Y=(e,o,t,p)=>{if(o&&typeof o=="object"||typeof o=="function")for(let u of V(o))!W.call(e,u)&&u!==t&&A(e,u,{get:()=>o[u],enumerable:!(p=q(o,u))||p.enumerable});return e};var J=e=>Y(A({},"__esModule",{value:!0}),e);var fe={};$(fe,{DEFAULT_SCOPE:()=>g,MODS:()=>s,SPECIAL:()=>m,bindKey:()=>ce,createKeybuddy:()=>T,default:()=>pe,destroy:()=>oe,getBoundKeys:()=>ie,getHandlers:()=>ae,getScope:()=>ee,isBound:()=>se,setScope:()=>te,unbindAll:()=>re,unbindKey:()=>de,unbindScope:()=>ne,unsafeUnbindKey:()=>le});module.exports=J(fe);var g="all",s={SHIFT:1,ALT:2,CTRL:4,META:8},w={"\u21E7":s.SHIFT,shift:s.SHIFT,"\u2325":s.ALT,alt:s.ALT,option:s.ALT,"\u2303":s.CTRL,ctrl:s.CTRL,control:s.CTRL,"\u2318":s.META,cmd:s.META,command:s.META},m={backspace:"Backspace",tab:"Tab",clear:"Clear",enter:"Enter",return:"Enter",esc:"Escape",escape:"Escape",space:" ",left:"ArrowLeft",up:"ArrowUp",right:"ArrowRight",down:"ArrowDown",del:"Delete",delete:"Delete",home:"Home",end:"End",pageup:"PageUp",pagedown:"PageDown",comma:",",".":".","/":"/","`":"`","-":"-","=":"=",";":";","'":"'","[":"[","]":"]","\\":"\\",Meta:"Meta",MetaLeft:"Meta",MetaRight:"Meta",OS:"Meta",ContextMenu:"Meta",ArrowLeft:"ArrowLeft",ArrowUp:"ArrowUp",ArrowRight:"ArrowRight",ArrowDown:"ArrowDown",Backspace:"Backspace",Tab:"Tab",Clear:"Clear",Enter:"Enter",Escape:"Escape",Delete:"Delete",Home:"Home",End:"End",PageUp:"PageUp",PageDown:"PageDown"},P="CapsLock";var E=e=>m[e]||e.toUpperCase(),D=e=>{let o=0;return e.shiftKey&&(o|=s.SHIFT),e.altKey&&(o|=s.ALT),e.ctrlKey&&(o|=s.CTRL),e.metaKey&&(o|=s.META),o};var X=e=>e.reduce((o,t)=>(t in w?o.mods|=w[t]:o.special.push(m[t]||t.toUpperCase()),o),{mods:0,special:[]}),z=e=>{let t=e.replace(/\s/g,"").split(",");return t[t.length-1]===""&&(t[t.length-2]+=","),t},K=e=>z(e).map(t=>{let p=t.split("+"),u=p[p.length-1];return{key:E(u),shortcut:X(p)}});var I=typeof navigator<"u"&&navigator.userAgent.includes("Firefox"),F=e=>e.isContentEditable||e.tagName==="INPUT"||e.tagName==="SELECT"||e.tagName==="TEXTAREA",b=(e,o)=>{if(e.length!==o.length)return!1;for(let t=0;t<e.length;t++)if(e[t]!==o[t])return!1;return!0};var G=e=>e&&!F(e.target),v=new WeakMap;function T(e,o=G){let t={},p=new Set,u="all",h=0,O=(r,n,d=()=>{},{skipOther:c}={skipOther:!1})=>{let i=typeof n=="function"?"all":n,a=typeof n=="function"?n:d;K(r).forEach(({key:l,shortcut:f})=>{t[l]||(t[l]=[]),t[l].push({scope:i,method:a,shortcut:f,skipOther:c})})},L=(r,n,d="all")=>{K(r).forEach(({key:c,shortcut:i})=>{let a=t[c];if(Array.isArray(a)){let l=t[c].filter(({scope:f,method:y,shortcut:S})=>!(f===d&&S.mods===i.mods&&b(S.special,i.special)&&(n===null||y===n)));l.length?t[c]=l:delete t[c]}})},R=(r,n,d=()=>{})=>{L(r,typeof n=="function"?n:d,typeof n=="function"?"all":n)},N=(r,n)=>L(r,null,n),k=r=>{let n=E(r.key);if(!o(r)||I&&n===P||(h=D(r),!(n==="SHIFT"||n==="ALT"||n==="CTRL"||n==="META")&&!p.has(n)&&p.add(n),!(n in t)))return;let c=t[n].filter(({scope:a,shortcut:{special:l,mods:f}})=>a!==u?!1:b(l,Array.from(p))&&f===h),i=c.find(a=>a.skipOther);i?i.method(r):c.forEach(({method:a})=>{a(r)})},M=r=>{let n=E(r.key);r.key&&r.key.toLowerCase()==="meta"?p.clear():p.delete(n)},B=r=>{Object.keys(t).forEach(n=>{let d=n,c=t[d].filter(({scope:i})=>i!==r);c.length?t[d]=c:delete t[d]})},_=r=>{u=r},j=()=>{t={},p.clear()},H=()=>{p.clear()},C=()=>{if(p.clear(),t={},e){let r=v.get(e);r&&(e.removeEventListener("keydown",r.dispatch),e.removeEventListener("keyup",r.cleanUp),r.window.removeEventListener("focus",r.reset),v.delete(e))}};C();let x=e.defaultView||window;return v.set(e,{dispatch:k,cleanUp:M,reset:H,window:x}),e.addEventListener("keydown",k),e.addEventListener("keyup",M),x.addEventListener("focus",H),{bind:O,unbind:R,unsafeUnbind:N,unbindScope:B,setScope:_,unbindAll:j,getScope:()=>u,destroy:C,isBound:(r,n)=>{let d=n?.scope||u;return K(r).some(({key:i,shortcut:a})=>{let l=t[i];return l?l.some(f=>f.scope===d&&f.shortcut.mods===a.mods&&b(f.shortcut.special,a.special)):!1})},getBoundKeys:r=>{let n=r?.scope||u,d=new Set;return Object.values(t).forEach(c=>{c.forEach(i=>{if(i.scope===n){let a=[];i.shortcut.mods&s.CTRL&&a.push("ctrl"),i.shortcut.mods&s.ALT&&a.push("alt"),i.shortcut.mods&s.SHIFT&&a.push("shift"),i.shortcut.mods&s.META&&a.push("cmd");let l=i.shortcut.special.join("+")||"",f=[...a,l].filter(Boolean).join("+");f&&d.add(f)}})}),Array.from(d)},getHandlers:(r,n)=>{let d=n?.scope||u,c=K(r),i=[];return c.forEach(({key:a,shortcut:l})=>{let f=t[a];f&&f.forEach(y=>{y.scope===d&&y.shortcut.mods===l.mods&&b(y.shortcut.special,l.special)&&i.push(y.method)})}),i}}}var{bind:U,unbind:Q,unsafeUnbind:Z,getScope:ee,setScope:te,unbindScope:ne,unbindAll:re,destroy:oe,isBound:se,getBoundKeys:ie,getHandlers:ae}=T(document),ce=U,de=Q,le=Z;var pe=U;0&&(module.exports={DEFAULT_SCOPE,MODS,SPECIAL,bindKey,createKeybuddy,destroy,getBoundKeys,getHandlers,getScope,isBound,setScope,unbindAll,unbindKey,unbindScope,unsafeUnbindKey});
2
+ var g="all",s={SHIFT:1,ALT:2,CTRL:4,META:8},w={"\u21E7":s.SHIFT,shift:s.SHIFT,"\u2325":s.ALT,alt:s.ALT,option:s.ALT,"\u2303":s.CTRL,ctrl:s.CTRL,control:s.CTRL,"\u2318":s.META,cmd:s.META,command:s.META},m={backspace:"Backspace",tab:"Tab",clear:"Clear",enter:"Enter",return:"Enter",esc:"Escape",escape:"Escape",space:" ",left:"ArrowLeft",up:"ArrowUp",right:"ArrowRight",down:"ArrowDown",del:"Delete",delete:"Delete",home:"Home",end:"End",pageup:"PageUp",pagedown:"PageDown",comma:",",".":".","/":"/","`":"`","-":"-","=":"=",";":";","'":"'","[":"[","]":"]","\\":"\\",Meta:"Meta",MetaLeft:"Meta",MetaRight:"Meta",OS:"Meta",ContextMenu:"Meta",ArrowLeft:"ArrowLeft",ArrowUp:"ArrowUp",ArrowRight:"ArrowRight",ArrowDown:"ArrowDown",Backspace:"Backspace",Tab:"Tab",Clear:"Clear",Enter:"Enter",Escape:"Escape",Delete:"Delete",Home:"Home",End:"End",PageUp:"PageUp",PageDown:"PageDown"},H="CapsLock";var E=e=>(m[e]||e).toLowerCase(),q={shift:!0,alt:!0,control:!0,meta:!0},x=e=>e in q,C=e=>{let d=0;return e.shiftKey&&(d|=s.SHIFT),e.altKey&&(d|=s.ALT),e.ctrlKey&&(d|=s.CTRL),e.metaKey&&(d|=s.META),d};var V=e=>e.reduce((d,t)=>(t in w?d.mods|=w[t]:d.special.push((m[t]||t).toLowerCase()),d),{mods:0,special:[]}),W=e=>{let t=e.replace(/\s/g,"").split(",");return t[t.length-1]===""&&(t[t.length-2]+=","),t},b=e=>W(e).map(t=>{let f=t.split("+"),u=f[f.length-1];return{key:E(u),shortcut:V(f)}});var P=typeof navigator<"u"&&navigator.userAgent.includes("Firefox"),D=e=>e.isContentEditable||e.tagName==="INPUT"||e.tagName==="SELECT"||e.tagName==="TEXTAREA",K=(e,d)=>{if(e.length!==d.length)return!1;for(let t=0;t<e.length;t++)if(e[t]!==d[t])return!1;return!0};var Y=e=>e&&!D(e.target),A=new WeakMap;function I(e,d=Y){let t={},f=new Set,u="all",h=0,O=(n,r,c=()=>{},{skipOther:a}={skipOther:!1})=>{let o=typeof r=="function"?"all":r,i=typeof r=="function"?r:c;b(n).forEach(({key:l,shortcut:p})=>{t[l]||(t[l]=[]),t[l].push({scope:o,method:i,shortcut:p,skipOther:a})})},v=(n,r,c="all")=>{b(n).forEach(({key:a,shortcut:o})=>{let i=t[a];if(Array.isArray(i)){let l=t[a].filter(({scope:p,method:y,shortcut:S})=>!(p===c&&S.mods===o.mods&&K(S.special,o.special)&&(r===null||y===r)));l.length?t[a]=l:delete t[a]}})},U=(n,r,c=()=>{})=>{v(n,typeof r=="function"?r:c,typeof r=="function"?"all":r)},R=(n,r)=>v(n,null,r),L=n=>{let r=E(n.key);if(!d(n)||P&&r===H||(h=C(n),!x(r)&&!f.has(r)&&f.add(r),!(r in t)))return;let a=t[r].filter(({scope:i,shortcut:{special:l,mods:p}})=>i!==u?!1:K(l,Array.from(f))&&p===h),o=a.find(i=>i.skipOther);o?o.method(n):a.forEach(({method:i})=>{i(n)})},M=n=>{let r=E(n.key);n.key&&n.key.toLowerCase()==="meta"?f.clear():f.delete(r)},N=n=>{Object.keys(t).forEach(r=>{let c=r,a=t[c].filter(({scope:o})=>o!==n);a.length?t[c]=a:delete t[c]})},B=n=>{u=n},_=()=>{t={},f.clear()},T=()=>{f.clear()},j=()=>{if(f.clear(),t={},e){let n=A.get(e);n&&(e.removeEventListener("keydown",n.dispatch),e.removeEventListener("keyup",n.cleanUp),n.window.removeEventListener("focus",n.reset),A.delete(e))}},k=e.defaultView||window;return A.set(e,{dispatch:L,cleanUp:M,reset:T,window:k}),e.addEventListener("keydown",L),e.addEventListener("keyup",M),k.addEventListener("focus",T),{bind:O,unbind:U,unsafeUnbind:R,unbindScope:N,setScope:B,unbindAll:_,getScope:()=>u,destroy:j,isBound:(n,r)=>{let c=r?.scope||u;return b(n).some(({key:o,shortcut:i})=>{let l=t[o];return l?l.some(p=>p.scope===c&&p.shortcut.mods===i.mods&&K(p.shortcut.special,i.special)):!1})},getBoundKeys:n=>{let r=n?.scope||u,c=new Set;return Object.values(t).forEach(a=>{a.forEach(o=>{if(o.scope===r){let i=[];o.shortcut.mods&s.CTRL&&i.push("ctrl"),o.shortcut.mods&s.ALT&&i.push("alt"),o.shortcut.mods&s.SHIFT&&i.push("shift"),o.shortcut.mods&s.META&&i.push("cmd");let l=o.shortcut.special.join("+")||"",p=[...i,l].filter(Boolean).join("+");p&&c.add(p)}})}),Array.from(c)},getHandlers:(n,r)=>{let c=r?.scope||u,a=b(n),o=[];return a.forEach(({key:i,shortcut:l})=>{let p=t[i];p&&p.forEach(y=>{y.scope===c&&y.shortcut.mods===l.mods&&K(y.shortcut.special,l.special)&&o.push(y.method)})}),o}}}var{bind:F,unbind:$,unsafeUnbind:J,getScope:he,setScope:Se,unbindScope:we,unbindAll:Ae,destroy:ve,isBound:Le,getBoundKeys:Me,getHandlers:Te}=I(document),ke=F,He=$,xe=J;var Ce=F;export{g as DEFAULT_SCOPE,s as MODS,m as SPECIAL,ke as bindKey,I as createKeybuddy,Ce as default,ve as destroy,Me as getBoundKeys,Te as getHandlers,he as getScope,Le as isBound,Se as setScope,Ae as unbindAll,He as unbindKey,we as unbindScope,xe as unsafeUnbindKey};
3
3
  //# sourceMappingURL=index.js.map
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/helpers/keyboard.ts","../src/helpers/keymap.ts","../src/helpers/utils.ts","../src/keybuddy.ts"],"sourcesContent":["import { DEFAULT_SCOPE } from './constants';\nimport { createKeybuddy } from './keybuddy';\n\nexport { createKeybuddy };\n\nconst {\n bind,\n unbind,\n unsafeUnbind,\n getScope,\n setScope,\n unbindScope,\n unbindAll,\n destroy,\n isBound,\n getBoundKeys,\n getHandlers,\n} = createKeybuddy(document);\n\nexport const bindKey = bind;\nexport const unbindKey = unbind;\nexport const unsafeUnbindKey = unsafeUnbind;\n\nexport {\n setScope,\n unbindScope,\n unbindAll,\n getScope,\n destroy,\n isBound,\n getBoundKeys,\n getHandlers,\n DEFAULT_SCOPE,\n};\nexport type { KeyString } from './constants';\nexport { MODS, SPECIAL } from './constants';\n\nexport default bind;\n","export const DEFAULT_SCOPE = 'all';\n\ndeclare const KeyStringBrand: unique symbol;\n\nexport type KeyString = string & { readonly [KeyStringBrand]: true };\n\nexport const MODS = {\n SHIFT: 0b0001, // 1\n ALT: 0b0010, // 2\n CTRL: 0b0100, // 4\n META: 0b1000, // 8\n} as const;\n\n// Map string modifier names to bitwise flags for parsing\nexport type ModifierNames = {\n '⇧': number;\n shift: number;\n '⌥': number;\n alt: number;\n option: number;\n '⌃': number;\n ctrl: number;\n control: number;\n '⌘': number;\n cmd: number;\n command: number;\n};\n\nexport const MODIFIERS: ModifierNames = {\n '⇧': MODS.SHIFT,\n shift: MODS.SHIFT,\n '⌥': MODS.ALT,\n alt: MODS.ALT,\n option: MODS.ALT,\n '⌃': MODS.CTRL,\n ctrl: MODS.CTRL,\n control: MODS.CTRL,\n '⌘': MODS.META,\n cmd: MODS.META,\n command: MODS.META,\n};\n\nexport const SPECIAL: { [key: string]: string } = {\n backspace: 'Backspace',\n tab: 'Tab',\n clear: 'Clear',\n enter: 'Enter',\n return: 'Enter',\n esc: 'Escape',\n escape: 'Escape',\n space: ' ',\n left: 'ArrowLeft',\n up: 'ArrowUp',\n right: 'ArrowRight',\n down: 'ArrowDown',\n del: 'Delete',\n delete: 'Delete',\n home: 'Home',\n end: 'End',\n pageup: 'PageUp',\n pagedown: 'PageDown',\n comma: ',',\n '.': '.',\n '/': '/',\n '`': '`',\n '-': '-',\n '=': '=',\n ';': ';',\n \"'\": \"'\",\n '[': '[',\n ']': ']',\n '\\\\': '\\\\',\n // Normalize Meta key variants\n Meta: 'Meta',\n MetaLeft: 'Meta',\n MetaRight: 'Meta',\n OS: 'Meta', // Some browsers use OS instead of Meta\n ContextMenu: 'Meta', // Right-click context menu key sometimes acts as Meta\n // Add identity mappings for already-normalized keys\n ArrowLeft: 'ArrowLeft',\n ArrowUp: 'ArrowUp',\n ArrowRight: 'ArrowRight',\n ArrowDown: 'ArrowDown',\n Backspace: 'Backspace',\n Tab: 'Tab',\n Clear: 'Clear',\n Enter: 'Enter',\n Escape: 'Escape',\n Delete: 'Delete',\n Home: 'Home',\n End: 'End',\n PageUp: 'PageUp',\n PageDown: 'PageDown',\n};\n\nexport const CAPS_LOCK_KEY = 'CapsLock';\n","import { KeyString, MODS, SPECIAL } from '../constants';\n\nexport const getKeyIdentifier = (key: string): KeyString => {\n return (SPECIAL[key] || key.toUpperCase()) as KeyString;\n};\n\nexport const updateModifiers = (e: KeyboardEvent): number => {\n let modifiers = 0;\n if (e.shiftKey) modifiers |= MODS.SHIFT;\n if (e.altKey) modifiers |= MODS.ALT;\n if (e.ctrlKey) modifiers |= MODS.CTRL;\n if (e.metaKey) modifiers |= MODS.META;\n return modifiers;\n};\n","import { KeyString, MODIFIERS, ModifierNames, SPECIAL } from '../constants';\nimport { getKeyIdentifier } from './keyboard';\n\nexport interface ParsedShortcut {\n mods: number; // Bitwise flag for modifiers\n special: string[];\n}\nexport interface KeyMap {\n key: KeyString;\n shortcut: ParsedShortcut;\n}\n\nconst getMods = (keys: string[]): ParsedShortcut =>\n keys.reduce(\n (acc, key) => {\n if (key in MODIFIERS) {\n acc.mods |= MODIFIERS[key as keyof ModifierNames];\n } else {\n acc.special.push(SPECIAL[key] || key.toUpperCase());\n }\n return acc;\n },\n {\n mods: 0, // Start with no modifiers\n special: [],\n } as ParsedShortcut,\n );\n\nconst getCombinations = (keysStr: string): string[] => {\n const cleanKeys = keysStr.replace(/\\s/g, '');\n const keys = cleanKeys.split(',');\n if (keys[keys.length - 1] === '') {\n keys[keys.length - 2] += ',';\n }\n\n return keys;\n};\n\nexport const getKeyMap = (keysStr: string): KeyMap[] => {\n const keymap = getCombinations(keysStr);\n return keymap.map((keyCmd) => {\n const keys = keyCmd.split('+');\n const key = keys[keys.length - 1];\n const keyIdentifier = getKeyIdentifier(key);\n\n return {\n key: keyIdentifier,\n shortcut: getMods(keys),\n };\n });\n};\n","export const invariant = (\n condition: boolean,\n message: string,\n ...args: unknown[]\n) => {\n if (\n typeof process !== 'undefined' &&\n process.env &&\n process.env.NODE_ENV === 'development' &&\n !condition\n ) {\n throw new Error(\n `Invariant failed: ${message}${args.length ? ` ${JSON.stringify(args)}` : ''}`,\n );\n }\n};\n\nexport const isFirefox =\n typeof navigator !== 'undefined' && navigator.userAgent.includes('Firefox');\n\nexport const isEditable = (el: HTMLElement): boolean =>\n el.isContentEditable ||\n el.tagName === 'INPUT' ||\n el.tagName === 'SELECT' ||\n el.tagName === 'TEXTAREA';\n\nexport const isEqArray = (\n arr1: (string | number)[],\n arr2: (string | number)[],\n): boolean => {\n if (arr1.length !== arr2.length) return false;\n\n for (let i = 0; i < arr1.length; i++) {\n if (arr1[i] !== arr2[i]) return false;\n }\n\n return true;\n};\n","import { CAPS_LOCK_KEY, DEFAULT_SCOPE, KeyString, MODS } from './constants';\nimport { getKeyIdentifier, updateModifiers } from './helpers/keyboard';\nimport { getKeyMap, ParsedShortcut } from './helpers/keymap';\nimport { invariant, isEditable, isEqArray, isFirefox } from './helpers/utils';\n\ntype KeyHandler = (e: KeyboardEvent) => void;\ntype FilterFn = (el: KeyboardEvent) => boolean;\n\ninterface Handler {\n scope: string;\n method: KeyHandler;\n shortcut: ParsedShortcut;\n skipOther: boolean;\n}\n\nconst defaultFilter = (e: KeyboardEvent): boolean =>\n e && !isEditable(e.target as HTMLElement);\n\nconst documentListeners = new WeakMap<\n Document,\n {\n dispatch: (e: KeyboardEvent) => void;\n cleanUp: (e: KeyboardEvent) => void;\n reset: () => void;\n window: Window & typeof globalThis;\n }\n>();\n\nexport function createKeybuddy(\n doc: Document,\n filterFn: FilterFn = defaultFilter,\n) {\n let handlers: { [key: KeyString]: Handler[] } = {};\n const downKeys: Set<KeyString> = new Set();\n let activeScope = DEFAULT_SCOPE;\n\n let modifiers = 0;\n\n const bindKey = (\n keysStr: string,\n scopeOrMethod: string | KeyHandler,\n methodOrNull: KeyHandler = () => {},\n {\n skipOther,\n }: {\n skipOther: boolean;\n } = {\n skipOther: false,\n },\n ): void => {\n const scope: string =\n typeof scopeOrMethod === 'function' ? DEFAULT_SCOPE : scopeOrMethod;\n const method: KeyHandler =\n typeof scopeOrMethod === 'function' ? scopeOrMethod : methodOrNull;\n\n getKeyMap(keysStr).forEach(({ key, shortcut }) => {\n if (!handlers[key]) {\n handlers[key] = [];\n }\n const handler = handlers[key];\n if (process.env.NODE_ENV === 'development') {\n if (skipOther) {\n const action = handler.find((i) => i.skipOther);\n invariant(\n !action,\n \"Conflicting 'skipOther' property with action\",\n action,\n );\n }\n }\n\n handler.push({\n scope,\n method,\n shortcut,\n skipOther,\n });\n });\n };\n\n const unbindKeyProcess = (\n keysStr: string,\n deleteMethod: null | KeyHandler,\n deleteScope: string = DEFAULT_SCOPE,\n ): void => {\n getKeyMap(keysStr).forEach(({ key, shortcut }) => {\n const handler = handlers[key];\n if (Array.isArray(handler)) {\n const handler = handlers[key].filter(\n ({ scope, method, shortcut: methodShortcut }: Handler) =>\n !(\n scope === deleteScope &&\n methodShortcut.mods === shortcut.mods &&\n isEqArray(methodShortcut.special, shortcut.special) &&\n (deleteMethod === null ? true : method === deleteMethod)\n ),\n );\n if (handler.length) {\n handlers[key] = handler;\n } else {\n delete handlers[key];\n }\n }\n });\n };\n\n const unbindKey = (\n keysStr: string,\n scopeOrMethod: string | KeyHandler,\n methodOrNull: KeyHandler = () => {},\n ) => {\n const deleteScope: string =\n typeof scopeOrMethod === 'function' ? DEFAULT_SCOPE : scopeOrMethod;\n const deleteMethod: KeyHandler =\n typeof scopeOrMethod === 'function' ? scopeOrMethod : methodOrNull;\n unbindKeyProcess(keysStr, deleteMethod, deleteScope);\n };\n\n const unsafeUnbindKey = (keysStr: string, scope?: string) =>\n unbindKeyProcess(keysStr, null, scope);\n\n const dispatch = (e: KeyboardEvent) => {\n const key = getKeyIdentifier(e.key);\n\n if (!filterFn(e)) {\n return;\n }\n\n if (isFirefox && key === CAPS_LOCK_KEY) {\n return;\n }\n\n modifiers = updateModifiers(e);\n\n const isModifierKey =\n key === ('SHIFT' as KeyString) ||\n key === ('ALT' as KeyString) ||\n key === ('CTRL' as KeyString) ||\n key === ('META' as KeyString);\n if (!isModifierKey && !downKeys.has(key)) {\n downKeys.add(key);\n }\n\n if (!(key in handlers)) {\n return;\n }\n\n const currentHandlers = handlers[key].filter(\n ({ scope, shortcut: { special, mods } }) => {\n if (scope !== activeScope) {\n return false;\n }\n\n return isEqArray(special, Array.from(downKeys)) && mods === modifiers;\n },\n );\n\n const primaryAction: Handler | undefined = currentHandlers.find(\n (action) => action.skipOther,\n );\n if (primaryAction) {\n primaryAction.method(e);\n } else {\n currentHandlers.forEach(({ method }) => {\n method(e);\n });\n }\n };\n\n const cleanUp = (e: KeyboardEvent) => {\n const key = getKeyIdentifier(e.key);\n\n if (e.key && e.key.toLowerCase() === 'meta') {\n downKeys.clear();\n } else {\n downKeys.delete(key);\n }\n };\n\n const unbindScope = (deleteScope: string): void => {\n Object.keys(handlers).forEach((key) => {\n const keyString = key as KeyString;\n const handler = handlers[keyString].filter(\n ({ scope }: Handler) => scope !== deleteScope,\n );\n if (handler.length) {\n handlers[keyString] = handler;\n } else {\n delete handlers[keyString];\n }\n });\n };\n\n const setScope = (scope: string): void => {\n activeScope = scope;\n };\n\n const unbindAll = (): void => {\n handlers = {};\n downKeys.clear();\n };\n\n const reset = (): void => {\n downKeys.clear();\n };\n\n const destroy = (): void => {\n downKeys.clear();\n handlers = {};\n if (doc) {\n const listeners = documentListeners.get(doc);\n if (listeners) {\n doc.removeEventListener('keydown', listeners.dispatch);\n doc.removeEventListener('keyup', listeners.cleanUp);\n listeners.window.removeEventListener('focus', listeners.reset);\n documentListeners.delete(doc);\n }\n }\n };\n\n destroy();\n\n const win = (doc.defaultView || window) as Window & typeof globalThis;\n\n documentListeners.set(doc, { dispatch, cleanUp, reset, window: win });\n doc.addEventListener('keydown', dispatch);\n doc.addEventListener('keyup', cleanUp);\n win.addEventListener('focus', reset);\n\n const getScope = () => activeScope;\n\n const isBound = (keysStr: string, options?: { scope?: string }): boolean => {\n const scope = options?.scope || activeScope;\n const keyMaps = getKeyMap(keysStr);\n\n return keyMaps.some(({ key, shortcut }) => {\n const keyHandlers = handlers[key];\n if (!keyHandlers) return false;\n\n return keyHandlers.some(\n (h) =>\n h.scope === scope &&\n h.shortcut.mods === shortcut.mods &&\n isEqArray(h.shortcut.special, shortcut.special),\n );\n });\n };\n\n const getBoundKeys = (options?: { scope?: string }): string[] => {\n const scope = options?.scope || activeScope;\n const keys = new Set<string>();\n\n Object.values(handlers).forEach((handlerList) => {\n handlerList.forEach((handler) => {\n if (handler.scope === scope) {\n const modParts: string[] = [];\n if (handler.shortcut.mods & MODS.CTRL) modParts.push('ctrl');\n if (handler.shortcut.mods & MODS.ALT) modParts.push('alt');\n if (handler.shortcut.mods & MODS.SHIFT) modParts.push('shift');\n if (handler.shortcut.mods & MODS.META) modParts.push('cmd');\n\n const keyPart = handler.shortcut.special.join('+') || '';\n const fullKey = [...modParts, keyPart].filter(Boolean).join('+');\n if (fullKey) keys.add(fullKey);\n }\n });\n });\n\n return Array.from(keys);\n };\n\n const getHandlers = (\n keysStr: string,\n options?: { scope?: string },\n ): KeyHandler[] => {\n const scope = options?.scope || activeScope;\n const keyMaps = getKeyMap(keysStr);\n const result: KeyHandler[] = [];\n\n keyMaps.forEach(({ key, shortcut }) => {\n const keyHandlers = handlers[key];\n if (!keyHandlers) return;\n\n keyHandlers.forEach((h) => {\n if (\n h.scope === scope &&\n h.shortcut.mods === shortcut.mods &&\n isEqArray(h.shortcut.special, shortcut.special)\n ) {\n result.push(h.method);\n }\n });\n });\n\n return result;\n };\n\n return {\n bind: bindKey,\n unbind: unbindKey,\n unsafeUnbind: unsafeUnbindKey,\n unbindScope,\n setScope,\n unbindAll,\n getScope,\n destroy,\n isBound,\n getBoundKeys,\n getHandlers,\n };\n}\n"],"mappings":"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","names":["src_exports","__export","DEFAULT_SCOPE","MODS","SPECIAL","bindKey","createKeybuddy","src_default","destroy","getBoundKeys","getHandlers","getScope","isBound","setScope","unbindAll","unbindKey","unbindScope","unsafeUnbindKey","__toCommonJS","DEFAULT_SCOPE","MODS","MODIFIERS","SPECIAL","CAPS_LOCK_KEY","getKeyIdentifier","key","SPECIAL","updateModifiers","modifiers","MODS","getMods","keys","acc","key","MODIFIERS","SPECIAL","getCombinations","keysStr","getKeyMap","keyCmd","getKeyIdentifier","isFirefox","isEditable","el","isEqArray","arr1","arr2","i","defaultFilter","isEditable","documentListeners","createKeybuddy","doc","filterFn","handlers","downKeys","activeScope","modifiers","bindKey","keysStr","scopeOrMethod","methodOrNull","skipOther","scope","method","getKeyMap","key","shortcut","unbindKeyProcess","deleteMethod","deleteScope","handler","methodShortcut","isEqArray","unbindKey","unsafeUnbindKey","dispatch","e","getKeyIdentifier","isFirefox","CAPS_LOCK_KEY","updateModifiers","currentHandlers","special","mods","primaryAction","action","cleanUp","unbindScope","keyString","setScope","unbindAll","reset","destroy","listeners","win","options","keyHandlers","h","keys","handlerList","modParts","MODS","keyPart","fullKey","keyMaps","result","bind","unbind","unsafeUnbind","getScope","setScope","unbindScope","unbindAll","destroy","isBound","getBoundKeys","getHandlers","createKeybuddy","bindKey","unbindKey","unsafeUnbindKey","src_default","bind"]}
1
+ {"version":3,"sources":["../src/constants.ts","../src/helpers/keyboard.ts","../src/helpers/keymap.ts","../src/helpers/utils.ts","../src/keybuddy.ts","../src/index.ts"],"sourcesContent":["export const DEFAULT_SCOPE = 'all';\n\ndeclare const KeyStringBrand: unique symbol;\n\nexport type KeyString = string & { readonly [KeyStringBrand]: true };\n\nexport const MODS = {\n SHIFT: 0b0001, // 1\n ALT: 0b0010, // 2\n CTRL: 0b0100, // 4\n META: 0b1000, // 8\n} as const;\n\n// Map string modifier names to bitwise flags for parsing\nexport type ModifierNames = {\n '⇧': number;\n shift: number;\n '⌥': number;\n alt: number;\n option: number;\n '⌃': number;\n ctrl: number;\n control: number;\n '⌘': number;\n cmd: number;\n command: number;\n};\n\nexport const MODIFIERS: ModifierNames = {\n '⇧': MODS.SHIFT,\n shift: MODS.SHIFT,\n '⌥': MODS.ALT,\n alt: MODS.ALT,\n option: MODS.ALT,\n '⌃': MODS.CTRL,\n ctrl: MODS.CTRL,\n control: MODS.CTRL,\n '⌘': MODS.META,\n cmd: MODS.META,\n command: MODS.META,\n};\n\nexport const SPECIAL: { [key: string]: string } = {\n backspace: 'Backspace',\n tab: 'Tab',\n clear: 'Clear',\n enter: 'Enter',\n return: 'Enter',\n esc: 'Escape',\n escape: 'Escape',\n space: ' ',\n left: 'ArrowLeft',\n up: 'ArrowUp',\n right: 'ArrowRight',\n down: 'ArrowDown',\n del: 'Delete',\n delete: 'Delete',\n home: 'Home',\n end: 'End',\n pageup: 'PageUp',\n pagedown: 'PageDown',\n comma: ',',\n '.': '.',\n '/': '/',\n '`': '`',\n '-': '-',\n '=': '=',\n ';': ';',\n \"'\": \"'\",\n '[': '[',\n ']': ']',\n '\\\\': '\\\\',\n // Normalize Meta key variants\n Meta: 'Meta',\n MetaLeft: 'Meta',\n MetaRight: 'Meta',\n OS: 'Meta', // Some browsers use OS instead of Meta\n ContextMenu: 'Meta', // Right-click context menu key sometimes acts as Meta\n // Add identity mappings for already-normalized keys\n ArrowLeft: 'ArrowLeft',\n ArrowUp: 'ArrowUp',\n ArrowRight: 'ArrowRight',\n ArrowDown: 'ArrowDown',\n Backspace: 'Backspace',\n Tab: 'Tab',\n Clear: 'Clear',\n Enter: 'Enter',\n Escape: 'Escape',\n Delete: 'Delete',\n Home: 'Home',\n End: 'End',\n PageUp: 'PageUp',\n PageDown: 'PageDown',\n};\n\nexport const CAPS_LOCK_KEY = 'CapsLock';\n","import { KeyString, MODS, SPECIAL } from '../constants';\n\nexport const getKeyIdentifier = (key: string): KeyString => {\n return (SPECIAL[key] || key).toLowerCase() as KeyString;\n};\n\nconst MODIFIER_KEYS: Record<string, true> = {\n shift: true,\n alt: true,\n control: true,\n meta: true,\n};\n\nexport const isModifierKey = (key: string): boolean => key in MODIFIER_KEYS;\n\nexport const updateModifiers = (e: KeyboardEvent): number => {\n let modifiers = 0;\n if (e.shiftKey) modifiers |= MODS.SHIFT;\n if (e.altKey) modifiers |= MODS.ALT;\n if (e.ctrlKey) modifiers |= MODS.CTRL;\n if (e.metaKey) modifiers |= MODS.META;\n return modifiers;\n};\n","import { KeyString, MODIFIERS, ModifierNames, SPECIAL } from '../constants';\nimport { getKeyIdentifier } from './keyboard';\n\nexport interface ParsedShortcut {\n mods: number; // Bitwise flag for modifiers\n special: string[];\n}\nexport interface KeyMap {\n key: KeyString;\n shortcut: ParsedShortcut;\n}\n\nconst getMods = (keys: string[]): ParsedShortcut =>\n keys.reduce(\n (acc, key) => {\n if (key in MODIFIERS) {\n acc.mods |= MODIFIERS[key as keyof ModifierNames];\n } else {\n acc.special.push((SPECIAL[key] || key).toLowerCase());\n }\n return acc;\n },\n {\n mods: 0, // Start with no modifiers\n special: [],\n } as ParsedShortcut,\n );\n\nconst getCombinations = (keysStr: string): string[] => {\n const cleanKeys = keysStr.replace(/\\s/g, '');\n const keys = cleanKeys.split(',');\n if (keys[keys.length - 1] === '') {\n keys[keys.length - 2] += ',';\n }\n\n return keys;\n};\n\nexport const getKeyMap = (keysStr: string): KeyMap[] => {\n const keymap = getCombinations(keysStr);\n return keymap.map((keyCmd) => {\n const keys = keyCmd.split('+');\n const key = keys[keys.length - 1];\n const keyIdentifier = getKeyIdentifier(key);\n\n return {\n key: keyIdentifier,\n shortcut: getMods(keys),\n };\n });\n};\n","export const invariant = (\n condition: boolean,\n message: string,\n ...args: unknown[]\n) => {\n if (\n typeof process !== 'undefined' &&\n process.env &&\n process.env.NODE_ENV === 'development' &&\n !condition\n ) {\n throw new Error(\n `Invariant failed: ${message}${args.length ? ` ${JSON.stringify(args)}` : ''}`,\n );\n }\n};\n\nexport const isFirefox =\n typeof navigator !== 'undefined' && navigator.userAgent.includes('Firefox');\n\nexport const isEditable = (el: HTMLElement): boolean =>\n el.isContentEditable ||\n el.tagName === 'INPUT' ||\n el.tagName === 'SELECT' ||\n el.tagName === 'TEXTAREA';\n\nexport const isEqArray = (\n arr1: (string | number)[],\n arr2: (string | number)[],\n): boolean => {\n if (arr1.length !== arr2.length) return false;\n\n for (let i = 0; i < arr1.length; i++) {\n if (arr1[i] !== arr2[i]) return false;\n }\n\n return true;\n};\n","import { CAPS_LOCK_KEY, DEFAULT_SCOPE, KeyString, MODS } from './constants';\nimport { getKeyIdentifier, isModifierKey, updateModifiers } from './helpers/keyboard';\nimport { getKeyMap, ParsedShortcut } from './helpers/keymap';\nimport { invariant, isEditable, isEqArray, isFirefox } from './helpers/utils';\n\ntype KeyHandler = (e: KeyboardEvent) => void;\ntype FilterFn = (el: KeyboardEvent) => boolean;\n\ninterface Handler {\n scope: string;\n method: KeyHandler;\n shortcut: ParsedShortcut;\n skipOther: boolean;\n}\n\nconst defaultFilter = (e: KeyboardEvent): boolean =>\n e && !isEditable(e.target as HTMLElement);\n\nconst documentListeners = new WeakMap<\n Document,\n {\n dispatch: (e: KeyboardEvent) => void;\n cleanUp: (e: KeyboardEvent) => void;\n reset: () => void;\n window: Window & typeof globalThis;\n }\n>();\n\nexport function createKeybuddy(\n doc: Document,\n filterFn: FilterFn = defaultFilter,\n) {\n let handlers: { [key: KeyString]: Handler[] } = {};\n const downKeys: Set<KeyString> = new Set();\n let activeScope = DEFAULT_SCOPE;\n\n let modifiers = 0;\n\n const bindKey = (\n keysStr: string,\n scopeOrMethod: string | KeyHandler,\n methodOrNull: KeyHandler = () => {},\n {\n skipOther,\n }: {\n skipOther: boolean;\n } = {\n skipOther: false,\n },\n ): void => {\n const scope: string =\n typeof scopeOrMethod === 'function' ? DEFAULT_SCOPE : scopeOrMethod;\n const method: KeyHandler =\n typeof scopeOrMethod === 'function' ? scopeOrMethod : methodOrNull;\n\n getKeyMap(keysStr).forEach(({ key, shortcut }) => {\n if (!handlers[key]) {\n handlers[key] = [];\n }\n const handler = handlers[key];\n if (process.env.NODE_ENV === 'development') {\n if (skipOther) {\n const action = handler.find((i) => i.skipOther);\n invariant(\n !action,\n \"Conflicting 'skipOther' property with action\",\n action,\n );\n }\n }\n\n handler.push({\n scope,\n method,\n shortcut,\n skipOther,\n });\n });\n };\n\n const unbindKeyProcess = (\n keysStr: string,\n deleteMethod: null | KeyHandler,\n deleteScope: string = DEFAULT_SCOPE,\n ): void => {\n getKeyMap(keysStr).forEach(({ key, shortcut }) => {\n const handler = handlers[key];\n if (Array.isArray(handler)) {\n const handler = handlers[key].filter(\n ({ scope, method, shortcut: methodShortcut }: Handler) =>\n !(\n scope === deleteScope &&\n methodShortcut.mods === shortcut.mods &&\n isEqArray(methodShortcut.special, shortcut.special) &&\n (deleteMethod === null ? true : method === deleteMethod)\n ),\n );\n if (handler.length) {\n handlers[key] = handler;\n } else {\n delete handlers[key];\n }\n }\n });\n };\n\n const unbindKey = (\n keysStr: string,\n scopeOrMethod: string | KeyHandler,\n methodOrNull: KeyHandler = () => {},\n ) => {\n const deleteScope: string =\n typeof scopeOrMethod === 'function' ? DEFAULT_SCOPE : scopeOrMethod;\n const deleteMethod: KeyHandler =\n typeof scopeOrMethod === 'function' ? scopeOrMethod : methodOrNull;\n unbindKeyProcess(keysStr, deleteMethod, deleteScope);\n };\n\n const unsafeUnbindKey = (keysStr: string, scope?: string) =>\n unbindKeyProcess(keysStr, null, scope);\n\n const dispatch = (e: KeyboardEvent) => {\n const key = getKeyIdentifier(e.key);\n\n if (!filterFn(e)) {\n return;\n }\n\n if (isFirefox && key === CAPS_LOCK_KEY) {\n return;\n }\n\n modifiers = updateModifiers(e);\n\n const isModifier = isModifierKey(key);\n if (!isModifier && !downKeys.has(key)) {\n downKeys.add(key);\n }\n\n if (!(key in handlers)) {\n return;\n }\n\n const currentHandlers = handlers[key].filter(\n ({ scope, shortcut: { special, mods } }) => {\n if (scope !== activeScope) {\n return false;\n }\n\n return isEqArray(special, Array.from(downKeys)) && mods === modifiers;\n },\n );\n\n const primaryAction: Handler | undefined = currentHandlers.find(\n (action) => action.skipOther,\n );\n\n console.log('has it?', primaryAction, currentHandlers);\n if (primaryAction) {\n primaryAction.method(e);\n } else {\n currentHandlers.forEach(({ method }) => {\n method(e);\n });\n }\n };\n\n const cleanUp = (e: KeyboardEvent) => {\n const key = getKeyIdentifier(e.key);\n\n if (e.key && e.key.toLowerCase() === 'meta') {\n downKeys.clear();\n } else {\n downKeys.delete(key);\n }\n };\n\n const unbindScope = (deleteScope: string): void => {\n Object.keys(handlers).forEach((key) => {\n const keyString = key as KeyString;\n const handler = handlers[keyString].filter(\n ({ scope }: Handler) => scope !== deleteScope,\n );\n if (handler.length) {\n handlers[keyString] = handler;\n } else {\n delete handlers[keyString];\n }\n });\n };\n\n const setScope = (scope: string): void => {\n activeScope = scope;\n };\n\n const unbindAll = (): void => {\n handlers = {};\n downKeys.clear();\n };\n\n const reset = (): void => {\n downKeys.clear();\n };\n\n const destroy = (): void => {\n downKeys.clear();\n handlers = {};\n if (doc) {\n const listeners = documentListeners.get(doc);\n if (listeners) {\n doc.removeEventListener('keydown', listeners.dispatch);\n doc.removeEventListener('keyup', listeners.cleanUp);\n listeners.window.removeEventListener('focus', listeners.reset);\n documentListeners.delete(doc);\n }\n }\n };\n\n const win = (doc.defaultView || window) as Window & typeof globalThis;\n\n documentListeners.set(doc, { dispatch, cleanUp, reset, window: win });\n doc.addEventListener('keydown', dispatch);\n doc.addEventListener('keyup', cleanUp);\n win.addEventListener('focus', reset);\n\n const getScope = () => activeScope;\n\n const isBound = (keysStr: string, options?: { scope?: string }): boolean => {\n const scope = options?.scope || activeScope;\n const keyMaps = getKeyMap(keysStr);\n\n return keyMaps.some(({ key, shortcut }) => {\n const keyHandlers = handlers[key];\n if (!keyHandlers) return false;\n\n return keyHandlers.some(\n (h) =>\n h.scope === scope &&\n h.shortcut.mods === shortcut.mods &&\n isEqArray(h.shortcut.special, shortcut.special),\n );\n });\n };\n\n const getBoundKeys = (options?: { scope?: string }): string[] => {\n const scope = options?.scope || activeScope;\n const keys = new Set<string>();\n\n Object.values(handlers).forEach((handlerList) => {\n handlerList.forEach((handler) => {\n if (handler.scope === scope) {\n const modParts: string[] = [];\n if (handler.shortcut.mods & MODS.CTRL) modParts.push('ctrl');\n if (handler.shortcut.mods & MODS.ALT) modParts.push('alt');\n if (handler.shortcut.mods & MODS.SHIFT) modParts.push('shift');\n if (handler.shortcut.mods & MODS.META) modParts.push('cmd');\n\n const keyPart = handler.shortcut.special.join('+') || '';\n const fullKey = [...modParts, keyPart].filter(Boolean).join('+');\n if (fullKey) keys.add(fullKey);\n }\n });\n });\n\n return Array.from(keys);\n };\n\n const getHandlers = (\n keysStr: string,\n options?: { scope?: string },\n ): KeyHandler[] => {\n const scope = options?.scope || activeScope;\n const keyMaps = getKeyMap(keysStr);\n const result: KeyHandler[] = [];\n\n keyMaps.forEach(({ key, shortcut }) => {\n const keyHandlers = handlers[key];\n if (!keyHandlers) return;\n\n keyHandlers.forEach((h) => {\n if (\n h.scope === scope &&\n h.shortcut.mods === shortcut.mods &&\n isEqArray(h.shortcut.special, shortcut.special)\n ) {\n result.push(h.method);\n }\n });\n });\n\n return result;\n };\n\n return {\n bind: bindKey,\n unbind: unbindKey,\n unsafeUnbind: unsafeUnbindKey,\n unbindScope,\n setScope,\n unbindAll,\n getScope,\n destroy,\n isBound,\n getBoundKeys,\n getHandlers,\n };\n}\n","import { DEFAULT_SCOPE } from './constants';\nimport { createKeybuddy } from './keybuddy';\n\nexport { createKeybuddy };\n\nconst {\n bind,\n unbind,\n unsafeUnbind,\n getScope,\n setScope,\n unbindScope,\n unbindAll,\n destroy,\n isBound,\n getBoundKeys,\n getHandlers,\n} = createKeybuddy(document);\n\nexport const bindKey = bind;\nexport const unbindKey = unbind;\nexport const unsafeUnbindKey = unsafeUnbind;\n\nexport {\n setScope,\n unbindScope,\n unbindAll,\n getScope,\n destroy,\n isBound,\n getBoundKeys,\n getHandlers,\n DEFAULT_SCOPE,\n};\nexport type { KeyString } from './constants';\nexport { MODS, SPECIAL } from './constants';\n\nexport default bind;\n"],"mappings":";AAAO,IAAMA,EAAgB,MAMhBC,EAAO,CAClB,MAAO,EACP,IAAK,EACL,KAAM,EACN,KAAM,CACR,EAiBaC,EAA2B,CACtC,SAAKD,EAAK,MACV,MAAOA,EAAK,MACZ,SAAKA,EAAK,IACV,IAAKA,EAAK,IACV,OAAQA,EAAK,IACb,SAAKA,EAAK,KACV,KAAMA,EAAK,KACX,QAASA,EAAK,KACd,SAAKA,EAAK,KACV,IAAKA,EAAK,KACV,QAASA,EAAK,IAChB,EAEaE,EAAqC,CAChD,UAAW,YACX,IAAK,MACL,MAAO,QACP,MAAO,QACP,OAAQ,QACR,IAAK,SACL,OAAQ,SACR,MAAO,IACP,KAAM,YACN,GAAI,UACJ,MAAO,aACP,KAAM,YACN,IAAK,SACL,OAAQ,SACR,KAAM,OACN,IAAK,MACL,OAAQ,SACR,SAAU,WACV,MAAO,IACP,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,KAAM,KAEN,KAAM,OACN,SAAU,OACV,UAAW,OACX,GAAI,OACJ,YAAa,OAEb,UAAW,YACX,QAAS,UACT,WAAY,aACZ,UAAW,YACX,UAAW,YACX,IAAK,MACL,MAAO,QACP,MAAO,QACP,OAAQ,SACR,OAAQ,SACR,KAAM,OACN,IAAK,MACL,OAAQ,SACR,SAAU,UACZ,EAEaC,EAAgB,WC7FtB,IAAMC,EAAoBC,IACvBC,EAAQD,CAAG,GAAKA,GAAK,YAAY,EAGrCE,EAAsC,CAC1C,MAAO,GACP,IAAK,GACL,QAAS,GACT,KAAM,EACR,EAEaC,EAAiBH,GAAyBA,KAAOE,EAEjDE,EAAmB,GAA6B,CAC3D,IAAIC,EAAY,EAChB,OAAI,EAAE,WAAUA,GAAaC,EAAK,OAC9B,EAAE,SAAQD,GAAaC,EAAK,KAC5B,EAAE,UAASD,GAAaC,EAAK,MAC7B,EAAE,UAASD,GAAaC,EAAK,MAC1BD,CACT,ECVA,IAAME,EAAWC,GACfA,EAAK,OACH,CAACC,EAAKC,KACAA,KAAOC,EACTF,EAAI,MAAQE,EAAUD,CAA0B,EAEhDD,EAAI,QAAQ,MAAMG,EAAQF,CAAG,GAAKA,GAAK,YAAY,CAAC,EAE/CD,GAET,CACE,KAAM,EACN,QAAS,CAAC,CACZ,CACF,EAEII,EAAmBC,GAA8B,CAErD,IAAMN,EADYM,EAAQ,QAAQ,MAAO,EAAE,EACpB,MAAM,GAAG,EAChC,OAAIN,EAAKA,EAAK,OAAS,CAAC,IAAM,KAC5BA,EAAKA,EAAK,OAAS,CAAC,GAAK,KAGpBA,CACT,EAEaO,EAAaD,GACTD,EAAgBC,CAAO,EACxB,IAAKE,GAAW,CAC5B,IAAMR,EAAOQ,EAAO,MAAM,GAAG,EACvBN,EAAMF,EAAKA,EAAK,OAAS,CAAC,EAGhC,MAAO,CACL,IAHoBS,EAAiBP,CAAG,EAIxC,SAAUH,EAAQC,CAAI,CACxB,CACF,CAAC,EChCI,IAAMU,EACX,OAAO,UAAc,KAAe,UAAU,UAAU,SAAS,SAAS,EAE/DC,EAAcC,GACzBA,EAAG,mBACHA,EAAG,UAAY,SACfA,EAAG,UAAY,UACfA,EAAG,UAAY,WAEJC,EAAY,CACvBC,EACAC,IACY,CACZ,GAAID,EAAK,SAAWC,EAAK,OAAQ,MAAO,GAExC,QAASC,EAAI,EAAGA,EAAIF,EAAK,OAAQE,IAC/B,GAAIF,EAAKE,CAAC,IAAMD,EAAKC,CAAC,EAAG,MAAO,GAGlC,MAAO,EACT,ECtBA,IAAMC,EAAiB,GACrB,GAAK,CAACC,EAAW,EAAE,MAAqB,EAEpCC,EAAoB,IAAI,QAUvB,SAASC,EACdC,EACAC,EAAqBL,EACrB,CACA,IAAIM,EAA4C,CAAC,EAC3CC,EAA2B,IAAI,IACjCC,EAAc,MAEdC,EAAY,EAEVC,EAAU,CACdC,EACAC,EACAC,EAA2B,IAAM,CAAC,EAClC,CACE,UAAAC,CACF,EAEI,CACF,UAAW,EACb,IACS,CACT,IAAMC,EACJ,OAAOH,GAAkB,WAAa,MAAgBA,EAClDI,EACJ,OAAOJ,GAAkB,WAAaA,EAAgBC,EAExDI,EAAUN,CAAO,EAAE,QAAQ,CAAC,CAAE,IAAAO,EAAK,SAAAC,CAAS,IAAM,CAC3Cb,EAASY,CAAG,IACfZ,EAASY,CAAG,EAAI,CAAC,GAEHZ,EAASY,CAAG,EAYpB,KAAK,CACX,MAAAH,EACA,OAAAC,EACA,SAAAG,EACA,UAAAL,CACF,CAAC,CACH,CAAC,CACH,EAEMM,EAAmB,CACvBT,EACAU,EACAC,EAAsB,QACb,CACTL,EAAUN,CAAO,EAAE,QAAQ,CAAC,CAAE,IAAAO,EAAK,SAAAC,CAAS,IAAM,CAChD,IAAMI,EAAUjB,EAASY,CAAG,EAC5B,GAAI,MAAM,QAAQK,CAAO,EAAG,CAC1B,IAAMA,EAAUjB,EAASY,CAAG,EAAE,OAC5B,CAAC,CAAE,MAAAH,EAAO,OAAAC,EAAQ,SAAUQ,CAAe,IACzC,EACET,IAAUO,GACVE,EAAe,OAASL,EAAS,MACjCM,EAAUD,EAAe,QAASL,EAAS,OAAO,IACjDE,IAAiB,MAAcL,IAAWK,GAEjD,EACIE,EAAQ,OACVjB,EAASY,CAAG,EAAIK,EAEhB,OAAOjB,EAASY,CAAG,CAEvB,CACF,CAAC,CACH,EAEMQ,EAAY,CAChBf,EACAC,EACAC,EAA2B,IAAM,CAAC,IAC/B,CAKHO,EAAiBT,EADf,OAAOC,GAAkB,WAAaA,EAAgBC,EAFtD,OAAOD,GAAkB,WAAa,MAAgBA,CAGL,CACrD,EAEMe,EAAkB,CAAChB,EAAiBI,IACxCK,EAAiBT,EAAS,KAAMI,CAAK,EAEjCa,EAAYC,GAAqB,CACrC,IAAMX,EAAMY,EAAiBD,EAAE,GAAG,EAiBlC,GAfI,CAACxB,EAASwB,CAAC,GAIXE,GAAab,IAAQc,IAIzBvB,EAAYwB,EAAgBJ,CAAC,EAGzB,CADeK,EAAchB,CAAG,GACjB,CAACX,EAAS,IAAIW,CAAG,GAClCX,EAAS,IAAIW,CAAG,EAGd,EAAEA,KAAOZ,IACX,OAGF,IAAM6B,EAAkB7B,EAASY,CAAG,EAAE,OACpC,CAAC,CAAE,MAAAH,EAAO,SAAU,CAAE,QAAAqB,EAAS,KAAAC,CAAK,CAAE,IAChCtB,IAAUP,EACL,GAGFiB,EAAUW,EAAS,MAAM,KAAK7B,CAAQ,CAAC,GAAK8B,IAAS5B,CAEhE,EAEM6B,EAAqCH,EAAgB,KACxDI,GAAWA,EAAO,SACrB,EAGID,EACFA,EAAc,OAAOT,CAAC,EAEtBM,EAAgB,QAAQ,CAAC,CAAE,OAAAnB,CAAO,IAAM,CACtCA,EAAOa,CAAC,CACV,CAAC,CAEL,EAEMW,EAAWX,GAAqB,CACpC,IAAMX,EAAMY,EAAiBD,EAAE,GAAG,EAE9BA,EAAE,KAAOA,EAAE,IAAI,YAAY,IAAM,OACnCtB,EAAS,MAAM,EAEfA,EAAS,OAAOW,CAAG,CAEvB,EAEMuB,EAAenB,GAA8B,CACjD,OAAO,KAAKhB,CAAQ,EAAE,QAASY,GAAQ,CACrC,IAAMwB,EAAYxB,EACZK,EAAUjB,EAASoC,CAAS,EAAE,OAClC,CAAC,CAAE,MAAA3B,CAAM,IAAeA,IAAUO,CACpC,EACIC,EAAQ,OACVjB,EAASoC,CAAS,EAAInB,EAEtB,OAAOjB,EAASoC,CAAS,CAE7B,CAAC,CACH,EAEMC,EAAY5B,GAAwB,CACxCP,EAAcO,CAChB,EAEM6B,EAAY,IAAY,CAC5BtC,EAAW,CAAC,EACZC,EAAS,MAAM,CACjB,EAEMsC,EAAQ,IAAY,CACxBtC,EAAS,MAAM,CACjB,EAEMuC,EAAU,IAAY,CAG1B,GAFAvC,EAAS,MAAM,EACfD,EAAW,CAAC,EACRF,EAAK,CACP,IAAM2C,EAAY7C,EAAkB,IAAIE,CAAG,EACvC2C,IACF3C,EAAI,oBAAoB,UAAW2C,EAAU,QAAQ,EACrD3C,EAAI,oBAAoB,QAAS2C,EAAU,OAAO,EAClDA,EAAU,OAAO,oBAAoB,QAASA,EAAU,KAAK,EAC7D7C,EAAkB,OAAOE,CAAG,EAEhC,CACF,EAEM4C,EAAO5C,EAAI,aAAe,OAEhC,OAAAF,EAAkB,IAAIE,EAAK,CAAE,SAAAwB,EAAU,QAAAY,EAAS,MAAAK,EAAO,OAAQG,CAAI,CAAC,EACpE5C,EAAI,iBAAiB,UAAWwB,CAAQ,EACxCxB,EAAI,iBAAiB,QAASoC,CAAO,EACrCQ,EAAI,iBAAiB,QAASH,CAAK,EAsE5B,CACL,KAAMnC,EACN,OAAQgB,EACR,aAAcC,EACd,YAAAc,EACA,SAAAE,EACA,UAAAC,EACA,SA3Ee,IAAMpC,EA4ErB,QAAAsC,EACA,QA3Ec,CAACnC,EAAiBsC,IAA0C,CAC1E,IAAMlC,EAAQkC,GAAS,OAASzC,EAGhC,OAFgBS,EAAUN,CAAO,EAElB,KAAK,CAAC,CAAE,IAAAO,EAAK,SAAAC,CAAS,IAAM,CACzC,IAAM+B,EAAc5C,EAASY,CAAG,EAChC,OAAKgC,EAEEA,EAAY,KAChBC,GACCA,EAAE,QAAUpC,GACZoC,EAAE,SAAS,OAAShC,EAAS,MAC7BM,EAAU0B,EAAE,SAAS,QAAShC,EAAS,OAAO,CAClD,EAPyB,EAQ3B,CAAC,CACH,EA6DE,aA3DoB8B,GAA2C,CAC/D,IAAMlC,EAAQkC,GAAS,OAASzC,EAC1B4C,EAAO,IAAI,IAEjB,cAAO,OAAO9C,CAAQ,EAAE,QAAS+C,GAAgB,CAC/CA,EAAY,QAAS9B,GAAY,CAC/B,GAAIA,EAAQ,QAAUR,EAAO,CAC3B,IAAMuC,EAAqB,CAAC,EACxB/B,EAAQ,SAAS,KAAOgC,EAAK,MAAMD,EAAS,KAAK,MAAM,EACvD/B,EAAQ,SAAS,KAAOgC,EAAK,KAAKD,EAAS,KAAK,KAAK,EACrD/B,EAAQ,SAAS,KAAOgC,EAAK,OAAOD,EAAS,KAAK,OAAO,EACzD/B,EAAQ,SAAS,KAAOgC,EAAK,MAAMD,EAAS,KAAK,KAAK,EAE1D,IAAME,EAAUjC,EAAQ,SAAS,QAAQ,KAAK,GAAG,GAAK,GAChDkC,EAAU,CAAC,GAAGH,EAAUE,CAAO,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,EAC3DC,GAASL,EAAK,IAAIK,CAAO,CAC/B,CACF,CAAC,CACH,CAAC,EAEM,MAAM,KAAKL,CAAI,CACxB,EAuCE,YArCkB,CAClBzC,EACAsC,IACiB,CACjB,IAAMlC,EAAQkC,GAAS,OAASzC,EAC1BkD,EAAUzC,EAAUN,CAAO,EAC3BgD,EAAuB,CAAC,EAE9B,OAAAD,EAAQ,QAAQ,CAAC,CAAE,IAAAxC,EAAK,SAAAC,CAAS,IAAM,CACrC,IAAM+B,EAAc5C,EAASY,CAAG,EAC3BgC,GAELA,EAAY,QAASC,GAAM,CAEvBA,EAAE,QAAUpC,GACZoC,EAAE,SAAS,OAAShC,EAAS,MAC7BM,EAAU0B,EAAE,SAAS,QAAShC,EAAS,OAAO,GAE9CwC,EAAO,KAAKR,EAAE,MAAM,CAExB,CAAC,CACH,CAAC,EAEMQ,CACT,CAcA,CACF,CC7SA,GAAM,CACJ,KAAAC,EACA,OAAAC,EACA,aAAAC,EACA,SAAAC,GACA,SAAAC,GACA,YAAAC,GACA,UAAAC,GACA,QAAAC,GACA,QAAAC,GACA,aAAAC,GACA,YAAAC,EACF,EAAIC,EAAe,QAAQ,EAEdC,GAAUZ,EACVa,GAAYZ,EACZa,GAAkBZ,EAgB/B,IAAOa,GAAQC","names":["DEFAULT_SCOPE","MODS","MODIFIERS","SPECIAL","CAPS_LOCK_KEY","getKeyIdentifier","key","SPECIAL","MODIFIER_KEYS","isModifierKey","updateModifiers","modifiers","MODS","getMods","keys","acc","key","MODIFIERS","SPECIAL","getCombinations","keysStr","getKeyMap","keyCmd","getKeyIdentifier","isFirefox","isEditable","el","isEqArray","arr1","arr2","i","defaultFilter","isEditable","documentListeners","createKeybuddy","doc","filterFn","handlers","downKeys","activeScope","modifiers","bindKey","keysStr","scopeOrMethod","methodOrNull","skipOther","scope","method","getKeyMap","key","shortcut","unbindKeyProcess","deleteMethod","deleteScope","handler","methodShortcut","isEqArray","unbindKey","unsafeUnbindKey","dispatch","e","getKeyIdentifier","isFirefox","CAPS_LOCK_KEY","updateModifiers","isModifierKey","currentHandlers","special","mods","primaryAction","action","cleanUp","unbindScope","keyString","setScope","unbindAll","reset","destroy","listeners","win","options","keyHandlers","h","keys","handlerList","modParts","MODS","keyPart","fullKey","keyMaps","result","bind","unbind","unsafeUnbind","getScope","setScope","unbindScope","unbindAll","destroy","isBound","getBoundKeys","getHandlers","createKeybuddy","bindKey","unbindKey","unsafeUnbindKey","src_default","bind"]}
package/package.json CHANGED
@@ -1,19 +1,15 @@
1
1
  {
2
2
  "name": "keybuddy",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
+ "type": "module",
4
5
  "main": "./index.cjs",
5
6
  "module": "./index.js",
6
7
  "types": "./index.d.ts",
7
8
  "exports": {
8
9
  ".": {
9
- "import": {
10
- "types": "./index.d.ts",
11
- "default": "./index.js"
12
- },
13
- "require": {
14
- "types": "./index.d.ts",
15
- "default": "./index.cjs"
16
- }
10
+ "types": "./index.d.ts",
11
+ "import": "./index.js",
12
+ "require": "./index.cjs"
17
13
  }
18
14
  },
19
15
  "sideEffects": false,
package/index.mjs DELETED
@@ -1,3 +0,0 @@
1
- /* keybuddy - Modern keyboard shortcuts library */
2
- var g="all",s={SHIFT:1,ALT:2,CTRL:4,META:8},A={"\u21E7":s.SHIFT,shift:s.SHIFT,"\u2325":s.ALT,alt:s.ALT,option:s.ALT,"\u2303":s.CTRL,ctrl:s.CTRL,control:s.CTRL,"\u2318":s.META,cmd:s.META,command:s.META},m={backspace:"Backspace",tab:"Tab",clear:"Clear",enter:"Enter",return:"Enter",esc:"Escape",escape:"Escape",space:" ",left:"ArrowLeft",up:"ArrowUp",right:"ArrowRight",down:"ArrowDown",del:"Delete",delete:"Delete",home:"Home",end:"End",pageup:"PageUp",pagedown:"PageDown",comma:",",".":".","/":"/","`":"`","-":"-","=":"=",";":";","'":"'","[":"[","]":"]","\\":"\\",Meta:"Meta",MetaLeft:"Meta",MetaRight:"Meta",OS:"Meta",ContextMenu:"Meta",ArrowLeft:"ArrowLeft",ArrowUp:"ArrowUp",ArrowRight:"ArrowRight",ArrowDown:"ArrowDown",Backspace:"Backspace",Tab:"Tab",Clear:"Clear",Enter:"Enter",Escape:"Escape",Delete:"Delete",Home:"Home",End:"End",PageUp:"PageUp",PageDown:"PageDown"},C="CapsLock";var E=t=>m[t]||t.toUpperCase(),x=t=>{let d=0;return t.shiftKey&&(d|=s.SHIFT),t.altKey&&(d|=s.ALT),t.ctrlKey&&(d|=s.CTRL),t.metaKey&&(d|=s.META),d};var j=t=>t.reduce((d,e)=>(e in A?d.mods|=A[e]:d.special.push(m[e]||e.toUpperCase()),d),{mods:0,special:[]}),q=t=>{let e=t.replace(/\s/g,"").split(",");return e[e.length-1]===""&&(e[e.length-2]+=","),e},K=t=>q(t).map(e=>{let f=e.split("+"),u=f[f.length-1];return{key:E(u),shortcut:j(f)}});var P=typeof navigator<"u"&&navigator.userAgent.includes("Firefox"),D=t=>t.isContentEditable||t.tagName==="INPUT"||t.tagName==="SELECT"||t.tagName==="TEXTAREA",b=(t,d)=>{if(t.length!==d.length)return!1;for(let e=0;e<t.length;e++)if(t[e]!==d[e])return!1;return!0};var V=t=>t&&!D(t.target),w=new WeakMap;function I(t,d=V){let e={},f=new Set,u="all",h=0,U=(r,n,c=()=>{},{skipOther:a}={skipOther:!1})=>{let o=typeof n=="function"?"all":n,i=typeof n=="function"?n:c;K(r).forEach(({key:l,shortcut:p})=>{e[l]||(e[l]=[]),e[l].push({scope:o,method:i,shortcut:p,skipOther:a})})},v=(r,n,c="all")=>{K(r).forEach(({key:a,shortcut:o})=>{let i=e[a];if(Array.isArray(i)){let l=e[a].filter(({scope:p,method:y,shortcut:S})=>!(p===c&&S.mods===o.mods&&b(S.special,o.special)&&(n===null||y===n)));l.length?e[a]=l:delete e[a]}})},O=(r,n,c=()=>{})=>{v(r,typeof n=="function"?n:c,typeof n=="function"?"all":n)},R=(r,n)=>v(r,null,n),T=r=>{let n=E(r.key);if(!d(r)||P&&n===C||(h=x(r),!(n==="SHIFT"||n==="ALT"||n==="CTRL"||n==="META")&&!f.has(n)&&f.add(n),!(n in e)))return;let a=e[n].filter(({scope:i,shortcut:{special:l,mods:p}})=>i!==u?!1:b(l,Array.from(f))&&p===h),o=a.find(i=>i.skipOther);o?o.method(r):a.forEach(({method:i})=>{i(r)})},L=r=>{let n=E(r.key);r.key&&r.key.toLowerCase()==="meta"?f.clear():f.delete(n)},N=r=>{Object.keys(e).forEach(n=>{let c=n,a=e[c].filter(({scope:o})=>o!==r);a.length?e[c]=a:delete e[c]})},B=r=>{u=r},_=()=>{e={},f.clear()},k=()=>{f.clear()},M=()=>{if(f.clear(),e={},t){let r=w.get(t);r&&(t.removeEventListener("keydown",r.dispatch),t.removeEventListener("keyup",r.cleanUp),r.window.removeEventListener("focus",r.reset),w.delete(t))}};M();let H=t.defaultView||window;return w.set(t,{dispatch:T,cleanUp:L,reset:k,window:H}),t.addEventListener("keydown",T),t.addEventListener("keyup",L),H.addEventListener("focus",k),{bind:U,unbind:O,unsafeUnbind:R,unbindScope:N,setScope:B,unbindAll:_,getScope:()=>u,destroy:M,isBound:(r,n)=>{let c=n?.scope||u;return K(r).some(({key:o,shortcut:i})=>{let l=e[o];return l?l.some(p=>p.scope===c&&p.shortcut.mods===i.mods&&b(p.shortcut.special,i.special)):!1})},getBoundKeys:r=>{let n=r?.scope||u,c=new Set;return Object.values(e).forEach(a=>{a.forEach(o=>{if(o.scope===n){let i=[];o.shortcut.mods&s.CTRL&&i.push("ctrl"),o.shortcut.mods&s.ALT&&i.push("alt"),o.shortcut.mods&s.SHIFT&&i.push("shift"),o.shortcut.mods&s.META&&i.push("cmd");let l=o.shortcut.special.join("+")||"",p=[...i,l].filter(Boolean).join("+");p&&c.add(p)}})}),Array.from(c)},getHandlers:(r,n)=>{let c=n?.scope||u,a=K(r),o=[];return a.forEach(({key:i,shortcut:l})=>{let p=e[i];p&&p.forEach(y=>{y.scope===c&&y.shortcut.mods===l.mods&&b(y.shortcut.special,l.special)&&o.push(y.method)})}),o}}}var{bind:F,unbind:W,unsafeUnbind:$,getScope:Ke,setScope:be,unbindScope:he,unbindAll:Se,destroy:Ae,isBound:we,getBoundKeys:ve,getHandlers:Te}=I(document),Le=F,ke=W,Me=$;var He=F;export{g as DEFAULT_SCOPE,s as MODS,m as SPECIAL,Le as bindKey,I as createKeybuddy,He as default,Ae as destroy,ve as getBoundKeys,Te as getHandlers,Ke as getScope,we as isBound,be as setScope,Se as unbindAll,ke as unbindKey,he as unbindScope,Me as unsafeUnbindKey};
3
- //# sourceMappingURL=index.mjs.map
package/index.mjs.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/helpers/keyboard.ts","../src/helpers/keymap.ts","../src/helpers/utils.ts","../src/keybuddy.ts","../src/index.ts"],"sourcesContent":["export const DEFAULT_SCOPE = 'all';\n\ndeclare const KeyStringBrand: unique symbol;\n\nexport type KeyString = string & { readonly [KeyStringBrand]: true };\n\nexport const MODS = {\n SHIFT: 0b0001, // 1\n ALT: 0b0010, // 2\n CTRL: 0b0100, // 4\n META: 0b1000, // 8\n} as const;\n\n// Map string modifier names to bitwise flags for parsing\nexport type ModifierNames = {\n '⇧': number;\n shift: number;\n '⌥': number;\n alt: number;\n option: number;\n '⌃': number;\n ctrl: number;\n control: number;\n '⌘': number;\n cmd: number;\n command: number;\n};\n\nexport const MODIFIERS: ModifierNames = {\n '⇧': MODS.SHIFT,\n shift: MODS.SHIFT,\n '⌥': MODS.ALT,\n alt: MODS.ALT,\n option: MODS.ALT,\n '⌃': MODS.CTRL,\n ctrl: MODS.CTRL,\n control: MODS.CTRL,\n '⌘': MODS.META,\n cmd: MODS.META,\n command: MODS.META,\n};\n\nexport const SPECIAL: { [key: string]: string } = {\n backspace: 'Backspace',\n tab: 'Tab',\n clear: 'Clear',\n enter: 'Enter',\n return: 'Enter',\n esc: 'Escape',\n escape: 'Escape',\n space: ' ',\n left: 'ArrowLeft',\n up: 'ArrowUp',\n right: 'ArrowRight',\n down: 'ArrowDown',\n del: 'Delete',\n delete: 'Delete',\n home: 'Home',\n end: 'End',\n pageup: 'PageUp',\n pagedown: 'PageDown',\n comma: ',',\n '.': '.',\n '/': '/',\n '`': '`',\n '-': '-',\n '=': '=',\n ';': ';',\n \"'\": \"'\",\n '[': '[',\n ']': ']',\n '\\\\': '\\\\',\n // Normalize Meta key variants\n Meta: 'Meta',\n MetaLeft: 'Meta',\n MetaRight: 'Meta',\n OS: 'Meta', // Some browsers use OS instead of Meta\n ContextMenu: 'Meta', // Right-click context menu key sometimes acts as Meta\n // Add identity mappings for already-normalized keys\n ArrowLeft: 'ArrowLeft',\n ArrowUp: 'ArrowUp',\n ArrowRight: 'ArrowRight',\n ArrowDown: 'ArrowDown',\n Backspace: 'Backspace',\n Tab: 'Tab',\n Clear: 'Clear',\n Enter: 'Enter',\n Escape: 'Escape',\n Delete: 'Delete',\n Home: 'Home',\n End: 'End',\n PageUp: 'PageUp',\n PageDown: 'PageDown',\n};\n\nexport const CAPS_LOCK_KEY = 'CapsLock';\n","import { KeyString, MODS, SPECIAL } from '../constants';\n\nexport const getKeyIdentifier = (key: string): KeyString => {\n return (SPECIAL[key] || key.toUpperCase()) as KeyString;\n};\n\nexport const updateModifiers = (e: KeyboardEvent): number => {\n let modifiers = 0;\n if (e.shiftKey) modifiers |= MODS.SHIFT;\n if (e.altKey) modifiers |= MODS.ALT;\n if (e.ctrlKey) modifiers |= MODS.CTRL;\n if (e.metaKey) modifiers |= MODS.META;\n return modifiers;\n};\n","import { KeyString, MODIFIERS, ModifierNames, SPECIAL } from '../constants';\nimport { getKeyIdentifier } from './keyboard';\n\nexport interface ParsedShortcut {\n mods: number; // Bitwise flag for modifiers\n special: string[];\n}\nexport interface KeyMap {\n key: KeyString;\n shortcut: ParsedShortcut;\n}\n\nconst getMods = (keys: string[]): ParsedShortcut =>\n keys.reduce(\n (acc, key) => {\n if (key in MODIFIERS) {\n acc.mods |= MODIFIERS[key as keyof ModifierNames];\n } else {\n acc.special.push(SPECIAL[key] || key.toUpperCase());\n }\n return acc;\n },\n {\n mods: 0, // Start with no modifiers\n special: [],\n } as ParsedShortcut,\n );\n\nconst getCombinations = (keysStr: string): string[] => {\n const cleanKeys = keysStr.replace(/\\s/g, '');\n const keys = cleanKeys.split(',');\n if (keys[keys.length - 1] === '') {\n keys[keys.length - 2] += ',';\n }\n\n return keys;\n};\n\nexport const getKeyMap = (keysStr: string): KeyMap[] => {\n const keymap = getCombinations(keysStr);\n return keymap.map((keyCmd) => {\n const keys = keyCmd.split('+');\n const key = keys[keys.length - 1];\n const keyIdentifier = getKeyIdentifier(key);\n\n return {\n key: keyIdentifier,\n shortcut: getMods(keys),\n };\n });\n};\n","export const invariant = (\n condition: boolean,\n message: string,\n ...args: unknown[]\n) => {\n if (\n typeof process !== 'undefined' &&\n process.env &&\n process.env.NODE_ENV === 'development' &&\n !condition\n ) {\n throw new Error(\n `Invariant failed: ${message}${args.length ? ` ${JSON.stringify(args)}` : ''}`,\n );\n }\n};\n\nexport const isFirefox =\n typeof navigator !== 'undefined' && navigator.userAgent.includes('Firefox');\n\nexport const isEditable = (el: HTMLElement): boolean =>\n el.isContentEditable ||\n el.tagName === 'INPUT' ||\n el.tagName === 'SELECT' ||\n el.tagName === 'TEXTAREA';\n\nexport const isEqArray = (\n arr1: (string | number)[],\n arr2: (string | number)[],\n): boolean => {\n if (arr1.length !== arr2.length) return false;\n\n for (let i = 0; i < arr1.length; i++) {\n if (arr1[i] !== arr2[i]) return false;\n }\n\n return true;\n};\n","import { CAPS_LOCK_KEY, DEFAULT_SCOPE, KeyString, MODS } from './constants';\nimport { getKeyIdentifier, updateModifiers } from './helpers/keyboard';\nimport { getKeyMap, ParsedShortcut } from './helpers/keymap';\nimport { invariant, isEditable, isEqArray, isFirefox } from './helpers/utils';\n\ntype KeyHandler = (e: KeyboardEvent) => void;\ntype FilterFn = (el: KeyboardEvent) => boolean;\n\ninterface Handler {\n scope: string;\n method: KeyHandler;\n shortcut: ParsedShortcut;\n skipOther: boolean;\n}\n\nconst defaultFilter = (e: KeyboardEvent): boolean =>\n e && !isEditable(e.target as HTMLElement);\n\nconst documentListeners = new WeakMap<\n Document,\n {\n dispatch: (e: KeyboardEvent) => void;\n cleanUp: (e: KeyboardEvent) => void;\n reset: () => void;\n window: Window & typeof globalThis;\n }\n>();\n\nexport function createKeybuddy(\n doc: Document,\n filterFn: FilterFn = defaultFilter,\n) {\n let handlers: { [key: KeyString]: Handler[] } = {};\n const downKeys: Set<KeyString> = new Set();\n let activeScope = DEFAULT_SCOPE;\n\n let modifiers = 0;\n\n const bindKey = (\n keysStr: string,\n scopeOrMethod: string | KeyHandler,\n methodOrNull: KeyHandler = () => {},\n {\n skipOther,\n }: {\n skipOther: boolean;\n } = {\n skipOther: false,\n },\n ): void => {\n const scope: string =\n typeof scopeOrMethod === 'function' ? DEFAULT_SCOPE : scopeOrMethod;\n const method: KeyHandler =\n typeof scopeOrMethod === 'function' ? scopeOrMethod : methodOrNull;\n\n getKeyMap(keysStr).forEach(({ key, shortcut }) => {\n if (!handlers[key]) {\n handlers[key] = [];\n }\n const handler = handlers[key];\n if (process.env.NODE_ENV === 'development') {\n if (skipOther) {\n const action = handler.find((i) => i.skipOther);\n invariant(\n !action,\n \"Conflicting 'skipOther' property with action\",\n action,\n );\n }\n }\n\n handler.push({\n scope,\n method,\n shortcut,\n skipOther,\n });\n });\n };\n\n const unbindKeyProcess = (\n keysStr: string,\n deleteMethod: null | KeyHandler,\n deleteScope: string = DEFAULT_SCOPE,\n ): void => {\n getKeyMap(keysStr).forEach(({ key, shortcut }) => {\n const handler = handlers[key];\n if (Array.isArray(handler)) {\n const handler = handlers[key].filter(\n ({ scope, method, shortcut: methodShortcut }: Handler) =>\n !(\n scope === deleteScope &&\n methodShortcut.mods === shortcut.mods &&\n isEqArray(methodShortcut.special, shortcut.special) &&\n (deleteMethod === null ? true : method === deleteMethod)\n ),\n );\n if (handler.length) {\n handlers[key] = handler;\n } else {\n delete handlers[key];\n }\n }\n });\n };\n\n const unbindKey = (\n keysStr: string,\n scopeOrMethod: string | KeyHandler,\n methodOrNull: KeyHandler = () => {},\n ) => {\n const deleteScope: string =\n typeof scopeOrMethod === 'function' ? DEFAULT_SCOPE : scopeOrMethod;\n const deleteMethod: KeyHandler =\n typeof scopeOrMethod === 'function' ? scopeOrMethod : methodOrNull;\n unbindKeyProcess(keysStr, deleteMethod, deleteScope);\n };\n\n const unsafeUnbindKey = (keysStr: string, scope?: string) =>\n unbindKeyProcess(keysStr, null, scope);\n\n const dispatch = (e: KeyboardEvent) => {\n const key = getKeyIdentifier(e.key);\n\n if (!filterFn(e)) {\n return;\n }\n\n if (isFirefox && key === CAPS_LOCK_KEY) {\n return;\n }\n\n modifiers = updateModifiers(e);\n\n const isModifierKey =\n key === ('SHIFT' as KeyString) ||\n key === ('ALT' as KeyString) ||\n key === ('CTRL' as KeyString) ||\n key === ('META' as KeyString);\n if (!isModifierKey && !downKeys.has(key)) {\n downKeys.add(key);\n }\n\n if (!(key in handlers)) {\n return;\n }\n\n const currentHandlers = handlers[key].filter(\n ({ scope, shortcut: { special, mods } }) => {\n if (scope !== activeScope) {\n return false;\n }\n\n return isEqArray(special, Array.from(downKeys)) && mods === modifiers;\n },\n );\n\n const primaryAction: Handler | undefined = currentHandlers.find(\n (action) => action.skipOther,\n );\n if (primaryAction) {\n primaryAction.method(e);\n } else {\n currentHandlers.forEach(({ method }) => {\n method(e);\n });\n }\n };\n\n const cleanUp = (e: KeyboardEvent) => {\n const key = getKeyIdentifier(e.key);\n\n if (e.key && e.key.toLowerCase() === 'meta') {\n downKeys.clear();\n } else {\n downKeys.delete(key);\n }\n };\n\n const unbindScope = (deleteScope: string): void => {\n Object.keys(handlers).forEach((key) => {\n const keyString = key as KeyString;\n const handler = handlers[keyString].filter(\n ({ scope }: Handler) => scope !== deleteScope,\n );\n if (handler.length) {\n handlers[keyString] = handler;\n } else {\n delete handlers[keyString];\n }\n });\n };\n\n const setScope = (scope: string): void => {\n activeScope = scope;\n };\n\n const unbindAll = (): void => {\n handlers = {};\n downKeys.clear();\n };\n\n const reset = (): void => {\n downKeys.clear();\n };\n\n const destroy = (): void => {\n downKeys.clear();\n handlers = {};\n if (doc) {\n const listeners = documentListeners.get(doc);\n if (listeners) {\n doc.removeEventListener('keydown', listeners.dispatch);\n doc.removeEventListener('keyup', listeners.cleanUp);\n listeners.window.removeEventListener('focus', listeners.reset);\n documentListeners.delete(doc);\n }\n }\n };\n\n destroy();\n\n const win = (doc.defaultView || window) as Window & typeof globalThis;\n\n documentListeners.set(doc, { dispatch, cleanUp, reset, window: win });\n doc.addEventListener('keydown', dispatch);\n doc.addEventListener('keyup', cleanUp);\n win.addEventListener('focus', reset);\n\n const getScope = () => activeScope;\n\n const isBound = (keysStr: string, options?: { scope?: string }): boolean => {\n const scope = options?.scope || activeScope;\n const keyMaps = getKeyMap(keysStr);\n\n return keyMaps.some(({ key, shortcut }) => {\n const keyHandlers = handlers[key];\n if (!keyHandlers) return false;\n\n return keyHandlers.some(\n (h) =>\n h.scope === scope &&\n h.shortcut.mods === shortcut.mods &&\n isEqArray(h.shortcut.special, shortcut.special),\n );\n });\n };\n\n const getBoundKeys = (options?: { scope?: string }): string[] => {\n const scope = options?.scope || activeScope;\n const keys = new Set<string>();\n\n Object.values(handlers).forEach((handlerList) => {\n handlerList.forEach((handler) => {\n if (handler.scope === scope) {\n const modParts: string[] = [];\n if (handler.shortcut.mods & MODS.CTRL) modParts.push('ctrl');\n if (handler.shortcut.mods & MODS.ALT) modParts.push('alt');\n if (handler.shortcut.mods & MODS.SHIFT) modParts.push('shift');\n if (handler.shortcut.mods & MODS.META) modParts.push('cmd');\n\n const keyPart = handler.shortcut.special.join('+') || '';\n const fullKey = [...modParts, keyPart].filter(Boolean).join('+');\n if (fullKey) keys.add(fullKey);\n }\n });\n });\n\n return Array.from(keys);\n };\n\n const getHandlers = (\n keysStr: string,\n options?: { scope?: string },\n ): KeyHandler[] => {\n const scope = options?.scope || activeScope;\n const keyMaps = getKeyMap(keysStr);\n const result: KeyHandler[] = [];\n\n keyMaps.forEach(({ key, shortcut }) => {\n const keyHandlers = handlers[key];\n if (!keyHandlers) return;\n\n keyHandlers.forEach((h) => {\n if (\n h.scope === scope &&\n h.shortcut.mods === shortcut.mods &&\n isEqArray(h.shortcut.special, shortcut.special)\n ) {\n result.push(h.method);\n }\n });\n });\n\n return result;\n };\n\n return {\n bind: bindKey,\n unbind: unbindKey,\n unsafeUnbind: unsafeUnbindKey,\n unbindScope,\n setScope,\n unbindAll,\n getScope,\n destroy,\n isBound,\n getBoundKeys,\n getHandlers,\n };\n}\n","import { DEFAULT_SCOPE } from './constants';\nimport { createKeybuddy } from './keybuddy';\n\nexport { createKeybuddy };\n\nconst {\n bind,\n unbind,\n unsafeUnbind,\n getScope,\n setScope,\n unbindScope,\n unbindAll,\n destroy,\n isBound,\n getBoundKeys,\n getHandlers,\n} = createKeybuddy(document);\n\nexport const bindKey = bind;\nexport const unbindKey = unbind;\nexport const unsafeUnbindKey = unsafeUnbind;\n\nexport {\n setScope,\n unbindScope,\n unbindAll,\n getScope,\n destroy,\n isBound,\n getBoundKeys,\n getHandlers,\n DEFAULT_SCOPE,\n};\nexport type { KeyString } from './constants';\nexport { MODS, SPECIAL } from './constants';\n\nexport default bind;\n"],"mappings":"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","names":["DEFAULT_SCOPE","MODS","MODIFIERS","SPECIAL","CAPS_LOCK_KEY","getKeyIdentifier","key","SPECIAL","updateModifiers","e","modifiers","MODS","getMods","keys","acc","key","MODIFIERS","SPECIAL","getCombinations","keysStr","getKeyMap","keyCmd","getKeyIdentifier","isFirefox","isEditable","el","isEqArray","arr1","arr2","i","defaultFilter","e","isEditable","documentListeners","createKeybuddy","doc","filterFn","handlers","downKeys","activeScope","modifiers","bindKey","keysStr","scopeOrMethod","methodOrNull","skipOther","scope","method","getKeyMap","key","shortcut","unbindKeyProcess","deleteMethod","deleteScope","handler","methodShortcut","isEqArray","unbindKey","unsafeUnbindKey","dispatch","getKeyIdentifier","isFirefox","CAPS_LOCK_KEY","updateModifiers","currentHandlers","special","mods","primaryAction","action","cleanUp","unbindScope","keyString","setScope","unbindAll","reset","destroy","listeners","win","options","keyHandlers","h","keys","handlerList","modParts","MODS","keyPart","fullKey","keyMaps","result","bind","unbind","unsafeUnbind","getScope","setScope","unbindScope","unbindAll","destroy","isBound","getBoundKeys","getHandlers","createKeybuddy","bindKey","unbindKey","unsafeUnbindKey","src_default","bind"]}
File without changes