@peter.naydenov/cuts 2.1.2 → 2.1.4

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/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.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};
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={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};
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@peter.naydenov/cuts",
3
3
  "description": "SPA scene manager",
4
- "version": "2.1.2",
4
+ "version": "2.1.4",
5
5
  "license": "MIT",
6
6
  "author": "Peter Naydenov",
7
7
  "main": "./src/main.js",
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= {logLevel:0} ) {
39
+ function main ( cfg= {} ) {
40
40
  const
41
41
  shortcutMngr = shortcuts ({ errorEventName: '@app-error' })
42
- , logLevel = cfg.logLevel || 1
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
- , parents : state.currentParents
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
 
@@ -12,37 +12,51 @@ function hide ( dependencies, state ) {
12
12
  return function hide ( endSteps=1 ) {
13
13
  const
14
14
  { askForPromise, shortcutMngr, setInstruction } = dependencies
15
- , { currentScene, currentParents, scenes } = state
15
+ , { currentScene, scenes } = state
16
16
  , hideTask = askForPromise ()
17
- , instructions = []
18
- , hasParents = currentParents.length > 0
17
+ , unloadTask = askForPromise ()
18
+ , hasBeforeHide = typeof scenes[currentScene].beforeHide === 'function'
19
19
  ;
20
20
 
21
- shortcutMngr.pause () // Stop all shortcuts
22
- instructions.push ( setInstruction ( scenes[currentScene].hide )) // Set instruction to hide current scene
21
+ if ( hasBeforeHide ) { // Execute 'beforeHide' function if exists - same guard 'show' honors when navigating away
22
+ const closingFn = scenes[currentScene].beforeHide;
23
+ closingFn ({ done:unloadTask.done, dependencies: shortcutMngr.getDependencies() })
24
+ }
25
+ else unloadTask.done ( true )
23
26
 
24
- if ( !hasParents ) state.currentScene = null
27
+ unloadTask.onComplete ( continueHiding => {
28
+ if ( !continueHiding ) {
29
+ // 'beforeHide' returned false - cancel, nothing was torn down or changed
30
+ hideTask.done ()
31
+ return hideTask.promise
32
+ }
25
33
 
26
- let namesToHide = []
27
- if ( hasParents && endSteps === '*' ) {
28
- namesToHide = [...currentParents].reverse ()
29
- }
30
- if ( hasParents && ![ '*', 1].includes(endSteps) ) {
31
- namesToHide = currentParents.slice ( `-${endSteps-1}` ).reverse ()
32
- }
34
+ const
35
+ instructions = []
36
+ // Work on a copy of the recorded ancestor chain - it's the source of truth for what to
37
+ // climb back to, including for wildcard-overlay scenes ('*' itself is never stored here,
38
+ // only the real scene name that was current when the overlay was shown).
39
+ , remaining = [ ...state.currentParents ]
40
+ ;
41
+
42
+ shortcutMngr.pause () // Stop all shortcuts
43
+ instructions.push ( setInstruction ( scenes[currentScene].hide )) // Hiding the current scene is always at least 1 step
33
44
 
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
- shortcutMngr.changeContext ( state.currentScene ) // If state.currentScene is null, then all shortcuts are switched off and currentContext is null
44
- hideTask.done ()
45
- })
45
+ const ancestorsToHide = ( endSteps === '*' ) ? remaining.length : Math.min ( endSteps - 1, remaining.length )
46
+ for ( let i = 0; i < ancestorsToHide; i++ ) {
47
+ const name = remaining.pop ()
48
+ instructions.push ( setInstruction ( scenes[name].hide ))
49
+ }
50
+
51
+ state.currentScene = remaining.length > 0 ? remaining.pop () : null
52
+ state.currentParents = remaining
53
+
54
+ const goingTask = askForPromise.sequence ( instructions );
55
+ goingTask.onComplete ( () => {
56
+ shortcutMngr.changeContext ( state.currentScene ) // If state.currentScene is null, then all shortcuts are switched off and currentContext is null
57
+ hideTask.done ()
58
+ })
59
+ }) // unloadTask onComplete
46
60
  return hideTask.promise
47
61
  }} // hide func.
