use-travel
Version:
A React hook for state time travel with undo, redo, reset and archive functionalities.
3 lines (2 loc) • 3.94 kB
JavaScript
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("mutative")):"function"==typeof define&&define.amd?define(["exports","react","mutative"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).UseTravel={},e.React,e.Mutative)}(this,(function(e,t,s){"use strict";function c(e,c){t.useRef({patches:[],inversePatches:[]});const a=t.useRef(0),n=t.useRef(0);let h=a.current;t.useEffect((()=>{a.current=h,n.current=h})),h+=1,n.current+=1;const[r,i]=t.useState((()=>"function"==typeof e?e():e)),l=t.useCallback((e=>{i((t=>s.create(t,"function"==typeof e?e:()=>e,c)))}),[]);return t.useEffect((()=>{})),[r,l]}"function"==typeof SuppressedError&&SuppressedError;e.useTravel=(e,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]=t.useState(r),[u,f]=c((()=>({patches:[],inversePatches:[]}))),[v,g]=c((()=>null!=h?h:{patches:[],inversePatches:[]})),[P,y]=t.useState(e),b=t.useCallback((e=>{const[t,c,a]="function"==typeof e?s.create(P,e,Object.assign(Object.assign({},l),{enablePatches:!0})):s.create(P,(()=>e),Object.assign(Object.assign({},l),{enablePatches:!0}));if(y(t),i)o(n<v.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<v.patches.length+Number(!!u.patches.length);e&&(v.patches.splice(p,v.patches.length-p),v.inversePatches.splice(p,v.inversePatches.length-p)),u.patches.length&&!e||o(n<v.patches.length+1?n:p+1),f((t=>{e&&(t.patches.length=0,t.inversePatches.length=0),t.patches.push(c),t.inversePatches.push(a)}))}}),[v,P,p,f]),d=()=>{i?console.warn("Auto archive is enabled, no need to archive manually"):u.patches.length&&(g((e=>{const[,t,c]=s.create(P,(e=>s.apply(e,u.inversePatches.flat().reverse())),{enablePatches:!0});e.patches.push(c),e.inversePatches.push(t),n<e.patches.length&&(e.patches=e.patches.slice(-n),e.inversePatches=e.inversePatches.slice(-n))})),f((e=>{e.patches.length=0,e.inversePatches.length=0})))},m=t.useMemo((()=>!i&&!!u.patches.length),[u]),O=t.useMemo((()=>{let e=v;return m&&(e={patches:v.patches.concat(),inversePatches:v.inversePatches.concat()},e.patches.push(u.patches.flat()),e.inversePatches.push(u.inversePatches.flat().reverse())),e}),[v,u,m]),j=t.useMemo((()=>{const t=e=>{const t=e<p;m&&d(),e>O.patches.length&&(console.warn(`Can't go forward to position ${e}`),e=O.patches.length),e<0&&(console.warn(`Can't go back to position ${e}`),e=0),e!==p&&(m&&O.inversePatches.slice(-1)[0].reverse(),y((()=>s.apply(P,t?O.inversePatches.slice(-n).slice(e).flat().reverse():O.patches.slice(-n).slice(p,e).flat()))),o(e))};let c;return{position:p,getHistory:()=>{if(c)return c;c=[P];let e=P;const t=!i&&O.patches.length>n?O.patches.slice(O.patches.length-n):O.patches,a=!i&&O.inversePatches.length>n?O.inversePatches.slice(O.inversePatches.length-n):O.inversePatches;for(let a=p;a<t.length;a++)e=s.apply(e,t[a]),c.push(e);e=P;for(let t=p-1;t>-1;t--)e=s.apply(e,a[t]),c.unshift(e);return c},patches:m?O:v,back:(e=1)=>{t(p-e)},forward:(e=1)=>{t(p+e)},reset:()=>{o(r),g((()=>null!=h?h:{patches:[],inversePatches:[]})),y((()=>e)),f((()=>({patches:[],inversePatches:[]})))},go:t,canBack:()=>p>0,canForward:()=>m?p<O.patches.length-1:p<v.patches.length,canArchive:()=>m,archive:d}}),[p,v,o,g,y,e,P,u,O,m]);return[P,b,j]}}));
//# sourceMappingURL=index.umd.js.map