@peter.naydenov/shortcuts 2.1.0 → 2.2.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/Changelog.md +13 -0
- package/README.md +2 -0
- package/cypress/fixtures/example.json +5 -0
- package/cypress/support/commands.js +25 -0
- package/cypress/support/component-index.html +14 -0
- package/cypress/support/component.js +27 -0
- package/cypress/support/e2e.js +20 -0
- package/dist/shortcuts.cjs +1 -0
- package/dist/shortcuts.esm.mjs +1 -0
- package/dist/shortcuts.umd.js +1 -0
- package/package.json +33 -20
- package/rollup.config.js +40 -0
package/Changelog.md
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
## Release History
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
|
|
5
|
+
### x.x.x ( 2024-02-?? )( in progress )
|
|
6
|
+
- [ ] New: Load different context during promise execution. Return back when promise resolved. Use it for creation of loading screens and disable shortcuts during loading, then return back to normal; (still in progress);
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### 2.2.0 ( 2024-02-10 )
|
|
11
|
+
- [x] Folder 'dist' was added to the project. Includes commonjs, umd and esm versions of the library;
|
|
12
|
+
- [x] Package.json: "exports" section was added. Allows you to use package as commonjs or es6 module without additional configuration;
|
|
13
|
+
- [x] Rollup was added to the project. Used to build the library versions;
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
4
17
|
### 2.1.0 ( 2023-10-17 )
|
|
5
18
|
- [x] Method `setDependencies` to add more external objects available in all action functions;
|
|
6
19
|
- [x] Method `getDependencies` to look at existing `dependencies` list;
|
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|

|
|
5
|
+

|
|
6
|
+

