@peter.naydenov/cuts 2.1.2 → 2.1.3
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 +9 -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 +6 -4
- package/src/methods/hide.js +14 -1
- package/test/02-cuts.test.js +80 -0
- package/types/main.d.ts +1 -3
- package/types/main.d.ts.map +1 -1
- package/types/methods/hide.d.ts.map +1 -1
package/Changelog.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
|
|
5
|
+
## 2.1.3 ( 2026-07-09 )
|
|
6
|
+
- [x] Fix: `getState()` returned a live reference to `state.currentParents` instead of a copy; a caller mutating the returned array corrupted cuts' own internal state;
|
|
7
|
+
- [x] Fix: `hide()` on a wildcard-overlay scene left `currentScene`/`currentParents` pointing at the (now-hidden) overlay instead of climbing back to the scene it was shown on top of, so that scene's shortcuts context never reactivated;
|
|
8
|
+
- [x] Fix: `cuts({ logLevel: 0 })` didn't actually silence errors - `cfg.logLevel || 1` treated the explicit `0` as falsy and forced it back to `1`, and even after correcting that, the internal log callback never checked the configured level before emitting `@app-error`;
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
4
12
|
## 2.1.2 ( 2026-07-09 )
|
|
5
13
|
- [x] Fix: `show()` crashed when a scene with `parents: ['*']` was the very first scene shown (`state.currentParents` was read before being initialized);
|
|
6
14
|
- [x] Fix: `hide()` (including `hide('*')` and multi-step `hide(n)`) left `currentScene`/`currentParents` stale instead of updating them as each parent scene was closed;
|
|
@@ -12,6 +20,7 @@
|
|
|
12
20
|
|
|
13
21
|
|
|
14
22
|
|
|
23
|
+
|
|
15
24
|
## 2.1.1 ( 2026-07-08 )
|
|
16
25
|
- [x] Dependency update. @peter.naydenov/shortcuts - v.4.1.2
|
|
17
26
|
- [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={
|
|
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={}){const c=e.shortcuts({errorEventName:"@app-error"}),u=o.logLevel??1,i=r({level:u},e=>{const{type:n,logLevel:r}=e;0!==r&&"error"===n&&c.getDependencies().emit("@app-error",e)}),l={currentScene:null,currentParents:null,sceneNames:new Set,scenes:{},opened:!1,jumpStack:[]},a={},p={shortcutMngr:c,findInstructions:t,askForPromise:n,setInstruction:s({askForPromise:n,deps:c.getDependencies}),log:i};return a.hide=function(e,n){return function(r=1){const{askForPromise:t,shortcutMngr:s,setInstruction:o}=e,{currentScene:c,currentParents:u,scenes:i}=n,l=t(),a=[],p=u.length>0;s.pause(),a.push(o(i[c].hide)),p||(n.currentScene=null);let d=[];return p&&"*"===r&&(d=[...u].reverse()),p&&!["*",1].includes(r)&&(d=u.slice("-"+(r-1)).reverse()),p&&0===d.length&&"*"===i[c].parents[0]&&(n.currentScene=n.currentParents.pop(),n.currentParents=n.currentScene?[...i[n.currentScene].parents]:[]),d.forEach(e=>{a.push(o(i[e].hide)),n.currentScene="*"===i[e].parents[0]?null:i[e].parents.at(-1)??null,n.currentParents=n.currentScene?i[n.currentScene].parents:[]}),t.sequence(a).onComplete(()=>{s.changeContext(n.currentScene),l.done()}),l.promise}}(p,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:u,afterShow:i,...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:u,parents:i,...l}=o,a={};a[r]=l,t.load(a)})}}(p,l),a.show=function(e,n){return function({scene:r,options:t={ssr:!1}},...s){const{shortcutMngr:o,askForPromise:c,log:u,findInstructions:i,setInstruction:l}=e,a=c(),p=c(),{opened:d,scenes:h,sceneNames:f,currentScene:m}=n;return m&&"function"==typeof h[m].beforeHide?(0,h[m].beforeHide)({done:p.done,dependencies:o.getDependencies()}):p.done(!0),p.onComplete(e=>{if(!e)return a.done(),a.promise;if(!f.has(r))return u({message:`Scene "${r}" is not available.`,level:1,type:"error"}),a.done(),a.promise;if(!d&&t.ssr)return n.opened=!0,n.currentScene=r,o.changeContext(r),a.done(),a.promise;const{show:p,parents:m=[]}=h[r];if(n.currentParents||(n.currentParents=[]),"*"===m[0])return l(p,...s)().then(()=>a.done()),n.currentParents.push(n.currentScene),n.currentScene=r,o.changeContext(r),a.promise;if(0!==m.length&&!m.every(e=>f.has(e)))return u({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=[...h[n.currentScene].parents]),n.currentScene=e;else{let r="*"===h[e].parents[0]?n.currentParents.pop():h[e].parents.at(-1);n.currentScene=r}return h[e][r]}const S=i(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=h[r].parents?[...h[r].parents]:null,o.changeContext(r),"function"==typeof h[r].afterShow&&h[r].afterShow({dependencies:o.getDependencies(),done:()=>{}}),a.done()})}),a.promise}}(p,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?[...l.currentParents]: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={
|
|
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={}){const c=e({errorEventName:"@app-error"}),i=o.logLevel??1,u=r({level:i},e=>{const{type:n,logLevel:r}=e;0!==r&&"error"===n&&c.getDependencies().emit("@app-error",e)}),l={currentScene:null,currentParents:null,sceneNames:new Set,scenes:{},opened:!1,jumpStack:[]},a={},p={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=[],p=i.length>0;s.pause(),a.push(o(u[c].hide)),p||(n.currentScene=null);let d=[];return p&&"*"===r&&(d=[...i].reverse()),p&&!["*",1].includes(r)&&(d=i.slice("-"+(r-1)).reverse()),p&&0===d.length&&"*"===u[c].parents[0]&&(n.currentScene=n.currentParents.pop(),n.currentParents=n.currentScene?[...u[n.currentScene].parents]:[]),d.forEach(e=>{a.push(o(u[e].hide)),n.currentScene="*"===u[e].parents[0]?null: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}}(p,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)})}}(p,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(),p=c(),{opened:d,scenes:f,sceneNames:h,currentScene:m}=n;return m&&"function"==typeof f[m].beforeHide?(0,f[m].beforeHide)({done:p.done,dependencies:o.getDependencies()}):p.done(!0),p.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(!d&&t.ssr)return n.opened=!0,n.currentScene=r,o.changeContext(r),a.done(),a.promise;const{show:p,parents:m=[]}=f[r];if(n.currentParents||(n.currentParents=[]),"*"===m[0])return l(p,...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}}(p,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?[...l.currentParents]:l.currentParents,opened:l.opened}),a.emit=(e,...n)=>c.getDependencies().emit(e,...n),a}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: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}});
|
|
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,r])=>{const i=e(o);i!==o&&(delete n[t][o],n[t][i]=r)})})}},_readShortcutWithPlugins:function(e,t){return function(n){const{inAPI:o}=e,r=n.split(":")[0].toLowerCase().trim(),i=o._systemAction(r,"none");let s=n;return-1!==i&&(s=t.plugins[i].shortcutName(n)),s}},_setupPlugin:function(e,t){const{inAPI:n}=e,{currentContext:o,shortcuts:r,exposeShortcut:i,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=r,p.exposeShortcut=i,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:r}=t,{ev:i}=e;return function(e=!1){const s=o.name;if(!e)return i.reset(),void(o.name=null);s!==e&&(n[e]?(n[s]&&i.reset(),o.name=e,t.plugins.forEach(t=>t.contextChange(e)),Object.entries(n[e]).forEach(([e,t])=>{e.includes(":SETUP")||t.forEach(t=>i.on(e,t))}),i.on("*",(...e)=>{t.exposeShortcut&&t.exposeShortcut(...e)})):i.emit(r,`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:r,getContext:i}}=e;return function(e){const t=i(),s=o.map(e=>e.getPrefix().toUpperCase());let c=!1;Object.entries(e).forEach(([e,r])=>{e===t&&(c=!0),n[e]={},Object.entries(r).forEach(([t,r])=>{let i=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];i=o[e].shortcutName(t)}r instanceof Function&&(r=[r]),n[e][i]=r})}),c&&(r(),r(t))}},unload:function(e,t){const{currentContext:n,shortcuts:o,ERROR_EVENT_NAME:r}=t,{ev:i}=e;return function(e){n.name!==e?o[e]?delete o[e]:i.emit(r,`Context '${e}' does not exist`):i.emit(r,`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:r,extra:i,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:i,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 r=`KEY:${e.join(",")}`;n.emit(r,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(r(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(r(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:r}=e,i=t(),s=e.code.replace("Key","").replace("Digit",""),c=[];return r&&c.push("CTRL"),n&&c.push("SHIFT"),o&&c.push("ALT"),i.hasOwnProperty(s)?c.push(i[s].toUpperCase()):["ControlLeft","ControlRight","ShiftLeft","ShiftRight","AltLeft","AltRight","Meta"].includes(s)||c.push(s.toUpperCase()),c.sort()}function r(e,t){let n=0,o=!1;const r=t.defaultOptions,{regex:i}=e,{currentContext:{name:s},shortcuts:c}=t;return null==s?0:(Object.entries(c[s]).forEach(([s,c])=>{if(!i.test(s))return;if("KEY:SETUP"===s){o=!0;const n=c.reduce((n,o)=>{const r=o({dependencies:e.extra,defaults:structuredClone(t.defaultOptions),options:t.listenOptions});return Object.assign(n,r)},r);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,r),n)}function i(){return{ArrowLeft:"LEFT",ArrowUp:"UP",ArrowRight:"RIGHT",ArrowDown:"DOWN",Enter:"ENTER",NumpadEnter:"ENTER",Escape:"ESC",Backspace:"BACKSPACE",Space:"SPACE",Tab:"TAB",Backquote:"`",BracketLeft:"[",BracketRight:"]",Equal:"=",Slash:"/",Backslash:"\\",IntlBackslash:"`",F1:"F1",F2:"F2",F3:"F3",F4:"F4",F5:"F5",F6:"F6",F7:"F7",F8:"F8",F9:"F9",F10:"F10",F11:"F11",F12:"F12"}}function s(e,t,n){const{listenOptions:{clickTarget:o}}=t,r=n;return r===document.body?null:o.some(e=>r.hasAttribute(e))?r:s(e,t,r.parentNode)}function c(e,t){const{ev:n,_findTarget:o,_readClickEvent:r,extra:i}=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=r(l,d),v={target:u,x:l.clientX,y:l.clientY,context:c.name,note:c.note,options:t.listenOptions,event:l,dependencies:i,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 r=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")&&(r=1),u&&"A"===u.tagName&&(r=1),l=n,d++,d>=r)return f(),void(r>1&&(p=setTimeout(()=>p=null,s.mouseWait)));a=setTimeout(f,s.mouseWait)}}function m(n){let r=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")&&(r=1),u&&"A"===u.tagName&&(r=1),l=n,d++,d>=r)return f(),void(r>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"],r=["ALT","SHIFT","CTRL"];let i=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)?i=e:r.includes(e)?c.push(e):isNaN(e)||(s=e)}),`CLICK:${i}-${s}${c.length>0?"-":""}${c.sort().join("-")}`):e}function l(e,t){const{shiftKey:n,altKey:o,ctrlKey:r,key:i,button:s}=e,c=`CLICK:${["LEFT","MIDDLE","RIGHT"][s]}-${t}`,u=[];return r&&u.push("CTRL"),n&&u.push("SHIFT"),o&&u.push("ALT"),u.length>0?`${c}${u.length>0?"-":""}${u.sort().join("-")}`:`${c}`}function a(e,t){let n=0,o=!1;const r=t.defaultOptions,{regex:i}=e,{listenOptions:s,currentContext:{name:c},shortcuts:u}=t;return null==c||(Object.entries(u[c]).forEach(([c,u])=>{if(!i.test(c))return;if("CLICK:SETUP"===c){o=!0;const n=u.reduce((n,o)=>{const r=o({dependencies:e.extra,defaults:structuredClone(t.defaultOptions),options:s});return Object.assign(n,r)},r);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,r)),n}function p(e,t){const{ev:n}=e;let o=null;function r(e,t,n,o){const{extra:r}=e,{left:i,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:r,options:t.listenOptions,viewport:{X:l,Y:a,width:window.innerWidth,height:window.innerHeight},sizes:{width:c,height:u},position:{x:i,y:s},pagePosition:{x:i+l,y:s+a},type:o}}function i(o){const{callbacks:i,typeFn:s}=t;o.target;const c=r(e,t,o,"form"),u=`${s(c)}/in`;null!=i[u]&&n.emit(u,c,i[u])}function s(o){const{callbacks:i,typeFn:s}=t,c=r(e,t,o,"form"),u=`${s(c)}/out`;null!=i[u]&&n.emit(u,c,i[u])}function c(i){const{callbacks:s,typeFn:c}=t,u=r(e,t,i,"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",i),document.addEventListener("focusout",s),document.addEventListener("input",c),t.active=!0)},stop:function(){t.active&&(document.removeEventListener("focusin",i),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:r}=e,{currentContext:{name:i,note:s},shortcuts:c,callbacks:u,ERROR_EVENT_NAME:l,defaultOptions:a}=t;let p=[],d=[],f=[],h=0;if(null==i)return!1;if(Object.entries(c[i]).forEach(([o,r])=>{if(n.test(o)){if(o.includes("SETUP")){const n=r.reduce((n,o)=>{const r=o({dependencies:e.extra,defaults:structuredClone(t.defaultOptions),options:t.listenOptions});return Object.assign(n,r)},a);return void Object.assign(t.listenOptions,n)}"FORM:WATCH"===o&&(p=r),"FORM:DEFINE"===o&&(d=r),"FORM:ACTION"===o&&(f=r)}}),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:i,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:r,width:c,height:u}=n.getBoundingClientRect(),l=window.scrollX,a=window.scrollY;return m.add(d[0]({target:n,context:i,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:r},pagePosition:{x:o+l,y:r+a}}))}),t.typeFn=d[0]?d[0]:o.define,f.forEach(n=>{if(!(n instanceof Function))return r.emit(l,"The 'form:action' should be a function."),!1;const o=n({dependencies:e.extra,options:t.listenOptions});if(!(o instanceof Array))return r.emit(l,"Warning: The 'form:action' function should RETURN an array."),!1;o.forEach(({fn:e,type:n,timing:o,wait:i=0})=>{if(m.has(n)&&e instanceof Function){const t=`${n}/${o}`,i=u.hasOwnProperty(t);i?u[t].push(e):u[t]=[e],i||r.on(t,(e,t)=>{t.forEach(t=>{t instanceof Function&&t(e)})})}"instant"===o&&(t.wait[`${n}`]=i)})}),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,r=n;return r!==document.body&&(r!==document&&(o.some(e=>r.hasAttribute(e))?r:m(e,t,r.parentNode)))}function g(e,t){const{ev:n,_findTarget:o,resetState:r,extra:i}=e;function s(r){const s=r.clientX,c=r.clientY,{hovered:u,hoverRectangle:l,listenOptions:a,hoverTimer:p,leaveTimer:d,lastEvent:f,lastHoverTarget:h}=t,m=o(e,t,r.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:r,dependencies:i,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),r())}}}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 r=t.defaultOptions,{regex:i,_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(i.test(s)){if("HOVER:SETUP"===s){o=!0;const n=c.reduce((n,o)=>{const r=o({dependencies:e.extra,defaults:structuredClone(t.defaultOptions),options:t.listenOptions});return Object.assign(n,r)},r);return void Object.assign(t.listenOptions,n)}n++}}),o||Object.assign(t.listenOptions,r)),n}function w(e,t){const{ev:n,resetState:o,extra:r}=e;let i=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:r,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(i),clearTimeout(s);const x=y[y.length-1]||null;i=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 r=t.defaultOptions,{regex:i}=e,{currentContext:{name:s},shortcuts:c}=t;return null==s||(Object.entries(c[s]).forEach(([s,c])=>{if(i.test(s)){if("SCROLL:SETUP"===s){o=!0;const n=c.reduce((n,o)=>{const r=o({dependencies:e.extra,defaults:structuredClone(t.defaultOptions),options:t.listenOptions});return Object.assign(n,r)},r);return void Object.assign(t.listenOptions,n)}n++}}),o||Object.assign(t.listenOptions,r)),n}function E(t={}){const n={},o={},r=function(){let e=Object.assign(Object.create(null),{"*":[]}),t=Object.create(null),n=new Set,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)),"*"!==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[i,...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(i,...s))))}if(o&&(console.log(`${r} Event "${String(i)}" was triggered.`),s.length>0&&(console.log("Arguments:"),console.log(...s),console.log("^----"))),"*"!==i){if(t[i]){if(n.has(i))return;const o=t[i];delete t[i],o.forEach(e=>e(...s)),e[i]||e["*"].forEach(e=>e(i,...s))}e[i]&&c(i)}else Reflect.ownKeys(e).forEach(e=>c(e))},stop:function(o){if("*"===o){const o=Reflect.ownKeys(e),r=Reflect.ownKeys(t);return void(n=new Set([...r,...o]))}n.add(o)},start:function(e){"*"!==e?n.delete(e):n.clear()},debug:function(e,t){o=!!e,t&&"string"==typeof t&&(r=t)}}}(),i={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:r,inAPI:n,API:o,extra:{emit:r.emit}};return o.enablePlugin=(e,t={})=>{if("function"!=typeof e)return;const o=e(n._setupPlugin,t),r=o.getPrefix(),s=n._systemAction(r,"none");-1===s?(i.plugins.push(o),o.unmute()):(o.destroy(),i.plugins[s].unmute())},o.disablePlugin=e=>{const t=n._systemAction(e,"destroy");-1!==t&&i.plugins.splice(t,1)},o.mutePlugin=e=>n._systemAction(e,"mute"),o.unmutePlugin=e=>n._systemAction(e,"unmute"),o.listPlugins=()=>i.plugins.map(e=>e.getPrefix()),o.getContext=()=>i.currentContext.name,o.getNote=()=>i.currentContext.note,o.setNote=(e=null)=>{"string"!=typeof e&&null!=e||(i.currentContext.note=e)},o.pause=(e="*")=>{const t=n._readShortcutWithPlugins(e);r.stop(t)},o.resume=(e="*")=>{const t=n._readShortcutWithPlugins(e);r.start(t)},o.emit=(e,...t)=>r.emit(n._readShortcutWithPlugins(e),{dependencies:s.extra,type:"custom"},...t),o.listContexts=()=>Object.keys(i.shortcuts),o.setDependencies=e=>Object.assign(s.extra,e),o.getDependencies=()=>s.extra,o.reset=function(){r.reset(),o.changeContext(),i.plugins.forEach(e=>e.destroy()),o.listContexts().map(e=>o.unload(e)),s.extra={emit:r.emit},i.exposeShortcut=null},Object.entries(e).forEach(([e,t])=>{e.startsWith("_")?n[e]=t(s,i):o[e]=t(s,i)}),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:i,_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:r,_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 r(e){let t="pending";return e.then(()=>t="fulfilled").catch(()=>t="rejected"),t}function i(n,...o){t.forEach((t,i)=>n({value:e[i],done:t.done,cancel:t.cancel,timeout:t.timeout,state:r(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:i,onComplete:o,timeout:()=>{}};return s.timeout=P(!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=P(!1,o),o.each=(n,...r)=>{n({value:null,done:e,cancel:t,timeout:o.timeout},...r)},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 P(e,t){let n;return n=e?Promise.all(t.promises.map(e=>e.promise)):t.promise,function(e,o){let r,i=new Promise((t,i)=>{r=setTimeout(()=>{t(o),Promise.resolve(n)},e)});return n.then(()=>clearTimeout(r)),t.onComplete=k(Promise.race([n,i])),t}}function b({message:e,level:t,type:n,logLevel:o}){if(0===o)return null;if(o<t)return null;const r=`[Debug]: ${e}`;switch(n){case"warn":console.warn(r);break;case"error":console.error(r);break;default:console.log(r)}return r}function R(e={},t=b){return function({message:n,type:o,level:r,...i}){const{level:s,type:c,defaultMessageLevel:u}=Object.assign({},{level:1e3,type:"log",defaultMessageLevel:1},e);return o||(o=c),r||(r=u),t({message:n,type:o,level:r,logLevel:s,...i})}}function*L(e,t,n,o){let r=null,i=!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]&&(r=n,!0)),null==r)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>r+1;e--)yield[t[e-1],"hide"];for(let e=r+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"]),i=!1}else{let e=[...t];e.reverse(),yield*e.map(e=>[e,"hide"])}i&&(yield[n,"show"])}}function _(e){return function(t,...n){const{askForPromise:o,deps:r}=e;return function(){const e=o();return t({task:e,dependencies:r()},...n),e.promise}}}return T.sequence=function(e,...t){const n=T(),o=[];const r=function*(e){for(const t of e)yield t}(e);return function e(t,...i){t.done?n.done(o):t.value(...i).then(t=>{o.push(t),e(r.next(),...i,t)})}(r.next(),...t),n},T.all=function(e,...t){const n=T(),o=[],r=e.map((e,n)=>"function"==typeof e?e(...t).then(e=>o[n]=e):e.then(e=>o[n]=e));return Promise.all(r).then(()=>n.done(o)),n},function(e={}){const t=E({errorEventName:"@app-error"}),n=R({level:e.logLevel??1},e=>{const{type:n,logLevel:o}=e;0!==o&&"error"===n&&t.getDependencies().emit("@app-error",e)}),o={currentScene:null,currentParents:null,sceneNames:new Set,scenes:{},opened:!1,jumpStack:[]},r={},i={shortcutMngr:t,findInstructions:L,askForPromise:T,setInstruction:_({askForPromise:T,deps:t.getDependencies}),log:n};return r.hide=function(e,t){return function(n=1){const{askForPromise:o,shortcutMngr:r,setInstruction:i}=e,{currentScene:s,currentParents:c,scenes:u}=t,l=o(),a=[],p=c.length>0;r.pause(),a.push(i(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()),p&&0===d.length&&"*"===u[s].parents[0]&&(t.currentScene=t.currentParents.pop(),t.currentParents=t.currentScene?[...u[t.currentScene].parents]:[]),d.forEach(e=>{a.push(i(u[e].hide)),t.currentScene="*"===u[e].parents[0]?null:u[e].parents.at(-1)??null,t.currentParents=t.currentScene?u[t.currentScene].parents:[]}),o.sequence(a).onComplete(()=>{r.changeContext(t.currentScene),l.done()}),l.promise}}(i,o),r.listShortcuts=function(e,t){return function(e){const{scenes:n,sceneNames:o}=t;if(!o.has(e))return null;const{show:r,hide:i,parents:s,beforeHide:c,afterShow:u,...l}=n[e];return Object.keys(l)}}(0,o),r.setScenes=function(e,t){return function(n){const{shortcutMngr:o,log:r}=e;n.forEach(e=>{if(null==e)return;const{name:n,scene:i}=e;if(!n)return void r({message:"Scene name is not defined",level:1,type:"error"});if(null==i)return void r({message:`Scene ${n} is not defined`,level:1,type:"error"});i.parents||(i.parents=[]),t.scenes[n]=i,t.sceneNames.add(n);const{show:s,hide:c,parents:u,...l}=i,a={};a[n]=l,o.load(a)})}}(i,o),r.show=function(e,t){return function({scene:n,options:o={ssr:!1}},...r){const{shortcutMngr:i,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:i.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,i.changeContext(n),a.done(),a.promise;const{show:p,parents:m=[]}=f[n];if(t.currentParents||(t.currentParents=[]),"*"===m[0])return l(p,...r)().then(()=>a.done()),t.currentParents.push(t.currentScene),t.currentScene=n,i.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,...r))}s.sequence(y).onComplete(()=>{t.opened=!0,t.currentScene=n,t.currentParents=f[n].parents?[...f[n].parents]:null,i.changeContext(n),"function"==typeof f[n].afterShow&&f[n].afterShow({dependencies:i.getDependencies(),done:()=>{}}),a.done()})}),a.promise}}(i,o),r.jump=function(e,t){return function({scene:n},...o){return e.jumpStack.push(e.currentScene),t({scene:n},...o)}}(o,r.show),r.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 r=e.jumpStack.pop();return t({scene:r},...o)}}(o,r.show),r.jumpsReset=function(e){return function(){e.jumpStack=[]}}(o),r.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])},r.setDependencies=e=>t.setDependencies(e),r.getDependencies=()=>t.getDependencies(),r.setNote=e=>t.setNote(e),r.listScenes=()=>[...o.sceneNames],r.enablePlugin=(e,n)=>t.enablePlugin(e,n),r.disablePlugin=e=>t.disablePlugin(e),r.getState=()=>({scene:o.currentScene,parents:o.currentParents?[...o.currentParents]:o.currentParents,opened:o.opened}),r.emit=(e,...n)=>t.getDependencies().emit(e,...n),r}});
|
package/package.json
CHANGED
package/src/main.js
CHANGED
|
@@ -36,12 +36,13 @@ import jumpBack from './methods/jumpBack.js'
|
|
|
36
36
|
import jumpsReset from './methods/jumpsReset.js'
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
function main ( cfg= {
|
|
39
|
+
function main ( cfg= {} ) {
|
|
40
40
|
const
|
|
41
41
|
shortcutMngr = shortcuts ({ errorEventName: '@app-error' })
|
|
42
|
-
, logLevel = cfg.logLevel
|
|
42
|
+
, logLevel = ( cfg.logLevel ?? 1 )
|
|
43
43
|
, log = createLog ({ level:logLevel }, (arg) => {
|
|
44
|
-
const { type } = arg;
|
|
44
|
+
const { type, logLevel:configuredLevel } = arg;
|
|
45
|
+
if ( configuredLevel === 0 ) return // Silent mode: no @app-error events
|
|
45
46
|
if ( type === 'error' ) {
|
|
46
47
|
// Use the raw emitter (not shortcutMngr.emit) so '@app-error'
|
|
47
48
|
// handlers keep receiving the log entry as their sole argument -
|
|
@@ -155,7 +156,8 @@ function main ( cfg= {logLevel:0} ) {
|
|
|
155
156
|
*/
|
|
156
157
|
API.getState = () => ({
|
|
157
158
|
scene : state.currentScene
|
|
158
|
-
|
|
159
|
+
// Copy - never leak the live array, or callers mutating it corrupt internal state.
|
|
160
|
+
, parents : state.currentParents ? [ ...state.currentParents ] : state.currentParents
|
|
159
161
|
, opened : state.opened
|
|
160
162
|
})
|
|
161
163
|
|
package/src/methods/hide.js
CHANGED
|
@@ -31,10 +31,23 @@ return function hide ( endSteps=1 ) {
|
|
|
31
31
|
namesToHide = currentParents.slice ( `-${endSteps-1}` ).reverse ()
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
if ( hasParents && namesToHide.length === 0 && scenes[currentScene].parents[0] === '*' ) {
|
|
35
|
+
// A wildcard overlay has no fixed scene to 'stay pointed at' once hidden - unlike a
|
|
36
|
+
// regular single-step hide(), always climb back to whatever scene it was shown on top
|
|
37
|
+
// of, so the shortcuts context returns to the (still visible) underlying scene.
|
|
38
|
+
state.currentScene = state.currentParents.pop ()
|
|
39
|
+
state.currentParents = state.currentScene ? [ ...scenes[state.currentScene].parents ] : []
|
|
40
|
+
}
|
|
41
|
+
|
|
34
42
|
namesToHide.forEach ( name => {
|
|
35
43
|
instructions.push ( setInstruction ( scenes[name].hide))
|
|
36
44
|
// Climb to the parent of the scene just hidden - same technique 'show' uses for its 'hide' steps.
|
|
37
|
-
|
|
45
|
+
// A wildcard overlay isn't climbing its own declared parent ('*' isn't a real scene) - and
|
|
46
|
+
// there's no reliable way to recover what it originally covered once it's this deep in the
|
|
47
|
+
// chain, so fall back to treating it as the end of the chain rather than crashing.
|
|
48
|
+
state.currentScene = ( scenes[name].parents[0] === '*' )
|
|
49
|
+
? null
|
|
50
|
+
: ( scenes[name].parents.at ( -1 ) ?? null )
|
|
38
51
|
state.currentParents = state.currentScene ? scenes[state.currentScene].parents : []
|
|
39
52
|
})
|
|
40
53
|
|
package/test/02-cuts.test.js
CHANGED
|
@@ -578,4 +578,84 @@ describe ( 'Cuts integration', () => {
|
|
|
578
578
|
|
|
579
579
|
|
|
580
580
|
|
|
581
|
+
it ( 'getState() does not leak a mutable reference to internal state', async () => {
|
|
582
|
+
// Regression test: getState() used to return state.currentParents by
|
|
583
|
+
// reference, so a caller mutating the returned array corrupted cuts' own state.
|
|
584
|
+
const script = cuts();
|
|
585
|
+
script.setScenes ([
|
|
586
|
+
{ name: 'home', scene: { show: ({task}) => task.done(), hide: ({task}) => task.done() } }
|
|
587
|
+
]);
|
|
588
|
+
|
|
589
|
+
await script.show ({ scene: 'home' });
|
|
590
|
+
const firstRead = script.getState ();
|
|
591
|
+
firstRead.parents.push ( 'INJECTED' );
|
|
592
|
+
|
|
593
|
+
expect ( script.getState().parents ).toEqual ([]);
|
|
594
|
+
}) // it getState() does not leak a mutable reference to internal state
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
|
|
598
|
+
it ( 'hide() restores state and shortcuts context after dismissing a wildcard overlay', async () => {
|
|
599
|
+
// Regression test: hide() on a wildcard-overlay scene left currentScene/currentParents
|
|
600
|
+
// stale (still pointing at the now-hidden overlay), so the underlying scene's
|
|
601
|
+
// shortcuts context was never reactivated even though it was still visible.
|
|
602
|
+
const seen = [];
|
|
603
|
+
const script = cuts();
|
|
604
|
+
const scenes = [
|
|
605
|
+
{
|
|
606
|
+
name: 'base'
|
|
607
|
+
, scene: {
|
|
608
|
+
show : ({task}) => task.done(),
|
|
609
|
+
hide : ({task}) => task.done(),
|
|
610
|
+
'@ping' : () => seen.push ( 'base' )
|
|
611
|
+
}
|
|
612
|
+
},
|
|
613
|
+
{
|
|
614
|
+
name: 'overlay'
|
|
615
|
+
, scene: {
|
|
616
|
+
show : ({task}) => task.done(),
|
|
617
|
+
hide : ({task}) => task.done(),
|
|
618
|
+
parents: ['*'],
|
|
619
|
+
'@ping' : () => seen.push ( 'overlay' )
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
];
|
|
623
|
+
|
|
624
|
+
script.setScenes ( scenes );
|
|
625
|
+
await script.show ({ scene: 'base' });
|
|
626
|
+
await script.show ({ scene: 'overlay' });
|
|
627
|
+
|
|
628
|
+
await script.hide (); // Dismiss the overlay
|
|
629
|
+
expect ( script.getState() ).toEqual ({ scene: 'base', parents: [], opened: true });
|
|
630
|
+
|
|
631
|
+
script.emit ( '@ping' );
|
|
632
|
+
expect ( seen ).toEqual ([ 'base' ]);
|
|
633
|
+
}) // it hide() restores state and shortcuts context after dismissing a wildcard overlay
|
|
634
|
+
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
it ( 'logLevel: 0 is honored as explicitly silent, and the no-args default stays 1', async () => {
|
|
638
|
+
// Regression test: 'cfg.logLevel || 1' treated an explicit 0 as falsy and
|
|
639
|
+
// silently forced logLevel back to 1, so 'silent mode' never actually worked.
|
|
640
|
+
const silentSeen = [];
|
|
641
|
+
const silentScript = cuts ({ logLevel: 0 });
|
|
642
|
+
silentScript.setScenes ([
|
|
643
|
+
{ name: 'top', scene: { show: ({task}) => task.done(), hide: ({task}) => task.done(), '@app-error': (e) => silentSeen.push(e) } }
|
|
644
|
+
]);
|
|
645
|
+
await silentScript.show ({ scene: 'top' });
|
|
646
|
+
await silentScript.show ({ scene: 'nope' });
|
|
647
|
+
expect ( silentSeen ).toEqual ([]);
|
|
648
|
+
|
|
649
|
+
const defaultSeen = [];
|
|
650
|
+
const defaultScript = cuts (); // No config at all - README default is logLevel 1
|
|
651
|
+
defaultScript.setScenes ([
|
|
652
|
+
{ name: 'top', scene: { show: ({task}) => task.done(), hide: ({task}) => task.done(), '@app-error': (e) => defaultSeen.push(e) } }
|
|
653
|
+
]);
|
|
654
|
+
await defaultScript.show ({ scene: 'top' });
|
|
655
|
+
await defaultScript.show ({ scene: 'nope' });
|
|
656
|
+
expect ( defaultSeen ).toHaveLength ( 1 );
|
|
657
|
+
}) // it logLevel: 0 is honored as explicitly silent, and the no-args default stays 1
|
|
658
|
+
|
|
659
|
+
|
|
660
|
+
|
|
581
661
|
}) // describe
|
package/types/main.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
declare function main(cfg?: {
|
|
2
|
-
logLevel: number;
|
|
3
|
-
}): {
|
|
1
|
+
declare function main(cfg?: {}): {
|
|
4
2
|
hide: (endSteps?: number | string) => Promise<any>;
|
|
5
3
|
listShortcuts: (sceneName: string) => (Array<string> | null);
|
|
6
4
|
setScenes: (list: import("./methods/setScenes.js").sceneDescription[]) => void;
|
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
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.js"],"names":[],"mappings":"AAsCA,iBAAS,IAAI,CAAG,GAAG,KAAI;;;;;;;;;;;;;;;;;IA2Cf;;;;;;;;;;;;;;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;IAalB;;;;;;OAMG;kBAHQ,MAAM,WACH,GAAC,EAAA;EAOvB;eAIc,IAAI"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hide.d.ts","sourceRoot":"","sources":["../../src/methods/hide.js"],"names":[],"mappings":"AAIA,iBAAS,IAAI,CAAG,YAAY,KAAA,EAAE,KAAK,KAAA,eAIxB,MAAM,GAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"hide.d.ts","sourceRoot":"","sources":["../../src/methods/hide.js"],"names":[],"mappings":"AAIA,iBAAS,IAAI,CAAG,YAAY,KAAA,EAAE,KAAK,KAAA,eAIxB,MAAM,GAAC,MAAM,kBAmDtB;eAIa,IAAI"}
|