48
62
 
@@ -50,4 +64,3 @@ return function hide ( endSteps=1 ) {
50
64
 
51
65
  export default hide
52
66
 
53
-
@@ -8,8 +8,13 @@ function jump ( state, show ) {
8
8
  * @returns {Promise} - promise that resolves when the jump is completed
9
9
  */
10
10
  function jump ( { scene }, ...args ) {
11
- state.jumpStack.push ( state.currentScene )
12
- return show ( { scene }, ...args )
11
+ const previousScene = state.currentScene
12
+ return show ( { scene }, ...args ).then ( () => {
13
+ // Only record the jump if it actually landed - 'show' silently no-ops on a
14
+ // blocked (beforeHide) or invalid navigation, and pushing anyway would leave
15
+ // a phantom entry that desyncs jumpBack() from what actually happened.
16
+ if ( state.currentScene === scene ) state.jumpStack.push ( previousScene )
17
+ })
13
18
  }
14
19
  return jump
15
20
  } // jump func.
@@ -8,7 +8,7 @@
8
8
  /**
9
9
  * @typedef {Object} SceneObject
10
10
  * @property {function({task: AskObject, dependencies: *}): void} show - load interface and prerequisites for the scene;
11
- * @property {function():boolean} [afterShow] - run after scene is loaded. Optional. Returns true to continue loading, false to cancel;
11
+ * @property {function({dependencies: *, done: function}):void} [afterShow] - run after the scene is shown. Optional. Fire-and-forget - its return value is not used, and it cannot cancel or affect the already-completed 'show';
12
12
  * @property {function({task: AskObject, dependencies: *}): void} hide - Reverse the settings from 'show';
13
13
  * @property {function():void} [beforeHide] - Run before scene is hidden. Optional;
14
14
  * @property {Array.<string>} [parents] - list of parent scene names.
@@ -53,6 +53,9 @@ function show ( dependencies, state ) {
53
53
  // Executes only once when the scene manager is started
54
54
  state.opened = true
55
55
  state.currentScene = requestedScene
56
+ // The server-rendered scene's ancestors are assumed already rendered too -
57
+ // record them, or navigating away later won't know to hide them.
58
+ state.currentParents = scenes[requestedScene].parents ? [ ...scenes[requestedScene].parents ] : []
56
59
  shortcutMngr.changeContext ( requestedScene )
57
60
  showTask.done ()
58
61
  return showTask.promise
@@ -65,7 +68,11 @@ function show ( dependencies, state ) {
65
68
  if ( parents[0] === '*' ) {
66
69
  const overlayTask = setInstruction(show, ...args)()
67
70
  overlayTask.then ( () => showTask.done () )
68
- state.currentParents.push ( state.currentScene )
71
+ // Only remember a real underlying scene - pushing 'null' as a placeholder
72
+ // makes later navigation treat it as a scene name to hide, and crash.
73
+ // Re-showing the SAME overlay that's already current must not push it onto
74
+ // its own ancestor chain either, or hide() later climbs back onto itself.
75
+ if ( state.currentScene && state.currentScene !== requestedScene ) state.currentParents.push ( state.currentScene )
69
76
  state.currentScene = requestedScene
70
77
  shortcutMngr.changeContext ( requestedScene ) // Activate the overlay scene's own shortcuts
71
78
  return showTask.promise
@@ -101,7 +108,10 @@ function show ( dependencies, state ) {
101
108
  } // getStep func.
102
109
 
103
110
  const
104
- g = findInstructions ( state.currentScene, state.currentParents, requestedScene, parents )
111
+ // Snapshot - findInstructions is a lazy generator, and getStep (in the loop below)
112
+ // mutates state.currentParents in place; without a copy, that mutation corrupts
113
+ // the generator's still-pending reads of the very array it was given.
114
+ g = findInstructions ( state.currentScene, [ ...state.currentParents ], requestedScene, parents )
105
115
  , instructions = []
106
116
  ;
107
117