|
|
5
7
|
|
|
6
8
|
|
|
7
9
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// ***********************************************
|
|
2
|
+
// This example commands.js shows you how to
|
|
3
|
+
// create various custom commands and overwrite
|
|
4
|
+
// existing commands.
|
|
5
|
+
//
|
|
6
|
+
// For more comprehensive examples of custom
|
|
7
|
+
// commands please read more here:
|
|
8
|
+
// https://on.cypress.io/custom-commands
|
|
9
|
+
// ***********************************************
|
|
10
|
+
//
|
|
11
|
+
//
|
|
12
|
+
// -- This is a parent command --
|
|
13
|
+
// Cypress.Commands.add('login', (email, password) => { ... })
|
|
14
|
+
//
|
|
15
|
+
//
|
|
16
|
+
// -- This is a child command --
|
|
17
|
+
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
|
|
18
|
+
//
|
|
19
|
+
//
|
|
20
|
+
// -- This is a dual command --
|
|
21
|
+
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
|
|
22
|
+
//
|
|
23
|
+
//
|
|
24
|
+
// -- This will overwrite an existing command --
|
|
25
|
+
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
6
|
+
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
7
|
+
<title>Components App</title>
|
|
8
|
+
<!-- Used by Next.js to inject CSS. -->
|
|
9
|
+
<div id="__next_css__DO_NOT_USE__"></div>
|
|
10
|
+
</head>
|
|
11
|
+
<body>
|
|
12
|
+
<div data-cy-root></div>
|
|
13
|
+
</body>
|
|
14
|
+
</html>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// ***********************************************************
|
|
2
|
+
// This example support/component.js is processed and
|
|
3
|
+
// loaded automatically before your test files.
|
|
4
|
+
//
|
|
5
|
+
// This is a great place to put global configuration and
|
|
6
|
+
// behavior that modifies Cypress.
|
|
7
|
+
//
|
|
8
|
+
// You can change the location of this file or turn off
|
|
9
|
+
// automatically serving support files with the
|
|
10
|
+
// 'supportFile' configuration option.
|
|
11
|
+
//
|
|
12
|
+
// You can read more here:
|
|
13
|
+
// https://on.cypress.io/configuration
|
|
14
|
+
// ***********************************************************
|
|
15
|
+
|
|
16
|
+
// Import commands.js using ES2015 syntax:
|
|
17
|
+
import './commands'
|
|
18
|
+
|
|
19
|
+
// Alternatively you can use CommonJS syntax:
|
|
20
|
+
// require('./commands')
|
|
21
|
+
|
|
22
|
+
import { mount } from 'cypress/react18'
|
|
23
|
+
|
|
24
|
+
Cypress.Commands.add('mount', mount)
|
|
25
|
+
|
|
26
|
+
// Example use:
|
|
27
|
+
// cy.mount(<MyComponent />)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// ***********************************************************
|
|
2
|
+
// This example support/e2e.js is processed and
|
|
3
|
+
// loaded automatically before your test files.
|
|
4
|
+
//
|
|
5
|
+
// This is a great place to put global configuration and
|
|
6
|
+
// behavior that modifies Cypress.
|
|
7
|
+
//
|
|
8
|
+
// You can change the location of this file or turn off
|
|
9
|
+
// automatically serving support files with the
|
|
10
|
+
// 'supportFile' configuration option.
|
|
11
|
+
//
|
|
12
|
+
// You can read more here:
|
|
13
|
+
// https://on.cypress.io/configuration
|
|
14
|
+
// ***********************************************************
|
|
15
|
+
|
|
16
|
+
// Import commands.js using ES2015 syntax:
|
|
17
|
+
import './commands'
|
|
18
|
+
|
|
19
|
+
// Alternatively you can use CommonJS syntax:
|
|
20
|
+
// require('./commands')
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var e=require("@peter.naydenov/notice");var t={_findTarget:function(e,t){const{listenOptions:{clickTarget:n}}=t;return function e(t){const o=t;return o===document||o===document.body?null:o.dataset[n]||"A"===o.nodeName?o:e(o.parentNode)}},_listen:function(e,t){return function(){const{ev:n,inAPI:{_findTarget:o,_specialChars:r,_readKeyEvent:i,_readMouseEvent:s}}=e,{exposeShortcut:u,currentContext:c,streamKeys:a,listenOptions:l}=t,{mouseWait:m,keyWait:d,clickTarget:p,listenFor:h}=l;let y=[],k=null,f=null,g=null,x=null,T=null,C=!0,F=!1,v=0;const I=()=>C=!1,E=()=>C=!0,S=()=>F=!0,A=()=>!1===C;function O(){let t=y.map((e=>[e.join("+")]));if(!C){let e=t.at(-1);n.emit(e,{wait:I,end:E,ignore:S,isWaiting:A,note:c.note,context:c.name}),F&&(t=t.slice(0,-1),F=!1)}const o={wait:I,end:E,ignore:S,isWaiting:A,note:c.note,context:c.name,dependencies:e.extra};C&&(n.emit(t.join(","),o),u&&u({shortcut:t.join(","),context:c.name,note:c.note,dependencies:e.extra}),y=[],g=null)}function K(){const t=s(f,v),o={target:k,targetProps:k?k.getBoundingClientRect():null,x:f.clientX,y:f.clientY,context:c.name,note:c.note,event:f,dependencies:e.extra};n.emit(t.join("+"),o),u&&u({shortcut:t.join("+"),context:c.name,note:c.note,dependencies:e.extra}),x=null,T=null,k=null,f=null,v=0}h.includes("mouse")&&(window.addEventListener("contextmenu",(e=>{let t=l.maxClicks;return e.preventDefault(),clearTimeout(x),T?(clearTimeout(T),void(T=setTimeout((()=>T=null),m))):(k=o(e.target),k&&k.dataset.hasOwnProperty("quickClick")&&(t=1),k&&"A"===k.tagName&&(t=1),f=e,v++,v>=t?(K(),void(t>1&&(T=setTimeout((()=>T=null),m)))):void(x=setTimeout(K,m)))})),document.addEventListener("click",(e=>{let t=l.maxClicks;return e.preventDefault(),clearTimeout(x),T?(clearTimeout(T),void(T=setTimeout((()=>T=null),m))):(k=o(e.target),k&&k.dataset.hasOwnProperty("quickClick")&&(t=1),k&&"A"===k.tagName&&(t=1),f=e,v++,v>=t?(K(),void(t>1&&(T=setTimeout((()=>T=null),m)))):void(x=setTimeout(K,m)))}))),h.includes("keyboard")&&(document.addEventListener("keydown",(t=>{if(clearTimeout(g),r.hasOwnProperty(t.code))return y.push(i(t,r)),a&&a({key:t.key,context:c.name,note:c.note,dependencies:e.extra}),l.keyIgnore?(clearTimeout(l.keyIgnore),void(l.keyIgnore=setTimeout((()=>l.keyIgnore=null),d))):C&&y.length===l.maxSequence?(O(),void(l.keyIgnore=setTimeout((()=>l.keyIgnore=null),d))):void(C?g=setTimeout(O,d):O())})),document.addEventListener("keypress",(t=>{if(!r.hasOwnProperty(t.code)){if(clearTimeout(g),a&&a({key:t.key,context:c.name,note:c.note,dependencies:e.extra}),l.keyIgnore)return clearTimeout(l.keyIgnore),void(l.keyIgnore=setTimeout((()=>l.keyIgnore=null),d));if(y.push(i(t,r)),C&&y.length===l.maxSequence)return O(),void(l.keyIgnore=setTimeout((()=>l.keyIgnore=null),d));C?g=setTimeout(O,d):O()}})))}},_readKeyEvent:function(){return function(e,t){let{shiftKey:n,altKey:o,ctrlKey:r}=e,i=e.code.replace("Key","").replace("Digit",""),s=[];return r&&s.push("CTRL"),n&&s.push("SHIFT"),o&&s.push("ALT"),t.hasOwnProperty(i)?s.push(t[i].toUpperCase()):["ControlLeft","ControlRight","ShiftLeft","ShiftRight","AltLeft","AltRight","Meta"].includes(i)||s.push(i.toUpperCase()),s.sort()}},_readMouseEvent:function(){return function(e,t){let{shiftKey:n,altKey:o,ctrlKey:r,key:i,button:s}=e,u=`MOUSE-CLICK-${["LEFT","MIDDLE","RIGHT"][s]}-${t}`,c=[];return c.push(u),r&&c.push("CTRL"),n&&c.push("SHIFT"),o&&c.push("ALT"),c.sort()}},_readShortcut:function(){return function(e){return e.split(",").map((e=>e.trim())).map((e=>e.split("+").map((e=>e.toUpperCase())).sort().join("+"))).join(",")}},_specialChars:function(){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"}},changeContext:function(e,t){const{shortcuts:n,listenOptions:o,currentContext:r}=t,{ev:i}=e;return function(e=!1){const t=r.name;if(o.maxSequence=1,o.maxClicks=1,o.keyIgnore>=0&&(clearTimeout(o.keyIgnore),o.keyIgnore=null),!e)return i.reset(),void(r.name=null);t!==e&&(n[e]?(n[t]&&i.reset(),Object.entries(n[e]).forEach((([e,t])=>{if(e.includes("MOUSE-CLICK-")){let[,,,t]=e.split("-"),n=parseInt(t);o.maxClicks<n&&(o.maxClicks=n)}else{let t=e.split(",").length;o.maxSequence<t&&(o.maxSequence=t)}t.forEach((t=>i.on(e,t)))})),r.name=e):i.emit("shortcuts-error",`Context '${e}' does not exist`))}},listShortcuts:function(e,t){const n=t.shortcuts;return function(e=null){if(null!=e){let t=n[e];return null==t?null:Object.entries(t).map((([e,t])=>e))}return Object.keys(n).map((e=>{let t={};return t.context=e,t.shortcuts=Object.entries(n[e]).map((([e,t])=>e)),t}))}},load:function(e,t){const{shortcuts:n}=t,{inAPI:{_readShortcut:o},API:{changeContext:r,getContext:i}}=e;return function(e){const t=i(),s=Object.keys(e);let u=!1;s.forEach((r=>{const i=Object.entries(e[r]);r===t&&(u=!0),n[r]={},i.forEach((([e,t])=>{const i=o(e);t instanceof Function&&(t=[t]),n[r][i]=t}))})),u&&(r(),r(t))}},unload:function(e,t){const{currentContext:n,shortcuts:o}=t,{ev:r}=e;return function(e){n.name!==e?o[e]?delete o[e]:r.emit("shortcuts-error",`Context '${e}' does not exist`):r.emit("shortcuts-error",`Context '${e}' can't be removed during is current active context. Change the context first`)}}};function n(n={}){const o=e(),r={},i={},s={currentContext:{name:null,note:null},shortcuts:{},listenOptions:{mouseWait:n.mouseWait?n.mouseWait:320,maxClicks:1,keyWait:n.keyWait?n.keyWait:480,maxSequence:1,clickTarget:n.clickTarget?n.clickTarget:"click",listenFor:n.listenFor&&Array.isArray(n.listenFor)?n.listenFor:["mouse","keyboard"],keyIgnore:null},exposeShortcut:!(!n.onShortcut||"function"!=typeof n.onShortcut)&&n.onShortcut,streamKeys:!(!n.streamKeys||"function"!=typeof n.streamKeys)&&n.streamKeys},u={ev:o,inAPI:r,API:i,extra:{}};return i.getContext=()=>s.currentContext.name,i.getNote=()=>s.currentContext.note,i.setNote=(e=null)=>{"string"!=typeof e&&null!=e||(s.currentContext.note=e)},i.pause=(e="*")=>o.stop(r._readShortcut(e)),i.resume=(e="*")=>o.start(r._readShortcut(e)),i.emit=(e,...t)=>o.emit(r._readShortcut(e),u.extra,...t),i.listContexts=()=>Object.keys(shortcuts),i.setDependencies=e=>u.extra={...u.extra,...e},i.getDependencies=()=>u.extra,Object.entries(t).forEach((([e,t])=>{e.startsWith("_")?r[e]=t(u,s):i[e]=t(u,s)})),r._listen(),i}n.getDefaults=()=>({mouseWait:320,keyWait:480,clickTarget:"click",listenFor:["mouse","keyboard"],onShortcut:!1,streamKeys:!1}),module.exports=n;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import e from"@peter.naydenov/notice";var t={_findTarget:function(e,t){const{listenOptions:{clickTarget:n}}=t;return function e(t){const o=t;return o===document||o===document.body?null:o.dataset[n]||"A"===o.nodeName?o:e(o.parentNode)}},_listen:function(e,t){return function(){const{ev:n,inAPI:{_findTarget:o,_specialChars:r,_readKeyEvent:i,_readMouseEvent:s}}=e,{exposeShortcut:u,currentContext:c,streamKeys:a,listenOptions:l}=t,{mouseWait:m,keyWait:d,clickTarget:p,listenFor:h}=l;let y=[],k=null,f=null,g=null,x=null,T=null,C=!0,F=!1,v=0;const I=()=>C=!1,E=()=>C=!0,S=()=>F=!0,A=()=>!1===C;function O(){let t=y.map((e=>[e.join("+")]));if(!C){let e=t.at(-1);n.emit(e,{wait:I,end:E,ignore:S,isWaiting:A,note:c.note,context:c.name}),F&&(t=t.slice(0,-1),F=!1)}const o={wait:I,end:E,ignore:S,isWaiting:A,note:c.note,context:c.name,dependencies:e.extra};C&&(n.emit(t.join(","),o),u&&u({shortcut:t.join(","),context:c.name,note:c.note,dependencies:e.extra}),y=[],g=null)}function K(){const t=s(f,v),o={target:k,targetProps:k?k.getBoundingClientRect():null,x:f.clientX,y:f.clientY,context:c.name,note:c.note,event:f,dependencies:e.extra};n.emit(t.join("+"),o),u&&u({shortcut:t.join("+"),context:c.name,note:c.note,dependencies:e.extra}),x=null,T=null,k=null,f=null,v=0}h.includes("mouse")&&(window.addEventListener("contextmenu",(e=>{let t=l.maxClicks;return e.preventDefault(),clearTimeout(x),T?(clearTimeout(T),void(T=setTimeout((()=>T=null),m))):(k=o(e.target),k&&k.dataset.hasOwnProperty("quickClick")&&(t=1),k&&"A"===k.tagName&&(t=1),f=e,v++,v>=t?(K(),void(t>1&&(T=setTimeout((()=>T=null),m)))):void(x=setTimeout(K,m)))})),document.addEventListener("click",(e=>{let t=l.maxClicks;return e.preventDefault(),clearTimeout(x),T?(clearTimeout(T),void(T=setTimeout((()=>T=null),m))):(k=o(e.target),k&&k.dataset.hasOwnProperty("quickClick")&&(t=1),k&&"A"===k.tagName&&(t=1),f=e,v++,v>=t?(K(),void(t>1&&(T=setTimeout((()=>T=null),m)))):void(x=setTimeout(K,m)))}))),h.includes("keyboard")&&(document.addEventListener("keydown",(t=>{if(clearTimeout(g),r.hasOwnProperty(t.code))return y.push(i(t,r)),a&&a({key:t.key,context:c.name,note:c.note,dependencies:e.extra}),l.keyIgnore?(clearTimeout(l.keyIgnore),void(l.keyIgnore=setTimeout((()=>l.keyIgnore=null),d))):C&&y.length===l.maxSequence?(O(),void(l.keyIgnore=setTimeout((()=>l.keyIgnore=null),d))):void(C?g=setTimeout(O,d):O())})),document.addEventListener("keypress",(t=>{if(!r.hasOwnProperty(t.code)){if(clearTimeout(g),a&&a({key:t.key,context:c.name,note:c.note,dependencies:e.extra}),l.keyIgnore)return clearTimeout(l.keyIgnore),void(l.keyIgnore=setTimeout((()=>l.keyIgnore=null),d));if(y.push(i(t,r)),C&&y.length===l.maxSequence)return O(),void(l.keyIgnore=setTimeout((()=>l.keyIgnore=null),d));C?g=setTimeout(O,d):O()}})))}},_readKeyEvent:function(){return function(e,t){let{shiftKey:n,altKey:o,ctrlKey:r}=e,i=e.code.replace("Key","").replace("Digit",""),s=[];return r&&s.push("CTRL"),n&&s.push("SHIFT"),o&&s.push("ALT"),t.hasOwnProperty(i)?s.push(t[i].toUpperCase()):["ControlLeft","ControlRight","ShiftLeft","ShiftRight","AltLeft","AltRight","Meta"].includes(i)||s.push(i.toUpperCase()),s.sort()}},_readMouseEvent:function(){return function(e,t){let{shiftKey:n,altKey:o,ctrlKey:r,key:i,button:s}=e,u=`MOUSE-CLICK-${["LEFT","MIDDLE","RIGHT"][s]}-${t}`,c=[];return c.push(u),r&&c.push("CTRL"),n&&c.push("SHIFT"),o&&c.push("ALT"),c.sort()}},_readShortcut:function(){return function(e){return e.split(",").map((e=>e.trim())).map((e=>e.split("+").map((e=>e.toUpperCase())).sort().join("+"))).join(",")}},_specialChars:function(){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"}},changeContext:function(e,t){const{shortcuts:n,listenOptions:o,currentContext:r}=t,{ev:i}=e;return function(e=!1){const t=r.name;if(o.maxSequence=1,o.maxClicks=1,o.keyIgnore>=0&&(clearTimeout(o.keyIgnore),o.keyIgnore=null),!e)return i.reset(),void(r.name=null);t!==e&&(n[e]?(n[t]&&i.reset(),Object.entries(n[e]).forEach((([e,t])=>{if(e.includes("MOUSE-CLICK-")){let[,,,t]=e.split("-"),n=parseInt(t);o.maxClicks<n&&(o.maxClicks=n)}else{let t=e.split(",").length;o.maxSequence<t&&(o.maxSequence=t)}t.forEach((t=>i.on(e,t)))})),r.name=e):i.emit("shortcuts-error",`Context '${e}' does not exist`))}},listShortcuts:function(e,t){const n=t.shortcuts;return function(e=null){if(null!=e){let t=n[e];return null==t?null:Object.entries(t).map((([e,t])=>e))}return Object.keys(n).map((e=>{let t={};return t.context=e,t.shortcuts=Object.entries(n[e]).map((([e,t])=>e)),t}))}},load:function(e,t){const{shortcuts:n}=t,{inAPI:{_readShortcut:o},API:{changeContext:r,getContext:i}}=e;return function(e){const t=i(),s=Object.keys(e);let u=!1;s.forEach((r=>{const i=Object.entries(e[r]);r===t&&(u=!0),n[r]={},i.forEach((([e,t])=>{const i=o(e);t instanceof Function&&(t=[t]),n[r][i]=t}))})),u&&(r(),r(t))}},unload:function(e,t){const{currentContext:n,shortcuts:o}=t,{ev:r}=e;return function(e){n.name!==e?o[e]?delete o[e]:r.emit("shortcuts-error",`Context '${e}' does not exist`):r.emit("shortcuts-error",`Context '${e}' can't be removed during is current active context. Change the context first`)}}};function n(n={}){const o=e(),r={},i={},s={currentContext:{name:null,note:null},shortcuts:{},listenOptions:{mouseWait:n.mouseWait?n.mouseWait:320,maxClicks:1,keyWait:n.keyWait?n.keyWait:480,maxSequence:1,clickTarget:n.clickTarget?n.clickTarget:"click",listenFor:n.listenFor&&Array.isArray(n.listenFor)?n.listenFor:["mouse","keyboard"],keyIgnore:null},exposeShortcut:!(!n.onShortcut||"function"!=typeof n.onShortcut)&&n.onShortcut,streamKeys:!(!n.streamKeys||"function"!=typeof n.streamKeys)&&n.streamKeys},u={ev:o,inAPI:r,API:i,extra:{}};return i.getContext=()=>s.currentContext.name,i.getNote=()=>s.currentContext.note,i.setNote=(e=null)=>{"string"!=typeof e&&null!=e||(s.currentContext.note=e)},i.pause=(e="*")=>o.stop(r._readShortcut(e)),i.resume=(e="*")=>o.start(r._readShortcut(e)),i.emit=(e,...t)=>o.emit(r._readShortcut(e),u.extra,...t),i.listContexts=()=>Object.keys(shortcuts),i.setDependencies=e=>u.extra={...u.extra,...e},i.getDependencies=()=>u.extra,Object.entries(t).forEach((([e,t])=>{e.startsWith("_")?r[e]=t(u,s):i[e]=t(u,s)})),r._listen(),i}n.getDefaults=()=>({mouseWait:320,keyWait:480,clickTarget:"click",listenFor:["mouse","keyboard"],onShortcut:!1,streamKeys:!1});export{n as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).shortcuts=t()}(this,(function(){"use strict";var e={_findTarget:function(e,t){const{listenOptions:{clickTarget:n}}=t;return function e(t){const o=t;return o===document||o===document.body?null:o.dataset[n]||"A"===o.nodeName?o:e(o.parentNode)}},_listen:function(e,t){return function(){const{ev:n,inAPI:{_findTarget:o,_specialChars:r,_readKeyEvent:i,_readMouseEvent:s}}=e,{exposeShortcut:c,currentContext:u,streamKeys:l,listenOptions:a}=t,{mouseWait:d,keyWait:f,clickTarget:m,listenFor:h}=a;let p=[],g=null,y=null,k=null,x=null,T=null,C=!0,F=!1,E=0;const v=()=>C=!1,I=()=>C=!0,S=()=>F=!0,A=()=>!1===C;function O(){let t=p.map((e=>[e.join("+")]));if(!C){let e=t.at(-1);n.emit(e,{wait:v,end:I,ignore:S,isWaiting:A,note:u.note,context:u.name}),F&&(t=t.slice(0,-1),F=!1)}const o={wait:v,end:I,ignore:S,isWaiting:A,note:u.note,context:u.name,dependencies:e.extra};C&&(n.emit(t.join(","),o),c&&c({shortcut:t.join(","),context:u.name,note:u.note,dependencies:e.extra}),p=[],k=null)}function b(){const t=s(y,E),o={target:g,targetProps:g?g.getBoundingClientRect():null,x:y.clientX,y:y.clientY,context:u.name,note:u.note,event:y,dependencies:e.extra};n.emit(t.join("+"),o),c&&c({shortcut:t.join("+"),context:u.name,note:u.note,dependencies:e.extra}),x=null,T=null,g=null,y=null,E=0}h.includes("mouse")&&(window.addEventListener("contextmenu",(e=>{let t=a.maxClicks;return e.preventDefault(),clearTimeout(x),T?(clearTimeout(T),void(T=setTimeout((()=>T=null),d))):(g=o(e.target),g&&g.dataset.hasOwnProperty("quickClick")&&(t=1),g&&"A"===g.tagName&&(t=1),y=e,E++,E>=t?(b(),void(t>1&&(T=setTimeout((()=>T=null),d)))):void(x=setTimeout(b,d)))})),document.addEventListener("click",(e=>{let t=a.maxClicks;return e.preventDefault(),clearTimeout(x),T?(clearTimeout(T),void(T=setTimeout((()=>T=null),d))):(g=o(e.target),g&&g.dataset.hasOwnProperty("quickClick")&&(t=1),g&&"A"===g.tagName&&(t=1),y=e,E++,E>=t?(b(),void(t>1&&(T=setTimeout((()=>T=null),d)))):void(x=setTimeout(b,d)))}))),h.includes("keyboard")&&(document.addEventListener("keydown",(t=>{if(clearTimeout(k),r.hasOwnProperty(t.code))return p.push(i(t,r)),l&&l({key:t.key,context:u.name,note:u.note,dependencies:e.extra}),a.keyIgnore?(clearTimeout(a.keyIgnore),void(a.keyIgnore=setTimeout((()=>a.keyIgnore=null),f))):C&&p.length===a.maxSequence?(O(),void(a.keyIgnore=setTimeout((()=>a.keyIgnore=null),f))):void(C?k=setTimeout(O,f):O())})),document.addEventListener("keypress",(t=>{if(!r.hasOwnProperty(t.code)){if(clearTimeout(k),l&&l({key:t.key,context:u.name,note:u.note,dependencies:e.extra}),a.keyIgnore)return clearTimeout(a.keyIgnore),void(a.keyIgnore=setTimeout((()=>a.keyIgnore=null),f));if(p.push(i(t,r)),C&&p.length===a.maxSequence)return O(),void(a.keyIgnore=setTimeout((()=>a.keyIgnore=null),f));C?k=setTimeout(O,f):O()}})))}},_readKeyEvent:function(){return function(e,t){let{shiftKey:n,altKey:o,ctrlKey:r}=e,i=e.code.replace("Key","").replace("Digit",""),s=[];return r&&s.push("CTRL"),n&&s.push("SHIFT"),o&&s.push("ALT"),t.hasOwnProperty(i)?s.push(t[i].toUpperCase()):["ControlLeft","ControlRight","ShiftLeft","ShiftRight","AltLeft","AltRight","Meta"].includes(i)||s.push(i.toUpperCase()),s.sort()}},_readMouseEvent:function(){return function(e,t){let{shiftKey:n,altKey:o,ctrlKey:r,key:i,button:s}=e,c=`MOUSE-CLICK-${["LEFT","MIDDLE","RIGHT"][s]}-${t}`,u=[];return u.push(c),r&&u.push("CTRL"),n&&u.push("SHIFT"),o&&u.push("ALT"),u.sort()}},_readShortcut:function(){return function(e){return e.split(",").map((e=>e.trim())).map((e=>e.split("+").map((e=>e.toUpperCase())).sort().join("+"))).join(",")}},_specialChars:function(){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"}},changeContext:function(e,t){const{shortcuts:n,listenOptions:o,currentContext:r}=t,{ev:i}=e;return function(e=!1){const t=r.name;if(o.maxSequence=1,o.maxClicks=1,o.keyIgnore>=0&&(clearTimeout(o.keyIgnore),o.keyIgnore=null),!e)return i.reset(),void(r.name=null);t!==e&&(n[e]?(n[t]&&i.reset(),Object.entries(n[e]).forEach((([e,t])=>{if(e.includes("MOUSE-CLICK-")){let[,,,t]=e.split("-"),n=parseInt(t);o.maxClicks<n&&(o.maxClicks=n)}else{let t=e.split(",").length;o.maxSequence<t&&(o.maxSequence=t)}t.forEach((t=>i.on(e,t)))})),r.name=e):i.emit("shortcuts-error",`Context '${e}' does not exist`))}},listShortcuts:function(e,t){const n=t.shortcuts;return function(e=null){if(null!=e){let t=n[e];return null==t?null:Object.entries(t).map((([e,t])=>e))}return Object.keys(n).map((e=>{let t={};return t.context=e,t.shortcuts=Object.entries(n[e]).map((([e,t])=>e)),t}))}},load:function(e,t){const{shortcuts:n}=t,{inAPI:{_readShortcut:o},API:{changeContext:r,getContext:i}}=e;return function(e){const t=i(),s=Object.keys(e);let c=!1;s.forEach((r=>{const i=Object.entries(e[r]);r===t&&(c=!0),n[r]={},i.forEach((([e,t])=>{const i=o(e);t instanceof Function&&(t=[t]),n[r][i]=t}))})),c&&(r(),r(t))}},unload:function(e,t){const{currentContext:n,shortcuts:o}=t,{ev:r}=e;return function(e){n.name!==e?o[e]?delete o[e]:r.emit("shortcuts-error",`Context '${e}' does not exist`):r.emit("shortcuts-error",`Context '${e}' can't be removed during is current active context. Change the context first`)}}};function t(t={}){const n=new function(){let e={"*":[]},t={},n=[],o=!1,r="";return{on:function(t,n){e[t]||(e[t]=[]),e[t].push(n)},once:function(e,n){"*"!==e&&(t[e]||(t[e]=[]),t[e].push(n))},off:function(n,o){if(o)return e[n]&&(e[n]=e[n].filter((e=>e!==o))),t[n]&&(t[n]=t[n].filter((e=>e!==o))),e[n]&&0===e[n].length&&delete e[n],void(t[n]&&0===t[n].length&&delete e[n]);t[n]&&delete t[n],e[n]&&delete e[n]},reset:function(){e={"*":[]},t={},n=[]},emit:function(){const[i,...s]=arguments;function c(t){"*"!==t&&(n.includes(t)||(e[t].forEach((e=>e(...s))),e["*"].forEach((e=>e(i,...s)))))}if(o&&(console.log(`${r} Event "${i}" was triggered.`),s.length>0&&(console.log("Arguments:"),console.log(...s),console.log("^----"))),"*"!==i){if(t[i]){if(n.includes(i))return;t[i].forEach((e=>e(...s))),delete t[i]}e[i]&&c(i)}else Object.keys(e).forEach((e=>c(e)))},stop:function(o){if("*"!==o)n.push(o);else{const o=Object.keys(e),r=Object.keys(t);n=[...r,...o]}},start:function(e){n="*"!==e?n.filter((t=>e!=t)):[]},debug:function(e,t){o=!!e,t&&"string"==typeof t&&(r=t)}}},o={},r={},i={currentContext:{name:null,note:null},shortcuts:{},listenOptions:{mouseWait:t.mouseWait?t.mouseWait:320,maxClicks:1,keyWait:t.keyWait?t.keyWait:480,maxSequence:1,clickTarget:t.clickTarget?t.clickTarget:"click",listenFor:t.listenFor&&Array.isArray(t.listenFor)?t.listenFor:["mouse","keyboard"],keyIgnore:null},exposeShortcut:!(!t.onShortcut||"function"!=typeof t.onShortcut)&&t.onShortcut,streamKeys:!(!t.streamKeys||"function"!=typeof t.streamKeys)&&t.streamKeys},s={ev:n,inAPI:o,API:r,extra:{}};return r.getContext=()=>i.currentContext.name,r.getNote=()=>i.currentContext.note,r.setNote=(e=null)=>{"string"!=typeof e&&null!=e||(i.currentContext.note=e)},r.pause=(e="*")=>n.stop(o._readShortcut(e)),r.resume=(e="*")=>n.start(o._readShortcut(e)),r.emit=(e,...t)=>n.emit(o._readShortcut(e),s.extra,...t),r.listContexts=()=>Object.keys(shortcuts),r.setDependencies=e=>s.extra={...s.extra,...e},r.getDependencies=()=>s.extra,Object.entries(e).forEach((([e,t])=>{e.startsWith("_")?o[e]=t(s,i):r[e]=t(s,i)})),o._listen(),r}return t.getDefaults=()=>({mouseWait:320,keyWait:480,clickTarget:"click",listenFor:["mouse","keyboard"],onShortcut:!1,streamKeys:!1}),t}));
|
package/package.json
CHANGED
|
@@ -1,38 +1,51 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peter.naydenov/shortcuts",
|
|
3
|
-
"version": "2.1.0",
|
|
4
3
|
"description": "Context control of shortcuts based on keyboard and mouse events",
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"mouse",
|
|
10
|
-
"click"
|
|
11
|
-
],
|
|
12
|
-
"main": "src/main.js",
|
|
4
|
+
"version": "2.2.0",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Peter Naydenov",
|
|
7
|
+
"main": "./dist/shortcuts.umd.js",
|
|
13
8
|
"type": "module",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/shortcuts.esm.mjs",
|
|
12
|
+
"require": "./dist/shortcuts.cjs",
|
|
13
|
+
"default": "./dist/shortcuts.umd.js"
|
|
14
|
+
},
|
|
15
|
+
"./package.json": "./package.json",
|
|
16
|
+
"./dist/*": "./dist/*",
|
|
17
|
+
"./src/*": "./src/*"
|
|
18
|
+
},
|
|
14
19
|
"scripts": {
|
|
15
20
|
"dev": "vite",
|
|
16
|
-
"build": "
|
|
17
|
-
"test": "cypress
|
|
21
|
+
"build": "rollup -c",
|
|
22
|
+
"test": "cypress run --component --browser chrome test"
|
|
18
23
|
},
|
|
19
24
|
"repository": {
|
|
20
25
|
"type": "git",
|
|
21
26
|
"url": "git+https://github.com/PeterNaydenov/shortcuts"
|
|
22
27
|
},
|
|
23
28
|
"dependencies": {
|
|
24
|
-
"@peter.naydenov/notice": "^2.2.
|
|
29
|
+
"@peter.naydenov/notice": "^2.2.3"
|
|
25
30
|
},
|
|
26
31
|
"devDependencies": {
|
|
27
|
-
"@
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
+
"@rollup/plugin-commonjs": "^25.0.7",
|
|
33
|
+
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
34
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
35
|
+
"@vitejs/plugin-react": "^4.2.1",
|
|
36
|
+
"ask-for-promise": "^2.0.3",
|
|
37
|
+
"chai": "^5.0.3",
|
|
38
|
+
"cypress": "^13.6.4",
|
|
39
|
+
"mocha": "^10.3.0",
|
|
32
40
|
"react": "^18.2.0",
|
|
33
41
|
"react-dom": "^18.2.0",
|
|
34
|
-
"vite": "^
|
|
42
|
+
"vite": "^5.1.1"
|
|
35
43
|
},
|
|
36
|
-
"
|
|
37
|
-
|
|
44
|
+
"keywords": [
|
|
45
|
+
"shortcut",
|
|
46
|
+
"key",
|
|
47
|
+
"keyboard",
|
|
48
|
+
"mouse",
|
|
49
|
+
"click"
|
|
50
|
+
]
|
|
38
51
|
}
|
package/rollup.config.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import resolve from '@rollup/plugin-node-resolve'
|
|
2
|
+
import commonjs from '@rollup/plugin-commonjs'
|
|
3
|
+
import terser from '@rollup/plugin-terser';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export default [
|
|
7
|
+
// browser-friendly UMD build
|
|
8
|
+
{
|
|
9
|
+
input: 'src/main.js',
|
|
10
|
+
output: {
|
|
11
|
+
name: 'shortcuts',
|
|
12
|
+
file: 'dist/shortcuts.umd.js',
|
|
13
|
+
format: 'umd',
|
|
14
|
+
globals : {
|
|
15
|
+
'@peter.naydenov/notice': 'notice'
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
plugins: [
|
|
19
|
+
resolve(), // so Rollup can find `ms`
|
|
20
|
+
commonjs() // so Rollup can convert `ms` to an ES module
|
|
21
|
+
, terser()
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
// CommonJS (for Node) and ES module (for bundlers) build.
|
|
26
|
+
// (We could have three entries in the configuration array
|
|
27
|
+
// instead of two, but it's quicker to generate multiple
|
|
28
|
+
// builds from a single configuration where possible, using
|
|
29
|
+
// an array for the `output` option, where we can specify
|
|
30
|
+
// `file` and `format` for each target)
|
|
31
|
+
{
|
|
32
|
+
input: 'src/main.js',
|
|
33
|
+
external: ['@peter.naydenov/notice'],
|
|
34
|
+
output: [
|
|
35
|
+
{ file: 'dist/shortcuts.cjs' , format: 'cjs' },
|
|
36
|
+
{ file: 'dist/shortcuts.esm.mjs', format: 'es' }
|
|
37
|
+
],
|
|
38
|
+
plugins: [ terser() ]
|
|
39
|
+
}
|
|
40
|
+
];
|