@umbraci/jsmind 0.9.3 → 0.9.4
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.
|
@@ -0,0 +1,16 @@
|
|
|
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
|
+
|
|
9
|
+
// Import all the modules from the source
|
|
10
|
+
import jsMind from '../src/jsmind.js';
|
|
11
|
+
|
|
12
|
+
// Export as default
|
|
13
|
+
export default jsMind;
|
|
14
|
+
|
|
15
|
+
// Also export named exports for compatibility
|
|
16
|
+
export const { mind, node, direction, event_type, $, plugin, register_plugin, util } = jsMind;
|
|
@@ -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")):"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.$,s={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},r={tagName:"span",clearElement:!0,applyStyles:!0,customClasses:[],customAttributes:{},customStyles:{},supportHtml:!1,preserveWhitespace:!0};function l(e,t,i={}){if(!(e&&e instanceof HTMLElement))throw new Error("renderTextToElement: element must be a valid DOM element");if(null==t)return console.warn("renderTextToElement: text is null or undefined, skipping render"),e;const s={};n.default.util.json.merge(s,r),n.default.util.json.merge(s,i),s.clearElement&&(e.innerHTML="");const l=String(t);if(s.customAttributes&&"object"==typeof s.customAttributes)for(const[t,i]of Object.entries(s.customAttributes))try{e.setAttribute(t,String(i))}catch(e){console.warn(`renderTextToElement: Failed to set attribute ${t}:`,e)}if(s.customClasses&&Array.isArray(s.customClasses))for(const t of s.customClasses)"string"==typeof t&&t.trim()&&e.classList.add(t.trim());if(l.includes("\n")?(e.textContent=l,s.applyStyles&&(e.style.whiteSpace="pre-wrap",e.style.wordBreak="break-word")):(s.applyStyles&&(e.style.whiteSpace="",e.style.wordBreak=""),s.supportHtml?o.h(e,l):o.t(e,l)),s.customStyles&&"object"==typeof s.customStyles)for(const[t,i]of Object.entries(s.customStyles))try{if(l.includes("\n")&&s.applyStyles){if("whiteSpace"===t||"white-space"===t){console.warn("renderTextToElement: Ignoring whiteSpace override for multiline text");continue}if("wordBreak"===t||"word-break"===t){console.warn("renderTextToElement: Ignoring wordBreak override for multiline text");continue}}e.style[t]=String(i)}catch(e){console.warn(`renderTextToElement: Failed to set style ${t}:`,e)}return e}function d(e,t={}){const i={};n.default.util.json.merge(i,r),n.default.util.json.merge(i,t);return l(o.c(i.tagName||"span"),e,{...i,clearElement:!1})}class _{constructor(e,t){var i={};n.default.util.json.merge(i,s),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),this.original_methods._custom_node_render=e._custom_node_render?e._custom_node_render.bind(e):null,this.original_methods._default_node_render=e._default_node_render?e._default_node_render.bind(e):null;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),this.original_methods._custom_node_render&&(e._custom_node_render=this.original_methods._custom_node_render),this.original_methods._default_node_render&&(e._default_node_render=this.original_methods._default_node_render)}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;l(e,t.topic,{clearElement:!0,applyStyles:!0,supportHtml:this.jm.view.opts.support_html||!1});i!==e.clientHeight&&i>0&&setTimeout(()=>{this.recalculate_layout(t)},0)}renderMultilineText(e,t,i={}){const o={supportHtml:this.jm.view.opts.support_html||!1},s={};return n.default.util.json.merge(s,o),n.default.util.json.merge(s,i),l(e,t,s)}createMultilineElement(e,t={}){const i={supportHtml:this.jm.view.opts.support_html||!1},o={};return n.default.util.json.merge(o,i),n.default.util.json.merge(o,t),d(e,o)}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,this.jm.view.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.wordBreak="break-word"}setup_editor_events(){const e=this.multiline_editor;o.on(e,"keydown",e=>{this.handle_editor_keydown(e)}),o.on(e,"blur",()=>{setTimeout(()=>{this.editing_node&&this.edit_node_end()},100)}),o.on(e,"input",()=>{this.auto_resize_editor()})}handle_editor_keydown(e){const t=e.key,i=e.shiftKey;if("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.jm.view.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.jm.view.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 u=new n.default.plugin("multiline_text",function(e,t){var i=new _(e,t);i.init(),e.multiline_text=i});n.default.register_plugin(u),e.MultilineText=_,e.createTextElement=d,e.default=_,e.multiline_text_plugin=u,e.renderTextToElement=l,Object.defineProperty(e,"__esModule",{value:!0})});
|
|
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.$,s={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},r={tagName:"span",clearElement:!0,applyStyles:!0,customClasses:[],customAttributes:{},customStyles:{},supportHtml:!1,preserveWhitespace:!0};function l(e,t,i={}){if(!(e&&e instanceof HTMLElement))throw new Error("renderTextToElement: element must be a valid DOM element");if(null==t)return console.warn("renderTextToElement: text is null or undefined, skipping render"),e;const s={};n.default.util.json.merge(s,r),n.default.util.json.merge(s,i),s.clearElement&&(e.innerHTML="");const l=String(t);if(s.customAttributes&&"object"==typeof s.customAttributes)for(const[t,i]of Object.entries(s.customAttributes))try{e.setAttribute(t,String(i))}catch(e){console.warn(`renderTextToElement: Failed to set attribute ${t}:`,e)}if(s.customClasses&&Array.isArray(s.customClasses))for(const t of s.customClasses)"string"==typeof t&&t.trim()&&e.classList.add(t.trim());if(l.includes("\n")?(e.textContent=l,s.applyStyles&&(e.style.whiteSpace="pre-wrap",e.style.wordBreak="break-word")):(s.applyStyles&&(e.style.whiteSpace="",e.style.wordBreak=""),s.supportHtml?o.h(e,l):o.t(e,l)),s.customStyles&&"object"==typeof s.customStyles)for(const[t,i]of Object.entries(s.customStyles))try{if(l.includes("\n")&&s.applyStyles){if("whiteSpace"===t||"white-space"===t){console.warn("renderTextToElement: Ignoring whiteSpace override for multiline text");continue}if("wordBreak"===t||"word-break"===t){console.warn("renderTextToElement: Ignoring wordBreak override for multiline text");continue}}e.style[t]=String(i)}catch(e){console.warn(`renderTextToElement: Failed to set style ${t}:`,e)}return e}function d(e,t={}){const i={};n.default.util.json.merge(i,r),n.default.util.json.merge(i,t);return l(o.c(i.tagName||"span"),e,{...i,clearElement:!1})}class _{constructor(e,t){var i={};n.default.util.json.merge(i,s),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),this.original_methods._custom_node_render=e._custom_node_render?e._custom_node_render.bind(e):null,this.original_methods._default_node_render=e._default_node_render?e._default_node_render.bind(e):null;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),this.original_methods._custom_node_render&&(e._custom_node_render=this.original_methods._custom_node_render),this.original_methods._default_node_render&&(e._default_node_render=this.original_methods._default_node_render)}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;let n=!1;if(this.jm.view.opts.custom_node_render&&"function"==typeof this.jm.view.opts.custom_node_render)try{n=this.jm.view.opts.custom_node_render(this.jm,e,t)}catch(e){console.error("Multiline text plugin: Error in custom_node_render",e),n=!1}n||l(e,t.topic,{clearElement:!0,applyStyles:!0,supportHtml:this.jm.view.opts.support_html||!1});i!==e.clientHeight&&i>0&&setTimeout(()=>{this.recalculate_layout(t)},0)}renderMultilineText(e,t,i={}){const o={supportHtml:this.jm.view.opts.support_html||!1},s={};return n.default.util.json.merge(s,o),n.default.util.json.merge(s,i),l(e,t,s)}createMultilineElement(e,t={}){const i={supportHtml:this.jm.view.opts.support_html||!1},o={};return n.default.util.json.merge(o,i),n.default.util.json.merge(o,t),d(e,o)}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,this.jm.view.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.wordBreak="break-word"}setup_editor_events(){const e=this.multiline_editor;o.on(e,"keydown",e=>{this.handle_editor_keydown(e)}),o.on(e,"blur",()=>{setTimeout(()=>{this.editing_node&&this.edit_node_end()},100)}),o.on(e,"input",()=>{this.auto_resize_editor()})}handle_editor_keydown(e){const t=e.key,i=e.shiftKey;if("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.jm.view.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.jm.view.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 u=new n.default.plugin("multiline_text",function(e,t){var i=new _(e,t);i.init(),e.multiline_text=i});n.default.register_plugin(u),e.MultilineText=_,e.createTextElement=d,e.default=_,e.multiline_text_plugin=u,e.renderTextToElement=l,Object.defineProperty(e,"__esModule",{value:!0})});
|
|
9
9
|
//# sourceMappingURL=jsmind.multiline-text.js.map
|
|
@@ -1 +1 @@
|
|
|
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 * Default options for text rendering functions.\n * @typedef {Object} TextRenderOptions\n * @property {string} [tagName='span'] - HTML tag name for created elements\n * @property {boolean} [clearElement=true] - Whether to clear existing element content\n * @property {boolean} [applyStyles=true] - Whether to apply multiline CSS styles\n * @property {string[]} [customClasses=[]] - Array of CSS class names to add\n * @property {Object} [customAttributes={}] - Object of HTML attributes to set\n * @property {Object} [customStyles={}] - Object of inline styles to apply\n * @property {boolean} [supportHtml=false] - Whether to support HTML content\n * @property {boolean} [preserveWhitespace=true] - Whether to preserve whitespace in multiline text\n */\nconst DEFAULT_RENDER_OPTIONS = {\n tagName: 'span',\n clearElement: true,\n applyStyles: true,\n customClasses: [],\n customAttributes: {},\n customStyles: {},\n supportHtml: false,\n preserveWhitespace: true\n};\n\n/**\n * Static utility function to render text content into an existing DOM element.\n *\n * This function handles both single-line and multiline text rendering with proper CSS styling.\n * For multiline text (containing \\n), it applies 'white-space: pre-wrap' and 'word-break: break-word'.\n * For single-line text, it uses standard text or HTML rendering based on supportHtml option.\n *\n * @param {HTMLElement} element - Target DOM element to render text into\n * @param {string} text - Text content to render (supports \\n for line breaks)\n * @param {Partial<TextRenderOptions>} [options={}] - Rendering options\n * @param {string} [options.tagName='span'] - HTML tag name (only used when creating new elements)\n * @param {boolean} [options.clearElement=true] - Whether to clear existing element content\n * @param {boolean} [options.applyStyles=true] - Whether to apply multiline CSS styles\n * @param {string[]} [options.customClasses=[]] - Array of CSS class names to add\n * @param {Object} [options.customAttributes={}] - Object of HTML attributes to set\n * @param {Object} [options.customStyles={}] - Object of inline styles to apply\n * @param {boolean} [options.supportHtml=false] - Whether to support HTML content in single-line text\n * @param {boolean} [options.preserveWhitespace=true] - Whether to preserve whitespace in multiline text\n * @returns {HTMLElement} The element with rendered text content\n * @throws {Error} If element is not a valid DOM element\n *\n * @example\n * // Basic multiline text rendering\n * const element = document.createElement('div');\n * renderTextToElement(element, 'Line 1\\nLine 2\\nLine 3');\n *\n * @example\n * // Custom styling and attributes\n * renderTextToElement(element, 'Custom text', {\n * customClasses: ['highlight', 'bold'],\n * customAttributes: { 'data-id': '123' },\n * customStyles: { color: 'red', fontSize: '14px' }\n * });\n *\n * @example\n * // HTML support for single-line text\n * renderTextToElement(element, '<strong>Bold text</strong>', {\n * supportHtml: true\n * });\n */\nexport function renderTextToElement(element, text, options = {}) {\n // Validate parameters\n if (!element || !(element instanceof HTMLElement)) {\n throw new Error('renderTextToElement: element must be a valid DOM element');\n }\n\n if (text == null) {\n console.warn('renderTextToElement: text is null or undefined, skipping render');\n return element;\n }\n\n // Merge options with defaults\n const opts = {};\n jsMind.util.json.merge(opts, DEFAULT_RENDER_OPTIONS);\n jsMind.util.json.merge(opts, options);\n\n // Clear element content if requested\n if (opts.clearElement) {\n element.innerHTML = '';\n }\n\n // Convert text to string\n const textContent = String(text);\n\n // Apply custom attributes\n if (opts.customAttributes && typeof opts.customAttributes === 'object') {\n for (const [key, value] of Object.entries(opts.customAttributes)) {\n try {\n element.setAttribute(key, String(value));\n } catch (error) {\n console.warn(`renderTextToElement: Failed to set attribute ${key}:`, error);\n }\n }\n }\n\n // Apply custom classes\n if (opts.customClasses && Array.isArray(opts.customClasses)) {\n for (const className of opts.customClasses) {\n if (typeof className === 'string' && className.trim()) {\n element.classList.add(className.trim());\n }\n }\n }\n\n // Render text content\n if (textContent.includes('\\n')) {\n // Handle multiline text\n element.textContent = textContent;\n\n if (opts.applyStyles) {\n // Apply multiline styles (these take precedence over custom styles)\n element.style.whiteSpace = 'pre-wrap';\n element.style.wordBreak = 'break-word';\n }\n } else {\n // Handle single-line text\n if (opts.applyStyles) {\n // Reset multiline styles for single-line text\n element.style.whiteSpace = '';\n element.style.wordBreak = '';\n }\n\n // Render based on HTML support\n if (opts.supportHtml) {\n $.h(element, textContent);\n } else {\n $.t(element, textContent);\n }\n }\n\n // Apply custom styles (after multiline styles to allow overrides where appropriate)\n if (opts.customStyles && typeof opts.customStyles === 'object') {\n for (const [property, value] of Object.entries(opts.customStyles)) {\n try {\n // Don't override critical multiline styles if text is multiline\n if (textContent.includes('\\n') && opts.applyStyles) {\n if (property === 'whiteSpace' || property === 'white-space') {\n console.warn('renderTextToElement: Ignoring whiteSpace override for multiline text');\n continue;\n }\n if (property === 'wordBreak' || property === 'word-break') {\n console.warn('renderTextToElement: Ignoring wordBreak override for multiline text');\n continue;\n }\n }\n element.style[property] = String(value);\n } catch (error) {\n console.warn(`renderTextToElement: Failed to set style ${property}:`, error);\n }\n }\n }\n\n return element;\n}\n\n/**\n * Static utility function to create a new DOM element with rendered text content.\n *\n * This function creates a new DOM element and renders text content into it using the same\n * logic as renderTextToElement. It's useful when you need a new element rather than\n * modifying an existing one.\n *\n * @param {string} text - Text content to render (supports \\n for line breaks)\n * @param {Partial<TextRenderOptions>} [options={}] - Rendering options\n * @param {string} [options.tagName='span'] - HTML tag name for the created element\n * @param {boolean} [options.applyStyles=true] - Whether to apply multiline CSS styles\n * @param {string[]} [options.customClasses=[]] - Array of CSS class names to add\n * @param {Object} [options.customAttributes={}] - Object of HTML attributes to set\n * @param {Object} [options.customStyles={}] - Object of inline styles to apply\n * @param {boolean} [options.supportHtml=false] - Whether to support HTML content in single-line text\n * @returns {HTMLElement} New DOM element with rendered text content\n *\n * @example\n * // Create a div with multiline text\n * const textDiv = createTextElement('Line 1\\nLine 2', {\n * tagName: 'div',\n * customClasses: ['multiline-text']\n * });\n *\n * @example\n * // Create a span with custom styling\n * const styledSpan = createTextElement('Styled text', {\n * customStyles: {\n * backgroundColor: '#f0f0f0',\n * padding: '4px',\n * borderRadius: '4px'\n * }\n * });\n */\nexport function createTextElement(text, options = {}) {\n // Merge options with defaults\n const opts = {};\n jsMind.util.json.merge(opts, DEFAULT_RENDER_OPTIONS);\n jsMind.util.json.merge(opts, options);\n\n // Create new element\n const element = $.c(opts.tagName || 'span');\n\n // Use renderTextToElement to handle the rendering\n return renderTextToElement(element, text, { ...opts, clearElement: false });\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 // Store original custom render methods if they exist\n this.original_methods._custom_node_render = view._custom_node_render\n ? view._custom_node_render.bind(view)\n : null;\n this.original_methods._default_node_render = view._default_node_render\n ? view._default_node_render.bind(view)\n : null;\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 if (this.original_methods._custom_node_render) {\n view._custom_node_render = this.original_methods._custom_node_render;\n }\n if (this.original_methods._default_node_render) {\n view._default_node_render = this.original_methods._default_node_render;\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 with custom_node_render support.\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 for layout recalculation\n const originalHeight = element.clientHeight;\n\n // Use the new static rendering function with plugin configuration\n renderTextToElement(element, node.topic, {\n clearElement: true,\n applyStyles: true,\n supportHtml: this.jm.view.opts.support_html || false\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 * Plugin instance method to render text content into an existing DOM element.\n *\n * This method automatically uses jsMind configuration settings (like support_html)\n * and provides a convenient way to render multiline text within custom node renderers.\n *\n * @param {HTMLElement} element - Target DOM element to render text into\n * @param {string} text - Text content to render (supports \\n for line breaks)\n * @param {Partial<TextRenderOptions>} [options={}] - Additional rendering options\n * @returns {HTMLElement} The element with rendered text content\n *\n * @example\n * // In a custom node render function\n * customNodeRender(jm, element, node) {\n * const wrapper = document.createElement('div');\n * wrapper.style.backgroundColor = '#f0f0f0';\n * wrapper.style.padding = '4px';\n *\n * const textElement = document.createElement('span');\n * jm.multiline_text.renderMultilineText(textElement, node.topic);\n *\n * wrapper.appendChild(textElement);\n * element.appendChild(wrapper);\n * return true;\n * }\n */\n renderMultilineText(element, text, options = {}) {\n // Prepare options with jsMind configuration\n const defaultOptions = {\n supportHtml: this.jm.view.opts.support_html || false\n };\n\n // Merge with provided options\n const mergedOptions = {};\n jsMind.util.json.merge(mergedOptions, defaultOptions);\n jsMind.util.json.merge(mergedOptions, options);\n\n // Use static function with merged options\n return renderTextToElement(element, text, mergedOptions);\n }\n\n /**\n * Plugin instance method to create a new DOM element with rendered text content.\n *\n * This method automatically uses jsMind configuration settings and creates a new\n * element with properly rendered multiline text. Useful for building complex\n * custom node structures.\n *\n * @param {string} text - Text content to render (supports \\n for line breaks)\n * @param {Partial<TextRenderOptions>} [options={}] - Additional rendering options\n * @returns {HTMLElement} New DOM element with rendered text content\n *\n * @example\n * // Create a text element for insertion into custom structure\n * customNodeRender(jm, element, node) {\n * const container = document.createElement('div');\n * container.className = 'custom-node';\n *\n * // Add priority indicator\n * if (node.data?.priority) {\n * const priority = document.createElement('span');\n * priority.className = 'priority-badge';\n * priority.textContent = node.data.priority;\n * container.appendChild(priority);\n * }\n *\n * // Add multiline text content\n * const textElement = jm.multiline_text.createMultilineElement(node.topic, {\n * tagName: 'div',\n * customClasses: ['node-text']\n * });\n * container.appendChild(textElement);\n *\n * element.appendChild(container);\n * return true;\n * }\n */\n createMultilineElement(text, options = {}) {\n // Prepare options with jsMind configuration\n const defaultOptions = {\n supportHtml: this.jm.view.opts.support_html || false\n };\n\n // Merge with provided options\n const mergedOptions = {};\n jsMind.util.json.merge(mergedOptions, defaultOptions);\n jsMind.util.json.merge(mergedOptions, options);\n\n // Use static function with merged options\n return createTextElement(text, mergedOptions);\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\n this.jm.view.editing_node = node;\n\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.wordBreak = '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', () => {\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', () => {\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\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\n this.jm.view.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\n this.jm.view.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","DEFAULT_RENDER_OPTIONS","tagName","clearElement","applyStyles","customClasses","customAttributes","customStyles","supportHtml","preserveWhitespace","renderTextToElement","element","text","options","HTMLElement","console","warn","opts","util","json","merge","innerHTML","textContent","String","key","value","Object","entries","setAttribute","error","Array","isArray","className","trim","classList","add","includes","style","whiteSpace","wordBreak","h","t","property","createTextElement","c","MultilineText","constructor","jm","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","_custom_node_render","_default_node_render","_render_multiline_node_wrapper","_show_wrapper","log","restore_original_methods","add_event_listener","type","data","jm_event_handle","node","_render_multiline_node","keep_center","topic","originalHeight","clientHeight","support_html","setTimeout","recalculate_layout","renderMultilineText","defaultOptions","mergedOptions","createMultilineElement","_data","create_multiline_editor","contentEditable","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","on","e","handle_editor_keydown","auto_resize_editor","shiftKey","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","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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"}
|
|
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 * Default options for text rendering functions.\n * @typedef {Object} TextRenderOptions\n * @property {string} [tagName='span'] - HTML tag name for created elements\n * @property {boolean} [clearElement=true] - Whether to clear existing element content\n * @property {boolean} [applyStyles=true] - Whether to apply multiline CSS styles\n * @property {string[]} [customClasses=[]] - Array of CSS class names to add\n * @property {Object} [customAttributes={}] - Object of HTML attributes to set\n * @property {Object} [customStyles={}] - Object of inline styles to apply\n * @property {boolean} [supportHtml=false] - Whether to support HTML content\n * @property {boolean} [preserveWhitespace=true] - Whether to preserve whitespace in multiline text\n */\nconst DEFAULT_RENDER_OPTIONS = {\n tagName: 'span',\n clearElement: true,\n applyStyles: true,\n customClasses: [],\n customAttributes: {},\n customStyles: {},\n supportHtml: false,\n preserveWhitespace: true\n};\n\n/**\n * Static utility function to render text content into an existing DOM element.\n *\n * This function handles both single-line and multiline text rendering with proper CSS styling.\n * For multiline text (containing \\n), it applies 'white-space: pre-wrap' and 'word-break: break-word'.\n * For single-line text, it uses standard text or HTML rendering based on supportHtml option.\n *\n * @param {HTMLElement} element - Target DOM element to render text into\n * @param {string} text - Text content to render (supports \\n for line breaks)\n * @param {Partial<TextRenderOptions>} [options={}] - Rendering options\n * @param {string} [options.tagName='span'] - HTML tag name (only used when creating new elements)\n * @param {boolean} [options.clearElement=true] - Whether to clear existing element content\n * @param {boolean} [options.applyStyles=true] - Whether to apply multiline CSS styles\n * @param {string[]} [options.customClasses=[]] - Array of CSS class names to add\n * @param {Object} [options.customAttributes={}] - Object of HTML attributes to set\n * @param {Object} [options.customStyles={}] - Object of inline styles to apply\n * @param {boolean} [options.supportHtml=false] - Whether to support HTML content in single-line text\n * @param {boolean} [options.preserveWhitespace=true] - Whether to preserve whitespace in multiline text\n * @returns {HTMLElement} The element with rendered text content\n * @throws {Error} If element is not a valid DOM element\n *\n * @example\n * // Basic multiline text rendering\n * const element = document.createElement('div');\n * renderTextToElement(element, 'Line 1\\nLine 2\\nLine 3');\n *\n * @example\n * // Custom styling and attributes\n * renderTextToElement(element, 'Custom text', {\n * customClasses: ['highlight', 'bold'],\n * customAttributes: { 'data-id': '123' },\n * customStyles: { color: 'red', fontSize: '14px' }\n * });\n *\n * @example\n * // HTML support for single-line text\n * renderTextToElement(element, '<strong>Bold text</strong>', {\n * supportHtml: true\n * });\n */\nexport function renderTextToElement(element, text, options = {}) {\n // Validate parameters\n if (!element || !(element instanceof HTMLElement)) {\n throw new Error('renderTextToElement: element must be a valid DOM element');\n }\n\n if (text == null) {\n console.warn('renderTextToElement: text is null or undefined, skipping render');\n return element;\n }\n\n // Merge options with defaults\n const opts = {};\n jsMind.util.json.merge(opts, DEFAULT_RENDER_OPTIONS);\n jsMind.util.json.merge(opts, options);\n\n // Clear element content if requested\n if (opts.clearElement) {\n element.innerHTML = '';\n }\n\n // Convert text to string\n const textContent = String(text);\n\n // Apply custom attributes\n if (opts.customAttributes && typeof opts.customAttributes === 'object') {\n for (const [key, value] of Object.entries(opts.customAttributes)) {\n try {\n element.setAttribute(key, String(value));\n } catch (error) {\n console.warn(`renderTextToElement: Failed to set attribute ${key}:`, error);\n }\n }\n }\n\n // Apply custom classes\n if (opts.customClasses && Array.isArray(opts.customClasses)) {\n for (const className of opts.customClasses) {\n if (typeof className === 'string' && className.trim()) {\n element.classList.add(className.trim());\n }\n }\n }\n\n // Render text content\n if (textContent.includes('\\n')) {\n // Handle multiline text\n element.textContent = textContent;\n\n if (opts.applyStyles) {\n // Apply multiline styles (these take precedence over custom styles)\n element.style.whiteSpace = 'pre-wrap';\n element.style.wordBreak = 'break-word';\n }\n } else {\n // Handle single-line text\n if (opts.applyStyles) {\n // Reset multiline styles for single-line text\n element.style.whiteSpace = '';\n element.style.wordBreak = '';\n }\n\n // Render based on HTML support\n if (opts.supportHtml) {\n $.h(element, textContent);\n } else {\n $.t(element, textContent);\n }\n }\n\n // Apply custom styles (after multiline styles to allow overrides where appropriate)\n if (opts.customStyles && typeof opts.customStyles === 'object') {\n for (const [property, value] of Object.entries(opts.customStyles)) {\n try {\n // Don't override critical multiline styles if text is multiline\n if (textContent.includes('\\n') && opts.applyStyles) {\n if (property === 'whiteSpace' || property === 'white-space') {\n console.warn('renderTextToElement: Ignoring whiteSpace override for multiline text');\n continue;\n }\n if (property === 'wordBreak' || property === 'word-break') {\n console.warn('renderTextToElement: Ignoring wordBreak override for multiline text');\n continue;\n }\n }\n element.style[property] = String(value);\n } catch (error) {\n console.warn(`renderTextToElement: Failed to set style ${property}:`, error);\n }\n }\n }\n\n return element;\n}\n\n/**\n * Static utility function to create a new DOM element with rendered text content.\n *\n * This function creates a new DOM element and renders text content into it using the same\n * logic as renderTextToElement. It's useful when you need a new element rather than\n * modifying an existing one.\n *\n * @param {string} text - Text content to render (supports \\n for line breaks)\n * @param {Partial<TextRenderOptions>} [options={}] - Rendering options\n * @param {string} [options.tagName='span'] - HTML tag name for the created element\n * @param {boolean} [options.applyStyles=true] - Whether to apply multiline CSS styles\n * @param {string[]} [options.customClasses=[]] - Array of CSS class names to add\n * @param {Object} [options.customAttributes={}] - Object of HTML attributes to set\n * @param {Object} [options.customStyles={}] - Object of inline styles to apply\n * @param {boolean} [options.supportHtml=false] - Whether to support HTML content in single-line text\n * @returns {HTMLElement} New DOM element with rendered text content\n *\n * @example\n * // Create a div with multiline text\n * const textDiv = createTextElement('Line 1\\nLine 2', {\n * tagName: 'div',\n * customClasses: ['multiline-text']\n * });\n *\n * @example\n * // Create a span with custom styling\n * const styledSpan = createTextElement('Styled text', {\n * customStyles: {\n * backgroundColor: '#f0f0f0',\n * padding: '4px',\n * borderRadius: '4px'\n * }\n * });\n */\nexport function createTextElement(text, options = {}) {\n // Merge options with defaults\n const opts = {};\n jsMind.util.json.merge(opts, DEFAULT_RENDER_OPTIONS);\n jsMind.util.json.merge(opts, options);\n\n // Create new element\n const element = $.c(opts.tagName || 'span');\n\n // Use renderTextToElement to handle the rendering\n return renderTextToElement(element, text, { ...opts, clearElement: false });\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 // Store original custom render methods if they exist\n this.original_methods._custom_node_render = view._custom_node_render\n ? view._custom_node_render.bind(view)\n : null;\n this.original_methods._default_node_render = view._default_node_render\n ? view._default_node_render.bind(view)\n : null;\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 if (this.original_methods._custom_node_render) {\n view._custom_node_render = this.original_methods._custom_node_render;\n }\n if (this.original_methods._default_node_render) {\n view._default_node_render = this.original_methods._default_node_render;\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 with custom_node_render support.\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 for layout recalculation\n const originalHeight = element.clientHeight;\n\n // Check if we have custom node render function\n const hasCustomRender =\n this.jm.view.opts.custom_node_render &&\n typeof this.jm.view.opts.custom_node_render === 'function';\n\n let customRendered = false;\n\n if (hasCustomRender) {\n // Try custom render first\n try {\n customRendered = this.jm.view.opts.custom_node_render(this.jm, element, node);\n } catch (error) {\n console.error('Multiline text plugin: Error in custom_node_render', error);\n customRendered = false;\n }\n }\n\n // If custom render didn't handle it, use our multiline logic\n if (!customRendered) {\n // Use the new static rendering function with plugin configuration\n renderTextToElement(element, node.topic, {\n clearElement: true,\n applyStyles: true,\n supportHtml: this.jm.view.opts.support_html || false,\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 * Plugin instance method to render text content into an existing DOM element.\n *\n * This method automatically uses jsMind configuration settings (like support_html)\n * and provides a convenient way to render multiline text within custom node renderers.\n *\n * @param {HTMLElement} element - Target DOM element to render text into\n * @param {string} text - Text content to render (supports \\n for line breaks)\n * @param {Partial<TextRenderOptions>} [options={}] - Additional rendering options\n * @returns {HTMLElement} The element with rendered text content\n *\n * @example\n * // In a custom node render function\n * customNodeRender(jm, element, node) {\n * const wrapper = document.createElement('div');\n * wrapper.style.backgroundColor = '#f0f0f0';\n * wrapper.style.padding = '4px';\n *\n * const textElement = document.createElement('span');\n * jm.multiline_text.renderMultilineText(textElement, node.topic);\n *\n * wrapper.appendChild(textElement);\n * element.appendChild(wrapper);\n * return true;\n * }\n */\n renderMultilineText(element, text, options = {}) {\n // Prepare options with jsMind configuration\n const defaultOptions = {\n supportHtml: this.jm.view.opts.support_html || false\n };\n\n // Merge with provided options\n const mergedOptions = {};\n jsMind.util.json.merge(mergedOptions, defaultOptions);\n jsMind.util.json.merge(mergedOptions, options);\n\n // Use static function with merged options\n return renderTextToElement(element, text, mergedOptions);\n }\n\n /**\n * Plugin instance method to create a new DOM element with rendered text content.\n *\n * This method automatically uses jsMind configuration settings and creates a new\n * element with properly rendered multiline text. Useful for building complex\n * custom node structures.\n *\n * @param {string} text - Text content to render (supports \\n for line breaks)\n * @param {Partial<TextRenderOptions>} [options={}] - Additional rendering options\n * @returns {HTMLElement} New DOM element with rendered text content\n *\n * @example\n * // Create a text element for insertion into custom structure\n * customNodeRender(jm, element, node) {\n * const container = document.createElement('div');\n * container.className = 'custom-node';\n *\n * // Add priority indicator\n * if (node.data?.priority) {\n * const priority = document.createElement('span');\n * priority.className = 'priority-badge';\n * priority.textContent = node.data.priority;\n * container.appendChild(priority);\n * }\n *\n * // Add multiline text content\n * const textElement = jm.multiline_text.createMultilineElement(node.topic, {\n * tagName: 'div',\n * customClasses: ['node-text']\n * });\n * container.appendChild(textElement);\n *\n * element.appendChild(container);\n * return true;\n * }\n */\n createMultilineElement(text, options = {}) {\n // Prepare options with jsMind configuration\n const defaultOptions = {\n supportHtml: this.jm.view.opts.support_html || false\n };\n\n // Merge with provided options\n const mergedOptions = {};\n jsMind.util.json.merge(mergedOptions, defaultOptions);\n jsMind.util.json.merge(mergedOptions, options);\n\n // Use static function with merged options\n return createTextElement(text, mergedOptions);\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\n this.jm.view.editing_node = node;\n\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.wordBreak = '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', () => {\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', () => {\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\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\n this.jm.view.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\n this.jm.view.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","DEFAULT_RENDER_OPTIONS","tagName","clearElement","applyStyles","customClasses","customAttributes","customStyles","supportHtml","preserveWhitespace","renderTextToElement","element","text","options","HTMLElement","console","warn","opts","util","json","merge","innerHTML","textContent","String","key","value","Object","entries","setAttribute","error","Array","isArray","className","trim","classList","add","includes","style","whiteSpace","wordBreak","h","t","property","createTextElement","c","MultilineText","constructor","jm","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","_custom_node_render","_default_node_render","_render_multiline_node_wrapper","_show_wrapper","log","restore_original_methods","add_event_listener","type","data","jm_event_handle","node","_render_multiline_node","keep_center","topic","originalHeight","clientHeight","customRendered","custom_node_render","support_html","setTimeout","recalculate_layout","renderMultilineText","defaultOptions","mergedOptions","createMultilineElement","_data","create_multiline_editor","contentEditable","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","on","e","handle_editor_keydown","auto_resize_editor","shiftKey","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","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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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umbraci/jsmind",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.4",
|
|
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",
|