@peter.naydenov/shortcuts 3.4.0 → 3.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/Changelog.md +11 -0
  2. package/README.md +38 -9
  3. package/dist/main.d.ts +120 -0
  4. package/dist/methods/_normalizeWithPlugins.d.ts +2 -0
  5. package/dist/methods/_readShortcutWithPlugins.d.ts +2 -0
  6. package/dist/methods/_systemAction.d.ts +2 -0
  7. package/dist/methods/changeContext.d.ts +2 -0
  8. package/dist/methods/index.d.ts +17 -0
  9. package/dist/methods/listShortcuts.d.ts +17 -0
  10. package/dist/methods/load.d.ts +2 -0
  11. package/dist/methods/unload.d.ts +2 -0
  12. package/dist/plugins/click/_findTarget.d.ts +2 -0
  13. package/dist/plugins/click/_listenDOM.d.ts +5 -0
  14. package/dist/plugins/click/_normalizeShortcutName.d.ts +2 -0
  15. package/dist/plugins/click/_readClickEvent.d.ts +2 -0
  16. package/dist/plugins/click/_registerShortcutEvents.d.ts +2 -0
  17. package/dist/plugins/click/index.d.ts +15 -0
  18. package/dist/plugins/form/_defaults.d.ts +5 -0
  19. package/dist/plugins/form/_listenDOM.d.ts +5 -0
  20. package/dist/plugins/form/_normalizeShortcutName.d.ts +2 -0
  21. package/dist/plugins/form/_registerShortcutEvents.d.ts +2 -0
  22. package/dist/plugins/form/index.d.ts +10 -0
  23. package/dist/plugins/key/_listenDOM.d.ts +5 -0
  24. package/dist/plugins/key/_normalizeShortcutName.d.ts +2 -0
  25. package/dist/plugins/key/_readKeyEvent.d.ts +2 -0
  26. package/dist/plugins/key/_registerShortcutEvents.d.ts +2 -0
  27. package/dist/plugins/key/_specialChars.d.ts +32 -0
  28. package/dist/plugins/key/index.d.ts +15 -0
  29. package/dist/shortcuts.cjs +1 -1
  30. package/dist/shortcuts.esm.mjs +1 -1
  31. package/dist/shortcuts.umd.js +1 -1
  32. package/package.json +9 -5
  33. package/src/main.js +74 -20
  34. package/src/methods/changeContext.js +2 -1
  35. package/src/methods/load.js +4 -3
  36. package/src/methods/unload.js +3 -3
  37. package/src/plugins/click/_listenDOM.js +1 -1
  38. package/src/plugins/click/index.js +10 -0
  39. package/src/plugins/form/index.js +8 -13
  40. package/src/plugins/key/index.js +10 -0
  41. package/test/01-general.test.js +64 -5
  42. package/test/02-key.test.js +136 -38
  43. package/test/03-click.test.js +88 -56
  44. package/test/04-form.test.js +52 -9
  45. package/tsconfig.json +23 -0
package/Changelog.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
 
4
4
 
5
+ ### 3.5.1 ( 2025-10-20 )
6
+ - [x] Update in package.json. Field 'types' was added;
7
+
8
+
9
+
10
+ ### 3.5.0 ( 2025-10-19)
11
+ - [x] Featire: New method 'listPlugins' to get list of enabled plugins;
12
+ - [x] Upgrade: Improvment of type definitions. New d.ts files were added;
13
+
14
+
15
+
5
16
  ### 3.4.0 ( 2025-10-18)
6
17
  - [x] Feature: New method 'reset' to reset the library instance;
7
18
  - [x] Refactoring: Added 'active' state property to 'click' plugin state management;
