@umbraci/jsmind 0.9.1 → 0.9.2-rich-text
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es6/jsmind.draggable-node.js.map +1 -1
- package/es6/jsmind.js +1 -1
- package/es6/jsmind.js.map +1 -1
- package/es6/jsmind.screenshot.js +1 -1
- package/es6/jsmind.screenshot.js.map +1 -1
- package/package.json +7 -11
- package/style/jsmind.css +90 -0
- package/es6/jsmind.multiline-text.js +0 -9
- package/es6/jsmind.multiline-text.js.map +0 -1
package/es6/jsmind.screenshot.js
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* Project Home:
|
|
6
6
|
* https://github.com/hizzgdev/jsmind/
|
|
7
7
|
*/
|
|
8
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@umbraci/jsmind"),require("dom-to-image")):"function"==typeof define&&define.amd?define(["exports","@umbraci/jsmind","dom-to-image"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).jsMindScreenshot={},e.jsMind,e.domtoimage)}(this,(function(e,t,i){"use strict";function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var o=n(t),r=n(i);if(!o.default)throw new Error("jsMind is not defined");if(!r.default)throw new Error("dom-to-image is required");const s=o.default.$,a={filename:null,watermark:{left:s.w.location,right:"https://github.com/
|
|
8
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@umbraci/jsmind"),require("dom-to-image")):"function"==typeof define&&define.amd?define(["exports","@umbraci/jsmind","dom-to-image"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).jsMindScreenshot={},e.jsMind,e.domtoimage)}(this,(function(e,t,i){"use strict";function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var o=n(t),r=n(i);if(!o.default)throw new Error("jsMind is not defined");if(!r.default)throw new Error("dom-to-image is required");const s=o.default.$,a={filename:null,watermark:{left:s.w.location,right:"https://github.com/hizzgdev/jsmind"},background:"transparent"};class d{constructor(e,t){var i={};o.default.util.json.merge(i,a),o.default.util.json.merge(i,t),this.version="0.2.0",this.jm=e,this.options=i,this.dpr=e.view.device_pixel_ratio}shoot(){let e=this.create_canvas(),t=e.getContext("2d");t.scale(this.dpr,this.dpr),Promise.resolve(t).then((()=>this.draw_background(t))).then((()=>this.draw_lines(t))).then((()=>this.draw_nodes(t))).then((()=>this.draw_watermark(e,t))).then((()=>this.download(e))).then((()=>this.clear(e)))}create_canvas(){let e=s.c("canvas");const t=this.jm.view.size.w,i=this.jm.view.size.h;return e.width=t*this.dpr,e.height=i*this.dpr,e.style.width=t+"px",e.style.height=i+"px",e.style.visibility="hidden",this.jm.view.e_panel.appendChild(e),e}clear(e){e.parentNode.removeChild(e)}draw_background(e){return new Promise(function(t,i){const n=this.options.background;n&&"transparent"!==n&&(e.fillStyle=this.options.background,e.fillRect(0,0,this.jm.view.size.w,this.jm.view.size.h)),t(e)}.bind(this))}draw_lines(e){return new Promise(function(t,i){this.jm.view.graph.copy_to(e,(function(){t(e)}))}.bind(this))}draw_nodes(e){return r.default.toSvg(this.jm.view.e_nodes,{style:{zoom:1}}).then(this.load_image).then((function(t){return e.drawImage(t,0,0),e}))}draw_watermark(e,t){return t.textBaseline="bottom",t.fillStyle="#000",t.font="11px Verdana,Arial,Helvetica,sans-serif",this.options.watermark.left&&(t.textAlign="left",t.fillText(this.options.watermark.left,5.5,e.height-2.5)),this.options.watermark.right&&(t.textAlign="right",t.fillText(this.options.watermark.right,e.width-5.5,e.height-2.5)),t}load_image(e){return new Promise((function(t,i){let n=new Image;n.onload=function(){t(n)},n.onerror=i,n.src=e}))}download(e){var t=(this.options.filename||this.jm.mind.name)+".png";if(navigator.msSaveBlob&&e.msToBlob){var i=e.msToBlob();navigator.msSaveBlob(i,t)}else{var n=e.toDataURL(),o=s.c("a");if("download"in o){o.style.visibility="hidden",o.href=n,o.download=t,s.d.body.appendChild(o);var r=s.d.createEvent("MouseEvents");r.initEvent("click",!0,!0),o.dispatchEvent(r),s.d.body.removeChild(o)}else location.href=n}}}const l=new o.default.plugin("screenshot",(function(e,t){var i=new d(e,t);e.screenshot=i,e.shoot=function(){i.shoot()}}));o.default.register_plugin(l),e.JmScreenshot=d,e.default=d,e.screenshot_plugin=l,Object.defineProperty(e,"__esModule",{value:!0})}));
|
|
9
9
|
//# sourceMappingURL=jsmind.screenshot.js.map
|
|
@@ -1 +1 @@
|
|
|
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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"}
|
|
1
|
+
{"version":3,"file":"jsmind.screenshot.js","sources":["../src/plugins/jsmind.screenshot.js"],"sourcesContent":["/**\n * @license BSD\n * @copyright 2014-2025 hizzgdev@163.com\n *\n * Project Home:\n * https://github.com/hizzgdev/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/hizzgdev/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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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umbraci/jsmind",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.2-rich-text",
|
|
4
4
|
"description": "jsMind is a pure javascript library for mindmap, it base on html5 canvas. jsMind was released under BSD license, you can embed it in any project, if only you observe the license.",
|
|
5
5
|
"main": "es6/jsmind.js",
|
|
6
6
|
"types": "types/generated/index.d.ts",
|
|
@@ -20,11 +20,6 @@
|
|
|
20
20
|
"require": "./es6/jsmind.screenshot.js",
|
|
21
21
|
"types": "./types/generated/plugins/jsmind.screenshot.d.ts"
|
|
22
22
|
},
|
|
23
|
-
"./multiline-text": {
|
|
24
|
-
"import": "./es6/jsmind.multiline-text.js",
|
|
25
|
-
"require": "./es6/jsmind.multiline-text.js",
|
|
26
|
-
"types": "./types/generated/plugins/jsmind.multiline-text.d.ts"
|
|
27
|
-
},
|
|
28
23
|
"./style/jsmind.css": "./style/jsmind.css"
|
|
29
24
|
},
|
|
30
25
|
"directories": {
|
|
@@ -52,23 +47,24 @@
|
|
|
52
47
|
},
|
|
53
48
|
"repository": {
|
|
54
49
|
"type": "git",
|
|
55
|
-
"url": "git+https://github.com/
|
|
50
|
+
"url": "git+https://github.com/hizzgdev/jsmind.git"
|
|
56
51
|
},
|
|
57
52
|
"author": {
|
|
58
|
-
"name": "
|
|
53
|
+
"name": "hizzgdev@163.com"
|
|
59
54
|
},
|
|
60
55
|
"license": "BSD-3-Clause",
|
|
61
56
|
"bugs": {
|
|
62
|
-
"url": "https://github.com/
|
|
57
|
+
"url": "https://github.com/hizzgdev/jsmind/issues"
|
|
63
58
|
},
|
|
64
|
-
"homepage": "https://github.com/
|
|
59
|
+
"homepage": "https://github.com/hizzgdev/jsmind#readme",
|
|
65
60
|
"keywords": [
|
|
66
61
|
"jsmind",
|
|
67
62
|
"mindmap"
|
|
68
63
|
],
|
|
69
64
|
"maintainers": [
|
|
70
65
|
{
|
|
71
|
-
"name": "
|
|
66
|
+
"name": "hizzgdev",
|
|
67
|
+
"email": "hizzgdev@163.com"
|
|
72
68
|
}
|
|
73
69
|
],
|
|
74
70
|
"devDependencies": {
|
package/style/jsmind.css
CHANGED
|
@@ -73,6 +73,96 @@ jmexpander {
|
|
|
73
73
|
overflow: hidden;
|
|
74
74
|
text-overflow: ellipsis;
|
|
75
75
|
}
|
|
76
|
+
|
|
77
|
+
/* Rich text and multiline support - unified div approach */
|
|
78
|
+
.jsmind-editor {
|
|
79
|
+
border: 2px solid #4caf50;
|
|
80
|
+
border-radius: 4px;
|
|
81
|
+
padding: 4px;
|
|
82
|
+
margin: 0;
|
|
83
|
+
outline: none;
|
|
84
|
+
background: #fff;
|
|
85
|
+
font-family: inherit;
|
|
86
|
+
font-size: inherit;
|
|
87
|
+
line-height: inherit;
|
|
88
|
+
color: #000 !important; /* 确保编辑器内字体始终为黑色 */
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.jsmind-rich-editor {
|
|
92
|
+
min-height: 20px;
|
|
93
|
+
word-wrap: break-word;
|
|
94
|
+
overflow-wrap: break-word;
|
|
95
|
+
white-space: normal;
|
|
96
|
+
max-height: 200px;
|
|
97
|
+
overflow-y: auto;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* Multiline editor using contenteditable div */
|
|
101
|
+
.jsmind-multiline-editor {
|
|
102
|
+
min-height: 20px;
|
|
103
|
+
word-wrap: break-word;
|
|
104
|
+
overflow-wrap: break-word;
|
|
105
|
+
white-space: pre-wrap;
|
|
106
|
+
max-height: 200px;
|
|
107
|
+
overflow-y: auto;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/* Input editor for single line text */
|
|
111
|
+
.jsmind-input-editor {
|
|
112
|
+
white-space: nowrap;
|
|
113
|
+
overflow: hidden;
|
|
114
|
+
text-overflow: ellipsis;
|
|
115
|
+
min-height: 20px;
|
|
116
|
+
border: none;
|
|
117
|
+
outline: none;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/* Legacy textarea support (deprecated - will be removed in future versions) */
|
|
121
|
+
.jsmind-textarea-editor {
|
|
122
|
+
resize: vertical;
|
|
123
|
+
min-height: 40px;
|
|
124
|
+
font-family: inherit;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/* Multiline node styles */
|
|
128
|
+
jmnode.multiline {
|
|
129
|
+
white-space: pre-wrap;
|
|
130
|
+
word-wrap: break-word;
|
|
131
|
+
overflow-wrap: break-word;
|
|
132
|
+
max-width: 300px; /* This value should be consistent with textAutoWrapWidth config */
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* Rich text node styles */
|
|
136
|
+
jmnode.rich-text {
|
|
137
|
+
white-space: normal;
|
|
138
|
+
word-wrap: break-word;
|
|
139
|
+
overflow-wrap: break-word;
|
|
140
|
+
max-width: 300px;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
jmnode.rich-text b,
|
|
144
|
+
jmnode.rich-text strong {
|
|
145
|
+
font-weight: bold;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
jmnode.rich-text i,
|
|
149
|
+
jmnode.rich-text em {
|
|
150
|
+
font-style: italic;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
jmnode.rich-text u {
|
|
154
|
+
text-decoration: underline;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
jmnode.rich-text ul,
|
|
158
|
+
jmnode.rich-text ol {
|
|
159
|
+
margin: 4px 0;
|
|
160
|
+
padding-left: 20px;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
jmnode.rich-text li {
|
|
164
|
+
margin: 2px 0;
|
|
165
|
+
}
|
|
76
166
|
/* default theme */
|
|
77
167
|
jmnode {
|
|
78
168
|
padding: 10px;
|
|
@@ -1,9 +0,0 @@
|
|
|
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
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@umbraci/jsmind")):"function"==typeof define&&define.amd?define(["exports","@umbraci/jsmind"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).jsMindMultilineText={},e.jsMind)}(this,(function(e,t){"use strict";function i(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var n=i(t);if(!n.default)throw new Error("jsMind is not defined");const o=n.default.$,d={text_width:200,editor_border_color:"#4CAF50",editor_border_width:"2px",save_shortcut:"Enter",cancel_shortcut:"Escape",newline_shortcut:"Shift+Enter",auto_resize:!0,min_height:20,line_height:1.2};class s{constructor(e,t){var i={};n.default.util.json.merge(i,d),n.default.util.json.merge(i,t),this.version="0.1.0",this.jm=e,this.options=i,this.original_methods={},this.editing_node=null,this.multiline_editor=null}init(){this.override_view_methods(),this.setup_event_listeners(),this.rerender_existing_nodes()}override_view_methods(){const e=this.jm.view;this.original_methods.edit_node_begin=e.edit_node_begin.bind(e),this.original_methods.edit_node_end=e.edit_node_end.bind(e),this.original_methods.render_node=e.render_node.bind(e),this.original_methods.show=e.show.bind(e);try{e.edit_node_begin=this.edit_node_begin.bind(this),e.edit_node_end=this.edit_node_end.bind(this),e.render_node=this._render_multiline_node_wrapper.bind(this),e.show=this._show_wrapper.bind(this),console.log("Multiline text plugin: Successfully overrode view methods")}catch(e){console.error("Multiline text plugin: Failed to override methods",e),this.restore_original_methods()}}restore_original_methods(){const e=this.jm.view;this.original_methods.edit_node_begin&&(e.edit_node_begin=this.original_methods.edit_node_begin),this.original_methods.edit_node_end&&(e.edit_node_end=this.original_methods.edit_node_end),this.original_methods.render_node&&(e.render_node=this.original_methods.render_node),this.original_methods.show&&(e.show=this.original_methods.show)}setup_event_listeners(){this.jm.add_event_listener(((e,t)=>{this.jm_event_handle(e,t)}))}_render_multiline_node_wrapper(e,t){try{this._render_multiline_node(e,t)}catch(i){console.error("Multiline text plugin: Error in render_node",i),this.original_methods.render_node&&this.original_methods.render_node(e,t)}}_show_wrapper(e){try{this.original_methods.show(!1)}catch(t){console.error("Multiline text plugin: Error in show",t),this.original_methods.show&&this.original_methods.show(e)}}_render_multiline_node(e,t){if(!t.topic)return;const i=e.clientHeight,n=t.topic;n.includes("\n")?(e.innerHTML="",e.textContent=n,e.style.whiteSpace="pre-wrap",e.style.wordBreak="break-word"):(e.style.whiteSpace="",e.style.wordBreak="",this.jm.view.opts.support_html?o.h(e,n):o.t(e,n));i!==e.clientHeight&&i>0&&setTimeout((()=>{this.recalculate_layout(t)}),0)}edit_node_begin(e){if(!e.topic)return void console.warn("don't edit image nodes");null!=this.editing_node&&this.edit_node_end(),this.editing_node=e;const t=e._data.view.element,i=e.topic;this.create_multiline_editor(t,i)}create_multiline_editor(e,t){this.multiline_editor=o.c("div"),this.multiline_editor.contentEditable="plaintext-only",this.multiline_editor.className="jsmind-multiline-editor",this.multiline_editor.textContent=t,this.style_multiline_editor(e),this.setup_editor_events(),e.innerHTML="",e.appendChild(this.multiline_editor),e.style.zIndex=5,this.multiline_editor.focus(),this.select_all_text()}style_multiline_editor(e){const t=getComputedStyle(e),i=this.multiline_editor;i.style.width=Math.max(e.clientWidth-parseInt(t.getPropertyValue("padding-left"))-parseInt(t.getPropertyValue("padding-right")),this.options.text_width)+"px",i.style.minHeight=this.options.min_height+"px",i.style.lineHeight=this.options.line_height,i.style.border=this.options.editor_border_width+" solid "+this.options.editor_border_color,i.style.borderRadius="4px",i.style.padding="4px",i.style.outline="none",i.style.resize="none",i.style.overflow="hidden",i.style.whiteSpace="pre-wrap",i.style.wordWrap="break-word"}setup_editor_events(){const e=this.multiline_editor;o.on(e,"keydown",(e=>{this.handle_editor_keydown(e)})),o.on(e,"blur",(e=>{setTimeout((()=>{this.editing_node&&this.edit_node_end()}),100)})),o.on(e,"input",(e=>{this.auto_resize_editor()}))}handle_editor_keydown(e){const t=e.key,i=e.shiftKey;if(e.ctrlKey||e.metaKey,"Enter"===t){if(i)return;e.preventDefault(),this.edit_node_end()}else"Escape"===t?(e.preventDefault(),this.cancel_editing()):"Tab"===t&&(e.preventDefault(),this.edit_node_end())}auto_resize_editor(){if(!this.options.auto_resize||!this.multiline_editor)return;const e=this.multiline_editor;e.style.height="auto";const t=e.scrollHeight,i=this.options.min_height;e.style.height=Math.max(t,i)+"px"}select_all_text(){if(!this.multiline_editor)return;const e=o.d.createRange();e.selectNodeContents(this.multiline_editor);const t=o.w.getSelection();t.removeAllRanges(),t.addRange(e)}edit_node_end(){if(null==this.editing_node||!this.multiline_editor)return;const e=this.editing_node,t=e._data.view.element,i=this.multiline_editor.textContent||"";this.cleanup_editor(t);const o=this.process_multiline_text(i);n.default.util.text.is_empty(o)||e.topic===o?this._render_multiline_node(t,e):this.jm.update_node(e.id,o),this.recalculate_layout(e),this.editing_node=null,this.multiline_editor=null,this.jm.view.e_panel.focus()}cancel_editing(){if(null==this.editing_node||!this.multiline_editor)return;const e=this.editing_node,t=e._data.view.element;this.cleanup_editor(t),this._render_multiline_node(t,e),this.editing_node=null,this.multiline_editor=null,this.jm.view.e_panel.focus()}cleanup_editor(e){this.multiline_editor&&this.multiline_editor.parentNode&&this.multiline_editor.parentNode.removeChild(this.multiline_editor),e.style.zIndex="auto"}process_multiline_text(e){return e?e=(e=(e=e.trim()).replace(/\r\n/g,"\n").replace(/\r/g,"\n")).replace(/\n{3,}/g,"\n\n"):""}rerender_existing_nodes(){if(!this.jm.mind||!this.jm.mind.nodes)return;const e=this.jm.mind.nodes;for(const t in e){const i=e[t];if(i.topic&&i.topic.includes("\n")){const e=i._data.view;e&&e.element&&this._render_multiline_node(e.element,i)}}}recalculate_layout(e){this.jm.layout.cache_valid=!1;const t=this.jm.mind.nodes;for(let e in t){const i=t[e];i._data.layout&&(delete i._data.layout._offset_,delete i._data.layout._pout_)}this.jm.view.update_node(e),this.jm.layout.layout(),this.jm.view.show()}jm_event_handle(e,t){n.default.event_type.resize}}const l=new n.default.plugin("multiline_text",(function(e,t){var i=new s(e,t);i.init(),e.multiline_text=i}));n.default.register_plugin(l),e.MultilineText=s,e.default=s,e.multiline_text_plugin=l,Object.defineProperty(e,"__esModule",{value:!0})}));
|
|
9
|
-
//# sourceMappingURL=jsmind.multiline-text.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"jsmind.multiline-text.js","sources":["../src/plugins/jsmind.multiline-text.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\n/**\n * Default options for multiline text plugin.\n * @typedef {Object} MultilineTextOptions\n * @property {number} [text_width] - Maximum text width in pixels\n * @property {string} [editor_border_color] - Border color for active editor\n * @property {string} [editor_border_width] - Border width for active editor\n * @property {string} [save_shortcut] - Key to save (without Shift)\n * @property {string} [cancel_shortcut] - Key to cancel editing\n * @property {string} [newline_shortcut] - Key combination for new line\n * @property {boolean} [auto_resize] - Auto-resize nodes for multiline text\n * @property {number} [min_height] - Minimum node height\n * @property {number} [line_height] - Line height multiplier\n */\nconst DEFAULT_OPTIONS = {\n text_width: 200,\n editor_border_color: '#4CAF50',\n editor_border_width: '2px',\n save_shortcut: 'Enter',\n cancel_shortcut: 'Escape',\n newline_shortcut: 'Shift+Enter',\n auto_resize: true,\n min_height: 20,\n line_height: 1.2,\n};\n\n/**\n * Multiline text plugin for jsMind.\n */\nexport class MultilineText {\n /**\n * Create multiline text plugin instance.\n * @param {import('../jsmind.js').default} jm - jsMind instance\n * @param {Partial<MultilineTextOptions>} 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.1.0';\n /** @type {import('../jsmind.js').default} */\n this.jm = jm;\n /** @type {MultilineTextOptions} */\n this.options = opts;\n\n // Store original methods for restoration if needed\n this.original_methods = {};\n\n // Current editing state\n this.editing_node = null;\n this.multiline_editor = null;\n }\n\n /** Initialize the multiline text plugin. */\n init() {\n this.override_view_methods();\n this.setup_event_listeners();\n // Re-render all existing nodes to apply multiline formatting\n this.rerender_existing_nodes();\n }\n\n /**\n * Override ViewProvider methods to support multiline text.\n */\n override_view_methods() {\n const view = this.jm.view;\n\n // Store original methods for fallback\n this.original_methods.edit_node_begin = view.edit_node_begin.bind(view);\n this.original_methods.edit_node_end = view.edit_node_end.bind(view);\n this.original_methods.render_node = view.render_node.bind(view);\n this.original_methods.show = view.show.bind(view);\n\n // Override methods with error handling\n try {\n view.edit_node_begin = this.edit_node_begin.bind(this);\n view.edit_node_end = this.edit_node_end.bind(this);\n view.render_node = this._render_multiline_node_wrapper.bind(this);\n view.show = this._show_wrapper.bind(this);\n console.log('Multiline text plugin: Successfully overrode view methods');\n } catch (error) {\n console.error('Multiline text plugin: Failed to override methods', error);\n // Restore original methods if override fails\n this.restore_original_methods();\n }\n }\n\n /**\n * Restore original methods if override fails.\n */\n restore_original_methods() {\n const view = this.jm.view;\n if (this.original_methods.edit_node_begin) {\n view.edit_node_begin = this.original_methods.edit_node_begin;\n }\n if (this.original_methods.edit_node_end) {\n view.edit_node_end = this.original_methods.edit_node_end;\n }\n if (this.original_methods.render_node) {\n view.render_node = this.original_methods.render_node;\n }\n if (this.original_methods.show) {\n view.show = this.original_methods.show;\n }\n }\n\n /**\n * Set up event listeners for the plugin.\n */\n setup_event_listeners() {\n // Listen for jsMind events if needed\n this.jm.add_event_listener((type, data) => {\n this.jm_event_handle(type, data);\n });\n }\n\n /**\n * Wrapper for render_node method with error handling.\n * @param {HTMLElement} element - Node element\n * @param {import('../jsmind.node.js').Node} node - Node data\n */\n _render_multiline_node_wrapper(element, node) {\n try {\n this._render_multiline_node(element, node);\n } catch (error) {\n console.error('Multiline text plugin: Error in render_node', error);\n // Fall back to original method\n if (this.original_methods.render_node) {\n this.original_methods.render_node(element, node);\n }\n }\n }\n\n /**\n * Wrapper for show method to prevent unwanted view resets.\n * @param {boolean} keep_center - Whether to center on root node\n */\n _show_wrapper(keep_center) {\n try {\n // Always call show without centering to prevent view jumps\n this.original_methods.show(false);\n } catch (error) {\n console.error('Multiline text plugin: Error in show', error);\n // Fall back to original method\n if (this.original_methods.show) {\n this.original_methods.show(keep_center);\n }\n }\n }\n\n /**\n * Render multiline text in node display.\n * @param {HTMLElement} element - Node element\n * @param {import('../jsmind.node.js').Node} node - Node data\n */\n _render_multiline_node(element, node) {\n if (!node.topic) {\n return;\n }\n\n // Store original dimensions\n const originalHeight = element.clientHeight;\n\n // Process multiline text for display\n const text = node.topic;\n if (text.includes('\\n')) {\n // Handle multiline text - use textContent with CSS white-space\n element.innerHTML = '';\n element.textContent = text;\n\n // Apply CSS to handle line breaks properly\n element.style.whiteSpace = 'pre-wrap';\n element.style.wordBreak = 'break-word';\n } else {\n // Use original rendering for single-line text\n element.style.whiteSpace = '';\n element.style.wordBreak = '';\n if (this.jm.view.opts.support_html) {\n $.h(element, text);\n } else {\n $.t(element, text);\n }\n }\n\n // Check if height changed and trigger layout update if needed\n const newHeight = element.clientHeight;\n if (originalHeight !== newHeight && originalHeight > 0) {\n // Use setTimeout to ensure DOM has updated before recalculating\n setTimeout(() => {\n this.recalculate_layout(node);\n }, 0);\n }\n }\n\n /**\n * Begin editing a node with multiline support.\n * @param {import('../jsmind.node.js').Node} node - Node to edit\n */\n edit_node_begin(node) {\n if (!node.topic) {\n console.warn(\"don't edit image nodes\");\n return;\n }\n\n if (this.editing_node != null) {\n this.edit_node_end();\n }\n\n this.editing_node = node;\n const view_data = node._data.view;\n const element = view_data.element;\n const topic = node.topic;\n\n // Create multiline editor\n this.create_multiline_editor(element, topic);\n }\n\n /**\n * Create contentEditable multiline editor.\n * @param {HTMLElement} element - Node element\n * @param {string} topic - Current text content\n */\n create_multiline_editor(element, topic) {\n // Create contentEditable div\n this.multiline_editor = $.c('div');\n this.multiline_editor.contentEditable = 'plaintext-only';\n this.multiline_editor.className = 'jsmind-multiline-editor';\n\n // Set initial content\n this.multiline_editor.textContent = topic;\n\n // Style the editor\n this.style_multiline_editor(element);\n\n // Add keyboard event handling\n this.setup_editor_events();\n\n // Replace element content with editor\n element.innerHTML = '';\n element.appendChild(this.multiline_editor);\n element.style.zIndex = 5;\n\n // Focus and select content\n this.multiline_editor.focus();\n this.select_all_text();\n }\n\n /**\n * Style the multiline editor.\n * @param {HTMLElement} element - Original node element\n */\n style_multiline_editor(element) {\n const ncs = getComputedStyle(element);\n const editor = this.multiline_editor;\n\n // Copy styles from original element\n editor.style.width =\n Math.max(\n element.clientWidth -\n parseInt(ncs.getPropertyValue('padding-left')) -\n parseInt(ncs.getPropertyValue('padding-right')),\n this.options.text_width\n ) + 'px';\n\n editor.style.minHeight = this.options.min_height + 'px';\n editor.style.lineHeight = this.options.line_height;\n editor.style.border =\n this.options.editor_border_width + ' solid ' + this.options.editor_border_color;\n editor.style.borderRadius = '4px';\n editor.style.padding = '4px';\n editor.style.outline = 'none';\n editor.style.resize = 'none';\n editor.style.overflow = 'hidden';\n editor.style.whiteSpace = 'pre-wrap';\n editor.style.wordWrap = 'break-word';\n }\n\n /**\n * Set up keyboard event handling for the editor.\n */\n setup_editor_events() {\n const editor = this.multiline_editor;\n\n $.on(editor, 'keydown', e => {\n this.handle_editor_keydown(e);\n });\n\n $.on(editor, 'blur', e => {\n // Delay to allow other events to process first\n setTimeout(() => {\n if (this.editing_node) {\n this.edit_node_end();\n }\n }, 100);\n });\n\n // Auto-resize editor as user types\n $.on(editor, 'input', e => {\n this.auto_resize_editor();\n });\n }\n\n /**\n * Handle keyboard events in the editor.\n * @param {KeyboardEvent} e - Keyboard event\n */\n handle_editor_keydown(e) {\n const key = e.key;\n const shiftKey = e.shiftKey;\n const ctrlKey = e.ctrlKey || e.metaKey;\n\n if (key === 'Enter') {\n if (shiftKey) {\n // Shift+Enter: Allow line break (default behavior)\n return;\n } else {\n // Enter: Save and exit\n e.preventDefault();\n this.edit_node_end();\n }\n } else if (key === 'Escape') {\n // Escape: Cancel editing\n e.preventDefault();\n this.cancel_editing();\n } else if (key === 'Tab') {\n // Tab: Save and exit (like Enter)\n e.preventDefault();\n this.edit_node_end();\n }\n }\n\n /**\n * Auto-resize editor based on content.\n */\n auto_resize_editor() {\n if (!this.options.auto_resize || !this.multiline_editor) {\n return;\n }\n\n const editor = this.multiline_editor;\n\n // Reset height to auto to get natural height\n editor.style.height = 'auto';\n\n // Set height to scroll height to fit content\n const scrollHeight = editor.scrollHeight;\n const minHeight = this.options.min_height;\n\n editor.style.height = Math.max(scrollHeight, minHeight) + 'px';\n }\n\n /**\n * Select all text in the editor.\n */\n select_all_text() {\n if (!this.multiline_editor) return;\n\n const range = $.d.createRange();\n range.selectNodeContents(this.multiline_editor);\n\n const selection = $.w.getSelection();\n selection.removeAllRanges();\n selection.addRange(range);\n }\n\n /**\n * End editing and save changes.\n */\n edit_node_end() {\n if (this.editing_node == null || !this.multiline_editor) {\n return;\n }\n\n const node = this.editing_node;\n const view_data = node._data.view;\n const element = view_data.element;\n const topic = this.multiline_editor.textContent || '';\n\n // Clean up editor\n this.cleanup_editor(element);\n\n // Process and validate text\n const processed_topic = this.process_multiline_text(topic);\n\n // Update node if text changed\n if (jsMind.util.text.is_empty(processed_topic) || node.topic === processed_topic) {\n // No change or empty text, just re-render\n this._render_multiline_node(element, node);\n } else {\n // Text changed, update node\n this.jm.update_node(node.id, processed_topic);\n }\n\n // Trigger layout recalculation\n this.recalculate_layout(node);\n\n // Reset editing state\n this.editing_node = null;\n this.multiline_editor = null;\n\n // Return focus to panel\n this.jm.view.e_panel.focus();\n }\n\n /**\n * Cancel editing without saving changes.\n */\n cancel_editing() {\n if (this.editing_node == null || !this.multiline_editor) {\n return;\n }\n\n const node = this.editing_node;\n const view_data = node._data.view;\n const element = view_data.element;\n\n // Clean up editor\n this.cleanup_editor(element);\n\n // Restore original content\n this._render_multiline_node(element, node);\n\n // Reset editing state\n this.editing_node = null;\n this.multiline_editor = null;\n\n // Return focus to panel\n this.jm.view.e_panel.focus();\n }\n\n /**\n * Clean up editor and restore element state.\n * @param {HTMLElement} element - Node element\n */\n cleanup_editor(element) {\n if (this.multiline_editor && this.multiline_editor.parentNode) {\n this.multiline_editor.parentNode.removeChild(this.multiline_editor);\n }\n element.style.zIndex = 'auto';\n }\n\n /**\n * Process and validate multiline text.\n * @param {string} text - Raw text from editor\n * @returns {string} Processed text\n */\n process_multiline_text(text) {\n if (!text) return '';\n\n // Trim whitespace but preserve internal line breaks\n text = text.trim();\n\n // Normalize line breaks to \\n\n text = text.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\n\n // Remove excessive consecutive line breaks (more than 2)\n text = text.replace(/\\n{3,}/g, '\\n\\n');\n\n return text;\n }\n\n /**\n * Re-render all existing nodes to apply multiline formatting.\n */\n rerender_existing_nodes() {\n if (!this.jm.mind || !this.jm.mind.nodes) {\n return;\n }\n\n // Re-render all nodes that have multiline text\n const nodes = this.jm.mind.nodes;\n for (const node_id in nodes) {\n const node = nodes[node_id];\n if (node.topic && node.topic.includes('\\n')) {\n const view_data = node._data.view;\n if (view_data && view_data.element) {\n this._render_multiline_node(view_data.element, node);\n }\n }\n }\n }\n\n /**\n * Recalculate layout after text changes.\n * @param {import('../jsmind.node.js').Node} node - Updated node\n */\n recalculate_layout(node) {\n // Clear layout cache to force recalculation\n this.jm.layout.cache_valid = false;\n\n // Clear any cached offset and point data for all nodes\n const nodes = this.jm.mind.nodes;\n for (let nodeid in nodes) {\n const n = nodes[nodeid];\n if (n._data.layout) {\n delete n._data.layout._offset_;\n delete n._data.layout._pout_;\n }\n }\n\n // Update node size first\n this.jm.view.update_node(node);\n\n // Trigger complete layout recalculation\n this.jm.layout.layout();\n\n // Redraw view with updated layout and lines\n this.jm.view.show();\n }\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 // Handle events if needed\n if (type === jsMind.event_type.resize) {\n // Handle resize events\n }\n }\n}\n\n/**\n * Multiline text plugin registration.\n * @type {import('../jsmind.plugin.js').Plugin<Partial<MultilineTextOptions>>}\n */\nexport const multiline_text_plugin = new jsMind.plugin('multiline_text', function (jm, options) {\n var mt = new MultilineText(jm, options);\n mt.init();\n jm.multiline_text = mt;\n});\n\njsMind.register_plugin(multiline_text_plugin);\n\nexport default MultilineText;\n"],"names":["jsMind","Error","$","DEFAULT_OPTIONS","text_width","editor_border_color","editor_border_width","save_shortcut","cancel_shortcut","newline_shortcut","auto_resize","min_height","line_height","MultilineText","constructor","jm","options","opts","util","json","merge","this","version","original_methods","editing_node","multiline_editor","init","override_view_methods","setup_event_listeners","rerender_existing_nodes","view","edit_node_begin","bind","edit_node_end","render_node","show","_render_multiline_node_wrapper","_show_wrapper","console","log","error","restore_original_methods","add_event_listener","type","data","jm_event_handle","element","node","_render_multiline_node","keep_center","topic","originalHeight","clientHeight","text","includes","innerHTML","textContent","style","whiteSpace","wordBreak","support_html","h","t","setTimeout","recalculate_layout","warn","_data","create_multiline_editor","c","contentEditable","className","style_multiline_editor","setup_editor_events","appendChild","zIndex","focus","select_all_text","ncs","getComputedStyle","editor","width","Math","max","clientWidth","parseInt","getPropertyValue","minHeight","lineHeight","border","borderRadius","padding","outline","resize","overflow","wordWrap","on","e","handle_editor_keydown","auto_resize_editor","key","shiftKey","ctrlKey","metaKey","preventDefault","cancel_editing","height","scrollHeight","range","d","createRange","selectNodeContents","selection","w","getSelection","removeAllRanges","addRange","cleanup_editor","processed_topic","process_multiline_text","is_empty","update_node","id","e_panel","parentNode","removeChild","trim","replace","mind","nodes","node_id","view_data","layout","cache_valid","nodeid","n","_offset_","_pout_","event_type","multiline_text_plugin","plugin","mt","multiline_text","register_plugin"],"mappings":"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"}
|