@peter.naydenov/cuts 2.1.1 → 2.1.2
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/.claude/settings.local.json +10 -0
- package/Changelog.md +11 -0
- package/dist/cuts.cjs +1 -1
- package/dist/cuts.esm.mjs +1 -1
- package/dist/cuts.umd.js +1 -1
- package/package.json +1 -1
- package/src/main.js +8 -3
- package/src/methods/hide.js +16 -16
- package/src/methods/listShortcuts.js +1 -1
- package/src/methods/show.js +14 -5
- package/test/02-cuts.test.js +169 -0
- package/types/main.d.ts +1 -1
- package/types/main.d.ts.map +1 -1
- package/types/methods/show.d.ts.map +1 -1
package/Changelog.md
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## 2.1.2 ( 2026-07-09 )
|
|
5
|
+
- [x] Fix: `show()` crashed when a scene with `parents: ['*']` was the very first scene shown (`state.currentParents` was read before being initialized);
|
|
6
|
+
- [x] Fix: `hide()` (including `hide('*')` and multi-step `hide(n)`) left `currentScene`/`currentParents` stale instead of updating them as each parent scene was closed;
|
|
7
|
+
- [x] Fix: `listShortcuts()` still excluded the old `beforeUnload`/`afterLoad` property names, so the current `beforeHide`/`afterShow` scene methods leaked into the returned shortcuts list;
|
|
8
|
+
- [x] Fix: `@app-error` handlers received a `{ dependencies, type: 'custom' }` context object instead of the log entry, because `@peter.naydenov/shortcuts` v4.1.x's `emit()` now injects that context ahead of the forwarded arguments. Cuts now emits through the raw (unwrapped) emitter for its internal error event;
|
|
9
|
+
- [x] Fix: `script.emit()` had the same issue - listeners now receive exactly the arguments passed to `emit()`, with no injected context object;
|
|
10
|
+
- [x] Fix: showing a wildcard-overlay scene (`parents: ['*']`) never switched the shortcuts context to it, so the overlay's own shortcut and event handlers never fired;
|
|
11
|
+
- [x] Fix: showing a wildcard-overlay scene aliased `state.currentParents` to the underlying scene's own `parents` array; pushing onto it permanently corrupted that scene's `parents` definition and crashed later navigation back to it;
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
4
15
|
## 2.1.1 ( 2026-07-08 )
|
|
5
16
|
- [x] Dependency update. @peter.naydenov/shortcuts - v.4.1.2
|
|
6
17
|
- [x] (fixes TypeScript declaration emit for `PluginAPI` and `ShortcutsAPI`);
|
package/dist/cuts.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("@peter.naydenov/shortcuts"),n=require("ask-for-promise"),r=require("@peter.naydenov/log");function*t(e,n,r,t){let s=null,o=!0;if(null===e)return yield*t.map(e=>[e,"show"]),void(yield[r,"show"]);if(0!==t.length){if(t.includes(e)){for(let n=t.indexOf(e)+1;n<t.length;n++)yield[t[n],"show"];return void(yield[r,"show"])}if(!n)return yield[e,"hide"],void(yield*t.map(e=>[e,"show"]));if(t.every((e,r)=>n[r]===t[r]&&(s=r,!0)),null==s)return yield[e,"hide"],n.reverse(),yield*n.map(e=>[e,"hide"]),yield*t.map(e=>[e,"show"]),void(yield[r,"show"]);yield[e,"hide"];for(let e=n.length;e>s+1;e--)yield[n[e-1],"hide"];for(let e=s+1;e<t.length;e++)yield[t[e],"show"];yield[r,"show"]}else{if(yield[e,"hide"],n.includes(r)){let e=n.indexOf(r),t=n.filter((n,r)=>r>e);t.reverse(),yield*t.map(e=>[e,"hide"]),o=!1}else{let e=[...n];e.reverse(),yield*e.map(e=>[e,"hide"])}o&&(yield[r,"show"])}}function s(e){return function(n,...r){const{askForPromise:t,deps:s}=e;return function(){const e=t();return n({task:e,dependencies:s()},...r),e.promise}}}module.exports=function(o={logLevel:0}){const c=e.shortcuts({errorEventName:"@app-error"}),i=o.logLevel||1,u=r({level:i},e=>{const{type:n}=e;"error"===n&&c.emit("@app-error",e)}),l={currentScene:null,currentParents:null,sceneNames:new Set,scenes:{},opened:!1,jumpStack:[]},
|
|
1
|
+
"use strict";var e=require("@peter.naydenov/shortcuts"),n=require("ask-for-promise"),r=require("@peter.naydenov/log");function*t(e,n,r,t){let s=null,o=!0;if(null===e)return yield*t.map(e=>[e,"show"]),void(yield[r,"show"]);if(0!==t.length){if(t.includes(e)){for(let n=t.indexOf(e)+1;n<t.length;n++)yield[t[n],"show"];return void(yield[r,"show"])}if(!n)return yield[e,"hide"],void(yield*t.map(e=>[e,"show"]));if(t.every((e,r)=>n[r]===t[r]&&(s=r,!0)),null==s)return yield[e,"hide"],n.reverse(),yield*n.map(e=>[e,"hide"]),yield*t.map(e=>[e,"show"]),void(yield[r,"show"]);yield[e,"hide"];for(let e=n.length;e>s+1;e--)yield[n[e-1],"hide"];for(let e=s+1;e<t.length;e++)yield[t[e],"show"];yield[r,"show"]}else{if(yield[e,"hide"],n.includes(r)){let e=n.indexOf(r),t=n.filter((n,r)=>r>e);t.reverse(),yield*t.map(e=>[e,"hide"]),o=!1}else{let e=[...n];e.reverse(),yield*e.map(e=>[e,"hide"])}o&&(yield[r,"show"])}}function s(e){return function(n,...r){const{askForPromise:t,deps:s}=e;return function(){const e=t();return n({task:e,dependencies:s()},...r),e.promise}}}module.exports=function(o={logLevel:0}){const c=e.shortcuts({errorEventName:"@app-error"}),i=o.logLevel||1,u=r({level:i},e=>{const{type:n}=e;"error"===n&&c.getDependencies().emit("@app-error",e)}),l={currentScene:null,currentParents:null,sceneNames:new Set,scenes:{},opened:!1,jumpStack:[]},a={},d={shortcutMngr:c,findInstructions:t,askForPromise:n,setInstruction:s({askForPromise:n,deps:c.getDependencies}),log:u};return a.hide=function(e,n){return function(r=1){const{askForPromise:t,shortcutMngr:s,setInstruction:o}=e,{currentScene:c,currentParents:i,scenes:u}=n,l=t(),a=[],d=i.length>0;s.pause(),a.push(o(u[c].hide)),d||(n.currentScene=null);let p=[];return d&&"*"===r&&(p=[...i].reverse()),d&&!["*",1].includes(r)&&(p=i.slice("-"+(r-1)).reverse()),p.forEach(e=>{a.push(o(u[e].hide)),n.currentScene=u[e].parents.at(-1)??null,n.currentParents=n.currentScene?u[n.currentScene].parents:[]}),t.sequence(a).onComplete(()=>{s.changeContext(n.currentScene),l.done()}),l.promise}}(d,l),a.listShortcuts=function(e,n){return function(e){const{scenes:r,sceneNames:t}=n;if(!t.has(e))return null;const{show:s,hide:o,parents:c,beforeHide:i,afterShow:u,...l}=r[e];return Object.keys(l)}}(0,l),a.setScenes=function(e,n){return function(r){const{shortcutMngr:t,log:s}=e;r.forEach(e=>{if(null==e)return;const{name:r,scene:o}=e;if(!r)return void s({message:"Scene name is not defined",level:1,type:"error"});if(null==o)return void s({message:`Scene ${r} is not defined`,level:1,type:"error"});o.parents||(o.parents=[]),n.scenes[r]=o,n.sceneNames.add(r);const{show:c,hide:i,parents:u,...l}=o,a={};a[r]=l,t.load(a)})}}(d,l),a.show=function(e,n){return function({scene:r,options:t={ssr:!1}},...s){const{shortcutMngr:o,askForPromise:c,log:i,findInstructions:u,setInstruction:l}=e,a=c(),d=c(),{opened:p,scenes:f,sceneNames:h,currentScene:m}=n;return m&&"function"==typeof f[m].beforeHide?(0,f[m].beforeHide)({done:d.done,dependencies:o.getDependencies()}):d.done(!0),d.onComplete(e=>{if(!e)return a.done(),a.promise;if(!h.has(r))return i({message:`Scene "${r}" is not available.`,level:1,type:"error"}),a.done(),a.promise;if(!p&&t.ssr)return n.opened=!0,n.currentScene=r,o.changeContext(r),a.done(),a.promise;const{show:d,parents:m=[]}=f[r];if(n.currentParents||(n.currentParents=[]),"*"===m[0])return l(d,...s)().then(()=>a.done()),n.currentParents.push(n.currentScene),n.currentScene=r,o.changeContext(r),a.promise;if(0!==m.length&&!m.every(e=>h.has(e)))return i({message:`Some of '${r}' parent scenes are not set.`,level:1,type:"error"}),a.done(),a.promise;function g([e,r]){if("show"===r)n.currentScene&&(n.currentParents=[...f[n.currentScene].parents]),n.currentScene=e;else{let r="*"===f[e].parents[0]?n.currentParents.pop():f[e].parents.at(-1);n.currentScene=r}return f[e][r]}const S=u(n.currentScene,n.currentParents,r,m),y=[];for(let e of S){const n=g(e);y.push(l(n,...s))}c.sequence(y).onComplete(()=>{n.opened=!0,n.currentScene=r,n.currentParents=f[r].parents?[...f[r].parents]:null,o.changeContext(r),"function"==typeof f[r].afterShow&&f[r].afterShow({dependencies:o.getDependencies(),done:()=>{}}),a.done()})}),a.promise}}(d,l),a.jump=function(e,n){return function({scene:r},...t){return e.jumpStack.push(e.currentScene),n({scene:r},...t)}}(l,a.show),a.jumpBack=function(e,n){return function({hops:r}={hops:1},...t){for(let n=0;n<r-1;n++)e.jumpStack.pop();if(0===e.jumpStack.length)return;const s=e.jumpStack.pop();return n({scene:s},...t)}}(l,a.show),a.jumpsReset=function(e){return function(){e.jumpStack=[]}}(l),a.loadPlugins=async function(e){const n=e.map(e=>`plugin${e}`),r=await import("@peter.naydenov/shortcuts");return n.map(e=>r[e])},a.setDependencies=e=>c.setDependencies(e),a.getDependencies=()=>c.getDependencies(),a.setNote=e=>c.setNote(e),a.listScenes=()=>[...l.sceneNames],a.enablePlugin=(e,n)=>c.enablePlugin(e,n),a.disablePlugin=e=>c.disablePlugin(e),a.getState=()=>({scene:l.currentScene,parents:l.currentParents,opened:l.opened}),a.emit=(e,...n)=>c.getDependencies().emit(e,...n),a};
|
package/dist/cuts.esm.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{shortcuts as e}from"@peter.naydenov/shortcuts";import n from"ask-for-promise";import r from"@peter.naydenov/log";function*t(e,n,r,t){let s=null,o=!0;if(null===e)return yield*t.map(e=>[e,"show"]),void(yield[r,"show"]);if(0!==t.length){if(t.includes(e)){for(let n=t.indexOf(e)+1;n<t.length;n++)yield[t[n],"show"];return void(yield[r,"show"])}if(!n)return yield[e,"hide"],void(yield*t.map(e=>[e,"show"]));if(t.every((e,r)=>n[r]===t[r]&&(s=r,!0)),null==s)return yield[e,"hide"],n.reverse(),yield*n.map(e=>[e,"hide"]),yield*t.map(e=>[e,"show"]),void(yield[r,"show"]);yield[e,"hide"];for(let e=n.length;e>s+1;e--)yield[n[e-1],"hide"];for(let e=s+1;e<t.length;e++)yield[t[e],"show"];yield[r,"show"]}else{if(yield[e,"hide"],n.includes(r)){let e=n.indexOf(r),t=n.filter((n,r)=>r>e);t.reverse(),yield*t.map(e=>[e,"hide"]),o=!1}else{let e=[...n];e.reverse(),yield*e.map(e=>[e,"hide"])}o&&(yield[r,"show"])}}function s(e){return function(n,...r){const{askForPromise:t,deps:s}=e;return function(){const e=t();return n({task:e,dependencies:s()},...r),e.promise}}}function o(o={logLevel:0}){const c=e({errorEventName:"@app-error"}),i=o.logLevel||1,u=r({level:i},e=>{const{type:n}=e;"error"===n&&c.emit("@app-error",e)}),l={currentScene:null,currentParents:null,sceneNames:new Set,scenes:{},opened:!1,jumpStack:[]},
|
|
1
|
+
import{shortcuts as e}from"@peter.naydenov/shortcuts";import n from"ask-for-promise";import r from"@peter.naydenov/log";function*t(e,n,r,t){let s=null,o=!0;if(null===e)return yield*t.map(e=>[e,"show"]),void(yield[r,"show"]);if(0!==t.length){if(t.includes(e)){for(let n=t.indexOf(e)+1;n<t.length;n++)yield[t[n],"show"];return void(yield[r,"show"])}if(!n)return yield[e,"hide"],void(yield*t.map(e=>[e,"show"]));if(t.every((e,r)=>n[r]===t[r]&&(s=r,!0)),null==s)return yield[e,"hide"],n.reverse(),yield*n.map(e=>[e,"hide"]),yield*t.map(e=>[e,"show"]),void(yield[r,"show"]);yield[e,"hide"];for(let e=n.length;e>s+1;e--)yield[n[e-1],"hide"];for(let e=s+1;e<t.length;e++)yield[t[e],"show"];yield[r,"show"]}else{if(yield[e,"hide"],n.includes(r)){let e=n.indexOf(r),t=n.filter((n,r)=>r>e);t.reverse(),yield*t.map(e=>[e,"hide"]),o=!1}else{let e=[...n];e.reverse(),yield*e.map(e=>[e,"hide"])}o&&(yield[r,"show"])}}function s(e){return function(n,...r){const{askForPromise:t,deps:s}=e;return function(){const e=t();return n({task:e,dependencies:s()},...r),e.promise}}}function o(o={logLevel:0}){const c=e({errorEventName:"@app-error"}),i=o.logLevel||1,u=r({level:i},e=>{const{type:n}=e;"error"===n&&c.getDependencies().emit("@app-error",e)}),l={currentScene:null,currentParents:null,sceneNames:new Set,scenes:{},opened:!1,jumpStack:[]},p={},a={shortcutMngr:c,findInstructions:t,askForPromise:n,setInstruction:s({askForPromise:n,deps:c.getDependencies}),log:u};return p.hide=function(e,n){return function(r=1){const{askForPromise:t,shortcutMngr:s,setInstruction:o}=e,{currentScene:c,currentParents:i,scenes:u}=n,l=t(),p=[],a=i.length>0;s.pause(),p.push(o(u[c].hide)),a||(n.currentScene=null);let d=[];return a&&"*"===r&&(d=[...i].reverse()),a&&!["*",1].includes(r)&&(d=i.slice("-"+(r-1)).reverse()),d.forEach(e=>{p.push(o(u[e].hide)),n.currentScene=u[e].parents.at(-1)??null,n.currentParents=n.currentScene?u[n.currentScene].parents:[]}),t.sequence(p).onComplete(()=>{s.changeContext(n.currentScene),l.done()}),l.promise}}(a,l),p.listShortcuts=function(e,n){return function(e){const{scenes:r,sceneNames:t}=n;if(!t.has(e))return null;const{show:s,hide:o,parents:c,beforeHide:i,afterShow:u,...l}=r[e];return Object.keys(l)}}(0,l),p.setScenes=function(e,n){return function(r){const{shortcutMngr:t,log:s}=e;r.forEach(e=>{if(null==e)return;const{name:r,scene:o}=e;if(!r)return void s({message:"Scene name is not defined",level:1,type:"error"});if(null==o)return void s({message:`Scene ${r} is not defined`,level:1,type:"error"});o.parents||(o.parents=[]),n.scenes[r]=o,n.sceneNames.add(r);const{show:c,hide:i,parents:u,...l}=o,p={};p[r]=l,t.load(p)})}}(a,l),p.show=function(e,n){return function({scene:r,options:t={ssr:!1}},...s){const{shortcutMngr:o,askForPromise:c,log:i,findInstructions:u,setInstruction:l}=e,p=c(),a=c(),{opened:d,scenes:f,sceneNames:h,currentScene:m}=n;return m&&"function"==typeof f[m].beforeHide?(0,f[m].beforeHide)({done:a.done,dependencies:o.getDependencies()}):a.done(!0),a.onComplete(e=>{if(!e)return p.done(),p.promise;if(!h.has(r))return i({message:`Scene "${r}" is not available.`,level:1,type:"error"}),p.done(),p.promise;if(!d&&t.ssr)return n.opened=!0,n.currentScene=r,o.changeContext(r),p.done(),p.promise;const{show:a,parents:m=[]}=f[r];if(n.currentParents||(n.currentParents=[]),"*"===m[0])return l(a,...s)().then(()=>p.done()),n.currentParents.push(n.currentScene),n.currentScene=r,o.changeContext(r),p.promise;if(0!==m.length&&!m.every(e=>h.has(e)))return i({message:`Some of '${r}' parent scenes are not set.`,level:1,type:"error"}),p.done(),p.promise;function g([e,r]){if("show"===r)n.currentScene&&(n.currentParents=[...f[n.currentScene].parents]),n.currentScene=e;else{let r="*"===f[e].parents[0]?n.currentParents.pop():f[e].parents.at(-1);n.currentScene=r}return f[e][r]}const S=u(n.currentScene,n.currentParents,r,m),y=[];for(let e of S){const n=g(e);y.push(l(n,...s))}c.sequence(y).onComplete(()=>{n.opened=!0,n.currentScene=r,n.currentParents=f[r].parents?[...f[r].parents]:null,o.changeContext(r),"function"==typeof f[r].afterShow&&f[r].afterShow({dependencies:o.getDependencies(),done:()=>{}}),p.done()})}),p.promise}}(a,l),p.jump=function(e,n){return function({scene:r},...t){return e.jumpStack.push(e.currentScene),n({scene:r},...t)}}(l,p.show),p.jumpBack=function(e,n){return function({hops:r}={hops:1},...t){for(let n=0;n<r-1;n++)e.jumpStack.pop();if(0===e.jumpStack.length)return;const s=e.jumpStack.pop();return n({scene:s},...t)}}(l,p.show),p.jumpsReset=function(e){return function(){e.jumpStack=[]}}(l),p.loadPlugins=async function(e){const n=e.map(e=>`plugin${e}`),r=await import("@peter.naydenov/shortcuts");return n.map(e=>r[e])},p.setDependencies=e=>c.setDependencies(e),p.getDependencies=()=>c.getDependencies(),p.setNote=e=>c.setNote(e),p.listScenes=()=>[...l.sceneNames],p.enablePlugin=(e,n)=>c.enablePlugin(e,n),p.disablePlugin=e=>c.disablePlugin(e),p.getState=()=>({scene:l.currentScene,parents:l.currentParents,opened:l.opened}),p.emit=(e,...n)=>c.getDependencies().emit(e,...n),p}export{o as default};
|
package/dist/cuts.umd.js
CHANGED
|
@@ -1 +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).cuts=t()}(this,function(){"use strict";var e={_normalizeWithPlugins:function(e,t){return function(e){const n=t.shortcuts;Object.keys(n).forEach(t=>{Object.entries(n[t]).forEach(([o,i])=>{const r=e(o);r!==o&&(delete n[t][o],n[t][r]=i)})})}},_readShortcutWithPlugins:function(e,t){return function(n){const{inAPI:o}=e,i=n.split(":")[0].toLowerCase().trim(),r=o._systemAction(i,"none");let s=n;return-1!==r&&(s=t.plugins[r].shortcutName(n)),s}},_setupPlugin:function(e,t){const{inAPI:n}=e,{currentContext:o,shortcuts:i,exposeShortcut:r,ERROR_EVENT_NAME:s}=t;return function(t){const{prefix:c,_normalizeShortcutName:u,_registerShortcutEvents:l,_listenDOM:a,pluginState:d,deps:p}=t,{resetState:f}=p;d.currentContext=o,d.shortcuts=i,d.exposeShortcut=r,d.ERROR_EVENT_NAME=s;const h={ev:e.ev,extra:e.extra,...p};n._normalizeWithPlugins(u);let m=l(h,d);const g=a(h,d);m>0&&g.start();const v={getPrefix:()=>c,shortcutName:e=>u(e),contextChange:()=>{f(),m=l(h,d),m<1&&g.stop(),m>0&&g.start()},mute:()=>g.stop(),unmute:()=>g.start(),destroy:()=>{g.stop(),f()}};return Object.freeze(v),v}},_systemAction:function(e,t){return function(e,n,o=null){return t.plugins.findIndex(t=>t.getPrefix()===e&&(t[n]&&t[n](o),!0))}},changeContext:function(e,t){const{shortcuts:n,currentContext:o,ERROR_EVENT_NAME:i}=t,{ev:r}=e;return function(e=!1){const s=o.name;if(!e)return r.reset(),void(o.name=null);s!==e&&(n[e]?(n[s]&&r.reset(),o.name=e,t.plugins.forEach(t=>t.contextChange(e)),Object.entries(n[e]).forEach(([e,t])=>{e.includes(":SETUP")||t.forEach(t=>r.on(e,t))}),r.on("*",(...e)=>{t.exposeShortcut&&t.exposeShortcut(...e)})):r.emit(i,`Context '${e}' does not exist`))}},listShortcuts:function(e,t){const n=t.shortcuts;return function(e=null){if(null!=e){const t=n[e];return null==t?null:Object.entries(t).map(([e,t])=>e)}return Object.keys(n).map(e=>{const t={};return t.context=e,t.shortcuts=Object.entries(n[e]).map(([e,t])=>e),t})}},load:function(e,t){const{shortcuts:n,plugins:o}=t,{API:{changeContext:i,getContext:r}}=e;return function(e){const t=r(),s=o.map(e=>e.getPrefix().toUpperCase());let c=!1;Object.entries(e).forEach(([e,i])=>{e===t&&(c=!0),n[e]={},Object.entries(i).forEach(([t,i])=>{let r=t;const c=t.toUpperCase().trim(),u=s.map((e,t)=>c.startsWith(e)?t:null).filter(e=>null!==e);if(u.length){const e=u[0];r=o[e].shortcutName(t)}i instanceof Function&&(i=[i]),n[e][r]=i})}),c&&(i(),i(t))}},unload:function(e,t){const{currentContext:n,shortcuts:o,ERROR_EVENT_NAME:i}=t,{ev:r}=e;return function(e){n.name!==e?o[e]?delete o[e]:r.emit(i,`Context '${e}' does not exist`):r.emit(i,`Context '${e}' can't be removed during is current active context. Change the context first`)}}};function t(e,t){const{ev:n,_specialChars:o,_readKeyEvent:i,extra:r,resetState:s}=e,{currentContext:c,streamKeys:u,listenOptions:l}=t;let a=[],d=null,p=!0,f=!1;const h=()=>p=!1,m=()=>p=!0,g=()=>f=!0,v=()=>!1===p;function y(){const e=a.map(e=>[e.join("+")]),o={wait:h,end:m,ignore:g,isWaiting:v,note:c.note,context:c.name,dependencies:r,options:t.listenOptions,viewport:{X:window.scrollX,Y:window.scrollY,width:window.innerWidth,height:window.innerHeight},type:"key"};if(!p){const t=`KEY:${e.at(-1).join("+")}`;n.emit(t,o),f&&(a=a.slice(0,-1),f=!1)}if(p){const i=`KEY:${e.join(",")}`;n.emit(i,o),f&&(a=a.slice(0,-1),f=!1),a=[],clearTimeout(t.keyIgnore),t.keyIgnore=null,clearTimeout(d),d=null}}function w(n){if(clearTimeout(d),o().hasOwnProperty(n.code))return a.push(i(n,o)),u&&u({key:n.key,context:c.name,note:c.note,dependencies:e.extra}),t.keyIgnore?(clearTimeout(t.keyIgnore),t.keyIgnore=setTimeout(()=>t.keyIgnore=null,l.keyWait),void a.pop()):p&&a.length===t.maxSequence?(y(),void(t.keyIgnore=setTimeout(()=>t.keyIgnore=null,l.keyWait))):void(p?d=setTimeout(y,l.keyWait):y())}function x(n){if(!o().hasOwnProperty(n.code)){if(clearTimeout(d),u&&u({key:n.key,context:c.name,note:c.note,dependencies:e.extra}),t.keyIgnore)return clearTimeout(t.keyIgnore),void(t.keyIgnore=setTimeout(()=>t.keyIgnore=null,l.keyWait));if(a.push(i(n,o)),p&&a.length===t.maxSequence)return y(),void(t.keyIgnore=setTimeout(()=>t.keyIgnore=null,l.keyWait));p?d=setTimeout(y,l.keyWait):y()}}return{start:function(){t.active||(document.addEventListener("keydown",w),document.addEventListener("keypress",x),t.active=!0)},stop:function(){t.active&&(document.removeEventListener("keydown",w),document.removeEventListener("keypress",x),t.active=!1,d&&(clearTimeout(d),d=null),t.keyIgnore&&(clearTimeout(t.keyIgnore),t.keyIgnore=null),a=[],p=!0,f=!1)}}}function n(e){const t=e.toUpperCase(),n=/KEY\s*\:/i.test(t),o=t.indexOf(":");return n?t.includes("SETUP")?"KEY:SETUP":`KEY:${t.slice(o+1).split(",").map(e=>e.trim()).map(e=>e.split("+").map(e=>e.trim()).sort().join("+")).join(",")}`:e}function o(e,t){const{shiftKey:n,altKey:o,ctrlKey:i}=e,r=t(),s=e.code.replace("Key","").replace("Digit",""),c=[];return i&&c.push("CTRL"),n&&c.push("SHIFT"),o&&c.push("ALT"),r.hasOwnProperty(s)?c.push(r[s].toUpperCase()):["ControlLeft","ControlRight","ShiftLeft","ShiftRight","AltLeft","AltRight","Meta"].includes(s)||c.push(s.toUpperCase()),c.sort()}function i(e,t){let n=0,o=!1;const i=t.defaultOptions,{regex:r}=e,{currentContext:{name:s},shortcuts:c}=t;return null==s?0:(Object.entries(c[s]).forEach(([s,c])=>{if(!r.test(s))return;if("KEY:SETUP"===s){o=!0;const n=c.reduce((n,o)=>{const i=o({dependencies:e.extra,defaults:structuredClone(t.defaultOptions),options:t.listenOptions});return Object.assign(n,i)},i);return void Object.assign(t.listenOptions,n)}n++;const u=s.slice(4).split(",").length;t.maxSequence<u&&(t.maxSequence=u)}),o||Object.assign(t.listenOptions,i),n)}function r(){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(e,t,n){const{listenOptions:{clickTarget:o}}=t,i=n;return i===document.body?null:o.some(e=>i.hasAttribute(e))?i:s(e,t,i.parentNode)}function c(e,t){const{ev:n,_findTarget:o,_readClickEvent:i,extra:r}=e,{listenOptions:s,currentContext:c}=t;let u=null,l=null,a=null,d=null,p=0;function f(){if(!u)return;const{left:e,top:o,width:s,height:f}=u.getBoundingClientRect(),h=window.scrollX,m=window.scrollY,g=i(l,p),v={target:u,x:l.clientX,y:l.clientY,context:c.name,note:c.note,options:t.listenOptions,event:l,dependencies:r,viewport:{X:h,Y:m,width:window.innerWidth,height:window.innerHeight},sizes:{width:s,height:f},position:{x:e,y:o},pagePosition:{x:e+h,y:o+m},type:"click"};n.emit(g,v),a=null,d=null,u=null,l=null,p=0}function h(n){let i=t.maxLeftClicks;if(clearTimeout(a),d)return clearTimeout(d),void(d=setTimeout(()=>d=null,s.mouseWait));if(u=o(e,t,n.target),null!=u){if(u&&u.dataset.hasOwnProperty("quickClick")&&(i=1),u&&"A"===u.tagName&&(i=1),l=n,p++,p>=i)return f(),void(i>1&&(d=setTimeout(()=>d=null,s.mouseWait)));a=setTimeout(f,s.mouseWait)}}function m(n){let i=t.maxRightClicks;if(clearTimeout(a),d)return clearTimeout(d),void(d=setTimeout(()=>d=null,s.mouseWait));if(u=o(e,t,n.target),null!=u){if(u&&u.dataset.hasOwnProperty("quickClick")&&(i=1),u&&"A"===u.tagName&&(i=1),l=n,p++,p>=i)return f(),void(i>1&&(d=setTimeout(()=>d=null,s.mouseWait)));a=setTimeout(f,s.mouseWait)}}return{start:function(){t.active||(window.addEventListener("contextmenu",m),document.addEventListener("click",h),t.active=!0)},stop:function(){t.active&&(window.removeEventListener("contextmenu",m),document.removeEventListener("click",h),t.active=!1,d&&(clearTimeout(d),d=null),u=null,l=null,p=0)}}}function u(e){const t=e.toUpperCase(),n=/CLICK\s*\:/i.test(t),o=["LEFT","MIDDLE","RIGHT"],i=["ALT","SHIFT","CTRL"];let r=null,s=0;const c=[],u=t.indexOf(":");return n?t.includes("SETUP")?"CLICK:SETUP":(t.slice(u+1).trim().split("-").map(e=>e.trim()).forEach(e=>{o.includes(e)?r=e:i.includes(e)?c.push(e):isNaN(e)||(s=e)}),`CLICK:${r}-${s}${c.length>0?"-":""}${c.sort().join("-")}`):e}function l(e,t){const{shiftKey:n,altKey:o,ctrlKey:i,key:r,button:s}=e,c=`CLICK:${["LEFT","MIDDLE","RIGHT"][s]}-${t}`,u=[];return i&&u.push("CTRL"),n&&u.push("SHIFT"),o&&u.push("ALT"),u.length>0?`${c}${u.length>0?"-":""}${u.sort().join("-")}`:`${c}`}function a(e,t){let n=0,o=!1;const i=t.defaultOptions,{regex:r}=e,{listenOptions:s,currentContext:{name:c},shortcuts:u}=t;return null==c||(Object.entries(u[c]).forEach(([c,u])=>{if(!r.test(c))return;if("CLICK:SETUP"===c){o=!0;const n=u.reduce((n,o)=>{const i=o({dependencies:e.extra,defaults:structuredClone(t.defaultOptions),options:s});return Object.assign(n,i)},i);return void Object.assign(t.listenOptions,n)}n++;const[l,a]=c.slice(6).split("-");"LEFT"===l&&t.maxLeftClicks<a&&(t.maxLeftClicks=a),"RIGHT"===l&&t.maxRightClicks<a&&(t.maxRightClicks=a)}),o||Object.assign(t.listenOptions,i)),n}function d(e,t){const{ev:n}=e;let o=null;function i(e,t,n,o){const{extra:i}=e,{left:r,top:s,width:c,height:u}=n.target.getBoundingClientRect(),l=window.scrollX,a=window.scrollY;return{target:n.target,context:t.currentContext.name,note:t.currentContext.note,event:n,dependencies:i,options:t.listenOptions,viewport:{X:l,Y:a,width:window.innerWidth,height:window.innerHeight},sizes:{width:c,height:u},position:{x:r,y:s},pagePosition:{x:r+l,y:s+a},type:o}}function r(o){const{callbacks:r,typeFn:s}=t;o.target;const c=i(e,t,o,"form"),u=`${s(c)}/in`;null!=r[u]&&n.emit(u,c,r[u])}function s(o){const{callbacks:r,typeFn:s}=t,c=i(e,t,o,"form"),u=`${s(c)}/out`;null!=r[u]&&n.emit(u,c,r[u])}function c(r){const{callbacks:s,typeFn:c}=t,u=i(e,t,r,"form"),l=c(u),a=t.wait[`${l}`],d=`${l}/instant`;null!=s[d]&&(0!==a?(clearTimeout(o),o=setTimeout(()=>n.emit(d,u,s[d]),a)):n.emit(d,u,s[d]))}return{start:function(){t.active||(document.addEventListener("focusin",r),document.addEventListener("focusout",s),document.addEventListener("input",c),t.active=!0)},stop:function(){t.active&&(document.removeEventListener("focusin",r),document.removeEventListener("focusout",s),document.removeEventListener("input",c),t.active=!1,o&&(clearTimeout(o),o=null))}}}function p(e){const t=e.toUpperCase(),n=/FORM\s*\:/i.test(t),o=t.indexOf(":");return n?`FORM:${t.slice(o+1).trim()}`:e}function f(e,t){const{regex:n,_defaults:o,ev:i}=e,{currentContext:{name:r,note:s},shortcuts:c,callbacks:u,ERROR_EVENT_NAME:l,defaultOptions:a}=t;let d=[],p=[],f=[],h=0;if(null==r)return!1;if(Object.entries(c[r]).forEach(([o,i])=>{if(n.test(o)){if(o.includes("SETUP")){const n=i.reduce((n,o)=>{const i=o({dependencies:e.extra,defaults:structuredClone(t.defaultOptions),options:t.listenOptions});return Object.assign(n,i)},a);return void Object.assign(t.listenOptions,n)}"FORM:WATCH"===o&&(d=i),"FORM:DEFINE"===o&&(p=i),"FORM:ACTION"===o&&(f=i)}}),0===f.length)return h;const m=new Set;0===p.length&&(p=[o.define]),0===d.length&&(d=[o.watch]);const g=d.map(n=>n({dependencies:e.extra,context:r,note:s,options:t.listenOptions})).reduce((e,t)=>(e.push(t),e),[]);return t.watchList=document.querySelectorAll(g),t.watchList.forEach(n=>{const{left:o,top:i,width:c,height:u}=n.getBoundingClientRect(),l=window.scrollX,a=window.scrollY;return m.add(p[0]({target:n,context:r,note:s,dependencies:e.extra,options:t.listenOptions,viewport:{X:l,Y:a,width:window.innerWidth,height:window.innerHeight},sizes:{width:c,height:u},position:{x:o,y:i},pagePosition:{x:o+l,y:i+a}}))}),t.typeFn=p[0]?p[0]:o.define,f.forEach(n=>{if(!(n instanceof Function))return i.emit(l,"The 'form:action' should be a function."),!1;const o=n({dependencies:e.extra,options:t.listenOptions});if(!(o instanceof Array))return i.emit(l,"Warning: The 'form:action' function should RETURN an array."),!1;o.forEach(({fn:e,type:n,timing:o,wait:r=0})=>{if(m.has(n)&&e instanceof Function){const t=`${n}/${o}`,r=u.hasOwnProperty(t);r?u[t].push(e):u[t]=[e],r||i.on(t,(e,t)=>{t.forEach(t=>{t instanceof Function&&t(e)})})}"instant"===o&&(t.wait[`${n}`]=r)})}),h=Object.keys(t.callbacks).length,h}const h={watch:()=>"input, select, textarea, button, a",define:({target:e})=>"checkbox"===e.type||"radio"===e.type?"checkbox":"button"==e.type||"submit"==e.type?"button":"input"};function m(e,t,n){const{listenOptions:{hoverTarget:o}}=t,i=n;return i!==document.body&&(i!==document&&(o.some(e=>i.hasAttribute(e))?i:m(e,t,i.parentNode)))}function g(e,t){const{ev:n,_findTarget:o,resetState:i,extra:r}=e;function s(i){const s=i.clientX,c=i.clientY,{hovered:u,hoverRectangle:l,listenOptions:a,hoverTimer:d,leaveTimer:p,lastEvent:f,lastHoverTarget:h}=t,m=o(e,t,i.target);if(!function(e,t,n){return!!e&&t>=e.left&&t<=e.right&&n>=e.top&&n<=e.bottom}(l,s,c)&&m!==u){if(u&&!m){if(t.hovered=!1,t.hoverRectangle=null,d&&(clearTimeout(d),t.hoverTimer=null),"off"===f)return;return void(t.leaveTimer=setTimeout(()=>{n.emit("HOVER:OFF",g(u)),t.leaveTimer=null,t.lastEvent="off"},a.wait))}u&&(n.emit("HOVER:OFF",g(u)),t.leaveTimer=null,t.lastEvent="off"),clearTimeout(p),clearTimeout(d),t.hovered=m,t.hoverRectangle=m.getBoundingClientRect(),t.hoverTimer=setTimeout(()=>{n.emit("HOVER:ON",g(m)),t.hoverTimer=null,t.lastHoverTarget=m,t.lastEvent="on"},a.wait)}function g(e){const{left:n,top:o,width:s,height:c}=e.getBoundingClientRect(),u=window.scrollX,l=window.scrollY;return{target:e,context:t.currentContext.name,note:t.currentContext.note,event:i,dependencies:r,options:t.listenOptions,viewport:{X:u,Y:l,width:window.innerWidth,height:window.innerHeight},sizes:{width:s,height:c},position:{x:n,y:o},pagePosition:{x:n+u,y:o+l},type:"hover"}}}return{start:function(){t.active||(document.addEventListener("mousemove",s),t.active=!0)},stop:function(){t.active&&(document.removeEventListener("mousemove",s),i())}}}function v(e){const t=e.toUpperCase(),n=/HOVER\s*\:/i.test(t),o=t.indexOf(":");return n?`HOVER:${t.slice(o+1).trim()}`:e}function y(e,t){let n=0,o=!1;const i=t.defaultOptions,{regex:r,_defaults:s,ev:c}=e,{currentContext:{name:u},shortcuts:l,ERROR_EVENT_NAME:a}=t;return null==u||(Object.entries(l[u]).forEach(([s,c])=>{if(r.test(s)){if("HOVER:SETUP"===s){o=!0;const n=c.reduce((n,o)=>{const i=o({dependencies:e.extra,defaults:structuredClone(t.defaultOptions),options:t.listenOptions});return Object.assign(n,i)},i);return void Object.assign(t.listenOptions,n)}n++}}),o||Object.assign(t.listenOptions,i)),n}function w(e,t){const{ev:n,resetState:o,extra:i}=e;let r=null,s=null;function c(e){e.clientX,e.clientY;const{lastPosition:o,lastDirection:c,listenOptions:u,currentContext:l}=t,{scrollWait:a,endScrollWait:d,minSpace:p}=u;if(!o)return;let f=null;const h=window.scrollX,m=window.scrollY,g=Math.abs(m-o.y),v=Math.abs(h-o.x);if(g<p&&v<p)return;const y=[];g>=p&&(m>o.y?y.push("down"):y.push("up")),v>=p&&(h>o.x?y.push("right"):y.push("left")),f=y[0]||null;const w=e=>({x:h,y:m,direction:e,context:l.name,note:l.note,dependencies:i,options:t.listenOptions,viewport:{X:h,Y:m,width:window.innerWidth,height:window.innerHeight},type:"scroll"});y.forEach(e=>{const t=`SCROLL:${e.toUpperCase()}`;n.emit(t,w(e))}),clearTimeout(r),clearTimeout(s);const x=y[y.length-1]||null;r=setTimeout(()=>{},a),s=setTimeout(()=>n.emit("SCROLL:END",w(x)),d),t.lastPosition={x:h,y:m},t.lastDirection=f}return{start:function(){t.active||(t.lastPosition={x:window.scrollX,y:window.scrollY},window.addEventListener("scroll",c),t.active=!0)},stop:function(){t.active&&(window.removeEventListener("scroll",c),o())}}}function x(e){const t=e.toUpperCase(),n=/SCROLL\s*\:/i.test(t),o=t.indexOf(":");return n?`SCROLL:${t.slice(o+1).trim()}`:e}function O(e,t){let n=0,o=!1;const i=t.defaultOptions,{regex:r}=e,{currentContext:{name:s},shortcuts:c}=t;return null==s||(Object.entries(c[s]).forEach(([s,c])=>{if(r.test(s)){if("SCROLL:SETUP"===s){o=!0;const n=c.reduce((n,o)=>{const i=o({dependencies:e.extra,defaults:structuredClone(t.defaultOptions),options:t.listenOptions});return Object.assign(n,i)},i);return void Object.assign(t.listenOptions,n)}n++}}),o||Object.assign(t.listenOptions,i)),n}function E(t={}){const n={},o={},i=function(){let e=Object.assign(Object.create(null),{"*":[]}),t=Object.create(null),n=new Set,o=!1,i="";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)),"*"!==n&&e[n]&&0===e[n].length&&delete e[n],void(t[n]&&0===t[n].length&&delete t[n]);t[n]&&delete t[n],"*"===n?e["*"]=[]:e[n]&&delete e[n]},reset:function(){e=Object.assign(Object.create(null),{"*":[]}),t=Object.create(null),n=new Set},emit:function(){const[r,...s]=arguments;function c(t){let o=!1;"*"!==t&&(n.has(t)||(e[t].every(e=>{const t=e(...s);return"string"!=typeof t||"STOP"!==t.toUpperCase()||(o=!0,!1)}),o||e["*"].forEach(e=>e(r,...s))))}if(o&&(console.log(`${i} Event "${String(r)}" was triggered.`),s.length>0&&(console.log("Arguments:"),console.log(...s),console.log("^----"))),"*"!==r){if(t[r]){if(n.has(r))return;const o=t[r];delete t[r],o.forEach(e=>e(...s)),e[r]||e["*"].forEach(e=>e(r,...s))}e[r]&&c(r)}else Reflect.ownKeys(e).forEach(e=>c(e))},stop:function(o){if("*"===o){const o=Reflect.ownKeys(e),i=Reflect.ownKeys(t);return void(n=new Set([...i,...o]))}n.add(o)},start:function(e){"*"!==e?n.delete(e):n.clear()},debug:function(e,t){o=!!e,t&&"string"==typeof t&&(i=t)}}}(),r={currentContext:{name:null,note:null},shortcuts:{},plugins:[],exposeShortcut:!(!t.onShortcut||"function"!=typeof t.onShortcut)&&t.onShortcut,ERROR_EVENT_NAME:t.errorEventName?t.errorEventName:"@shortcuts-error"},s={ev:i,inAPI:n,API:o,extra:{emit:i.emit}};return o.enablePlugin=(e,t={})=>{if("function"!=typeof e)return;const o=e(n._setupPlugin,t),i=o.getPrefix(),s=n._systemAction(i,"none");-1===s?(r.plugins.push(o),o.unmute()):(o.destroy(),r.plugins[s].unmute())},o.disablePlugin=e=>{const t=n._systemAction(e,"destroy");-1!==t&&r.plugins.splice(t,1)},o.mutePlugin=e=>n._systemAction(e,"mute"),o.unmutePlugin=e=>n._systemAction(e,"unmute"),o.listPlugins=()=>r.plugins.map(e=>e.getPrefix()),o.getContext=()=>r.currentContext.name,o.getNote=()=>r.currentContext.note,o.setNote=(e=null)=>{"string"!=typeof e&&null!=e||(r.currentContext.note=e)},o.pause=(e="*")=>{const t=n._readShortcutWithPlugins(e);i.stop(t)},o.resume=(e="*")=>{const t=n._readShortcutWithPlugins(e);i.start(t)},o.emit=(e,...t)=>i.emit(n._readShortcutWithPlugins(e),{dependencies:s.extra,type:"custom"},...t),o.listContexts=()=>Object.keys(r.shortcuts),o.setDependencies=e=>Object.assign(s.extra,e),o.getDependencies=()=>s.extra,o.reset=function(){i.reset(),o.changeContext(),r.plugins.forEach(e=>e.destroy()),o.listContexts().map(e=>o.unload(e)),s.extra={emit:i.emit},r.exposeShortcut=null},Object.entries(e).forEach(([e,t])=>{e.startsWith("_")?n[e]=t(s,r):o[e]=t(s,r)}),o}var S=Object.freeze({__proto__:null,pluginClick:function(e,t={}){const n={_findTarget:s,_readClickEvent:l,regex:/CLICK\s*\:/i},o={active:!1,maxLeftClicks:1,maxRightClicks:1,defaultOptions:{mouseWait:320,clickTarget:["data-click","href"]},listenOptions:{mouseWait:320,clickTarget:["data-click","href"]},streamKeys:!(!t.streamKeys||"function"!=typeof t.streamKeys)&&t.streamKeys};return n.resetState=function(){},e({prefix:"click",_normalizeShortcutName:u,_registerShortcutEvents:a,_listenDOM:c,pluginState:o,deps:n})},pluginForm:function(e,t={}){const n={_defaults:h,regex:/FORM\s*\:/i},o={callbacks:{},typeFn:"",watchList:[],wait:{},defaultOptions:{},listenOptions:{}};return n.resetState=function(){o.callbacks={},o.typeFn="",o.watchList=[],o.wait={}},e({prefix:"form",_normalizeShortcutName:p,_registerShortcutEvents:f,_listenDOM:d,pluginState:o,deps:n})},pluginHover:function(e,t={}){const n={_findTarget:m,regex:/HOVER\s*\:/i},o={active:!1,hovered:!1,hoverRectangle:null,hoverTimer:null,leaveTimer:null,lastEvent:"",lastHoverTarget:null,defaultOptions:{hoverTarget:["data-hover"],wait:320},listenOptions:{hoverTarget:["data-hover"],wait:320}};return n.resetState=function(){o.active=!1,o.hovered=!1,o.hoverRectangle=null,clearTimeout(o.hoverTimer),clearTimeout(o.leaveTimer),o.hoverTimer=null,o.leaveTimer=null,o.lastHoverTarget=null},e({prefix:"hover",_normalizeShortcutName:v,_registerShortcutEvents:y,_listenDOM:g,pluginState:o,deps:n})},pluginKey:function(e,s={}){const c={_specialChars:r,_readKeyEvent:o,regex:/KEY\s*\:/i},u={active:!1,maxSequence:1,keyIgnore:null,defaultOptions:{keyWait:480},listenOptions:{keyWait:480},streamKeys:!(!s.streamKeys||"function"!=typeof s.streamKeys)&&s.streamKeys};return c.resetState=function(){u.active=!1,u.keyIgnore=null,u.maxSequence=1},e({prefix:"key",_normalizeShortcutName:n,_registerShortcutEvents:i,_listenDOM:t,pluginState:u,deps:c})},pluginScroll:function(e,t={}){const n={regex:/SCROLL\s*\:/i},o={active:!1,lastPosition:null,lastDirection:null,defaultOptions:{scrollWait:50,endScrollWait:400,minSpace:40},listenOptions:{scrollWait:50,endScrollWait:400,minSpace:40}};return n.resetState=function(){o.active=!1},e({prefix:"scroll",_normalizeShortcutName:x,_registerShortcutEvents:O,_listenDOM:w,pluginState:o,deps:n})},shortcuts:E});function T(e){return e?function(e){let t=e.map(e=>C()),n=t.map(e=>e.promise);t.promises=t;let o=k(Promise.all(n));function i(e){let t="pending";return e.then(()=>t="fulfilled").catch(()=>t="rejected"),t}function r(n,...o){t.forEach((t,r)=>n({value:e[r],done:t.done,cancel:t.cancel,timeout:t.timeout,state:i(t.promise)},...o))}const s={promise:Promise.all(n),promises:t,done:e=>{t.forEach(t=>t.done(e))},cancel:e=>{t.forEach(t=>t.cancel(e))},each:r,onComplete:o,timeout:()=>{}};return s.timeout=b(!0,s),s}(e):C()}function C(){let e,t;const n=new Promise((n,o)=>{e=n,t=o}),o={promise:n,promises:null,done:e,cancel:t,each:()=>{},onComplete:k(n),timeout:()=>{}};return o.timeout=b(!1,o),o.each=(n,...i)=>{n({value:null,done:e,cancel:t,timeout:o.timeout},...i)},o}function k(e){return function(t,n=null){null===n?e.then(e=>t(e)):e.then(e=>t(e),e=>n(e))}}function b(e,t){let n;return n=e?Promise.all(t.promises.map(e=>e.promise)):t.promise,function(e,o){let i,r=new Promise((t,r)=>{i=setTimeout(()=>{t(o),Promise.resolve(n)},e)});return n.then(()=>clearTimeout(i)),t.onComplete=k(Promise.race([n,r])),t}}function P({message:e,level:t,type:n,logLevel:o}){if(0===o)return null;if(o<t)return null;const i=`[Debug]: ${e}`;switch(n){case"warn":console.warn(i);break;case"error":console.error(i);break;default:console.log(i)}return i}function R(e={},t=P){return function({message:n,type:o,level:i,...r}){const{level:s,type:c,defaultMessageLevel:u}=Object.assign({},{level:1e3,type:"log",defaultMessageLevel:1},e);return o||(o=c),i||(i=u),t({message:n,type:o,level:i,logLevel:s,...r})}}function*L(e,t,n,o){let i=null,r=!0;if(null===e)return yield*o.map(e=>[e,"show"]),void(yield[n,"show"]);if(0!==o.length){if(o.includes(e)){for(let t=o.indexOf(e)+1;t<o.length;t++)yield[o[t],"show"];return void(yield[n,"show"])}if(!t)return yield[e,"hide"],void(yield*o.map(e=>[e,"show"]));if(o.every((e,n)=>t[n]===o[n]&&(i=n,!0)),null==i)return yield[e,"hide"],t.reverse(),yield*t.map(e=>[e,"hide"]),yield*o.map(e=>[e,"show"]),void(yield[n,"show"]);yield[e,"hide"];for(let e=t.length;e>i+1;e--)yield[t[e-1],"hide"];for(let e=i+1;e<o.length;e++)yield[o[e],"show"];yield[n,"show"]}else{if(yield[e,"hide"],t.includes(n)){let e=t.indexOf(n),o=t.filter((t,n)=>n>e);o.reverse(),yield*o.map(e=>[e,"hide"]),r=!1}else{let e=[...t];e.reverse(),yield*e.map(e=>[e,"hide"])}r&&(yield[n,"show"])}}function _(e){return function(t,...n){const{askForPromise:o,deps:i}=e;return function(){const e=o();return t({task:e,dependencies:i()},...n),e.promise}}}return T.sequence=function(e,...t){const n=T(),o=[];const i=function*(e){for(const t of e)yield t}(e);return function e(t,...r){t.done?n.done(o):t.value(...r).then(t=>{o.push(t),e(i.next(),...r,t)})}(i.next(),...t),n},T.all=function(e,...t){const n=T(),o=[],i=e.map((e,n)=>"function"==typeof e?e(...t).then(e=>o[n]=e):e.then(e=>o[n]=e));return Promise.all(i).then(()=>n.done(o)),n},function(e={logLevel:0}){const t=E({errorEventName:"@app-error"}),n=R({level:e.logLevel||1},e=>{const{type:n}=e;"error"===n&&t.emit("@app-error",e)}),o={currentScene:null,currentParents:null,sceneNames:new Set,scenes:{},opened:!1,jumpStack:[]},i={},r={shortcutMngr:t,findInstructions:L,askForPromise:T,setInstruction:_({askForPromise:T,deps:t.getDependencies}),log:n};return i.hide=function(e,t){return function(n=1){const{askForPromise:o,shortcutMngr:i,setInstruction:r}=e,{currentScene:s,currentParents:c,scenes:u}=t,l=o(),a=[],d=c.length>0;let p;return i.pause(),a.push(r(u[s].hide)),d||(t.currentScene=null),d&&"*"===n&&[...c].reverse().forEach(e=>{p=t.currentParents.at(-1),t.currentScene=p,a.push(r(u[e].hide))}),d&&!["*",1].includes(n)&&c.slice("-"+(n-1)).reverse().map(e=>{p=t.currentParents.at(-1),t.currentScene=p,a.push(r(u[e].hide))}),(n=o.sequence(a)).onComplete(()=>{i.changeContext(t.currentScene),l.done()}),l.promise}}(r,o),i.listShortcuts=function(e,t){return function(e){const{scenes:n,sceneNames:o}=t;if(!o.has(e))return null;const{show:i,hide:r,parents:s,beforeUnload:c,afterLoad:u,...l}=n[e];return Object.keys(l)}}(0,o),i.setScenes=function(e,t){return function(n){const{shortcutMngr:o,log:i}=e;n.forEach(e=>{if(null==e)return;const{name:n,scene:r}=e;if(!n)return void i({message:"Scene name is not defined",level:1,type:"error"});if(null==r)return void i({message:`Scene ${n} is not defined`,level:1,type:"error"});r.parents||(r.parents=[]),t.scenes[n]=r,t.sceneNames.add(n);const{show:s,hide:c,parents:u,...l}=r,a={};a[n]=l,o.load(a)})}}(r,o),i.show=function(e,t){return function({scene:n,options:o={ssr:!1}},...i){const{shortcutMngr:r,askForPromise:s,log:c,findInstructions:u,setInstruction:l}=e,a=s(),d=s(),{opened:p,scenes:f,sceneNames:h,currentScene:m}=t;return m&&"function"==typeof f[m].beforeHide?(0,f[m].beforeHide)({done:d.done,dependencies:r.getDependencies()}):d.done(!0),d.onComplete(e=>{if(!e)return a.done(),a.promise;if(!h.has(n))return c({message:`Scene "${n}" is not available.`,level:1,type:"error"}),a.done(),a.promise;if(!p&&o.ssr)return t.opened=!0,t.currentScene=n,r.changeContext(n),a.done(),a.promise;const{show:d,parents:m=[]}=f[n];if("*"===m[0])return l(d,...i)().then(()=>a.done()),t.currentParents.push(t.currentScene),t.currentScene=n,a.promise;if(0!==m.length&&!m.every(e=>h.has(e)))return c({message:`Some of '${n}' parent scenes are not set.`,level:1,type:"error"}),a.done(),a.promise;function g([e,n]){if("show"===n)t.currentScene&&(t.currentParents=[...f[t.currentScene].parents]),t.currentScene=e;else{let n=f[e].parents.at(-1);t.currentScene=n}return f[e][n]}t.currentParents||(t.currentParents=[]);const v=u(t.currentScene,t.currentParents,n,m),y=[];for(let e of v){const t=g(e);y.push(l(t,...i))}s.sequence(y).onComplete(()=>{t.opened=!0,t.currentScene=n,t.currentParents=f[n].parents||null,r.changeContext(n),"function"==typeof f[n].afterShow&&f[n].afterShow({dependencies:r.getDependencies(),done:()=>{}}),a.done()})}),a.promise}}(r,o),i.jump=function(e,t){return function({scene:n},...o){return e.jumpStack.push(e.currentScene),t({scene:n},...o)}}(o,i.show),i.jumpBack=function(e,t){return function({hops:n}={hops:1},...o){for(let t=0;t<n-1;t++)e.jumpStack.pop();if(0===e.jumpStack.length)return;const i=e.jumpStack.pop();return t({scene:i},...o)}}(o,i.show),i.jumpsReset=function(e){return function(){e.jumpStack=[]}}(o),i.loadPlugins=async function(e){const t=e.map(e=>`plugin${e}`),n=await Promise.resolve().then(function(){return S});return t.map(e=>n[e])},i.setDependencies=e=>t.setDependencies(e),i.getDependencies=()=>t.getDependencies(),i.setNote=e=>t.setNote(e),i.listScenes=()=>[...o.sceneNames],i.enablePlugin=(e,n)=>t.enablePlugin(e,n),i.disablePlugin=e=>t.disablePlugin(e),i.getState=()=>({scene:o.currentScene,parents:o.currentParents,opened:o.opened}),i.emit=(e,...n)=>t.emit(e,...n),i}});
|
|
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).cuts=t()}(this,function(){"use strict";var e={_normalizeWithPlugins:function(e,t){return function(e){const n=t.shortcuts;Object.keys(n).forEach(t=>{Object.entries(n[t]).forEach(([o,i])=>{const r=e(o);r!==o&&(delete n[t][o],n[t][r]=i)})})}},_readShortcutWithPlugins:function(e,t){return function(n){const{inAPI:o}=e,i=n.split(":")[0].toLowerCase().trim(),r=o._systemAction(i,"none");let s=n;return-1!==r&&(s=t.plugins[r].shortcutName(n)),s}},_setupPlugin:function(e,t){const{inAPI:n}=e,{currentContext:o,shortcuts:i,exposeShortcut:r,ERROR_EVENT_NAME:s}=t;return function(t){const{prefix:c,_normalizeShortcutName:u,_registerShortcutEvents:l,_listenDOM:a,pluginState:p,deps:d}=t,{resetState:f}=d;p.currentContext=o,p.shortcuts=i,p.exposeShortcut=r,p.ERROR_EVENT_NAME=s;const h={ev:e.ev,extra:e.extra,...d};n._normalizeWithPlugins(u);let m=l(h,p);const g=a(h,p);m>0&&g.start();const v={getPrefix:()=>c,shortcutName:e=>u(e),contextChange:()=>{f(),m=l(h,p),m<1&&g.stop(),m>0&&g.start()},mute:()=>g.stop(),unmute:()=>g.start(),destroy:()=>{g.stop(),f()}};return Object.freeze(v),v}},_systemAction:function(e,t){return function(e,n,o=null){return t.plugins.findIndex(t=>t.getPrefix()===e&&(t[n]&&t[n](o),!0))}},changeContext:function(e,t){const{shortcuts:n,currentContext:o,ERROR_EVENT_NAME:i}=t,{ev:r}=e;return function(e=!1){const s=o.name;if(!e)return r.reset(),void(o.name=null);s!==e&&(n[e]?(n[s]&&r.reset(),o.name=e,t.plugins.forEach(t=>t.contextChange(e)),Object.entries(n[e]).forEach(([e,t])=>{e.includes(":SETUP")||t.forEach(t=>r.on(e,t))}),r.on("*",(...e)=>{t.exposeShortcut&&t.exposeShortcut(...e)})):r.emit(i,`Context '${e}' does not exist`))}},listShortcuts:function(e,t){const n=t.shortcuts;return function(e=null){if(null!=e){const t=n[e];return null==t?null:Object.entries(t).map(([e,t])=>e)}return Object.keys(n).map(e=>{const t={};return t.context=e,t.shortcuts=Object.entries(n[e]).map(([e,t])=>e),t})}},load:function(e,t){const{shortcuts:n,plugins:o}=t,{API:{changeContext:i,getContext:r}}=e;return function(e){const t=r(),s=o.map(e=>e.getPrefix().toUpperCase());let c=!1;Object.entries(e).forEach(([e,i])=>{e===t&&(c=!0),n[e]={},Object.entries(i).forEach(([t,i])=>{let r=t;const c=t.toUpperCase().trim(),u=s.map((e,t)=>c.startsWith(e)?t:null).filter(e=>null!==e);if(u.length){const e=u[0];r=o[e].shortcutName(t)}i instanceof Function&&(i=[i]),n[e][r]=i})}),c&&(i(),i(t))}},unload:function(e,t){const{currentContext:n,shortcuts:o,ERROR_EVENT_NAME:i}=t,{ev:r}=e;return function(e){n.name!==e?o[e]?delete o[e]:r.emit(i,`Context '${e}' does not exist`):r.emit(i,`Context '${e}' can't be removed during is current active context. Change the context first`)}}};function t(e,t){const{ev:n,_specialChars:o,_readKeyEvent:i,extra:r,resetState:s}=e,{currentContext:c,streamKeys:u,listenOptions:l}=t;let a=[],p=null,d=!0,f=!1;const h=()=>d=!1,m=()=>d=!0,g=()=>f=!0,v=()=>!1===d;function y(){const e=a.map(e=>[e.join("+")]),o={wait:h,end:m,ignore:g,isWaiting:v,note:c.note,context:c.name,dependencies:r,options:t.listenOptions,viewport:{X:window.scrollX,Y:window.scrollY,width:window.innerWidth,height:window.innerHeight},type:"key"};if(!d){const t=`KEY:${e.at(-1).join("+")}`;n.emit(t,o),f&&(a=a.slice(0,-1),f=!1)}if(d){const i=`KEY:${e.join(",")}`;n.emit(i,o),f&&(a=a.slice(0,-1),f=!1),a=[],clearTimeout(t.keyIgnore),t.keyIgnore=null,clearTimeout(p),p=null}}function w(n){if(clearTimeout(p),o().hasOwnProperty(n.code))return a.push(i(n,o)),u&&u({key:n.key,context:c.name,note:c.note,dependencies:e.extra}),t.keyIgnore?(clearTimeout(t.keyIgnore),t.keyIgnore=setTimeout(()=>t.keyIgnore=null,l.keyWait),void a.pop()):d&&a.length===t.maxSequence?(y(),void(t.keyIgnore=setTimeout(()=>t.keyIgnore=null,l.keyWait))):void(d?p=setTimeout(y,l.keyWait):y())}function x(n){if(!o().hasOwnProperty(n.code)){if(clearTimeout(p),u&&u({key:n.key,context:c.name,note:c.note,dependencies:e.extra}),t.keyIgnore)return clearTimeout(t.keyIgnore),void(t.keyIgnore=setTimeout(()=>t.keyIgnore=null,l.keyWait));if(a.push(i(n,o)),d&&a.length===t.maxSequence)return y(),void(t.keyIgnore=setTimeout(()=>t.keyIgnore=null,l.keyWait));d?p=setTimeout(y,l.keyWait):y()}}return{start:function(){t.active||(document.addEventListener("keydown",w),document.addEventListener("keypress",x),t.active=!0)},stop:function(){t.active&&(document.removeEventListener("keydown",w),document.removeEventListener("keypress",x),t.active=!1,p&&(clearTimeout(p),p=null),t.keyIgnore&&(clearTimeout(t.keyIgnore),t.keyIgnore=null),a=[],d=!0,f=!1)}}}function n(e){const t=e.toUpperCase(),n=/KEY\s*\:/i.test(t),o=t.indexOf(":");return n?t.includes("SETUP")?"KEY:SETUP":`KEY:${t.slice(o+1).split(",").map(e=>e.trim()).map(e=>e.split("+").map(e=>e.trim()).sort().join("+")).join(",")}`:e}function o(e,t){const{shiftKey:n,altKey:o,ctrlKey:i}=e,r=t(),s=e.code.replace("Key","").replace("Digit",""),c=[];return i&&c.push("CTRL"),n&&c.push("SHIFT"),o&&c.push("ALT"),r.hasOwnProperty(s)?c.push(r[s].toUpperCase()):["ControlLeft","ControlRight","ShiftLeft","ShiftRight","AltLeft","AltRight","Meta"].includes(s)||c.push(s.toUpperCase()),c.sort()}function i(e,t){let n=0,o=!1;const i=t.defaultOptions,{regex:r}=e,{currentContext:{name:s},shortcuts:c}=t;return null==s?0:(Object.entries(c[s]).forEach(([s,c])=>{if(!r.test(s))return;if("KEY:SETUP"===s){o=!0;const n=c.reduce((n,o)=>{const i=o({dependencies:e.extra,defaults:structuredClone(t.defaultOptions),options:t.listenOptions});return Object.assign(n,i)},i);return void Object.assign(t.listenOptions,n)}n++;const u=s.slice(4).split(",").length;t.maxSequence<u&&(t.maxSequence=u)}),o||Object.assign(t.listenOptions,i),n)}function r(){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(e,t,n){const{listenOptions:{clickTarget:o}}=t,i=n;return i===document.body?null:o.some(e=>i.hasAttribute(e))?i:s(e,t,i.parentNode)}function c(e,t){const{ev:n,_findTarget:o,_readClickEvent:i,extra:r}=e,{listenOptions:s,currentContext:c}=t;let u=null,l=null,a=null,p=null,d=0;function f(){if(!u)return;const{left:e,top:o,width:s,height:f}=u.getBoundingClientRect(),h=window.scrollX,m=window.scrollY,g=i(l,d),v={target:u,x:l.clientX,y:l.clientY,context:c.name,note:c.note,options:t.listenOptions,event:l,dependencies:r,viewport:{X:h,Y:m,width:window.innerWidth,height:window.innerHeight},sizes:{width:s,height:f},position:{x:e,y:o},pagePosition:{x:e+h,y:o+m},type:"click"};n.emit(g,v),a=null,p=null,u=null,l=null,d=0}function h(n){let i=t.maxLeftClicks;if(clearTimeout(a),p)return clearTimeout(p),void(p=setTimeout(()=>p=null,s.mouseWait));if(u=o(e,t,n.target),null!=u){if(u&&u.dataset.hasOwnProperty("quickClick")&&(i=1),u&&"A"===u.tagName&&(i=1),l=n,d++,d>=i)return f(),void(i>1&&(p=setTimeout(()=>p=null,s.mouseWait)));a=setTimeout(f,s.mouseWait)}}function m(n){let i=t.maxRightClicks;if(clearTimeout(a),p)return clearTimeout(p),void(p=setTimeout(()=>p=null,s.mouseWait));if(u=o(e,t,n.target),null!=u){if(u&&u.dataset.hasOwnProperty("quickClick")&&(i=1),u&&"A"===u.tagName&&(i=1),l=n,d++,d>=i)return f(),void(i>1&&(p=setTimeout(()=>p=null,s.mouseWait)));a=setTimeout(f,s.mouseWait)}}return{start:function(){t.active||(window.addEventListener("contextmenu",m),document.addEventListener("click",h),t.active=!0)},stop:function(){t.active&&(window.removeEventListener("contextmenu",m),document.removeEventListener("click",h),t.active=!1,p&&(clearTimeout(p),p=null),u=null,l=null,d=0)}}}function u(e){const t=e.toUpperCase(),n=/CLICK\s*\:/i.test(t),o=["LEFT","MIDDLE","RIGHT"],i=["ALT","SHIFT","CTRL"];let r=null,s=0;const c=[],u=t.indexOf(":");return n?t.includes("SETUP")?"CLICK:SETUP":(t.slice(u+1).trim().split("-").map(e=>e.trim()).forEach(e=>{o.includes(e)?r=e:i.includes(e)?c.push(e):isNaN(e)||(s=e)}),`CLICK:${r}-${s}${c.length>0?"-":""}${c.sort().join("-")}`):e}function l(e,t){const{shiftKey:n,altKey:o,ctrlKey:i,key:r,button:s}=e,c=`CLICK:${["LEFT","MIDDLE","RIGHT"][s]}-${t}`,u=[];return i&&u.push("CTRL"),n&&u.push("SHIFT"),o&&u.push("ALT"),u.length>0?`${c}${u.length>0?"-":""}${u.sort().join("-")}`:`${c}`}function a(e,t){let n=0,o=!1;const i=t.defaultOptions,{regex:r}=e,{listenOptions:s,currentContext:{name:c},shortcuts:u}=t;return null==c||(Object.entries(u[c]).forEach(([c,u])=>{if(!r.test(c))return;if("CLICK:SETUP"===c){o=!0;const n=u.reduce((n,o)=>{const i=o({dependencies:e.extra,defaults:structuredClone(t.defaultOptions),options:s});return Object.assign(n,i)},i);return void Object.assign(t.listenOptions,n)}n++;const[l,a]=c.slice(6).split("-");"LEFT"===l&&t.maxLeftClicks<a&&(t.maxLeftClicks=a),"RIGHT"===l&&t.maxRightClicks<a&&(t.maxRightClicks=a)}),o||Object.assign(t.listenOptions,i)),n}function p(e,t){const{ev:n}=e;let o=null;function i(e,t,n,o){const{extra:i}=e,{left:r,top:s,width:c,height:u}=n.target.getBoundingClientRect(),l=window.scrollX,a=window.scrollY;return{target:n.target,context:t.currentContext.name,note:t.currentContext.note,event:n,dependencies:i,options:t.listenOptions,viewport:{X:l,Y:a,width:window.innerWidth,height:window.innerHeight},sizes:{width:c,height:u},position:{x:r,y:s},pagePosition:{x:r+l,y:s+a},type:o}}function r(o){const{callbacks:r,typeFn:s}=t;o.target;const c=i(e,t,o,"form"),u=`${s(c)}/in`;null!=r[u]&&n.emit(u,c,r[u])}function s(o){const{callbacks:r,typeFn:s}=t,c=i(e,t,o,"form"),u=`${s(c)}/out`;null!=r[u]&&n.emit(u,c,r[u])}function c(r){const{callbacks:s,typeFn:c}=t,u=i(e,t,r,"form"),l=c(u),a=t.wait[`${l}`],p=`${l}/instant`;null!=s[p]&&(0!==a?(clearTimeout(o),o=setTimeout(()=>n.emit(p,u,s[p]),a)):n.emit(p,u,s[p]))}return{start:function(){t.active||(document.addEventListener("focusin",r),document.addEventListener("focusout",s),document.addEventListener("input",c),t.active=!0)},stop:function(){t.active&&(document.removeEventListener("focusin",r),document.removeEventListener("focusout",s),document.removeEventListener("input",c),t.active=!1,o&&(clearTimeout(o),o=null))}}}function d(e){const t=e.toUpperCase(),n=/FORM\s*\:/i.test(t),o=t.indexOf(":");return n?`FORM:${t.slice(o+1).trim()}`:e}function f(e,t){const{regex:n,_defaults:o,ev:i}=e,{currentContext:{name:r,note:s},shortcuts:c,callbacks:u,ERROR_EVENT_NAME:l,defaultOptions:a}=t;let p=[],d=[],f=[],h=0;if(null==r)return!1;if(Object.entries(c[r]).forEach(([o,i])=>{if(n.test(o)){if(o.includes("SETUP")){const n=i.reduce((n,o)=>{const i=o({dependencies:e.extra,defaults:structuredClone(t.defaultOptions),options:t.listenOptions});return Object.assign(n,i)},a);return void Object.assign(t.listenOptions,n)}"FORM:WATCH"===o&&(p=i),"FORM:DEFINE"===o&&(d=i),"FORM:ACTION"===o&&(f=i)}}),0===f.length)return h;const m=new Set;0===d.length&&(d=[o.define]),0===p.length&&(p=[o.watch]);const g=p.map(n=>n({dependencies:e.extra,context:r,note:s,options:t.listenOptions})).reduce((e,t)=>(e.push(t),e),[]);return t.watchList=document.querySelectorAll(g),t.watchList.forEach(n=>{const{left:o,top:i,width:c,height:u}=n.getBoundingClientRect(),l=window.scrollX,a=window.scrollY;return m.add(d[0]({target:n,context:r,note:s,dependencies:e.extra,options:t.listenOptions,viewport:{X:l,Y:a,width:window.innerWidth,height:window.innerHeight},sizes:{width:c,height:u},position:{x:o,y:i},pagePosition:{x:o+l,y:i+a}}))}),t.typeFn=d[0]?d[0]:o.define,f.forEach(n=>{if(!(n instanceof Function))return i.emit(l,"The 'form:action' should be a function."),!1;const o=n({dependencies:e.extra,options:t.listenOptions});if(!(o instanceof Array))return i.emit(l,"Warning: The 'form:action' function should RETURN an array."),!1;o.forEach(({fn:e,type:n,timing:o,wait:r=0})=>{if(m.has(n)&&e instanceof Function){const t=`${n}/${o}`,r=u.hasOwnProperty(t);r?u[t].push(e):u[t]=[e],r||i.on(t,(e,t)=>{t.forEach(t=>{t instanceof Function&&t(e)})})}"instant"===o&&(t.wait[`${n}`]=r)})}),h=Object.keys(t.callbacks).length,h}const h={watch:()=>"input, select, textarea, button, a",define:({target:e})=>"checkbox"===e.type||"radio"===e.type?"checkbox":"button"==e.type||"submit"==e.type?"button":"input"};function m(e,t,n){const{listenOptions:{hoverTarget:o}}=t,i=n;return i!==document.body&&(i!==document&&(o.some(e=>i.hasAttribute(e))?i:m(e,t,i.parentNode)))}function g(e,t){const{ev:n,_findTarget:o,resetState:i,extra:r}=e;function s(i){const s=i.clientX,c=i.clientY,{hovered:u,hoverRectangle:l,listenOptions:a,hoverTimer:p,leaveTimer:d,lastEvent:f,lastHoverTarget:h}=t,m=o(e,t,i.target);if(!function(e,t,n){return!!e&&t>=e.left&&t<=e.right&&n>=e.top&&n<=e.bottom}(l,s,c)&&m!==u){if(u&&!m){if(t.hovered=!1,t.hoverRectangle=null,p&&(clearTimeout(p),t.hoverTimer=null),"off"===f)return;return void(t.leaveTimer=setTimeout(()=>{n.emit("HOVER:OFF",g(u)),t.leaveTimer=null,t.lastEvent="off"},a.wait))}u&&(n.emit("HOVER:OFF",g(u)),t.leaveTimer=null,t.lastEvent="off"),clearTimeout(d),clearTimeout(p),t.hovered=m,t.hoverRectangle=m.getBoundingClientRect(),t.hoverTimer=setTimeout(()=>{n.emit("HOVER:ON",g(m)),t.hoverTimer=null,t.lastHoverTarget=m,t.lastEvent="on"},a.wait)}function g(e){const{left:n,top:o,width:s,height:c}=e.getBoundingClientRect(),u=window.scrollX,l=window.scrollY;return{target:e,context:t.currentContext.name,note:t.currentContext.note,event:i,dependencies:r,options:t.listenOptions,viewport:{X:u,Y:l,width:window.innerWidth,height:window.innerHeight},sizes:{width:s,height:c},position:{x:n,y:o},pagePosition:{x:n+u,y:o+l},type:"hover"}}}return{start:function(){t.active||(document.addEventListener("mousemove",s),t.active=!0)},stop:function(){t.active&&(document.removeEventListener("mousemove",s),i())}}}function v(e){const t=e.toUpperCase(),n=/HOVER\s*\:/i.test(t),o=t.indexOf(":");return n?`HOVER:${t.slice(o+1).trim()}`:e}function y(e,t){let n=0,o=!1;const i=t.defaultOptions,{regex:r,_defaults:s,ev:c}=e,{currentContext:{name:u},shortcuts:l,ERROR_EVENT_NAME:a}=t;return null==u||(Object.entries(l[u]).forEach(([s,c])=>{if(r.test(s)){if("HOVER:SETUP"===s){o=!0;const n=c.reduce((n,o)=>{const i=o({dependencies:e.extra,defaults:structuredClone(t.defaultOptions),options:t.listenOptions});return Object.assign(n,i)},i);return void Object.assign(t.listenOptions,n)}n++}}),o||Object.assign(t.listenOptions,i)),n}function w(e,t){const{ev:n,resetState:o,extra:i}=e;let r=null,s=null;function c(e){e.clientX,e.clientY;const{lastPosition:o,lastDirection:c,listenOptions:u,currentContext:l}=t,{scrollWait:a,endScrollWait:p,minSpace:d}=u;if(!o)return;let f=null;const h=window.scrollX,m=window.scrollY,g=Math.abs(m-o.y),v=Math.abs(h-o.x);if(g<d&&v<d)return;const y=[];g>=d&&(m>o.y?y.push("down"):y.push("up")),v>=d&&(h>o.x?y.push("right"):y.push("left")),f=y[0]||null;const w=e=>({x:h,y:m,direction:e,context:l.name,note:l.note,dependencies:i,options:t.listenOptions,viewport:{X:h,Y:m,width:window.innerWidth,height:window.innerHeight},type:"scroll"});y.forEach(e=>{const t=`SCROLL:${e.toUpperCase()}`;n.emit(t,w(e))}),clearTimeout(r),clearTimeout(s);const x=y[y.length-1]||null;r=setTimeout(()=>{},a),s=setTimeout(()=>n.emit("SCROLL:END",w(x)),p),t.lastPosition={x:h,y:m},t.lastDirection=f}return{start:function(){t.active||(t.lastPosition={x:window.scrollX,y:window.scrollY},window.addEventListener("scroll",c),t.active=!0)},stop:function(){t.active&&(window.removeEventListener("scroll",c),o())}}}function x(e){const t=e.toUpperCase(),n=/SCROLL\s*\:/i.test(t),o=t.indexOf(":");return n?`SCROLL:${t.slice(o+1).trim()}`:e}function O(e,t){let n=0,o=!1;const i=t.defaultOptions,{regex:r}=e,{currentContext:{name:s},shortcuts:c}=t;return null==s||(Object.entries(c[s]).forEach(([s,c])=>{if(r.test(s)){if("SCROLL:SETUP"===s){o=!0;const n=c.reduce((n,o)=>{const i=o({dependencies:e.extra,defaults:structuredClone(t.defaultOptions),options:t.listenOptions});return Object.assign(n,i)},i);return void Object.assign(t.listenOptions,n)}n++}}),o||Object.assign(t.listenOptions,i)),n}function E(t={}){const n={},o={},i=function(){let e=Object.assign(Object.create(null),{"*":[]}),t=Object.create(null),n=new Set,o=!1,i="";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)),"*"!==n&&e[n]&&0===e[n].length&&delete e[n],void(t[n]&&0===t[n].length&&delete t[n]);t[n]&&delete t[n],"*"===n?e["*"]=[]:e[n]&&delete e[n]},reset:function(){e=Object.assign(Object.create(null),{"*":[]}),t=Object.create(null),n=new Set},emit:function(){const[r,...s]=arguments;function c(t){let o=!1;"*"!==t&&(n.has(t)||(e[t].every(e=>{const t=e(...s);return"string"!=typeof t||"STOP"!==t.toUpperCase()||(o=!0,!1)}),o||e["*"].forEach(e=>e(r,...s))))}if(o&&(console.log(`${i} Event "${String(r)}" was triggered.`),s.length>0&&(console.log("Arguments:"),console.log(...s),console.log("^----"))),"*"!==r){if(t[r]){if(n.has(r))return;const o=t[r];delete t[r],o.forEach(e=>e(...s)),e[r]||e["*"].forEach(e=>e(r,...s))}e[r]&&c(r)}else Reflect.ownKeys(e).forEach(e=>c(e))},stop:function(o){if("*"===o){const o=Reflect.ownKeys(e),i=Reflect.ownKeys(t);return void(n=new Set([...i,...o]))}n.add(o)},start:function(e){"*"!==e?n.delete(e):n.clear()},debug:function(e,t){o=!!e,t&&"string"==typeof t&&(i=t)}}}(),r={currentContext:{name:null,note:null},shortcuts:{},plugins:[],exposeShortcut:!(!t.onShortcut||"function"!=typeof t.onShortcut)&&t.onShortcut,ERROR_EVENT_NAME:t.errorEventName?t.errorEventName:"@shortcuts-error"},s={ev:i,inAPI:n,API:o,extra:{emit:i.emit}};return o.enablePlugin=(e,t={})=>{if("function"!=typeof e)return;const o=e(n._setupPlugin,t),i=o.getPrefix(),s=n._systemAction(i,"none");-1===s?(r.plugins.push(o),o.unmute()):(o.destroy(),r.plugins[s].unmute())},o.disablePlugin=e=>{const t=n._systemAction(e,"destroy");-1!==t&&r.plugins.splice(t,1)},o.mutePlugin=e=>n._systemAction(e,"mute"),o.unmutePlugin=e=>n._systemAction(e,"unmute"),o.listPlugins=()=>r.plugins.map(e=>e.getPrefix()),o.getContext=()=>r.currentContext.name,o.getNote=()=>r.currentContext.note,o.setNote=(e=null)=>{"string"!=typeof e&&null!=e||(r.currentContext.note=e)},o.pause=(e="*")=>{const t=n._readShortcutWithPlugins(e);i.stop(t)},o.resume=(e="*")=>{const t=n._readShortcutWithPlugins(e);i.start(t)},o.emit=(e,...t)=>i.emit(n._readShortcutWithPlugins(e),{dependencies:s.extra,type:"custom"},...t),o.listContexts=()=>Object.keys(r.shortcuts),o.setDependencies=e=>Object.assign(s.extra,e),o.getDependencies=()=>s.extra,o.reset=function(){i.reset(),o.changeContext(),r.plugins.forEach(e=>e.destroy()),o.listContexts().map(e=>o.unload(e)),s.extra={emit:i.emit},r.exposeShortcut=null},Object.entries(e).forEach(([e,t])=>{e.startsWith("_")?n[e]=t(s,r):o[e]=t(s,r)}),o}var S=Object.freeze({__proto__:null,pluginClick:function(e,t={}){const n={_findTarget:s,_readClickEvent:l,regex:/CLICK\s*\:/i},o={active:!1,maxLeftClicks:1,maxRightClicks:1,defaultOptions:{mouseWait:320,clickTarget:["data-click","href"]},listenOptions:{mouseWait:320,clickTarget:["data-click","href"]},streamKeys:!(!t.streamKeys||"function"!=typeof t.streamKeys)&&t.streamKeys};return n.resetState=function(){},e({prefix:"click",_normalizeShortcutName:u,_registerShortcutEvents:a,_listenDOM:c,pluginState:o,deps:n})},pluginForm:function(e,t={}){const n={_defaults:h,regex:/FORM\s*\:/i},o={callbacks:{},typeFn:"",watchList:[],wait:{},defaultOptions:{},listenOptions:{}};return n.resetState=function(){o.callbacks={},o.typeFn="",o.watchList=[],o.wait={}},e({prefix:"form",_normalizeShortcutName:d,_registerShortcutEvents:f,_listenDOM:p,pluginState:o,deps:n})},pluginHover:function(e,t={}){const n={_findTarget:m,regex:/HOVER\s*\:/i},o={active:!1,hovered:!1,hoverRectangle:null,hoverTimer:null,leaveTimer:null,lastEvent:"",lastHoverTarget:null,defaultOptions:{hoverTarget:["data-hover"],wait:320},listenOptions:{hoverTarget:["data-hover"],wait:320}};return n.resetState=function(){o.active=!1,o.hovered=!1,o.hoverRectangle=null,clearTimeout(o.hoverTimer),clearTimeout(o.leaveTimer),o.hoverTimer=null,o.leaveTimer=null,o.lastHoverTarget=null},e({prefix:"hover",_normalizeShortcutName:v,_registerShortcutEvents:y,_listenDOM:g,pluginState:o,deps:n})},pluginKey:function(e,s={}){const c={_specialChars:r,_readKeyEvent:o,regex:/KEY\s*\:/i},u={active:!1,maxSequence:1,keyIgnore:null,defaultOptions:{keyWait:480},listenOptions:{keyWait:480},streamKeys:!(!s.streamKeys||"function"!=typeof s.streamKeys)&&s.streamKeys};return c.resetState=function(){u.active=!1,u.keyIgnore=null,u.maxSequence=1},e({prefix:"key",_normalizeShortcutName:n,_registerShortcutEvents:i,_listenDOM:t,pluginState:u,deps:c})},pluginScroll:function(e,t={}){const n={regex:/SCROLL\s*\:/i},o={active:!1,lastPosition:null,lastDirection:null,defaultOptions:{scrollWait:50,endScrollWait:400,minSpace:40},listenOptions:{scrollWait:50,endScrollWait:400,minSpace:40}};return n.resetState=function(){o.active=!1},e({prefix:"scroll",_normalizeShortcutName:x,_registerShortcutEvents:O,_listenDOM:w,pluginState:o,deps:n})},shortcuts:E});function T(e){return e?function(e){let t=e.map(e=>C()),n=t.map(e=>e.promise);t.promises=t;let o=k(Promise.all(n));function i(e){let t="pending";return e.then(()=>t="fulfilled").catch(()=>t="rejected"),t}function r(n,...o){t.forEach((t,r)=>n({value:e[r],done:t.done,cancel:t.cancel,timeout:t.timeout,state:i(t.promise)},...o))}const s={promise:Promise.all(n),promises:t,done:e=>{t.forEach(t=>t.done(e))},cancel:e=>{t.forEach(t=>t.cancel(e))},each:r,onComplete:o,timeout:()=>{}};return s.timeout=b(!0,s),s}(e):C()}function C(){let e,t;const n=new Promise((n,o)=>{e=n,t=o}),o={promise:n,promises:null,done:e,cancel:t,each:()=>{},onComplete:k(n),timeout:()=>{}};return o.timeout=b(!1,o),o.each=(n,...i)=>{n({value:null,done:e,cancel:t,timeout:o.timeout},...i)},o}function k(e){return function(t,n=null){null===n?e.then(e=>t(e)):e.then(e=>t(e),e=>n(e))}}function b(e,t){let n;return n=e?Promise.all(t.promises.map(e=>e.promise)):t.promise,function(e,o){let i,r=new Promise((t,r)=>{i=setTimeout(()=>{t(o),Promise.resolve(n)},e)});return n.then(()=>clearTimeout(i)),t.onComplete=k(Promise.race([n,r])),t}}function P({message:e,level:t,type:n,logLevel:o}){if(0===o)return null;if(o<t)return null;const i=`[Debug]: ${e}`;switch(n){case"warn":console.warn(i);break;case"error":console.error(i);break;default:console.log(i)}return i}function R(e={},t=P){return function({message:n,type:o,level:i,...r}){const{level:s,type:c,defaultMessageLevel:u}=Object.assign({},{level:1e3,type:"log",defaultMessageLevel:1},e);return o||(o=c),i||(i=u),t({message:n,type:o,level:i,logLevel:s,...r})}}function*L(e,t,n,o){let i=null,r=!0;if(null===e)return yield*o.map(e=>[e,"show"]),void(yield[n,"show"]);if(0!==o.length){if(o.includes(e)){for(let t=o.indexOf(e)+1;t<o.length;t++)yield[o[t],"show"];return void(yield[n,"show"])}if(!t)return yield[e,"hide"],void(yield*o.map(e=>[e,"show"]));if(o.every((e,n)=>t[n]===o[n]&&(i=n,!0)),null==i)return yield[e,"hide"],t.reverse(),yield*t.map(e=>[e,"hide"]),yield*o.map(e=>[e,"show"]),void(yield[n,"show"]);yield[e,"hide"];for(let e=t.length;e>i+1;e--)yield[t[e-1],"hide"];for(let e=i+1;e<o.length;e++)yield[o[e],"show"];yield[n,"show"]}else{if(yield[e,"hide"],t.includes(n)){let e=t.indexOf(n),o=t.filter((t,n)=>n>e);o.reverse(),yield*o.map(e=>[e,"hide"]),r=!1}else{let e=[...t];e.reverse(),yield*e.map(e=>[e,"hide"])}r&&(yield[n,"show"])}}function _(e){return function(t,...n){const{askForPromise:o,deps:i}=e;return function(){const e=o();return t({task:e,dependencies:i()},...n),e.promise}}}return T.sequence=function(e,...t){const n=T(),o=[];const i=function*(e){for(const t of e)yield t}(e);return function e(t,...r){t.done?n.done(o):t.value(...r).then(t=>{o.push(t),e(i.next(),...r,t)})}(i.next(),...t),n},T.all=function(e,...t){const n=T(),o=[],i=e.map((e,n)=>"function"==typeof e?e(...t).then(e=>o[n]=e):e.then(e=>o[n]=e));return Promise.all(i).then(()=>n.done(o)),n},function(e={logLevel:0}){const t=E({errorEventName:"@app-error"}),n=R({level:e.logLevel||1},e=>{const{type:n}=e;"error"===n&&t.getDependencies().emit("@app-error",e)}),o={currentScene:null,currentParents:null,sceneNames:new Set,scenes:{},opened:!1,jumpStack:[]},i={},r={shortcutMngr:t,findInstructions:L,askForPromise:T,setInstruction:_({askForPromise:T,deps:t.getDependencies}),log:n};return i.hide=function(e,t){return function(n=1){const{askForPromise:o,shortcutMngr:i,setInstruction:r}=e,{currentScene:s,currentParents:c,scenes:u}=t,l=o(),a=[],p=c.length>0;i.pause(),a.push(r(u[s].hide)),p||(t.currentScene=null);let d=[];return p&&"*"===n&&(d=[...c].reverse()),p&&!["*",1].includes(n)&&(d=c.slice("-"+(n-1)).reverse()),d.forEach(e=>{a.push(r(u[e].hide)),t.currentScene=u[e].parents.at(-1)??null,t.currentParents=t.currentScene?u[t.currentScene].parents:[]}),o.sequence(a).onComplete(()=>{i.changeContext(t.currentScene),l.done()}),l.promise}}(r,o),i.listShortcuts=function(e,t){return function(e){const{scenes:n,sceneNames:o}=t;if(!o.has(e))return null;const{show:i,hide:r,parents:s,beforeHide:c,afterShow:u,...l}=n[e];return Object.keys(l)}}(0,o),i.setScenes=function(e,t){return function(n){const{shortcutMngr:o,log:i}=e;n.forEach(e=>{if(null==e)return;const{name:n,scene:r}=e;if(!n)return void i({message:"Scene name is not defined",level:1,type:"error"});if(null==r)return void i({message:`Scene ${n} is not defined`,level:1,type:"error"});r.parents||(r.parents=[]),t.scenes[n]=r,t.sceneNames.add(n);const{show:s,hide:c,parents:u,...l}=r,a={};a[n]=l,o.load(a)})}}(r,o),i.show=function(e,t){return function({scene:n,options:o={ssr:!1}},...i){const{shortcutMngr:r,askForPromise:s,log:c,findInstructions:u,setInstruction:l}=e,a=s(),p=s(),{opened:d,scenes:f,sceneNames:h,currentScene:m}=t;return m&&"function"==typeof f[m].beforeHide?(0,f[m].beforeHide)({done:p.done,dependencies:r.getDependencies()}):p.done(!0),p.onComplete(e=>{if(!e)return a.done(),a.promise;if(!h.has(n))return c({message:`Scene "${n}" is not available.`,level:1,type:"error"}),a.done(),a.promise;if(!d&&o.ssr)return t.opened=!0,t.currentScene=n,r.changeContext(n),a.done(),a.promise;const{show:p,parents:m=[]}=f[n];if(t.currentParents||(t.currentParents=[]),"*"===m[0])return l(p,...i)().then(()=>a.done()),t.currentParents.push(t.currentScene),t.currentScene=n,r.changeContext(n),a.promise;if(0!==m.length&&!m.every(e=>h.has(e)))return c({message:`Some of '${n}' parent scenes are not set.`,level:1,type:"error"}),a.done(),a.promise;function g([e,n]){if("show"===n)t.currentScene&&(t.currentParents=[...f[t.currentScene].parents]),t.currentScene=e;else{let n="*"===f[e].parents[0]?t.currentParents.pop():f[e].parents.at(-1);t.currentScene=n}return f[e][n]}const v=u(t.currentScene,t.currentParents,n,m),y=[];for(let e of v){const t=g(e);y.push(l(t,...i))}s.sequence(y).onComplete(()=>{t.opened=!0,t.currentScene=n,t.currentParents=f[n].parents?[...f[n].parents]:null,r.changeContext(n),"function"==typeof f[n].afterShow&&f[n].afterShow({dependencies:r.getDependencies(),done:()=>{}}),a.done()})}),a.promise}}(r,o),i.jump=function(e,t){return function({scene:n},...o){return e.jumpStack.push(e.currentScene),t({scene:n},...o)}}(o,i.show),i.jumpBack=function(e,t){return function({hops:n}={hops:1},...o){for(let t=0;t<n-1;t++)e.jumpStack.pop();if(0===e.jumpStack.length)return;const i=e.jumpStack.pop();return t({scene:i},...o)}}(o,i.show),i.jumpsReset=function(e){return function(){e.jumpStack=[]}}(o),i.loadPlugins=async function(e){const t=e.map(e=>`plugin${e}`),n=await Promise.resolve().then(function(){return S});return t.map(e=>n[e])},i.setDependencies=e=>t.setDependencies(e),i.getDependencies=()=>t.getDependencies(),i.setNote=e=>t.setNote(e),i.listScenes=()=>[...o.sceneNames],i.enablePlugin=(e,n)=>t.enablePlugin(e,n),i.disablePlugin=e=>t.disablePlugin(e),i.getState=()=>({scene:o.currentScene,parents:o.currentParents,opened:o.opened}),i.emit=(e,...n)=>t.getDependencies().emit(e,...n),i}});
|
package/package.json
CHANGED
package/src/main.js
CHANGED
|
@@ -42,8 +42,11 @@ function main ( cfg= {logLevel:0} ) {
|
|
|
42
42
|
, logLevel = cfg.logLevel || 1
|
|
43
43
|
, log = createLog ({ level:logLevel }, (arg) => {
|
|
44
44
|
const { type } = arg;
|
|
45
|
-
if ( type === 'error' ) {
|
|
46
|
-
shortcutMngr.emit
|
|
45
|
+
if ( type === 'error' ) {
|
|
46
|
+
// Use the raw emitter (not shortcutMngr.emit) so '@app-error'
|
|
47
|
+
// handlers keep receiving the log entry as their sole argument -
|
|
48
|
+
// shortcutMngr.emit now prepends a { dependencies, type } context object.
|
|
49
|
+
shortcutMngr.getDependencies().emit ( '@app-error', arg )
|
|
47
50
|
}
|
|
48
51
|
})
|
|
49
52
|
, state = {
|
|
@@ -164,7 +167,9 @@ function main ( cfg= {logLevel:0} ) {
|
|
|
164
167
|
* @param {...*} args - Extra data to pass to the listeners
|
|
165
168
|
* @returns void
|
|
166
169
|
*/
|
|
167
|
-
|
|
170
|
+
// Use the raw emitter (not shortcutMngr.emit) so listeners keep receiving exactly the
|
|
171
|
+
// args passed here - shortcutMngr.emit prepends a { dependencies, type } context object.
|
|
172
|
+
API.emit = ( event, ...args ) => shortcutMngr.getDependencies().emit ( event, ...args )
|
|
168
173
|
return API
|
|
169
174
|
} // main func.
|
|
170
175
|
|
package/src/methods/hide.js
CHANGED
|
@@ -17,31 +17,31 @@ return function hide ( endSteps=1 ) {
|
|
|
17
17
|
, instructions = []
|
|
18
18
|
, hasParents = currentParents.length > 0
|
|
19
19
|
;
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
|
|
22
21
|
shortcutMngr.pause () // Stop all shortcuts
|
|
23
22
|
instructions.push ( setInstruction ( scenes[currentScene].hide )) // Set instruction to hide current scene
|
|
24
23
|
|
|
25
24
|
if ( !hasParents ) state.currentScene = null
|
|
26
|
-
|
|
25
|
+
|
|
26
|
+
let namesToHide = []
|
|
27
27
|
if ( hasParents && endSteps === '*' ) {
|
|
28
|
-
[...currentParents].reverse()
|
|
29
|
-
el = state.currentParents.at ( -1 )
|
|
30
|
-
state.currentScene = el
|
|
31
|
-
instructions.push ( setInstruction ( scenes[name].hide))
|
|
32
|
-
})
|
|
28
|
+
namesToHide = [...currentParents].reverse ()
|
|
33
29
|
}
|
|
34
30
|
if ( hasParents && ![ '*', 1].includes(endSteps) ) {
|
|
35
|
-
currentParents.slice ( `-${endSteps-1}` ).reverse()
|
|
36
|
-
el = state.currentParents.at ( -1 )
|
|
37
|
-
state.currentScene = el
|
|
38
|
-
instructions.push ( setInstruction (scenes[name].hide))
|
|
39
|
-
})
|
|
31
|
+
namesToHide = currentParents.slice ( `-${endSteps-1}` ).reverse ()
|
|
40
32
|
}
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
|
|
34
|
+
namesToHide.forEach ( name => {
|
|
35
|
+
instructions.push ( setInstruction ( scenes[name].hide))
|
|
36
|
+
// Climb to the parent of the scene just hidden - same technique 'show' uses for its 'hide' steps.
|
|
37
|
+
state.currentScene = scenes[name].parents.at ( -1 ) ?? null
|
|
38
|
+
state.currentParents = state.currentScene ? scenes[state.currentScene].parents : []
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const goingTask = askForPromise.sequence ( instructions );
|
|
42
|
+
goingTask.onComplete ( () => {
|
|
43
43
|
shortcutMngr.changeContext ( state.currentScene ) // If state.currentScene is null, then all shortcuts are switched off and currentContext is null
|
|
44
|
-
hideTask.done ()
|
|
44
|
+
hideTask.done ()
|
|
45
45
|
})
|
|
46
46
|
return hideTask.promise
|
|
47
47
|
}} // hide func.
|
|
@@ -10,7 +10,7 @@ function listShortcuts ( dependencies, state ) {
|
|
|
10
10
|
return function listShortcuts ( sceneName ) {
|
|
11
11
|
const { scenes, sceneNames } = state;
|
|
12
12
|
if ( ! sceneNames.has ( sceneName ) ) return null
|
|
13
|
-
const { show, hide, parents,
|
|
13
|
+
const { show, hide, parents, beforeHide, afterShow, ...shortcuts } = scenes[sceneName];
|
|
14
14
|
return Object.keys ( shortcuts )
|
|
15
15
|
}} // listShortcuts func.
|
|
16
16
|
|
package/src/methods/show.js
CHANGED
|
@@ -59,12 +59,15 @@ function show ( dependencies, state ) {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
const { show, parents=[] } = scenes[requestedScene];
|
|
62
|
-
|
|
62
|
+
|
|
63
|
+
if ( !state.currentParents ) state.currentParents = []
|
|
64
|
+
|
|
63
65
|
if ( parents[0] === '*' ) {
|
|
64
66
|
const overlayTask = setInstruction(show, ...args)()
|
|
65
67
|
overlayTask.then ( () => showTask.done () )
|
|
66
68
|
state.currentParents.push ( state.currentScene )
|
|
67
69
|
state.currentScene = requestedScene
|
|
70
|
+
shortcutMngr.changeContext ( requestedScene ) // Activate the overlay scene's own shortcuts
|
|
68
71
|
return showTask.promise
|
|
69
72
|
}
|
|
70
73
|
|
|
@@ -86,14 +89,18 @@ function show ( dependencies, state ) {
|
|
|
86
89
|
state.currentScene = name
|
|
87
90
|
}
|
|
88
91
|
else {
|
|
89
|
-
|
|
92
|
+
// Wildcard overlays aren't climbing their own declared parents ('*' isn't a
|
|
93
|
+
// real scene) - they climb back to whatever scene they were shown on top of.
|
|
94
|
+
let el = ( scenes[name].parents[0] === '*' )
|
|
95
|
+
? state.currentParents.pop ()
|
|
96
|
+
: scenes[name].parents.at ( -1 )
|
|
97
|
+
;
|
|
90
98
|
state.currentScene = el
|
|
91
99
|
}
|
|
92
100
|
return scenes[name][action]
|
|
93
101
|
} // getStep func.
|
|
94
102
|
|
|
95
|
-
|
|
96
|
-
const
|
|
103
|
+
const
|
|
97
104
|
g = findInstructions ( state.currentScene, state.currentParents, requestedScene, parents )
|
|
98
105
|
, instructions = []
|
|
99
106
|
;
|
|
@@ -109,7 +116,9 @@ function show ( dependencies, state ) {
|
|
|
109
116
|
goingTask.onComplete ( () => {
|
|
110
117
|
state.opened = true
|
|
111
118
|
state.currentScene = requestedScene
|
|
112
|
-
state.currentParents
|
|
119
|
+
// Copy - never alias state.currentParents to a scene's own 'parents' array,
|
|
120
|
+
// or later mutations (eg. the wildcard-overlay push above) corrupt the scene definition.
|
|
121
|
+
state.currentParents = scenes[requestedScene].parents ? [...scenes[requestedScene].parents] : null
|
|
113
122
|
shortcutMngr.changeContext ( requestedScene )
|
|
114
123
|
if ( typeof scenes[requestedScene].afterShow === 'function' ) scenes[requestedScene].afterShow ({ dependencies: shortcutMngr.getDependencies(), done: () => {} })
|
|
115
124
|
showTask.done ()
|
package/test/02-cuts.test.js
CHANGED
|
@@ -252,6 +252,30 @@ describe ( 'Cuts integration', () => {
|
|
|
252
252
|
|
|
253
253
|
|
|
254
254
|
|
|
255
|
+
it ( 'List shortcuts excludes beforeHide and afterShow', async () => {
|
|
256
|
+
// Regression test: listShortcuts used to destructure the old
|
|
257
|
+
// 'beforeUnload'/'afterLoad' names, so the real 'beforeHide'/'afterShow'
|
|
258
|
+
// scene methods leaked into the returned shortcuts list.
|
|
259
|
+
const script = cuts ()
|
|
260
|
+
const scenes = [
|
|
261
|
+
{
|
|
262
|
+
name: 'top'
|
|
263
|
+
, scene: {
|
|
264
|
+
show : ({task}) => task.done(),
|
|
265
|
+
hide : ({task}) => task.done(),
|
|
266
|
+
beforeHide : ({ done }) => done ( true ),
|
|
267
|
+
afterShow : () => {},
|
|
268
|
+
'click: left-1' : () => {}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
];
|
|
272
|
+
|
|
273
|
+
script.setScenes ( scenes )
|
|
274
|
+
expect ( script.listShortcuts( 'top' ) ).toEqual ( ['click: left-1'] )
|
|
275
|
+
}) // it List shortcuts excludes beforeHide and afterShow
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
|
|
255
279
|
it ( 'Jump functionality', async () => {
|
|
256
280
|
const script = cuts({ logLevel : 0 });
|
|
257
281
|
const calls = [];
|
|
@@ -409,4 +433,149 @@ describe ( 'Cuts integration', () => {
|
|
|
409
433
|
|
|
410
434
|
|
|
411
435
|
|
|
436
|
+
it ( 'Show scene with wildcard parent as the very first scene', async () => {
|
|
437
|
+
// Regression test: state.currentParents starts as null, and the
|
|
438
|
+
// wildcard branch used to push into it before it was initialized,
|
|
439
|
+
// crashing on the first-ever show() call.
|
|
440
|
+
const script = cuts();
|
|
441
|
+
const calls = [];
|
|
442
|
+
const scenes = [
|
|
443
|
+
{
|
|
444
|
+
name: 'overlay'
|
|
445
|
+
, scene: {
|
|
446
|
+
show: ({task}) => { calls.push('show overlay'); task.done() },
|
|
447
|
+
hide: ({task}) => { calls.push('hide overlay'); task.done() },
|
|
448
|
+
parents: ['*']
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
];
|
|
452
|
+
|
|
453
|
+
script.setScenes ( scenes );
|
|
454
|
+
|
|
455
|
+
await script.show ({ scene: 'overlay' });
|
|
456
|
+
expect ( calls ).toEqual (['show overlay']);
|
|
457
|
+
expect ( script.getState().scene ).toEqual ( 'overlay' );
|
|
458
|
+
expect ( script.getState().parents ).toEqual ( [null] ); // No previous scene, saved as null
|
|
459
|
+
}) // it Show scene with wildcard parent as the very first scene
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
it ( 'Hide with wildcard steps resets state to the root', async () => {
|
|
464
|
+
// Regression test: hide('*') used to hide every scene correctly but left
|
|
465
|
+
// 'currentScene'/'currentParents' stale instead of resetting them to the root.
|
|
466
|
+
const calls = [];
|
|
467
|
+
const script = cuts();
|
|
468
|
+
const scenes = [
|
|
469
|
+
{ name: 'top' , scene: { show: ({task}) => { calls.push('show top'); task.done() }, hide: ({task}) => { calls.push('hide top'); task.done() } } },
|
|
470
|
+
{ name: 'mid' , scene: { show: ({task}) => { calls.push('show mid'); task.done() }, hide: ({task}) => { calls.push('hide mid'); task.done() }, parents: ['top'] } },
|
|
471
|
+
{ name: 'deep', scene: { show: ({task}) => { calls.push('show deep'); task.done() }, hide: ({task}) => { calls.push('hide deep'); task.done() }, parents: ['top', 'mid'] } }
|
|
472
|
+
];
|
|
473
|
+
|
|
474
|
+
script.setScenes ( scenes );
|
|
475
|
+
await script.show ({ scene: 'deep' });
|
|
476
|
+
calls.length = 0;
|
|
477
|
+
|
|
478
|
+
await script.hide ( '*' );
|
|
479
|
+
expect ( calls ).toEqual ([ 'hide deep', 'hide mid', 'hide top' ]);
|
|
480
|
+
expect ( script.getState() ).toEqual ({ scene: null, parents: [], opened: true });
|
|
481
|
+
}) // it Hide with wildcard steps resets state to the root
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
it ( 'emit() passes args through without an injected context object', async () => {
|
|
486
|
+
// Regression test: shortcuts@4.1.1's own emit() now prepends a
|
|
487
|
+
// { dependencies, type: 'custom' } object to support event chaining.
|
|
488
|
+
// cuts.emit() must keep forwarding exactly what the caller passed.
|
|
489
|
+
const received = [];
|
|
490
|
+
const script = cuts();
|
|
491
|
+
const scenes = [
|
|
492
|
+
{
|
|
493
|
+
name: 'top'
|
|
494
|
+
, scene: {
|
|
495
|
+
show : ({task}) => task.done(),
|
|
496
|
+
hide : ({task}) => task.done(),
|
|
497
|
+
'@custom-event' : ( payload ) => received.push ( payload )
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
];
|
|
501
|
+
|
|
502
|
+
script.setScenes ( scenes );
|
|
503
|
+
await script.show ({ scene: 'top' });
|
|
504
|
+
|
|
505
|
+
script.emit ( '@custom-event', { foo: 'bar' } );
|
|
506
|
+
expect ( received ).toEqual ([{ foo: 'bar' }]);
|
|
507
|
+
}) // it emit() passes args through without an injected context object
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
it ( 'Wildcard overlay scene activates its own shortcuts context', async () => {
|
|
512
|
+
// Regression test: showing a '*'-parented scene never switched the
|
|
513
|
+
// shortcuts context to it, so its own shortcut/event handlers never fired.
|
|
514
|
+
const seen = [];
|
|
515
|
+
const script = cuts();
|
|
516
|
+
const scenes = [
|
|
517
|
+
{
|
|
518
|
+
name: 'base'
|
|
519
|
+
, scene: {
|
|
520
|
+
show : ({task}) => task.done(),
|
|
521
|
+
hide : ({task}) => task.done(),
|
|
522
|
+
'@ping' : () => seen.push ( 'base' )
|
|
523
|
+
}
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
name: 'overlay'
|
|
527
|
+
, scene: {
|
|
528
|
+
show : ({task}) => task.done(),
|
|
529
|
+
hide : ({task}) => task.done(),
|
|
530
|
+
parents: ['*'],
|
|
531
|
+
'@ping' : () => seen.push ( 'overlay' )
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
];
|
|
535
|
+
|
|
536
|
+
script.setScenes ( scenes );
|
|
537
|
+
await script.show ({ scene: 'base' });
|
|
538
|
+
await script.show ({ scene: 'overlay' });
|
|
539
|
+
|
|
540
|
+
script.emit ( '@ping' );
|
|
541
|
+
expect ( seen ).toEqual ([ 'overlay' ]);
|
|
542
|
+
}) // it Wildcard overlay scene activates its own shortcuts context
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
it ( 'Showing a wildcard overlay does not corrupt the underlying scene, and returning to it works', async () => {
|
|
547
|
+
// Regression test: state.currentParents used to be aliased directly to a
|
|
548
|
+
// scene's own 'parents' array, so pushing onto it (done when showing a
|
|
549
|
+
// wildcard overlay) permanently mutated that scene's 'parents' definition -
|
|
550
|
+
// which then crashed when navigating back to it.
|
|
551
|
+
const calls = [];
|
|
552
|
+
const script = cuts();
|
|
553
|
+
const baseScene = {
|
|
554
|
+
show : ({task}) => { calls.push('show base'); task.done() }
|
|
555
|
+
, hide : ({task}) => { calls.push('hide base'); task.done() }
|
|
556
|
+
};
|
|
557
|
+
const scenes = [
|
|
558
|
+
{ name: 'base', scene: baseScene },
|
|
559
|
+
{
|
|
560
|
+
name: 'overlay'
|
|
561
|
+
, scene: {
|
|
562
|
+
show : ({task}) => { calls.push('show overlay'); task.done() },
|
|
563
|
+
hide : ({task}) => { calls.push('hide overlay'); task.done() },
|
|
564
|
+
parents: ['*']
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
];
|
|
568
|
+
|
|
569
|
+
script.setScenes ( scenes );
|
|
570
|
+
await script.show ({ scene: 'base' });
|
|
571
|
+
await script.show ({ scene: 'overlay' });
|
|
572
|
+
|
|
573
|
+
expect ( baseScene.parents ).toEqual ([]); // Not corrupted into ['base']
|
|
574
|
+
|
|
575
|
+
await script.show ({ scene: 'base' }); // Used to throw
|
|
576
|
+
expect ( script.getState() ).toEqual ({ scene: 'base', parents: [], opened: true });
|
|
577
|
+
}) // it Showing a wildcard overlay does not corrupt the underlying scene, and returning to it works
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
|
|
412
581
|
}) // describe
|
package/types/main.d.ts
CHANGED
|
@@ -89,7 +89,7 @@ declare function main(cfg?: {
|
|
|
89
89
|
* @param {...*} args - Extra data to pass to the listeners
|
|
90
90
|
* @returns void
|
|
91
91
|
*/
|
|
92
|
-
emit: (event: string, ...args: any[]) =>
|
|
92
|
+
emit: (event: string, ...args: any[]) => any;
|
|
93
93
|
};
|
|
94
94
|
export default main;
|
|
95
95
|
//# sourceMappingURL=main.d.ts.map
|
package/types/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.js"],"names":[],"mappings":"AAsCA,iBAAS,IAAI,CAAG,GAAG;IAAG,QAAQ;CAAG;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.js"],"names":[],"mappings":"AAsCA,iBAAS,IAAI,CAAG,GAAG;IAAG,QAAQ;CAAG;;;;;;;;;;;;;;;;;IA0CzB;;;;;;;;;;;;;;OAcG;2BAPQ,KAAK,+CAAc,KACjB,OAAO,CAAE,UAAU,CAAC;IAajC;;;;;OAKG;4BAFQ,GAAC;IAKZ;;;;OAIG;2BADU,GAAC;IAId;;;;OAIG;oBAFQ,MAAM;IAKjB;;;;OAIG;sBADU,KAAK,CAAE,MAAM,CAAC;IAI3B;;;;;;OAMG;+CAFQ,GAAC;IAKZ;;;;;OAKG;gCAFQ,MAAM;IAKjB;;;;;;;OAOG;oBAJU,MAAM;IAYlB;;;;;;OAMG;kBAHQ,MAAM,WACH,GAAC,EAAA;EAOvB;eAIc,IAAI"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"show.d.ts","sourceRoot":"","sources":["../../src/methods/show.js"],"names":[],"mappings":"AAIA,iBAAS,IAAI,CAAG,YAAY,KAAA,EAAE,KAAK,KAAA,wCAKhC;IAAwB,KAAK,EAArB,MAAM,CACd;IAAyB,OAAO,AAAhC,CAEA,EADA;QAAiC,GAAG,EAA5B,OAAO,CACf;KAAA,CAAA;CAAA,
|
|
1
|
+
{"version":3,"file":"show.d.ts","sourceRoot":"","sources":["../../src/methods/show.js"],"names":[],"mappings":"AAIA,iBAAS,IAAI,CAAG,YAAY,KAAA,EAAE,KAAK,KAAA,wCAKhC;IAAwB,KAAK,EAArB,MAAM,CACd;IAAyB,OAAO,AAAhC,CAEA,EADA;QAAiC,GAAG,EAA5B,OAAO,CACf;KAAA,CAAA;CAAA,mCAqHF;eAIc,IAAI"}
|