@peter.naydenov/cuts 1.4.4 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Changelog.md +9 -0
- package/README.md +1 -0
- package/dist/cuts.cjs +1 -1
- package/dist/cuts.esm.mjs +1 -1
- package/dist/cuts.umd.js +1 -1
- package/package.json +12 -26
- package/src/findInstructions.js +27 -7
- package/src/main.js +22 -9
- package/src/methods/hide.js +2 -2
- package/src/methods/jump.js +8 -0
- package/src/methods/jumpBack.js +8 -0
- package/src/methods/jumpsReset.js +5 -0
- package/src/methods/setScenes.js +15 -15
- package/src/methods/show.js +20 -21
- package/src/setInstruction.js +7 -0
- package/test-vitest/01-findPosition.test.js +119 -0
- package/test-vitest/02-cuts.test.js +56 -0
- package/tsconfig.json +4 -1
- package/types/findInstructions.d.ts +10 -1
- package/types/findInstructions.d.ts.map +1 -1
- package/types/main.d.ts +10 -9
- package/types/main.d.ts.map +1 -1
- package/types/methods/jump.d.ts +2 -2
- package/types/methods/jump.d.ts.map +1 -1
- package/types/methods/jumpBack.d.ts +2 -2
- package/types/methods/jumpBack.d.ts.map +1 -1
- package/types/methods/jumpsReset.d.ts.map +1 -1
- package/types/methods/setScenes.d.ts +45 -11
- package/types/methods/setScenes.d.ts.map +1 -1
- package/types/methods/show.d.ts.map +1 -1
- package/types/setInstruction.d.ts +1 -1
- package/types/setInstruction.d.ts.map +1 -1
- package/vitest.config.js +12 -0
package/Changelog.md
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## 1.5.0 ( 2025-10-?? )
|
|
5
|
+
- [x] Dependency update. @peter.naydenov/shortcuts - v.3.5.1
|
|
6
|
+
- [x] Dev dependency update. Vitest - v.4.0.1
|
|
7
|
+
- [x] Cuts has event '@app-error'. Shortcut errors will trigger this event;
|
|
8
|
+
- [x] Type improvements;
|
|
9
|
+
- [x] New method `getState` returns an object with the current state;
|
|
10
|
+
- [x] Fix: Closing a long list of scenes breaks the state;
|
|
11
|
+
|
|
12
|
+
|
|
4
13
|
|
|
5
14
|
|
|
6
15
|
## 1.4.4 ( 2025-10-10)
|
package/README.md
CHANGED
|
@@ -55,6 +55,7 @@ script.show ({ scene : 'sceneName'}) // change the current Scene
|
|
|
55
55
|
, getDependencies : 'Returns the "dependencies" object'
|
|
56
56
|
, enablePlugin : 'Enable a shortcut plugin. Available after version 1.1.0'
|
|
57
57
|
, disablePlugin : 'Disable a shortcut plugin. Available after version 1.1.0'
|
|
58
|
+
, getState : 'Get the current state of the application'
|
|
58
59
|
, emit : 'Emit an event'
|
|
59
60
|
```
|
|
60
61
|
|
package/dist/cuts.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("@peter.naydenov/shortcuts"),n=require("ask-for-promise"),
|
|
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(!n)return yield[e,"hide"],void(yield[r,"show"]);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||0,u=r({level:i}),l={currentScene:null,currentParents:null,sceneNames:new Set,scenes:{},opened:!1,jumpStack:[]},d={},a={shortcutMngr:c,findInstructions:t,askForPromise:n,setInstruction:s({askForPromise:n,deps:c.getDependencies}),log:u};return d.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(),d=[],a=i.length>0;let p;return s.pause(),d.push(o(u[c].hide)),a||(n.currentScene=null),a&&"*"===r&&[...i].reverse().forEach(e=>{p=n.currentParents.at(-1),n.currentScene=p,d.push(o(u[e].hide))}),a&&!["*",1].includes(r)&&i.slice("-"+(r-1)).reverse().map(e=>{p=n.currentParents.at(-1),n.currentScene=p,d.push(o(u[e].hide))}),(r=t.sequence(d)).onComplete(()=>{s.changeContext(n.currentScene),l.done()}),l.promise}}(a,l),d.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,beforeUnload:i,afterLoad:u,...l}=r[e];return Object.keys(l)}}(0,l),d.setScenes=function(e,n){return function(r){const{shortcutMngr:t}=e;r.forEach(e=>{if(null==e)return;const{name:r,scene:s}=e;if(null==s)return void console.warn(`Scene ${r} is not defined`);s.parents||(s.parents=[]),n.scenes[r]=s,n.sceneNames.add(r);const{show:o,hide:c,parents:i,...u}=s,l={};l[r]=u,t.load(l)})}}(a,l),d.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,d=c(),a=c(),{opened:p,scenes:h,sceneNames:f,currentScene:m}=n;return m&&"function"==typeof h[m].beforeHide?(0,h[m].beforeHide)({done:a.done,dependencies:o.getDependencies()}):a.done(!0),a.onComplete(e=>{if(!e)return d.done(),d.promise;if(!f.has(r)&&i)return i({message:`Scene ${r} is not available.`,level:1,type:"error"}),d.done(),d.promise;if(!p&&t.ssr)return n.opened=!0,n.currentPage=r,o.changeContext(r),d.done(),d.promise;const{show:a,parents:m=[]}=h[r];if("*"===m[0])return a().then(()=>d.done()),n.currentParents.push(n.currentPage),n.currentPage=r,d.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.at(-1);n.currentScene=r}return h[e][r]}m.forEach(e=>f.has(e)),n.currentParents||(n.currentParents=[]);const y=u(n.currentScene,n.currentParents,r,m),S=[];for(let e of y){const n=g(e);S.push(l(n,...s))}c.sequence(S).onComplete(()=>{n.opened=!0,n.currentPage=r,n.currentParents=h[r].parents||null,o.changeContext(r),"function"==typeof h[r].afterShow&&h[r].afterShow({dependencies:o.getDependencies(),done:()=>{}}),d.done()})}),d.promise}}(a,l),d.jump=function(e,n){return function({scene:r},...t){return e.jumpStack.push(e.currentScene),n({scene:r},...t)}}(l,d.show),d.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,d.show),d.jumpsReset=function(e){return function(){e.jumpStack=[]}}(l),d.loadPlugins=async function(e){const n=e.map(e=>`plugin${e}`),r=await import("@peter.naydenov/shortcuts");return n.map(e=>r[e])},d.setDependencies=e=>c.setDependencies(e),d.getDependencies=()=>c.getDependencies(),d.setNote=n=>e.shortcuts.setNote(n),d.listScenes=()=>[...l.sceneNames],d.enablePlugin=(e,n)=>c.enablePlugin(e,n),d.disablePlugin=e=>c.disablePlugin(e),d.getState=()=>({scene:l.currentScene,parents:l.currentParents,opened:l.opened}),d.emit=(e,...n)=>c.emit(e,...n),d};
|
package/dist/cuts.esm.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{shortcuts as e}from"@peter.naydenov/shortcuts";import n from"ask-for-promise";import
|
|
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(!n)return yield[e,"hide"],void(yield[r,"show"]);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||0,u=r({level:i}),l={currentScene:null,currentParents:null,sceneNames:new Set,scenes:{},opened:!1,jumpStack:[]},d={},a={shortcutMngr:c,findInstructions:t,askForPromise:n,setInstruction:s({askForPromise:n,deps:c.getDependencies}),log:u};return d.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(),d=[],a=i.length>0;let p;return s.pause(),d.push(o(u[c].hide)),a||(n.currentScene=null),a&&"*"===r&&[...i].reverse().forEach(e=>{p=n.currentParents.at(-1),n.currentScene=p,d.push(o(u[e].hide))}),a&&!["*",1].includes(r)&&i.slice("-"+(r-1)).reverse().map(e=>{p=n.currentParents.at(-1),n.currentScene=p,d.push(o(u[e].hide))}),(r=t.sequence(d)).onComplete(()=>{s.changeContext(n.currentScene),l.done()}),l.promise}}(a,l),d.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,beforeUnload:i,afterLoad:u,...l}=r[e];return Object.keys(l)}}(0,l),d.setScenes=function(e,n){return function(r){const{shortcutMngr:t}=e;r.forEach(e=>{if(null==e)return;const{name:r,scene:s}=e;if(null==s)return void console.warn(`Scene ${r} is not defined`);s.parents||(s.parents=[]),n.scenes[r]=s,n.sceneNames.add(r);const{show:o,hide:c,parents:i,...u}=s,l={};l[r]=u,t.load(l)})}}(a,l),d.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,d=c(),a=c(),{opened:p,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 d.done(),d.promise;if(!h.has(r)&&i)return i({message:`Scene ${r} is not available.`,level:1,type:"error"}),d.done(),d.promise;if(!p&&t.ssr)return n.opened=!0,n.currentPage=r,o.changeContext(r),d.done(),d.promise;const{show:a,parents:m=[]}=f[r];if("*"===m[0])return a().then(()=>d.done()),n.currentParents.push(n.currentPage),n.currentPage=r,d.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.at(-1);n.currentScene=r}return f[e][r]}m.forEach(e=>h.has(e)),n.currentParents||(n.currentParents=[]);const y=u(n.currentScene,n.currentParents,r,m),S=[];for(let e of y){const n=g(e);S.push(l(n,...s))}c.sequence(S).onComplete(()=>{n.opened=!0,n.currentPage=r,n.currentParents=f[r].parents||null,o.changeContext(r),"function"==typeof f[r].afterShow&&f[r].afterShow({dependencies:o.getDependencies(),done:()=>{}}),d.done()})}),d.promise}}(a,l),d.jump=function(e,n){return function({scene:r},...t){return e.jumpStack.push(e.currentScene),n({scene:r},...t)}}(l,d.show),d.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,d.show),d.jumpsReset=function(e){return function(){e.jumpStack=[]}}(l),d.loadPlugins=async function(e){const n=e.map(e=>`plugin${e}`),r=await import("@peter.naydenov/shortcuts");return n.map(e=>r[e])},d.setDependencies=e=>c.setDependencies(e),d.getDependencies=()=>c.getDependencies(),d.setNote=n=>e.setNote(n),d.listScenes=()=>[...l.sceneNames],d.enablePlugin=(e,n)=>c.enablePlugin(e,n),d.disablePlugin=e=>c.disablePlugin(e),d.getState=()=>({scene:l.currentScene,parents:l.currentParents,opened:l.opened}),d.emit=(e,...n)=>c.emit(e,...n),d}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,r])=>{const s=e(o);s!==o&&(delete n[t][o],n[t][s]=r)})})}},_readShortcutWithPlugins:function(e,t){return function(n){const{inAPI:o}=e,r=n.split(":")[0],s=o._systemAction(r,"none");let i=n;return-1!==s&&(i=t.plugins[s].shortcutName(n)),i}},_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}=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])=>{t.forEach(t=>r.on(e,t))}),r.on("*",(...e)=>{t.exposeShortcut&&t.exposeShortcut(...e)})):r.emit("@shortcuts-error",`Context '${e}' does not exist`))}},listShortcuts:function(e,t){const n=t.shortcuts;return function(e=null){if(null!=e){let t=n[e];return null==t?null:Object.entries(t).map(([e,t])=>e)}return Object.keys(n).map(e=>{let t={};return t.context=e,t.shortcuts=Object.entries(n[e]).map(([e,t])=>e),t})}},load:function(e,t){const{shortcuts:n,plugins:o}=t,{API:{changeContext:r,getContext:s}}=e;return function(e){const t=s(),i=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 s=t,c=t.toUpperCase().trim(),u=i.map((e,t)=>c.startsWith(e)?t:null).filter(e=>null!==e);if(u.length){let e=u[0];s=o[e].shortcutName(t)}r instanceof Function&&(r=[r]),n[e][s]=r})}),c&&(r(),r(t))}},unload:function(e,t){const{currentContext:n,shortcuts:o}=t,{ev:r}=e;return function(e){n.name!==e?o[e]?delete o[e]:r.emit("shortcuts-error",`Context '${e}' does not exist`):r.emit("shortcuts-error",`Context '${e}' can't be removed during is current active context. Change the context first`)}}};function t(e){const t=e.toUpperCase(),n=/KEY\s*\:/i.test(t),o=t.indexOf(":");return n?`KEY:${t.slice(o+1).split(",").map(e=>e.trim()).map(e=>e.split("+").map(e=>e.trim()).sort().join("+")).join(",")}`:e}function n(e,t){let{shiftKey:n,altKey:o,ctrlKey:r}=e,s=t(),i=e.code.replace("Key","").replace("Digit",""),c=[];return r&&c.push("CTRL"),n&&c.push("SHIFT"),o&&c.push("ALT"),s.hasOwnProperty(i)?c.push(s[i].toUpperCase()):["ControlLeft","ControlRight","ShiftLeft","ShiftRight","AltLeft","AltRight","Meta"].includes(i)||c.push(i.toUpperCase()),c.sort()}function o(e,t){let n=0;const{regex:o}=e,{listenOptions:r,currentContext:{name:s},shortcuts:i}=t;return null==s?0:(Object.entries(i[s]).forEach(([e,t])=>{if(!o.test(e))return;n++;let s=e.slice(4).split(",").length;r.maxSequence<s&&(r.maxSequence=s)}),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;let r=n;return r===document||r===document.body?null:r.dataset[o]||"A"===r.nodeName?r:s(e,t,r.parentNode)}function i(e){const t=e.toUpperCase(),n=/CLICK\s*\:/i.test(t),o=["LEFT","MIDDLE","RIGHT"],r=["ALT","SHIFT","CTRL"];let s=null,i=[],c=0,u=t.indexOf(":");return n?(t.slice(u+1).trim().split("-").map(e=>e.trim()).forEach(e=>{o.includes(e)?s=e:r.includes(e)?i.push(e):isNaN(e)||(c=e)}),`CLICK:${s}-${c}${i.length>0?"-":""}${i.sort().join("-")}`):e}function c(e,t){let{shiftKey:n,altKey:o,ctrlKey:r,key:s,button:i}=e,c=`CLICK:${["LEFT","MIDDLE","RIGHT"][i]}-${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 u(e,t){let n=0;const{regex:o}=e,{listenOptions:r,currentContext:{name:s},shortcuts:i}=t;return null==s?0:(Object.entries(i[s]).forEach(([e,t])=>{if(!o.test(e))return;n++;let[,s]=e.slice(6).split("-");r.maxClicks<s&&(r.maxClicks=s)}),n)}function l(e){const t=e.toUpperCase(),n=/FORM\s*\:/i.test(t),o=t.indexOf(":");return n?`FORM:${t.slice(o+1).trim()}`:e}function a(e,t){const{regex:n,_defaults:o,ev:r}=e,{currentContext:{name:s},shortcuts:i,callbacks:c}=t;let u=[],l=[],a=[];if(null==s)return!1;if(Object.entries(i[s]).forEach(([e,t])=>{n.test(e)&&("FORM:WATCH"===e&&(u=t),"FORM:DEFINE"===e&&(l=t),"FORM:ACTION"===e&&(a=t))}),0===a.length)return!1;let f=new Set;0===l.length&&(l=[o.define]),0===u.length&&(u=[o.watch]);let p=u.map(e=>e()).reduce((e,t)=>(e.push(t),e),[]);return t.watchList=document.querySelectorAll(p),t.watchList.forEach(e=>f.add(l[0](e))),t.typeFn=l[0]?l[0]:o.define,a.forEach(e=>e instanceof Function?e()instanceof Array?void e().forEach(({fn:e,type:n,timing:o,wait:s=0})=>{if(f.has(n)&&e instanceof Function){let t=`${n}/${o}`;const s=c.hasOwnProperty(t);s?c[t].push(e):c[t]=[e],s||r.on(t,(e,t)=>{t.forEach(t=>{t instanceof Function&&t(e)})})}"instant"===o&&(t.wait[`${n}`]=s)}):(console.warn("Warning: The 'form:action' function should RETURN an array."),!1):(console.warn("Warning: The 'form:action' should be a function."),!1)),Object.keys(t.callbacks).length>0}const f={watch:()=>"input, select, textarea, button, a",define:e=>"checkbox"===e.type||"radio"===e.type?"checkbox":"button"==e.type||"submit"==e.type?"button":"input"};function p(t={}){const n=function(){let e={"*":[]},t={},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)),e[n]&&0===e[n].length&&delete e[n],void(t[n]&&0===t[n].length&&delete e[n]);t[n]&&delete t[n],e[n]&&delete e[n]},reset:function(){e={"*":[]},t={},n=new Set},emit:function(){const[s,...i]=arguments;function c(t){let o=!1;"*"!==t&&(n.has(t)||(e[t].every(e=>{const t=e(...i);return"string"!=typeof t||"STOP"!==t.toUpperCase()||(o=!0,!1)}),o||e["*"].forEach(e=>e(s,...i))))}if(o&&(console.log(`${r} Event "${s}" was triggered.`),i.length>0&&(console.log("Arguments:"),console.log(...i),console.log("^----"))),"*"!==s){if(t[s]){if(n.has(s))return;t[s].forEach(e=>e(...i)),delete t[s]}e[s]&&c(s)}else Object.keys(e).forEach(e=>c(e))},stop:function(o){if("*"===o){const o=Object.keys(e),r=Object.keys(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)}}}(),o={},r={},s={currentContext:{name:null,note:null},shortcuts:{},plugins:[],exposeShortcut:!(!t.onShortcut||"function"!=typeof t.onShortcut)&&t.onShortcut},i={ev:n,inAPI:o,API:r,extra:{}};return r.enablePlugin=(e,t={})=>{const n=e.name;if(-1===o._systemAction(n,"none")){let n;n=e(i,s,t),s.plugins.push(n)}},r.disablePlugin=e=>{const t=o._systemAction(e,"destroy");-1!==t&&(s.plugins=s.plugins.filter((e,n)=>n!==t))},r.mutePlugin=e=>o._systemAction(e,"mute"),r.unmutePlugin=e=>o._systemAction(e,"unmute"),r.getContext=()=>s.currentContext.name,r.getNote=()=>s.currentContext.note,r.setNote=(e=null)=>{"string"!=typeof e&&null!=e||(s.currentContext.note=e)},r.pause=(e="*")=>{let t=o._readShortcutWithPlugins(e);n.stop(t)},r.resume=(e="*")=>{const t=o._readShortcutWithPlugins(e);n.start(t)},r.emit=(e,...t)=>n.emit(o._readShortcutWithPlugins(e),...t),r.listContexts=()=>Object.keys(s.shortcuts),r.setDependencies=e=>i.extra={...i.extra,...e},r.getDependencies=()=>i.extra,Object.entries(e).forEach(([e,t])=>{e.startsWith("_")?o[e]=t(i,s):r[e]=t(i,s)}),r}var m=Object.freeze({__proto__:null,pluginClick:function(e,t,n){let{currentContext:o,shortcuts:r}=t,{inAPI:l}=e,a={ev:e.ev,_findTarget:s,_readClickEvent:c,mainDependencies:e,regex:/CLICK\s*\:/i},f={currentContext:o,shortcuts:r,listenOptions:{mouseWait:n.mouseWait?n.mouseWait:320,maxClicks:1,clickTarget:n.clickTarget?n.clickTarget:"click"}};l._normalizeWithPlugins(i);let p=function(e,t){const{ev:n,_findTarget:o,_readClickEvent:r,mainDependencies:s}=e,{listenOptions:i,currentContext:c}=t,{mouseWait:u}=i;let l=null,a=null,f=null,p=null,m=0;function d(){const e=r(a,m),t={target:l,targetProps:l?l.getBoundingClientRect():null,x:a.clientX,y:a.clientY,context:c.name,note:c.note,event:a,dependencies:s.extra,type:"click"};n.emit(e,t),f=null,p=null,l=null,a=null,m=0}function h(n){let r=i.maxClicks;return clearTimeout(f),p?(clearTimeout(p),void(p=setTimeout(()=>p=null,u))):(l=o(e,t,n.target),l&&l.dataset.hasOwnProperty("quickClick")&&(r=1),l&&"A"===l.tagName&&(r=1),a=n,m++,m>=r?(d(),void(r>1&&(p=setTimeout(()=>p=null,u)))):void(f=setTimeout(d,u)))}function g(n){let r=i.maxClicks;return clearTimeout(f),p?(clearTimeout(p),void(p=setTimeout(()=>p=null,u))):(l=o(e,t,n.target),l&&l.dataset.hasOwnProperty("quickClick")&&(r=1),l&&"A"===l.tagName&&(r=1),a=n,m++,m>=r?(d(),void(r>1&&(p=setTimeout(()=>p=null,u)))):void(f=setTimeout(d,u)))}return{start:function(){t.active||(window.addEventListener("contextmenu",g),document.addEventListener("click",h),t.active=!0)},stop:function(){t.active&&(window.removeEventListener("contextmenu",g),document.removeEventListener("click",h),t.active=!1)}}}(a,f),m=u(a,f);m>0&&p.start();let d={getPrefix:()=>"click",shortcutName:e=>i(e),contextChange:()=>{m=u(a,f),m<1&&p.stop(),m>0&&p.start()},mute:()=>p.stop(),unmute:()=>p.start(),destroy:()=>{p.stop(),f=null,d=null}};return Object.freeze(d),d},pluginForm:function(e,t,n){let{currentContext:o,shortcuts:r}=t,{inAPI:s}=e,i={ev:e.ev,mainDependencies:e,regex:/FORM\s*\:/i,_defaults:f},c={currentContext:o,shortcuts:r,callbacks:{},typeFn:"",watchList:[],wait:{}};s._normalizeWithPlugins(l);let u=function(e,t){const{ev:n}=e;let o=null;function r(e,t,n,o){return{target:n.target,context:t.currentContext.name,note:t.currentContext.note,event:n,dependencies:e.mainDependencies.extra,type:o}}function s(o){const{callbacks:s,typeFn:i}=t,c=i(o.target),u=r(e,t,o,c),l=`${c}/in`;null!=s[l]&&n.emit(l,u,s[l])}function i(o){const{callbacks:s,typeFn:i}=t,c=r(e,t,o,"form-out"),u=`${i(o.target)}/out`;null!=s[u]&&n.emit(u,c,s[u])}function c(s){const{callbacks:i,typeFn:c}=t,u=r(e,t,s,"form-instant"),l=c(s.target),a=t.wait[`${l}`],f=`${l}/instant`;null!=i[f]&&(0!==a?(clearTimeout(o),o=setTimeout(()=>n.emit(f,u,i[f]),a)):n.emit(f,u,i[f]))}return{start:function(){t.active||(document.addEventListener("focusin",s),document.addEventListener("focusout",i),document.addEventListener("input",c),t.active=!0)},stop:function(){t.active&&(document.removeEventListener("focusin",s),document.removeEventListener("focusout",i),document.removeEventListener("input",c),t.active=!1)}}}(i,c);o.name&&a(i,c)&&u.start();let p={getPrefix:()=>"form",shortcutName:e=>l(e),contextChange:()=>{c.callbacks={},c.typeFn="",c.watchList=[],c.wait={},a(i,c)?u.start():u.stop()},mute:()=>u.stop(),unmute:()=>u.start(),destroy:()=>{u.stop(),c=null,p=null}};return Object.freeze(p),p},pluginKey:function(e,s,i={}){let{currentContext:c,shortcuts:u,exposeShortcut:l}=s,{inAPI:a}=e,f={ev:e.ev,_specialChars:r,_readKeyEvent:n,mainDependencies:e,regex:/KEY\s*\:/i},p={currentContext:c,shortcuts:u,active:!1,listenOptions:{keyWait:i.keyWait?i.keyWait:480,maxSequence:1,keyIgnore:null},streamKeys:!(!i.streamKeys||"function"!=typeof i.streamKeys)&&i.streamKeys};a._normalizeWithPlugins(t);let m=function(e,t){const{ev:n,_specialChars:o,_readKeyEvent:r,mainDependencies:s}=e,{currentContext:i,streamKeys:c,listenOptions:u}=t,{keyWait:l}=u;let a=[],f=null,p=!0,m=!1;const d=()=>p=!1,h=()=>p=!0,g=()=>m=!0,y=()=>!1===p;function v(){let e=a.map(e=>[e.join("+")]);const t={wait:d,end:h,ignore:g,isWaiting:y,note:i.note,context:i.name,dependencies:s.extra,type:"key"};if(!p){let o=e.at(-1);n.emit(o,t),m&&(e=e.slice(0,-1),m=!1)}if(p){const o=`KEY:${e.join(",")}`;n.emit(o,t),a=[],f=null}}function x(t){if(clearTimeout(f),o().hasOwnProperty(t.code))return a.push(r(t,o)),c&&c({key:t.key,context:i.name,note:i.note,dependencies:e.extra}),u.keyIgnore?(clearTimeout(u.keyIgnore),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,l))):p&&a.length===u.maxSequence?(v(),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,l))):void(p?f=setTimeout(v,l):v())}function k(t){if(!o().hasOwnProperty(t.code)){if(clearTimeout(f),c&&c({key:t.key,context:i.name,note:i.note,dependencies:e.extra}),u.keyIgnore)return clearTimeout(u.keyIgnore),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,l));if(a.push(r(t,o)),p&&a.length===u.maxSequence)return v(),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,l));p?f=setTimeout(v,l):v()}}return{start:function(){t.active||(document.addEventListener("keydown",x),document.addEventListener("keypress",k),t.active=!0)},stop:function(){t.active&&(document.removeEventListener("keydown",x),document.removeEventListener("keypress",k),t.active=!1)}}}(f,p),d=o(f,p);d>0&&m.start();let h={getPrefix:()=>"key",shortcutName:e=>t(e),contextChange:e=>{d=o(f,p),d<1&&m.stop(),d>0&&m.start()},mute:()=>m.stop(),unmute:()=>m.start(),destroy:()=>{m.stop(),p=null,h=null}};return Object.freeze(h),h},shortcuts:p});function d(e){return e?function(e){let t=e.map(e=>h()),n=t.map(e=>e.promise);t.promises=t;let o=g(Promise.all(n));function r(e){let t="pending";return e.then(()=>t="fulfilled").catch(()=>t="rejected"),t}function s(n,...o){t.forEach((t,s)=>n({value:e[s],done:t.done,cancel:t.cancel,timeout:t.timeout,state:r(t.promise)},...o))}const i={promise:Promise.all(n),promises:t,done:e=>{t.forEach(t=>t.done(e))},cancel:e=>{t.forEach(t=>t.cancel(e))},each:s,onComplete:o,timeout:()=>{}};return i.timeout=y(!0,i),i}(e):h()}function h(){let e,t;const n=new Promise((n,o)=>{e=n,t=o}),o={promise:n,promises:null,done:e,cancel:t,each:()=>{},onComplete:g(n),timeout:()=>{}};return o.timeout=y(!1,o),o.each=(n,...r)=>{n({value:null,done:e,cancel:t,timeout:o.timeout},...r)},o}function g(e){return function(t,n=null){null===n?e.then(e=>t(e)):e.then(e=>t(e),e=>n(e))}}function y(e,t){let n;return n=e?Promise.all(t.promises.map(e=>e.promise)):t.promise,function(e,o){let r,s=new Promise((t,s)=>{r=setTimeout(()=>{t(o),Promise.resolve(n)},e)});return n.then(()=>clearTimeout(r)),t.onComplete=g(Promise.race([n,s])),t}}function v({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 x(e={},t=v){return function({message:n,type:o,level:r,...s}){const{level:i,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:i,...s})}}function*k(e,t,n,o){let r=null;if(null===e)return yield*o.map(e=>[e,"show"]),void(yield[n,"show"]);if(!o||0===o.length)return t?(yield[e,"hide"],t.reverse(),yield*t.map(e=>[e,"hide"]),void(yield[n,"show"])):(yield[e,"hide"],void(yield[n,"show"]));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"]}function C(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 d.sequence=function(e,...t){const n=d(),o=[];const r=function*(e){for(const t of e)yield t}(e);return function e(t,...s){t.done?n.done(o):t.value(...s).then(t=>{o.push(t),e(r.next(),...s,t)})}(r.next(),...t),n},d.all=function(e,...t){const n=d(),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={logLevel:0}){const t=p(),n=x({level:e.logLevel||0}),o={currentScene:null,currentParents:null,sceneNames:new Set,scenes:{},opened:!1,jumpStack:[]},r={},s={shortcutMngr:t,findInstructions:k,askForPromise:d,setInstruction:C({askForPromise:d,deps:t.getDependencies}),log:n};return r.hide=function(e,t){return function(n=1){const{askForPromise:o,shortcutMngr:r,setInstruction:s}=e,{currentScene:i,currentParents:c,scenes:u}=t,l=o(),a=[],f=c.length>0;let p;return r.pause(),a.push(s(u[i].hide)),f||(t.currentScene=null),f&&"*"===n&&[...c].reverse().forEach(e=>{p=t.currentParents.pop(),t.currentScene=p,a.push(s(u[e].hide))}),f&&!["*",1].includes(n)&&c.slice("-"+(n-1)).reverse().map(e=>{p=t.currentParents.pop(),t.currentScene=p,a.push(s(u[e].hide))}),(n=o.sequence(a)).onComplete(()=>{r.changeContext(t.currentScene),l.done()}),l.promise}}(s,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:s,parents:i,beforeUnload:c,afterLoad:u,...l}=n[e];return Object.keys(l)}}(0,o),r.setScenes=function(e,t){return function(n){const{shortcutMngr:o}=e;n.forEach(e=>{if(null==e)return;const{name:n,scene:r}=e;if(null==r)return void console.warn(`Scene ${n} is not defined`);r.parents||(r.parents=[]),t.scenes[n]=r,t.sceneNames.add(n);const{show:s,hide:i,parents:c,...u}=r,l={};l[n]=u,o.load(l)})}}(s,o),r.show=function(e,t){return function({scene:n,options:o={ssr:!1}},...r){const{shortcutMngr:s,askForPromise:i,log:c,findInstructions:u,setInstruction:l}=e,a=i(),f=i(),{opened:p,scenes:m,sceneNames:d,currentPage:h}=t;if(h){const e=m[h].beforeHide;"function"==typeof e&&e({done:f.done,dependencies:s.getDependencies()})}else f.done(!0);return f.onComplete(e=>{if(!e)return a.done(),a.promise;if(!d.has(n)&&c)return c({message:`Scene ${n} is not available.`,level:1,type:"error"}),a.done(),a.promise;if(!p&&o.ssr)return t.opened=!0,t.currentPage=n,s.changeContext(n),a.done(),a.promise;const{show:f,parents:h=[]}=m[n];if("*"===h[0])return f().then(()=>a.done()),t.currentParents.push(t.currentPage),t.currentPage=n,a.promise;function g([e,n]){if("show"===n)t.currentScene&&t.currentParents.push(t.currentScene),t.currentScene=e;else{let e=t.currentParents.pop();t.currentScene=e}return m[e][n]}h.forEach(e=>d.has(e)),t.currentParents||(t.currentParents=[]);const y=u(t.currentScene,t.currentParents,n,h),v=[];for(let e of y)[e].map(g).map(e=>v.push(l(e),...r));i.sequence(v).onComplete(()=>{t.opened=!0,s.changeContext(n),"function"==typeof m[n].afterShow&&m[n].afterShow({dependencies:s.getDependencies(),done:()=>{}}),a.done()})}),a.promise}}(s,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 m});return t.map(e=>n[e])},r.setDependencies=e=>t.setDependencies(e),r.getDependencies=()=>t.getDependencies(),r.setNote=e=>p.setNote(e),r.listScenes=()=>[...o.sceneNames],r.enablePlugin=(e,n)=>t.enablePlugin(e,n),r.disablePlugin=e=>t.disablePlugin(e),r.emit=(e,...n)=>t.emit(e,...n),r}});
|
|
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(([r,o])=>{const s=e(r);s!==r&&(delete n[t][r],n[t][s]=o)})})}},_readShortcutWithPlugins:function(e,t){return function(n){const{inAPI:r}=e,o=n.split(":")[0].toLowerCase().trim(),s=r._systemAction(o,"none");let i=n;return-1!==s&&(i=t.plugins[s].shortcutName(n)),i}},_systemAction:function(e,t){return function(e,n,r=null){return t.plugins.findIndex(t=>t.getPrefix()===e&&(t[n]&&t[n](r),!0))}},changeContext:function(e,t){const{shortcuts:n,currentContext:r,ERROR_EVENT_NAME:o}=t,{ev:s}=e;return function(e=!1){const i=r.name;if(!e)return s.reset(),void(r.name=null);i!==e&&(n[e]?(n[i]&&s.reset(),r.name=e,t.plugins.forEach(t=>t.contextChange(e)),Object.entries(n[e]).forEach(([e,t])=>{t.forEach(t=>s.on(e,t))}),s.on("*",(...e)=>{t.exposeShortcut&&t.exposeShortcut(...e)})):s.emit(o,`Context '${e}' does not exist`))}},listShortcuts:function(e,t){const n=t.shortcuts;return function(e=null){if(null!=e){let t=n[e];return null==t?null:Object.entries(t).map(([e,t])=>e)}return Object.keys(n).map(e=>{let t={};return t.context=e,t.shortcuts=Object.entries(n[e]).map(([e,t])=>e),t})}},load:function(e,t){const{shortcuts:n,plugins:r}=t,{API:{changeContext:o,getContext:s}}=e;return function(e){const t=s(),i=r.map(e=>e.getPrefix().toUpperCase());let c=!1;Object.entries(e).forEach(([e,o])=>{e===t&&(c=!0),n[e]={},Object.entries(o).forEach(([t,o])=>{let s=t,c=t.toUpperCase().trim(),u=i.map((e,t)=>c.startsWith(e)?t:null).filter(e=>null!==e);if(u.length){let e=u[0];s=r[e].shortcutName(t)}o instanceof Function&&(o=[o]),n[e][s]=o})}),c&&(o(),o(t))}},unload:function(e,t){const{currentContext:n,shortcuts:r,ERROR_EVENT_NAME:o}=t,{ev:s}=e;return function(e){n.name!==e?r[e]?delete r[e]:s.emit(o,`Context '${e}' does not exist`):s.emit(o,`Context '${e}' can't be removed during is current active context. Change the context first`)}}};function t(e){const t=e.toUpperCase(),n=/KEY\s*\:/i.test(t),r=t.indexOf(":");return n?`KEY:${t.slice(r+1).split(",").map(e=>e.trim()).map(e=>e.split("+").map(e=>e.trim()).sort().join("+")).join(",")}`:e}function n(e,t){let{shiftKey:n,altKey:r,ctrlKey:o}=e,s=t(),i=e.code.replace("Key","").replace("Digit",""),c=[];return o&&c.push("CTRL"),n&&c.push("SHIFT"),r&&c.push("ALT"),s.hasOwnProperty(i)?c.push(s[i].toUpperCase()):["ControlLeft","ControlRight","ShiftLeft","ShiftRight","AltLeft","AltRight","Meta"].includes(i)||c.push(i.toUpperCase()),c.sort()}function r(e,t){let n=0;const{regex:r}=e,{listenOptions:o,currentContext:{name:s},shortcuts:i}=t;return null==s?0:(Object.entries(i[s]).forEach(([e,t])=>{if(!r.test(e))return;n++;let s=e.slice(4).split(",").length;o.maxSequence<s&&(o.maxSequence=s)}),n)}function o(){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:r}}=t;let o=n;return o===document||o===document.body?null:o.dataset[r]||"A"===o.nodeName?o:s(e,t,o.parentNode)}function i(e){const t=e.toUpperCase(),n=/CLICK\s*\:/i.test(t),r=["LEFT","MIDDLE","RIGHT"],o=["ALT","SHIFT","CTRL"];let s=null,i=[],c=0,u=t.indexOf(":");return n?(t.slice(u+1).trim().split("-").map(e=>e.trim()).forEach(e=>{r.includes(e)?s=e:o.includes(e)?i.push(e):isNaN(e)||(c=e)}),`CLICK:${s}-${c}${i.length>0?"-":""}${i.sort().join("-")}`):e}function c(e,t){let{shiftKey:n,altKey:r,ctrlKey:o,key:s,button:i}=e,c=`CLICK:${["LEFT","MIDDLE","RIGHT"][i]}-${t}`,u=[];return o&&u.push("CTRL"),n&&u.push("SHIFT"),r&&u.push("ALT"),u.length>0?`${c}${u.length>0?"-":""}${u.sort().join("-")}`:`${c}`}function u(e,t){let n=0;const{regex:r}=e,{listenOptions:o,currentContext:{name:s},shortcuts:i}=t;return null==s?0:(Object.entries(i[s]).forEach(([e,t])=>{if(!r.test(e))return;n++;let[,s]=e.slice(6).split("-");o.maxClicks<s&&(o.maxClicks=s)}),n)}function l(e){const t=e.toUpperCase(),n=/FORM\s*\:/i.test(t),r=t.indexOf(":");return n?`FORM:${t.slice(r+1).trim()}`:e}function a(e,t){const{regex:n,_defaults:r,ev:o}=e,{currentContext:{name:s},shortcuts:i,callbacks:c}=t;let u=[],l=[],a=[];if(null==s)return!1;if(Object.entries(i[s]).forEach(([e,t])=>{n.test(e)&&("FORM:WATCH"===e&&(u=t),"FORM:DEFINE"===e&&(l=t),"FORM:ACTION"===e&&(a=t))}),0===a.length)return!1;let f=new Set;0===l.length&&(l=[r.define]),0===u.length&&(u=[r.watch]);let p=u.map(e=>e()).reduce((e,t)=>(e.push(t),e),[]);return t.watchList=document.querySelectorAll(p),t.watchList.forEach(e=>f.add(l[0](e))),t.typeFn=l[0]?l[0]:r.define,a.forEach(n=>{if(!(n instanceof Function))return console.warn("Warning: The 'form:action' should be a function."),!1;let r=n({dependencies:e.mainDependencies.extra});if(!(r instanceof Array))return console.warn("Warning: The 'form:action' function should RETURN an array."),!1;r.forEach(({fn:e,type:n,timing:r,wait:s=0})=>{if(f.has(n)&&e instanceof Function){let t=`${n}/${r}`;const s=c.hasOwnProperty(t);s?c[t].push(e):c[t]=[e],s||o.on(t,(e,t)=>{t.forEach(t=>{t instanceof Function&&t(e)})})}"instant"===r&&(t.wait[`${n}`]=s)})}),Object.keys(t.callbacks).length>0}const f={watch:()=>"input, select, textarea, button, a",define:e=>"checkbox"===e.type||"radio"===e.type?"checkbox":"button"==e.type||"submit"==e.type?"button":"input"};function p(t={}){let n={},r={};const o=function(){let e={"*":[]},t={},n=new Set,r=!1,o="";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,r){if(r)return e[n]&&(e[n]=e[n].filter(e=>e!==r)),t[n]&&(t[n]=t[n].filter(e=>e!==r)),e[n]&&0===e[n].length&&delete e[n],void(t[n]&&0===t[n].length&&delete e[n]);t[n]&&delete t[n],e[n]&&delete e[n]},reset:function(){e={"*":[]},t={},n=new Set},emit:function(){const[s,...i]=arguments;function c(t){let r=!1;"*"!==t&&(n.has(t)||(e[t].every(e=>{const t=e(...i);return"string"!=typeof t||"STOP"!==t.toUpperCase()||(r=!0,!1)}),r||e["*"].forEach(e=>e(s,...i))))}if(r&&(console.log(`${o} Event "${s}" was triggered.`),i.length>0&&(console.log("Arguments:"),console.log(...i),console.log("^----"))),"*"!==s){if(t[s]){if(n.has(s))return;t[s].forEach(e=>e(...i)),delete t[s]}e[s]&&c(s)}else Object.keys(e).forEach(e=>c(e))},stop:function(r){if("*"===r){const r=Object.keys(e),o=Object.keys(t);return void(n=new Set([...o,...r]))}n.add(r)},start:function(e){"*"!==e?n.delete(e):n.clear()},debug:function(e,t){r=!!e,t&&"string"==typeof t&&(o=t)}}}(),s={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"};let i={ev:o,inAPI:n,API:r,extra:{}};return r.enablePlugin=(e,t={})=>{if("function"!=typeof e)return;let r=e(i,s,t);const o=r.getPrefix();-1===n._systemAction(o,"none")?s.plugins.push(r):r.destroy()},r.disablePlugin=e=>{const t=n._systemAction(e,"destroy");-1!==t&&(s.plugins=s.plugins.filter((e,n)=>n!==t))},r.mutePlugin=e=>n._systemAction(e,"mute"),r.unmutePlugin=e=>n._systemAction(e,"unmute"),r.listPlugins=()=>s.plugins.map(e=>e.getPrefix()),r.getContext=()=>s.currentContext.name,r.getNote=()=>s.currentContext.note,r.setNote=(e=null)=>{"string"!=typeof e&&null!=e||(s.currentContext.note=e)},r.pause=(e="*")=>{let t=n._readShortcutWithPlugins(e);o.stop(t)},r.resume=(e="*")=>{const t=n._readShortcutWithPlugins(e);o.start(t)},r.emit=(e,...t)=>o.emit(n._readShortcutWithPlugins(e),...t),r.listContexts=()=>Object.keys(s.shortcuts),r.setDependencies=e=>i.extra={...i.extra,...e},r.getDependencies=()=>i.extra,r.reset=function(){o.reset(),r.changeContext(),s.plugins.forEach(e=>e.destroy()),r.listContexts().map(e=>r.unload(e)),i.extra={},s.exposeShortcut=null},Object.entries(e).forEach(([e,t])=>{e.startsWith("_")?n[e]=t(i,s):r[e]=t(i,s)}),r}var d=Object.freeze({__proto__:null,pluginClick:function(e,t,n){let{currentContext:r,shortcuts:o}=t,{inAPI:l}=e,a={ev:e.ev,_findTarget:s,_readClickEvent:c,mainDependencies:e,regex:/CLICK\s*\:/i},f={currentContext:r,active:!1,shortcuts:o,listenOptions:{mouseWait:n.mouseWait?n.mouseWait:320,maxClicks:1,clickTarget:n.clickTarget?n.clickTarget:"click"}};l._normalizeWithPlugins(i);let p=function(e,t){const{ev:n,_findTarget:r,_readClickEvent:o,mainDependencies:s}=e,{listenOptions:i,currentContext:c}=t,{mouseWait:u}=i;let l=null,a=null,f=null,p=null,d=0;function m(){const e=o(a,d),t={target:l,targetProps:l?l.getBoundingClientRect():null,x:a.clientX,y:a.clientY,context:c.name,note:c.note,event:a,dependencies:s.extra,type:"click"};n.emit(e,t),f=null,p=null,l=null,a=null,d=0}function h(n){let o=i.maxClicks;return clearTimeout(f),p?(clearTimeout(p),void(p=setTimeout(()=>p=null,u))):(l=r(e,t,n.target),l&&l.dataset.hasOwnProperty("quickClick")&&(o=1),l&&"A"===l.tagName&&(o=1),a=n,d++,d>=o?(m(),void(o>1&&(p=setTimeout(()=>p=null,u)))):void(f=setTimeout(m,u)))}function g(n){let o=i.maxClicks;return clearTimeout(f),p?(clearTimeout(p),void(p=setTimeout(()=>p=null,u))):(l=r(e,t,n.target),l&&l.dataset.hasOwnProperty("quickClick")&&(o=1),l&&"A"===l.tagName&&(o=1),a=n,d++,d>=o?(m(),void(o>1&&(p=setTimeout(()=>p=null,u)))):void(f=setTimeout(m,u)))}return{start:function(){t.active||(window.addEventListener("contextmenu",g),document.addEventListener("click",h),t.active=!0)},stop:function(){t.active&&(window.removeEventListener("contextmenu",g),document.removeEventListener("click",h),t.active=!1,f&&(clearTimeout(f),f=null),p&&(clearTimeout(p),p=null),d=0)}}}(a,f),d=u(a,f);d>0&&p.start();let m={getPrefix:()=>"click",shortcutName:e=>i(e),contextChange:()=>{d=u(a,f),d<1&&p.stop(),d>0&&p.start()},mute:()=>{p.stop()},unmute:()=>p.start(),destroy:()=>p.stop()};return Object.freeze(m),m},pluginForm:function(e,t,n){let{currentContext:r,shortcuts:o}=t,{inAPI:s}=e,i={ev:e.ev,mainDependencies:e,regex:/FORM\s*\:/i,_defaults:f},c={currentContext:r,shortcuts:o,callbacks:{},typeFn:"",watchList:[],wait:{}};s._normalizeWithPlugins(l);let u=function(e,t){const{ev:n}=e;let r=null;function o(e,t,n,r){return{target:n.target,context:t.currentContext.name,note:t.currentContext.note,event:n,dependencies:e.mainDependencies.extra,type:r}}function s(r){const{callbacks:s,typeFn:i}=t,c=i(r.target),u=o(e,t,r,c),l=`${c}/in`;null!=s[l]&&n.emit(l,u,s[l])}function i(r){const{callbacks:s,typeFn:i}=t,c=o(e,t,r,"form-out"),u=`${i(r.target)}/out`;null!=s[u]&&n.emit(u,c,s[u])}function c(s){const{callbacks:i,typeFn:c}=t,u=o(e,t,s,"form-instant"),l=c(s.target),a=t.wait[`${l}`],f=`${l}/instant`;null!=i[f]&&(0!==a?(clearTimeout(r),r=setTimeout(()=>n.emit(f,u,i[f]),a)):n.emit(f,u,i[f]))}return{start:function(){t.active||(document.addEventListener("focusin",s),document.addEventListener("focusout",i),document.addEventListener("input",c),t.active=!0)},stop:function(){t.active&&(document.removeEventListener("focusin",s),document.removeEventListener("focusout",i),document.removeEventListener("input",c),t.active=!1)}}}(i,c);r.name&&a(i,c)&&u.start();let p={getPrefix:()=>"form",shortcutName:e=>l(e),contextChange:()=>{c.callbacks={},c.typeFn="",c.watchList=[],c.wait={},a(i,c)?u.start():u.stop()},mute:()=>u.stop(),unmute:()=>u.start(),destroy:()=>{u.stop()}};return Object.freeze(p),p},pluginKey:function(e,s,i={}){let{currentContext:c,shortcuts:u,exposeShortcut:l}=s,{inAPI:a}=e,f={ev:e.ev,_specialChars:o,_readKeyEvent:n,mainDependencies:e,regex:/KEY\s*\:/i},p={currentContext:c,shortcuts:u,active:!1,listenOptions:{keyWait:i.keyWait?i.keyWait:480,maxSequence:1,keyIgnore:null},streamKeys:!(!i.streamKeys||"function"!=typeof i.streamKeys)&&i.streamKeys};a._normalizeWithPlugins(t);let d=function(e,t){const{ev:n,_specialChars:r,_readKeyEvent:o,mainDependencies:s}=e,{currentContext:i,streamKeys:c,listenOptions:u}=t,{keyWait:l}=u;let a=[],f=null,p=!0,d=!1;const m=()=>p=!1,h=()=>p=!0,g=()=>d=!0,y=()=>!1===p;function v(){let e=a.map(e=>[e.join("+")]);const t={wait:m,end:h,ignore:g,isWaiting:y,note:i.note,context:i.name,dependencies:s.extra,type:"key"};if(!p){let r=e.at(-1);n.emit(r,t),d&&(e=e.slice(0,-1),d=!1)}if(p){const r=`KEY:${e.join(",")}`;n.emit(r,t),a=[],f=null}}function x(t){if(clearTimeout(f),r().hasOwnProperty(t.code))return a.push(o(t,r)),c&&c({key:t.key,context:i.name,note:i.note,dependencies:e.extra}),u.keyIgnore?(clearTimeout(u.keyIgnore),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,l))):p&&a.length===u.maxSequence?(v(),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,l))):void(p?f=setTimeout(v,l):v())}function k(t){if(!r().hasOwnProperty(t.code)){if(clearTimeout(f),c&&c({key:t.key,context:i.name,note:i.note,dependencies:e.extra}),u.keyIgnore)return clearTimeout(u.keyIgnore),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,l));if(a.push(o(t,r)),p&&a.length===u.maxSequence)return v(),void(u.keyIgnore=setTimeout(()=>u.keyIgnore=null,l));p?f=setTimeout(v,l):v()}}return{start:function(){t.active||(document.addEventListener("keydown",x),document.addEventListener("keypress",k),t.active=!0)},stop:function(){t.active&&(document.removeEventListener("keydown",x),document.removeEventListener("keypress",k),t.active=!1,f&&(clearTimeout(f),f=null),u.keyIgnore&&(clearTimeout(u.keyIgnore),u.keyIgnore=null),a=[],p=!0,d=!1)}}}(f,p),m=r(f,p);m>0&&d.start();let h={getPrefix:()=>"key",shortcutName:e=>t(e),contextChange:e=>{m=r(f,p),m<1&&d.stop(),m>0&&d.start()},mute:()=>d.stop(),unmute:()=>d.start(),destroy:()=>d.stop()};return Object.freeze(h),h},shortcuts:p});function m(e){return e?function(e){let t=e.map(e=>h()),n=t.map(e=>e.promise);t.promises=t;let r=g(Promise.all(n));function o(e){let t="pending";return e.then(()=>t="fulfilled").catch(()=>t="rejected"),t}function s(n,...r){t.forEach((t,s)=>n({value:e[s],done:t.done,cancel:t.cancel,timeout:t.timeout,state:o(t.promise)},...r))}const i={promise:Promise.all(n),promises:t,done:e=>{t.forEach(t=>t.done(e))},cancel:e=>{t.forEach(t=>t.cancel(e))},each:s,onComplete:r,timeout:()=>{}};return i.timeout=y(!0,i),i}(e):h()}function h(){let e,t;const n=new Promise((n,r)=>{e=n,t=r}),r={promise:n,promises:null,done:e,cancel:t,each:()=>{},onComplete:g(n),timeout:()=>{}};return r.timeout=y(!1,r),r.each=(n,...o)=>{n({value:null,done:e,cancel:t,timeout:r.timeout},...o)},r}function g(e){return function(t,n=null){null===n?e.then(e=>t(e)):e.then(e=>t(e),e=>n(e))}}function y(e,t){let n;return n=e?Promise.all(t.promises.map(e=>e.promise)):t.promise,function(e,r){let o,s=new Promise((t,s)=>{o=setTimeout(()=>{t(r),Promise.resolve(n)},e)});return n.then(()=>clearTimeout(o)),t.onComplete=g(Promise.race([n,s])),t}}function v({message:e,level:t,type:n,logLevel:r}){if(0===r)return null;if(r<t)return null;const o=`[Debug]: ${e}`;switch(n){case"warn":console.warn(o);break;case"error":console.error(o);break;default:console.log(o)}return o}function x(e={},t=v){return function({message:n,type:r,level:o,...s}){const{level:i,type:c,defaultMessageLevel:u}=Object.assign({},{level:1e3,type:"log",defaultMessageLevel:1},e);return r||(r=c),o||(o=u),t({message:n,type:r,level:o,logLevel:i,...s})}}function*k(e,t,n,r){let o=null,s=!0;if(null===e)return yield*r.map(e=>[e,"show"]),void(yield[n,"show"]);if(0!==r.length){if(r.includes(e)){for(let t=r.indexOf(e)+1;t<r.length;t++)yield[r[t],"show"];return void(yield[n,"show"])}if(!t)return yield[e,"hide"],void(yield*r.map(e=>[e,"show"]));if(r.every((e,n)=>t[n]===r[n]&&(o=n,!0)),null==o)return yield[e,"hide"],t.reverse(),yield*t.map(e=>[e,"hide"]),yield*r.map(e=>[e,"show"]),void(yield[n,"show"]);yield[e,"hide"];for(let e=t.length;e>o+1;e--)yield[t[e-1],"hide"];for(let e=o+1;e<r.length;e++)yield[r[e],"show"];yield[n,"show"]}else{if(!t)return yield[e,"hide"],void(yield[n,"show"]);if(yield[e,"hide"],t.includes(n)){let e=t.indexOf(n),r=t.filter((t,n)=>n>e);r.reverse(),yield*r.map(e=>[e,"hide"]),s=!1}else{let e=[...t];e.reverse(),yield*e.map(e=>[e,"hide"])}s&&(yield[n,"show"])}}function C(e){return function(t,...n){const{askForPromise:r,deps:o}=e;return function(){const e=r();return t({task:e,dependencies:o()},...n),e.promise}}}return m.sequence=function(e,...t){const n=m(),r=[];const o=function*(e){for(const t of e)yield t}(e);return function e(t,...s){t.done?n.done(r):t.value(...s).then(t=>{r.push(t),e(o.next(),...s,t)})}(o.next(),...t),n},m.all=function(e,...t){const n=m(),r=[],o=e.map((e,n)=>"function"==typeof e?e(...t).then(e=>r[n]=e):e.then(e=>r[n]=e));return Promise.all(o).then(()=>n.done(r)),n},function(e={logLevel:0}){const t=p({errorEventName:"@app-error"}),n=x({level:e.logLevel||0}),r={currentScene:null,currentParents:null,sceneNames:new Set,scenes:{},opened:!1,jumpStack:[]},o={},s={shortcutMngr:t,findInstructions:k,askForPromise:m,setInstruction:C({askForPromise:m,deps:t.getDependencies}),log:n};return o.hide=function(e,t){return function(n=1){const{askForPromise:r,shortcutMngr:o,setInstruction:s}=e,{currentScene:i,currentParents:c,scenes:u}=t,l=r(),a=[],f=c.length>0;let p;return o.pause(),a.push(s(u[i].hide)),f||(t.currentScene=null),f&&"*"===n&&[...c].reverse().forEach(e=>{p=t.currentParents.at(-1),t.currentScene=p,a.push(s(u[e].hide))}),f&&!["*",1].includes(n)&&c.slice("-"+(n-1)).reverse().map(e=>{p=t.currentParents.at(-1),t.currentScene=p,a.push(s(u[e].hide))}),(n=r.sequence(a)).onComplete(()=>{o.changeContext(t.currentScene),l.done()}),l.promise}}(s,r),o.listShortcuts=function(e,t){return function(e){const{scenes:n,sceneNames:r}=t;if(!r.has(e))return null;const{show:o,hide:s,parents:i,beforeUnload:c,afterLoad:u,...l}=n[e];return Object.keys(l)}}(0,r),o.setScenes=function(e,t){return function(n){const{shortcutMngr:r}=e;n.forEach(e=>{if(null==e)return;const{name:n,scene:o}=e;if(null==o)return void console.warn(`Scene ${n} is not defined`);o.parents||(o.parents=[]),t.scenes[n]=o,t.sceneNames.add(n);const{show:s,hide:i,parents:c,...u}=o,l={};l[n]=u,r.load(l)})}}(s,r),o.show=function(e,t){return function({scene:n,options:r={ssr:!1}},...o){const{shortcutMngr:s,askForPromise:i,log:c,findInstructions:u,setInstruction:l}=e,a=i(),f=i(),{opened:p,scenes:d,sceneNames:m,currentScene:h}=t;return h&&"function"==typeof d[h].beforeHide?(0,d[h].beforeHide)({done:f.done,dependencies:s.getDependencies()}):f.done(!0),f.onComplete(e=>{if(!e)return a.done(),a.promise;if(!m.has(n)&&c)return c({message:`Scene ${n} is not available.`,level:1,type:"error"}),a.done(),a.promise;if(!p&&r.ssr)return t.opened=!0,t.currentPage=n,s.changeContext(n),a.done(),a.promise;const{show:f,parents:h=[]}=d[n];if("*"===h[0])return f().then(()=>a.done()),t.currentParents.push(t.currentPage),t.currentPage=n,a.promise;function g([e,n]){if("show"===n)t.currentScene&&(t.currentParents=[...d[t.currentScene].parents]),t.currentScene=e;else{let n=d[e].parents.at(-1);t.currentScene=n}return d[e][n]}h.forEach(e=>m.has(e)),t.currentParents||(t.currentParents=[]);const y=u(t.currentScene,t.currentParents,n,h),v=[];for(let e of y){const t=g(e);v.push(l(t,...o))}i.sequence(v).onComplete(()=>{t.opened=!0,t.currentPage=n,t.currentParents=d[n].parents||null,s.changeContext(n),"function"==typeof d[n].afterShow&&d[n].afterShow({dependencies:s.getDependencies(),done:()=>{}}),a.done()})}),a.promise}}(s,r),o.jump=function(e,t){return function({scene:n},...r){return e.jumpStack.push(e.currentScene),t({scene:n},...r)}}(r,o.show),o.jumpBack=function(e,t){return function({hops:n}={hops:1},...r){for(let t=0;t<n-1;t++)e.jumpStack.pop();if(0===e.jumpStack.length)return;const o=e.jumpStack.pop();return t({scene:o},...r)}}(r,o.show),o.jumpsReset=function(e){return function(){e.jumpStack=[]}}(r),o.loadPlugins=async function(e){const t=e.map(e=>`plugin${e}`),n=await Promise.resolve().then(function(){return d});return t.map(e=>n[e])},o.setDependencies=e=>t.setDependencies(e),o.getDependencies=()=>t.getDependencies(),o.setNote=e=>p.setNote(e),o.listScenes=()=>[...r.sceneNames],o.enablePlugin=(e,n)=>t.enablePlugin(e,n),o.disablePlugin=e=>t.disablePlugin(e),o.getState=()=>({scene:r.currentScene,parents:r.currentParents,opened:r.opened}),o.emit=(e,...n)=>t.emit(e,...n),o}});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peter.naydenov/cuts",
|
|
3
3
|
"description": "SPA scene manager",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.5.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Peter Naydenov",
|
|
7
7
|
"main": "./src/main.js",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"build": "rollup -c",
|
|
23
23
|
"postbuild": "tsc -p tsconfig.json",
|
|
24
24
|
"preview": "vite preview",
|
|
25
|
-
"test": "
|
|
26
|
-
"cover": "
|
|
25
|
+
"test": "vitest",
|
|
26
|
+
"cover": "vitest run --coverage",
|
|
27
27
|
"cypress": "cypress open --component --browser chrome"
|
|
28
28
|
},
|
|
29
29
|
"repository": {
|
|
@@ -32,38 +32,24 @@
|
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@peter.naydenov/visual-controller-for-vue3": "^2.1.6",
|
|
35
|
-
"@rollup/plugin-commonjs": "^28.0.
|
|
36
|
-
"@rollup/plugin-node-resolve": "^16.0.
|
|
35
|
+
"@rollup/plugin-commonjs": "^28.0.8",
|
|
36
|
+
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
37
37
|
"@rollup/plugin-terser": "^0.4.4",
|
|
38
|
-
"@types/node": "^24.
|
|
38
|
+
"@types/node": "^24.9.1",
|
|
39
39
|
"@vitejs/plugin-vue": "^6.0.1",
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"mocha": "^11.7.4",
|
|
44
|
-
"rollup": "^4.52.4",
|
|
40
|
+
"@vitest/coverage-v8": "^4.0.1",
|
|
41
|
+
"cypress": "^15.5.0",
|
|
42
|
+
"rollup": "^4.52.5",
|
|
45
43
|
"typescript": "^5.9.3",
|
|
46
|
-
"vite": "^7.1.
|
|
44
|
+
"vite": "^7.1.11",
|
|
45
|
+
"vitest": "^4.0.1",
|
|
47
46
|
"vue": "^3.5.22"
|
|
48
47
|
},
|
|
49
48
|
"dependencies": {
|
|
50
49
|
"@peter.naydenov/log": "^1.1.1",
|
|
51
|
-
"@peter.naydenov/shortcuts": "^3.
|
|
50
|
+
"@peter.naydenov/shortcuts": "^3.5.1",
|
|
52
51
|
"ask-for-promise": "^3.0.2"
|
|
53
52
|
},
|
|
54
|
-
"c8": {
|
|
55
|
-
"include": [
|
|
56
|
-
"src/**/*.js"
|
|
57
|
-
],
|
|
58
|
-
"exclude": [
|
|
59
|
-
"node_modules",
|
|
60
|
-
"test"
|
|
61
|
-
],
|
|
62
|
-
"reporter": [
|
|
63
|
-
"lcov",
|
|
64
|
-
"text-summary"
|
|
65
|
-
]
|
|
66
|
-
},
|
|
67
53
|
"keywords": [
|
|
68
54
|
"script",
|
|
69
55
|
"visual",
|
package/src/findInstructions.js
CHANGED
|
@@ -1,29 +1,48 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @function findInstructions
|
|
6
|
+
* @description Generator that yields instructions for transitioning between scenes
|
|
7
|
+
* @param {string|null} currentName - current scene name
|
|
8
|
+
* @param {Array.<string>} currentParents - current scene parents
|
|
9
|
+
* @param {string} targetName - target scene name
|
|
10
|
+
* @param {Array.<string>} targetParents - target scene parents
|
|
11
|
+
* @yields {Array.<string, 'show'|'hide'>} - instruction array with scene name and action
|
|
12
|
+
*/
|
|
4
13
|
function* findInstructions ( currentName, currentParents, targetName, targetParents ) {
|
|
5
|
-
let backToName, backIndex=null;
|
|
6
|
-
|
|
14
|
+
let backToName, backIndex=null, isNoParent=true;
|
|
15
|
+
|
|
7
16
|
if ( currentName === null ) { // When the scene manager is just started
|
|
8
17
|
yield* targetParents.map ( name => [ name, 'show' ])
|
|
9
18
|
yield [ targetName, 'show' ]
|
|
10
19
|
return
|
|
11
20
|
}
|
|
12
21
|
|
|
13
|
-
if (
|
|
22
|
+
if ( targetParents.length === 0 ) { // Need to close all current parents, then open the target
|
|
14
23
|
if ( !currentParents ) {
|
|
15
24
|
yield [ currentName, 'hide' ]
|
|
16
25
|
yield [ targetName, 'show' ]
|
|
17
26
|
return
|
|
18
27
|
}
|
|
19
28
|
yield [ currentName, 'hide' ]
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
29
|
+
|
|
30
|
+
if ( currentParents.includes ( targetName ) ) {
|
|
31
|
+
let index = currentParents.indexOf ( targetName );
|
|
32
|
+
let filtered = currentParents.filter ( (x,i) => i > index )
|
|
33
|
+
filtered.reverse ()
|
|
34
|
+
yield* filtered.map ( name => [ name, 'hide' ])
|
|
35
|
+
isNoParent = false
|
|
36
|
+
} else {
|
|
37
|
+
let cp = [...currentParents]
|
|
38
|
+
cp.reverse ()
|
|
39
|
+
yield* cp.map ( name => [ name, 'hide' ])
|
|
40
|
+
}
|
|
41
|
+
if ( isNoParent ) yield [ targetName, 'show' ]
|
|
23
42
|
return
|
|
24
43
|
}
|
|
25
44
|
|
|
26
|
-
if ( targetParents.includes ( currentName ) ) { // Target is a
|
|
45
|
+
if ( targetParents.includes ( currentName ) ) { // Target is a subscene of the current scene. No closing needed.
|
|
27
46
|
let id = targetParents.indexOf ( currentName );
|
|
28
47
|
for ( let i = id+1; i < targetParents.length; i++ ) {
|
|
29
48
|
yield [ targetParents[i], 'show' ]
|
|
@@ -58,6 +77,7 @@ function* findInstructions ( currentName, currentParents, targetName, targetPare
|
|
|
58
77
|
return
|
|
59
78
|
}
|
|
60
79
|
|
|
80
|
+
|
|
61
81
|
yield [ currentName, 'hide' ]
|
|
62
82
|
for ( let i = currentParents.length; i > backIndex+1; i-- ) {
|
|
63
83
|
yield [ currentParents[i-1], 'hide' ]
|
package/src/main.js
CHANGED
|
@@ -36,7 +36,7 @@ import jumpsReset from './methods/jumpsReset.js'
|
|
|
36
36
|
|
|
37
37
|
function main ( cfg= {logLevel:0} ) {
|
|
38
38
|
const
|
|
39
|
-
shortcutMngr = shortcuts ()
|
|
39
|
+
shortcutMngr = shortcuts ({ errorEventName: '@app-error' })
|
|
40
40
|
, logLevel = cfg.logLevel || 0
|
|
41
41
|
, log = createLog ({ level:logLevel })
|
|
42
42
|
, state = {
|
|
@@ -134,16 +134,29 @@ function main ( cfg= {logLevel:0} ) {
|
|
|
134
134
|
* @returns void
|
|
135
135
|
*/
|
|
136
136
|
API.disablePlugin = ( pluginName ) => shortcutMngr.disablePlugin ( pluginName )
|
|
137
|
-
|
|
138
|
-
|
|
137
|
+
|
|
139
138
|
/**
|
|
140
|
-
*
|
|
141
|
-
* @
|
|
142
|
-
* @
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
139
|
+
* Get the current state of the application
|
|
140
|
+
* @function getState
|
|
141
|
+
* @returns {Object} with properties:
|
|
142
|
+
* - scene: current scene name
|
|
143
|
+
* - parents: current parent scene names
|
|
144
|
+
* - opened: boolean indicating if the application is opened
|
|
146
145
|
*/
|
|
146
|
+
API.getState = () => ({
|
|
147
|
+
scene : state.currentScene
|
|
148
|
+
, parents : state.currentParents
|
|
149
|
+
, opened : state.opened
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* @function emit
|
|
155
|
+
* @description Emit an event
|
|
156
|
+
* @param {string} event - event name
|
|
157
|
+
* @param {...*} args - Extra data to pass to the listeners
|
|
158
|
+
* @returns void
|
|
159
|
+
*/
|
|
147
160
|
API.emit = ( event, ...args ) => shortcutMngr.emit ( event, ...args )
|
|
148
161
|
return API
|
|
149
162
|
} // main func.
|
package/src/methods/hide.js
CHANGED
|
@@ -26,14 +26,14 @@ return function hide ( endSteps=1 ) {
|
|
|
26
26
|
|
|
27
27
|
if ( hasParents && endSteps === '*' ) {
|
|
28
28
|
[...currentParents].reverse().forEach ( name => {
|
|
29
|
-
el = state.currentParents.
|
|
29
|
+
el = state.currentParents.at ( -1 )
|
|
30
30
|
state.currentScene = el
|
|
31
31
|
instructions.push ( setInstruction ( scenes[name].hide))
|
|
32
32
|
})
|
|
33
33
|
}
|
|
34
34
|
if ( hasParents && ![ '*', 1].includes(endSteps) ) {
|
|
35
35
|
currentParents.slice ( `-${endSteps-1}` ).reverse().map ( name => {
|
|
36
|
-
el = state.currentParents.
|
|
36
|
+
el = state.currentParents.at ( -1 )
|
|
37
37
|
state.currentScene = el
|
|
38
38
|
instructions.push ( setInstruction (scenes[name].hide))
|
|
39
39
|
})
|
package/src/methods/jump.js
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
function jump ( state, show ) {
|
|
2
|
+
/**
|
|
3
|
+
* @function jump
|
|
4
|
+
* @description Jump to a scene, saving the current scene on the jump stack for later return
|
|
5
|
+
* @param {Object} request - request object
|
|
6
|
+
* @param {string} request.scene - target scene name
|
|
7
|
+
* @param {Array} [args] - arguments to pass to the scene method
|
|
8
|
+
* @returns {Promise} - promise that resolves when the jump is completed
|
|
9
|
+
*/
|
|
2
10
|
function jump ( { scene }, ...args ) {
|
|
3
11
|
state.jumpStack.push ( state.currentScene )
|
|
4
12
|
return show ( { scene }, ...args )
|
package/src/methods/jumpBack.js
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
function jumpBack ( state, show ) {
|
|
2
|
+
/**
|
|
3
|
+
* @function jumpBack
|
|
4
|
+
* @description Jump back to a previous scene from the jump stack
|
|
5
|
+
* @param {Object} [options] - options object
|
|
6
|
+
* @param {number} [options.hops=1] - number of hops to jump back
|
|
7
|
+
* @param {Array} [args] - arguments to pass to the scene method
|
|
8
|
+
* @returns {Promise|undefined} - promise that resolves when the jump back is completed, or undefined if no scenes in stack
|
|
9
|
+
*/
|
|
2
10
|
function jumpBack ({hops}={hops:1}, ...args ) {
|
|
3
11
|
for ( let i = 0; i < hops-1; i++ ) {
|
|
4
12
|
state.jumpStack.pop ()
|
package/src/methods/setScenes.js
CHANGED
|
@@ -3,32 +3,32 @@
|
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @typedef {Object} SceneObject
|
|
6
|
-
* @
|
|
7
|
-
* @
|
|
8
|
-
* @
|
|
9
|
-
* @
|
|
10
|
-
* @
|
|
11
|
-
* @
|
|
6
|
+
* @property {function} show - load interface and prerequisites for the scene;
|
|
7
|
+
* @property {function():boolean} [afterShow] - run after scene is loaded. Optional. Returns true to continue loading, false to cancel;
|
|
8
|
+
* @property {function():void} hide - Reverse the settings from 'show';
|
|
9
|
+
* @property {function():void} [beforeHide] - Run before scene is hidden. Optional;
|
|
10
|
+
* @property {Array.<string>} [parents] - list of parent scene names.
|
|
11
|
+
* @property {*} ... - shortcut descriptions
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
/**
|
|
16
|
+
/**
|
|
17
17
|
* @typedef {Object} sceneDescription
|
|
18
|
-
* @
|
|
19
|
-
* @
|
|
18
|
+
* @property {string} name - name of the scene
|
|
19
|
+
* @property {SceneObject} scene - object should contain 'show' and 'hide' + shortcuts and action functions
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
function setScenes ( dependencies, state ) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
/**
|
|
27
|
+
* @function setScenes
|
|
28
|
+
* @param {sceneDescription[]} list - list of objects with name and scene. Scene should be a Scene model.
|
|
29
|
+
* @returns void
|
|
30
|
+
* @description Screen Description is an object with fields 'name' and 'scene'
|
|
31
|
+
*/
|
|
32
32
|
return function setScenes ( list ) {
|
|
33
33
|
const { shortcutMngr } = dependencies;
|
|
34
34
|
list.forEach ( item => {
|
package/src/methods/show.js
CHANGED
|
@@ -18,20 +18,18 @@ function show ( dependencies, state ) {
|
|
|
18
18
|
{ shortcutMngr, askForPromise, log, findInstructions, setInstruction } = dependencies
|
|
19
19
|
, showTask = askForPromise ()
|
|
20
20
|
, unloadTask = askForPromise ()
|
|
21
|
-
, { opened, scenes, sceneNames,
|
|
21
|
+
, { opened, scenes, sceneNames, currentScene } = state
|
|
22
|
+
, hasBeforeHide = currentScene && (typeof scenes[currentScene].beforeHide === 'function')
|
|
22
23
|
;
|
|
23
24
|
|
|
24
|
-
if (
|
|
25
|
-
const closingFn = scenes[
|
|
26
|
-
|
|
27
|
-
closingFn ({ done:unloadTask.done, dependencies: shortcutMngr.getDependencies() })
|
|
28
|
-
}
|
|
25
|
+
if ( hasBeforeHide ) { // Execute 'beforeUnload' function if exists
|
|
26
|
+
const closingFn = scenes[currentScene].beforeHide;
|
|
27
|
+
closingFn ({ done:unloadTask.done, dependencies: shortcutMngr.getDependencies() })
|
|
29
28
|
} // if currentPage
|
|
30
29
|
else unloadTask.done ( true )
|
|
31
30
|
|
|
32
31
|
|
|
33
32
|
unloadTask.onComplete ( continueLoading => {
|
|
34
|
-
|
|
35
33
|
if ( !continueLoading ) {
|
|
36
34
|
// if the 'beforeUnload' function returns false
|
|
37
35
|
// Cancel loading the new scene
|
|
@@ -70,10 +68,11 @@ function show ( dependencies, state ) {
|
|
|
70
68
|
}
|
|
71
69
|
|
|
72
70
|
let checkParents = parents.forEach ( name => sceneNames.has ( name ) ) || true ;
|
|
71
|
+
|
|
73
72
|
if ( !checkParents ) {
|
|
74
73
|
if ( log ) {
|
|
75
74
|
log ({
|
|
76
|
-
|
|
75
|
+
message: `Some of '${requestedScene}' parent scenes are not set.`
|
|
77
76
|
, level : 1
|
|
78
77
|
, type : 'error'
|
|
79
78
|
})
|
|
@@ -82,13 +81,13 @@ function show ( dependencies, state ) {
|
|
|
82
81
|
return showTask.promise
|
|
83
82
|
}
|
|
84
83
|
|
|
85
|
-
|
|
84
|
+
function getStep ([name, action]) { // Returns a scene function(hide or show) according to instructions
|
|
86
85
|
if ( action === 'show' ) {
|
|
87
|
-
if ( state.currentScene ) state.currentParents
|
|
86
|
+
if ( state.currentScene ) state.currentParents = [...scenes[state.currentScene].parents]
|
|
88
87
|
state.currentScene = name
|
|
89
88
|
}
|
|
90
89
|
else {
|
|
91
|
-
let el =
|
|
90
|
+
let el = scenes[name].parents.at ( -1 )
|
|
92
91
|
state.currentScene = el
|
|
93
92
|
}
|
|
94
93
|
return scenes[name][action]
|
|
@@ -96,22 +95,22 @@ function show ( dependencies, state ) {
|
|
|
96
95
|
|
|
97
96
|
if ( !state.currentParents ) state.currentParents = []
|
|
98
97
|
const
|
|
99
|
-
|
|
98
|
+
g = findInstructions ( state.currentScene, state.currentParents, requestedScene, parents )
|
|
100
99
|
, instructions = []
|
|
101
100
|
;
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
101
|
+
|
|
102
|
+
for ( let inst of g ) {
|
|
103
|
+
const step = getStep ( inst )
|
|
104
|
+
instructions.push ( setInstruction(step, ...args) )
|
|
105
|
+
// Note: Methods 'show' and 'hide' are async, but we need to provide them a data,
|
|
106
|
+
// so we need to wrap them in a another function that returns a promise
|
|
107
|
+
}
|
|
111
108
|
const goingTask = askForPromise.sequence ( instructions ); // Execute open steps(show and hide) in sequence
|
|
112
109
|
|
|
113
110
|
goingTask.onComplete ( () => {
|
|
114
111
|
state.opened = true
|
|
112
|
+
state.currentPage = requestedScene
|
|
113
|
+
state.currentParents = scenes[requestedScene].parents || null
|
|
115
114
|
shortcutMngr.changeContext ( requestedScene )
|
|
116
115
|
if ( typeof scenes[requestedScene].afterShow === 'function' ) scenes[requestedScene].afterShow ({ dependencies: shortcutMngr.getDependencies(), done: () => {} })
|
|
117
116
|
showTask.done ()
|
package/src/setInstruction.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
function setInstruction ( dependencies ) {
|
|
4
|
+
/**
|
|
5
|
+
* @function setInstruction
|
|
6
|
+
* @description Wrap a scene function (show/hide) to return a promise-based instruction
|
|
7
|
+
* @param {function} fn - the scene function to wrap
|
|
8
|
+
* @param {...*} args - arguments to pass to the scene function
|
|
9
|
+
* @returns {function} - a function that returns a promise when executed
|
|
10
|
+
*/
|
|
4
11
|
return function setInstruction ( fn, ...args ) {
|
|
5
12
|
const { askForPromise, deps } = dependencies;
|
|
6
13
|
return function applyInstruction () {
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import findInstructions from "../src/findInstructions.js"
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
describe ( 'Find a Position', () => {
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
it ( 'Switch top level scenes', () => {
|
|
11
|
+
let result = []
|
|
12
|
+
let g = findInstructions ( 'old', [], 'new', [] )
|
|
13
|
+
|
|
14
|
+
for (const n of g) { result.push(n) }
|
|
15
|
+
|
|
16
|
+
expect(result.length).toBe ( 2 )
|
|
17
|
+
expect(result[0][0]).toBe ( 'old' )
|
|
18
|
+
expect(result[0][1]).toBe ( 'hide' )
|
|
19
|
+
|
|
20
|
+
expect(result[1][0]).toBe ( 'new' )
|
|
21
|
+
expect(result[1][1]).toBe ( 'show' )
|
|
22
|
+
}) // it switch top level scenes
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
it ( 'Switch from child scene to top level scene', () => {
|
|
27
|
+
let result = []
|
|
28
|
+
let g = findInstructions ( 'old', ['one', 'two'], 'new', [] )
|
|
29
|
+
|
|
30
|
+
for (const n of g) { result.push(n) }
|
|
31
|
+
|
|
32
|
+
expect(result[0]).toEqual(['old', 'hide'])
|
|
33
|
+
expect(result[1]).toEqual(['two', 'hide'])
|
|
34
|
+
expect(result[2]).toEqual(['one', 'hide'])
|
|
35
|
+
expect(result[3]).toEqual(['new', 'show'])
|
|
36
|
+
}) // it switch from child scene to top level scene
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
it ( 'Switch to child scene', () => {
|
|
41
|
+
let result = []
|
|
42
|
+
let g = findInstructions ( 'old', ['bla'], 'new', ['old', 'two', 'three'])
|
|
43
|
+
for (const n of g) { result.push(n) }
|
|
44
|
+
|
|
45
|
+
expect(result).toHaveLength(3)
|
|
46
|
+
expect(result[0]).toEqual(['two', 'show'])
|
|
47
|
+
expect(result[1]).toEqual(['three', 'show'])
|
|
48
|
+
expect(result[2]).toEqual(['new', 'show'])
|
|
49
|
+
}) // it switch to child scene
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
it ( 'From child scene to other siblings scene', () => {
|
|
54
|
+
let result = []
|
|
55
|
+
let g = findInstructions('old', ['two', 'three'], 'new', ['two', 'three'])
|
|
56
|
+
for (const n of g) { result.push(n) }
|
|
57
|
+
|
|
58
|
+
expect(result).toHaveLength ( 2 )
|
|
59
|
+
expect(result[0]).toEqual(['old', 'hide'])
|
|
60
|
+
expect(result[1]).toEqual(['new', 'show'])
|
|
61
|
+
}) // it from top level scene to not own child scene
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
it ( 'From top level scene to not own child scene', () => {
|
|
66
|
+
let result = []
|
|
67
|
+
let g = findInstructions('old', undefined, 'new', ['two', 'three'])
|
|
68
|
+
for (const n of g) { result.push(n) }
|
|
69
|
+
|
|
70
|
+
expect(result).toHaveLength(3)
|
|
71
|
+
expect(result[0]).toEqual(['old', 'hide'])
|
|
72
|
+
expect(result[1]).toEqual(['two', 'show'])
|
|
73
|
+
expect(result[2]).toEqual(['three', 'show'])
|
|
74
|
+
}) // it from top level scene to not own child scene
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
it ( 'Long chain of parents', () => {
|
|
79
|
+
let result = []
|
|
80
|
+
let g = findInstructions('old', ['one', 'branch'], 'new', ['one', 'two', 'three'])
|
|
81
|
+
for (const n of g) { result.push(n) }
|
|
82
|
+
|
|
83
|
+
expect(result).toHaveLength(5)
|
|
84
|
+
expect(result[0]).toEqual(['old', 'hide'])
|
|
85
|
+
expect(result[1]).toEqual(['branch', 'hide'])
|
|
86
|
+
expect(result[2]).toEqual(['two', 'show'])
|
|
87
|
+
expect(result[3]).toEqual(['three', 'show'])
|
|
88
|
+
expect(result[4]).toEqual(['new', 'show'])
|
|
89
|
+
}) // it long chain of parents
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
it ( 'Different branches', () => {
|
|
94
|
+
let result = []
|
|
95
|
+
let g = findInstructions('old', ['something', 'branch'], 'new', ['one', 'two', 'three'])
|
|
96
|
+
for (const n of g) { result.push(n) }
|
|
97
|
+
|
|
98
|
+
expect(result).toHaveLength(7)
|
|
99
|
+
expect(result[0]).toEqual(['old', 'hide'])
|
|
100
|
+
expect(result[1]).toEqual(['branch', 'hide'])
|
|
101
|
+
expect(result[2]).toEqual(['something', 'hide'])
|
|
102
|
+
expect(result[3]).toEqual(['one', 'show'])
|
|
103
|
+
expect(result[4]).toEqual(['two', 'show'])
|
|
104
|
+
expect(result[5]).toEqual(['three', 'show'])
|
|
105
|
+
expect(result[6]).toEqual(['new', 'show'])
|
|
106
|
+
}) // it long chain of parents
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
it ( 'Target scene is in the list of parents of the current scene', () => {
|
|
111
|
+
let result = []
|
|
112
|
+
let g = findInstructions ( 'token-get-role', ['tokens', 'token-pop'], 'tokens', [] )
|
|
113
|
+
for (const n of g) { result.push(n) }
|
|
114
|
+
expect ( result ).toHaveLength ( 2 )
|
|
115
|
+
expect ( result[0] ).toEqual ( [ 'token-get-role', 'hide' ])
|
|
116
|
+
expect ( result[1] ).toEqual ( [ 'token-pop', 'hide' ])
|
|
117
|
+
}) // it Target scene is in the list of parents of the current scene
|
|
118
|
+
|
|
119
|
+
}) // describe
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import cuts from "../src/main.js"
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
describe ( 'Cuts integration', () => {
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
it ( 'Open a scene, and 2 levels deep child', async () => {
|
|
11
|
+
const calls = [];
|
|
12
|
+
|
|
13
|
+
const scenes = [
|
|
14
|
+
{ name: 'top', scene: { show: ({task}) => { calls.push('show top'); task.done() }, hide: ({task}) => { calls.push('hide top'); task.done() } } },
|
|
15
|
+
{ name: 'mid', scene: { show: ({task}) => { calls.push('show mid'); task.done() }, hide: ({task}) => { calls.push('hide mid'); task.done() }, parents: ['top'] } },
|
|
16
|
+
{ name: 'deep', scene: { show: ({task}) => { calls.push('show deep'); task.done() }, hide: ({task}) => { calls.push('hide deep'); task.done() }, parents: ['top', 'mid'] } }
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
const script = cuts()
|
|
20
|
+
script.setScenes ( scenes )
|
|
21
|
+
|
|
22
|
+
await script.show ({ scene: 'top' })
|
|
23
|
+
expect ( calls ).toEqual ([ 'show top' ])
|
|
24
|
+
|
|
25
|
+
await script.show ({ scene: 'deep' })
|
|
26
|
+
expect ( calls ).toEqual ([
|
|
27
|
+
'show top',
|
|
28
|
+
'show mid',
|
|
29
|
+
'show deep'
|
|
30
|
+
])
|
|
31
|
+
|
|
32
|
+
await script.show ({ scene: 'top' })
|
|
33
|
+
expect ( calls ).toEqual ([
|
|
34
|
+
'show top',
|
|
35
|
+
'show mid',
|
|
36
|
+
'show deep',
|
|
37
|
+
'hide deep',
|
|
38
|
+
'hide mid'
|
|
39
|
+
])
|
|
40
|
+
|
|
41
|
+
await script.show ({ scene: 'deep' })
|
|
42
|
+
expect ( calls ).toEqual ([
|
|
43
|
+
'show top',
|
|
44
|
+
'show mid',
|
|
45
|
+
'show deep',
|
|
46
|
+
'hide deep',
|
|
47
|
+
'hide mid',
|
|
48
|
+
'show mid',
|
|
49
|
+
'show deep'
|
|
50
|
+
])
|
|
51
|
+
}) // it Open a scene, and 2 levels deep child
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
}) // describe
|
package/tsconfig.json
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
1
|
export default findInstructions;
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* @function findInstructions
|
|
4
|
+
* @description Generator that yields instructions for transitioning between scenes
|
|
5
|
+
* @param {string|null} currentName - current scene name
|
|
6
|
+
* @param {Array.<string>} currentParents - current scene parents
|
|
7
|
+
* @param {string} targetName - target scene name
|
|
8
|
+
* @param {Array.<string>} targetParents - target scene parents
|
|
9
|
+
* @yields {Array.<string, 'show'|'hide'>} - instruction array with scene name and action
|
|
10
|
+
*/
|
|
11
|
+
declare function findInstructions(currentName: string | null, currentParents: Array<string>, targetName: string, targetParents: Array<string>): Generator<string[], void, unknown>;
|
|
3
12
|
//# sourceMappingURL=findInstructions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"findInstructions.d.ts","sourceRoot":"","sources":["../src/findInstructions.js"],"names":[],"mappings":";AAGA,
|
|
1
|
+
{"version":3,"file":"findInstructions.d.ts","sourceRoot":"","sources":["../src/findInstructions.js"],"names":[],"mappings":";AAGA;;;;;;;;GAQG;AACH,+CANW,MAAM,GAAC,IAAI,kBACX,KAAK,CAAE,MAAM,CAAC,cACd,MAAM,iBACN,KAAK,CAAE,MAAM,CAAC,sCA+ExB"}
|
package/types/main.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ declare function main(cfg?: {
|
|
|
4
4
|
}): {
|
|
5
5
|
hide: (endSteps?: number | string) => Promise<any>;
|
|
6
6
|
listShortcuts: (sceneName: string) => (Array<string> | null);
|
|
7
|
-
setScenes: (list:
|
|
7
|
+
setScenes: (list: import("./methods/setScenes.js").sceneDescription[]) => void;
|
|
8
8
|
show: ({ scene: requestedScene, options }: {
|
|
9
9
|
scene: string;
|
|
10
10
|
options?: {
|
|
@@ -12,19 +12,20 @@ declare function main(cfg?: {
|
|
|
12
12
|
};
|
|
13
13
|
}, ...args?: any[]) => Promise<any>;
|
|
14
14
|
jump: ({ scene }: {
|
|
15
|
-
scene:
|
|
16
|
-
}, ...args
|
|
15
|
+
scene: string;
|
|
16
|
+
}, ...args?: any[]) => Promise<any>;
|
|
17
17
|
jumpBack: ({ hops }?: {
|
|
18
|
-
hops
|
|
19
|
-
}, ...args
|
|
18
|
+
hops?: number;
|
|
19
|
+
}, ...args?: any[]) => Promise<any> | undefined;
|
|
20
20
|
jumpsReset: () => void;
|
|
21
21
|
loadPlugins(plugins: Array<"Key" | "Click" | "Form">): Promise<Function[]>;
|
|
22
|
-
setDependencies(deps: any):
|
|
22
|
+
setDependencies(deps: any): void;
|
|
23
23
|
getDependencies(): any;
|
|
24
24
|
setNote(note: string): any;
|
|
25
25
|
listScenes(): Array<string>;
|
|
26
|
-
enablePlugin(plugin: Function, options?: any):
|
|
27
|
-
disablePlugin(pluginName: string):
|
|
28
|
-
|
|
26
|
+
enablePlugin(plugin: Function, options?: any): void;
|
|
27
|
+
disablePlugin(pluginName: string): void;
|
|
28
|
+
getState(): any;
|
|
29
|
+
emit(event: string, ...args: any[]): void;
|
|
29
30
|
};
|
|
30
31
|
//# sourceMappingURL=main.d.ts.map
|
package/types/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.js"],"names":[],"mappings":";AAoCA
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.js"],"names":[],"mappings":";AAoCA;;;;;;;;;;;;;;;;;;;yBAyCmB,KAAK,0BAAc,GACjB,OAAO,CAAE,UAAU,CAAC;0BAgBtB,GAAC;uBAQC,GAAC;kBAMH,MAAM;kBAQJ,KAAK,CAAE,MAAM,CAAC;6CAQhB,GAAC;8BAQD,MAAM;;gBAuBL,MAAM,WACH,GAAC,EAAA;EAKvB"}
|
package/types/methods/jump.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jump.d.ts","sourceRoot":"","sources":["../../src/methods/jump.js"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"jump.d.ts","sourceRoot":"","sources":["../../src/methods/jump.js"],"names":[],"mappings":";AAAA,0DAKO;IAAwB,KAAK,EAArB,MAAM;CACd,mCAQN"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jumpBack.d.ts","sourceRoot":"","sources":["../../src/methods/jumpBack.js"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"jumpBack.d.ts","sourceRoot":"","sources":["../../src/methods/jumpBack.js"],"names":[],"mappings":";AAAA,8DAKO;IAAyB,IAAI,GAArB,MAAM;CACd,sBACU,eAAQ,SAAS,CAWjC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jumpsReset.d.ts","sourceRoot":"","sources":["../../src/methods/jumpsReset.js"],"names":[],"mappings":";AAAA,
|
|
1
|
+
{"version":3,"file":"jumpsReset.d.ts","sourceRoot":"","sources":["../../src/methods/jumpsReset.js"],"names":[],"mappings":";AAAA,+CAIiB,IAAI,CAKpB"}
|
|
@@ -1,19 +1,53 @@
|
|
|
1
1
|
export default setScenes;
|
|
2
|
-
export type SceneObject =
|
|
3
|
-
|
|
2
|
+
export type SceneObject = {
|
|
3
|
+
/**
|
|
4
|
+
* - load interface and prerequisites for the scene;
|
|
5
|
+
*/
|
|
6
|
+
show: Function;
|
|
7
|
+
/**
|
|
8
|
+
* - run after scene is loaded. Optional. Returns true to continue loading, false to cancel;
|
|
9
|
+
*/
|
|
10
|
+
afterShow?: () => boolean;
|
|
11
|
+
/**
|
|
12
|
+
* - Reverse the settings from 'show';
|
|
13
|
+
*/
|
|
14
|
+
hide: () => void;
|
|
15
|
+
/**
|
|
16
|
+
* - Run before scene is hidden. Optional;
|
|
17
|
+
*/
|
|
18
|
+
beforeHide?: () => void;
|
|
19
|
+
/**
|
|
20
|
+
* - list of parent scene names.
|
|
21
|
+
*/
|
|
22
|
+
parents?: Array<string>;
|
|
23
|
+
/**
|
|
24
|
+
* - shortcut descriptions
|
|
25
|
+
*/
|
|
26
|
+
"": any;
|
|
27
|
+
};
|
|
28
|
+
export type sceneDescription = {
|
|
29
|
+
/**
|
|
30
|
+
* - name of the scene
|
|
31
|
+
*/
|
|
32
|
+
name: string;
|
|
33
|
+
/**
|
|
34
|
+
* - object should contain 'show' and 'hide' + shortcuts and action functions
|
|
35
|
+
*/
|
|
36
|
+
scene: SceneObject;
|
|
37
|
+
};
|
|
4
38
|
/**
|
|
5
39
|
* @typedef {Object} SceneObject
|
|
6
|
-
* @
|
|
7
|
-
* @
|
|
8
|
-
* @
|
|
9
|
-
* @
|
|
10
|
-
* @
|
|
11
|
-
* @
|
|
40
|
+
* @property {function} show - load interface and prerequisites for the scene;
|
|
41
|
+
* @property {function():boolean} [afterShow] - run after scene is loaded. Optional. Returns true to continue loading, false to cancel;
|
|
42
|
+
* @property {function():void} hide - Reverse the settings from 'show';
|
|
43
|
+
* @property {function():void} [beforeHide] - Run before scene is hidden. Optional;
|
|
44
|
+
* @property {Array.<string>} [parents] - list of parent scene names.
|
|
45
|
+
* @property {*} ... - shortcut descriptions
|
|
12
46
|
*/
|
|
13
47
|
/**
|
|
14
48
|
* @typedef {Object} sceneDescription
|
|
15
|
-
* @
|
|
16
|
-
* @
|
|
49
|
+
* @property {string} name - name of the scene
|
|
50
|
+
* @property {SceneObject} scene - object should contain 'show' and 'hide' + shortcuts and action functions
|
|
17
51
|
*/
|
|
18
|
-
declare function setScenes(dependencies: any, state: any): (list:
|
|
52
|
+
declare function setScenes(dependencies: any, state: any): (list: sceneDescription[]) => void;
|
|
19
53
|
//# sourceMappingURL=setScenes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setScenes.d.ts","sourceRoot":"","sources":["../../src/methods/setScenes.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"setScenes.d.ts","sourceRoot":"","sources":["../../src/methods/setScenes.js"],"names":[],"mappings":";;;;;;;;;gBAMc,MAAW,OAAO;;;;UAClB,MAAW,IAAI;;;;iBACf,MAAW,IAAI;;;;cACf,KAAK,CAAE,MAAM,CAAC;;;;QACd,GAAC;;;;;;UAOD,MAAM;;;;WACN,WAAW;;AAfzB;;;;;;;;GAQG;AAIH;;;;GAIG;AAKH,4DAOgC,MAJhB,gBAAgB,EAII,UAsBlC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"show.d.ts","sourceRoot":"","sources":["../../src/methods/show.js"],"names":[],"mappings":";AAIA,2FAKG;IAAwB,KAAK,EAArB,MAAM;IACW,OAAO,GAChC;QAAiC,GAAG,EAA5B,OAAO;KACf;CAAA,
|
|
1
|
+
{"version":3,"file":"show.d.ts","sourceRoot":"","sources":["../../src/methods/show.js"],"names":[],"mappings":";AAIA,2FAKG;IAAwB,KAAK,EAArB,MAAM;IACW,OAAO,GAChC;QAAiC,GAAG,EAA5B,OAAO;KACf;CAAA,mCA6GF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setInstruction.d.ts","sourceRoot":"","sources":["../src/setInstruction.js"],"names":[],"mappings":";AAEA,
|
|
1
|
+
{"version":3,"file":"setInstruction.d.ts","sourceRoot":"","sources":["../src/setInstruction.js"],"names":[],"mappings":";AAEA,qDAQiC,YAAE,EAAE,GAAG,MAHtB,GAAC,EAGyB,cAO1C"}
|