use-travel
Version:
A React hook for state time travel with undo, redo, reset and archive functionalities.
3 lines (2 loc) • 3.68 kB
JavaScript
;var e=require("react"),t=require("mutative");function s(s,c){e.useRef({patches:[],inversePatches:[]});const a=e.useRef(0),n=e.useRef(0);let h=a.current;e.useEffect((()=>{a.current=h,n.current=h})),h+=1,n.current+=1;const[r,i]=e.useState((()=>"function"==typeof s?s():s)),l=e.useCallback((e=>{i((s=>t.create(s,"function"==typeof e?e:()=>e,c)))}),[]);return e.useEffect((()=>{})),[r,l]}"function"==typeof SuppressedError&&SuppressedError;exports.useTravel=(c,a={})=>{const{maxHistory:n=10,initialPatches:h,initialPosition:r=0,autoArchive:i=!0}=a,l=function(e,t){var s={};for(var c in e)Object.prototype.hasOwnProperty.call(e,c)&&t.indexOf(c)<0&&(s[c]=e[c]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var a=0;for(c=Object.getOwnPropertySymbols(e);a<c.length;a++)t.indexOf(c[a])<0&&Object.prototype.propertyIsEnumerable.call(e,c[a])&&(s[c[a]]=e[c[a]])}return s}(a,["maxHistory","initialPatches","initialPosition","autoArchive"]),[p,o]=e.useState(r),[u,v]=s((()=>({patches:[],inversePatches:[]}))),[P,g]=s((()=>null!=h?h:{patches:[],inversePatches:[]})),[f,y]=e.useState(c),b=e.useCallback((e=>{const[s,c,a]="function"==typeof e?t.create(f,e,Object.assign(Object.assign({},l),{enablePatches:!0})):t.create(f,(()=>e),Object.assign(Object.assign({},l),{enablePatches:!0}));if(y(s),i)o(n<P.patches.length+1?n:p+1),g((e=>{p<e.patches.length&&(e.patches.splice(p,e.patches.length-p),e.inversePatches.splice(p,e.inversePatches.length-p)),e.patches.push(c),e.inversePatches.push(a),n<e.patches.length&&(e.patches=e.patches.slice(-n),e.inversePatches=e.inversePatches.slice(-n))}));else{const e=p<P.patches.length+Number(!!u.patches.length);e&&(P.patches.splice(p,P.patches.length-p),P.inversePatches.splice(p,P.inversePatches.length-p)),u.patches.length&&!e||o(n<P.patches.length+1?n:p+1),v((t=>{e&&(t.patches.length=0,t.inversePatches.length=0),t.patches.push(c),t.inversePatches.push(a)}))}}),[P,f,p,v]),O=()=>{i?console.warn("Auto archive is enabled, no need to archive manually"):u.patches.length&&(g((e=>{const[,s,c]=t.create(f,(e=>t.apply(e,u.inversePatches.flat().reverse())),{enablePatches:!0});e.patches.push(c),e.inversePatches.push(s),n<e.patches.length&&(e.patches=e.patches.slice(-n),e.inversePatches=e.inversePatches.slice(-n))})),v((e=>{e.patches.length=0,e.inversePatches.length=0})))},m=e.useMemo((()=>!i&&!!u.patches.length),[u]),d=e.useMemo((()=>{let e=P;return m&&(e={patches:P.patches.concat(),inversePatches:P.inversePatches.concat()},e.patches.push(u.patches.flat()),e.inversePatches.push(u.inversePatches.flat().reverse())),e}),[P,u,m]),w=e.useMemo((()=>{const e=e=>{const s=e<p;m&&O(),e>d.patches.length&&(console.warn(`Can't go forward to position ${e}`),e=d.patches.length),e<0&&(console.warn(`Can't go back to position ${e}`),e=0),e!==p&&(m&&d.inversePatches.slice(-1)[0].reverse(),y((()=>t.apply(f,s?d.inversePatches.slice(-n).slice(e).flat().reverse():d.patches.slice(-n).slice(p,e).flat()))),o(e))};let s;return{position:p,getHistory:()=>{if(s)return s;s=[f];let e=f;const c=!i&&d.patches.length>n?d.patches.slice(d.patches.length-n):d.patches,a=!i&&d.inversePatches.length>n?d.inversePatches.slice(d.inversePatches.length-n):d.inversePatches;for(let a=p;a<c.length;a++)e=t.apply(e,c[a]),s.push(e);e=f;for(let c=p-1;c>-1;c--)e=t.apply(e,a[c]),s.unshift(e);return s},patches:m?d:P,back:(t=1)=>{e(p-t)},forward:(t=1)=>{e(p+t)},reset:()=>{o(r),g((()=>null!=h?h:{patches:[],inversePatches:[]})),y((()=>c)),v((()=>({patches:[],inversePatches:[]})))},go:e,canBack:()=>p>0,canForward:()=>m?p<d.patches.length-1:p<P.patches.length,canArchive:()=>m,archive:O}}),[p,P,o,g,y,c,f,u,d,m]);return[f,b,w]};
//# sourceMappingURL=index.cjs.js.map