@umbraci/jsmind 0.10.14 → 0.10.15

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.
Files changed (69) hide show
  1. package/LICENSE +24 -24
  2. package/README.md +116 -116
  3. package/dist/jsmind.copy-paste.js +9 -0
  4. package/dist/jsmind.copy-paste.js.map +1 -0
  5. package/dist/jsmind.draggable-node.js +1 -1
  6. package/dist/jsmind.draggable-node.js.map +1 -1
  7. package/dist/jsmind.history.js +1 -1
  8. package/dist/jsmind.history.js.map +1 -1
  9. package/dist/jsmind.js +1 -1
  10. package/dist/jsmind.js.map +1 -1
  11. package/dist/jsmind.multi-select.js +1 -1
  12. package/dist/jsmind.multi-select.js.map +1 -1
  13. package/dist/jsmind.multiline-text.js +1 -1
  14. package/dist/jsmind.multiline-text.js.map +1 -1
  15. package/dist/jsmind.screenshot.js +1 -1
  16. package/dist/jsmind.screenshot.js.map +1 -1
  17. package/es/jsmind.copy-paste.js +9 -0
  18. package/es/jsmind.copy-paste.js.map +1 -0
  19. package/es/jsmind.draggable-node.js +1 -1
  20. package/es/jsmind.draggable-node.js.map +1 -1
  21. package/es/jsmind.history.js +1 -1
  22. package/es/jsmind.history.js.map +1 -1
  23. package/es/jsmind.js +1 -1
  24. package/es/jsmind.js.map +1 -1
  25. package/es/jsmind.multi-select.js +1 -1
  26. package/es/jsmind.multi-select.js.map +1 -1
  27. package/es/jsmind.multiline-text.js +1 -1
  28. package/es/jsmind.multiline-text.js.map +1 -1
  29. package/es/jsmind.screenshot.js +1 -1
  30. package/es/jsmind.screenshot.js.map +1 -1
  31. package/lib/jsmind.copy-paste.js +9 -0
  32. package/lib/jsmind.copy-paste.js.map +1 -0
  33. package/lib/jsmind.draggable-node.js +1 -1
  34. package/lib/jsmind.draggable-node.js.map +1 -1
  35. package/lib/jsmind.history.js +1 -1
  36. package/lib/jsmind.history.js.map +1 -1
  37. package/lib/jsmind.js +1 -1
  38. package/lib/jsmind.js.map +1 -1
  39. package/lib/jsmind.multi-select.js +1 -1
  40. package/lib/jsmind.multi-select.js.map +1 -1
  41. package/lib/jsmind.multiline-text.js +1 -1
  42. package/lib/jsmind.multiline-text.js.map +1 -1
  43. package/lib/jsmind.screenshot.js +1 -1
  44. package/lib/jsmind.screenshot.js.map +1 -1
  45. package/package.json +115 -115
  46. package/style/jsmind.css +408 -408
  47. package/types/generated/index.d.ts +8 -0
  48. package/types/generated/jsmind.common.d.ts +68 -0
  49. package/types/generated/jsmind.d.ts +632 -0
  50. package/types/generated/jsmind.data_provider.d.ts +56 -0
  51. package/types/generated/jsmind.dom.d.ts +59 -0
  52. package/types/generated/jsmind.enhanced-plugin.d.ts +103 -0
  53. package/types/generated/jsmind.format.d.ts +113 -0
  54. package/types/generated/jsmind.graph.d.ts +180 -0
  55. package/types/generated/jsmind.layout_provider.d.ts +182 -0
  56. package/types/generated/jsmind.mind.d.ts +129 -0
  57. package/types/generated/jsmind.node.d.ts +69 -0
  58. package/types/generated/jsmind.option.d.ts +78 -0
  59. package/types/generated/jsmind.plugin.d.ts +21 -0
  60. package/types/generated/jsmind.shortcut_provider.d.ts +52 -0
  61. package/types/generated/jsmind.util.d.ts +26 -0
  62. package/types/generated/jsmind.view_provider.d.ts +374 -0
  63. package/types/generated/plugins/history/history-diff.d.ts +310 -0
  64. package/types/generated/plugins/history/jsmind.history.d.ts +87 -0
  65. package/types/generated/plugins/jsmind.draggable-node.d.ts +262 -0
  66. package/types/generated/plugins/jsmind.multiline-text-v2.d.ts +58 -0
  67. package/types/generated/plugins/jsmind.multiline-text.d.ts +43 -0
  68. package/types/generated/plugins/jsmind.screenshot.d.ts +83 -0
  69. package/types/tsconfig.declaration.json +19 -19