package/README.md CHANGED
@@ -6,14 +6,15 @@
6
6
  ![npm bundle size](https://img.shields.io/bundlephobia/minzip/%40peter.naydenov%2Fshortcuts)
7
7
 
8
8
 
9
-
10
- Describe all page activities as list of shortcuts wrapped in contexts. Switch among available contexts.
11
- Library has a plugin system to extend the possible `shortcut names`/`event coverage`. Plugins role is to convert DOM events to shortcut strings, then the core part will trigger the action functions related to the shortcut. At the moment we have 3 plugins:
12
- - `key` - converts keyboard events to shortcut names;
13
- - `click` - converts mouse events to shortcut names;
14
- - `form` - watches for form elements changes;
15
9
 
16
- Planned work on the plugins for `scroll`, `drag-drop`, etc...
10
+ A shortcut management library that wrappes shortcut definitions in a context and allows to switch between contexts. Shortcuts are events triggered by keyboard, mouse, and DOM events. The library has a plugin system that makes the library extensible.
11
+
12
+ Currently existing plugins:
13
+ - `key` - Converts keyboard events to shortcuts;
14
+ - `click` - Converts mouse events to shortcuts;
15
+ - `form` - Form element changes to shortcuts;
16
+
17
+ Planned work on plugins: `scroll`, `drag-drop`, etc.
17
18
 
18
19
 
19
20
 
@@ -49,9 +50,9 @@ Load a shortcut definition by calling `load` method.
49
50
 
50
51
  ```js
51
52
  // for es6 module projects:
52
- include { shortcuts, pluginKey, pluginClick } from '@peter.naydenov/shortcuts'
53
+ import { shortcuts, pluginKey, pluginClick, pluginForm } from '@peter.naydenov/shortcuts'
53
54
  // for commonjs projects:
54
- const { shortcuts, pluginKey, pluginClick } = require('@peter.naydenov/shortcuts')
55
+ const { shortcuts, pluginKey, pluginClick, pluginForm } = require('@peter.naydenov/shortcuts')
55
56
 
56
57
 
57
58
 
@@ -393,12 +394,14 @@ Description of the methods of shortcut instance:
393
394
  , emit : 'Trigger a shortcut or custom event programmatically.'
394
395
  , pause : 'Stop listening for shortcuts.'
395
396
  , resume : 'Resume listening for shortcuts.'
397
+ , listPlugins : "Return list of enabled plugins. Plugins are represented by plugin's prefixes."
396
398
  , listContexts : 'Return list of available contexts.'
397
399
  , listShortcuts : 'Return list of shortcuts per context.'
398
400
  , getNote : `Return a name of current note or null if note isn't set`
399
401
  , setNote : 'Set a note to current context.'
400
402
  , setDependencies : 'Set dependencies that will be available in action functions.'
401
403
  , getDependencies : 'Return a dependencies object.'
404
+ , reset : 'Reset shortcut instance.'
402
405
  ```
403
406
 
404
407
  ### How to 'pause' and 'resume'?
@@ -482,6 +485,32 @@ Plugin options are provided as a second argument during the plugin enabling. It'
482
485
 
483
486
 
484
487
 
488
+ ## TypeScript Support
489
+
490
+ The library includes TypeScript definitions. Install the package and TypeScript will automatically detect the types.
491
+
492
+ ```typescript
493
+ import { shortcuts, pluginKey, pluginClick, pluginForm } from '@peter.naydenov/shortcuts';
494
+
495
+ const short: ShortcutsAPI = shortcuts();
496
+ short.enablePlugin(pluginKey);
497
+ short.enablePlugin(pluginClick);
498
+ short.enablePlugin(pluginForm);
499
+
500
+ // Type-safe shortcut definitions
501
+ const shortcutDefinition = {
502
+ myContext: {
503
+ 'key:ctrl+s': () => console.log('Saved'),
504
+ 'click:left-1': (args: { target: HTMLElement }) => console.log('Clicked', args.target)
505
+ }
506
+ };
507
+
508
+ short.load(shortcutDefinition);
509
+ short.changeContext('myContext');
510
+ ```
511
+
512
+ The `ShortcutsAPI` interface provides full type safety for all methods and their parameters.
513
+
485
514
  ## Links
486
515
 
487
516
  - [History of changes](https://github.com/PeterNaydenov/shortcuts/blob/main/Changelog.md)
package/dist/main.d.ts ADDED
@@ -0,0 +1,120 @@
1
+ export type PluginAPI = {
2
+ /**
3
+ * - Get plugin prefix
4
+ */
5
+ getPrefix: () => string;
6
+ /**
7
+ * - Format shortcut name
8
+ */
9
+ shortcutName: (arg0: string) => string;
10
+ /**
11
+ * - Handle context change
12
+ */
13
+ contextChange: (arg0: string) => void;
14
+ /**
15
+ * - Mute the plugin
16
+ */
17
+ mute: () => void;
18
+ /**
19
+ * - Unmute the plugin
20
+ */
21
+ unmute: () => void;
22
+ /**
23
+ * - Destroy the plugin
24
+ */
25
+ destroy: () => void;
26
+ };
27
+ export type ShortcutsAPI = {
28
+ /**
29
+ * - Enable a plugin
30
+ */
31
+ enablePlugin: (arg0: Function, arg1: any) => void;
32
+ /**
33
+ * - Disable a plugin
34
+ */
35
+ disablePlugin: (arg0: string) => void;
36
+ /**
37
+ * - Mute a plugin
38
+ */
39
+ mutePlugin: (arg0: string) => number;
40
+ /**
41
+ * - Unmute a plugin
42
+ */
43
+ unmutePlugin: (arg0: string) => number;
44
+ /**
45
+ * - List enabled plugins
46
+ */
47
+ listPlugins: () => string[];
48
+ /**
49
+ * - Get current context name
50
+ */
51
+ getContext: () => string | null;
52
+ /**
53
+ * - Get current context note
54
+ */
55
+ getNote: () => string | null;
56
+ /**
57
+ * - Set current context note
58
+ */
59
+ setNote: (arg0: string | null) => void;
60
+ /**
61
+ * - Pause shortcuts in current context
62
+ */
63
+ pause: (arg0: string) => void;
64
+ /**
65
+ * - Resume shortcuts in current context
66
+ */
67
+ resume: (arg0: string) => void;
68
+ /**
69
+ * - Emit event for shortcut
70
+ */
71
+ emit: (arg0: string, ...args: any[]) => void;
72
+ /**
73
+ * - List all context names
74
+ */
75
+ listContexts: () => string[];
76
+ /**
77
+ * - Set external dependencies
78
+ */
79
+ setDependencies: (arg0: any) => void;
80
+ /**
81
+ * - Get external dependencies
82
+ */
83
+ getDependencies: () => any;
84
+ /**
85
+ * - Reset the library instance
86
+ */
87
+ reset: () => void;
88
+ /**
89
+ * - Change current context
90
+ */
91
+ changeContext: (arg0: string | boolean) => void;
92
+ /**
93
+ * - List shortcuts
94
+ */
95
+ listShortcuts: (arg0: string | null) => string[] | any[];
96
+ /**
97
+ * - Load shortcuts into contexts
98
+ */
99
+ load: (arg0: any) => void;
100
+ /**
101
+ * - Unload a context
102
+ */
103
+ unload: (arg0: string) => void;
104
+ };
105
+ /**
106
+ * @function shortcuts
107
+ * @description Create a shortcuts instance
108
+ * @param {Object} [options={}] - Configuration options
109
+ * @param {function} [options.onShortcut] - Function to log shortcut events
110
+ * @param {string} [options.errorEventName='@shortcuts-error'] - Name for error events
111
+ * @returns {ShortcutsAPI} The shortcuts API
112
+ */
113
+ declare function main(options?: {
114
+ onShortcut?: Function;
115
+ errorEventName?: string;
116
+ }): ShortcutsAPI;
117
+ import pluginKey from './plugins/key/index.js';
118
+ import pluginClick from './plugins/click/index.js';
119
+ import pluginForm from './plugins/form/index.js';
120
+ export { main as shortcuts, pluginKey, pluginClick, pluginForm };
@@ -0,0 +1,2 @@
1
+ export default _normalizeWithPlugins;
2
+ declare function _normalizeWithPlugins(dependencies: any, state: any): (_normalizeShortcutName: Function) => void;
@@ -0,0 +1,2 @@
1
+ export default _readShortcutWithPlugins;
2
+ declare function _readShortcutWithPlugins(dependencies: any, state: any): (shortcut: string) => string;
@@ -0,0 +1,2 @@
1
+ export default _systemAction;
2
+ declare function _systemAction(dependencies: any, state: any): (pluginName: string, fn: string, params?: any) => any;
@@ -0,0 +1,2 @@
1
+ export default changeContext;
2
+ declare function changeContext(dependencies: any, state: any): (contextName?: string) => void;
@@ -0,0 +1,17 @@
1
+ declare namespace _default {
2
+ export { _normalizeWithPlugins };
3
+ export { _readShortcutWithPlugins };
4
+ export { _systemAction };
5
+ export { changeContext };
6
+ export { listShortcuts };
7
+ export { load };
8
+ export { unload };
9
+ }
10
+ export default _default;
11
+ import _normalizeWithPlugins from './_normalizeWithPlugins.js';
12
+ import _readShortcutWithPlugins from './_readShortcutWithPlugins.js';
13
+ import _systemAction from './_systemAction.js';
14
+ import changeContext from './changeContext.js';
15
+ import listShortcuts from './listShortcuts.js';
16
+ import load from './load.js';
17
+ import unload from './unload.js';
@@ -0,0 +1,17 @@
1
+ export default listShortcuts;
2
+ export type contextShortcuts = {
3
+ /**
4
+ * - Context name
5
+ */
6
+ context: string;
7
+ /**
8
+ * - List of shortcuts in a context
9
+ */
10
+ shortcuts: string[];
11
+ };
12
+ /**
13
+ * @typedef {object} contextShortcuts
14
+ * @property {string} context - Context name
15
+ * @property {string[]} shortcuts - List of shortcuts in a context
16
+ */
17
+ declare function listShortcuts(dependencies: any, state: any): (contextName?: string) => string[] | contextShortcuts[];
@@ -0,0 +1,2 @@
1
+ export default load;
2
+ declare function load(dependencies: any, state: any): (shortcutsUpdate: any) => void;
@@ -0,0 +1,2 @@
1
+ export default unload;
2
+ declare function unload(dependencies: any, state: any): (contextName: string) => void;
@@ -0,0 +1,2 @@
1
+ export default _findTarget;
2
+ declare function _findTarget(dependencies: any, state: any, target: any): any;
@@ -0,0 +1,5 @@
1
+ export default _listenDOM;
2
+ declare function _listenDOM(dependencies: any, state: any): {
3
+ start: () => void;
4
+ stop: () => void;
5
+ };
@@ -0,0 +1,2 @@
1
+ export default _normalizeShortcutName;
2
+ declare function _normalizeShortcutName(name: any): any;
@@ -0,0 +1,2 @@
1
+ export default _readClickEvent;
2
+ declare function _readClickEvent(event: any, count: any): string;
@@ -0,0 +1,2 @@
1
+ export default _registerShortcutEvents;
2
+ declare function _registerShortcutEvents(dependencies: any, pluginState: any): number;
@@ -0,0 +1,15 @@
1
+ export default pluginClick;
2
+ /**
3
+ * @function pluginClick
4
+ * @description Plugin for mouse click shortcuts
5
+ * @param {Object} dependencies - Internal dependencies
6
+ * @param {Object} state - Library state
7
+ * @param {Object} [options={}] - Plugin options
8
+ * @param {number} [options.mouseWait=320] - Time to wait for click sequence in ms
9
+ * @param {string} [options.clickTarget='click'] - Data attribute name for click targets
10
+ * @returns {PluginAPI} Plugin API
11
+ */
12
+ declare function pluginClick(dependencies: any, state: any, options?: {
13
+ mouseWait?: number;
14
+ clickTarget?: string;
15
+ }): PluginAPI;
@@ -0,0 +1,5 @@
1
+ export default _defaults;
2
+ declare namespace _defaults {
3
+ function watch(): string;
4
+ function define(el: any): "input" | "checkbox" | "button";
5
+ }
@@ -0,0 +1,5 @@
1
+ export default _listenDOM;
2
+ declare function _listenDOM(dependencies: any, state: any): {
3
+ start: () => void;
4
+ stop: () => void;
5
+ };
@@ -0,0 +1,2 @@
1
+ export default _normalizeShortcutName;
2
+ declare function _normalizeShortcutName(name: any): any;
@@ -0,0 +1,2 @@
1
+ export default _registerShortcutEvents;
2
+ declare function _registerShortcutEvents(dependencies: any, pluginState: any): boolean;
@@ -0,0 +1,10 @@
1
+ export default pluginForm;
2
+ /**
3
+ * @function pluginForm
4
+ * @description Plugin for form element shortcuts
5
+ * @param {Object} dependencies - Internal dependencies
6
+ * @param {Object} state - Library state
7
+ * @param {Object} [options={}] - Plugin options
8
+ * @returns {PluginAPI} Plugin API
9
+ */
10
+ declare function pluginForm(dependencies: any, state: any, options?: any): PluginAPI;
@@ -0,0 +1,5 @@
1
+ export default _listenDOM;
2
+ declare function _listenDOM(dependencies: any, state: any): {
3
+ start: () => void;
4
+ stop: () => void;
5
+ };
@@ -0,0 +1,2 @@
1
+ export default _normalizeShortcutName;
2
+ declare function _normalizeShortcutName(name: any): any;
@@ -0,0 +1,2 @@
1
+ export default _readKeyEvent;
2
+ declare function _readKeyEvent(event: any, _specialChars: any): any[];
@@ -0,0 +1,2 @@
1
+ export default _registerShortcutEvents;
2
+ declare function _registerShortcutEvents(dependencies: any, pluginState: any): number;
@@ -0,0 +1,32 @@
1
+ export default _specialChars;
2
+ declare function _specialChars(): {
3
+ ArrowLeft: string;
4
+ ArrowUp: string;
5
+ ArrowRight: string;
6
+ ArrowDown: string;
7
+ Enter: string;
8
+ NumpadEnter: string;
9
+ Escape: string;
10
+ Backspace: string;
11
+ Space: string;
12
+ Tab: string;
13
+ Backquote: string;
14
+ BracketLeft: string;
15
+ BracketRight: string;
16
+ Equal: string;
17
+ Slash: string;
18
+ Backslash: string;
19
+ IntlBackslash: string;
20
+ F1: string;
21
+ F2: string;
22
+ F3: string;
23
+ F4: string;
24
+ F5: string;
25
+ F6: string;
26
+ F7: string;
27
+ F8: string;
28
+ F9: string;
29
+ F10: string;
30
+ F11: string;
31
+ F12: string;
32
+ };
@@ -0,0 +1,15 @@
1
+ export default pluginKey;
2
+ /**
3
+ * @function pluginKey
4
+ * @description Plugin for keyboard shortcuts
5
+ * @param {Object} dependencies - Internal dependencies
6
+ * @param {Object} state - Library state
7
+ * @param {Object} [options={}] - Plugin options
8
+ * @param {number} [options.keyWait=480] - Time to wait for key sequence in ms
9
+ * @param {function} [options.streamKeys] - Function to stream key presses
10
+ * @returns {PluginAPI} Plugin API
11
+ */
12
+ declare function pluginKey(dependencies: any, state: any, options?: {
13
+ keyWait?: number;
14
+ streamKeys?: Function;
15
+ }): PluginAPI;
@@ -1 +1 @@
1
- "use strict";var t=require("@peter.naydenov/notice");var e={_normalizeWithPlugins:function(t,e){return function(t){const n=e.shortcuts;Object.keys(n).forEach(e=>{Object.entries(n[e]).forEach(([o,r])=>{const i=t(o);i!==o&&(delete n[e][o],n[e][i]=r)})})}},_readShortcutWithPlugins:function(t,e){return function(n){const{inAPI:o}=t,r=n.split(":")[0].toLowerCase().trim(),i=o._systemAction(r,"none");let s=n;return-1!==i&&(s=e.plugins[i].shortcutName(n)),s}},_systemAction:function(t,e){return function(t,n,o=null){return e.plugins.findIndex(e=>e.getPrefix()===t&&(e[n]&&e[n](o),!0))}},changeContext:function(t,e){const{shortcuts:n,currentContext:o}=e,{ev:r}=t;return function(t=!1){const i=o.name;if(!t)return r.reset(),void(o.name=null);i!==t&&(n[t]?(n[i]&&r.reset(),o.name=t,e.plugins.forEach(e=>e.contextChange(t)),Object.entries(n[t]).forEach(([t,e])=>{e.forEach(e=>r.on(t,e))}),r.on("*",(...t)=>{e.exposeShortcut&&e.exposeShortcut(...t)})):r.emit("@shortcuts-error",`Context '${t}' does not exist`))}},listShortcuts:function(t,e){const n=e.shortcuts;return function(t=null){if(null!=t){let e=n[t];return null==e?null:Object.entries(e).map(([t,e])=>t)}return Object.keys(n).map(t=>{let e={};return e.context=t,e.shortcuts=Object.entries(n[t]).map(([t,e])=>t),e})}},load:function(t,e){const{shortcuts:n,plugins:o}=e,{API:{changeContext:r,getContext:i}}=t;return function(t){const e=i(),s=o.map(t=>t.getPrefix().toUpperCase());let c=!1;Object.entries(t).forEach(([t,r])=>{t===e&&(c=!0),n[t]={},Object.entries(r).forEach(([e,r])=>{let i=e,c=e.toUpperCase().trim(),u=s.map((t,e)=>c.startsWith(t)?e:null).filter(t=>null!==t);if(u.length){let t=u[0];i=o[t].shortcutName(e)}r instanceof Function&&(r=[r]),n[t][i]=r})}),c&&(r(),r(e))}},unload:function(t,e){const{currentContext:n,shortcuts:o}=e,{ev:r}=t;return function(t){n.name!==t?o[t]?delete o[t]:r.emit("shortcuts-error",`Context '${t}' does not exist`):r.emit("shortcuts-error",`Context '${t}' can't be removed during is current active context. Change the context first`)}}};function n(t){const e=t.toUpperCase(),n=/KEY\s*\:/i.test(e),o=e.indexOf(":");if(!n)return t;return`KEY:${e.slice(o+1).split(",").map(t=>t.trim()).map(t=>t.split("+").map(t=>t.trim()).sort().join("+")).join(",")}`}function o(t,e){let{shiftKey:n,altKey:o,ctrlKey:r}=t,i=e(),s=t.code.replace("Key","").replace("Digit",""),c=[];return r&&c.push("CTRL"),n&&c.push("SHIFT"),o&&c.push("ALT"),i.hasOwnProperty(s)?c.push(i[s].toUpperCase()):["ControlLeft","ControlRight","ShiftLeft","ShiftRight","AltLeft","AltRight","Meta"].includes(s)||c.push(s.toUpperCase()),c.sort()}function r(t,e){let n=0;const{regex:o}=t,{listenOptions:r,currentContext:{name:i},shortcuts:s}=e;return null==i?0:(Object.entries(s[i]).forEach(([t,e])=>{if(!o.test(t))return;n++;let i=t.slice(4).split(",").length;r.maxSequence<i&&(r.maxSequence=i)}),n)}function i(){return{ArrowLeft:"LEFT",ArrowUp:"UP",ArrowRight:"RIGHT",ArrowDown:"DOWN",Enter:"ENTER",NumpadEnter:"ENTER",Escape:"ESC",Backspace:"BACKSPACE",Space:"SPACE",Tab:"TAB",Backquote:"`",BracketLeft:"[",BracketRight:"]",Equal:"=",Slash:"/",Backslash:"\\",IntlBackslash:"`",F1:"F1",F2:"F2",F3:"F3",F4:"F4",F5:"F5",F6:"F6",F7:"F7",F8:"F8",F9:"F9",F10:"F10",F11:"F11",F12:"F12"}}function s(t,e,n){const{listenOptions:{clickTarget:o}}=e;let r=n;return r===document||r===document.body?null:r.dataset[o]||"A"===r.nodeName?r:s(t,e,r.parentNode)}function c(t){const e=t.toUpperCase(),n=/CLICK\s*\:/i.test(e),o=["LEFT","MIDDLE","RIGHT"],r=["ALT","SHIFT","CTRL"];let i=null,s=[],c=0,u=e.indexOf(":");return n?(e.slice(u+1).trim().split("-").map(t=>t.trim()).forEach(t=>{o.includes(t)?i=t:r.includes(t)?s.push(t):isNaN(t)||(c=t)}),`CLICK:${i}-${c}${s.length>0?"-":""}${s.sort().join("-")}`):t}function u(t,e){let{shiftKey:n,altKey:o,ctrlKey:r,key:i,button:s}=t,c=`CLICK:${["LEFT","MIDDLE","RIGHT"][s]}-${e}`,u=[];return r&&u.push("CTRL"),n&&u.push("SHIFT"),o&&u.push("ALT"),u.length>0?`${c}${u.length>0?"-":""}${u.sort().join("-")}`:`${c}`}function a(t,e){let n=0;const{regex:o}=t,{listenOptions:r,currentContext:{name:i},shortcuts:s}=e;return null==i?0:(Object.entries(s[i]).forEach(([t,e])=>{if(!o.test(t))return;n++;let[,i]=t.slice(6).split("-");r.maxClicks<i&&(r.maxClicks=i)}),n)}function l(t){const e=t.toUpperCase(),n=/FORM\s*\:/i.test(e),o=e.indexOf(":");if(!n)return t;return`FORM:${e.slice(o+1).trim()}`}function m(t,e){const{regex:n,_defaults:o,ev:r}=t,{currentContext:{name:i},shortcuts:s,callbacks:c}=e;let u=[],a=[],l=[];if(null==i)return!1;if(Object.entries(s[i]).forEach(([t,e])=>{n.test(t)&&("FORM:WATCH"===t&&(u=e),"FORM:DEFINE"===t&&(a=e),"FORM:ACTION"===t&&(l=e))}),0===l.length)return!1;let m=new Set;0===a.length&&(a=[o.define]),0===u.length&&(u=[o.watch]);let p=u.map(t=>t()).reduce((t,e)=>(t.push(e),t),[]);return e.watchList=document.querySelectorAll(p),e.watchList.forEach(t=>m.add(a[0](t))),e.typeFn=a[0]?a[0]:o.define,l.forEach(t=>{if(!(t instanceof Function))return console.warn("Warning: The 'form:action' should be a function."),!1;if(!(t()instanceof Array))return console.warn("Warning: The 'form:action' function should RETURN an array."),!1;t().forEach(({fn:t,type:n,timing:o,wait:i=0})=>{if(m.has(n)&&t instanceof Function){let e=`${n}/${o}`;const i=c.hasOwnProperty(e);i?c[e].push(t):c[e]=[t],i||r.on(e,(t,e)=>{e.forEach(e=>{e instanceof Function&&e(t)})})}"instant"===o&&(e.wait[`${n}`]=i)})}),Object.keys(e.callbacks).length>0}const p={watch:()=>"input, select, textarea, button, a",define:t=>"checkbox"===t.type||"radio"===t.type?"checkbox":"button"==t.type||"submit"==t.type?"button":"input"};exports.pluginClick=function(t,e,n){let{currentContext:o,shortcuts:r}=e,{inAPI:i}=t,l={ev:t.ev,_findTarget:s,_readClickEvent:u,mainDependencies:t,regex:/CLICK\s*\:/i},m={currentContext:o,active:!1,shortcuts:r,listenOptions:{mouseWait:n.mouseWait?n.mouseWait:320,maxClicks:1,clickTarget:n.clickTarget?n.clickTarget:"click"}};i._normalizeWithPlugins(c);let p=function(t,e){const{ev:n,_findTarget:o,_readClickEvent:r,mainDependencies:i}=t,{listenOptions:s,currentContext:c}=e,{mouseWait:u}=s;let a=null,l=null,m=null,p=null,f=0;function h(){const t=r(l,f),e={target:a,targetProps:a?a.getBoundingClientRect():null,x:l.clientX,y:l.clientY,context:c.name,note:c.note,event:l,dependencies:i.extra,type:"click"};n.emit(t,e),m=null,p=null,a=null,l=null,f=0}function d(n){let r=s.maxClicks;return clearTimeout(m),p?(clearTimeout(p),void(p=setTimeout(()=>p=null,u))):(a=o(t,e,n.target),a&&a.dataset.hasOwnProperty("quickClick")&&(r=1),a&&"A"===a.tagName&&(r=1),l=n,f++,f>=r?(h(),void(r>1&&(p=setTimeout(()=>p=null,u)))):void(m=setTimeout(h,u)))}function g(n){let r=s.maxClicks;return clearTimeout(m),p?(clearTimeout(p),void(p=setTimeout(()=>p=null,u))):(a=o(t,e,n.target),a&&a.dataset.hasOwnProperty("quickClick")&&(r=1),a&&"A"===a.tagName&&(r=1),l=n,f++,f>=r?(h(),void(r>1&&(p=setTimeout(()=>p=null,u)))):void(m=setTimeout(h,u)))}return{start:function(){e.active||(window.addEventListener("contextmenu",g),document.addEventListener("click",d),e.active=!0)},stop:function(){e.active&&(window.removeEventListener("contextmenu",g),document.removeEventListener("click",d),e.active=!1,m&&(clearTimeout(m),m=null),p&&(clearTimeout(p),p=null),f=0)}}}(l,m),f=a(l,m);f>0&&p.start();let h={getPrefix:()=>"click",shortcutName:t=>c(t),contextChange:()=>{f=a(l,m),f<1&&p.stop(),f>0&&p.start()},mute:()=>{p.stop()},unmute:()=>p.start(),destroy:()=>p.stop()};return Object.freeze(h),h},exports.pluginForm=function(t,e,n){let{currentContext:o,shortcuts:r}=e,{inAPI:i}=t,s={ev:t.ev,mainDependencies:t,regex:/FORM\s*\:/i,_defaults:p},c={currentContext:o,shortcuts:r,callbacks:{},typeFn:"",watchList:[],wait:{}};i._normalizeWithPlugins(l);let u=function(t,e){const{ev:n}=t;let o=null;function r(t,e,n,o){return{target:n.target,context:e.currentContext.name,note:e.currentContext.note,event:n,dependencies:t.mainDependencies.extra,type:o}}function i(o){const{callbacks:i,typeFn:s}=e,c=s(o.target),u=r(t,e,o,c),a=`${c}/in`;null!=i[a]&&n.emit(a,u,i[a])}function s(o){const{callbacks:i,typeFn:s}=e,c=r(t,e,o,"form-out"),u=`${s(o.target)}/out`;null!=i[u]&&n.emit(u,c,i[u])}function c(i){const{callbacks:s,typeFn:c}=e,u=r(t,e,i,"form-instant"),a=c(i.target),l=e.wait[`${a}`],m=`${a}/instant`;null!=s[m]&&(0!==l?(clearTimeout(o),o=setTimeout(()=>n.emit(m,u,s[m]),l)):n.emit(m,u,s[m]))}return{start:function(){e.active||(document.addEventListener("focusin",i),document.addEventListener("focusout",s),document.addEventListener("input",c),e.active=!0)},stop:function(){e.active&&(document.removeEventListener("focusin",i),document.removeEventListener("focusout",s),document.removeEventListener("input",c),e.active=!1)}}}(s,c);if(o.name){m(s,c)&&u.start()}let a={getPrefix:()=>"form",shortcutName:t=>l(t),contextChange:()=>{c.callbacks={},c.typeFn="",c.watchList=[],c.wait={},m(s,c)?u.start():u.stop()},mute:()=>u.stop(),unmute:()=>u.start(),destroy:()=>{u.stop()}};return Object.freeze(a),a},exports.pluginKey=function(t,e,s={}){let{currentContext:c,shortcuts:u,exposeShortcut:a}=e,{inAPI:l}=t,m={ev:t.ev,_specialChars:i,_readKeyEvent:o,mainDependencies:t,regex:/KEY\s*\:/i},p={currentContext:c,shortcuts:u,active:!1,listenOptions:{keyWait:s.keyWait?s.keyWait:480,maxSequence:1,keyIgnore:null},streamKeys:!(!s.streamKeys||"function"!=typeof s.streamKeys)&&s.streamKeys};l._normalizeWithPlugins(n);let f=function(t,e){const{ev:n,_specialChars:o,_readKeyEvent:r,mainDependencies:i}=t,{currentContext:s,streamKeys:c,listenOptions:u}=e,{keyWait:a}=u;let l=[],m=null,p=!0,f=!1;const h=()=>p=!1,d=()=>p=!0,g=()=>f=!0,x=()=>!1===p;function y(){let t=l.map(t=>[t.join("+")]);const e={wait:h,end:d,ignore:g,isWaiting:x,note:s.note,context:s.name,dependencies:i.extra,type:"key"};if(!p){let o=t.at(-1);n.emit(o,e),f&&(t=t.slice(0,-1),f=!1)}if(p){const o=`KEY:${t.join(",")}`;n.emit(o,e),l=[],m=null}}function C(e){if(clearTimeout(m),o().hasOwnProperty(e.code))return l.push(r(e,o)),c&&c({key:e.key,context:s.name,note:s.note,dependencies:t.extra}),u.keyIgnore?(clearTimeout(u.keyIgnore),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,a))):p&&l.length===u.maxSequence?(y(),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,a))):void(p?m=setTimeout(y,a):y())}function k(e){if(!o().hasOwnProperty(e.code)){if(clearTimeout(m),c&&c({key:e.key,context:s.name,note:s.note,dependencies:t.extra}),u.keyIgnore)return clearTimeout(u.keyIgnore),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,a));if(l.push(r(e,o)),p&&l.length===u.maxSequence)return y(),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,a));p?m=setTimeout(y,a):y()}}return{start:function(){e.active||(document.addEventListener("keydown",C),document.addEventListener("keypress",k),e.active=!0)},stop:function(){e.active&&(document.removeEventListener("keydown",C),document.removeEventListener("keypress",k),e.active=!1,m&&(clearTimeout(m),m=null),u.keyIgnore&&(clearTimeout(u.keyIgnore),u.keyIgnore=null),l=[],p=!0,f=!1)}}}(m,p),h=r(m,p);h>0&&f.start();let d={getPrefix:()=>"key",shortcutName:t=>n(t),contextChange:t=>{h=r(m,p),h<1&&f.stop(),h>0&&f.start()},mute:()=>f.stop(),unmute:()=>f.start(),destroy:()=>f.stop()};return Object.freeze(d),d},exports.shortcuts=function(n={}){let o={},r={};const i=t(),s={currentContext:{name:null,note:null},shortcuts:{},plugins:[],exposeShortcut:!(!n.onShortcut||"function"!=typeof n.onShortcut)&&n.onShortcut};let c={ev:i,inAPI:o,API:r,extra:{}};return r.enablePlugin=(t,e={})=>{const n=t.name.replace("plugin","").toLowerCase();if(-1===o._systemAction(n,"none")){let n=t(c,s,e);s.plugins.push(n)}},r.disablePlugin=t=>{const e=o._systemAction(t,"destroy");-1!==e&&(s.plugins=s.plugins.filter((t,n)=>n!==e))},r.mutePlugin=t=>o._systemAction(t,"mute"),r.unmutePlugin=t=>o._systemAction(t,"unmute"),r.getContext=()=>s.currentContext.name,r.getNote=()=>s.currentContext.note,r.setNote=(t=null)=>{"string"!=typeof t&&null!=t||(s.currentContext.note=t)},r.pause=(t="*")=>{let e=o._readShortcutWithPlugins(t);i.stop(e)},r.resume=(t="*")=>{const e=o._readShortcutWithPlugins(t);i.start(e)},r.emit=(t,...e)=>i.emit(o._readShortcutWithPlugins(t),...e),r.listContexts=()=>Object.keys(s.shortcuts),r.setDependencies=t=>c.extra={...c.extra,...t},r.getDependencies=()=>c.extra,r.reset=function(){i.reset(),r.changeContext(),s.plugins.forEach(t=>t.destroy()),r.listContexts().map(t=>r.unload(t)),c.extra={},s.exposeShortcut=null},Object.entries(e).forEach(([t,e])=>{t.startsWith("_")?o[t]=e(c,s):r[t]=e(c,s)}),r};
1
+ "use strict";var t=require("@peter.naydenov/notice");var e={_normalizeWithPlugins:function(t,e){return function(t){const n=e.shortcuts;Object.keys(n).forEach(e=>{Object.entries(n[e]).forEach(([o,r])=>{const i=t(o);i!==o&&(delete n[e][o],n[e][i]=r)})})}},_readShortcutWithPlugins:function(t,e){return function(n){const{inAPI:o}=t,r=n.split(":")[0].toLowerCase().trim(),i=o._systemAction(r,"none");let s=n;return-1!==i&&(s=e.plugins[i].shortcutName(n)),s}},_systemAction:function(t,e){return function(t,n,o=null){return e.plugins.findIndex(e=>e.getPrefix()===t&&(e[n]&&e[n](o),!0))}},changeContext:function(t,e){const{shortcuts:n,currentContext:o,ERROR_EVENT_NAME:r}=e,{ev:i}=t;return function(t=!1){const s=o.name;if(!t)return i.reset(),void(o.name=null);s!==t&&(n[t]?(n[s]&&i.reset(),o.name=t,e.plugins.forEach(e=>e.contextChange(t)),Object.entries(n[t]).forEach(([t,e])=>{e.forEach(e=>i.on(t,e))}),i.on("*",(...t)=>{e.exposeShortcut&&e.exposeShortcut(...t)})):i.emit(r,`Context '${t}' does not exist`))}},listShortcuts:function(t,e){const n=e.shortcuts;return function(t=null){if(null!=t){let e=n[t];return null==e?null:Object.entries(e).map(([t,e])=>t)}return Object.keys(n).map(t=>{let e={};return e.context=t,e.shortcuts=Object.entries(n[t]).map(([t,e])=>t),e})}},load:function(t,e){const{shortcuts:n,plugins:o}=e,{API:{changeContext:r,getContext:i}}=t;return function(t){const e=i(),s=o.map(t=>t.getPrefix().toUpperCase());let c=!1;Object.entries(t).forEach(([t,r])=>{t===e&&(c=!0),n[t]={},Object.entries(r).forEach(([e,r])=>{let i=e,c=e.toUpperCase().trim(),u=s.map((t,e)=>c.startsWith(t)?e:null).filter(t=>null!==t);if(u.length){let t=u[0];i=o[t].shortcutName(e)}r instanceof Function&&(r=[r]),n[t][i]=r})}),c&&(r(),r(e))}},unload:function(t,e){const{currentContext:n,shortcuts:o,ERROR_EVENT_NAME:r}=e,{ev:i}=t;return function(t){n.name!==t?o[t]?delete o[t]:i.emit(r,`Context '${t}' does not exist`):i.emit(r,`Context '${t}' can't be removed during is current active context. Change the context first`)}}};function n(t){const e=t.toUpperCase(),n=/KEY\s*\:/i.test(e),o=e.indexOf(":");if(!n)return t;return`KEY:${e.slice(o+1).split(",").map(t=>t.trim()).map(t=>t.split("+").map(t=>t.trim()).sort().join("+")).join(",")}`}function o(t,e){let{shiftKey:n,altKey:o,ctrlKey:r}=t,i=e(),s=t.code.replace("Key","").replace("Digit",""),c=[];return r&&c.push("CTRL"),n&&c.push("SHIFT"),o&&c.push("ALT"),i.hasOwnProperty(s)?c.push(i[s].toUpperCase()):["ControlLeft","ControlRight","ShiftLeft","ShiftRight","AltLeft","AltRight","Meta"].includes(s)||c.push(s.toUpperCase()),c.sort()}function r(t,e){let n=0;const{regex:o}=t,{listenOptions:r,currentContext:{name:i},shortcuts:s}=e;return null==i?0:(Object.entries(s[i]).forEach(([t,e])=>{if(!o.test(t))return;n++;let i=t.slice(4).split(",").length;r.maxSequence<i&&(r.maxSequence=i)}),n)}function i(){return{ArrowLeft:"LEFT",ArrowUp:"UP",ArrowRight:"RIGHT",ArrowDown:"DOWN",Enter:"ENTER",NumpadEnter:"ENTER",Escape:"ESC",Backspace:"BACKSPACE",Space:"SPACE",Tab:"TAB",Backquote:"`",BracketLeft:"[",BracketRight:"]",Equal:"=",Slash:"/",Backslash:"\\",IntlBackslash:"`",F1:"F1",F2:"F2",F3:"F3",F4:"F4",F5:"F5",F6:"F6",F7:"F7",F8:"F8",F9:"F9",F10:"F10",F11:"F11",F12:"F12"}}function s(t,e,n){const{listenOptions:{clickTarget:o}}=e;let r=n;return r===document||r===document.body?null:r.dataset[o]||"A"===r.nodeName?r:s(t,e,r.parentNode)}function c(t){const e=t.toUpperCase(),n=/CLICK\s*\:/i.test(e),o=["LEFT","MIDDLE","RIGHT"],r=["ALT","SHIFT","CTRL"];let i=null,s=[],c=0,u=e.indexOf(":");return n?(e.slice(u+1).trim().split("-").map(t=>t.trim()).forEach(t=>{o.includes(t)?i=t:r.includes(t)?s.push(t):isNaN(t)||(c=t)}),`CLICK:${i}-${c}${s.length>0?"-":""}${s.sort().join("-")}`):t}function u(t,e){let{shiftKey:n,altKey:o,ctrlKey:r,key:i,button:s}=t,c=`CLICK:${["LEFT","MIDDLE","RIGHT"][s]}-${e}`,u=[];return r&&u.push("CTRL"),n&&u.push("SHIFT"),o&&u.push("ALT"),u.length>0?`${c}${u.length>0?"-":""}${u.sort().join("-")}`:`${c}`}function a(t,e){let n=0;const{regex:o}=t,{listenOptions:r,currentContext:{name:i},shortcuts:s}=e;return null==i?0:(Object.entries(s[i]).forEach(([t,e])=>{if(!o.test(t))return;n++;let[,i]=t.slice(6).split("-");r.maxClicks<i&&(r.maxClicks=i)}),n)}function l(t){const e=t.toUpperCase(),n=/FORM\s*\:/i.test(e),o=e.indexOf(":");if(!n)return t;return`FORM:${e.slice(o+1).trim()}`}function m(t,e){const{regex:n,_defaults:o,ev:r}=t,{currentContext:{name:i},shortcuts:s,callbacks:c}=e;let u=[],a=[],l=[];if(null==i)return!1;if(Object.entries(s[i]).forEach(([t,e])=>{n.test(t)&&("FORM:WATCH"===t&&(u=e),"FORM:DEFINE"===t&&(a=e),"FORM:ACTION"===t&&(l=e))}),0===l.length)return!1;let m=new Set;0===a.length&&(a=[o.define]),0===u.length&&(u=[o.watch]);let p=u.map(t=>t()).reduce((t,e)=>(t.push(e),t),[]);return e.watchList=document.querySelectorAll(p),e.watchList.forEach(t=>m.add(a[0](t))),e.typeFn=a[0]?a[0]:o.define,l.forEach(t=>{if(!(t instanceof Function))return console.warn("Warning: The 'form:action' should be a function."),!1;if(!(t()instanceof Array))return console.warn("Warning: The 'form:action' function should RETURN an array."),!1;t().forEach(({fn:t,type:n,timing:o,wait:i=0})=>{if(m.has(n)&&t instanceof Function){let e=`${n}/${o}`;const i=c.hasOwnProperty(e);i?c[e].push(t):c[e]=[t],i||r.on(e,(t,e)=>{e.forEach(e=>{e instanceof Function&&e(t)})})}"instant"===o&&(e.wait[`${n}`]=i)})}),Object.keys(e.callbacks).length>0}const p={watch:()=>"input, select, textarea, button, a",define:t=>"checkbox"===t.type||"radio"===t.type?"checkbox":"button"==t.type||"submit"==t.type?"button":"input"};exports.pluginClick=function(t,e,n){let{currentContext:o,shortcuts:r}=e,{inAPI:i}=t,l={ev:t.ev,_findTarget:s,_readClickEvent:u,mainDependencies:t,regex:/CLICK\s*\:/i},m={currentContext:o,active:!1,shortcuts:r,listenOptions:{mouseWait:n.mouseWait?n.mouseWait:320,maxClicks:1,clickTarget:n.clickTarget?n.clickTarget:"click"}};i._normalizeWithPlugins(c);let p=function(t,e){const{ev:n,_findTarget:o,_readClickEvent:r,mainDependencies:i}=t,{listenOptions:s,currentContext:c}=e,{mouseWait:u}=s;let a=null,l=null,m=null,p=null,f=0;function h(){const t=r(l,f),e={target:a,targetProps:a?a.getBoundingClientRect():null,x:l.clientX,y:l.clientY,context:c.name,note:c.note,event:l,dependencies:i.extra,type:"click"};n.emit(t,e),m=null,p=null,a=null,l=null,f=0}function d(n){let r=s.maxClicks;return clearTimeout(m),p?(clearTimeout(p),void(p=setTimeout(()=>p=null,u))):(a=o(t,e,n.target),a&&a.dataset.hasOwnProperty("quickClick")&&(r=1),a&&"A"===a.tagName&&(r=1),l=n,f++,f>=r?(h(),void(r>1&&(p=setTimeout(()=>p=null,u)))):void(m=setTimeout(h,u)))}function g(n){let r=s.maxClicks;return clearTimeout(m),p?(clearTimeout(p),void(p=setTimeout(()=>p=null,u))):(a=o(t,e,n.target),a&&a.dataset.hasOwnProperty("quickClick")&&(r=1),a&&"A"===a.tagName&&(r=1),l=n,f++,f>=r?(h(),void(r>1&&(p=setTimeout(()=>p=null,u)))):void(m=setTimeout(h,u)))}return{start:function(){e.active||(window.addEventListener("contextmenu",g),document.addEventListener("click",d),e.active=!0)},stop:function(){e.active&&(window.removeEventListener("contextmenu",g),document.removeEventListener("click",d),e.active=!1,m&&(clearTimeout(m),m=null),p&&(clearTimeout(p),p=null),f=0)}}}(l,m),f=a(l,m);f>0&&p.start();let h={getPrefix:()=>"click",shortcutName:t=>c(t),contextChange:()=>{f=a(l,m),f<1&&p.stop(),f>0&&p.start()},mute:()=>{p.stop()},unmute:()=>p.start(),destroy:()=>p.stop()};return Object.freeze(h),h},exports.pluginForm=function(t,e,n){let{currentContext:o,shortcuts:r}=e,{inAPI:i}=t,s={ev:t.ev,mainDependencies:t,regex:/FORM\s*\:/i,_defaults:p},c={currentContext:o,shortcuts:r,callbacks:{},typeFn:"",watchList:[],wait:{}};i._normalizeWithPlugins(l);let u=function(t,e){const{ev:n}=t;let o=null;function r(t,e,n,o){return{target:n.target,context:e.currentContext.name,note:e.currentContext.note,event:n,dependencies:t.mainDependencies.extra,type:o}}function i(o){const{callbacks:i,typeFn:s}=e,c=s(o.target),u=r(t,e,o,c),a=`${c}/in`;null!=i[a]&&n.emit(a,u,i[a])}function s(o){const{callbacks:i,typeFn:s}=e,c=r(t,e,o,"form-out"),u=`${s(o.target)}/out`;null!=i[u]&&n.emit(u,c,i[u])}function c(i){const{callbacks:s,typeFn:c}=e,u=r(t,e,i,"form-instant"),a=c(i.target),l=e.wait[`${a}`],m=`${a}/instant`;null!=s[m]&&(0!==l?(clearTimeout(o),o=setTimeout(()=>n.emit(m,u,s[m]),l)):n.emit(m,u,s[m]))}return{start:function(){e.active||(document.addEventListener("focusin",i),document.addEventListener("focusout",s),document.addEventListener("input",c),e.active=!0)},stop:function(){e.active&&(document.removeEventListener("focusin",i),document.removeEventListener("focusout",s),document.removeEventListener("input",c),e.active=!1)}}}(s,c);if(o.name){m(s,c)&&u.start()}let a={getPrefix:()=>"form",shortcutName:t=>l(t),contextChange:()=>{c.callbacks={},c.typeFn="",c.watchList=[],c.wait={},m(s,c)?u.start():u.stop()},mute:()=>u.stop(),unmute:()=>u.start(),destroy:()=>{u.stop()}};return Object.freeze(a),a},exports.pluginKey=function(t,e,s={}){let{currentContext:c,shortcuts:u,exposeShortcut:a}=e,{inAPI:l}=t,m={ev:t.ev,_specialChars:i,_readKeyEvent:o,mainDependencies:t,regex:/KEY\s*\:/i},p={currentContext:c,shortcuts:u,active:!1,listenOptions:{keyWait:s.keyWait?s.keyWait:480,maxSequence:1,keyIgnore:null},streamKeys:!(!s.streamKeys||"function"!=typeof s.streamKeys)&&s.streamKeys};l._normalizeWithPlugins(n);let f=function(t,e){const{ev:n,_specialChars:o,_readKeyEvent:r,mainDependencies:i}=t,{currentContext:s,streamKeys:c,listenOptions:u}=e,{keyWait:a}=u;let l=[],m=null,p=!0,f=!1;const h=()=>p=!1,d=()=>p=!0,g=()=>f=!0,x=()=>!1===p;function y(){let t=l.map(t=>[t.join("+")]);const e={wait:h,end:d,ignore:g,isWaiting:x,note:s.note,context:s.name,dependencies:i.extra,type:"key"};if(!p){let o=t.at(-1);n.emit(o,e),f&&(t=t.slice(0,-1),f=!1)}if(p){const o=`KEY:${t.join(",")}`;n.emit(o,e),l=[],m=null}}function C(e){if(clearTimeout(m),o().hasOwnProperty(e.code))return l.push(r(e,o)),c&&c({key:e.key,context:s.name,note:s.note,dependencies:t.extra}),u.keyIgnore?(clearTimeout(u.keyIgnore),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,a))):p&&l.length===u.maxSequence?(y(),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,a))):void(p?m=setTimeout(y,a):y())}function v(e){if(!o().hasOwnProperty(e.code)){if(clearTimeout(m),c&&c({key:e.key,context:s.name,note:s.note,dependencies:t.extra}),u.keyIgnore)return clearTimeout(u.keyIgnore),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,a));if(l.push(r(e,o)),p&&l.length===u.maxSequence)return y(),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,a));p?m=setTimeout(y,a):y()}}return{start:function(){e.active||(document.addEventListener("keydown",C),document.addEventListener("keypress",v),e.active=!0)},stop:function(){e.active&&(document.removeEventListener("keydown",C),document.removeEventListener("keypress",v),e.active=!1,m&&(clearTimeout(m),m=null),u.keyIgnore&&(clearTimeout(u.keyIgnore),u.keyIgnore=null),l=[],p=!0,f=!1)}}}(m,p),h=r(m,p);h>0&&f.start();let d={getPrefix:()=>"key",shortcutName:t=>n(t),contextChange:t=>{h=r(m,p),h<1&&f.stop(),h>0&&f.start()},mute:()=>f.stop(),unmute:()=>f.start(),destroy:()=>f.stop()};return Object.freeze(d),d},exports.shortcuts=function(n={}){let o={},r={};const i=t(),s={currentContext:{name:null,note:null},shortcuts:{},plugins:[],exposeShortcut:!(!n.onShortcut||"function"!=typeof n.onShortcut)&&n.onShortcut,ERROR_EVENT_NAME:n.errorEventName?n.errorEventName:"@shortcuts-error"};let c={ev:i,inAPI:o,API:r,extra:{}};return r.enablePlugin=(t,e={})=>{if("function"!=typeof t)return;let n=t(c,s,e);const r=n.getPrefix();-1===o._systemAction(r,"none")?s.plugins.push(n):n.destroy()},r.disablePlugin=t=>{const e=o._systemAction(t,"destroy");-1!==e&&(s.plugins=s.plugins.filter((t,n)=>n!==e))},r.mutePlugin=t=>o._systemAction(t,"mute"),r.unmutePlugin=t=>o._systemAction(t,"unmute"),r.listPlugins=()=>s.plugins.map(t=>t.getPrefix()),r.getContext=()=>s.currentContext.name,r.getNote=()=>s.currentContext.note,r.setNote=(t=null)=>{"string"!=typeof t&&null!=t||(s.currentContext.note=t)},r.pause=(t="*")=>{let e=o._readShortcutWithPlugins(t);i.stop(e)},r.resume=(t="*")=>{const e=o._readShortcutWithPlugins(t);i.start(e)},r.emit=(t,...e)=>i.emit(o._readShortcutWithPlugins(t),...e),r.listContexts=()=>Object.keys(s.shortcuts),r.setDependencies=t=>c.extra={...c.extra,...t},r.getDependencies=()=>c.extra,r.reset=function(){i.reset(),r.changeContext(),s.plugins.forEach(t=>t.destroy()),r.listContexts().map(t=>r.unload(t)),c.extra={},s.exposeShortcut=null},Object.entries(e).forEach(([t,e])=>{t.startsWith("_")?o[t]=e(c,s):r[t]=e(c,s)}),r};
@@ -1 +1 @@
1
- import t from"@peter.naydenov/notice";var e={_normalizeWithPlugins:function(t,e){return function(t){const n=e.shortcuts;Object.keys(n).forEach(e=>{Object.entries(n[e]).forEach(([o,r])=>{const i=t(o);i!==o&&(delete n[e][o],n[e][i]=r)})})}},_readShortcutWithPlugins:function(t,e){return function(n){const{inAPI:o}=t,r=n.split(":")[0].toLowerCase().trim(),i=o._systemAction(r,"none");let s=n;return-1!==i&&(s=e.plugins[i].shortcutName(n)),s}},_systemAction:function(t,e){return function(t,n,o=null){return e.plugins.findIndex(e=>e.getPrefix()===t&&(e[n]&&e[n](o),!0))}},changeContext:function(t,e){const{shortcuts:n,currentContext:o}=e,{ev:r}=t;return function(t=!1){const i=o.name;if(!t)return r.reset(),void(o.name=null);i!==t&&(n[t]?(n[i]&&r.reset(),o.name=t,e.plugins.forEach(e=>e.contextChange(t)),Object.entries(n[t]).forEach(([t,e])=>{e.forEach(e=>r.on(t,e))}),r.on("*",(...t)=>{e.exposeShortcut&&e.exposeShortcut(...t)})):r.emit("@shortcuts-error",`Context '${t}' does not exist`))}},listShortcuts:function(t,e){const n=e.shortcuts;return function(t=null){if(null!=t){let e=n[t];return null==e?null:Object.entries(e).map(([t,e])=>t)}return Object.keys(n).map(t=>{let e={};return e.context=t,e.shortcuts=Object.entries(n[t]).map(([t,e])=>t),e})}},load:function(t,e){const{shortcuts:n,plugins:o}=e,{API:{changeContext:r,getContext:i}}=t;return function(t){const e=i(),s=o.map(t=>t.getPrefix().toUpperCase());let c=!1;Object.entries(t).forEach(([t,r])=>{t===e&&(c=!0),n[t]={},Object.entries(r).forEach(([e,r])=>{let i=e,c=e.toUpperCase().trim(),u=s.map((t,e)=>c.startsWith(t)?e:null).filter(t=>null!==t);if(u.length){let t=u[0];i=o[t].shortcutName(e)}r instanceof Function&&(r=[r]),n[t][i]=r})}),c&&(r(),r(e))}},unload:function(t,e){const{currentContext:n,shortcuts:o}=e,{ev:r}=t;return function(t){n.name!==t?o[t]?delete o[t]:r.emit("shortcuts-error",`Context '${t}' does not exist`):r.emit("shortcuts-error",`Context '${t}' can't be removed during is current active context. Change the context first`)}}};function n(t){const e=t.toUpperCase(),n=/KEY\s*\:/i.test(e),o=e.indexOf(":");if(!n)return t;return`KEY:${e.slice(o+1).split(",").map(t=>t.trim()).map(t=>t.split("+").map(t=>t.trim()).sort().join("+")).join(",")}`}function o(t,e){let{shiftKey:n,altKey:o,ctrlKey:r}=t,i=e(),s=t.code.replace("Key","").replace("Digit",""),c=[];return r&&c.push("CTRL"),n&&c.push("SHIFT"),o&&c.push("ALT"),i.hasOwnProperty(s)?c.push(i[s].toUpperCase()):["ControlLeft","ControlRight","ShiftLeft","ShiftRight","AltLeft","AltRight","Meta"].includes(s)||c.push(s.toUpperCase()),c.sort()}function r(t,e){let n=0;const{regex:o}=t,{listenOptions:r,currentContext:{name:i},shortcuts:s}=e;return null==i?0:(Object.entries(s[i]).forEach(([t,e])=>{if(!o.test(t))return;n++;let i=t.slice(4).split(",").length;r.maxSequence<i&&(r.maxSequence=i)}),n)}function i(){return{ArrowLeft:"LEFT",ArrowUp:"UP",ArrowRight:"RIGHT",ArrowDown:"DOWN",Enter:"ENTER",NumpadEnter:"ENTER",Escape:"ESC",Backspace:"BACKSPACE",Space:"SPACE",Tab:"TAB",Backquote:"`",BracketLeft:"[",BracketRight:"]",Equal:"=",Slash:"/",Backslash:"\\",IntlBackslash:"`",F1:"F1",F2:"F2",F3:"F3",F4:"F4",F5:"F5",F6:"F6",F7:"F7",F8:"F8",F9:"F9",F10:"F10",F11:"F11",F12:"F12"}}function s(t,e,s={}){let{currentContext:c,shortcuts:u,exposeShortcut:a}=e,{inAPI:l}=t,m={ev:t.ev,_specialChars:i,_readKeyEvent:o,mainDependencies:t,regex:/KEY\s*\:/i},f={currentContext:c,shortcuts:u,active:!1,listenOptions:{keyWait:s.keyWait?s.keyWait:480,maxSequence:1,keyIgnore:null},streamKeys:!(!s.streamKeys||"function"!=typeof s.streamKeys)&&s.streamKeys};l._normalizeWithPlugins(n);let p=function(t,e){const{ev:n,_specialChars:o,_readKeyEvent:r,mainDependencies:i}=t,{currentContext:s,streamKeys:c,listenOptions:u}=e,{keyWait:a}=u;let l=[],m=null,f=!0,p=!1;const h=()=>f=!1,d=()=>f=!0,g=()=>p=!0,x=()=>!1===f;function y(){let t=l.map(t=>[t.join("+")]);const e={wait:h,end:d,ignore:g,isWaiting:x,note:s.note,context:s.name,dependencies:i.extra,type:"key"};if(!f){let o=t.at(-1);n.emit(o,e),p&&(t=t.slice(0,-1),p=!1)}if(f){const o=`KEY:${t.join(",")}`;n.emit(o,e),l=[],m=null}}function C(e){if(clearTimeout(m),o().hasOwnProperty(e.code))return l.push(r(e,o)),c&&c({key:e.key,context:s.name,note:s.note,dependencies:t.extra}),u.keyIgnore?(clearTimeout(u.keyIgnore),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,a))):f&&l.length===u.maxSequence?(y(),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,a))):void(f?m=setTimeout(y,a):y())}function k(e){if(!o().hasOwnProperty(e.code)){if(clearTimeout(m),c&&c({key:e.key,context:s.name,note:s.note,dependencies:t.extra}),u.keyIgnore)return clearTimeout(u.keyIgnore),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,a));if(l.push(r(e,o)),f&&l.length===u.maxSequence)return y(),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,a));f?m=setTimeout(y,a):y()}}return{start:function(){e.active||(document.addEventListener("keydown",C),document.addEventListener("keypress",k),e.active=!0)},stop:function(){e.active&&(document.removeEventListener("keydown",C),document.removeEventListener("keypress",k),e.active=!1,m&&(clearTimeout(m),m=null),u.keyIgnore&&(clearTimeout(u.keyIgnore),u.keyIgnore=null),l=[],f=!0,p=!1)}}}(m,f),h=r(m,f);h>0&&p.start();let d={getPrefix:()=>"key",shortcutName:t=>n(t),contextChange:t=>{h=r(m,f),h<1&&p.stop(),h>0&&p.start()},mute:()=>p.stop(),unmute:()=>p.start(),destroy:()=>p.stop()};return Object.freeze(d),d}function c(t,e,n){const{listenOptions:{clickTarget:o}}=e;let r=n;return r===document||r===document.body?null:r.dataset[o]||"A"===r.nodeName?r:c(t,e,r.parentNode)}function u(t){const e=t.toUpperCase(),n=/CLICK\s*\:/i.test(e),o=["LEFT","MIDDLE","RIGHT"],r=["ALT","SHIFT","CTRL"];let i=null,s=[],c=0,u=e.indexOf(":");return n?(e.slice(u+1).trim().split("-").map(t=>t.trim()).forEach(t=>{o.includes(t)?i=t:r.includes(t)?s.push(t):isNaN(t)||(c=t)}),`CLICK:${i}-${c}${s.length>0?"-":""}${s.sort().join("-")}`):t}function a(t,e){let{shiftKey:n,altKey:o,ctrlKey:r,key:i,button:s}=t,c=`CLICK:${["LEFT","MIDDLE","RIGHT"][s]}-${e}`,u=[];return r&&u.push("CTRL"),n&&u.push("SHIFT"),o&&u.push("ALT"),u.length>0?`${c}${u.length>0?"-":""}${u.sort().join("-")}`:`${c}`}function l(t,e){let n=0;const{regex:o}=t,{listenOptions:r,currentContext:{name:i},shortcuts:s}=e;return null==i?0:(Object.entries(s[i]).forEach(([t,e])=>{if(!o.test(t))return;n++;let[,i]=t.slice(6).split("-");r.maxClicks<i&&(r.maxClicks=i)}),n)}function m(t,e,n){let{currentContext:o,shortcuts:r}=e,{inAPI:i}=t,s={ev:t.ev,_findTarget:c,_readClickEvent:a,mainDependencies:t,regex:/CLICK\s*\:/i},m={currentContext:o,active:!1,shortcuts:r,listenOptions:{mouseWait:n.mouseWait?n.mouseWait:320,maxClicks:1,clickTarget:n.clickTarget?n.clickTarget:"click"}};i._normalizeWithPlugins(u);let f=function(t,e){const{ev:n,_findTarget:o,_readClickEvent:r,mainDependencies:i}=t,{listenOptions:s,currentContext:c}=e,{mouseWait:u}=s;let a=null,l=null,m=null,f=null,p=0;function h(){const t=r(l,p),e={target:a,targetProps:a?a.getBoundingClientRect():null,x:l.clientX,y:l.clientY,context:c.name,note:c.note,event:l,dependencies:i.extra,type:"click"};n.emit(t,e),m=null,f=null,a=null,l=null,p=0}function d(n){let r=s.maxClicks;return clearTimeout(m),f?(clearTimeout(f),void(f=setTimeout(()=>f=null,u))):(a=o(t,e,n.target),a&&a.dataset.hasOwnProperty("quickClick")&&(r=1),a&&"A"===a.tagName&&(r=1),l=n,p++,p>=r?(h(),void(r>1&&(f=setTimeout(()=>f=null,u)))):void(m=setTimeout(h,u)))}function g(n){let r=s.maxClicks;return clearTimeout(m),f?(clearTimeout(f),void(f=setTimeout(()=>f=null,u))):(a=o(t,e,n.target),a&&a.dataset.hasOwnProperty("quickClick")&&(r=1),a&&"A"===a.tagName&&(r=1),l=n,p++,p>=r?(h(),void(r>1&&(f=setTimeout(()=>f=null,u)))):void(m=setTimeout(h,u)))}return{start:function(){e.active||(window.addEventListener("contextmenu",g),document.addEventListener("click",d),e.active=!0)},stop:function(){e.active&&(window.removeEventListener("contextmenu",g),document.removeEventListener("click",d),e.active=!1,m&&(clearTimeout(m),m=null),f&&(clearTimeout(f),f=null),p=0)}}}(s,m),p=l(s,m);p>0&&f.start();let h={getPrefix:()=>"click",shortcutName:t=>u(t),contextChange:()=>{p=l(s,m),p<1&&f.stop(),p>0&&f.start()},mute:()=>{f.stop()},unmute:()=>f.start(),destroy:()=>f.stop()};return Object.freeze(h),h}function f(t){const e=t.toUpperCase(),n=/FORM\s*\:/i.test(e),o=e.indexOf(":");if(!n)return t;return`FORM:${e.slice(o+1).trim()}`}function p(t,e){const{regex:n,_defaults:o,ev:r}=t,{currentContext:{name:i},shortcuts:s,callbacks:c}=e;let u=[],a=[],l=[];if(null==i)return!1;if(Object.entries(s[i]).forEach(([t,e])=>{n.test(t)&&("FORM:WATCH"===t&&(u=e),"FORM:DEFINE"===t&&(a=e),"FORM:ACTION"===t&&(l=e))}),0===l.length)return!1;let m=new Set;0===a.length&&(a=[o.define]),0===u.length&&(u=[o.watch]);let f=u.map(t=>t()).reduce((t,e)=>(t.push(e),t),[]);return e.watchList=document.querySelectorAll(f),e.watchList.forEach(t=>m.add(a[0](t))),e.typeFn=a[0]?a[0]:o.define,l.forEach(t=>{if(!(t instanceof Function))return console.warn("Warning: The 'form:action' should be a function."),!1;if(!(t()instanceof Array))return console.warn("Warning: The 'form:action' function should RETURN an array."),!1;t().forEach(({fn:t,type:n,timing:o,wait:i=0})=>{if(m.has(n)&&t instanceof Function){let e=`${n}/${o}`;const i=c.hasOwnProperty(e);i?c[e].push(t):c[e]=[t],i||r.on(e,(t,e)=>{e.forEach(e=>{e instanceof Function&&e(t)})})}"instant"===o&&(e.wait[`${n}`]=i)})}),Object.keys(e.callbacks).length>0}const h={watch:()=>"input, select, textarea, button, a",define:t=>"checkbox"===t.type||"radio"===t.type?"checkbox":"button"==t.type||"submit"==t.type?"button":"input"};function d(t,e,n){let{currentContext:o,shortcuts:r}=e,{inAPI:i}=t,s={ev:t.ev,mainDependencies:t,regex:/FORM\s*\:/i,_defaults:h},c={currentContext:o,shortcuts:r,callbacks:{},typeFn:"",watchList:[],wait:{}};i._normalizeWithPlugins(f);let u=function(t,e){const{ev:n}=t;let o=null;function r(t,e,n,o){return{target:n.target,context:e.currentContext.name,note:e.currentContext.note,event:n,dependencies:t.mainDependencies.extra,type:o}}function i(o){const{callbacks:i,typeFn:s}=e,c=s(o.target),u=r(t,e,o,c),a=`${c}/in`;null!=i[a]&&n.emit(a,u,i[a])}function s(o){const{callbacks:i,typeFn:s}=e,c=r(t,e,o,"form-out"),u=`${s(o.target)}/out`;null!=i[u]&&n.emit(u,c,i[u])}function c(i){const{callbacks:s,typeFn:c}=e,u=r(t,e,i,"form-instant"),a=c(i.target),l=e.wait[`${a}`],m=`${a}/instant`;null!=s[m]&&(0!==l?(clearTimeout(o),o=setTimeout(()=>n.emit(m,u,s[m]),l)):n.emit(m,u,s[m]))}return{start:function(){e.active||(document.addEventListener("focusin",i),document.addEventListener("focusout",s),document.addEventListener("input",c),e.active=!0)},stop:function(){e.active&&(document.removeEventListener("focusin",i),document.removeEventListener("focusout",s),document.removeEventListener("input",c),e.active=!1)}}}(s,c);if(o.name){p(s,c)&&u.start()}let a={getPrefix:()=>"form",shortcutName:t=>f(t),contextChange:()=>{c.callbacks={},c.typeFn="",c.watchList=[],c.wait={},p(s,c)?u.start():u.stop()},mute:()=>u.stop(),unmute:()=>u.start(),destroy:()=>{u.stop()}};return Object.freeze(a),a}function g(n={}){let o={},r={};const i=t(),s={currentContext:{name:null,note:null},shortcuts:{},plugins:[],exposeShortcut:!(!n.onShortcut||"function"!=typeof n.onShortcut)&&n.onShortcut};let c={ev:i,inAPI:o,API:r,extra:{}};return r.enablePlugin=(t,e={})=>{const n=t.name.replace("plugin","").toLowerCase();if(-1===o._systemAction(n,"none")){let n=t(c,s,e);s.plugins.push(n)}},r.disablePlugin=t=>{const e=o._systemAction(t,"destroy");-1!==e&&(s.plugins=s.plugins.filter((t,n)=>n!==e))},r.mutePlugin=t=>o._systemAction(t,"mute"),r.unmutePlugin=t=>o._systemAction(t,"unmute"),r.getContext=()=>s.currentContext.name,r.getNote=()=>s.currentContext.note,r.setNote=(t=null)=>{"string"!=typeof t&&null!=t||(s.currentContext.note=t)},r.pause=(t="*")=>{let e=o._readShortcutWithPlugins(t);i.stop(e)},r.resume=(t="*")=>{const e=o._readShortcutWithPlugins(t);i.start(e)},r.emit=(t,...e)=>i.emit(o._readShortcutWithPlugins(t),...e),r.listContexts=()=>Object.keys(s.shortcuts),r.setDependencies=t=>c.extra={...c.extra,...t},r.getDependencies=()=>c.extra,r.reset=function(){i.reset(),r.changeContext(),s.plugins.forEach(t=>t.destroy()),r.listContexts().map(t=>r.unload(t)),c.extra={},s.exposeShortcut=null},Object.entries(e).forEach(([t,e])=>{t.startsWith("_")?o[t]=e(c,s):r[t]=e(c,s)}),r}export{m as pluginClick,d as pluginForm,s as pluginKey,g as shortcuts};
1
+ import t from"@peter.naydenov/notice";var e={_normalizeWithPlugins:function(t,e){return function(t){const n=e.shortcuts;Object.keys(n).forEach(e=>{Object.entries(n[e]).forEach(([o,r])=>{const i=t(o);i!==o&&(delete n[e][o],n[e][i]=r)})})}},_readShortcutWithPlugins:function(t,e){return function(n){const{inAPI:o}=t,r=n.split(":")[0].toLowerCase().trim(),i=o._systemAction(r,"none");let s=n;return-1!==i&&(s=e.plugins[i].shortcutName(n)),s}},_systemAction:function(t,e){return function(t,n,o=null){return e.plugins.findIndex(e=>e.getPrefix()===t&&(e[n]&&e[n](o),!0))}},changeContext:function(t,e){const{shortcuts:n,currentContext:o,ERROR_EVENT_NAME:r}=e,{ev:i}=t;return function(t=!1){const s=o.name;if(!t)return i.reset(),void(o.name=null);s!==t&&(n[t]?(n[s]&&i.reset(),o.name=t,e.plugins.forEach(e=>e.contextChange(t)),Object.entries(n[t]).forEach(([t,e])=>{e.forEach(e=>i.on(t,e))}),i.on("*",(...t)=>{e.exposeShortcut&&e.exposeShortcut(...t)})):i.emit(r,`Context '${t}' does not exist`))}},listShortcuts:function(t,e){const n=e.shortcuts;return function(t=null){if(null!=t){let e=n[t];return null==e?null:Object.entries(e).map(([t,e])=>t)}return Object.keys(n).map(t=>{let e={};return e.context=t,e.shortcuts=Object.entries(n[t]).map(([t,e])=>t),e})}},load:function(t,e){const{shortcuts:n,plugins:o}=e,{API:{changeContext:r,getContext:i}}=t;return function(t){const e=i(),s=o.map(t=>t.getPrefix().toUpperCase());let c=!1;Object.entries(t).forEach(([t,r])=>{t===e&&(c=!0),n[t]={},Object.entries(r).forEach(([e,r])=>{let i=e,c=e.toUpperCase().trim(),u=s.map((t,e)=>c.startsWith(t)?e:null).filter(t=>null!==t);if(u.length){let t=u[0];i=o[t].shortcutName(e)}r instanceof Function&&(r=[r]),n[t][i]=r})}),c&&(r(),r(e))}},unload:function(t,e){const{currentContext:n,shortcuts:o,ERROR_EVENT_NAME:r}=e,{ev:i}=t;return function(t){n.name!==t?o[t]?delete o[t]:i.emit(r,`Context '${t}' does not exist`):i.emit(r,`Context '${t}' can't be removed during is current active context. Change the context first`)}}};function n(t){const e=t.toUpperCase(),n=/KEY\s*\:/i.test(e),o=e.indexOf(":");if(!n)return t;return`KEY:${e.slice(o+1).split(",").map(t=>t.trim()).map(t=>t.split("+").map(t=>t.trim()).sort().join("+")).join(",")}`}function o(t,e){let{shiftKey:n,altKey:o,ctrlKey:r}=t,i=e(),s=t.code.replace("Key","").replace("Digit",""),c=[];return r&&c.push("CTRL"),n&&c.push("SHIFT"),o&&c.push("ALT"),i.hasOwnProperty(s)?c.push(i[s].toUpperCase()):["ControlLeft","ControlRight","ShiftLeft","ShiftRight","AltLeft","AltRight","Meta"].includes(s)||c.push(s.toUpperCase()),c.sort()}function r(t,e){let n=0;const{regex:o}=t,{listenOptions:r,currentContext:{name:i},shortcuts:s}=e;return null==i?0:(Object.entries(s[i]).forEach(([t,e])=>{if(!o.test(t))return;n++;let i=t.slice(4).split(",").length;r.maxSequence<i&&(r.maxSequence=i)}),n)}function i(){return{ArrowLeft:"LEFT",ArrowUp:"UP",ArrowRight:"RIGHT",ArrowDown:"DOWN",Enter:"ENTER",NumpadEnter:"ENTER",Escape:"ESC",Backspace:"BACKSPACE",Space:"SPACE",Tab:"TAB",Backquote:"`",BracketLeft:"[",BracketRight:"]",Equal:"=",Slash:"/",Backslash:"\\",IntlBackslash:"`",F1:"F1",F2:"F2",F3:"F3",F4:"F4",F5:"F5",F6:"F6",F7:"F7",F8:"F8",F9:"F9",F10:"F10",F11:"F11",F12:"F12"}}function s(t,e,s={}){let{currentContext:c,shortcuts:u,exposeShortcut:a}=e,{inAPI:l}=t,m={ev:t.ev,_specialChars:i,_readKeyEvent:o,mainDependencies:t,regex:/KEY\s*\:/i},f={currentContext:c,shortcuts:u,active:!1,listenOptions:{keyWait:s.keyWait?s.keyWait:480,maxSequence:1,keyIgnore:null},streamKeys:!(!s.streamKeys||"function"!=typeof s.streamKeys)&&s.streamKeys};l._normalizeWithPlugins(n);let p=function(t,e){const{ev:n,_specialChars:o,_readKeyEvent:r,mainDependencies:i}=t,{currentContext:s,streamKeys:c,listenOptions:u}=e,{keyWait:a}=u;let l=[],m=null,f=!0,p=!1;const h=()=>f=!1,d=()=>f=!0,g=()=>p=!0,x=()=>!1===f;function y(){let t=l.map(t=>[t.join("+")]);const e={wait:h,end:d,ignore:g,isWaiting:x,note:s.note,context:s.name,dependencies:i.extra,type:"key"};if(!f){let o=t.at(-1);n.emit(o,e),p&&(t=t.slice(0,-1),p=!1)}if(f){const o=`KEY:${t.join(",")}`;n.emit(o,e),l=[],m=null}}function C(e){if(clearTimeout(m),o().hasOwnProperty(e.code))return l.push(r(e,o)),c&&c({key:e.key,context:s.name,note:s.note,dependencies:t.extra}),u.keyIgnore?(clearTimeout(u.keyIgnore),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,a))):f&&l.length===u.maxSequence?(y(),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,a))):void(f?m=setTimeout(y,a):y())}function v(e){if(!o().hasOwnProperty(e.code)){if(clearTimeout(m),c&&c({key:e.key,context:s.name,note:s.note,dependencies:t.extra}),u.keyIgnore)return clearTimeout(u.keyIgnore),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,a));if(l.push(r(e,o)),f&&l.length===u.maxSequence)return y(),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,a));f?m=setTimeout(y,a):y()}}return{start:function(){e.active||(document.addEventListener("keydown",C),document.addEventListener("keypress",v),e.active=!0)},stop:function(){e.active&&(document.removeEventListener("keydown",C),document.removeEventListener("keypress",v),e.active=!1,m&&(clearTimeout(m),m=null),u.keyIgnore&&(clearTimeout(u.keyIgnore),u.keyIgnore=null),l=[],f=!0,p=!1)}}}(m,f),h=r(m,f);h>0&&p.start();let d={getPrefix:()=>"key",shortcutName:t=>n(t),contextChange:t=>{h=r(m,f),h<1&&p.stop(),h>0&&p.start()},mute:()=>p.stop(),unmute:()=>p.start(),destroy:()=>p.stop()};return Object.freeze(d),d}function c(t,e,n){const{listenOptions:{clickTarget:o}}=e;let r=n;return r===document||r===document.body?null:r.dataset[o]||"A"===r.nodeName?r:c(t,e,r.parentNode)}function u(t){const e=t.toUpperCase(),n=/CLICK\s*\:/i.test(e),o=["LEFT","MIDDLE","RIGHT"],r=["ALT","SHIFT","CTRL"];let i=null,s=[],c=0,u=e.indexOf(":");return n?(e.slice(u+1).trim().split("-").map(t=>t.trim()).forEach(t=>{o.includes(t)?i=t:r.includes(t)?s.push(t):isNaN(t)||(c=t)}),`CLICK:${i}-${c}${s.length>0?"-":""}${s.sort().join("-")}`):t}function a(t,e){let{shiftKey:n,altKey:o,ctrlKey:r,key:i,button:s}=t,c=`CLICK:${["LEFT","MIDDLE","RIGHT"][s]}-${e}`,u=[];return r&&u.push("CTRL"),n&&u.push("SHIFT"),o&&u.push("ALT"),u.length>0?`${c}${u.length>0?"-":""}${u.sort().join("-")}`:`${c}`}function l(t,e){let n=0;const{regex:o}=t,{listenOptions:r,currentContext:{name:i},shortcuts:s}=e;return null==i?0:(Object.entries(s[i]).forEach(([t,e])=>{if(!o.test(t))return;n++;let[,i]=t.slice(6).split("-");r.maxClicks<i&&(r.maxClicks=i)}),n)}function m(t,e,n){let{currentContext:o,shortcuts:r}=e,{inAPI:i}=t,s={ev:t.ev,_findTarget:c,_readClickEvent:a,mainDependencies:t,regex:/CLICK\s*\:/i},m={currentContext:o,active:!1,shortcuts:r,listenOptions:{mouseWait:n.mouseWait?n.mouseWait:320,maxClicks:1,clickTarget:n.clickTarget?n.clickTarget:"click"}};i._normalizeWithPlugins(u);let f=function(t,e){const{ev:n,_findTarget:o,_readClickEvent:r,mainDependencies:i}=t,{listenOptions:s,currentContext:c}=e,{mouseWait:u}=s;let a=null,l=null,m=null,f=null,p=0;function h(){const t=r(l,p),e={target:a,targetProps:a?a.getBoundingClientRect():null,x:l.clientX,y:l.clientY,context:c.name,note:c.note,event:l,dependencies:i.extra,type:"click"};n.emit(t,e),m=null,f=null,a=null,l=null,p=0}function d(n){let r=s.maxClicks;return clearTimeout(m),f?(clearTimeout(f),void(f=setTimeout(()=>f=null,u))):(a=o(t,e,n.target),a&&a.dataset.hasOwnProperty("quickClick")&&(r=1),a&&"A"===a.tagName&&(r=1),l=n,p++,p>=r?(h(),void(r>1&&(f=setTimeout(()=>f=null,u)))):void(m=setTimeout(h,u)))}function g(n){let r=s.maxClicks;return clearTimeout(m),f?(clearTimeout(f),void(f=setTimeout(()=>f=null,u))):(a=o(t,e,n.target),a&&a.dataset.hasOwnProperty("quickClick")&&(r=1),a&&"A"===a.tagName&&(r=1),l=n,p++,p>=r?(h(),void(r>1&&(f=setTimeout(()=>f=null,u)))):void(m=setTimeout(h,u)))}return{start:function(){e.active||(window.addEventListener("contextmenu",g),document.addEventListener("click",d),e.active=!0)},stop:function(){e.active&&(window.removeEventListener("contextmenu",g),document.removeEventListener("click",d),e.active=!1,m&&(clearTimeout(m),m=null),f&&(clearTimeout(f),f=null),p=0)}}}(s,m),p=l(s,m);p>0&&f.start();let h={getPrefix:()=>"click",shortcutName:t=>u(t),contextChange:()=>{p=l(s,m),p<1&&f.stop(),p>0&&f.start()},mute:()=>{f.stop()},unmute:()=>f.start(),destroy:()=>f.stop()};return Object.freeze(h),h}function f(t){const e=t.toUpperCase(),n=/FORM\s*\:/i.test(e),o=e.indexOf(":");if(!n)return t;return`FORM:${e.slice(o+1).trim()}`}function p(t,e){const{regex:n,_defaults:o,ev:r}=t,{currentContext:{name:i},shortcuts:s,callbacks:c}=e;let u=[],a=[],l=[];if(null==i)return!1;if(Object.entries(s[i]).forEach(([t,e])=>{n.test(t)&&("FORM:WATCH"===t&&(u=e),"FORM:DEFINE"===t&&(a=e),"FORM:ACTION"===t&&(l=e))}),0===l.length)return!1;let m=new Set;0===a.length&&(a=[o.define]),0===u.length&&(u=[o.watch]);let f=u.map(t=>t()).reduce((t,e)=>(t.push(e),t),[]);return e.watchList=document.querySelectorAll(f),e.watchList.forEach(t=>m.add(a[0](t))),e.typeFn=a[0]?a[0]:o.define,l.forEach(t=>{if(!(t instanceof Function))return console.warn("Warning: The 'form:action' should be a function."),!1;if(!(t()instanceof Array))return console.warn("Warning: The 'form:action' function should RETURN an array."),!1;t().forEach(({fn:t,type:n,timing:o,wait:i=0})=>{if(m.has(n)&&t instanceof Function){let e=`${n}/${o}`;const i=c.hasOwnProperty(e);i?c[e].push(t):c[e]=[t],i||r.on(e,(t,e)=>{e.forEach(e=>{e instanceof Function&&e(t)})})}"instant"===o&&(e.wait[`${n}`]=i)})}),Object.keys(e.callbacks).length>0}const h={watch:()=>"input, select, textarea, button, a",define:t=>"checkbox"===t.type||"radio"===t.type?"checkbox":"button"==t.type||"submit"==t.type?"button":"input"};function d(t,e,n){let{currentContext:o,shortcuts:r}=e,{inAPI:i}=t,s={ev:t.ev,mainDependencies:t,regex:/FORM\s*\:/i,_defaults:h},c={currentContext:o,shortcuts:r,callbacks:{},typeFn:"",watchList:[],wait:{}};i._normalizeWithPlugins(f);let u=function(t,e){const{ev:n}=t;let o=null;function r(t,e,n,o){return{target:n.target,context:e.currentContext.name,note:e.currentContext.note,event:n,dependencies:t.mainDependencies.extra,type:o}}function i(o){const{callbacks:i,typeFn:s}=e,c=s(o.target),u=r(t,e,o,c),a=`${c}/in`;null!=i[a]&&n.emit(a,u,i[a])}function s(o){const{callbacks:i,typeFn:s}=e,c=r(t,e,o,"form-out"),u=`${s(o.target)}/out`;null!=i[u]&&n.emit(u,c,i[u])}function c(i){const{callbacks:s,typeFn:c}=e,u=r(t,e,i,"form-instant"),a=c(i.target),l=e.wait[`${a}`],m=`${a}/instant`;null!=s[m]&&(0!==l?(clearTimeout(o),o=setTimeout(()=>n.emit(m,u,s[m]),l)):n.emit(m,u,s[m]))}return{start:function(){e.active||(document.addEventListener("focusin",i),document.addEventListener("focusout",s),document.addEventListener("input",c),e.active=!0)},stop:function(){e.active&&(document.removeEventListener("focusin",i),document.removeEventListener("focusout",s),document.removeEventListener("input",c),e.active=!1)}}}(s,c);if(o.name){p(s,c)&&u.start()}let a={getPrefix:()=>"form",shortcutName:t=>f(t),contextChange:()=>{c.callbacks={},c.typeFn="",c.watchList=[],c.wait={},p(s,c)?u.start():u.stop()},mute:()=>u.stop(),unmute:()=>u.start(),destroy:()=>{u.stop()}};return Object.freeze(a),a}function g(n={}){let o={},r={};const i=t(),s={currentContext:{name:null,note:null},shortcuts:{},plugins:[],exposeShortcut:!(!n.onShortcut||"function"!=typeof n.onShortcut)&&n.onShortcut,ERROR_EVENT_NAME:n.errorEventName?n.errorEventName:"@shortcuts-error"};let c={ev:i,inAPI:o,API:r,extra:{}};return r.enablePlugin=(t,e={})=>{if("function"!=typeof t)return;let n=t(c,s,e);const r=n.getPrefix();-1===o._systemAction(r,"none")?s.plugins.push(n):n.destroy()},r.disablePlugin=t=>{const e=o._systemAction(t,"destroy");-1!==e&&(s.plugins=s.plugins.filter((t,n)=>n!==e))},r.mutePlugin=t=>o._systemAction(t,"mute"),r.unmutePlugin=t=>o._systemAction(t,"unmute"),r.listPlugins=()=>s.plugins.map(t=>t.getPrefix()),r.getContext=()=>s.currentContext.name,r.getNote=()=>s.currentContext.note,r.setNote=(t=null)=>{"string"!=typeof t&&null!=t||(s.currentContext.note=t)},r.pause=(t="*")=>{let e=o._readShortcutWithPlugins(t);i.stop(e)},r.resume=(t="*")=>{const e=o._readShortcutWithPlugins(t);i.start(e)},r.emit=(t,...e)=>i.emit(o._readShortcutWithPlugins(t),...e),r.listContexts=()=>Object.keys(s.shortcuts),r.setDependencies=t=>c.extra={...c.extra,...t},r.getDependencies=()=>c.extra,r.reset=function(){i.reset(),r.changeContext(),s.plugins.forEach(t=>t.destroy()),r.listContexts().map(t=>r.unload(t)),c.extra={},s.exposeShortcut=null},Object.entries(e).forEach(([t,e])=>{t.startsWith("_")?o[t]=e(c,s):r[t]=e(c,s)}),r}export{m as pluginClick,d as pluginForm,s as pluginKey,g as shortcuts};