@umbraci/jsmind
Version:
jsMind is a pure javascript library for mindmap, it base on html5 canvas. jsMind was released under BSD license, you can embed it in any project, if only you observe the license.
10 lines (9 loc) • 17.7 kB
JavaScript
/**
* @license BSD-3-Clause
* @copyright 2014-2025 hizzgdev@163.com
*
* Project Home:
* https://github.com/hizzgdev/jsmind/
*/
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).jsMindHistory={})}(this,(function(t){"use strict";"function"!=typeof String.prototype.startsWith&&(String.prototype.startsWith=function(t){return this.slice(0,t.length)===t});const e=1,r=3,i=6,n=1,o=2,s=3,a=4;var u=function(){};let h="undefined"==typeof console?{level:u,log:u,debug:u,info:u,warn:u,error:u}:{level:function(t){h.debug=t>n?u:console.debug;h.info=t>o?u:console.info;h.warn=t>s?u:console.warn;h.error=t>a?u:console.error},log:console.log,debug:console.debug,info:console.info,warn:console.warn,error:console.error};class c{static instanceName="";static preload=!1;constructor({jm:t,pluginOpt:e}){this.jm=t,this.options=e||{}}beforePluginRemove(){}beforePluginDestroy(){this.beforePluginRemove()}}var d=Object.getOwnPropertyNames,l=Object.getOwnPropertySymbols,f=Object.prototype.hasOwnProperty;function p(t,e){return function(r,i,n){return t(r,i,n)&&e(r,i,n)}}function y(t){return function(e,r,i){if(!e||!r||"object"!=typeof e||"object"!=typeof r)return t(e,r,i);var n=i.cache,o=n.get(e),s=n.get(r);if(o&&s)return o===r&&s===e;n.set(e,r),n.set(r,e);var a=t(e,r,i);return n.delete(e),n.delete(r),a}}function g(t){return d(t).concat(l(t))}var m=Object.hasOwn||function(t,e){return f.call(t,e)};function _(t,e){return t===e||!t&&!e&&t!=t&&e!=e}var b=Object.getOwnPropertyDescriptor,v=Object.keys;function x(t,e,r){var i=t.length;if(e.length!==i)return!1;for(;i-- >0;)if(!r.equals(t[i],e[i],i,i,t,e,r))return!1;return!0}function j(t,e){return _(t.getTime(),e.getTime())}function S(t,e){return t.name===e.name&&t.message===e.message&&t.cause===e.cause&&t.stack===e.stack}function w(t,e){return t===e}function k(t,e,r){var i=t.size;if(i!==e.size)return!1;if(!i)return!0;for(var n,o,s=new Array(i),a=t.entries(),u=0;(n=a.next())&&!n.done;){for(var h=e.entries(),c=!1,d=0;(o=h.next())&&!o.done;)if(s[d])d++;else{var l=n.value,f=o.value;if(r.equals(l[0],f[0],u,d,t,e,r)&&r.equals(l[1],f[1],l[0],f[0],t,e,r)){c=s[d]=!0;break}d++}if(!c)return!1;u++}return!0}var M=_;function O(t,e,r){var i=v(t),n=i.length;if(v(e).length!==n)return!1;for(;n-- >0;)if(!T(t,e,r,i[n]))return!1;return!0}function q(t,e,r){var i,n,o,s=g(t),a=s.length;if(g(e).length!==a)return!1;for(;a-- >0;){if(!T(t,e,r,i=s[a]))return!1;if(n=b(t,i),o=b(e,i),(n||o)&&(!n||!o||n.configurable!==o.configurable||n.enumerable!==o.enumerable||n.writable!==o.writable))return!1}return!0}function A(t,e){return _(t.valueOf(),e.valueOf())}function E(t,e){return t.source===e.source&&t.flags===e.flags}function P(t,e,r){var i=t.size;if(i!==e.size)return!1;if(!i)return!0;for(var n,o,s=new Array(i),a=t.values();(n=a.next())&&!n.done;){for(var u=e.values(),h=!1,c=0;(o=u.next())&&!o.done;){if(!s[c]&&r.equals(n.value,o.value,n.value,o.value,t,e,r)){h=s[c]=!0;break}c++}if(!h)return!1}return!0}function C(t,e){var r=t.length;if(e.length!==r)return!1;for(;r-- >0;)if(t[r]!==e[r])return!1;return!0}function N(t,e){return t.hostname===e.hostname&&t.pathname===e.pathname&&t.protocol===e.protocol&&t.port===e.port&&t.hash===e.hash&&t.username===e.username&&t.password===e.password}function T(t,e,r,i){return!("_owner"!==i&&"__o"!==i&&"__v"!==i||!t.$$typeof&&!e.$$typeof)||m(e,i)&&r.equals(t[i],e[i],i,i,t,e,r)}var D=Array.isArray,I="undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView?ArrayBuffer.isView:null,F=Object.assign,z=Object.prototype.toString.call.bind(Object.prototype.toString);function K(t){var e=t.areArraysEqual,r=t.areDatesEqual,i=t.areErrorsEqual,n=t.areFunctionsEqual,o=t.areMapsEqual,s=t.areNumbersEqual,a=t.areObjectsEqual,u=t.arePrimitiveWrappersEqual,h=t.areRegExpsEqual,c=t.areSetsEqual,d=t.areTypedArraysEqual,l=t.areUrlsEqual,f=t.unknownTagComparators;return function(t,p,y){if(t===p)return!0;if(null==t||null==p)return!1;var g=typeof t;if(g!==typeof p)return!1;if("object"!==g)return"number"===g?s(t,p,y):"function"===g&&n(t,p,y);var m=t.constructor;if(m!==p.constructor)return!1;if(m===Object)return a(t,p,y);if(D(t))return e(t,p,y);if(null!=I&&I(t))return d(t,p,y);if(m===Date)return r(t,p,y);if(m===RegExp)return h(t,p,y);if(m===Map)return o(t,p,y);if(m===Set)return c(t,p,y);var _,b=z(t);if("[object Date]"===b)return r(t,p,y);if("[object RegExp]"===b)return h(t,p,y);if("[object Map]"===b)return o(t,p,y);if("[object Set]"===b)return c(t,p,y);if("[object Object]"===b)return"function"!=typeof t.then&&"function"!=typeof p.then&&a(t,p,y);if("[object URL]"===b)return l(t,p,y);if("[object Error]"===b)return i(t,p,y);if("[object Arguments]"===b)return a(t,p,y);if("[object Boolean]"===b||"[object Number]"===b||"[object String]"===b)return u(t,p,y);if(f){var v=f[b];if(!v){var x=null!=(_=t)?_[Symbol.toStringTag]:void 0;x&&(v=f[x])}if(v)return v(t,p,y)}return!1}}var R=B();function B(t){void 0===t&&(t={});var e,r=t.circular,i=void 0!==r&&r,n=t.createInternalComparator,o=t.createState,s=t.strict,a=void 0!==s&&s,u=function(t){var e=t.circular,r=t.createCustomConfig,i=t.strict,n={areArraysEqual:i?q:x,areDatesEqual:j,areErrorsEqual:S,areFunctionsEqual:w,areMapsEqual:i?p(k,q):k,areNumbersEqual:M,areObjectsEqual:i?q:O,arePrimitiveWrappersEqual:A,areRegExpsEqual:E,areSetsEqual:i?p(P,q):P,areTypedArraysEqual:i?q:C,areUrlsEqual:N,unknownTagComparators:void 0};if(r&&(n=F({},n,r(n))),e){var o=y(n.areArraysEqual),s=y(n.areMapsEqual),a=y(n.areObjectsEqual),u=y(n.areSetsEqual);n=F({},n,{areArraysEqual:o,areMapsEqual:s,areObjectsEqual:a,areSetsEqual:u})}return n}(t),h=K(u);return function(t){var e=t.circular,r=t.comparator,i=t.createState,n=t.equals,o=t.strict;if(i)return function(t,s){var a=i(),u=a.cache,h=void 0===u?e?new WeakMap:void 0:u,c=a.meta;return r(t,s,{cache:h,equals:n,meta:c,strict:o})};if(e)return function(t,e){return r(t,e,{cache:new WeakMap,equals:n,meta:void 0,strict:o})};var s={cache:void 0,equals:n,meta:void 0,strict:o};return function(t,e){return r(t,e,s)}}({circular:i,comparator:h,createState:o,equals:n?n(h):(e=h,function(t,r,i,n,o,s,a){return e(t,r,a)}),strict:a})}function H(t,e){const r=function(t){return(e=t)&&"object"==typeof e&&"data"in e?t.data:t;var e}(t),i=e&&Array.isArray(e.fields)?e.fields:["topic","data","id"],n=e&&e.idKey?e.idKey:"id",o=e&&e.childrenKey?e.childrenKey:"children",s=!e||!1!==e.includeStructure,a=new Map;return r&&r[n]&&function t(e,r,u){const h=function(t){const e={};n in t&&(e[n]=t[n]);const r=new Set([n,o,"direction","expanded","parentid","index","isroot"]);i.includes("data");for(const o of i)if("data"===o){const n={};let o=!1;for(const e in t)r.has(e)||i.includes(e)||(n[e]=t[e],o=!0);o&&(e.data=n)}else o in t&&o!==n&&(e[o]=t[o]);return e}(e),c=e[n];s&&(h.parentid=r||null,h.index="number"==typeof u?u:0),a.set(c,h);const d=e[o];d&&Array.isArray(d)&&d.forEach(((e,r)=>t(e,c,r)))}(r,null,0),a}function U(t,e){if(t===e)return!0;if(!t||!e)return!1;const r=Object.keys(t),i=Object.keys(e);if(r.length!==i.length)return!1;for(const i of r){const r=t[i],n=e[i];if(r===n)continue;if(r&&n&&"object"==typeof r&&"object"==typeof n){if(!R(r,n))return!1}else if(r!==n)return!1}return!0}function W(t,e){const r=[];if(!t||!e)return r;const i=new Set([...Object.keys(t),...Object.keys(e)]);i.delete("id");for(const n of i){const i=t[n],o=e[n];if(i===o)continue;(i&&o&&"object"==typeof i&&"object"==typeof o?!R(i,o):i!==o)&&r.push({key:n,before:i,after:o})}return r}function $(t){let e=!1,r=!1;for(const i of t)"parentid"===i.key&&(e=!0),"index"===i.key&&(r=!0);return{moved:e||r,parentChanged:e,orderChanged:r}}function J(t,e,r,i,n,o){if(n<=o)return!1;const s=[],a=[];for(const[e,r]of t)r.parentid===i&&s.push({id:e,index:r.index});for(const[t,r]of e)r.parentid===i&&a.push({id:t,index:r.index});s.sort(((t,e)=>t.index-e.index)),a.sort(((t,e)=>t.index-e.index));let u=0;for(const t of s)if(t.index<n){a.some((e=>e.id===t.id))||u++}return n-o===u}function Y(t,e,r={}){const{fields:i,idKey:n,childrenKey:o,includeStructure:s=!0,maxSize:a=5e3,categorize:u=!1,ignoreDeletionShift:h=!1}=r,c=H(t,{fields:i,idKey:n,childrenKey:o,includeStructure:s}),d=H(e,{fields:i,idKey:n,childrenKey:o,includeStructure:s}),l=[],f=[],p=[];for(const[t,e]of d){if(!c.has(t)){l.push(e);continue}const r=c.get(t);if(!U(r,e)){const i=W(r,e);if(h&&!i.some((t=>"parentid"===t.key))){if(i.some((t=>"index"===t.key))){const t=i.find((t=>"index"===t.key));if(J(c,d,0,r.parentid,t.before,t.after)){const t=i.filter((t=>"index"!==t.key));if(0===t.length)continue;i.length=0,i.push(...t)}}}f.push({id:t,before:r,after:e,changes:i})}}for(const[t,e]of c)d.has(t)||p.push(e);let y=!1;const g=l.length+f.length+p.length;if(g>a){y=!0;const t=Math.max(0,a),e=Math.min(l.length,Math.floor(t*(l.length/g))),r=Math.min(f.length,Math.floor(t*(f.length/g))),i=Math.min(p.length,Math.max(0,t-e-r));l.length=e,f.length=r,p.length=i}if(u&&s){const t=function(t){const e=[],r=[],i=[];for(const n of t){const{id:t,before:o,after:s,changes:a}=n,u=$(a);if(u.moved){const r={parentChanged:u.parentChanged,orderChanged:u.orderChanged,fromParent:o.parentid,toParent:s.parentid,fromOrder:o.index,toOrder:s.index},n=a.filter((t=>"parentid"!==t.key&&"index"!==t.key));n.length>0?i.push({id:t,before:o,after:s,changes:n,moveInfo:r}):e.push({id:t,before:o,after:s,moveInfo:r})}else r.push({id:t,before:o,after:s,changes:a})}return{moved:e,modified:r,movedAndModified:i}}(f);return{created:l,updated:f,deleted:p,truncated:y,moved:t.moved,modified:t.modified,movedAndModified:t.movedAndModified}}return{created:l,updated:f,deleted:p,truncated:y}}B({strict:!0}),B({circular:!0}),B({circular:!0,strict:!0}),B({createInternalComparator:function(){return _}}),B({strict:!0,createInternalComparator:function(){return _}}),B({circular:!0,createInternalComparator:function(){return _}}),B({circular:!0,createInternalComparator:function(){return _},strict:!0});const V={enabled:!0,throttleMs:100,maxHistory:500,storageMode:"object",autoSwitchThreshold:0,keymap:{enabled:!1,redoUsesY:!1},detail:{enabled:!1},diff:{flat:!0,fields:void 0,maxSize:5e3}};class L extends c{static instanceName="historyPlugin";static preload=!0;constructor({jm:t,pluginOpt:e}){super({jm:t,pluginOpt:e}),this.options=function(t){const e=Object.assign({},V,t||{});return e.keymap||(e.keymap={enabled:!1,redoUsesY:!1}),e.detail||(e.detail={enabled:!1}),e.diff||(e.diff={flat:!0,fields:void 0,maxSize:5e3}),e}(e),this._mounted=!1,this._core=null,this._mountAPI(),this._initCore()}beforePluginDestroy(){h.debug("[history] beforePluginDestroy: clearing history stack"),this._core&&this._core.clear()}_initCore(){const t=this.jm,i=this.options;i.keymap&&i.keymap.enabled&&t.options&&t.options.shortcut&&this._injectShortcuts(t.options.shortcut,!!i.keymap.redoUsesY);const n=new G(t,i);this._core=n,t.history&&(t.history.add=(t,e)=>n.add(t,e),t.history.pause=()=>n.pause(),t.history.resume=t=>n.resume(!!t),t.history.clear=()=>n.clear(),t.history.canBack=()=>n.canBack(),t.history.canForward=()=>n.canForward(),t.history.back=t=>n.back("number"==typeof t?t:1),t.history.forward=t=>n.forward("number"==typeof t?t:1),t.history.length=()=>n.length(),t.history.index=()=>n.index(),t.history.setMax=t=>n.setMax(t),t.history.setThrottle=t=>n.setThrottle(t),t.history.exportSnapshot=()=>n.exportSnapshot(),t.history.importSnapshot=(t,e)=>n.importSnapshot(t,e),t.history.getStack=()=>n.getStackMeta(),t.history.diff=(t,e,r)=>{const i=this.jm.options.fieldNames,n=i?.id||"id";return Y(t,e,{fields:[i?.topic||"topic","data",n],idKey:n,childrenKey:i?.children||"children",...r})},this._listener=(t,i)=>{try{if(t===e&&i&&"data"in i){let t=null;const e=i.data&&i.data[0];if(e)if(e.data)if(Array.isArray(e.data)){const r=e.data.find((t=>t.isroot));t=r&&r.id}else t=e.data.id;else e.id&&(t=e.id);return void(t&&t!==n._lastRootId&&(h.debug("[history] root id changed, clearing stack and pausing"),n.clear(),n._lastRootId=t,setTimeout((()=>{try{h.debug("[history] adding bootstrap snapshot after show"),n._addNow&&n._addNow("bootstrap"),h.debug("[history] resuming history recording")}catch(t){h.warn("[history] failed to add bootstrap snapshot",t)}}),100)))}t===r&&i&&i.evt&&n.add(i.evt,i)}catch(t){h.warn("[history] listener error",t)}},t.add_event_listener(this._listener))}_injectShortcuts(t,e){const r=[4186,8282],i=e?[4185,8281]:[5210,9306];t.handles.history_back=(t,e)=>{t.history&&t.history.back()&&(e.preventDefault(),e.stopPropagation&&e.stopPropagation())},t.handles.history_forward=(t,e)=>{t.history&&t.history.forward()&&(e.preventDefault(),e.stopPropagation&&e.stopPropagation())},t.mapping.history_back=r,t.mapping.history_forward=i}_mountAPI(){if(this._mounted)return;const t=this.jm,e={add:()=>{},pause:()=>{},resume:t=>{},clear:()=>{},canBack:()=>!1,canForward:()=>!1,back:t=>!1,forward:t=>!1,length:()=>0,index:()=>-1,setMax:t=>{},setThrottle:t=>{},exportSnapshot:()=>null,importSnapshot:(t,e)=>{},getStack:()=>({items:[],index:-1}),diff:(t,e,r)=>{const i=this.jm.options.fieldNames,n=i?.id||"id";return Y(t,e,{fields:[i?.topic||"topic","data",n],idKey:n,childrenKey:i?.children||"children",...r})},getOptions:()=>Object.assign({},this.options)};Object.defineProperty(t,"history",{value:e,configurable:!0,enumerable:!1,writable:!1}),this._mounted=!0,h.info("[history] API mounted (preload).")}beforePluginRemove(){try{if(this._listener&&this.jm&&Array.isArray(this.jm.event_handles)){const t=this.jm.event_handles.indexOf(this._listener);t>=0&&this.jm.event_handles.splice(t,1)}this.jm&&Object.prototype.hasOwnProperty.call(this.jm,"history")&&delete this.jm.history,this._mounted=!1}catch(t){h.error("[history] remove failed:",t)}}beforePluginDestroy(){h.error("beforePluginDestroy"),this.beforePluginRemove()}}class G{constructor(t,e){this.jm=t,this.options=e,this.enabled=!!e.enabled,this.maxHistory=Math.max(1,0|e.maxHistory),this.throttleMs=Math.max(0,0|e.throttleMs),this.storageMode=e.storageMode||"object",this.autoSwitchThreshold=Math.max(0,0|e.autoSwitchThreshold),this._history=[],this._idx=-1,this._paused=!1,this._lastAddAt=0,this._timer=0,this._pending=!1,this._pendingMeta=void 0,this._lastSig=null,this._lastRootId=null}add(t="manual",e){if(!this.enabled||this._paused)return;const r=Date.now()-this._lastAddAt;if(r>=this.throttleMs)return this._addNow(t,e),void(this._lastAddAt=Date.now());if(this._pending=!0,this._pendingMeta=e,this._timer)return;const i=Math.max(0,this.throttleMs-r);this._timer=setTimeout((()=>{this._timer=0,!this._paused&&this.enabled&&(this._addNow(t,this._pendingMeta),this._lastAddAt=Date.now()),this._pending=!1,this._pendingMeta=void 0}),i)}pause(){this._paused=!0}resume(t=!1){this._paused=!1,t&&this._pending&&(clearTimeout(this._timer),this._timer=0,this._addNow("resume-flush",this._pendingMeta),this._lastAddAt=Date.now(),this._pending=!1,this._pendingMeta=void 0)}clear(){this._history=[],this._idx=-1,this._lastSig=null,this._notifyChange()}canBack(){return this._idx>0}canForward(){return this._idx>=0&&this._idx<this._history.length-1}back(t=1){if((!Number.isFinite(t)||t<=0)&&(t=1),this._idx-t<0)return!1;this._idx-=t;const e=this._applyIndex();return e&&this._notifyChange(),e}forward(t=1){if((!Number.isFinite(t)||t<=0)&&(t=1),this._idx+t>=this._history.length)return!1;this._idx+=t;const e=this._applyIndex();return e&&this._notifyChange(),e}length(){return this._history.length}index(){return this._idx}setMax(t){this.maxHistory=Math.max(1,0|t)}setThrottle(t){this.throttleMs=Math.max(0,0|t)}exportSnapshot(){return this._takeSnapshot()}importSnapshot(t,e){return this._applySnapshot(t,e)}getStackMeta(){return{items:this._history.slice(),index:this._idx}}_notifyChange(){try{this.jm.invoke_event_handle(i,{index:this._idx,length:this._history.length,canBack:this.canBack(),canForward:this.canForward()})}catch(t){h.warn("[history] failed to notify change",t)}}_addNow(t,e){const r=this._takeSnapshot();let i=this.storageMode;if(this.autoSwitchThreshold>0&&"object"===i){const t=this._countNodes(r);t>this.autoSwitchThreshold&&(i="string",h.debug(`[history] auto-switched to string mode (${t} nodes > ${this.autoSwitchThreshold})`))}let n=null;try{n=JSON.stringify(r)}catch{}if(!n||!this._lastSig||n!==this._lastSig){if(this._idx<this._history.length-1&&(this._history=this._history.slice(0,this._idx+1)),this._history.length>=this.maxHistory&&(this._history.shift(),this._idx=Math.max(-1,this._idx-1)),"string"===i)this._history.push(n);else{const t=this._deepFreeze(r);this._history.push(t)}this._idx=this._history.length-1,this._lastSig=n,this._notifyChange()}}_applyIndex(){const t=this._history[this._idx];if(!t)return!1;try{let e;if("string"==typeof t)e=JSON.parse(t),this._lastSig=t;else{e=this._cloneSnapshot(t);try{this._lastSig=JSON.stringify(t)}catch{this._lastSig=null}}return this._applySnapshot(e,{skipCentering:!0}),!0}catch(t){return h.error("[history] apply snapshot failed",t),!1}}_takeSnapshot(){return this.jm.get_data("node_tree")}_applySnapshot(t,e){const r=!(!e||!e.skipCentering);return this.jm.show(t,r),!0}_countNodes(t){let e=0;return function t(r){if(r&&(e++,r.children&&Array.isArray(r.children)))for(const e of r.children)t(e)}(t&&t.data?t.data:t),e}_deepFreeze(t){if(!t||"object"!=typeof t)return t;if(Object.isFrozen(t))return t;if(Object.freeze(t),Array.isArray(t))for(const e of t)this._deepFreeze(e);else for(const e of Object.keys(t))this._deepFreeze(t[e]);return t}_cloneSnapshot(t){if("function"==typeof structuredClone)try{return structuredClone(t)}catch{}try{return JSON.parse(JSON.stringify(t))}catch{return t}}}t.HistoryPlugin=L,t.default=L,Object.defineProperty(t,"__esModule",{value:!0})}));
//# sourceMappingURL=jsmind.history.js.map