@@ -1 +1 @@
1
- {"version":3,"file":"jsmind.screenshot.js","sources":["../src/plugins/jsmind.screenshot.js"],"sourcesContent":["/**\r\n * @license BSD\r\n * @copyright 2014-2025 UmbraCi\r\n *\r\n * Project Home:\r\n * https://github.com/UmbraCi/jsmind/\r\n */\r\n\r\nimport jsMind from '@umbraci/jsmind';\r\nimport domtoimage from 'dom-to-image';\r\n\r\nif (!jsMind) {\r\n throw new Error('jsMind is not defined');\r\n}\r\n\r\nif (!domtoimage) {\r\n throw new Error('dom-to-image is required');\r\n}\r\n\r\nconst $ = jsMind.$;\r\n\r\n/**\r\n * Default options for screenshot plugin.\r\n * @typedef {Object} ScreenshotOptions\r\n * @property {string|null} [filename]\r\n * @property {{left?:string|Location,right?:string}} [watermark]\r\n * @property {string} [background]\r\n */\r\nconst DEFAULT_OPTIONS = {\r\n filename: null,\r\n watermark: {\r\n left: $.w.location,\r\n right: 'https://github.com/UmbraCi/jsmind',\r\n },\r\n background: 'transparent',\r\n};\r\n\r\n/**\r\n * Screenshot plugin for jsMind.\r\n */\r\nexport class JmScreenshot {\r\n /**\r\n * Create screenshot plugin instance.\r\n * @param {import('../jsmind.js').default} jm - jsMind instance\r\n * @param {Partial<ScreenshotOptions>} options - Plugin options\r\n */\r\n constructor(jm, options) {\r\n var opts = {};\r\n jsMind.util.json.merge(opts, DEFAULT_OPTIONS);\r\n jsMind.util.json.merge(opts, options);\r\n\r\n this.version = '0.2.0';\r\n /** @type {import('../jsmind.js').default} */\r\n this.jm = jm;\r\n /** @type {ScreenshotOptions} */\r\n this.options = opts;\r\n /** @type {number} */\r\n this.dpr = jm.view.device_pixel_ratio;\r\n }\r\n\r\n /** Take a screenshot of the mind map. */\r\n shoot() {\r\n let c = this.create_canvas();\r\n let ctx = c.getContext('2d');\r\n ctx.scale(this.dpr, this.dpr);\r\n Promise.resolve(ctx)\r\n .then(() => this.draw_background(ctx))\r\n .then(() => this.draw_lines(ctx))\r\n .then(() => this.draw_nodes(ctx))\r\n .then(() => this.draw_watermark(c, ctx))\r\n .then(() => this.download(c))\r\n .then(() => this.clear(c));\r\n }\r\n\r\n /**\r\n * Create canvas for screenshot.\r\n * @returns {HTMLCanvasElement} Canvas element\r\n */\r\n create_canvas() {\r\n let c = $.c('canvas');\r\n const w = this.jm.view.size.w;\r\n const h = this.jm.view.size.h;\r\n c.width = w * this.dpr;\r\n c.height = h * this.dpr;\r\n c.style.width = w + 'px';\r\n c.style.height = h + 'px';\r\n\r\n c.style.visibility = 'hidden';\r\n this.jm.view.e_panel.appendChild(c);\r\n return c;\r\n }\r\n\r\n /**\r\n * Clean up canvas element.\r\n * @param {HTMLCanvasElement} c - Canvas to remove\r\n */\r\n clear(c) {\r\n c.parentNode.removeChild(c);\r\n }\r\n\r\n /**\r\n * Draw background on canvas.\r\n * @param {CanvasRenderingContext2D} ctx - Canvas context\r\n * @returns {Promise<CanvasRenderingContext2D>} Promise resolving to context\r\n */\r\n draw_background(ctx) {\r\n return new Promise(\r\n function (resolve, _) {\r\n const bg = this.options.background;\r\n if (!!bg && bg !== 'transparent') {\r\n ctx.fillStyle = this.options.background;\r\n ctx.fillRect(0, 0, this.jm.view.size.w, this.jm.view.size.h);\r\n }\r\n resolve(ctx);\r\n }.bind(this)\r\n );\r\n }\r\n\r\n /**\r\n * Draw connection lines on canvas by copying from view graph.\r\n * @param {CanvasRenderingContext2D} ctx\r\n * @returns {Promise<CanvasRenderingContext2D>}\r\n */\r\n draw_lines(ctx) {\r\n return new Promise(\r\n function (resolve, _) {\r\n this.jm.view.graph.copy_to(ctx, function () {\r\n resolve(ctx);\r\n });\r\n }.bind(this)\r\n );\r\n }\r\n\r\n /**\r\n * Draw node DOM into canvas via SVG snapshot.\r\n * @param {CanvasRenderingContext2D} ctx\r\n * @returns {Promise<CanvasRenderingContext2D>}\r\n */\r\n draw_nodes(ctx) {\r\n return domtoimage\r\n .toSvg(this.jm.view.e_nodes, { style: { zoom: 1 } })\r\n .then(this.load_image)\r\n .then(function (img) {\r\n ctx.drawImage(img, 0, 0);\r\n return ctx;\r\n });\r\n }\r\n\r\n /**\r\n * Draw watermark text on canvas.\r\n * @param {HTMLCanvasElement} c\r\n * @param {CanvasRenderingContext2D} ctx\r\n * @returns {CanvasRenderingContext2D}\r\n */\r\n draw_watermark(c, ctx) {\r\n ctx.textBaseline = 'bottom';\r\n ctx.fillStyle = '#000';\r\n ctx.font = '11px Verdana,Arial,Helvetica,sans-serif';\r\n if (!!this.options.watermark.left) {\r\n ctx.textAlign = 'left';\r\n ctx.fillText(this.options.watermark.left, 5.5, c.height - 2.5);\r\n }\r\n if (!!this.options.watermark.right) {\r\n ctx.textAlign = 'right';\r\n ctx.fillText(this.options.watermark.right, c.width - 5.5, c.height - 2.5);\r\n }\r\n return ctx;\r\n }\r\n\r\n /**\r\n * Load image from URL and resolve img element.\r\n * @param {string} url\r\n * @returns {Promise<HTMLImageElement>}\r\n */\r\n load_image(url) {\r\n return new Promise(function (resolve, reject) {\r\n let img = new Image();\r\n img.onload = function () {\r\n resolve(img);\r\n };\r\n img.onerror = reject;\r\n img.src = url;\r\n });\r\n }\r\n\r\n /**\r\n * Trigger download of canvas content as PNG.\r\n * @param {HTMLCanvasElement} c\r\n */\r\n download(c) {\r\n var name = (this.options.filename || this.jm.mind.name) + '.png';\r\n\r\n if (navigator.msSaveBlob && !!c.msToBlob) {\r\n var blob = c.msToBlob();\r\n navigator.msSaveBlob(blob, name);\r\n } else {\r\n var blob_url = c.toDataURL();\r\n var anchor = $.c('a');\r\n if ('download' in anchor) {\r\n anchor.style.visibility = 'hidden';\r\n anchor.href = blob_url;\r\n anchor.download = name;\r\n $.d.body.appendChild(anchor);\r\n var evt = $.d.createEvent('MouseEvents');\r\n evt.initEvent('click', true, true);\r\n anchor.dispatchEvent(evt);\r\n $.d.body.removeChild(anchor);\r\n } else {\r\n location.href = blob_url;\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Screenshot plugin registration.\r\n * @type {import('../jsmind.plugin.js').Plugin<Partial<ScreenshotOptions>>}\r\n */\r\nexport const screenshot_plugin = new jsMind.plugin('screenshot', function (jm, options) {\r\n var jmss = new JmScreenshot(jm, options);\r\n jm.screenshot = jmss;\r\n jm.shoot = function () {\r\n jmss.shoot();\r\n };\r\n});\r\n\r\njsMind.register_plugin(screenshot_plugin);\r\n\r\nexport default JmScreenshot;\r\n"],"names":["jsMind","Error","domtoimage","$","DEFAULT_OPTIONS","filename","watermark","left","w","location","right","background","JmScreenshot","constructor","jm","options","opts","util","json","merge","this","version","dpr","view","device_pixel_ratio","shoot","c","create_canvas","ctx","getContext","scale","Promise","resolve","then","draw_background","draw_lines","draw_nodes","draw_watermark","download","clear","size","h","width","height","style","visibility","e_panel","appendChild","parentNode","removeChild","_","bg","fillStyle","fillRect","bind","graph","copy_to","toSvg","e_nodes","zoom","load_image","img","drawImage","textBaseline","font","textAlign","fillText","url","reject","Image","onload","onerror","src","name","mind","navigator","msSaveBlob","msToBlob","blob","blob_url","toDataURL","anchor","href","d","body","evt","createEvent","initEvent","dispatchEvent","screenshot_plugin","plugin","jmss","screenshot","register_plugin"],"mappings":"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"}
1
+ {"version":3,"file":"jsmind.screenshot.js","sources":["../src/plugins/jsmind.screenshot.js"],"sourcesContent":["/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport jsMind from '@umbraci/jsmind';\nimport domtoimage from 'dom-to-image';\n\nif (!jsMind) {\n throw new Error('jsMind is not defined');\n}\n\nif (!domtoimage) {\n throw new Error('dom-to-image is required');\n}\n\nconst $ = jsMind.$;\n\n/**\n * Default options for screenshot plugin.\n * @typedef {Object} ScreenshotOptions\n * @property {string|null} [filename]\n * @property {{left?:string|Location,right?:string}} [watermark]\n * @property {string} [background]\n */\nconst DEFAULT_OPTIONS = {\n filename: null,\n watermark: {\n left: $.w.location,\n right: 'https://github.com/UmbraCi/jsmind',\n },\n background: 'transparent',\n};\n\n/**\n * Screenshot plugin for jsMind.\n */\nexport class JmScreenshot {\n /**\n * Create screenshot plugin instance.\n * @param {import('../jsmind.js').default} jm - jsMind instance\n * @param {Partial<ScreenshotOptions>} options - Plugin options\n */\n constructor(jm, options) {\n var opts = {};\n jsMind.util.json.merge(opts, DEFAULT_OPTIONS);\n jsMind.util.json.merge(opts, options);\n\n this.version = '0.2.0';\n /** @type {import('../jsmind.js').default} */\n this.jm = jm;\n /** @type {ScreenshotOptions} */\n this.options = opts;\n /** @type {number} */\n this.dpr = jm.view.device_pixel_ratio;\n }\n\n /** Take a screenshot of the mind map. */\n shoot() {\n let c = this.create_canvas();\n let ctx = c.getContext('2d');\n ctx.scale(this.dpr, this.dpr);\n Promise.resolve(ctx)\n .then(() => this.draw_background(ctx))\n .then(() => this.draw_lines(ctx))\n .then(() => this.draw_nodes(ctx))\n .then(() => this.draw_watermark(c, ctx))\n .then(() => this.download(c))\n .then(() => this.clear(c));\n }\n\n /**\n * Create canvas for screenshot.\n * @returns {HTMLCanvasElement} Canvas element\n */\n create_canvas() {\n let c = $.c('canvas');\n const w = this.jm.view.size.w;\n const h = this.jm.view.size.h;\n c.width = w * this.dpr;\n c.height = h * this.dpr;\n c.style.width = w + 'px';\n c.style.height = h + 'px';\n\n c.style.visibility = 'hidden';\n this.jm.view.e_panel.appendChild(c);\n return c;\n }\n\n /**\n * Clean up canvas element.\n * @param {HTMLCanvasElement} c - Canvas to remove\n */\n clear(c) {\n c.parentNode.removeChild(c);\n }\n\n /**\n * Draw background on canvas.\n * @param {CanvasRenderingContext2D} ctx - Canvas context\n * @returns {Promise<CanvasRenderingContext2D>} Promise resolving to context\n */\n draw_background(ctx) {\n return new Promise(\n function (resolve, _) {\n const bg = this.options.background;\n if (!!bg && bg !== 'transparent') {\n ctx.fillStyle = this.options.background;\n ctx.fillRect(0, 0, this.jm.view.size.w, this.jm.view.size.h);\n }\n resolve(ctx);\n }.bind(this)\n );\n }\n\n /**\n * Draw connection lines on canvas by copying from view graph.\n * @param {CanvasRenderingContext2D} ctx\n * @returns {Promise<CanvasRenderingContext2D>}\n */\n draw_lines(ctx) {\n return new Promise(\n function (resolve, _) {\n this.jm.view.graph.copy_to(ctx, function () {\n resolve(ctx);\n });\n }.bind(this)\n );\n }\n\n /**\n * Draw node DOM into canvas via SVG snapshot.\n * @param {CanvasRenderingContext2D} ctx\n * @returns {Promise<CanvasRenderingContext2D>}\n */\n draw_nodes(ctx) {\n return domtoimage\n .toSvg(this.jm.view.e_nodes, { style: { zoom: 1 } })\n .then(this.load_image)\n .then(function (img) {\n ctx.drawImage(img, 0, 0);\n return ctx;\n });\n }\n\n /**\n * Draw watermark text on canvas.\n * @param {HTMLCanvasElement} c\n * @param {CanvasRenderingContext2D} ctx\n * @returns {CanvasRenderingContext2D}\n */\n draw_watermark(c, ctx) {\n ctx.textBaseline = 'bottom';\n ctx.fillStyle = '#000';\n ctx.font = '11px Verdana,Arial,Helvetica,sans-serif';\n if (!!this.options.watermark.left) {\n ctx.textAlign = 'left';\n ctx.fillText(this.options.watermark.left, 5.5, c.height - 2.5);\n }\n if (!!this.options.watermark.right) {\n ctx.textAlign = 'right';\n ctx.fillText(this.options.watermark.right, c.width - 5.5, c.height - 2.5);\n }\n return ctx;\n }\n\n /**\n * Load image from URL and resolve img element.\n * @param {string} url\n * @returns {Promise<HTMLImageElement>}\n */\n load_image(url) {\n return new Promise(function (resolve, reject) {\n let img = new Image();\n img.onload = function () {\n resolve(img);\n };\n img.onerror = reject;\n img.src = url;\n });\n }\n\n /**\n * Trigger download of canvas content as PNG.\n * @param {HTMLCanvasElement} c\n */\n download(c) {\n var name = (this.options.filename || this.jm.mind.name) + '.png';\n\n if (navigator.msSaveBlob && !!c.msToBlob) {\n var blob = c.msToBlob();\n navigator.msSaveBlob(blob, name);\n } else {\n var blob_url = c.toDataURL();\n var anchor = $.c('a');\n if ('download' in anchor) {\n anchor.style.visibility = 'hidden';\n anchor.href = blob_url;\n anchor.download = name;\n $.d.body.appendChild(anchor);\n var evt = $.d.createEvent('MouseEvents');\n evt.initEvent('click', true, true);\n anchor.dispatchEvent(evt);\n $.d.body.removeChild(anchor);\n } else {\n location.href = blob_url;\n }\n }\n }\n}\n\n/**\n * Screenshot plugin registration.\n * @type {import('../jsmind.plugin.js').Plugin<Partial<ScreenshotOptions>>}\n */\nexport const screenshot_plugin = new jsMind.plugin('screenshot', function (jm, options) {\n var jmss = new JmScreenshot(jm, options);\n jm.screenshot = jmss;\n jm.shoot = function () {\n jmss.shoot();\n };\n});\n\njsMind.register_plugin(screenshot_plugin);\n\nexport default JmScreenshot;\n"],"names":["jsMind","Error","domtoimage","$","DEFAULT_OPTIONS","filename","watermark","left","w","location","right","background","JmScreenshot","constructor","jm","options","opts","util","json","merge","this","version","dpr","view","device_pixel_ratio","shoot","c","create_canvas","ctx","getContext","scale","Promise","resolve","then","draw_background","draw_lines","draw_nodes","draw_watermark","download","clear","size","h","width","height","style","visibility","e_panel","appendChild","parentNode","removeChild","_","bg","fillStyle","fillRect","bind","graph","copy_to","toSvg","e_nodes","zoom","load_image","img","drawImage","textBaseline","font","textAlign","fillText","url","reject","Image","onload","onerror","src","name","mind","navigator","msSaveBlob","msToBlob","blob","blob_url","toDataURL","anchor","href","d","body","evt","createEvent","initEvent","dispatchEvent","screenshot_plugin","plugin","jmss","screenshot","register_plugin"],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @license BSD-3-Clause
3
+ * @copyright 2014-2025 hizzgdev@163.com
4
+ *
5
+ * Project Home:
6
+ * https://github.com/hizzgdev/jsmind/
7
+ */
8
+ "use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}Object.defineProperty(exports,"__esModule",{value:!0});var t=e(require("@umbraci/jsmind"));const i=new class{constructor(e){this.w=e,this.d=e.document,this.g=function(e){return this.d.getElementById(e)},this.c=function(e){return this.d.createElement(e)},this.t=function(e,t){e.hasChildNodes()?e.firstChild.nodeValue=t:e.appendChild(this.d.createTextNode(t))},this.h=function(e,t){t instanceof HTMLElement?(e.innerHTML="",e.appendChild(t)):e.innerHTML=t},this.i=function(e){return!!e&&"object"==typeof e&&1===e.nodeType&&"object"==typeof e.style&&"object"==typeof e.ownerDocument},this.on=function(e,t,i){e.addEventListener?e.addEventListener(t,i,!1):e.attachEvent("on"+t,i)}}}(window),n={file:{read:function(e,t){var i=new FileReader;i.onload=function(){"function"==typeof t&&t(this.result,e.name)},i.readAsText(e)},save:function(e,t,n){var o;if("function"==typeof i.w.Blob)o=new Blob([e],{type:t});else{var r=new(i.w.BlobBuilder||i.w.MozBlobBuilder||i.w.WebKitBlobBuilder||i.w.MSBlobBuilder);r.append(e),o=r.getBlob(t)}if(navigator.msSaveBlob)navigator.msSaveBlob(o,n);else{var a=(i.w.URL||i.w.webkitURL).createObjectURL(o),s=i.c("a");if("download"in s){s.style.visibility="hidden",s.href=a,s.download=n,i.d.body.appendChild(s);var d=i.d.createEvent("MouseEvents");d.initEvent("click",!0,!0),s.dispatchEvent(d),i.d.body.removeChild(s)}else location.href=a}}},json:{json2string:function(e){return JSON.stringify(e)},string2json:function(e){return JSON.parse(e)},merge:function(e,t){for(var i in t)i in e?"object"!=typeof e[i]||"[object object]"!=Object.prototype.toString.call(e[i]).toLowerCase()||e[i].length?e[i]=t[i]:n.json.merge(e[i],t[i]):e[i]=t[i];return e}},uuid:{newid:function(){return((new Date).getTime().toString(16)+Math.random().toString(16).substring(2)).substring(2,18)}},text:{is_empty:function(e){return!e||0==e.replace(/\s*/,"").length}}};class o{constructor(e,t={}){this.jsMind=e,this.options={enabled:!0,shortcuts:{copy:"meta+c",paste:"meta+v",cut:"meta+x"},...t},this.clipboardData=null,this.logger={info:e=>console.info("[CopyPaste]",e),warn:e=>console.warn("[CopyPaste]",e),error:e=>console.error("[CopyPaste]",e),debug:e=>console.debug("[CopyPaste]",e)},this.init()}init(){return this.logger.info("CopyPaste plugin initialized"),!0}handleCopy(e){if(!this.options.enabled)return;const t=this.jsMind.get_selected_node();if(t)try{e.preventDefault(),this.clipboardData={id:t.id,topic:t.topic,data:t.data||{},direction:t.direction,expanded:t.expanded,children:this.copyChildren(t)},this.logger.info("Node copied:",t.topic),this.showMessage("节点已复制")}catch(e){this.logger.error("Copy failed:",e),this.showMessage("复制失败","error")}else this.logger.warn("No node selected for copying")}handlePaste(e){if(!this.options.enabled)return;if(!this.clipboardData)return this.logger.warn("No data in clipboard"),void this.showMessage("剪贴板为空,请先复制节点","warning");const t=this.jsMind.get_selected_node();if(!t)return this.logger.warn("No target node selected for pasting"),void this.showMessage("请选择目标节点","warning");try{e.preventDefault();const i=this.prepareBatchData(this.clipboardData),n=this.jsMind.add_nodes(t,[i]);n&&n.length>0&&(this.logger.info("Nodes pasted successfully:",this.clipboardData.topic),this.showMessage("粘贴成功"))}catch(e){this.logger.error("Paste failed:",e),this.showMessage("粘贴失败","error")}}handleCut(e){if(!this.options.enabled)return;const t=this.jsMind.get_selected_node();if(t){if(t.isroot)return this.logger.warn("Cannot cut root node"),void this.showMessage("不能剪切根节点","warning");try{e.preventDefault(),this.clipboardData={id:t.id,topic:t.topic,data:t.data||{},direction:t.direction,expanded:t.expanded,children:this.copyChildren(t)};this.jsMind.remove_node(t)&&(this.logger.info("Node cut:",t.topic),this.showMessage("节点已剪切"))}catch(e){this.logger.error("Cut failed:",e),this.showMessage("剪切失败","error")}}else this.logger.warn("No node selected for cutting")}copyChildren(e){return e.children&&0!==e.children.length?e.children.map(e=>({id:e.id,topic:e.topic,data:e.data||{},direction:e.direction,expanded:e.expanded,children:this.copyChildren(e)})):[]}prepareBatchData(e){return{id:n.uuid.newid(),topic:e.topic,data:e.data||{},children:e.children&&e.children.length>0?e.children.map(e=>this.prepareBatchData(e)):void 0}}pasteChildren(e,t){if(!t||0===t.length)return[];const i=t.map(e=>this.prepareBatchData(e));return this.jsMind.add_nodes(e,i)}showMessage(e,t="info"){console.log(`[CopyPaste ${t.toUpperCase()}]: ${e}`)}clear(){this.clipboardData=null,this.logger.info("Clipboard cleared")}getStatus(){return{hasData:!!this.clipboardData,data:this.clipboardData}}}const r=new t.default.plugin("copy-paste",function(e,t){var i=t||{};i.shortcuts=i.shortcuts||{copy:"meta+c",paste:"meta+v",cut:"meta+x"};var n=new o(e,i);e.view&&e.view.e_panel&&e.view.e_panel.addEventListener("keydown",function(e){!e.metaKey&&!e.ctrlKey||"c"!==e.key||e.shiftKey||e.altKey?!e.metaKey&&!e.ctrlKey||"v"!==e.key||e.shiftKey||e.altKey?!e.metaKey&&!e.ctrlKey||"x"!==e.key||e.shiftKey||e.altKey||n.handleCut(e):n.handlePaste(e):n.handleCopy(e)}),e.copy_paste_handler=n});t.default.register_plugin(r),exports.copy_paste_plugin=r,exports.default=o;
9
+ //# sourceMappingURL=jsmind.copy-paste.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsmind.copy-paste.js","sources":["../src/jsmind.dom.js","../src/jsmind.util.js","../src/plugins/copy-paste/copy-paste-plugin-simple.js"],"sourcesContent":["/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\n/**\n * Lightweight DOM helpers bound to a window.\n */\nclass Dom {\n /**\n * @param {Window} w\n */\n constructor(w) {\n /** @type {Window} */\n this.w = w;\n /** @type {Document} */\n this.d = w.document;\n /**\n * Get element by id.\n * @param {string} id\n * @returns {HTMLElement|null}\n */\n this.g = function (id) {\n return this.d.getElementById(id);\n };\n /**\n * Create element with given tag.\n * @param {string} tag\n * @returns {HTMLElement}\n */\n this.c = function (tag) {\n return this.d.createElement(tag);\n };\n /**\n * Set text content for element.\n * @param {HTMLElement} n\n * @param {string} t\n */\n this.t = function (n, t) {\n if (n.hasChildNodes()) {\n n.firstChild.nodeValue = t;\n } else {\n n.appendChild(this.d.createTextNode(t));\n }\n };\n\n /**\n * Set inner HTML or append element.\n * @param {HTMLElement} n\n * @param {string|HTMLElement} t\n */\n this.h = function (n, t) {\n if (t instanceof HTMLElement) {\n n.innerHTML = '';\n n.appendChild(t);\n } else {\n n.innerHTML = t;\n }\n };\n // detect isElement\n /**\n * Runtime check for HTMLElement.\n * @param {unknown} el\n * @returns {el is HTMLElement}\n */\n this.i = function (el) {\n return (\n !!el &&\n typeof el === 'object' &&\n el.nodeType === 1 &&\n typeof el.style === 'object' &&\n typeof el.ownerDocument === 'object'\n );\n };\n\n //target,eventType,handler\n /**\n * Add event listener with legacy fallback.\n * @param {HTMLElement} t\n * @param {string} e\n * @param {(ev:Event)=>void} h\n */\n this.on = function (t, e, h) {\n if (!!t.addEventListener) {\n t.addEventListener(e, h, false);\n } else {\n t.attachEvent('on' + e, h);\n }\n };\n }\n}\n\nexport const $ = new Dom(window);\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { $ } from './jsmind.dom.js';\n\n/**\n * Misc utility collection.\n * @type {{\n * file: { read: (file: File, cb:(result:string,name:string)=>void)=>void, save:(data:string,type:string,name:string)=>void},\n * json: { json2string:(v:unknown)=>string, string2json:(s:string)=>unknown, merge:(b:object,a:object)=>object },\n * uuid: { newid:()=>string },\n * text: { is_empty:(s?:string)=>boolean }\n * }}\n */\nexport const util = {\n file: {\n read: function (file_data, fn_callback) {\n var reader = new FileReader();\n reader.onload = function () {\n if (typeof fn_callback === 'function') {\n fn_callback(this.result, file_data.name);\n }\n };\n reader.readAsText(file_data);\n },\n\n save: function (file_data, type, name) {\n var blob;\n if (typeof $.w.Blob === 'function') {\n blob = new Blob([file_data], { type: type });\n } else {\n var BlobBuilder =\n $.w.BlobBuilder ||\n $.w.MozBlobBuilder ||\n $.w.WebKitBlobBuilder ||\n $.w.MSBlobBuilder;\n var bb = new BlobBuilder();\n bb.append(file_data);\n blob = bb.getBlob(type);\n }\n if (navigator.msSaveBlob) {\n navigator.msSaveBlob(blob, name);\n } else {\n var URL = $.w.URL || $.w.webkitURL;\n var blob_url = URL.createObjectURL(blob);\n var anchor = $.c('a');\n if ('download' in anchor) {\n anchor.style.visibility = 'hidden';\n anchor.href = blob_url;\n anchor.download = name;\n $.d.body.appendChild(anchor);\n var evt = $.d.createEvent('MouseEvents');\n evt.initEvent('click', true, true);\n anchor.dispatchEvent(evt);\n $.d.body.removeChild(anchor);\n } else {\n location.href = blob_url;\n }\n }\n },\n },\n\n json: {\n json2string: function (json) {\n return JSON.stringify(json);\n },\n string2json: function (json_str) {\n return JSON.parse(json_str);\n },\n merge: function (b, a) {\n for (var o in a) {\n if (o in b) {\n if (\n typeof b[o] === 'object' &&\n Object.prototype.toString.call(b[o]).toLowerCase() == '[object object]' &&\n !b[o].length\n ) {\n util.json.merge(b[o], a[o]);\n } else {\n b[o] = a[o];\n }\n } else {\n b[o] = a[o];\n }\n }\n return b;\n },\n },\n\n uuid: {\n newid: function () {\n return (\n new Date().getTime().toString(16) + Math.random().toString(16).substring(2)\n ).substring(2, 18);\n },\n },\n\n text: {\n is_empty: function (s) {\n if (!s) {\n return true;\n }\n return s.replace(/\\s*/, '').length == 0;\n },\n },\n};\n","/**\n * @license BSD-3-Clause\n * @copyright 2014-2025 hizzgdev@163.com\n *\n * Project Home:\n * https://github.com/hizzgdev/jsmind/\n */\n\nimport { Plugin } from '../../jsmind.plugin.js';\nimport { util } from '../../jsmind.util.js';\nimport jsMind from '@umbraci/jsmind';\n\n/**\n * 简化版复制粘贴插件\n */\n\nclass CopyPasteHandler {\n constructor(jm, options = {}) {\n this.jsMind = jm;\n this.options = {\n enabled: true,\n shortcuts: {\n copy: 'meta+c',\n paste: 'meta+v',\n cut: 'meta+x'\n },\n ...options\n };\n this.clipboardData = null;\n\n this.logger = {\n info: (msg) => console.info('[CopyPaste]', msg),\n warn: (msg) => console.warn('[CopyPaste]', msg),\n error: (msg) => console.error('[CopyPaste]', msg),\n debug: (msg) => console.debug('[CopyPaste]', msg)\n };\n\n this.init();\n }\n\n init() {\n this.logger.info('CopyPaste plugin initialized');\n return true;\n }\n\n handleCopy(event) {\n if (!this.options.enabled) return;\n\n const selectedNode = this.jsMind.get_selected_node();\n if (!selectedNode) {\n this.logger.warn('No node selected for copying');\n return;\n }\n\n try {\n event.preventDefault();\n\n // 复制节点数据\n this.clipboardData = {\n id: selectedNode.id,\n topic: selectedNode.topic,\n data: selectedNode.data || {},\n direction: selectedNode.direction,\n expanded: selectedNode.expanded,\n children: this.copyChildren(selectedNode)\n };\n\n this.logger.info('Node copied:', selectedNode.topic);\n\n // 显示成功消息\n this.showMessage('节点已复制');\n\n } catch (error) {\n this.logger.error('Copy failed:', error);\n this.showMessage('复制失败', 'error');\n }\n }\n\n handlePaste(event) {\n if (!this.options.enabled) return;\n if (!this.clipboardData) {\n this.logger.warn('No data in clipboard');\n this.showMessage('剪贴板为空,请先复制节点', 'warning');\n return;\n }\n\n const targetNode = this.jsMind.get_selected_node();\n if (!targetNode) {\n this.logger.warn('No target node selected for pasting');\n this.showMessage('请选择目标节点', 'warning');\n return;\n }\n\n try {\n event.preventDefault();\n\n // 准备批量数据(包含所有子节点)\n const batchData = this.prepareBatchData(this.clipboardData);\n\n // 使用 add_nodes 批量创建节点\n const createdNodes = this.jsMind.add_nodes(targetNode, [batchData]);\n\n if (createdNodes && createdNodes.length > 0) {\n this.logger.info('Nodes pasted successfully:', this.clipboardData.topic);\n this.showMessage('粘贴成功');\n }\n\n } catch (error) {\n this.logger.error('Paste failed:', error);\n this.showMessage('粘贴失败', 'error');\n }\n }\n\n handleCut(event) {\n if (!this.options.enabled) return;\n\n const selectedNode = this.jsMind.get_selected_node();\n if (!selectedNode) {\n this.logger.warn('No node selected for cutting');\n return;\n }\n\n if (selectedNode.isroot) {\n this.logger.warn('Cannot cut root node');\n this.showMessage('不能剪切根节点', 'warning');\n return;\n }\n\n try {\n event.preventDefault();\n\n // 先复制到剪贴板\n this.clipboardData = {\n id: selectedNode.id,\n topic: selectedNode.topic,\n data: selectedNode.data || {},\n direction: selectedNode.direction,\n expanded: selectedNode.expanded,\n children: this.copyChildren(selectedNode)\n };\n\n // 删除原节点\n const removed = this.jsMind.remove_node(selectedNode);\n\n if (removed) {\n this.logger.info('Node cut:', selectedNode.topic);\n this.showMessage('节点已剪切');\n }\n\n } catch (error) {\n this.logger.error('Cut failed:', error);\n this.showMessage('剪切失败', 'error');\n }\n }\n\n copyChildren(node) {\n if (!node.children || node.children.length === 0) {\n return [];\n }\n\n return node.children.map(child => ({\n id: child.id,\n topic: child.topic,\n data: child.data || {},\n direction: child.direction,\n expanded: child.expanded,\n children: this.copyChildren(child)\n }));\n }\n\n /**\n * 准备批量数据,将节点数据转换为 add_nodes 所需的格式\n * @param {Object} nodeData - 节点数据\n * @returns {Object} - 格式化后的批量数据\n */\n prepareBatchData(nodeData) {\n return {\n id: util.uuid.newid(),\n topic: nodeData.topic,\n data: nodeData.data || {},\n children: nodeData.children && nodeData.children.length > 0\n ? nodeData.children.map(child => this.prepareBatchData(child))\n : undefined\n };\n }\n\n pasteChildren(parentNode, children) {\n // 保留此方法以备兼容性,但新的实现不再使用递归方式\n if (!children || children.length === 0) return [];\n\n const batchData = children.map(child => this.prepareBatchData(child));\n return this.jsMind.add_nodes(parentNode, batchData);\n }\n\n showMessage(message, type = 'info') {\n // 简单的消息显示\n console.log(`[CopyPaste ${type.toUpperCase()}]: ${message}`);\n }\n\n clear() {\n this.clipboardData = null;\n this.logger.info('Clipboard cleared');\n }\n\n getStatus() {\n return {\n hasData: !!this.clipboardData,\n data: this.clipboardData\n };\n }\n}\n\n/**\n * 复制粘贴插件注册\n */\nexport const copy_paste_plugin = new jsMind.plugin('copy-paste', function (jm, options) {\n // 确保options存在且包含shortcuts\n var pluginOptions = options || {};\n pluginOptions.shortcuts = pluginOptions.shortcuts || {\n copy: 'meta+c',\n paste: 'meta+v',\n cut: 'meta+x'\n };\n\n var handler = new CopyPasteHandler(jm, pluginOptions);\n\n // 直接注册键盘事件监听器,而不是使用不存在的add_shortcut方法\n if (jm.view && jm.view.e_panel) {\n jm.view.e_panel.addEventListener('keydown', function(event) {\n // 检查是否按下了复制快捷键\n if ((event.metaKey || event.ctrlKey) && event.key === 'c' && !event.shiftKey && !event.altKey) {\n handler.handleCopy(event);\n }\n // 检查是否按下了粘贴快捷键\n else if ((event.metaKey || event.ctrlKey) && event.key === 'v' && !event.shiftKey && !event.altKey) {\n handler.handlePaste(event);\n }\n // 检查是否按下了剪切快捷键\n else if ((event.metaKey || event.ctrlKey) && event.key === 'x' && !event.shiftKey && !event.altKey) {\n handler.handleCut(event);\n }\n });\n }\n\n // 将处理器实例附加到jm对象,方便外部调用\n jm.copy_paste_handler = handler;\n});\n\n// 注册插件\njsMind.register_plugin(copy_paste_plugin);\n\nexport default CopyPasteHandler;"],"names":["$","constructor","w","this","d","document","g","id","getElementById","c","tag","createElement","t","n","hasChildNodes","firstChild","nodeValue","appendChild","createTextNode","h","HTMLElement","innerHTML","i","el","nodeType","style","ownerDocument","on","e","addEventListener","attachEvent","window","util","file","read","file_data","fn_callback","reader","FileReader","onload","result","name","readAsText","save","type","blob","Blob","bb","BlobBuilder","MozBlobBuilder","WebKitBlobBuilder","MSBlobBuilder","append","getBlob","navigator","msSaveBlob","blob_url","URL","webkitURL","createObjectURL","anchor","visibility","href","download","body","evt","createEvent","initEvent","dispatchEvent","removeChild","location","json","json2string","JSON","stringify","string2json","json_str","parse","merge","b","a","o","Object","prototype","toString","call","toLowerCase","length","uuid","newid","Date","getTime","Math","random","substring","text","is_empty","s","replace","CopyPasteHandler","jm","options","jsMind","enabled","shortcuts","copy","paste","cut","clipboardData","logger","info","msg","console","warn","error","debug","init","handleCopy","event","selectedNode","get_selected_node","preventDefault","topic","data","direction","expanded","children","copyChildren","showMessage","handlePaste","targetNode","batchData","prepareBatchData","createdNodes","add_nodes","handleCut","isroot","remove_node","node","map","child","nodeData","undefined","pasteChildren","parentNode","message","log","toUpperCase","clear","getStatus","hasData","copy_paste_plugin","plugin","pluginOptions","handler","view","e_panel","metaKey","ctrlKey","key","shiftKey","altKey","copy_paste_handler","register_plugin"],"mappings":"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"}
@@ -5,5 +5,5 @@
5
5
  * Project Home:
6
6
  * https://github.com/hizzgdev/jsmind/
7
7
  */
8
- "use strict";function t(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}Object.defineProperty(exports,"__esModule",{value:!0});var e=t(require("@umbraci/jsmind"));if(!e.default)throw new Error("jsMind is not defined");const i=e.default.$,s="getSelection"in i.w?function(){i.w.getSelection().removeAllRanges()}:function(){i.d.selection.empty()},o={line_width:5,line_color:"rgba(0,0,0,0.3)",line_color_invalid:"rgba(255,51,51,0.6)",lookup_delay:200,lookup_interval:100,scrolling_trigger_width:20,scrolling_step_length:10,shadow_node_class_name:"jsmind-draggable-shadow-node"};class n{constructor(t,i){var s={};e.default.util.json.merge(s,o),e.default.util.json.merge(s,i),this.version="0.4.0",this.jm=t,this.options=s,this.is_svg_engine="svg"===t.view.opts.engine,this.e_canvas=null,this.canvas_ctx=null,this.helper_line=null,this.shadow=null,this.shadow_p_x=0,this.shadow_p_y=0,this.shadow_w=0,this.shadow_h=0,this.active_node=null,this.target_node=null,this.target_direct=null,this.client_w=0,this.client_h=0,this.offset_x=0,this.offset_y=0,this.hlookup_delay=0,this.hlookup_timer=0,this.capture=!1,this.moved=!1,this.canvas_draggable=t.get_view_draggable(),this.view_panel=t.view.e_panel,this.view_panel_rect=null}init(){this.create_canvas(),this.create_shadow(),this.event_bind()}resize(){this.jm.view.e_nodes.appendChild(this.shadow),this.is_svg_engine?(this.e_canvas.setAttribute("width",this.jm.view.size.w),this.e_canvas.setAttribute("height",this.jm.view.size.h)):(this.e_canvas.width=this.jm.view.size.w,this.e_canvas.height=this.jm.view.size.h)}create_canvas(){if(this.is_svg_engine){var t=this._create_svg_element("svg");t.setAttribute("class","jsmind-draggable-helper"),t.setAttribute("style","position: absolute; top: 0; left: 0; pointer-events: none;"),this.jm.view.e_panel.appendChild(t),this.e_canvas=t}else{var e=i.c("canvas");this.jm.view.e_panel.appendChild(e);var s=e.getContext("2d");this.e_canvas=e,this.canvas_ctx=s}}_create_svg_element(t){return i.d.createElementNS("http://www.w3.org/2000/svg",t)}create_shadow(){var t=i.c("jmnode");t.style.visibility="hidden",t.style.zIndex="3",t.style.cursor="move",t.style.opacity="0.7",t.className=this.options.shadow_node_class_name,this.shadow=t}reset_shadow(t){var e=this.shadow.style;this.shadow.innerHTML=t.innerHTML,e.left=t.style.left,e.top=t.style.top,e.width=t.style.width,e.height=t.style.height,e.backgroundImage=t.style.backgroundImage,e.backgroundSize=t.style.backgroundSize,e.transform=t.style.transform,this.shadow_w=this.shadow.clientWidth,this.shadow_h=this.shadow.clientHeight}show_shadow(){this.moved||(this.shadow.style.visibility="visible")}hide_shadow(){this.shadow.style.visibility="hidden"}magnet_shadow(t,e,i){this.clear_lines();var s=i?this.options.line_color_invalid:this.options.line_color;this.is_svg_engine?this.svg_draw_line(t.x,t.y,e.x,e.y,s):(this.canvas_ctx.lineWidth=this.options.line_width,this.canvas_ctx.strokeStyle=s,this.canvas_ctx.lineCap="round",this.canvas_lineto(t.x,t.y,e.x,e.y))}clear_lines(){this.is_svg_engine?this.helper_line&&this.helper_line.parentNode&&(this.e_canvas.removeChild(this.helper_line),this.helper_line=null):this.canvas_ctx.clearRect(0,0,this.jm.view.size.w,this.jm.view.size.h)}canvas_lineto(t,e,i,s){this.canvas_ctx.beginPath(),this.canvas_ctx.moveTo(t,e),this.canvas_ctx.lineTo(i,s),this.canvas_ctx.stroke()}svg_draw_line(t,e,i,s,o){this.helper_line=this._create_svg_element("path"),this.helper_line.setAttribute("stroke",o),this.helper_line.setAttribute("stroke-width",this.options.line_width),this.helper_line.setAttribute("fill","transparent"),this.helper_line.setAttribute("stroke-linecap","round"),this._svg_bezier_to(this.helper_line,t,e,i,s),this.e_canvas.appendChild(this.helper_line)}_svg_bezier_to(t,e,i,s,o){t.setAttribute("d","M "+e+" "+i+" C "+(e+2*(s-e)/3)+" "+i+", "+e+" "+o+", "+s+" "+o)}event_bind(){var t=this,e=this.jm.view.container;i.on(e,"mousedown",(function(e){0===e.button&&t.dragstart.call(t,e)})),i.on(e,"mousemove",(function(e){0===e.movementX&&0===e.movementY||t.drag.call(t,e)})),i.on(e,"mouseup",(function(e){t.dragend.call(t,e)})),i.on(e,"touchstart",(function(e){t.dragstart.call(t,e)})),i.on(e,"touchmove",(function(e){t.drag.call(t,e)})),i.on(e,"touchend",(function(e){t.dragend.call(t,e)}))}dragstart(t){if(this.jm.get_editable()&&!this.capture){var e=this.jm.view;if(!e.is_editing()){this.active_node=null,this.view_draggable=this.jm.get_view_draggable();var s=this.find_node_element(t.target);if(s){this.view_draggable&&this.jm.disable_view_draggable();var o=e.get_binded_nodeid(s);if(o){var n=this.jm.get_node(o);if(!n.isroot){if(n.data&&!1===n.data.draggable)return;this.reset_shadow(s),this.view_panel_rect=this.view_panel.getBoundingClientRect(),this.active_node=n,this.offset_x=(t.clientX||t.touches[0].clientX)/e.zoom_current-s.offsetLeft,this.offset_y=(t.clientY||t.touches[0].clientY)/e.zoom_current-s.offsetTop,this.client_hw=Math.floor(s.clientWidth/2),this.client_hh=Math.floor(s.clientHeight/2),0!=this.hlookup_delay&&i.w.clearTimeout(this.hlookup_delay),0!=this.hlookup_timer&&i.w.clearInterval(this.hlookup_timer);var h=this;this.hlookup_delay=i.w.setTimeout((function(){h.hlookup_delay=0,h.hlookup_timer=i.w.setInterval((function(){h.lookup_target_node.call(h)}),h.options.lookup_interval)}),this.options.lookup_delay),h.capture=!0}}}}}}drag(t){if(this.jm.get_editable()&&this.capture){t.preventDefault(),this.show_shadow(),this.moved=!0,s();var e=this.jm.view,i=(t.clientX||t.touches[0].clientX)/e.zoom_current-this.offset_x,o=(t.clientY||t.touches[0].clientY)/e.zoom_current-this.offset_y;t.clientY-this.view_panel_rect.top<this.options.scrolling_trigger_width&&this.view_panel.scrollTop>this.options.scrolling_step_length?(this.view_panel.scrollBy(0,-this.options.scrolling_step_length),this.offset_y+=this.options.scrolling_step_length/e.zoom_current):this.view_panel_rect.bottom-t.clientY<this.options.scrolling_trigger_width&&this.view_panel.scrollTop<this.view_panel.scrollHeight-this.view_panel_rect.height-this.options.scrolling_step_length&&(this.view_panel.scrollBy(0,this.options.scrolling_step_length),this.offset_y-=this.options.scrolling_step_length/e.zoom_current),t.clientX-this.view_panel_rect.left<this.options.scrolling_trigger_width&&this.view_panel.scrollLeft>this.options.scrolling_step_length?(this.view_panel.scrollBy(-this.options.scrolling_step_length,0),this.offset_x+=this.options.scrolling_step_length/e.zoom_current):this.view_panel_rect.right-t.clientX<this.options.scrolling_trigger_width&&this.view_panel.scrollLeft<this.view_panel.scrollWidth-this.view_panel_rect.width-this.options.scrolling_step_length&&(this.view_panel.scrollBy(this.options.scrolling_step_length,0),this.offset_x-=this.options.scrolling_step_length/e.zoom_current),this.shadow.style.left=i+"px",this.shadow.style.top=o+"px",s()}}dragend(t){if(this.jm.get_editable()){if(this.view_draggable&&this.jm.enable_view_draggable(),this.capture){if(0!=this.hlookup_delay&&(i.w.clearTimeout(this.hlookup_delay),this.hlookup_delay=0,this.clear_lines()),0!=this.hlookup_timer&&(i.w.clearInterval(this.hlookup_timer),this.hlookup_timer=0,this.clear_lines()),this.moved){var e=this.active_node,s=this.target_node,o=this.target_direct;this.move_node(e,s,o)}this.hide_shadow()}this.view_panel_rect=null,this.moved=!1,this.capture=!1}}find_node_element(t){return t===this.jm.view.e_nodes||t===this.jm.view.e_panel||t===this.jm.view.container?null:"jmnode"===t.tagName.toLowerCase()?t:this.find_node_element(t.parentNode)}lookup_target_node(){let t=this.shadow.offsetLeft,i=this.shadow.offsetTop;if(t===this.shadow_p_x&&i===this.shadow_p_y)return;this.shadow_p_x=t,this.shadow_p_y=i;let s=this.shadow_p_x+this.shadow_w/2>=this.get_root_x()?e.default.direction.right:e.default.direction.left,o=this.lookup_overlapping_node_parent(s)||this.lookup_close_node(s);if(o){let t=this.calc_point_of_node(o,s),i=e.default.node.inherited(this.active_node,o);this.magnet_shadow(t.sp,t.np,i),this.target_node=o,this.target_direct=s}}get_root_x(){let t=this.jm.get_root(),e=t.get_location(),i=t.get_size();return e.x+i.w/2}lookup_overlapping_node_parent(t){let e=this.shadow.getBoundingClientRect(),i=e.x+e.width*(1-t)/2,s=(this.jm.options.layout.hspace+this.jm.options.layout.pspace)*t,o=e.height,n=[[i,e.y],[i,e.y+o/2],[i,e.y+o],[i+s/2,e.y],[i+s/2,e.y+o/2],[i+s/2,e.y+o],[i+s,e.y],[i+s,e.y+o/2],[i+s,e.y+o]];for(const t of n){let e=this.lookup_node_parent_by_location(t[0],t[1]);if(e)return e}}lookup_node_parent_by_location(t,e){return i.d.elementsFromPoint(t,e).filter((t=>"JMNODE"===t.tagName&&t.className!==this.options.shadow_node_class_name)).map((t=>this.jm.view.get_binded_nodeid(t))).map((t=>t&&this.jm.mind.nodes[t])).map((t=>t&&t.parent)).find((t=>t))}lookup_close_node(t){return Object.values(this.jm.mind.nodes).filter((e=>e.direction==t||e.isroot)).filter((t=>this.jm.layout.is_visible(t))).filter((e=>this.shadow_on_target_side(e,t))).map((e=>({node:e,distance:this.shadow_to_node(e,t)}))).reduce(((t,e)=>t.distance<e.distance?t:e),{node:this.jm.get_root(),distance:Number.MAX_VALUE}).node}shadow_on_target_side(t,i){return i==e.default.direction.right&&this.shadow_to_right_of_node(t)>0||i==e.default.direction.left&&this.shadow_to_left_of_node(t)>0}shadow_to_right_of_node(t){return this.shadow_p_x-t.get_location().x-t.get_size().w}shadow_to_left_of_node(t){return t.get_location().x-this.shadow_p_x-this.shadow_w}shadow_to_base_line_of_node(t){return this.shadow_p_y+this.shadow_h/2-t.get_location().y-t.get_size().h/2}shadow_to_node(t,i){return(i===e.default.direction.right?Math.abs(this.shadow_to_right_of_node(t)):Math.abs(this.shadow_to_left_of_node(t)))+Math.abs(this.shadow_to_base_line_of_node(t))}calc_point_of_node(t,e){let i=t.get_size(),s=t.get_location(),o=t.isroot?s.x+i.w/2:s.x+i.w*(1+e)/2+this.options.line_width*e,n=s.y+i.h/2;return{sp:{x:this.shadow_p_x+this.shadow_w*(1-e)/2-this.options.line_width*e,y:this.shadow_p_y+this.shadow_h/2},np:{x:o,y:n}}}move_node(t,i,s){var o=this.shadow.offsetTop;if(i&&t&&!e.default.node.inherited(t,i)){if(this.options.validate_drag&&"function"==typeof this.options.validate_drag){if(!this.options.validate_drag(t,i))return this.active_node=null,this.target_node=null,void(this.target_direct=null)}for(var n=i.children,h=n.length,l=null,_=Number.MAX_VALUE,a=null,r="_last_";h--;)if((l=n[h]).direction==s&&l.id!=t.id){var d=l.get_location().y-o;d>0&&d<_&&(_=d,a=l,r="_first_")}a&&(r=a.id),this.jm.move_node(t.id,r,i.id,s)}this.active_node=null,this.target_node=null,this.target_direct=null}jm_event_handle(t,i){t===e.default.event_type.resize&&this.resize()}}const h=new e.default.plugin("draggable_node",(function(t,e){var i=new n(t,e);i.init(),t.add_event_listener((function(t,e){i.jm_event_handle.call(i,t,e)}))}));e.default.register_plugin(h),exports.DraggableNode=n,exports.default=n,exports.draggable_plugin=h;
8
+ "use strict";function t(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}Object.defineProperty(exports,"__esModule",{value:!0});var e=t(require("@umbraci/jsmind"));if(!e.default)throw new Error("jsMind is not defined");const i=e.default.$,s="getSelection"in i.w?function(){i.w.getSelection().removeAllRanges()}:function(){i.d.selection.empty()},o={line_width:5,line_color:"rgba(0,0,0,0.3)",line_color_invalid:"rgba(255,51,51,0.6)",lookup_delay:200,lookup_interval:100,scrolling_trigger_width:20,scrolling_step_length:10,shadow_node_class_name:"jsmind-draggable-shadow-node"};class n{constructor(t,i){var s={};e.default.util.json.merge(s,o),e.default.util.json.merge(s,i),this.version="0.4.0",this.jm=t,this.options=s,this.is_svg_engine="svg"===t.view.opts.engine,this.e_canvas=null,this.canvas_ctx=null,this.helper_line=null,this.shadow=null,this.shadow_p_x=0,this.shadow_p_y=0,this.shadow_w=0,this.shadow_h=0,this.active_node=null,this.target_node=null,this.target_direct=null,this.client_w=0,this.client_h=0,this.offset_x=0,this.offset_y=0,this.hlookup_delay=0,this.hlookup_timer=0,this.capture=!1,this.moved=!1,this.canvas_draggable=t.get_view_draggable(),this.view_panel=t.view.e_panel,this.view_panel_rect=null}init(){this.create_canvas(),this.create_shadow(),this.event_bind()}resize(){this.jm.view.e_nodes.appendChild(this.shadow),this.is_svg_engine?(this.e_canvas.setAttribute("width",this.jm.view.size.w),this.e_canvas.setAttribute("height",this.jm.view.size.h)):(this.e_canvas.width=this.jm.view.size.w,this.e_canvas.height=this.jm.view.size.h)}create_canvas(){if(this.is_svg_engine){var t=this._create_svg_element("svg");t.setAttribute("class","jsmind-draggable-helper"),t.setAttribute("style","position: absolute; top: 0; left: 0; pointer-events: none;"),this.jm.view.e_panel.appendChild(t),this.e_canvas=t}else{var e=i.c("canvas");this.jm.view.e_panel.appendChild(e);var s=e.getContext("2d");this.e_canvas=e,this.canvas_ctx=s}}_create_svg_element(t){return i.d.createElementNS("http://www.w3.org/2000/svg",t)}create_shadow(){var t=i.c("jmnode");t.style.visibility="hidden",t.style.zIndex="3",t.style.cursor="move",t.style.opacity="0.7",t.className=this.options.shadow_node_class_name,this.shadow=t}reset_shadow(t){var e=this.shadow.style;this.shadow.innerHTML=t.innerHTML,e.left=t.style.left,e.top=t.style.top,e.width=t.style.width,e.height=t.style.height,e.backgroundImage=t.style.backgroundImage,e.backgroundSize=t.style.backgroundSize,e.transform=t.style.transform,this.shadow_w=this.shadow.clientWidth,this.shadow_h=this.shadow.clientHeight}show_shadow(){this.moved||(this.shadow.style.visibility="visible")}hide_shadow(){this.shadow.style.visibility="hidden"}magnet_shadow(t,e,i){this.clear_lines();var s=i?this.options.line_color_invalid:this.options.line_color;this.is_svg_engine?this.svg_draw_line(t.x,t.y,e.x,e.y,s):(this.canvas_ctx.lineWidth=this.options.line_width,this.canvas_ctx.strokeStyle=s,this.canvas_ctx.lineCap="round",this.canvas_lineto(t.x,t.y,e.x,e.y))}clear_lines(){this.is_svg_engine?this.helper_line&&this.helper_line.parentNode&&(this.e_canvas.removeChild(this.helper_line),this.helper_line=null):this.canvas_ctx.clearRect(0,0,this.jm.view.size.w,this.jm.view.size.h)}canvas_lineto(t,e,i,s){this.canvas_ctx.beginPath(),this.canvas_ctx.moveTo(t,e),this.canvas_ctx.lineTo(i,s),this.canvas_ctx.stroke()}svg_draw_line(t,e,i,s,o){this.helper_line=this._create_svg_element("path"),this.helper_line.setAttribute("stroke",o),this.helper_line.setAttribute("stroke-width",this.options.line_width),this.helper_line.setAttribute("fill","transparent"),this.helper_line.setAttribute("stroke-linecap","round"),this._svg_bezier_to(this.helper_line,t,e,i,s),this.e_canvas.appendChild(this.helper_line)}_svg_bezier_to(t,e,i,s,o){t.setAttribute("d","M "+e+" "+i+" C "+(e+2*(s-e)/3)+" "+i+", "+e+" "+o+", "+s+" "+o)}event_bind(){var t=this,e=this.jm.view.container;i.on(e,"mousedown",function(e){0===e.button&&t.dragstart.call(t,e)}),i.on(e,"mousemove",function(e){0===e.movementX&&0===e.movementY||t.drag.call(t,e)}),i.on(e,"mouseup",function(e){t.dragend.call(t,e)}),i.on(e,"touchstart",function(e){t.dragstart.call(t,e)}),i.on(e,"touchmove",function(e){t.drag.call(t,e)}),i.on(e,"touchend",function(e){t.dragend.call(t,e)})}dragstart(t){if(this.jm.get_editable()&&!this.capture){var e=this.jm.view;if(!e.is_editing()){this.active_node=null,this.view_draggable=this.jm.get_view_draggable();var s=this.find_node_element(t.target);if(s){this.view_draggable&&this.jm.disable_view_draggable();var o=e.get_binded_nodeid(s);if(o){var n=this.jm.get_node(o);if(!n.isroot){if(n.data&&!1===n.data.draggable)return;this.reset_shadow(s),this.view_panel_rect=this.view_panel.getBoundingClientRect(),this.active_node=n,this.offset_x=(t.clientX||t.touches[0].clientX)/e.zoom_current-s.offsetLeft,this.offset_y=(t.clientY||t.touches[0].clientY)/e.zoom_current-s.offsetTop,this.client_hw=Math.floor(s.clientWidth/2),this.client_hh=Math.floor(s.clientHeight/2),0!=this.hlookup_delay&&i.w.clearTimeout(this.hlookup_delay),0!=this.hlookup_timer&&i.w.clearInterval(this.hlookup_timer);var h=this;this.hlookup_delay=i.w.setTimeout(function(){h.hlookup_delay=0,h.hlookup_timer=i.w.setInterval(function(){h.lookup_target_node.call(h)},h.options.lookup_interval)},this.options.lookup_delay),h.capture=!0}}}}}}drag(t){if(this.jm.get_editable()&&this.capture){t.preventDefault(),this.show_shadow(),this.moved=!0,s();var e=this.jm.view,i=(t.clientX||t.touches[0].clientX)/e.zoom_current-this.offset_x,o=(t.clientY||t.touches[0].clientY)/e.zoom_current-this.offset_y;t.clientY-this.view_panel_rect.top<this.options.scrolling_trigger_width&&this.view_panel.scrollTop>this.options.scrolling_step_length?(this.view_panel.scrollBy(0,-this.options.scrolling_step_length),this.offset_y+=this.options.scrolling_step_length/e.zoom_current):this.view_panel_rect.bottom-t.clientY<this.options.scrolling_trigger_width&&this.view_panel.scrollTop<this.view_panel.scrollHeight-this.view_panel_rect.height-this.options.scrolling_step_length&&(this.view_panel.scrollBy(0,this.options.scrolling_step_length),this.offset_y-=this.options.scrolling_step_length/e.zoom_current),t.clientX-this.view_panel_rect.left<this.options.scrolling_trigger_width&&this.view_panel.scrollLeft>this.options.scrolling_step_length?(this.view_panel.scrollBy(-this.options.scrolling_step_length,0),this.offset_x+=this.options.scrolling_step_length/e.zoom_current):this.view_panel_rect.right-t.clientX<this.options.scrolling_trigger_width&&this.view_panel.scrollLeft<this.view_panel.scrollWidth-this.view_panel_rect.width-this.options.scrolling_step_length&&(this.view_panel.scrollBy(this.options.scrolling_step_length,0),this.offset_x-=this.options.scrolling_step_length/e.zoom_current),this.shadow.style.left=i+"px",this.shadow.style.top=o+"px",s()}}dragend(t){if(this.jm.get_editable()){if(this.view_draggable&&this.jm.enable_view_draggable(),this.capture){if(0!=this.hlookup_delay&&(i.w.clearTimeout(this.hlookup_delay),this.hlookup_delay=0,this.clear_lines()),0!=this.hlookup_timer&&(i.w.clearInterval(this.hlookup_timer),this.hlookup_timer=0,this.clear_lines()),this.moved){var e=this.active_node,s=this.target_node,o=this.target_direct;this.move_node(e,s,o)}this.hide_shadow()}this.view_panel_rect=null,this.moved=!1,this.capture=!1}}find_node_element(t){return t===this.jm.view.e_nodes||t===this.jm.view.e_panel||t===this.jm.view.container?null:"jmnode"===t.tagName.toLowerCase()?t:this.find_node_element(t.parentNode)}lookup_target_node(){let t=this.shadow.offsetLeft,i=this.shadow.offsetTop;if(t===this.shadow_p_x&&i===this.shadow_p_y)return;this.shadow_p_x=t,this.shadow_p_y=i;let s=this.shadow_p_x+this.shadow_w/2>=this.get_root_x()?e.default.direction.right:e.default.direction.left,o=this.lookup_overlapping_node_parent(s)||this.lookup_close_node(s);if(o){let t=this.calc_point_of_node(o,s),i=e.default.node.inherited(this.active_node,o);this.magnet_shadow(t.sp,t.np,i),this.target_node=o,this.target_direct=s}}get_root_x(){let t=this.jm.get_root(),e=t.get_location(),i=t.get_size();return e.x+i.w/2}lookup_overlapping_node_parent(t){let e=this.shadow.getBoundingClientRect(),i=e.x+e.width*(1-t)/2,s=(this.jm.options.layout.hspace+this.jm.options.layout.pspace)*t,o=e.height,n=[[i,e.y],[i,e.y+o/2],[i,e.y+o],[i+s/2,e.y],[i+s/2,e.y+o/2],[i+s/2,e.y+o],[i+s,e.y],[i+s,e.y+o/2],[i+s,e.y+o]];for(const t of n){let e=this.lookup_node_parent_by_location(t[0],t[1]);if(e)return e}}lookup_node_parent_by_location(t,e){return i.d.elementsFromPoint(t,e).filter(t=>"JMNODE"===t.tagName&&t.className!==this.options.shadow_node_class_name).map(t=>this.jm.view.get_binded_nodeid(t)).map(t=>t&&this.jm.mind.nodes[t]).map(t=>t&&t.parent).find(t=>t)}lookup_close_node(t){return Object.values(this.jm.mind.nodes).filter(e=>e.direction==t||e.isroot).filter(t=>this.jm.layout.is_visible(t)).filter(e=>this.shadow_on_target_side(e,t)).map(e=>({node:e,distance:this.shadow_to_node(e,t)})).reduce((t,e)=>t.distance<e.distance?t:e,{node:this.jm.get_root(),distance:Number.MAX_VALUE}).node}shadow_on_target_side(t,i){return i==e.default.direction.right&&this.shadow_to_right_of_node(t)>0||i==e.default.direction.left&&this.shadow_to_left_of_node(t)>0}shadow_to_right_of_node(t){return this.shadow_p_x-t.get_location().x-t.get_size().w}shadow_to_left_of_node(t){return t.get_location().x-this.shadow_p_x-this.shadow_w}shadow_to_base_line_of_node(t){return this.shadow_p_y+this.shadow_h/2-t.get_location().y-t.get_size().h/2}shadow_to_node(t,i){return(i===e.default.direction.right?Math.abs(this.shadow_to_right_of_node(t)):Math.abs(this.shadow_to_left_of_node(t)))+Math.abs(this.shadow_to_base_line_of_node(t))}calc_point_of_node(t,e){let i=t.get_size(),s=t.get_location(),o=t.isroot?s.x+i.w/2:s.x+i.w*(1+e)/2+this.options.line_width*e,n=s.y+i.h/2;return{sp:{x:this.shadow_p_x+this.shadow_w*(1-e)/2-this.options.line_width*e,y:this.shadow_p_y+this.shadow_h/2},np:{x:o,y:n}}}move_node(t,i,s){var o=this.shadow.offsetTop;if(i&&t&&!e.default.node.inherited(t,i)){if(this.options.validate_drag&&"function"==typeof this.options.validate_drag){if(!this.options.validate_drag(t,i))return this.active_node=null,this.target_node=null,void(this.target_direct=null)}for(var n=i.children,h=n.length,l=null,_=Number.MAX_VALUE,a=null,r="_last_";h--;)if((l=n[h]).direction==s&&l.id!=t.id){var d=l.get_location().y-o;d>0&&d<_&&(_=d,a=l,r="_first_")}a&&(r=a.id),this.jm.move_node(t.id,r,i.id,s)}this.active_node=null,this.target_node=null,this.target_direct=null}jm_event_handle(t,i){t===e.default.event_type.resize&&this.resize()}}const h=new e.default.plugin("draggable_node",function(t,e){var i=new n(t,e);i.init(),t.add_event_listener(function(t,e){i.jm_event_handle.call(i,t,e)})});e.default.register_plugin(h),exports.DraggableNode=n,exports.default=n,exports.draggable_plugin=h;
9
9
  //# sourceMappingURL=jsmind.draggable-node.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"jsmind.draggable-node.js","sources":["../src/plugins/jsmind.draggable-node.js"],"sourcesContent":["/**\r\n * @license BSD\r\n * @copyright 2014-2025 UmbraCi\r\n *\r\n * Project Home:\r\n * https://github.com/UmbraCi/jsmind/\r\n */\r\n\r\nimport jsMind from '@umbraci/jsmind';\r\n\r\nif (!jsMind) {\r\n throw new Error('jsMind is not defined');\r\n}\r\n\r\nconst $ = jsMind.$;\r\n\r\nconst clear_selection =\r\n 'getSelection' in $.w\r\n ? function () {\r\n $.w.getSelection().removeAllRanges();\r\n }\r\n : function () {\r\n $.d.selection.empty();\r\n };\r\n\r\n/**\r\n * Default options for draggable node plugin.\r\n * @typedef {Object} DraggableNodeOptions\r\n * @property {number} [line_width]\r\n * @property {string} [line_color]\r\n * @property {string} [line_color_invalid]\r\n * @property {number} [lookup_delay]\r\n * @property {number} [lookup_interval]\r\n * @property {number} [scrolling_trigger_width]\r\n * @property {number} [scrolling_step_length]\r\n * @property {string} [shadow_node_class_name]\r\n * @property {(draggedNode:import('../jsmind.node.js').Node, targetNode:import('../jsmind.node.js').Node|null)=>boolean} [validate_drag]\r\n */\r\nconst DEFAULT_OPTIONS = {\r\n line_width: 5,\r\n line_color: 'rgba(0,0,0,0.3)',\r\n line_color_invalid: 'rgba(255,51,51,0.6)',\r\n lookup_delay: 200,\r\n lookup_interval: 100,\r\n scrolling_trigger_width: 20,\r\n scrolling_step_length: 10,\r\n shadow_node_class_name: 'jsmind-draggable-shadow-node',\r\n};\r\n\r\n/**\r\n * Draggable node plugin for jsMind.\r\n */\r\nexport class DraggableNode {\r\n /**\r\n * Create draggable node plugin instance.\r\n * @param {import('../jsmind.js').default} jm - jsMind instance\r\n * @param {Partial<DraggableNodeOptions>} options - Plugin options\r\n */\r\n constructor(jm, options) {\r\n var opts = {};\r\n jsMind.util.json.merge(opts, DEFAULT_OPTIONS);\r\n jsMind.util.json.merge(opts, options);\r\n\r\n this.version = '0.4.0';\r\n /** @type {import('../jsmind.js').default} */\r\n this.jm = jm;\r\n /** @type {DraggableNodeOptions} */\r\n this.options = opts;\r\n /** @type {boolean} */\r\n this.is_svg_engine = jm.view.opts.engine === 'svg';\r\n /** @type {HTMLCanvasElement|SVGSVGElement|null} */\r\n this.e_canvas = null;\r\n /** @type {CanvasRenderingContext2D|null} */\r\n this.canvas_ctx = null;\r\n /** @type {SVGPathElement|null} */\r\n this.helper_line = null;\r\n /** @type {HTMLElement|null} */\r\n this.shadow = null;\r\n /** @type {number} */\r\n this.shadow_p_x = 0;\r\n /** @type {number} */\r\n this.shadow_p_y = 0;\r\n /** @type {number} */\r\n this.shadow_w = 0;\r\n /** @type {number} */\r\n this.shadow_h = 0;\r\n /** @type {import('../jsmind.node.js').Node|null} */\r\n this.active_node = null;\r\n /** @type {import('../jsmind.node.js').Node|null} */\r\n this.target_node = null;\r\n /** @type {number|null} */\r\n this.target_direct = null;\r\n /** @type {number} */\r\n this.client_w = 0;\r\n /** @type {number} */\r\n this.client_h = 0;\r\n /** @type {number} */\r\n this.offset_x = 0;\r\n /** @type {number} */\r\n this.offset_y = 0;\r\n /** @type {number} */\r\n this.hlookup_delay = 0;\r\n /** @type {number} */\r\n this.hlookup_timer = 0;\r\n /** @type {boolean} */\r\n this.capture = false;\r\n /** @type {boolean} */\r\n this.moved = false;\r\n /** @type {boolean} */\r\n this.canvas_draggable = jm.get_view_draggable();\r\n /** @type {HTMLElement} */\r\n this.view_panel = jm.view.e_panel;\r\n /** @type {DOMRect|null} */\r\n this.view_panel_rect = null;\r\n }\r\n /** Initialize the draggable node plugin. */\r\n init() {\r\n this.create_canvas();\r\n this.create_shadow();\r\n this.event_bind();\r\n }\r\n /** Resize canvas/SVG and shadow elements. */\r\n resize() {\r\n this.jm.view.e_nodes.appendChild(this.shadow);\r\n if (this.is_svg_engine) {\r\n this.e_canvas.setAttribute('width', this.jm.view.size.w);\r\n this.e_canvas.setAttribute('height', this.jm.view.size.h);\r\n } else {\r\n this.e_canvas.width = this.jm.view.size.w;\r\n this.e_canvas.height = this.jm.view.size.h;\r\n }\r\n }\r\n /** Create canvas or SVG for drawing drag lines. */\r\n create_canvas() {\r\n if (this.is_svg_engine) {\r\n // Create SVG element for helper lines\r\n var svg = this._create_svg_element('svg');\r\n svg.setAttribute('class', 'jsmind-draggable-helper');\r\n svg.setAttribute('style', 'position: absolute; top: 0; left: 0; pointer-events: none;');\r\n this.jm.view.e_panel.appendChild(svg);\r\n this.e_canvas = svg;\r\n } else {\r\n // Create Canvas element for helper lines\r\n var c = $.c('canvas');\r\n this.jm.view.e_panel.appendChild(c);\r\n var ctx = c.getContext('2d');\r\n this.e_canvas = c;\r\n this.canvas_ctx = ctx;\r\n }\r\n }\r\n /**\r\n * Create SVG element with proper namespace.\r\n * @param {string} tag - SVG tag name\r\n * @returns {SVGElement}\r\n * @private\r\n */\r\n _create_svg_element(tag) {\r\n return $.d.createElementNS('http://www.w3.org/2000/svg', tag);\r\n }\r\n create_shadow() {\r\n var s = $.c('jmnode');\r\n s.style.visibility = 'hidden';\r\n s.style.zIndex = '3';\r\n s.style.cursor = 'move';\r\n s.style.opacity = '0.7';\r\n s.className = this.options.shadow_node_class_name;\r\n this.shadow = s;\r\n }\r\n /**\r\n * Reset shadow element style and cache its size.\r\n * @param {HTMLElement} el - The node element to mirror as shadow\r\n */\r\n reset_shadow(el) {\r\n var s = this.shadow.style;\r\n this.shadow.innerHTML = el.innerHTML;\r\n s.left = el.style.left;\r\n s.top = el.style.top;\r\n s.width = el.style.width;\r\n s.height = el.style.height;\r\n s.backgroundImage = el.style.backgroundImage;\r\n s.backgroundSize = el.style.backgroundSize;\r\n s.transform = el.style.transform;\r\n this.shadow_w = this.shadow.clientWidth;\r\n this.shadow_h = this.shadow.clientHeight;\r\n }\r\n /** Show the shadow element. */\r\n show_shadow() {\r\n if (!this.moved) {\r\n this.shadow.style.visibility = 'visible';\r\n }\r\n }\r\n /** Hide the shadow element. */\r\n hide_shadow() {\r\n this.shadow.style.visibility = 'hidden';\r\n }\r\n /**\r\n * Draw a helper line between the shadow and target node.\r\n * @param {{x:number,y:number}} shadow_p - Shadow anchor point\r\n * @param {{x:number,y:number}} node_p - Target node anchor point\r\n * @param {boolean} invalid - Whether current target is invalid\r\n */\r\n magnet_shadow(shadow_p, node_p, invalid) {\r\n this.clear_lines();\r\n var color = invalid ? this.options.line_color_invalid : this.options.line_color;\r\n\r\n if (this.is_svg_engine) {\r\n this.svg_draw_line(shadow_p.x, shadow_p.y, node_p.x, node_p.y, color);\r\n } else {\r\n this.canvas_ctx.lineWidth = this.options.line_width;\r\n this.canvas_ctx.strokeStyle = color;\r\n this.canvas_ctx.lineCap = 'round';\r\n this.canvas_lineto(shadow_p.x, shadow_p.y, node_p.x, node_p.y);\r\n }\r\n }\r\n /** Clear helper lines from canvas or SVG. */\r\n clear_lines() {\r\n if (this.is_svg_engine) {\r\n if (this.helper_line && this.helper_line.parentNode) {\r\n this.e_canvas.removeChild(this.helper_line);\r\n this.helper_line = null;\r\n }\r\n } else {\r\n this.canvas_ctx.clearRect(0, 0, this.jm.view.size.w, this.jm.view.size.h);\r\n }\r\n }\r\n /**\r\n * Draw a straight helper line on canvas.\r\n * @param {number} x1\r\n * @param {number} y1\r\n * @param {number} x2\r\n * @param {number} y2\r\n */\r\n canvas_lineto(x1, y1, x2, y2) {\r\n this.canvas_ctx.beginPath();\r\n this.canvas_ctx.moveTo(x1, y1);\r\n this.canvas_ctx.lineTo(x2, y2);\r\n this.canvas_ctx.stroke();\r\n }\r\n /**\r\n * Draw a helper line on SVG using bezier curve.\r\n * Reuses the line drawing logic from SvgGraph.\r\n * @param {number} x1 - Start x coordinate\r\n * @param {number} y1 - Start y coordinate\r\n * @param {number} x2 - End x coordinate\r\n * @param {number} y2 - End y coordinate\r\n * @param {string} color - Line color\r\n */\r\n svg_draw_line(x1, y1, x2, y2, color) {\r\n // Create SVG path element for helper line\r\n this.helper_line = this._create_svg_element('path');\r\n this.helper_line.setAttribute('stroke', color);\r\n this.helper_line.setAttribute('stroke-width', this.options.line_width);\r\n this.helper_line.setAttribute('fill', 'transparent');\r\n this.helper_line.setAttribute('stroke-linecap', 'round');\r\n\r\n // Draw bezier curve (same as SvgGraph._bezier_to)\r\n this._svg_bezier_to(this.helper_line, x1, y1, x2, y2);\r\n\r\n // Add to SVG container\r\n this.e_canvas.appendChild(this.helper_line);\r\n }\r\n /**\r\n * Draw bezier curve to SVG path element.\r\n * Reuses logic from SvgGraph._bezier_to.\r\n * @param {SVGPathElement} path - SVG path element\r\n * @param {number} x1 - Start x coordinate\r\n * @param {number} y1 - Start y coordinate\r\n * @param {number} x2 - End x coordinate\r\n * @param {number} y2 - End y coordinate\r\n * @private\r\n */\r\n _svg_bezier_to(path, x1, y1, x2, y2) {\r\n path.setAttribute(\r\n 'd',\r\n 'M ' +\r\n x1 +\r\n ' ' +\r\n y1 +\r\n ' C ' +\r\n (x1 + ((x2 - x1) * 2) / 3) +\r\n ' ' +\r\n y1 +\r\n ', ' +\r\n x1 +\r\n ' ' +\r\n y2 +\r\n ', ' +\r\n x2 +\r\n ' ' +\r\n y2\r\n );\r\n }\r\n /** Bind mouse/touch events for dragging. */\r\n event_bind() {\r\n var jd = this;\r\n var container = this.jm.view.container;\r\n $.on(container, 'mousedown', function (e) {\r\n if (e.button === 0) {\r\n jd.dragstart.call(jd, e);\r\n }\r\n });\r\n $.on(container, 'mousemove', function (e) {\r\n if (e.movementX !== 0 || e.movementY !== 0) {\r\n jd.drag.call(jd, e);\r\n }\r\n });\r\n $.on(container, 'mouseup', function (e) {\r\n jd.dragend.call(jd, e);\r\n });\r\n $.on(container, 'touchstart', function (e) {\r\n jd.dragstart.call(jd, e);\r\n });\r\n $.on(container, 'touchmove', function (e) {\r\n jd.drag.call(jd, e);\r\n });\r\n $.on(container, 'touchend', function (e) {\r\n jd.dragend.call(jd, e);\r\n });\r\n }\r\n /**\r\n * Begin dragging interaction.\r\n * @param {MouseEvent|TouchEvent} e - Pointer down event\r\n */\r\n dragstart(e) {\r\n if (!this.jm.get_editable()) {\r\n return;\r\n }\r\n if (this.capture) {\r\n return;\r\n }\r\n var jview = this.jm.view;\r\n if (jview.is_editing()) {\r\n return;\r\n }\r\n this.active_node = null;\r\n this.view_draggable = this.jm.get_view_draggable();\r\n\r\n var el = this.find_node_element(e.target);\r\n if (!el) {\r\n return;\r\n }\r\n if (this.view_draggable) {\r\n this.jm.disable_view_draggable();\r\n }\r\n var nodeid = jview.get_binded_nodeid(el);\r\n if (!!nodeid) {\r\n var node = this.jm.get_node(nodeid);\r\n if (!node.isroot) {\r\n // 检查节点是否允许拖拽\r\n if (node.data && node.data.draggable === false) {\r\n return;\r\n }\r\n this.reset_shadow(el);\r\n this.view_panel_rect = this.view_panel.getBoundingClientRect();\r\n this.active_node = node;\r\n this.offset_x =\r\n (e.clientX || e.touches[0].clientX) / jview.zoom_current - el.offsetLeft;\r\n this.offset_y =\r\n (e.clientY || e.touches[0].clientY) / jview.zoom_current - el.offsetTop;\r\n this.client_hw = Math.floor(el.clientWidth / 2);\r\n this.client_hh = Math.floor(el.clientHeight / 2);\r\n if (this.hlookup_delay != 0) {\r\n $.w.clearTimeout(this.hlookup_delay);\r\n }\r\n if (this.hlookup_timer != 0) {\r\n $.w.clearInterval(this.hlookup_timer);\r\n }\r\n var jd = this;\r\n this.hlookup_delay = $.w.setTimeout(function () {\r\n jd.hlookup_delay = 0;\r\n jd.hlookup_timer = $.w.setInterval(function () {\r\n jd.lookup_target_node.call(jd);\r\n }, jd.options.lookup_interval);\r\n }, this.options.lookup_delay);\r\n jd.capture = true;\r\n }\r\n }\r\n }\r\n /**\r\n * Drag handler to move shadow and auto-scroll container.\r\n * @param {MouseEvent|TouchEvent} e - Pointer move event\r\n */\r\n drag(e) {\r\n if (!this.jm.get_editable()) {\r\n return;\r\n }\r\n if (this.capture) {\r\n e.preventDefault();\r\n this.show_shadow();\r\n this.moved = true;\r\n clear_selection();\r\n var jview = this.jm.view;\r\n var px = (e.clientX || e.touches[0].clientX) / jview.zoom_current - this.offset_x;\r\n var py = (e.clientY || e.touches[0].clientY) / jview.zoom_current - this.offset_y;\r\n // scrolling container axisY if drag nodes exceeding container\r\n if (\r\n e.clientY - this.view_panel_rect.top < this.options.scrolling_trigger_width &&\r\n this.view_panel.scrollTop > this.options.scrolling_step_length\r\n ) {\r\n this.view_panel.scrollBy(0, -this.options.scrolling_step_length);\r\n this.offset_y += this.options.scrolling_step_length / jview.zoom_current;\r\n } else if (\r\n this.view_panel_rect.bottom - e.clientY < this.options.scrolling_trigger_width &&\r\n this.view_panel.scrollTop <\r\n this.view_panel.scrollHeight -\r\n this.view_panel_rect.height -\r\n this.options.scrolling_step_length\r\n ) {\r\n this.view_panel.scrollBy(0, this.options.scrolling_step_length);\r\n this.offset_y -= this.options.scrolling_step_length / jview.zoom_current;\r\n }\r\n // scrolling container axisX if drag nodes exceeding container\r\n if (\r\n e.clientX - this.view_panel_rect.left < this.options.scrolling_trigger_width &&\r\n this.view_panel.scrollLeft > this.options.scrolling_step_length\r\n ) {\r\n this.view_panel.scrollBy(-this.options.scrolling_step_length, 0);\r\n this.offset_x += this.options.scrolling_step_length / jview.zoom_current;\r\n } else if (\r\n this.view_panel_rect.right - e.clientX < this.options.scrolling_trigger_width &&\r\n this.view_panel.scrollLeft <\r\n this.view_panel.scrollWidth -\r\n this.view_panel_rect.width -\r\n this.options.scrolling_step_length\r\n ) {\r\n this.view_panel.scrollBy(this.options.scrolling_step_length, 0);\r\n this.offset_x -= this.options.scrolling_step_length / jview.zoom_current;\r\n }\r\n this.shadow.style.left = px + 'px';\r\n this.shadow.style.top = py + 'px';\r\n clear_selection();\r\n }\r\n }\r\n /**\r\n * Finish dragging, move the node if applicable.\r\n * @param {MouseEvent|TouchEvent} e - Pointer up event\r\n */\r\n dragend(e) {\r\n if (!this.jm.get_editable()) {\r\n return;\r\n }\r\n if (this.view_draggable) {\r\n this.jm.enable_view_draggable();\r\n }\r\n if (this.capture) {\r\n if (this.hlookup_delay != 0) {\r\n $.w.clearTimeout(this.hlookup_delay);\r\n this.hlookup_delay = 0;\r\n this.clear_lines();\r\n }\r\n if (this.hlookup_timer != 0) {\r\n $.w.clearInterval(this.hlookup_timer);\r\n this.hlookup_timer = 0;\r\n this.clear_lines();\r\n }\r\n if (this.moved) {\r\n var src_node = this.active_node;\r\n var target_node = this.target_node;\r\n var target_direct = this.target_direct;\r\n this.move_node(src_node, target_node, target_direct);\r\n }\r\n this.hide_shadow();\r\n }\r\n this.view_panel_rect = null;\r\n this.moved = false;\r\n this.capture = false;\r\n }\r\n /**\r\n * Find the closest node element from an event target.\r\n * @param {HTMLElement} el - Current DOM element\r\n * @returns {HTMLElement|null} Matched node element or null\r\n */\r\n find_node_element(el) {\r\n if (\r\n el === this.jm.view.e_nodes ||\r\n el === this.jm.view.e_panel ||\r\n el === this.jm.view.container\r\n ) {\r\n return null;\r\n }\r\n if (el.tagName.toLowerCase() === 'jmnode') {\r\n return el;\r\n }\r\n return this.find_node_element(el.parentNode);\r\n }\r\n /** Recompute target node under the shadow and draw helper. */\r\n lookup_target_node() {\r\n let sx = this.shadow.offsetLeft;\r\n let sy = this.shadow.offsetTop;\r\n if (sx === this.shadow_p_x && sy === this.shadow_p_y) {\r\n return;\r\n }\r\n this.shadow_p_x = sx;\r\n this.shadow_p_y = sy;\r\n\r\n let target_direction =\r\n this.shadow_p_x + this.shadow_w / 2 >= this.get_root_x()\r\n ? jsMind.direction.right\r\n : jsMind.direction.left;\r\n let overlapping_node = this.lookup_overlapping_node_parent(target_direction);\r\n let target_node = overlapping_node || this.lookup_close_node(target_direction);\r\n if (!!target_node) {\r\n let points = this.calc_point_of_node(target_node, target_direction);\r\n let invalid = jsMind.node.inherited(this.active_node, target_node);\r\n this.magnet_shadow(points.sp, points.np, invalid);\r\n this.target_node = target_node;\r\n this.target_direct = target_direction;\r\n }\r\n }\r\n /**\r\n * Get X coordinate of root node center.\r\n * @returns {number}\r\n */\r\n get_root_x() {\r\n let root = this.jm.get_root();\r\n let root_location = root.get_location();\r\n let root_size = root.get_size();\r\n return root_location.x + root_size.w / 2;\r\n }\r\n\r\n /**\r\n * Lookup overlapping node's parent near the shadow position.\r\n * @param {number} direction - Direction constant\r\n * @returns {import('../jsmind.node.js').Node|null}\r\n */\r\n lookup_overlapping_node_parent(direction) {\r\n let shadowRect = this.shadow.getBoundingClientRect();\r\n let x = shadowRect.x + (shadowRect.width * (1 - direction)) / 2;\r\n let deltaX = (this.jm.options.layout.hspace + this.jm.options.layout.pspace) * direction;\r\n let deltaY = shadowRect.height;\r\n let points = [\r\n [x, shadowRect.y],\r\n [x, shadowRect.y + deltaY / 2],\r\n [x, shadowRect.y + deltaY],\r\n [x + deltaX / 2, shadowRect.y],\r\n [x + deltaX / 2, shadowRect.y + deltaY / 2],\r\n [x + deltaX / 2, shadowRect.y + deltaY],\r\n [x + deltaX, shadowRect.y],\r\n [x + deltaX, shadowRect.y + deltaY / 2],\r\n [x + deltaX, shadowRect.y + deltaY],\r\n ];\r\n for (const p of points) {\r\n let n = this.lookup_node_parent_by_location(p[0], p[1]);\r\n if (!!n) {\r\n return n;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Find node's parent by a screen location.\r\n * @param {number} x - Client X\r\n * @param {number} y - Client Y\r\n * @returns {import('../jsmind.node.js').Node|null}\r\n */\r\n lookup_node_parent_by_location(x, y) {\r\n return $.d\r\n .elementsFromPoint(x, y)\r\n .filter(\r\n x => x.tagName === 'JMNODE' && x.className !== this.options.shadow_node_class_name\r\n )\r\n .map(el => this.jm.view.get_binded_nodeid(el))\r\n .map(id => id && this.jm.mind.nodes[id])\r\n .map(n => n && n.parent)\r\n .find(n => n);\r\n }\r\n\r\n /**\r\n * Lookup the closest node along a direction.\r\n * @param {number} direction\r\n * @returns {import('../jsmind.node.js').Node}\r\n */\r\n lookup_close_node(direction) {\r\n return Object.values(this.jm.mind.nodes)\r\n .filter(n => n.direction == direction || n.isroot)\r\n .filter(n => this.jm.layout.is_visible(n))\r\n .filter(n => this.shadow_on_target_side(n, direction))\r\n .map(n => ({ node: n, distance: this.shadow_to_node(n, direction) }))\r\n .reduce(\r\n (prev, curr) => {\r\n return prev.distance < curr.distance ? prev : curr;\r\n },\r\n { node: this.jm.get_root(), distance: Number.MAX_VALUE }\r\n ).node;\r\n }\r\n\r\n /**\r\n * Check if shadow is on the target side of a node.\r\n * @param {import('../jsmind.node.js').Node} node\r\n * @param {number} dir\r\n * @returns {boolean}\r\n */\r\n shadow_on_target_side(node, dir) {\r\n return (\r\n (dir == jsMind.direction.right && this.shadow_to_right_of_node(node) > 0) ||\r\n (dir == jsMind.direction.left && this.shadow_to_left_of_node(node) > 0)\r\n );\r\n }\r\n\r\n /**\r\n * Distance from shadow to the right side of a node.\r\n * @param {import('../jsmind.node.js').Node} node\r\n * @returns {number}\r\n */\r\n shadow_to_right_of_node(node) {\r\n return this.shadow_p_x - node.get_location().x - node.get_size().w;\r\n }\r\n\r\n /**\r\n * Distance from shadow to the left side of a node.\r\n * @param {import('../jsmind.node.js').Node} node\r\n * @returns {number}\r\n */\r\n shadow_to_left_of_node(node) {\r\n return node.get_location().x - this.shadow_p_x - this.shadow_w;\r\n }\r\n\r\n /**\r\n * Vertical distance between shadow centerline and node centerline.\r\n * @param {import('../jsmind.node.js').Node} node\r\n * @returns {number}\r\n */\r\n shadow_to_base_line_of_node(node) {\r\n return this.shadow_p_y + this.shadow_h / 2 - node.get_location().y - node.get_size().h / 2;\r\n }\r\n\r\n /**\r\n * Manhattan distance to a node along a direction.\r\n * @param {import('../jsmind.node.js').Node} node\r\n * @param {number} dir\r\n * @returns {number}\r\n */\r\n shadow_to_node(node, dir) {\r\n let distance_x =\r\n dir === jsMind.direction.right\r\n ? Math.abs(this.shadow_to_right_of_node(node))\r\n : Math.abs(this.shadow_to_left_of_node(node));\r\n let distance_y = Math.abs(this.shadow_to_base_line_of_node(node));\r\n return distance_x + distance_y;\r\n }\r\n\r\n /**\r\n * Calculate connection points of a node and the shadow.\r\n * @param {import('../jsmind.node.js').Node} node\r\n * @param {number} dir\r\n * @returns {{sp:{x:number,y:number}, np:{x:number,y:number}}}\r\n */\r\n calc_point_of_node(node, dir) {\r\n let ns = node.get_size();\r\n let nl = node.get_location();\r\n let node_x = node.isroot\r\n ? nl.x + ns.w / 2\r\n : nl.x + (ns.w * (1 + dir)) / 2 + this.options.line_width * dir;\r\n let node_y = nl.y + ns.h / 2;\r\n let shadow_x =\r\n this.shadow_p_x + (this.shadow_w * (1 - dir)) / 2 - this.options.line_width * dir;\r\n let shadow_y = this.shadow_p_y + this.shadow_h / 2;\r\n return {\r\n sp: { x: shadow_x, y: shadow_y },\r\n np: { x: node_x, y: node_y },\r\n };\r\n }\r\n\r\n /**\r\n * Move a node to a new parent/position.\r\n * @param {import('../jsmind.node.js').Node} src_node\r\n * @param {import('../jsmind.node.js').Node|null} target_node\r\n * @param {number|null} target_direct\r\n */\r\n move_node(src_node, target_node, target_direct) {\r\n var shadow_h = this.shadow.offsetTop;\r\n if (!!target_node && !!src_node && !jsMind.node.inherited(src_node, target_node)) {\r\n // Call validate_drag function if provided, to validate the drag operation\r\n if (this.options.validate_drag && typeof this.options.validate_drag === 'function') {\r\n const isValid = this.options.validate_drag(src_node, target_node);\r\n if (!isValid) {\r\n // Drag operation is not allowed, cleanup and return\r\n this.active_node = null;\r\n this.target_node = null;\r\n this.target_direct = null;\r\n return;\r\n }\r\n }\r\n\r\n // lookup before_node\r\n var sibling_nodes = target_node.children;\r\n var sc = sibling_nodes.length;\r\n var node = null;\r\n var delta_y = Number.MAX_VALUE;\r\n var node_before = null;\r\n var beforeid = '_last_';\r\n while (sc--) {\r\n node = sibling_nodes[sc];\r\n if (node.direction == target_direct && node.id != src_node.id) {\r\n var dy = node.get_location().y - shadow_h;\r\n if (dy > 0 && dy < delta_y) {\r\n delta_y = dy;\r\n node_before = node;\r\n beforeid = '_first_';\r\n }\r\n }\r\n }\r\n if (!!node_before) {\r\n beforeid = node_before.id;\r\n }\r\n this.jm.move_node(src_node.id, beforeid, target_node.id, target_direct);\r\n }\r\n this.active_node = null;\r\n this.target_node = null;\r\n this.target_direct = null;\r\n }\r\n /**\r\n * Handle jsMind events.\r\n * @param {number|string} type - Event type\r\n * @param {object} [data] - Event data\r\n */\r\n jm_event_handle(type, data) {\r\n if (type === jsMind.event_type.resize) {\r\n this.resize();\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Draggable node plugin registration.\r\n * @type {import('../jsmind.plugin.js').Plugin<Partial<DraggableNodeOptions>>}\r\n */\r\nexport const draggable_plugin = new jsMind.plugin('draggable_node', function (jm, options) {\r\n var jd = new DraggableNode(jm, options);\r\n jd.init();\r\n jm.add_event_listener(function (type, data) {\r\n jd.jm_event_handle.call(jd, type, data);\r\n });\r\n});\r\n\r\njsMind.register_plugin(draggable_plugin);\r\n\r\nexport default DraggableNode;\r\n"],"names":["jsMind","Error","$","clear_selection","w","getSelection","removeAllRanges","d","selection","empty","DEFAULT_OPTIONS","line_width","line_color","line_color_invalid","lookup_delay","lookup_interval","scrolling_trigger_width","scrolling_step_length","shadow_node_class_name","DraggableNode","constructor","jm","options","opts","util","json","merge","this","version","is_svg_engine","view","engine","e_canvas","canvas_ctx","helper_line","shadow","shadow_p_x","shadow_p_y","shadow_w","shadow_h","active_node","target_node","target_direct","client_w","client_h","offset_x","offset_y","hlookup_delay","hlookup_timer","capture","moved","canvas_draggable","get_view_draggable","view_panel","e_panel","view_panel_rect","init","create_canvas","create_shadow","event_bind","resize","e_nodes","appendChild","setAttribute","size","h","width","height","svg","_create_svg_element","c","ctx","getContext","tag","createElementNS","s","style","visibility","zIndex","cursor","opacity","className","reset_shadow","el","innerHTML","left","top","backgroundImage","backgroundSize","transform","clientWidth","clientHeight","show_shadow","hide_shadow","magnet_shadow","shadow_p","node_p","invalid","clear_lines","color","svg_draw_line","x","y","lineWidth","strokeStyle","lineCap","canvas_lineto","parentNode","removeChild","clearRect","x1","y1","x2","y2","beginPath","moveTo","lineTo","stroke","_svg_bezier_to","path","jd","container","on","e","button","dragstart","call","movementX","movementY","drag","dragend","get_editable","jview","is_editing","view_draggable","find_node_element","target","disable_view_draggable","nodeid","get_binded_nodeid","node","get_node","isroot","data","draggable","getBoundingClientRect","clientX","touches","zoom_current","offsetLeft","clientY","offsetTop","client_hw","Math","floor","client_hh","clearTimeout","clearInterval","setTimeout","setInterval","lookup_target_node","preventDefault","px","py","scrollTop","scrollBy","bottom","scrollHeight","scrollLeft","right","scrollWidth","enable_view_draggable","src_node","move_node","tagName","toLowerCase","sx","sy","target_direction","get_root_x","direction","lookup_overlapping_node_parent","lookup_close_node","points","calc_point_of_node","inherited","sp","np","root","get_root","root_location","get_location","root_size","get_size","shadowRect","deltaX","layout","hspace","pspace","deltaY","p","n","lookup_node_parent_by_location","elementsFromPoint","filter","map","id","mind","nodes","parent","find","Object","values","is_visible","shadow_on_target_side","distance","shadow_to_node","reduce","prev","curr","Number","MAX_VALUE","dir","shadow_to_right_of_node","shadow_to_left_of_node","shadow_to_base_line_of_node","abs","ns","nl","node_x","node_y","validate_drag","sibling_nodes","children","sc","length","delta_y","node_before","beforeid","dy","jm_event_handle","type","event_type","draggable_plugin","plugin","add_event_listener","register_plugin"],"mappings":";;;;;;;gLAUA,IAAKA,UACD,MAAM,IAAIC,MAAM,yBAGpB,MAAMC,EAAIF,EAAM,QAACE,EAEXC,EACF,iBAAkBD,EAAEE,EACd,WACIF,EAAEE,EAAEC,eAAeC,iBACtB,EACD,WACIJ,EAAEK,EAAEC,UAAUC,OAC5B,EAeMC,EAAkB,CACpBC,WAAY,EACZC,WAAY,kBACZC,mBAAoB,sBACpBC,aAAc,IACdC,gBAAiB,IACjBC,wBAAyB,GACzBC,sBAAuB,GACvBC,uBAAwB,gCAMrB,MAAMC,EAMT,WAAAC,CAAYC,EAAIC,GACZ,IAAIC,EAAO,CAAA,EACXvB,EAAM,QAACwB,KAAKC,KAAKC,MAAMH,EAAMb,GAC7BV,EAAM,QAACwB,KAAKC,KAAKC,MAAMH,EAAMD,GAE7BK,KAAKC,QAAU,QAEfD,KAAKN,GAAKA,EAEVM,KAAKL,QAAUC,EAEfI,KAAKE,cAAwC,QAAxBR,EAAGS,KAAKP,KAAKQ,OAElCJ,KAAKK,SAAW,KAEhBL,KAAKM,WAAa,KAElBN,KAAKO,YAAc,KAEnBP,KAAKQ,OAAS,KAEdR,KAAKS,WAAa,EAElBT,KAAKU,WAAa,EAElBV,KAAKW,SAAW,EAEhBX,KAAKY,SAAW,EAEhBZ,KAAKa,YAAc,KAEnBb,KAAKc,YAAc,KAEnBd,KAAKe,cAAgB,KAErBf,KAAKgB,SAAW,EAEhBhB,KAAKiB,SAAW,EAEhBjB,KAAKkB,SAAW,EAEhBlB,KAAKmB,SAAW,EAEhBnB,KAAKoB,cAAgB,EAErBpB,KAAKqB,cAAgB,EAErBrB,KAAKsB,SAAU,EAEftB,KAAKuB,OAAQ,EAEbvB,KAAKwB,iBAAmB9B,EAAG+B,qBAE3BzB,KAAK0B,WAAahC,EAAGS,KAAKwB,QAE1B3B,KAAK4B,gBAAkB,IAC1B,CAED,IAAAC,GACI7B,KAAK8B,gBACL9B,KAAK+B,gBACL/B,KAAKgC,YACR,CAED,MAAAC,GACIjC,KAAKN,GAAGS,KAAK+B,QAAQC,YAAYnC,KAAKQ,QAClCR,KAAKE,eACLF,KAAKK,SAAS+B,aAAa,QAASpC,KAAKN,GAAGS,KAAKkC,KAAK5D,GACtDuB,KAAKK,SAAS+B,aAAa,SAAUpC,KAAKN,GAAGS,KAAKkC,KAAKC,KAEvDtC,KAAKK,SAASkC,MAAQvC,KAAKN,GAAGS,KAAKkC,KAAK5D,EACxCuB,KAAKK,SAASmC,OAASxC,KAAKN,GAAGS,KAAKkC,KAAKC,EAEhD,CAED,aAAAR,GACI,GAAI9B,KAAKE,cAAe,CAEpB,IAAIuC,EAAMzC,KAAK0C,oBAAoB,OACnCD,EAAIL,aAAa,QAAS,2BAC1BK,EAAIL,aAAa,QAAS,8DAC1BpC,KAAKN,GAAGS,KAAKwB,QAAQQ,YAAYM,GACjCzC,KAAKK,SAAWoC,CAC5B,KAAe,CAEH,IAAIE,EAAIpE,EAAEoE,EAAE,UACZ3C,KAAKN,GAAGS,KAAKwB,QAAQQ,YAAYQ,GACjC,IAAIC,EAAMD,EAAEE,WAAW,MACvB7C,KAAKK,SAAWsC,EAChB3C,KAAKM,WAAasC,CACrB,CACJ,CAOD,mBAAAF,CAAoBI,GAChB,OAAOvE,EAAEK,EAAEmE,gBAAgB,6BAA8BD,EAC5D,CACD,aAAAf,GACI,IAAIiB,EAAIzE,EAAEoE,EAAE,UACZK,EAAEC,MAAMC,WAAa,SACrBF,EAAEC,MAAME,OAAS,IACjBH,EAAEC,MAAMG,OAAS,OACjBJ,EAAEC,MAAMI,QAAU,MAClBL,EAAEM,UAAYtD,KAAKL,QAAQJ,uBAC3BS,KAAKQ,OAASwC,CACjB,CAKD,YAAAO,CAAaC,GACT,IAAIR,EAAIhD,KAAKQ,OAAOyC,MACpBjD,KAAKQ,OAAOiD,UAAYD,EAAGC,UAC3BT,EAAEU,KAAOF,EAAGP,MAAMS,KAClBV,EAAEW,IAAMH,EAAGP,MAAMU,IACjBX,EAAET,MAAQiB,EAAGP,MAAMV,MACnBS,EAAER,OAASgB,EAAGP,MAAMT,OACpBQ,EAAEY,gBAAkBJ,EAAGP,MAAMW,gBAC7BZ,EAAEa,eAAiBL,EAAGP,MAAMY,eAC5Bb,EAAEc,UAAYN,EAAGP,MAAMa,UACvB9D,KAAKW,SAAWX,KAAKQ,OAAOuD,YAC5B/D,KAAKY,SAAWZ,KAAKQ,OAAOwD,YAC/B,CAED,WAAAC,GACSjE,KAAKuB,QACNvB,KAAKQ,OAAOyC,MAAMC,WAAa,UAEtC,CAED,WAAAgB,GACIlE,KAAKQ,OAAOyC,MAAMC,WAAa,QAClC,CAOD,aAAAiB,CAAcC,EAAUC,EAAQC,GAC5BtE,KAAKuE,cACL,IAAIC,EAAQF,EAAUtE,KAAKL,QAAQT,mBAAqBc,KAAKL,QAAQV,WAEjEe,KAAKE,cACLF,KAAKyE,cAAcL,EAASM,EAAGN,EAASO,EAAGN,EAAOK,EAAGL,EAAOM,EAAGH,IAE/DxE,KAAKM,WAAWsE,UAAY5E,KAAKL,QAAQX,WACzCgB,KAAKM,WAAWuE,YAAcL,EAC9BxE,KAAKM,WAAWwE,QAAU,QAC1B9E,KAAK+E,cAAcX,EAASM,EAAGN,EAASO,EAAGN,EAAOK,EAAGL,EAAOM,GAEnE,CAED,WAAAJ,GACQvE,KAAKE,cACDF,KAAKO,aAAeP,KAAKO,YAAYyE,aACrChF,KAAKK,SAAS4E,YAAYjF,KAAKO,aAC/BP,KAAKO,YAAc,MAGvBP,KAAKM,WAAW4E,UAAU,EAAG,EAAGlF,KAAKN,GAAGS,KAAKkC,KAAK5D,EAAGuB,KAAKN,GAAGS,KAAKkC,KAAKC,EAE9E,CAQD,aAAAyC,CAAcI,EAAIC,EAAIC,EAAIC,GACtBtF,KAAKM,WAAWiF,YAChBvF,KAAKM,WAAWkF,OAAOL,EAAIC,GAC3BpF,KAAKM,WAAWmF,OAAOJ,EAAIC,GAC3BtF,KAAKM,WAAWoF,QACnB,CAUD,aAAAjB,CAAcU,EAAIC,EAAIC,EAAIC,EAAId,GAE1BxE,KAAKO,YAAcP,KAAK0C,oBAAoB,QAC5C1C,KAAKO,YAAY6B,aAAa,SAAUoC,GACxCxE,KAAKO,YAAY6B,aAAa,eAAgBpC,KAAKL,QAAQX,YAC3DgB,KAAKO,YAAY6B,aAAa,OAAQ,eACtCpC,KAAKO,YAAY6B,aAAa,iBAAkB,SAGhDpC,KAAK2F,eAAe3F,KAAKO,YAAa4E,EAAIC,EAAIC,EAAIC,GAGlDtF,KAAKK,SAAS8B,YAAYnC,KAAKO,YAClC,CAWD,cAAAoF,CAAeC,EAAMT,EAAIC,EAAIC,EAAIC,GAC7BM,EAAKxD,aACD,IACA,KACI+C,EACA,IACAC,EACA,OACCD,EAAkB,GAAXE,EAAKF,GAAW,GACxB,IACAC,EACA,KACAD,EACA,IACAG,EACA,KACAD,EACA,IACAC,EAEX,CAED,UAAAtD,GACI,IAAI6D,EAAK7F,KACL8F,EAAY9F,KAAKN,GAAGS,KAAK2F,UAC7BvH,EAAEwH,GAAGD,EAAW,aAAa,SAAUE,GAClB,IAAbA,EAAEC,QACFJ,EAAGK,UAAUC,KAAKN,EAAIG,EAEtC,IACQzH,EAAEwH,GAAGD,EAAW,aAAa,SAAUE,GACf,IAAhBA,EAAEI,WAAmC,IAAhBJ,EAAEK,WACvBR,EAAGS,KAAKH,KAAKN,EAAIG,EAEjC,IACQzH,EAAEwH,GAAGD,EAAW,WAAW,SAAUE,GACjCH,EAAGU,QAAQJ,KAAKN,EAAIG,EAChC,IACQzH,EAAEwH,GAAGD,EAAW,cAAc,SAAUE,GACpCH,EAAGK,UAAUC,KAAKN,EAAIG,EAClC,IACQzH,EAAEwH,GAAGD,EAAW,aAAa,SAAUE,GACnCH,EAAGS,KAAKH,KAAKN,EAAIG,EAC7B,IACQzH,EAAEwH,GAAGD,EAAW,YAAY,SAAUE,GAClCH,EAAGU,QAAQJ,KAAKN,EAAIG,EAChC,GACK,CAKD,SAAAE,CAAUF,GACN,GAAKhG,KAAKN,GAAG8G,iBAGTxG,KAAKsB,QAAT,CAGA,IAAImF,EAAQzG,KAAKN,GAAGS,KACpB,IAAIsG,EAAMC,aAAV,CAGA1G,KAAKa,YAAc,KACnBb,KAAK2G,eAAiB3G,KAAKN,GAAG+B,qBAE9B,IAAI+B,EAAKxD,KAAK4G,kBAAkBZ,EAAEa,QAClC,GAAKrD,EAAL,CAGIxD,KAAK2G,gBACL3G,KAAKN,GAAGoH,yBAEZ,IAAIC,EAASN,EAAMO,kBAAkBxD,GACrC,GAAMuD,EAAQ,CACV,IAAIE,EAAOjH,KAAKN,GAAGwH,SAASH,GAC5B,IAAKE,EAAKE,OAAQ,CAEd,GAAIF,EAAKG,OAAgC,IAAxBH,EAAKG,KAAKC,UACvB,OAEJrH,KAAKuD,aAAaC,GAClBxD,KAAK4B,gBAAkB5B,KAAK0B,WAAW4F,wBACvCtH,KAAKa,YAAcoG,EACnBjH,KAAKkB,UACA8E,EAAEuB,SAAWvB,EAAEwB,QAAQ,GAAGD,SAAWd,EAAMgB,aAAejE,EAAGkE,WAClE1H,KAAKmB,UACA6E,EAAE2B,SAAW3B,EAAEwB,QAAQ,GAAGG,SAAWlB,EAAMgB,aAAejE,EAAGoE,UAClE5H,KAAK6H,UAAYC,KAAKC,MAAMvE,EAAGO,YAAc,GAC7C/D,KAAKgI,UAAYF,KAAKC,MAAMvE,EAAGQ,aAAe,GACpB,GAAtBhE,KAAKoB,eACL7C,EAAEE,EAAEwJ,aAAajI,KAAKoB,eAEA,GAAtBpB,KAAKqB,eACL9C,EAAEE,EAAEyJ,cAAclI,KAAKqB,eAE3B,IAAIwE,EAAK7F,KACTA,KAAKoB,cAAgB7C,EAAEE,EAAE0J,YAAW,WAChCtC,EAAGzE,cAAgB,EACnByE,EAAGxE,cAAgB9C,EAAEE,EAAE2J,aAAY,WAC/BvC,EAAGwC,mBAAmBlC,KAAKN,EACnD,GAAuBA,EAAGlG,QAAQP,gBAClC,GAAmBY,KAAKL,QAAQR,cAChB0G,EAAGvE,SAAU,CAChB,CACJ,CApCA,CAPA,CAJA,CAgDJ,CAKD,IAAAgF,CAAKN,GACD,GAAKhG,KAAKN,GAAG8G,gBAGTxG,KAAKsB,QAAS,CACd0E,EAAEsC,iBACFtI,KAAKiE,cACLjE,KAAKuB,OAAQ,EACb/C,IACA,IAAIiI,EAAQzG,KAAKN,GAAGS,KAChBoI,GAAMvC,EAAEuB,SAAWvB,EAAEwB,QAAQ,GAAGD,SAAWd,EAAMgB,aAAezH,KAAKkB,SACrEsH,GAAMxC,EAAE2B,SAAW3B,EAAEwB,QAAQ,GAAGG,SAAWlB,EAAMgB,aAAezH,KAAKmB,SAGrE6E,EAAE2B,QAAU3H,KAAK4B,gBAAgB+B,IAAM3D,KAAKL,QAAQN,yBACpDW,KAAK0B,WAAW+G,UAAYzI,KAAKL,QAAQL,uBAEzCU,KAAK0B,WAAWgH,SAAS,GAAI1I,KAAKL,QAAQL,uBAC1CU,KAAKmB,UAAYnB,KAAKL,QAAQL,sBAAwBmH,EAAMgB,cAE5DzH,KAAK4B,gBAAgB+G,OAAS3C,EAAE2B,QAAU3H,KAAKL,QAAQN,yBACvDW,KAAK0B,WAAW+G,UACZzI,KAAK0B,WAAWkH,aACZ5I,KAAK4B,gBAAgBY,OACrBxC,KAAKL,QAAQL,wBAErBU,KAAK0B,WAAWgH,SAAS,EAAG1I,KAAKL,QAAQL,uBACzCU,KAAKmB,UAAYnB,KAAKL,QAAQL,sBAAwBmH,EAAMgB,cAI5DzB,EAAEuB,QAAUvH,KAAK4B,gBAAgB8B,KAAO1D,KAAKL,QAAQN,yBACrDW,KAAK0B,WAAWmH,WAAa7I,KAAKL,QAAQL,uBAE1CU,KAAK0B,WAAWgH,UAAU1I,KAAKL,QAAQL,sBAAuB,GAC9DU,KAAKkB,UAAYlB,KAAKL,QAAQL,sBAAwBmH,EAAMgB,cAE5DzH,KAAK4B,gBAAgBkH,MAAQ9C,EAAEuB,QAAUvH,KAAKL,QAAQN,yBACtDW,KAAK0B,WAAWmH,WACZ7I,KAAK0B,WAAWqH,YACZ/I,KAAK4B,gBAAgBW,MACrBvC,KAAKL,QAAQL,wBAErBU,KAAK0B,WAAWgH,SAAS1I,KAAKL,QAAQL,sBAAuB,GAC7DU,KAAKkB,UAAYlB,KAAKL,QAAQL,sBAAwBmH,EAAMgB,cAEhEzH,KAAKQ,OAAOyC,MAAMS,KAAO6E,EAAK,KAC9BvI,KAAKQ,OAAOyC,MAAMU,IAAM6E,EAAK,KAC7BhK,GACH,CACJ,CAKD,OAAA+H,CAAQP,GACJ,GAAKhG,KAAKN,GAAG8G,eAAb,CAMA,GAHIxG,KAAK2G,gBACL3G,KAAKN,GAAGsJ,wBAERhJ,KAAKsB,QAAS,CAWd,GAV0B,GAAtBtB,KAAKoB,gBACL7C,EAAEE,EAAEwJ,aAAajI,KAAKoB,eACtBpB,KAAKoB,cAAgB,EACrBpB,KAAKuE,eAEiB,GAAtBvE,KAAKqB,gBACL9C,EAAEE,EAAEyJ,cAAclI,KAAKqB,eACvBrB,KAAKqB,cAAgB,EACrBrB,KAAKuE,eAELvE,KAAKuB,MAAO,CACZ,IAAI0H,EAAWjJ,KAAKa,YAChBC,EAAcd,KAAKc,YACnBC,EAAgBf,KAAKe,cACzBf,KAAKkJ,UAAUD,EAAUnI,EAAaC,EACzC,CACDf,KAAKkE,aACR,CACDlE,KAAK4B,gBAAkB,KACvB5B,KAAKuB,OAAQ,EACbvB,KAAKsB,SAAU,CAzBd,CA0BJ,CAMD,iBAAAsF,CAAkBpD,GACd,OACIA,IAAOxD,KAAKN,GAAGS,KAAK+B,SACpBsB,IAAOxD,KAAKN,GAAGS,KAAKwB,SACpB6B,IAAOxD,KAAKN,GAAGS,KAAK2F,UAEb,KAEsB,WAA7BtC,EAAG2F,QAAQC,cACJ5F,EAEJxD,KAAK4G,kBAAkBpD,EAAGwB,WACpC,CAED,kBAAAqD,GACI,IAAIgB,EAAKrJ,KAAKQ,OAAOkH,WACjB4B,EAAKtJ,KAAKQ,OAAOoH,UACrB,GAAIyB,IAAOrJ,KAAKS,YAAc6I,IAAOtJ,KAAKU,WACtC,OAEJV,KAAKS,WAAa4I,EAClBrJ,KAAKU,WAAa4I,EAElB,IAAIC,EACAvJ,KAAKS,WAAaT,KAAKW,SAAW,GAAKX,KAAKwJ,aACtCnL,EAAM,QAACoL,UAAUX,MACjBzK,EAAM,QAACoL,UAAU/F,KAEvB5C,EADmBd,KAAK0J,+BAA+BH,IACrBvJ,KAAK2J,kBAAkBJ,GAC7D,GAAMzI,EAAa,CACf,IAAI8I,EAAS5J,KAAK6J,mBAAmB/I,EAAayI,GAC9CjF,EAAUjG,EAAAA,QAAO4I,KAAK6C,UAAU9J,KAAKa,YAAaC,GACtDd,KAAKmE,cAAcyF,EAAOG,GAAIH,EAAOI,GAAI1F,GACzCtE,KAAKc,YAAcA,EACnBd,KAAKe,cAAgBwI,CACxB,CACJ,CAKD,UAAAC,GACI,IAAIS,EAAOjK,KAAKN,GAAGwK,WACfC,EAAgBF,EAAKG,eACrBC,EAAYJ,EAAKK,WACrB,OAAOH,EAAczF,EAAI2F,EAAU5L,EAAI,CAC1C,CAOD,8BAAAiL,CAA+BD,GAC3B,IAAIc,EAAavK,KAAKQ,OAAO8G,wBACzB5C,EAAI6F,EAAW7F,EAAK6F,EAAWhI,OAAS,EAAIkH,GAAc,EAC1De,GAAUxK,KAAKN,GAAGC,QAAQ8K,OAAOC,OAAS1K,KAAKN,GAAGC,QAAQ8K,OAAOE,QAAUlB,EAC3EmB,EAASL,EAAW/H,OACpBoH,EAAS,CACT,CAAClF,EAAG6F,EAAW5F,GACf,CAACD,EAAG6F,EAAW5F,EAAIiG,EAAS,GAC5B,CAAClG,EAAG6F,EAAW5F,EAAIiG,GACnB,CAAClG,EAAI8F,EAAS,EAAGD,EAAW5F,GAC5B,CAACD,EAAI8F,EAAS,EAAGD,EAAW5F,EAAIiG,EAAS,GACzC,CAAClG,EAAI8F,EAAS,EAAGD,EAAW5F,EAAIiG,GAChC,CAAClG,EAAI8F,EAAQD,EAAW5F,GACxB,CAACD,EAAI8F,EAAQD,EAAW5F,EAAIiG,EAAS,GACrC,CAAClG,EAAI8F,EAAQD,EAAW5F,EAAIiG,IAEhC,IAAK,MAAMC,KAAKjB,EAAQ,CACpB,IAAIkB,EAAI9K,KAAK+K,+BAA+BF,EAAE,GAAIA,EAAE,IACpD,GAAMC,EACF,OAAOA,CAEd,CACJ,CAQD,8BAAAC,CAA+BrG,EAAGC,GAC9B,OAAOpG,EAAEK,EACJoM,kBAAkBtG,EAAGC,GACrBsG,QACGvG,GAAmB,WAAdA,EAAEyE,SAAwBzE,EAAEpB,YAActD,KAAKL,QAAQJ,yBAE/D2L,KAAI1H,GAAMxD,KAAKN,GAAGS,KAAK6G,kBAAkBxD,KACzC0H,KAAIC,GAAMA,GAAMnL,KAAKN,GAAG0L,KAAKC,MAAMF,KACnCD,KAAIJ,GAAKA,GAAKA,EAAEQ,SAChBC,MAAKT,GAAKA,GAClB,CAOD,iBAAAnB,CAAkBF,GACd,OAAO+B,OAAOC,OAAOzL,KAAKN,GAAG0L,KAAKC,OAC7BJ,QAAOH,GAAKA,EAAErB,WAAaA,GAAaqB,EAAE3D,SAC1C8D,QAAOH,GAAK9K,KAAKN,GAAG+K,OAAOiB,WAAWZ,KACtCG,QAAOH,GAAK9K,KAAK2L,sBAAsBb,EAAGrB,KAC1CyB,KAAIJ,IAAC,CAAO7D,KAAM6D,EAAGc,SAAU5L,KAAK6L,eAAef,EAAGrB,OACtDqC,QACG,CAACC,EAAMC,IACID,EAAKH,SAAWI,EAAKJ,SAAWG,EAAOC,GAElD,CAAE/E,KAAMjH,KAAKN,GAAGwK,WAAY0B,SAAUK,OAAOC,YAC/CjF,IACT,CAQD,qBAAA0E,CAAsB1E,EAAMkF,GACxB,OACKA,GAAO9N,EAAM,QAACoL,UAAUX,OAAS9I,KAAKoM,wBAAwBnF,GAAQ,GACtEkF,GAAO9N,EAAAA,QAAOoL,UAAU/F,MAAQ1D,KAAKqM,uBAAuBpF,GAAQ,CAE5E,CAOD,uBAAAmF,CAAwBnF,GACpB,OAAOjH,KAAKS,WAAawG,EAAKmD,eAAe1F,EAAIuC,EAAKqD,WAAW7L,CACpE,CAOD,sBAAA4N,CAAuBpF,GACnB,OAAOA,EAAKmD,eAAe1F,EAAI1E,KAAKS,WAAaT,KAAKW,QACzD,CAOD,2BAAA2L,CAA4BrF,GACxB,OAAOjH,KAAKU,WAAaV,KAAKY,SAAW,EAAIqG,EAAKmD,eAAezF,EAAIsC,EAAKqD,WAAWhI,EAAI,CAC5F,CAQD,cAAAuJ,CAAe5E,EAAMkF,GAMjB,OAJIA,IAAQ9N,EAAAA,QAAOoL,UAAUX,MACnBhB,KAAKyE,IAAIvM,KAAKoM,wBAAwBnF,IACtCa,KAAKyE,IAAIvM,KAAKqM,uBAAuBpF,KAC9Ba,KAAKyE,IAAIvM,KAAKsM,4BAA4BrF,GAE9D,CAQD,kBAAA4C,CAAmB5C,EAAMkF,GACrB,IAAIK,EAAKvF,EAAKqD,WACVmC,EAAKxF,EAAKmD,eACVsC,EAASzF,EAAKE,OACZsF,EAAG/H,EAAI8H,EAAG/N,EAAI,EACdgO,EAAG/H,EAAK8H,EAAG/N,GAAK,EAAI0N,GAAQ,EAAInM,KAAKL,QAAQX,WAAamN,EAC5DQ,EAASF,EAAG9H,EAAI6H,EAAGlK,EAAI,EAI3B,MAAO,CACHyH,GAAI,CAAErF,EAHN1E,KAAKS,WAAcT,KAAKW,UAAY,EAAIwL,GAAQ,EAAInM,KAAKL,QAAQX,WAAamN,EAG3DxH,EAFR3E,KAAKU,WAAaV,KAAKY,SAAW,GAG7CoJ,GAAI,CAAEtF,EAAGgI,EAAQ/H,EAAGgI,GAE3B,CAQD,SAAAzD,CAAUD,EAAUnI,EAAaC,GAC7B,IAAIH,EAAWZ,KAAKQ,OAAOoH,UAC3B,GAAM9G,GAAiBmI,IAAa5K,UAAO4I,KAAK6C,UAAUb,EAAUnI,GAAc,CAE9E,GAAId,KAAKL,QAAQiN,eAAuD,mBAA/B5M,KAAKL,QAAQiN,cAA8B,CAEhF,IADgB5M,KAAKL,QAAQiN,cAAc3D,EAAUnI,GAMjD,OAHAd,KAAKa,YAAc,KACnBb,KAAKc,YAAc,UACnBd,KAAKe,cAAgB,KAG5B,CASD,IANA,IAAI8L,EAAgB/L,EAAYgM,SAC5BC,EAAKF,EAAcG,OACnB/F,EAAO,KACPgG,EAAUhB,OAAOC,UACjBgB,EAAc,KACdC,EAAW,SACRJ,KAEH,IADA9F,EAAO4F,EAAcE,IACZtD,WAAa1I,GAAiBkG,EAAKkE,IAAMlC,EAASkC,GAAI,CAC3D,IAAIiC,EAAKnG,EAAKmD,eAAezF,EAAI/D,EAC7BwM,EAAK,GAAKA,EAAKH,IACfA,EAAUG,EACVF,EAAcjG,EACdkG,EAAW,UAElB,CAECD,IACFC,EAAWD,EAAY/B,IAE3BnL,KAAKN,GAAGwJ,UAAUD,EAASkC,GAAIgC,EAAUrM,EAAYqK,GAAIpK,EAC5D,CACDf,KAAKa,YAAc,KACnBb,KAAKc,YAAc,KACnBd,KAAKe,cAAgB,IACxB,CAMD,eAAAsM,CAAgBC,EAAMlG,GACdkG,IAASjP,EAAAA,QAAOkP,WAAWtL,QAC3BjC,KAAKiC,QAEZ,EAOO,MAACuL,EAAmB,IAAInP,EAAAA,QAAOoP,OAAO,kBAAkB,SAAU/N,EAAIC,GAC9E,IAAIkG,EAAK,IAAIrG,EAAcE,EAAIC,GAC/BkG,EAAGhE,OACHnC,EAAGgO,oBAAmB,SAAUJ,EAAMlG,GAClCvB,EAAGwH,gBAAgBlH,KAAKN,EAAIyH,EAAMlG,EAC1C,GACA,IAEA/I,EAAAA,QAAOsP,gBAAgBH"}
1
+ {"version":3,"file":"jsmind.draggable-node.js","sources":["../src/plugins/jsmind.draggable-node.js"],"sourcesContent":["/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport jsMind from '@umbraci/jsmind';\n\nif (!jsMind) {\n throw new Error('jsMind is not defined');\n}\n\nconst $ = jsMind.$;\n\nconst clear_selection =\n 'getSelection' in $.w\n ? function () {\n $.w.getSelection().removeAllRanges();\n }\n : function () {\n $.d.selection.empty();\n };\n\n/**\n * Default options for draggable node plugin.\n * @typedef {Object} DraggableNodeOptions\n * @property {number} [line_width]\n * @property {string} [line_color]\n * @property {string} [line_color_invalid]\n * @property {number} [lookup_delay]\n * @property {number} [lookup_interval]\n * @property {number} [scrolling_trigger_width]\n * @property {number} [scrolling_step_length]\n * @property {string} [shadow_node_class_name]\n * @property {(draggedNode:import('../jsmind.node.js').Node, targetNode:import('../jsmind.node.js').Node|null)=>boolean} [validate_drag]\n */\nconst DEFAULT_OPTIONS = {\n line_width: 5,\n line_color: 'rgba(0,0,0,0.3)',\n line_color_invalid: 'rgba(255,51,51,0.6)',\n lookup_delay: 200,\n lookup_interval: 100,\n scrolling_trigger_width: 20,\n scrolling_step_length: 10,\n shadow_node_class_name: 'jsmind-draggable-shadow-node',\n};\n\n/**\n * Draggable node plugin for jsMind.\n */\nexport class DraggableNode {\n /**\n * Create draggable node plugin instance.\n * @param {import('../jsmind.js').default} jm - jsMind instance\n * @param {Partial<DraggableNodeOptions>} options - Plugin options\n */\n constructor(jm, options) {\n var opts = {};\n jsMind.util.json.merge(opts, DEFAULT_OPTIONS);\n jsMind.util.json.merge(opts, options);\n\n this.version = '0.4.0';\n /** @type {import('../jsmind.js').default} */\n this.jm = jm;\n /** @type {DraggableNodeOptions} */\n this.options = opts;\n /** @type {boolean} */\n this.is_svg_engine = jm.view.opts.engine === 'svg';\n /** @type {HTMLCanvasElement|SVGSVGElement|null} */\n this.e_canvas = null;\n /** @type {CanvasRenderingContext2D|null} */\n this.canvas_ctx = null;\n /** @type {SVGPathElement|null} */\n this.helper_line = null;\n /** @type {HTMLElement|null} */\n this.shadow = null;\n /** @type {number} */\n this.shadow_p_x = 0;\n /** @type {number} */\n this.shadow_p_y = 0;\n /** @type {number} */\n this.shadow_w = 0;\n /** @type {number} */\n this.shadow_h = 0;\n /** @type {import('../jsmind.node.js').Node|null} */\n this.active_node = null;\n /** @type {import('../jsmind.node.js').Node|null} */\n this.target_node = null;\n /** @type {number|null} */\n this.target_direct = null;\n /** @type {number} */\n this.client_w = 0;\n /** @type {number} */\n this.client_h = 0;\n /** @type {number} */\n this.offset_x = 0;\n /** @type {number} */\n this.offset_y = 0;\n /** @type {number} */\n this.hlookup_delay = 0;\n /** @type {number} */\n this.hlookup_timer = 0;\n /** @type {boolean} */\n this.capture = false;\n /** @type {boolean} */\n this.moved = false;\n /** @type {boolean} */\n this.canvas_draggable = jm.get_view_draggable();\n /** @type {HTMLElement} */\n this.view_panel = jm.view.e_panel;\n /** @type {DOMRect|null} */\n this.view_panel_rect = null;\n }\n /** Initialize the draggable node plugin. */\n init() {\n this.create_canvas();\n this.create_shadow();\n this.event_bind();\n }\n /** Resize canvas/SVG and shadow elements. */\n resize() {\n this.jm.view.e_nodes.appendChild(this.shadow);\n if (this.is_svg_engine) {\n this.e_canvas.setAttribute('width', this.jm.view.size.w);\n this.e_canvas.setAttribute('height', this.jm.view.size.h);\n } else {\n this.e_canvas.width = this.jm.view.size.w;\n this.e_canvas.height = this.jm.view.size.h;\n }\n }\n /** Create canvas or SVG for drawing drag lines. */\n create_canvas() {\n if (this.is_svg_engine) {\n // Create SVG element for helper lines\n var svg = this._create_svg_element('svg');\n svg.setAttribute('class', 'jsmind-draggable-helper');\n svg.setAttribute('style', 'position: absolute; top: 0; left: 0; pointer-events: none;');\n this.jm.view.e_panel.appendChild(svg);\n this.e_canvas = svg;\n } else {\n // Create Canvas element for helper lines\n var c = $.c('canvas');\n this.jm.view.e_panel.appendChild(c);\n var ctx = c.getContext('2d');\n this.e_canvas = c;\n this.canvas_ctx = ctx;\n }\n }\n /**\n * Create SVG element with proper namespace.\n * @param {string} tag - SVG tag name\n * @returns {SVGElement}\n * @private\n */\n _create_svg_element(tag) {\n return $.d.createElementNS('http://www.w3.org/2000/svg', tag);\n }\n create_shadow() {\n var s = $.c('jmnode');\n s.style.visibility = 'hidden';\n s.style.zIndex = '3';\n s.style.cursor = 'move';\n s.style.opacity = '0.7';\n s.className = this.options.shadow_node_class_name;\n this.shadow = s;\n }\n /**\n * Reset shadow element style and cache its size.\n * @param {HTMLElement} el - The node element to mirror as shadow\n */\n reset_shadow(el) {\n var s = this.shadow.style;\n this.shadow.innerHTML = el.innerHTML;\n s.left = el.style.left;\n s.top = el.style.top;\n s.width = el.style.width;\n s.height = el.style.height;\n s.backgroundImage = el.style.backgroundImage;\n s.backgroundSize = el.style.backgroundSize;\n s.transform = el.style.transform;\n this.shadow_w = this.shadow.clientWidth;\n this.shadow_h = this.shadow.clientHeight;\n }\n /** Show the shadow element. */\n show_shadow() {\n if (!this.moved) {\n this.shadow.style.visibility = 'visible';\n }\n }\n /** Hide the shadow element. */\n hide_shadow() {\n this.shadow.style.visibility = 'hidden';\n }\n /**\n * Draw a helper line between the shadow and target node.\n * @param {{x:number,y:number}} shadow_p - Shadow anchor point\n * @param {{x:number,y:number}} node_p - Target node anchor point\n * @param {boolean} invalid - Whether current target is invalid\n */\n magnet_shadow(shadow_p, node_p, invalid) {\n this.clear_lines();\n var color = invalid ? this.options.line_color_invalid : this.options.line_color;\n\n if (this.is_svg_engine) {\n this.svg_draw_line(shadow_p.x, shadow_p.y, node_p.x, node_p.y, color);\n } else {\n this.canvas_ctx.lineWidth = this.options.line_width;\n this.canvas_ctx.strokeStyle = color;\n this.canvas_ctx.lineCap = 'round';\n this.canvas_lineto(shadow_p.x, shadow_p.y, node_p.x, node_p.y);\n }\n }\n /** Clear helper lines from canvas or SVG. */\n clear_lines() {\n if (this.is_svg_engine) {\n if (this.helper_line && this.helper_line.parentNode) {\n this.e_canvas.removeChild(this.helper_line);\n this.helper_line = null;\n }\n } else {\n this.canvas_ctx.clearRect(0, 0, this.jm.view.size.w, this.jm.view.size.h);\n }\n }\n /**\n * Draw a straight helper line on canvas.\n * @param {number} x1\n * @param {number} y1\n * @param {number} x2\n * @param {number} y2\n */\n canvas_lineto(x1, y1, x2, y2) {\n this.canvas_ctx.beginPath();\n this.canvas_ctx.moveTo(x1, y1);\n this.canvas_ctx.lineTo(x2, y2);\n this.canvas_ctx.stroke();\n }\n /**\n * Draw a helper line on SVG using bezier curve.\n * Reuses the line drawing logic from SvgGraph.\n * @param {number} x1 - Start x coordinate\n * @param {number} y1 - Start y coordinate\n * @param {number} x2 - End x coordinate\n * @param {number} y2 - End y coordinate\n * @param {string} color - Line color\n */\n svg_draw_line(x1, y1, x2, y2, color) {\n // Create SVG path element for helper line\n this.helper_line = this._create_svg_element('path');\n this.helper_line.setAttribute('stroke', color);\n this.helper_line.setAttribute('stroke-width', this.options.line_width);\n this.helper_line.setAttribute('fill', 'transparent');\n this.helper_line.setAttribute('stroke-linecap', 'round');\n\n // Draw bezier curve (same as SvgGraph._bezier_to)\n this._svg_bezier_to(this.helper_line, x1, y1, x2, y2);\n\n // Add to SVG container\n this.e_canvas.appendChild(this.helper_line);\n }\n /**\n * Draw bezier curve to SVG path element.\n * Reuses logic from SvgGraph._bezier_to.\n * @param {SVGPathElement} path - SVG path element\n * @param {number} x1 - Start x coordinate\n * @param {number} y1 - Start y coordinate\n * @param {number} x2 - End x coordinate\n * @param {number} y2 - End y coordinate\n * @private\n */\n _svg_bezier_to(path, x1, y1, x2, y2) {\n path.setAttribute(\n 'd',\n 'M ' +\n x1 +\n ' ' +\n y1 +\n ' C ' +\n (x1 + ((x2 - x1) * 2) / 3) +\n ' ' +\n y1 +\n ', ' +\n x1 +\n ' ' +\n y2 +\n ', ' +\n x2 +\n ' ' +\n y2\n );\n }\n /** Bind mouse/touch events for dragging. */\n event_bind() {\n var jd = this;\n var container = this.jm.view.container;\n $.on(container, 'mousedown', function (e) {\n if (e.button === 0) {\n jd.dragstart.call(jd, e);\n }\n });\n $.on(container, 'mousemove', function (e) {\n if (e.movementX !== 0 || e.movementY !== 0) {\n jd.drag.call(jd, e);\n }\n });\n $.on(container, 'mouseup', function (e) {\n jd.dragend.call(jd, e);\n });\n $.on(container, 'touchstart', function (e) {\n jd.dragstart.call(jd, e);\n });\n $.on(container, 'touchmove', function (e) {\n jd.drag.call(jd, e);\n });\n $.on(container, 'touchend', function (e) {\n jd.dragend.call(jd, e);\n });\n }\n /**\n * Begin dragging interaction.\n * @param {MouseEvent|TouchEvent} e - Pointer down event\n */\n dragstart(e) {\n if (!this.jm.get_editable()) {\n return;\n }\n if (this.capture) {\n return;\n }\n var jview = this.jm.view;\n if (jview.is_editing()) {\n return;\n }\n this.active_node = null;\n this.view_draggable = this.jm.get_view_draggable();\n\n var el = this.find_node_element(e.target);\n if (!el) {\n return;\n }\n if (this.view_draggable) {\n this.jm.disable_view_draggable();\n }\n var nodeid = jview.get_binded_nodeid(el);\n if (!!nodeid) {\n var node = this.jm.get_node(nodeid);\n if (!node.isroot) {\n // 检查节点是否允许拖拽\n if (node.data && node.data.draggable === false) {\n return;\n }\n this.reset_shadow(el);\n this.view_panel_rect = this.view_panel.getBoundingClientRect();\n this.active_node = node;\n this.offset_x =\n (e.clientX || e.touches[0].clientX) / jview.zoom_current - el.offsetLeft;\n this.offset_y =\n (e.clientY || e.touches[0].clientY) / jview.zoom_current - el.offsetTop;\n this.client_hw = Math.floor(el.clientWidth / 2);\n this.client_hh = Math.floor(el.clientHeight / 2);\n if (this.hlookup_delay != 0) {\n $.w.clearTimeout(this.hlookup_delay);\n }\n if (this.hlookup_timer != 0) {\n $.w.clearInterval(this.hlookup_timer);\n }\n var jd = this;\n this.hlookup_delay = $.w.setTimeout(function () {\n jd.hlookup_delay = 0;\n jd.hlookup_timer = $.w.setInterval(function () {\n jd.lookup_target_node.call(jd);\n }, jd.options.lookup_interval);\n }, this.options.lookup_delay);\n jd.capture = true;\n }\n }\n }\n /**\n * Drag handler to move shadow and auto-scroll container.\n * @param {MouseEvent|TouchEvent} e - Pointer move event\n */\n drag(e) {\n if (!this.jm.get_editable()) {\n return;\n }\n if (this.capture) {\n e.preventDefault();\n this.show_shadow();\n this.moved = true;\n clear_selection();\n var jview = this.jm.view;\n var px = (e.clientX || e.touches[0].clientX) / jview.zoom_current - this.offset_x;\n var py = (e.clientY || e.touches[0].clientY) / jview.zoom_current - this.offset_y;\n // scrolling container axisY if drag nodes exceeding container\n if (\n e.clientY - this.view_panel_rect.top < this.options.scrolling_trigger_width &&\n this.view_panel.scrollTop > this.options.scrolling_step_length\n ) {\n this.view_panel.scrollBy(0, -this.options.scrolling_step_length);\n this.offset_y += this.options.scrolling_step_length / jview.zoom_current;\n } else if (\n this.view_panel_rect.bottom - e.clientY < this.options.scrolling_trigger_width &&\n this.view_panel.scrollTop <\n this.view_panel.scrollHeight -\n this.view_panel_rect.height -\n this.options.scrolling_step_length\n ) {\n this.view_panel.scrollBy(0, this.options.scrolling_step_length);\n this.offset_y -= this.options.scrolling_step_length / jview.zoom_current;\n }\n // scrolling container axisX if drag nodes exceeding container\n if (\n e.clientX - this.view_panel_rect.left < this.options.scrolling_trigger_width &&\n this.view_panel.scrollLeft > this.options.scrolling_step_length\n ) {\n this.view_panel.scrollBy(-this.options.scrolling_step_length, 0);\n this.offset_x += this.options.scrolling_step_length / jview.zoom_current;\n } else if (\n this.view_panel_rect.right - e.clientX < this.options.scrolling_trigger_width &&\n this.view_panel.scrollLeft <\n this.view_panel.scrollWidth -\n this.view_panel_rect.width -\n this.options.scrolling_step_length\n ) {\n this.view_panel.scrollBy(this.options.scrolling_step_length, 0);\n this.offset_x -= this.options.scrolling_step_length / jview.zoom_current;\n }\n this.shadow.style.left = px + 'px';\n this.shadow.style.top = py + 'px';\n clear_selection();\n }\n }\n /**\n * Finish dragging, move the node if applicable.\n * @param {MouseEvent|TouchEvent} e - Pointer up event\n */\n dragend(e) {\n if (!this.jm.get_editable()) {\n return;\n }\n if (this.view_draggable) {\n this.jm.enable_view_draggable();\n }\n if (this.capture) {\n if (this.hlookup_delay != 0) {\n $.w.clearTimeout(this.hlookup_delay);\n this.hlookup_delay = 0;\n this.clear_lines();\n }\n if (this.hlookup_timer != 0) {\n $.w.clearInterval(this.hlookup_timer);\n this.hlookup_timer = 0;\n this.clear_lines();\n }\n if (this.moved) {\n var src_node = this.active_node;\n var target_node = this.target_node;\n var target_direct = this.target_direct;\n this.move_node(src_node, target_node, target_direct);\n }\n this.hide_shadow();\n }\n this.view_panel_rect = null;\n this.moved = false;\n this.capture = false;\n }\n /**\n * Find the closest node element from an event target.\n * @param {HTMLElement} el - Current DOM element\n * @returns {HTMLElement|null} Matched node element or null\n */\n find_node_element(el) {\n if (\n el === this.jm.view.e_nodes ||\n el === this.jm.view.e_panel ||\n el === this.jm.view.container\n ) {\n return null;\n }\n if (el.tagName.toLowerCase() === 'jmnode') {\n return el;\n }\n return this.find_node_element(el.parentNode);\n }\n /** Recompute target node under the shadow and draw helper. */\n lookup_target_node() {\n let sx = this.shadow.offsetLeft;\n let sy = this.shadow.offsetTop;\n if (sx === this.shadow_p_x && sy === this.shadow_p_y) {\n return;\n }\n this.shadow_p_x = sx;\n this.shadow_p_y = sy;\n\n let target_direction =\n this.shadow_p_x + this.shadow_w / 2 >= this.get_root_x()\n ? jsMind.direction.right\n : jsMind.direction.left;\n let overlapping_node = this.lookup_overlapping_node_parent(target_direction);\n let target_node = overlapping_node || this.lookup_close_node(target_direction);\n if (!!target_node) {\n let points = this.calc_point_of_node(target_node, target_direction);\n let invalid = jsMind.node.inherited(this.active_node, target_node);\n this.magnet_shadow(points.sp, points.np, invalid);\n this.target_node = target_node;\n this.target_direct = target_direction;\n }\n }\n /**\n * Get X coordinate of root node center.\n * @returns {number}\n */\n get_root_x() {\n let root = this.jm.get_root();\n let root_location = root.get_location();\n let root_size = root.get_size();\n return root_location.x + root_size.w / 2;\n }\n\n /**\n * Lookup overlapping node's parent near the shadow position.\n * @param {number} direction - Direction constant\n * @returns {import('../jsmind.node.js').Node|null}\n */\n lookup_overlapping_node_parent(direction) {\n let shadowRect = this.shadow.getBoundingClientRect();\n let x = shadowRect.x + (shadowRect.width * (1 - direction)) / 2;\n let deltaX = (this.jm.options.layout.hspace + this.jm.options.layout.pspace) * direction;\n let deltaY = shadowRect.height;\n let points = [\n [x, shadowRect.y],\n [x, shadowRect.y + deltaY / 2],\n [x, shadowRect.y + deltaY],\n [x + deltaX / 2, shadowRect.y],\n [x + deltaX / 2, shadowRect.y + deltaY / 2],\n [x + deltaX / 2, shadowRect.y + deltaY],\n [x + deltaX, shadowRect.y],\n [x + deltaX, shadowRect.y + deltaY / 2],\n [x + deltaX, shadowRect.y + deltaY],\n ];\n for (const p of points) {\n let n = this.lookup_node_parent_by_location(p[0], p[1]);\n if (!!n) {\n return n;\n }\n }\n }\n\n /**\n * Find node's parent by a screen location.\n * @param {number} x - Client X\n * @param {number} y - Client Y\n * @returns {import('../jsmind.node.js').Node|null}\n */\n lookup_node_parent_by_location(x, y) {\n return $.d\n .elementsFromPoint(x, y)\n .filter(\n x => x.tagName === 'JMNODE' && x.className !== this.options.shadow_node_class_name\n )\n .map(el => this.jm.view.get_binded_nodeid(el))\n .map(id => id && this.jm.mind.nodes[id])\n .map(n => n && n.parent)\n .find(n => n);\n }\n\n /**\n * Lookup the closest node along a direction.\n * @param {number} direction\n * @returns {import('../jsmind.node.js').Node}\n */\n lookup_close_node(direction) {\n return Object.values(this.jm.mind.nodes)\n .filter(n => n.direction == direction || n.isroot)\n .filter(n => this.jm.layout.is_visible(n))\n .filter(n => this.shadow_on_target_side(n, direction))\n .map(n => ({ node: n, distance: this.shadow_to_node(n, direction) }))\n .reduce(\n (prev, curr) => {\n return prev.distance < curr.distance ? prev : curr;\n },\n { node: this.jm.get_root(), distance: Number.MAX_VALUE }\n ).node;\n }\n\n /**\n * Check if shadow is on the target side of a node.\n * @param {import('../jsmind.node.js').Node} node\n * @param {number} dir\n * @returns {boolean}\n */\n shadow_on_target_side(node, dir) {\n return (\n (dir == jsMind.direction.right && this.shadow_to_right_of_node(node) > 0) ||\n (dir == jsMind.direction.left && this.shadow_to_left_of_node(node) > 0)\n );\n }\n\n /**\n * Distance from shadow to the right side of a node.\n * @param {import('../jsmind.node.js').Node} node\n * @returns {number}\n */\n shadow_to_right_of_node(node) {\n return this.shadow_p_x - node.get_location().x - node.get_size().w;\n }\n\n /**\n * Distance from shadow to the left side of a node.\n * @param {import('../jsmind.node.js').Node} node\n * @returns {number}\n */\n shadow_to_left_of_node(node) {\n return node.get_location().x - this.shadow_p_x - this.shadow_w;\n }\n\n /**\n * Vertical distance between shadow centerline and node centerline.\n * @param {import('../jsmind.node.js').Node} node\n * @returns {number}\n */\n shadow_to_base_line_of_node(node) {\n return this.shadow_p_y + this.shadow_h / 2 - node.get_location().y - node.get_size().h / 2;\n }\n\n /**\n * Manhattan distance to a node along a direction.\n * @param {import('../jsmind.node.js').Node} node\n * @param {number} dir\n * @returns {number}\n */\n shadow_to_node(node, dir) {\n let distance_x =\n dir === jsMind.direction.right\n ? Math.abs(this.shadow_to_right_of_node(node))\n : Math.abs(this.shadow_to_left_of_node(node));\n let distance_y = Math.abs(this.shadow_to_base_line_of_node(node));\n return distance_x + distance_y;\n }\n\n /**\n * Calculate connection points of a node and the shadow.\n * @param {import('../jsmind.node.js').Node} node\n * @param {number} dir\n * @returns {{sp:{x:number,y:number}, np:{x:number,y:number}}}\n */\n calc_point_of_node(node, dir) {\n let ns = node.get_size();\n let nl = node.get_location();\n let node_x = node.isroot\n ? nl.x + ns.w / 2\n : nl.x + (ns.w * (1 + dir)) / 2 + this.options.line_width * dir;\n let node_y = nl.y + ns.h / 2;\n let shadow_x =\n this.shadow_p_x + (this.shadow_w * (1 - dir)) / 2 - this.options.line_width * dir;\n let shadow_y = this.shadow_p_y + this.shadow_h / 2;\n return {\n sp: { x: shadow_x, y: shadow_y },\n np: { x: node_x, y: node_y },\n };\n }\n\n /**\n * Move a node to a new parent/position.\n * @param {import('../jsmind.node.js').Node} src_node\n * @param {import('../jsmind.node.js').Node|null} target_node\n * @param {number|null} target_direct\n */\n move_node(src_node, target_node, target_direct) {\n var shadow_h = this.shadow.offsetTop;\n if (!!target_node && !!src_node && !jsMind.node.inherited(src_node, target_node)) {\n // Call validate_drag function if provided, to validate the drag operation\n if (this.options.validate_drag && typeof this.options.validate_drag === 'function') {\n const isValid = this.options.validate_drag(src_node, target_node);\n if (!isValid) {\n // Drag operation is not allowed, cleanup and return\n this.active_node = null;\n this.target_node = null;\n this.target_direct = null;\n return;\n }\n }\n\n // lookup before_node\n var sibling_nodes = target_node.children;\n var sc = sibling_nodes.length;\n var node = null;\n var delta_y = Number.MAX_VALUE;\n var node_before = null;\n var beforeid = '_last_';\n while (sc--) {\n node = sibling_nodes[sc];\n if (node.direction == target_direct && node.id != src_node.id) {\n var dy = node.get_location().y - shadow_h;\n if (dy > 0 && dy < delta_y) {\n delta_y = dy;\n node_before = node;\n beforeid = '_first_';\n }\n }\n }\n if (!!node_before) {\n beforeid = node_before.id;\n }\n this.jm.move_node(src_node.id, beforeid, target_node.id, target_direct);\n }\n this.active_node = null;\n this.target_node = null;\n this.target_direct = null;\n }\n /**\n * Handle jsMind events.\n * @param {number|string} type - Event type\n * @param {object} [data] - Event data\n */\n jm_event_handle(type, data) {\n if (type === jsMind.event_type.resize) {\n this.resize();\n }\n }\n}\n\n/**\n * Draggable node plugin registration.\n * @type {import('../jsmind.plugin.js').Plugin<Partial<DraggableNodeOptions>>}\n */\nexport const draggable_plugin = new jsMind.plugin('draggable_node', function (jm, options) {\n var jd = new DraggableNode(jm, options);\n jd.init();\n jm.add_event_listener(function (type, data) {\n jd.jm_event_handle.call(jd, type, data);\n });\n});\n\njsMind.register_plugin(draggable_plugin);\n\nexport default DraggableNode;\n"],"names":["jsMind","Error","$","clear_selection","w","getSelection","removeAllRanges","d","selection","empty","DEFAULT_OPTIONS","line_width","line_color","line_color_invalid","lookup_delay","lookup_interval","scrolling_trigger_width","scrolling_step_length","shadow_node_class_name","DraggableNode","constructor","jm","options","opts","util","json","merge","this","version","is_svg_engine","view","engine","e_canvas","canvas_ctx","helper_line","shadow","shadow_p_x","shadow_p_y","shadow_w","shadow_h","active_node","target_node","target_direct","client_w","client_h","offset_x","offset_y","hlookup_delay","hlookup_timer","capture","moved","canvas_draggable","get_view_draggable","view_panel","e_panel","view_panel_rect","init","create_canvas","create_shadow","event_bind","resize","e_nodes","appendChild","setAttribute","size","h","width","height","svg","_create_svg_element","c","ctx","getContext","tag","createElementNS","s","style","visibility","zIndex","cursor","opacity","className","reset_shadow","el","innerHTML","left","top","backgroundImage","backgroundSize","transform","clientWidth","clientHeight","show_shadow","hide_shadow","magnet_shadow","shadow_p","node_p","invalid","clear_lines","color","svg_draw_line","x","y","lineWidth","strokeStyle","lineCap","canvas_lineto","parentNode","removeChild","clearRect","x1","y1","x2","y2","beginPath","moveTo","lineTo","stroke","_svg_bezier_to","path","jd","container","on","e","button","dragstart","call","movementX","movementY","drag","dragend","get_editable","jview","is_editing","view_draggable","find_node_element","target","disable_view_draggable","nodeid","get_binded_nodeid","node","get_node","isroot","data","draggable","getBoundingClientRect","clientX","touches","zoom_current","offsetLeft","clientY","offsetTop","client_hw","Math","floor","client_hh","clearTimeout","clearInterval","setTimeout","setInterval","lookup_target_node","preventDefault","px","py","scrollTop","scrollBy","bottom","scrollHeight","scrollLeft","right","scrollWidth","enable_view_draggable","src_node","move_node","tagName","toLowerCase","sx","sy","target_direction","get_root_x","direction","lookup_overlapping_node_parent","lookup_close_node","points","calc_point_of_node","inherited","sp","np","root","get_root","root_location","get_location","root_size","get_size","shadowRect","deltaX","layout","hspace","pspace","deltaY","p","n","lookup_node_parent_by_location","elementsFromPoint","filter","map","id","mind","nodes","parent","find","Object","values","is_visible","shadow_on_target_side","distance","shadow_to_node","reduce","prev","curr","Number","MAX_VALUE","dir","shadow_to_right_of_node","shadow_to_left_of_node","shadow_to_base_line_of_node","abs","ns","nl","node_x","node_y","validate_drag","sibling_nodes","children","sc","length","delta_y","node_before","beforeid","dy","jm_event_handle","type","event_type","draggable_plugin","plugin","add_event_listener","register_plugin"],"mappings":"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"}
@@ -5,5 +5,5 @@
5
5
  * Project Home:
6
6
  * https://github.com/hizzgdev/jsmind/
7
7
  */
8
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),"function"!=typeof String.prototype.startsWith&&(String.prototype.startsWith=function(t){return this.slice(0,t.length)===t});const t=1,e=3,r=6,i=1,n=2,o=3,s=4;var a=function(){};let u="undefined"==typeof console?{level:a,log:a,debug:a,info:a,warn:a,error:a}:{level:function(t){u.debug=t>i?a:console.debug;u.info=t>n?a:console.info;u.warn=t>o?a:console.warn;u.error=t>s?a:console.error},log:console.log,debug:console.debug,info:console.info,warn:console.warn,error:console.error};class h{static instanceName="";static preload=!1;constructor({jm:t,pluginOpt:e}){this.jm=t,this.options=e||{}}beforePluginRemove(){}beforePluginDestroy(){this.beforePluginRemove()}}var c=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,l=Object.prototype.hasOwnProperty;function f(t,e){return function(r,i,n){return t(r,i,n)&&e(r,i,n)}}function p(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 y(t){return c(t).concat(d(t))}var g=Object.hasOwn||function(t,e){return l.call(t,e)};function m(t,e){return t===e||!t&&!e&&t!=t&&e!=e}var _=Object.getOwnPropertyDescriptor,b=Object.keys;function v(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 x(t,e){return m(t.getTime(),e.getTime())}function j(t,e){return t.name===e.name&&t.message===e.message&&t.cause===e.cause&&t.stack===e.stack}function S(t,e){return t===e}function w(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 k=m;function M(t,e,r){var i=b(t),n=i.length;if(b(e).length!==n)return!1;for(;n-- >0;)if(!N(t,e,r,i[n]))return!1;return!0}function O(t,e,r){var i,n,o,s=y(t),a=s.length;if(y(e).length!==a)return!1;for(;a-- >0;){if(!N(t,e,r,i=s[a]))return!1;if(n=_(t,i),o=_(e,i),(n||o)&&(!n||!o||n.configurable!==o.configurable||n.enumerable!==o.enumerable||n.writable!==o.writable))return!1}return!0}function q(t,e){return m(t.valueOf(),e.valueOf())}function A(t,e){return t.source===e.source&&t.flags===e.flags}function E(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 P(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 C(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 N(t,e,r,i){return!("_owner"!==i&&"__o"!==i&&"__v"!==i||!t.$$typeof&&!e.$$typeof)||g(e,i)&&r.equals(t[i],e[i],i,i,t,e,r)}var T=Array.isArray,D="undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView?ArrayBuffer.isView:null,I=Object.assign,F=Object.prototype.toString.call.bind(Object.prototype.toString);function z(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(T(t))return e(t,p,y);if(null!=D&&D(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=F(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 K=R();function R(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?O:v,areDatesEqual:x,areErrorsEqual:j,areFunctionsEqual:S,areMapsEqual:i?f(w,O):w,areNumbersEqual:k,areObjectsEqual:i?O:M,arePrimitiveWrappersEqual:q,areRegExpsEqual:A,areSetsEqual:i?f(E,O):E,areTypedArraysEqual:i?O:P,areUrlsEqual:C,unknownTagComparators:void 0};if(r&&(n=I({},n,r(n))),e){var o=p(n.areArraysEqual),s=p(n.areMapsEqual),a=p(n.areObjectsEqual),u=p(n.areSetsEqual);n=I({},n,{areArraysEqual:o,areMapsEqual:s,areObjectsEqual:a,areSetsEqual:u})}return n}(t),h=z(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 B(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 H(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(!K(r,n))return!1}else if(r!==n)return!1}return!0}function U(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?!K(i,o):i!==o)&&r.push({key:n,before:i,after:o})}return r}function W(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 $(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 J(t,e,r={}){const{fields:i,idKey:n,childrenKey:o,includeStructure:s=!0,maxSize:a=5e3,categorize:u=!1,ignoreDeletionShift:h=!1}=r,c=B(t,{fields:i,idKey:n,childrenKey:o,includeStructure:s}),d=B(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(!H(r,e)){const i=U(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($(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=W(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}}R({strict:!0}),R({circular:!0}),R({circular:!0,strict:!0}),R({createInternalComparator:function(){return m}}),R({strict:!0,createInternalComparator:function(){return m}}),R({circular:!0,createInternalComparator:function(){return m}}),R({circular:!0,createInternalComparator:function(){return m},strict:!0});const Y={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 V extends h{static instanceName="historyPlugin";static preload=!0;constructor({jm:t,pluginOpt:e}){super({jm:t,pluginOpt:e}),this.options=function(t){const e=Object.assign({},Y,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(){u.debug("[history] beforePluginDestroy: clearing history stack"),this._core&&this._core.clear()}_initCore(){const r=this.jm,i=this.options;i.keymap&&i.keymap.enabled&&r.options&&r.options.shortcut&&this._injectShortcuts(r.options.shortcut,!!i.keymap.redoUsesY);const n=new L(r,i);this._core=n,r.history&&(r.history.add=(t,e)=>n.add(t,e),r.history.pause=()=>n.pause(),r.history.resume=t=>n.resume(!!t),r.history.clear=()=>n.clear(),r.history.canBack=()=>n.canBack(),r.history.canForward=()=>n.canForward(),r.history.back=t=>n.back("number"==typeof t?t:1),r.history.forward=t=>n.forward("number"==typeof t?t:1),r.history.length=()=>n.length(),r.history.index=()=>n.index(),r.history.setMax=t=>n.setMax(t),r.history.setThrottle=t=>n.setThrottle(t),r.history.exportSnapshot=()=>n.exportSnapshot(),r.history.importSnapshot=(t,e)=>n.importSnapshot(t,e),r.history.getStack=()=>n.getStackMeta(),r.history.diff=(t,e,r)=>{const i=this.jm.options.fieldNames,n=i?.id||"id";return J(t,e,{fields:[i?.topic||"topic","data",n],idKey:n,childrenKey:i?.children||"children",...r})},this._listener=(r,i)=>{try{if(r===t&&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&&(u.debug("[history] root id changed, clearing stack and pausing"),n.clear(),n._lastRootId=t,setTimeout((()=>{try{u.debug("[history] adding bootstrap snapshot after show"),n._addNow&&n._addNow("bootstrap"),u.debug("[history] resuming history recording")}catch(t){u.warn("[history] failed to add bootstrap snapshot",t)}}),100)))}r===e&&i&&i.evt&&n.add(i.evt,i)}catch(t){u.warn("[history] listener error",t)}},r.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 J(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,u.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){u.error("[history] remove failed:",t)}}beforePluginDestroy(){u.error("beforePluginDestroy"),this.beforePluginRemove()}}class L{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(r,{index:this._idx,length:this._history.length,canBack:this.canBack(),canForward:this.canForward()})}catch(t){u.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",u.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 u.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}}}exports.HistoryPlugin=V,exports.default=V;
8
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),"function"!=typeof String.prototype.startsWith&&(String.prototype.startsWith=function(t){return this.slice(0,t.length)===t});const t=1,e=3,r=6,n=1,i=2,o=3,s=4;var a=function(){};let h="undefined"==typeof console?{level:a,log:a,debug:a,info:a,warn:a,error:a}:{level:function(t){h.debug=t>n?a:console.debug;h.info=t>i?a:console.info;h.warn=t>o?a:console.warn;h.error=t>s?a: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 u=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,l=Object.prototype.hasOwnProperty;function f(t,e){return function(r,n,i){return t(r,n,i)&&e(r,n,i)}}function p(t){return function(e,r,n){if(!e||!r||"object"!=typeof e||"object"!=typeof r)return t(e,r,n);var i=n.cache,o=i.get(e),s=i.get(r);if(o&&s)return o===r&&s===e;i.set(e,r),i.set(r,e);var a=t(e,r,n);return i.delete(e),i.delete(r),a}}function y(t){return u(t).concat(d(t))}var g=Object.hasOwn||function(t,e){return l.call(t,e)};function m(t,e){return t===e||!t&&!e&&t!=t&&e!=e}var _=Object.getOwnPropertyDescriptor,b=Object.keys;function v(t,e,r){var n=t.length;if(e.length!==n)return!1;for(;n-- >0;)if(!r.equals(t[n],e[n],n,n,t,e,r))return!1;return!0}function x(t,e){return m(t.getTime(),e.getTime())}function j(t,e){return t.name===e.name&&t.message===e.message&&t.cause===e.cause&&t.stack===e.stack}function S(t,e){return t===e}function w(t,e,r){var n=t.size;if(n!==e.size)return!1;if(!n)return!0;for(var i,o,s=new Array(n),a=t.entries(),h=0;(i=a.next())&&!i.done;){for(var c=e.entries(),u=!1,d=0;(o=c.next())&&!o.done;)if(s[d])d++;else{var l=i.value,f=o.value;if(r.equals(l[0],f[0],h,d,t,e,r)&&r.equals(l[1],f[1],l[0],f[0],t,e,r)){u=s[d]=!0;break}d++}if(!u)return!1;h++}return!0}var k=m;function M(t,e,r){var n=b(t),i=n.length;if(b(e).length!==i)return!1;for(;i-- >0;)if(!N(t,e,r,n[i]))return!1;return!0}function O(t,e,r){var n,i,o,s=y(t),a=s.length;if(y(e).length!==a)return!1;for(;a-- >0;){if(!N(t,e,r,n=s[a]))return!1;if(i=_(t,n),o=_(e,n),(i||o)&&(!i||!o||i.configurable!==o.configurable||i.enumerable!==o.enumerable||i.writable!==o.writable))return!1}return!0}function q(t,e){return m(t.valueOf(),e.valueOf())}function A(t,e){return t.source===e.source&&t.flags===e.flags}function E(t,e,r){var n=t.size;if(n!==e.size)return!1;if(!n)return!0;for(var i,o,s=new Array(n),a=t.values();(i=a.next())&&!i.done;){for(var h=e.values(),c=!1,u=0;(o=h.next())&&!o.done;){if(!s[u]&&r.equals(i.value,o.value,i.value,o.value,t,e,r)){c=s[u]=!0;break}u++}if(!c)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 P(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 N(t,e,r,n){return!("_owner"!==n&&"__o"!==n&&"__v"!==n||!t.$$typeof&&!e.$$typeof)||g(e,n)&&r.equals(t[n],e[n],n,n,t,e,r)}var T=Array.isArray,D="function"==typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView:null,I=Object.assign,F=Object.prototype.toString.call.bind(Object.prototype.toString);function z(t){var e=t.areArraysEqual,r=t.areDatesEqual,n=t.areErrorsEqual,i=t.areFunctionsEqual,o=t.areMapsEqual,s=t.areNumbersEqual,a=t.areObjectsEqual,h=t.arePrimitiveWrappersEqual,c=t.areRegExpsEqual,u=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&&i(t,p,y);var m=t.constructor;if(m!==p.constructor)return!1;if(m===Object)return a(t,p,y);if(T(t))return e(t,p,y);if(null!=D&&D(t))return d(t,p,y);if(m===Date)return r(t,p,y);if(m===RegExp)return c(t,p,y);if(m===Map)return o(t,p,y);if(m===Set)return u(t,p,y);var _,b=F(t);if("[object Date]"===b)return r(t,p,y);if("[object RegExp]"===b)return c(t,p,y);if("[object Map]"===b)return o(t,p,y);if("[object Set]"===b)return u(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 n(t,p,y);if("[object Arguments]"===b)return a(t,p,y);if("[object Boolean]"===b||"[object Number]"===b||"[object String]"===b)return h(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 K=R();function R(t){void 0===t&&(t={});var e,r=t.circular,n=void 0!==r&&r,i=t.createInternalComparator,o=t.createState,s=t.strict,a=void 0!==s&&s,h=function(t){var e=t.circular,r=t.createCustomConfig,n=t.strict,i={areArraysEqual:n?O:v,areDatesEqual:x,areErrorsEqual:j,areFunctionsEqual:S,areMapsEqual:n?f(w,O):w,areNumbersEqual:k,areObjectsEqual:n?O:M,arePrimitiveWrappersEqual:q,areRegExpsEqual:A,areSetsEqual:n?f(E,O):E,areTypedArraysEqual:n?O:C,areUrlsEqual:P,unknownTagComparators:void 0};if(r&&(i=I({},i,r(i))),e){var o=p(i.areArraysEqual),s=p(i.areMapsEqual),a=p(i.areObjectsEqual),h=p(i.areSetsEqual);i=I({},i,{areArraysEqual:o,areMapsEqual:s,areObjectsEqual:a,areSetsEqual:h})}return i}(t),c=z(h);return function(t){var e=t.circular,r=t.comparator,n=t.createState,i=t.equals,o=t.strict;if(n)return function(t,s){var a=n(),h=a.cache,c=void 0===h?e?new WeakMap:void 0:h,u=a.meta;return r(t,s,{cache:c,equals:i,meta:u,strict:o})};if(e)return function(t,e){return r(t,e,{cache:new WeakMap,equals:i,meta:void 0,strict:o})};var s={cache:void 0,equals:i,meta:void 0,strict:o};return function(t,e){return r(t,e,s)}}({circular:n,comparator:c,createState:o,equals:i?i(c):(e=c,function(t,r,n,i,o,s,a){return e(t,r,a)}),strict:a})}function B(t,e){const r=function(t){return(e=t)&&"object"==typeof e&&"data"in e?t.data:t;var e}(t),n=e&&Array.isArray(e.fields)?e.fields:["topic","data","id"],i=e&&e.idKey?e.idKey:"id",o=e&&e.childrenKey?e.childrenKey:"children",s=!e||!1!==e.includeStructure,a=new Map;return r&&r[i]&&function t(e,r,h){const c=function(t){const e={};i in t&&(e[i]=t[i]);const r=new Set([i,o,"direction","expanded","parentid","index","isroot"]);n.includes("data");for(const o of n)if("data"===o){const i={};let o=!1;for(const e in t)r.has(e)||n.includes(e)||(i[e]=t[e],o=!0);o&&(e.data=i)}else o in t&&o!==i&&(e[o]=t[o]);return e}(e),u=e[i];s&&(c.parentid=r||null,c.index="number"==typeof h?h:0),a.set(u,c);const d=e[o];d&&Array.isArray(d)&&d.forEach((e,r)=>t(e,u,r))}(r,null,0),a}function H(t,e){if(t===e)return!0;if(!t||!e)return!1;const r=Object.keys(t),n=Object.keys(e);if(r.length!==n.length)return!1;for(const n of r){const r=t[n],i=e[n];if(r===i)continue;if(r&&i&&"object"==typeof r&&"object"==typeof i){if(!K(r,i))return!1}else if(r!==i)return!1}return!0}function U(t,e){const r=[];if(!t||!e)return r;const n=new Set([...Object.keys(t),...Object.keys(e)]);n.delete("id");for(const i of n){const n=t[i],o=e[i];if(n===o)continue;(n&&o&&"object"==typeof n&&"object"==typeof o?!K(n,o):n!==o)&&r.push({key:i,before:n,after:o})}return r}function W(t){let e=!1,r=!1;for(const n of t)"parentid"===n.key&&(e=!0),"index"===n.key&&(r=!0);return{moved:e||r,parentChanged:e,orderChanged:r}}function $(t){const e=new Map;for(const[r,n]of t){const t=n.parentid;e.has(t)||e.set(t,[]),e.get(t).push({id:r,index:n.index})}for(const t of e.values())t.sort((t,e)=>t.index-e.index);return e}function J(t,e,r){const n=new Set,i=new Map;e.forEach((t,e)=>i.set(t.id,e));const o=[],s=[];for(const e of t)i.has(e.id)&&(o.push(e.id),s.push(i.get(e.id)));if(o.length<=1)return n;const a=function(t){const e=t.slice(),r=[0];let n,i,o,s,a;const h=t.length;for(n=0;n<h;n++){const h=t[n];if(0!==h||0===n){if(i=r[r.length-1],t[i]<h){e[n]=i,r.push(n);continue}for(o=0,s=r.length-1;o<s;)a=o+s>>1,t[r[a]]<h?o=a+1:s=a;h<t[r[o]]&&(o>0&&(e[n]=r[o-1]),r[o]=n)}}for(o=r.length,s=r[o-1];o-- >0;)r[o]=s,s=e[s];return r}(s),h=new Set(a);return o.forEach((t,e)=>{h.has(e)||n.add(t)}),n}function Y(t,e,r={}){const{fields:n,idKey:i,childrenKey:o,includeStructure:s=!0,maxSize:a=5e3,categorize:h=!1}=r,c=B(t,{fields:n,idKey:i,childrenKey:o,includeStructure:s}),u=B(e,{fields:n,idKey:i,childrenKey:o,includeStructure:s}),d=[],l=[],f=[];for(const[t,e]of u){if(!c.has(t)){d.push(e);continue}const r=c.get(t);if(!H(r,e)){const n=U(r,e);l.push({id:t,before:r,after:e,changes:n})}}for(const[t,e]of c)u.has(t)||f.push(e);let p=!1;const y=d.length+l.length+f.length;if(y>a){p=!0;const t=Math.max(0,a),e=Math.min(d.length,Math.floor(t*(d.length/y))),r=Math.min(l.length,Math.floor(t*(l.length/y))),n=Math.min(f.length,Math.max(0,t-e-r));d.length=e,l.length=r,f.length=n}if(h&&s){const t=function(t,e,r){const n=[],i=[],o=[],s=new Set,a=$(e),h=$(r);for(const[t,e]of h){const r=J(a.get(t)||[],e);for(const t of r)s.add(t)}for(const e of t){const{id:t,before:r,after:a,changes:h}=e,c=W(h),u=c.parentChanged,d=!u&&c.orderChanged&&s.has(t);if(u||d){const e={moveType:u?"cross-parent":"reorder",parentChanged:c.parentChanged,orderChanged:c.orderChanged,fromParent:r.parentid,toParent:a.parentid,fromOrder:r.index,toOrder:a.index},i=h.filter(t=>"parentid"!==t.key&&"index"!==t.key);i.length>0?o.push({id:t,before:r,after:a,changes:i,moveInfo:e}):n.push({id:t,before:r,after:a,moveInfo:e})}else if(c.orderChanged){const e=h.filter(t=>"parentid"!==t.key&&"index"!==t.key);e.length>0&&i.push({id:t,before:r,after:a,changes:e})}else i.push({id:t,before:r,after:a,changes:h})}return{moved:n,modified:i,movedAndModified:o}}(l,c,u);return{created:d,updated:l,deleted:f,truncated:p,moved:t.moved,modified:t.modified,movedAndModified:t.movedAndModified}}return{created:d,updated:l,deleted:f,truncated:p}}R({strict:!0}),R({circular:!0}),R({circular:!0,strict:!0}),R({createInternalComparator:function(){return m}}),R({strict:!0,createInternalComparator:function(){return m}}),R({circular:!0,createInternalComparator:function(){return m}}),R({circular:!0,createInternalComparator:function(){return m},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 r=this.jm,n=this.options;n.keymap&&n.keymap.enabled&&r.options&&r.options.shortcut&&this._injectShortcuts(r.options.shortcut,!!n.keymap.redoUsesY);const i=new G(r,n);this._core=i,r.history&&(r.history.add=(t,e)=>i.add(t,e),r.history.pause=()=>i.pause(),r.history.resume=t=>i.resume(!!t),r.history.clear=()=>i.clear(),r.history.canBack=()=>i.canBack(),r.history.canForward=()=>i.canForward(),r.history.back=t=>i.back("number"==typeof t?t:1),r.history.forward=t=>i.forward("number"==typeof t?t:1),r.history.length=()=>i.length(),r.history.index=()=>i.index(),r.history.setMax=t=>i.setMax(t),r.history.setThrottle=t=>i.setThrottle(t),r.history.exportSnapshot=()=>i.exportSnapshot(),r.history.importSnapshot=(t,e)=>i.importSnapshot(t,e),r.history.getStack=()=>i.getStackMeta(),r.history.diff=(t,e,r)=>{const n=this.jm.options.fieldNames,i=n?.id||"id";return Y(t,e,{fields:[n?.topic||"topic","data",i],idKey:i,childrenKey:n?.children||"children",...r})},this._listener=(r,n)=>{try{if(r===t&&n&&"data"in n){let t=null;const e=n.data&&n.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!==i._lastRootId&&(h.debug("[history] root id changed, clearing stack and pausing"),i.clear(),i._lastRootId=t,setTimeout(()=>{try{h.debug("[history] adding bootstrap snapshot after show"),i._addNow&&i._addNow("bootstrap"),h.debug("[history] resuming history recording")}catch(t){h.warn("[history] failed to add bootstrap snapshot",t)}},100)))}r===e&&n&&n.evt&&i.add(n.evt,n)}catch(t){h.warn("[history] listener error",t)}},r.add_event_listener(this._listener))}_injectShortcuts(t,e){const r=[4186,8282],n=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=n}_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 n=this.jm.options.fieldNames,i=n?.id||"id";return Y(t,e,{fields:[n?.topic||"topic","data",i],idKey:i,childrenKey:n?.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 n=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},n)}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(r,{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 n=this.storageMode;if(this.autoSwitchThreshold>0&&"object"===n){const t=this._countNodes(r);t>this.autoSwitchThreshold&&(n="string",h.debug(`[history] auto-switched to string mode (${t} nodes > ${this.autoSwitchThreshold})`))}let i=null;try{i=JSON.stringify(r)}catch{}if(!i||!this._lastSig||i!==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"===n)this._history.push(i);else{const t=this._deepFreeze(r);this._history.push(t)}this._idx=this._history.length-1,this._lastSig=i,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}}}exports.HistoryPlugin=L,exports.default=L;
9
9
  //# sourceMappingURL=jsmind.history.js.map