@umbraci/jsmind 0.10.8 → 0.10.9

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/es/jsmind.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"jsmind.js","sources":["../src/jsmind.common.js","../src/jsmind.dom.js","../src/jsmind.util.js","../src/jsmind.option.js","../src/jsmind.node.js","../src/jsmind.mind.js","../src/jsmind.format.js","../src/jsmind.data_provider.js","../src/jsmind.layout_provider.js","../src/jsmind.graph.js","../src/jsmind.view_provider.js","../src/jsmind.shortcut_provider.js","../src/jsmind.plugin.js","../src/jsmind.enhanced-plugin.js","../src/jsmind.js"],"sourcesContent":["/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\n/**\n * Library version string.\n * @type {string}\n */\nexport const __version__ = '0.9.0';\n/**\n * Library author.\n * @type {string}\n */\nexport const __author__ = 'UmbraCi';\n\nif (typeof String.prototype.startsWith != 'function') {\n String.prototype.startsWith = function (p) {\n return this.slice(0, p.length) === p;\n };\n}\n\n/**\n * Direction constants and parser.\n * @typedef {{left:number,center:number,right:number,of:(dir:(string|number))=>number|undefined}} DirectionType\n */\n/** @type {DirectionType} */\nexport const Direction = {\n left: -1,\n center: 0,\n right: 1,\n of: function (dir) {\n if (!dir || dir === -1 || dir === 0 || dir === 1) {\n return dir;\n }\n if (dir === '-1' || dir === '0' || dir === '1') {\n return parseInt(dir);\n }\n if (dir.toLowerCase() === 'left') {\n return this.left;\n }\n if (dir.toLowerCase() === 'right') {\n return this.right;\n }\n if (dir.toLowerCase() === 'center') {\n return this.center;\n }\n },\n};\n/** @enum {number} */\nexport const EventType = { show: 1, resize: 2, edit: 3, select: 4, reset: 5, history_change: 6 };\n/** @enum {number} */\nexport const Key = { meta: 1 << 13, ctrl: 1 << 12, alt: 1 << 11, shift: 1 << 10 };\n/** @enum {number} */\nexport const LogLevel = { debug: 1, info: 2, warn: 3, error: 4, disable: 9 };\n\n// an noop function define\nvar _noop = function () {};\n/**\n * Logger facade with dynamic level.\n * @type {{level:(lvl:number)=>void,log:Function,debug:Function,info:Function,warn:Function,error:Function}}\n */\nexport let logger =\n typeof console === 'undefined'\n ? {\n level: _noop,\n log: _noop,\n debug: _noop,\n info: _noop,\n warn: _noop,\n error: _noop,\n }\n : {\n level: setup_logger_level,\n log: console.log,\n debug: console.debug,\n info: console.info,\n warn: console.warn,\n error: console.error,\n };\n\n/**\n * Set logger level.\n * @param {number} log_level\n */\nfunction setup_logger_level(log_level) {\n if (log_level > LogLevel.debug) {\n logger.debug = _noop;\n } else {\n logger.debug = console.debug;\n }\n if (log_level > LogLevel.info) {\n logger.info = _noop;\n } else {\n logger.info = console.info;\n }\n if (log_level > LogLevel.warn) {\n logger.warn = _noop;\n } else {\n logger.warn = console.warn;\n }\n if (log_level > LogLevel.error) {\n logger.error = _noop;\n } else {\n logger.error = console.error;\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\n/**\n * Lightweight DOM helpers bound to a window.\n */\nclass Dom {\n /**\n * @param {Window} w\n */\n constructor(w) {\n /** @type {Window} */\n this.w = w;\n /** @type {Document} */\n this.d = w.document;\n /**\n * Get element by id.\n * @param {string} id\n * @returns {HTMLElement|null}\n */\n this.g = function (id) {\n return this.d.getElementById(id);\n };\n /**\n * Create element with given tag.\n * @param {string} tag\n * @returns {HTMLElement}\n */\n this.c = function (tag) {\n return this.d.createElement(tag);\n };\n /**\n * Set text content for element.\n * @param {HTMLElement} n\n * @param {string} t\n */\n this.t = function (n, t) {\n if (n.hasChildNodes()) {\n n.firstChild.nodeValue = t;\n } else {\n n.appendChild(this.d.createTextNode(t));\n }\n };\n\n /**\n * Set inner HTML or append element.\n * @param {HTMLElement} n\n * @param {string|HTMLElement} t\n */\n this.h = function (n, t) {\n if (t instanceof HTMLElement) {\n n.innerHTML = '';\n n.appendChild(t);\n } else {\n n.innerHTML = t;\n }\n };\n // detect isElement\n /**\n * Runtime check for HTMLElement.\n * @param {unknown} el\n * @returns {el is HTMLElement}\n */\n this.i = function (el) {\n return (\n !!el &&\n typeof el === 'object' &&\n el.nodeType === 1 &&\n typeof el.style === 'object' &&\n typeof el.ownerDocument === 'object'\n );\n };\n\n //target,eventType,handler\n /**\n * Add event listener with legacy fallback.\n * @param {HTMLElement} t\n * @param {string} e\n * @param {(ev:Event)=>void} h\n */\n this.on = function (t, e, h) {\n if (!!t.addEventListener) {\n t.addEventListener(e, h, false);\n } else {\n t.attachEvent('on' + e, h);\n }\n };\n }\n}\n\nexport const $ = new Dom(window);\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { $ } from './jsmind.dom.js';\n\n/**\n * Misc utility collection.\n * @type {{\n * file: { read: (file: File, cb:(result:string,name:string)=>void)=>void, save:(data:string,type:string,name:string)=>void},\n * json: { json2string:(v:unknown)=>string, string2json:(s:string)=>unknown, merge:(b:object,a:object)=>object },\n * uuid: { newid:()=>string },\n * text: { is_empty:(s?:string)=>boolean }\n * }}\n */\nexport const util = {\n file: {\n read: function (file_data, fn_callback) {\n var reader = new FileReader();\n reader.onload = function () {\n if (typeof fn_callback === 'function') {\n fn_callback(this.result, file_data.name);\n }\n };\n reader.readAsText(file_data);\n },\n\n save: function (file_data, type, name) {\n var blob;\n if (typeof $.w.Blob === 'function') {\n blob = new Blob([file_data], { type: type });\n } else {\n var BlobBuilder =\n $.w.BlobBuilder ||\n $.w.MozBlobBuilder ||\n $.w.WebKitBlobBuilder ||\n $.w.MSBlobBuilder;\n var bb = new BlobBuilder();\n bb.append(file_data);\n blob = bb.getBlob(type);\n }\n if (navigator.msSaveBlob) {\n navigator.msSaveBlob(blob, name);\n } else {\n var URL = $.w.URL || $.w.webkitURL;\n var blob_url = URL.createObjectURL(blob);\n var anchor = $.c('a');\n if ('download' in anchor) {\n anchor.style.visibility = 'hidden';\n anchor.href = blob_url;\n anchor.download = name;\n $.d.body.appendChild(anchor);\n var evt = $.d.createEvent('MouseEvents');\n evt.initEvent('click', true, true);\n anchor.dispatchEvent(evt);\n $.d.body.removeChild(anchor);\n } else {\n location.href = blob_url;\n }\n }\n },\n },\n\n json: {\n json2string: function (json) {\n return JSON.stringify(json);\n },\n string2json: function (json_str) {\n return JSON.parse(json_str);\n },\n merge: function (b, a) {\n for (var o in a) {\n if (o in b) {\n if (\n typeof b[o] === 'object' &&\n Object.prototype.toString.call(b[o]).toLowerCase() == '[object object]' &&\n !b[o].length\n ) {\n util.json.merge(b[o], a[o]);\n } else {\n b[o] = a[o];\n }\n } else {\n b[o] = a[o];\n }\n }\n return b;\n },\n },\n\n uuid: {\n newid: function () {\n return (\n new Date().getTime().toString(16) + Math.random().toString(16).substring(2)\n ).substring(2, 18);\n },\n },\n\n text: {\n is_empty: function (s) {\n if (!s) {\n return true;\n }\n return s.replace(/\\s*/, '').length == 0;\n },\n },\n};\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { util } from './jsmind.util.js';\n\n/**\n * @typedef {{\n * container: string|HTMLElement,\n * editable?: boolean,\n * theme?: (string|null),\n * mode?: ('full'|'side'),\n * support_html?: boolean,\n * log_level?: 'debug'|'info'|'warn'|'error'|'disable',\n * view?: {\n * engine?: 'canvas'|'svg',\n * enable_device_pixel_ratio?: boolean,\n * hmargin?: number,\n * vmargin?: number,\n * line_width?: number,\n * line_color?: string,\n * line_style?: 'curved'|'straight',\n * custom_line_render?: (this: object, arg:{ ctx: CanvasRenderingContext2D|SVGPathElement, start_point:{x:number,y:number}, end_point:{x:number,y:number} })=>void,\n * draggable?: boolean,\n * hide_scrollbars_when_draggable?: boolean,\n * node_overflow?: 'hidden'|'wrap'|'visible',\n * zoom?: { min?:number, max?:number, step?:number, mask_key?:number },\n * custom_node_render?: (null|((jm: import('./jsmind.js').default, ele: HTMLElement, node: import('./jsmind.node.js').Node)=>void)),\n * expander_style?: 'char'|'number'\n * },\n * layout?: { hspace?:number, vspace?:number, pspace?:number, cousin_space?:number },\n * default_event_handle?: { enable_mousedown_handle?:boolean, enable_click_handle?:boolean, enable_dblclick_handle?:boolean, enable_mousewheel_handle?:boolean },\n * shortcut?: { enable?:boolean, handles?: Record<string,(jm: import('./jsmind.js').default, e: KeyboardEvent)=>void>, mapping?: Record<string, number|number[]>, id_generator?: ()=>string },\n * fieldNames?: { id?:string, topic?:string, children?:string, parentid?:string, isroot?:string, direction?:string, expanded?:string },\n * plugin?: Record<string, object>\n * }} JsMindRuntimeOptions\n */\n/** @type {JsMindRuntimeOptions} */\nconst default_options = {\n container: '', // id of the container\n editable: false, // you can change it in your options\n theme: null,\n mode: 'full', // full or side\n support_html: true,\n log_level: 'info',\n\n view: {\n engine: 'canvas',\n enable_device_pixel_ratio: false,\n hmargin: 100,\n vmargin: 50,\n line_width: 2,\n line_color: '#555',\n line_style: 'curved', // [straight | curved]\n draggable: false, // drag the mind map with your mouse, when it's larger that the container\n hide_scrollbars_when_draggable: false, // hide container scrollbars, when mind map is larger than container and draggable option is true.\n node_overflow: 'hidden', // [hidden | wrap]\n zoom: {\n min: 0.5,\n max: 2.1,\n step: 0.1,\n mask_key: 4096,\n },\n custom_node_render: null,\n expander_style: 'char', // [char | number]\n },\n layout: {\n hspace: 30,\n vspace: 20,\n pspace: 13,\n cousin_space: 0,\n },\n default_event_handle: {\n enable_mousedown_handle: true,\n enable_click_handle: true,\n enable_dblclick_handle: true,\n enable_mousewheel_handle: true,\n },\n shortcut: {\n enable: true,\n handles: {},\n mapping: {\n addchild: [45, 4096 + 13], // Insert, Ctrl+Enter\n addbrother: 13, // Enter\n editnode: 113, // F2\n delnode: 46, // Delete\n toggle: 32, // Space\n left: 37, // Left\n up: 38, // Up\n right: 39, // Right\n down: 40, // Down\n },\n },\n // Field names mapping for custom data structure\n // Similar to Ant Design's fieldNames prop\n fieldNames: {\n id: 'id',\n topic: 'topic',\n children: 'children',\n parentid: 'parentid',\n isroot: 'isroot',\n direction: 'direction',\n expanded: 'expanded',\n },\n plugin: {},\n};\n\n/**\n * Merge user options with defaults. Throws if container missing.\n * @param {JsMindRuntimeOptions} options\n * @returns {JsMindRuntimeOptions}\n */\nexport function merge_option(options) {\n var opts = {};\n util.json.merge(opts, default_options);\n util.json.merge(opts, options);\n\n if (!opts.container) {\n throw new Error('the options.container should not be null or empty.');\n }\n return opts;\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { logger } from './jsmind.common.js';\nexport class Node {\n /**\n * Create a Node instance.\n * @param {string} sId - Node id\n * @param {number} iIndex - Node index (order among siblings). Use -1 for tail\n * @param {string} sTopic - Node topic text\n * @param {Record<string, any>=} oData - Arbitrary node data\n * @param {boolean=} bIsRoot - Whether it is the root node\n * @param {Node | null=} oParent - Parent node\n * @param {number=} eDirection - Direction for children under root (-1 left, 0 center, 1 right)\n * @param {boolean=} bExpanded - Expanded state\n */\n constructor(sId, iIndex, sTopic, oData, bIsRoot, oParent, eDirection, bExpanded) {\n if (!sId) {\n logger.error('invalid node id');\n return;\n }\n if (typeof iIndex != 'number') {\n logger.error('invalid node index');\n return;\n }\n if (typeof bExpanded === 'undefined') {\n bExpanded = true;\n }\n this.id = sId;\n this.index = iIndex;\n this.topic = sTopic;\n /** @type {Record<string, any>} */\n this.data = oData || {};\n this.isroot = bIsRoot;\n this.parent = oParent;\n this.direction = eDirection;\n this.expanded = !!bExpanded;\n /** @type {Node[]} */\n this.children = [];\n this._data = {};\n }\n\n /**\n * Get absolute location of this node in view coordinates.\n * @returns {{x:number,y:number}}\n */\n get_location() {\n var vd = this._data.view;\n return {\n x: vd.abs_x,\n y: vd.abs_y,\n };\n }\n /**\n * Get rendered size of this node.\n * @returns {{w:number,h:number}}\n */\n get_size() {\n var vd = this._data.view;\n return {\n w: vd.width,\n h: vd.height,\n };\n }\n\n /**\n * Compare two nodes by index for ordering.\n * @param {Node} node1\n * @param {Node} node2\n * @returns {number}\n */\n static compare(node1, node2) {\n // '-1' is always the latest\n var r = 0;\n var i1 = node1.index;\n var i2 = node2.index;\n if (i1 >= 0 && i2 >= 0) {\n r = i1 - i2;\n } else if (i1 == -1 && i2 == -1) {\n r = 0;\n } else if (i1 == -1) {\n r = 1;\n } else if (i2 == -1) {\n r = -1;\n } else {\n r = 0;\n }\n return r;\n }\n /**\n * Check if node is the same as or a descendant of parent_node.\n * @param {Node} parent_node\n * @param {Node} node\n * @returns {boolean}\n */\n static inherited(parent_node, node) {\n if (!!parent_node && !!node) {\n if (parent_node.id === node.id) {\n return true;\n }\n if (parent_node.isroot) {\n return true;\n }\n var pid = parent_node.id;\n var p = node;\n while (!p.isroot) {\n p = p.parent;\n if (p.id === pid) {\n return true;\n }\n }\n }\n return false;\n }\n /**\n * Runtime check for Node instance.\n * @param {unknown} n\n * @returns {n is Node}\n */\n static is_node(n) {\n return !!n && n instanceof Node;\n }\n\n /**\n * Convert node to plain object with custom field names.\n * @param {Record<string,string>=} fieldNames - Field names mapping\n * @param {boolean=} includeChildren - Whether to include children nodes (default: false)\n * @returns {Record<string, any>} Plain object representation of node\n */\n toObject(fieldNames, includeChildren = false) {\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var childrenKey = fn.children || 'children';\n var directionKey = fn.direction || 'direction';\n var expandedKey = fn.expanded || 'expanded';\n\n var obj = {};\n obj[idKey] = this.id;\n obj[topicKey] = this.topic;\n obj[expandedKey] = this.expanded;\n\n // Add direction for nodes under root\n if (!!this.parent && this.parent.isroot) {\n obj[directionKey] = this.direction === -1 ? 'left' : 'right';\n }\n\n // Add custom data properties\n if (this.data != null) {\n for (var k in this.data) {\n obj[k] = this.data[k];\n }\n }\n\n // Add children if requested\n if (includeChildren && this.children.length > 0) {\n obj[childrenKey] = this.children.map(child => child.toObject(fieldNames, true));\n }\n\n return obj;\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { Node } from './jsmind.node.js';\nimport { logger, Direction } from './jsmind.common.js';\n\nexport class Mind {\n /**\n * Mind model: holds nodes and selection.\n */\n constructor() {\n /** @type {string | null} */\n this.name = null;\n /** @type {string | null} */\n this.author = null;\n /** @type {string | null} */\n this.version = null;\n /** @type {Node | null} */\n this.root = null;\n /** @type {Node | null} */\n this.selected = null;\n /** @type {Record<string, Node>} */\n this.nodes = {};\n }\n /**\n * Get a node by id.\n * @param {string} node_id\n * @returns {Node | null}\n */\n get_node(node_id) {\n if (node_id in this.nodes) {\n return this.nodes[node_id];\n } else {\n logger.warn('the node[id=' + node_id + '] can not be found');\n return null;\n }\n }\n /**\n * Set the root node, only once.\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @returns {Node | null}\n */\n set_root(node_id, topic, data) {\n if (this.root == null) {\n this.root = new Node(node_id, 0, topic, data, true);\n this._put_node(this.root);\n return this.root;\n } else {\n logger.error('root node is already exist');\n return null;\n }\n }\n /**\n * Add a child node under parent.\n * @param {Node} parent_node\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @param {boolean=} expanded\n * @param {number=} idx\n * @returns {Node | null}\n */\n add_node(parent_node, node_id, topic, data, direction, expanded, idx) {\n if (!Node.is_node(parent_node)) {\n logger.error('the parent_node ' + parent_node + ' is not a node.');\n return null;\n }\n var node_index = idx || -1;\n var node = new Node(\n node_id,\n node_index,\n topic,\n data,\n false,\n parent_node,\n parent_node.direction,\n expanded\n );\n if (parent_node.isroot) {\n node.direction = direction || Direction.right;\n }\n if (this._put_node(node)) {\n parent_node.children.push(node);\n this._update_index(parent_node);\n } else {\n logger.error(\"fail, the node id '\" + node.id + \"' has been already exist.\");\n node = null;\n }\n return node;\n }\n /**\n * Insert a node before target node.\n * @param {Node} node_before\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @returns {Node | null}\n */\n insert_node_before(node_before, node_id, topic, data, direction) {\n if (!Node.is_node(node_before)) {\n logger.error('the node_before ' + node_before + ' is not a node.');\n return null;\n }\n var node_index = node_before.index - 0.5;\n return this.add_node(node_before.parent, node_id, topic, data, direction, true, node_index);\n }\n /**\n * Get previous sibling of a node or node id.\n * @param {string | Node} node\n * @returns {Node | null}\n */\n get_node_before(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return null;\n } else {\n return this.get_node_before(the_node);\n }\n }\n if (node.isroot) {\n return null;\n }\n var idx = node.index - 2;\n if (idx >= 0) {\n return node.parent.children[idx];\n } else {\n return null;\n }\n }\n /**\n * Insert a node after target node.\n * @param {Node} node_after\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @returns {Node | null}\n */\n insert_node_after(node_after, node_id, topic, data, direction) {\n if (!Node.is_node(node_after)) {\n logger.error('the node_after ' + node_after + ' is not a node.');\n return null;\n }\n var node_index = node_after.index + 0.5;\n return this.add_node(node_after.parent, node_id, topic, data, direction, true, node_index);\n }\n /**\n * Get next sibling of a node or node id.\n * @param {string | Node} node\n * @returns {Node | null}\n */\n get_node_after(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return null;\n } else {\n return this.get_node_after(the_node);\n }\n }\n if (node.isroot) {\n return null;\n }\n var idx = node.index;\n var brothers = node.parent.children;\n if (brothers.length > idx) {\n return node.parent.children[idx];\n } else {\n return null;\n }\n }\n /**\n * Move a node to new parent/position.\n * @param {Node} node\n * @param {string=} before_id - The ID of the node before which to place the moved node. Special values: \"_first_\", \"_last_\"\n * @param {string=} parent_id\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @returns {Node | null}\n */\n move_node(node, before_id, parent_id, direction) {\n if (!Node.is_node(node)) {\n logger.error('the parameter node ' + node + ' is not a node.');\n return null;\n }\n if (!parent_id) {\n parent_id = node.parent.id;\n }\n return this._move_node(node, before_id, parent_id, direction);\n }\n /**\n * Propagate direction to descendants.\n * @param {Node} node\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n */\n _flow_node_direction(node, direction) {\n if (typeof direction === 'undefined') {\n direction = node.direction;\n } else {\n node.direction = direction;\n }\n var len = node.children.length;\n while (len--) {\n this._flow_node_direction(node.children[len], direction);\n }\n }\n /**\n * Re-index node among siblings based on before_id marker.\n * @param {Node} node\n * @param {string} before_id\n * @returns {Node}\n */\n _move_node_internal(node, before_id) {\n if (!!node && !!before_id) {\n if (before_id == '_last_') {\n node.index = -1;\n this._update_index(node.parent);\n } else if (before_id == '_first_') {\n node.index = 0;\n this._update_index(node.parent);\n } else {\n var node_before = !!before_id ? this.get_node(before_id) : null;\n if (\n node_before != null &&\n node_before.parent != null &&\n node_before.parent.id == node.parent.id\n ) {\n node.index = node_before.index - 0.5;\n this._update_index(node.parent);\n }\n }\n }\n return node;\n }\n /**\n * Internal move implementation.\n * @param {Node} node\n * @param {string} before_id\n * @param {string} parent_id\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @returns {Node | null}\n */\n _move_node(node, before_id, parent_id, direction) {\n if (!!node && !!parent_id) {\n var parent_node = this.get_node(parent_id);\n if (Node.inherited(node, parent_node)) {\n logger.error('can not move a node to its children');\n return null;\n }\n if (node.parent.id != parent_id) {\n // remove from parent's children\n var sibling = node.parent.children;\n var si = sibling.length;\n while (si--) {\n if (sibling[si].id == node.id) {\n sibling.splice(si, 1);\n break;\n }\n }\n let origin_parent = node.parent;\n node.parent = parent_node;\n parent_node.children.push(node);\n this._update_index(origin_parent);\n }\n\n if (node.parent.isroot) {\n if (direction == Direction.left) {\n node.direction = direction;\n } else {\n node.direction = Direction.right;\n }\n } else {\n node.direction = node.parent.direction;\n }\n this._move_node_internal(node, before_id);\n this._flow_node_direction(node);\n }\n return node;\n }\n /**\n * Remove a node from the mind.\n * @param {Node} node\n * @returns {boolean}\n */\n remove_node(node) {\n if (!Node.is_node(node)) {\n logger.error('the parameter node ' + node + ' is not a node.');\n return false;\n }\n if (node.isroot) {\n logger.error('fail, can not remove root node');\n return false;\n }\n if (this.selected != null && this.selected.id == node.id) {\n this.selected = null;\n }\n // clean all subordinate nodes\n var children = node.children;\n var ci = children.length;\n while (ci--) {\n this.remove_node(children[ci]);\n }\n // clean all children\n children.length = 0;\n var node_parent = node.parent;\n // remove from parent's children\n var sibling = node_parent.children;\n var si = sibling.length;\n while (si--) {\n if (sibling[si].id == node.id) {\n sibling.splice(si, 1);\n break;\n }\n }\n // remove from global nodes\n delete this.nodes[node.id];\n // clean all properties\n for (var k in node) {\n delete node[k];\n }\n // remove it's self\n node = null;\n this._update_index(node_parent);\n return true;\n }\n /**\n * Put node into the map if id is not taken.\n * @param {Node} node\n * @returns {boolean}\n */\n _put_node(node) {\n if (node.id in this.nodes) {\n logger.warn(\"the node_id '\" + node.id + \"' has been already exist.\");\n return false;\n } else {\n this.nodes[node.id] = node;\n return true;\n }\n }\n /**\n * Re-index children by Node.compare.\n * @param {Node} node\n */\n _update_index(node) {\n if (node instanceof Node) {\n node.children.sort(Node.compare);\n for (var i = 0; i < node.children.length; i++) {\n node.children[i].index = i + 1;\n }\n }\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { __author__, __version__, logger, Direction } from './jsmind.common.js';\nimport { Mind } from './jsmind.mind.js';\nimport { Node } from './jsmind.node.js';\nimport { util } from './jsmind.util.js';\n\n/** @typedef {{name:string,author:string,version:string}} MindMapMeta */\n/**\n * Node tree data item\n *\n * Note: When using custom fieldNames configuration, the actual property names\n * in your data may differ from these type definitions. For example, if you\n * configure `fieldNames: { topic: 'name' }`, your data should use 'name'\n * instead of 'topic'. The types shown here represent the default field names.\n *\n * @typedef {{\n * id?: string,\n * topic?: string,\n * data?: Record<string, any>,\n * direction?: (number|string),\n * expanded?: boolean,\n * children?: NodeTreeData[],\n * [key: string]: any\n * }} NodeTreeData\n */\n/**\n * Node tree formatted payload\n * @typedef {{\n * meta?: MindMapMeta,\n * format: 'node_tree',\n * data: NodeTreeData\n * }} NodeTreeFormat\n */\n/**\n * Node array data item\n *\n * Note: When using custom fieldNames configuration, the actual property names\n * in your data may differ from these type definitions. For example, if you\n * configure `fieldNames: { topic: 'name', parentid: 'parent' }`, your data\n * should use 'name' and 'parent' instead of 'topic' and 'parentid'. The types\n * shown here represent the default field names.\n *\n * @typedef {{\n * id?: string,\n * topic?: string,\n * parentid?: string,\n * data?: Record<string, any>,\n * direction?: (number|string),\n * expanded?: boolean,\n * isroot?: boolean,\n * [key: string]: any\n * }} NodeArrayItem\n */\n/**\n * Node array formatted payload\n * @typedef {{\n * meta?: MindMapMeta,\n * format: 'node_array',\n * data: NodeArrayItem[]\n * }} NodeArrayFormat\n */\n/** @type {MindMapMeta} */\nconst DEFAULT_META = { name: 'jsMind', author: __author__, version: __version__ };\n\n/**\n * Mind data format handlers.\n * @type {{\n * node_tree: { example:NodeTreeFormat, get_mind:(src:NodeTreeFormat)=>Mind, get_data:(mind:Mind)=>NodeTreeFormat },\n * node_array: { example:NodeArrayFormat, get_mind:(src:NodeArrayFormat)=>Mind, get_data:(mind:Mind)=>NodeArrayFormat },\n * freemind: { example:{meta:MindMapMeta,format:'freemind',data:string}, get_mind:(src:{meta?:MindMapMeta,format:'freemind',data:string})=>Mind, get_data:(mind:Mind)=>{meta:MindMapMeta,format:'freemind',data:string} },\n * text: { example:{meta:MindMapMeta,format:'text',data:string}, get_mind:(src:{meta?:MindMapMeta,format:'text',data:string})=>Mind, get_data:(mind:Mind)=>{meta:MindMapMeta,format:'text',data:string} }\n * }}\n */\nexport const format = {\n node_tree: {\n example: {\n meta: DEFAULT_META,\n format: 'node_tree',\n data: { id: 'root', topic: 'jsMind node_tree example' },\n },\n /** @param {NodeTreeFormat} source @param {Record<string,string>=} fieldNames @returns {Mind} */\n get_mind: function (source, fieldNames) {\n var df = format.node_tree;\n var mind = new Mind();\n mind.name = source.meta.name;\n mind.author = source.meta.author;\n mind.version = source.meta.version;\n df._parse(mind, source.data, fieldNames);\n return mind;\n },\n /** @param {Mind} mind @param {Record<string,string>=} fieldNames */\n get_data: function (mind, fieldNames) {\n var df = format.node_tree;\n var json = {};\n json.meta = {\n name: mind.name,\n author: mind.author,\n version: mind.version,\n };\n json.format = 'node_tree';\n json.data = df._build_node(mind.root, fieldNames);\n return json;\n },\n\n /** @param {Mind} mind @param {NodeTreeData} node_root @param {Record<string,string>=} fieldNames */\n _parse: function (mind, node_root, fieldNames) {\n var df = format.node_tree;\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var childrenKey = fn.children || 'children';\n\n var data = df._extract_data(node_root, fieldNames);\n mind.set_root(node_root[idKey], node_root[topicKey], data);\n if (childrenKey in node_root) {\n var children = node_root[childrenKey];\n for (var i = 0; i < children.length; i++) {\n df._extract_subnode(mind, mind.root, children[i], fieldNames);\n }\n }\n },\n\n /**\n * Extract custom data from node JSON, excluding standard properties.\n * @private\n * @param {Record<string, unknown>} node_json - Node JSON object\n * @param {Record<string,string>=} fieldNames - Field names mapping\n * @returns {Record<string,any>} Custom data object\n */\n _extract_data: function (node_json, fieldNames) {\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var childrenKey = fn.children || 'children';\n var directionKey = fn.direction || 'direction';\n var expandedKey = fn.expanded || 'expanded';\n\n var data = {};\n for (var k in node_json) {\n if (\n k == idKey ||\n k == topicKey ||\n k == childrenKey ||\n k == directionKey ||\n k == expandedKey\n ) {\n continue;\n }\n data[k] = node_json[k];\n }\n return data;\n },\n\n /** @param {Mind} mind @param {Node} node_parent @param {NodeTreeData} node_json @param {Record<string,string>=} fieldNames */\n _extract_subnode: function (mind, node_parent, node_json, fieldNames) {\n var df = format.node_tree;\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var childrenKey = fn.children || 'children';\n var directionKey = fn.direction || 'direction';\n var expandedKey = fn.expanded || 'expanded';\n\n var data = df._extract_data(node_json, fieldNames);\n var d = null;\n if (node_parent.isroot) {\n d = node_json[directionKey] == 'left' ? Direction.left : Direction.right;\n }\n var node = mind.add_node(\n node_parent,\n node_json[idKey],\n node_json[topicKey],\n data,\n d,\n node_json[expandedKey]\n );\n if (!!node_json[childrenKey]) {\n var children = node_json[childrenKey];\n for (var i = 0; i < children.length; i++) {\n df._extract_subnode(mind, node, children[i], fieldNames);\n }\n }\n },\n\n /**\n * Build JSON object from a node.\n * @private\n * @param {Node} node - Node to convert\n * @param {Record<string,string>=} fieldNames - Field names mapping\n * @returns {NodeTreeData} JSON representation of node\n */\n _build_node: function (node, fieldNames) {\n var df = format.node_tree;\n if (!(node instanceof Node)) {\n return;\n }\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var childrenKey = fn.children || 'children';\n var directionKey = fn.direction || 'direction';\n var expandedKey = fn.expanded || 'expanded';\n\n var o = {};\n o[idKey] = node.id;\n o[topicKey] = node.topic;\n o[expandedKey] = node.expanded;\n\n if (!!node.parent && node.parent.isroot) {\n o[directionKey] = node.direction == Direction.left ? 'left' : 'right';\n }\n if (node.data != null) {\n var node_data = node.data;\n for (var k in node_data) {\n o[k] = node_data[k];\n }\n }\n var children = node.children;\n if (children.length > 0) {\n o[childrenKey] = [];\n for (var i = 0; i < children.length; i++) {\n o[childrenKey].push(df._build_node(children[i], fieldNames));\n }\n }\n return o;\n },\n },\n\n node_array: {\n example: {\n meta: DEFAULT_META,\n format: 'node_array',\n data: [{ id: 'root', topic: 'jsMind node_array example', isroot: true }],\n },\n\n /** @param {NodeArrayFormat} source @param {Record<string,string>=} fieldNames @returns {Mind} */\n get_mind: function (source, fieldNames) {\n var df = format.node_array;\n var mind = new Mind();\n mind.name = source.meta.name;\n mind.author = source.meta.author;\n mind.version = source.meta.version;\n df._parse(mind, source.data, fieldNames);\n return mind;\n },\n\n /** @param {Mind} mind @param {Record<string,string>=} fieldNames */\n get_data: function (mind, fieldNames) {\n var df = format.node_array;\n var json = {};\n json.meta = {\n name: mind.name,\n author: mind.author,\n version: mind.version,\n };\n json.format = 'node_array';\n json.data = [];\n df._array(mind, json.data, fieldNames);\n return json;\n },\n\n /** @param {Mind} mind @param {NodeArrayItem[]} node_array @param {Record<string,string>=} fieldNames */\n _parse: function (mind, node_array, fieldNames) {\n var df = format.node_array;\n var nodes = node_array.slice(0);\n // reverse array for improving looping performance\n nodes.reverse();\n var root_node = df._extract_root(mind, nodes, fieldNames);\n if (!!root_node) {\n df._extract_subnode(mind, root_node, nodes, fieldNames);\n } else {\n logger.error('root node can not be found');\n }\n },\n\n /** @param {Mind} mind @param {NodeArrayItem[]} node_array @param {Record<string,string>=} fieldNames */\n _extract_root: function (mind, node_array, fieldNames) {\n var df = format.node_array;\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var isrootKey = fn.isroot || 'isroot';\n\n var i = node_array.length;\n while (i--) {\n if (isrootKey in node_array[i] && node_array[i][isrootKey]) {\n var root_json = node_array[i];\n var data = df._extract_data(root_json, fieldNames);\n var node = mind.set_root(root_json[idKey], root_json[topicKey], data);\n node_array.splice(i, 1);\n return node;\n }\n }\n return null;\n },\n\n /** @param {Mind} mind @param {Node} parent_node @param {NodeArrayItem[]} node_array @param {Record<string,string>=} fieldNames */\n _extract_subnode: function (mind, parent_node, node_array, fieldNames) {\n var df = format.node_array;\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var parentidKey = fn.parentid || 'parentid';\n var directionKey = fn.direction || 'direction';\n var expandedKey = fn.expanded || 'expanded';\n\n var i = node_array.length;\n var node_json = null;\n var data = null;\n var extract_count = 0;\n while (i--) {\n node_json = node_array[i];\n if (node_json[parentidKey] == parent_node.id) {\n data = df._extract_data(node_json, fieldNames);\n var d = null;\n var node_direction = node_json[directionKey];\n if (!!node_direction) {\n d = node_direction == 'left' ? Direction.left : Direction.right;\n }\n var node = mind.add_node(\n parent_node,\n node_json[idKey],\n node_json[topicKey],\n data,\n d,\n node_json[expandedKey]\n );\n node_array.splice(i, 1);\n extract_count++;\n var sub_extract_count = df._extract_subnode(mind, node, node_array, fieldNames);\n if (sub_extract_count > 0) {\n // reset loop index after extract subordinate node\n i = node_array.length;\n extract_count += sub_extract_count;\n }\n }\n }\n return extract_count;\n },\n\n /** @param {Record<string, unknown>} node_json @param {Record<string,string>=} fieldNames */\n _extract_data: function (node_json, fieldNames) {\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var parentidKey = fn.parentid || 'parentid';\n var isrootKey = fn.isroot || 'isroot';\n var directionKey = fn.direction || 'direction';\n var expandedKey = fn.expanded || 'expanded';\n\n var data = {};\n for (var k in node_json) {\n if (\n k == idKey ||\n k == topicKey ||\n k == parentidKey ||\n k == isrootKey ||\n k == directionKey ||\n k == expandedKey\n ) {\n continue;\n }\n data[k] = node_json[k];\n }\n return data;\n },\n\n /** @param {Mind} mind @param {NodeArrayItem[]} node_array @param {Record<string,string>=} fieldNames */\n _array: function (mind, node_array, fieldNames) {\n var df = format.node_array;\n df._array_node(mind.root, node_array, fieldNames);\n },\n\n /** @param {Node} node @param {NodeArrayItem[]} node_array @param {Record<string,string>=} fieldNames */\n _array_node: function (node, node_array, fieldNames) {\n var df = format.node_array;\n if (!(node instanceof Node)) {\n return;\n }\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var parentidKey = fn.parentid || 'parentid';\n var isrootKey = fn.isroot || 'isroot';\n var directionKey = fn.direction || 'direction';\n var expandedKey = fn.expanded || 'expanded';\n\n var o = {};\n o[idKey] = node.id;\n o[topicKey] = node.topic;\n o[expandedKey] = node.expanded;\n\n if (!!node.parent) {\n o[parentidKey] = node.parent.id;\n }\n if (node.isroot) {\n o[isrootKey] = true;\n }\n if (!!node.parent && node.parent.isroot) {\n o[directionKey] = node.direction == Direction.left ? 'left' : 'right';\n }\n if (node.data != null) {\n var node_data = node.data;\n for (var k in node_data) {\n o[k] = node_data[k];\n }\n }\n node_array.push(o);\n var ci = node.children.length;\n for (var i = 0; i < ci; i++) {\n df._array_node(node.children[i], node_array, fieldNames);\n }\n },\n },\n\n freemind: {\n example: {\n meta: DEFAULT_META,\n format: 'freemind',\n data: '<map version=\"1.0.1\"><node ID=\"root\" TEXT=\"jsMind freemind example\"/></map>',\n },\n /** @param {{meta:MindMapMeta,data:string}} source @param {Record<string,string>=} fieldNames @returns {Mind} */\n get_mind: function (source, fieldNames) {\n var df = format.freemind;\n var mind = new Mind();\n mind.name = source.meta.name;\n mind.author = source.meta.author;\n mind.version = source.meta.version;\n var xml = source.data;\n var xml_doc = df._parse_xml(xml);\n var xml_root = df._find_root(xml_doc);\n // freemind format uses fixed XML attributes (ID, TEXT), fieldNames not applicable\n df._load_node(mind, null, xml_root);\n return mind;\n },\n\n /** @param {Mind} mind @param {Record<string,string>=} fieldNames */\n get_data: function (mind, fieldNames) {\n var df = format.freemind;\n var json = {};\n json.meta = {\n name: mind.name,\n author: mind.author,\n version: mind.version,\n };\n json.format = 'freemind';\n var xml_lines = [];\n xml_lines.push('<map version=\"1.0.1\">');\n // freemind format uses fixed XML attributes, fieldNames not applicable\n df._build_map(mind.root, xml_lines);\n xml_lines.push('</map>');\n json.data = xml_lines.join('');\n return json;\n },\n\n /** @param {string} xml */\n _parse_xml: function (xml) {\n var xml_doc = null;\n if (window.DOMParser) {\n var parser = new DOMParser();\n xml_doc = parser.parseFromString(xml, 'text/xml');\n } else {\n // Internet Explorer\n xml_doc = new ActiveXObject('Microsoft.XMLDOM');\n xml_doc.async = false;\n xml_doc.loadXML(xml);\n }\n return xml_doc;\n },\n\n /** @param {Document} xml_doc */\n _find_root: function (xml_doc) {\n var nodes = xml_doc.childNodes;\n var node = null;\n var root = null;\n var n = null;\n for (var i = 0; i < nodes.length; i++) {\n n = nodes[i];\n if (n.nodeType == 1 && n.tagName == 'map') {\n node = n;\n break;\n }\n }\n if (!!node) {\n var ns = node.childNodes;\n node = null;\n for (var i = 0; i < ns.length; i++) {\n n = ns[i];\n if (n.nodeType == 1 && n.tagName == 'node') {\n node = n;\n break;\n }\n }\n }\n return node;\n },\n\n /** @param {Mind} mind @param {Node|null} parent_node @param {Element} xml_node */\n _load_node: function (mind, parent_node, xml_node) {\n var df = format.freemind;\n var node_id = xml_node.getAttribute('ID');\n var node_topic = xml_node.getAttribute('TEXT');\n var node_folded = xml_node.getAttribute('FOLDED');\n // look for richcontent\n if (node_topic == null) {\n var topic_children = xml_node.childNodes;\n var topic_child = null;\n for (var i = 0; i < topic_children.length; i++) {\n topic_child = topic_children[i];\n if (topic_child.nodeType == 1 && topic_child.tagName === 'richcontent') {\n node_topic = topic_child.textContent;\n break;\n }\n }\n }\n var node_data = df._load_attributes(xml_node);\n var node_expanded =\n 'expanded' in node_data ? node_data.expanded == 'true' : node_folded != 'true';\n delete node_data.expanded;\n\n var node_foreground_color = xml_node.getAttribute('COLOR');\n if (!!node_foreground_color) {\n node_data['foreground-color'] = node_foreground_color;\n }\n\n var node_background_color = xml_node.getAttribute('BACKGROUND_COLOR');\n if (!!node_background_color) {\n node_data['background-color'] = node_background_color;\n }\n\n var node_position = xml_node.getAttribute('POSITION');\n var node_direction = null;\n if (!!node_position) {\n node_direction = node_position == 'left' ? Direction.left : Direction.right;\n }\n var node = null;\n if (!!parent_node) {\n node = mind.add_node(\n parent_node,\n node_id,\n node_topic,\n node_data,\n node_direction,\n node_expanded\n );\n } else {\n node = mind.set_root(node_id, node_topic, node_data);\n }\n var children = xml_node.childNodes;\n var child = null;\n for (var i = 0; i < children.length; i++) {\n child = children[i];\n if (child.nodeType == 1 && child.tagName == 'node') {\n df._load_node(mind, node, child);\n }\n }\n },\n\n /** @param {Element} xml_node */\n _load_attributes: function (xml_node) {\n var children = xml_node.childNodes;\n var attr = null;\n var attr_data = {};\n for (var i = 0; i < children.length; i++) {\n attr = children[i];\n if (attr.nodeType == 1 && attr.tagName === 'attribute') {\n attr_data[attr.getAttribute('NAME')] = attr.getAttribute('VALUE');\n }\n }\n return attr_data;\n },\n\n /** @param {Node} node @param {string[]} xml_lines */\n _build_map: function (node, xml_lines) {\n var df = format.freemind;\n var pos = null;\n var node_data = node.data;\n\n if (!!node.parent && node.parent.isroot) {\n pos = node.direction === Direction.left ? 'left' : 'right';\n }\n xml_lines.push('<node');\n xml_lines.push(' ID=\"' + node.id + '\"');\n if (!!pos) {\n xml_lines.push(' POSITION=\"' + pos + '\"');\n }\n if (!node.expanded) {\n xml_lines.push(' FOLDED=\"true\"');\n }\n if (!!node_data['foreground-color']) {\n xml_lines.push(' COLOR=\"' + node_data['foreground-color'] + '\"');\n }\n if (!!node_data['background-color']) {\n xml_lines.push(' BACKGROUND_COLOR=\"' + node_data['background-color'] + '\"');\n }\n xml_lines.push(' TEXT=\"' + df._escape(node.topic) + '\">');\n\n // for attributes\n if (node_data != null) {\n for (var k in node_data) {\n if (k === 'foreground-color' || k === 'background-color') {\n continue;\n }\n xml_lines.push('<attribute NAME=\"' + k + '\" VALUE=\"' + node_data[k] + '\"/>');\n }\n }\n\n // for children\n var children = node.children;\n for (var i = 0; i < children.length; i++) {\n df._build_map(children[i], xml_lines);\n }\n\n xml_lines.push('</node>');\n },\n\n /** @param {string} text */\n _escape: function (text) {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/'/g, '&apos;')\n .replace(/\"/g, '&quot;');\n },\n },\n text: {\n example: {\n meta: DEFAULT_META,\n format: 'text',\n data: 'jsMind text example\\n node1\\n node1-sub\\n node1-sub\\n node2',\n },\n _line_regex: /\\s*/,\n /** @param {{meta:MindMapMeta,data:string}} source @param {Record<string,string>=} fieldNames @returns {Mind} */\n get_mind: function (source, fieldNames) {\n var df = format.text;\n var mind = new Mind();\n mind.name = source.meta.name;\n mind.author = source.meta.author;\n mind.version = source.meta.version;\n var lines = source.data.split(/\\n|\\r/);\n // text format uses indentation-based structure, fieldNames not applicable\n df._fill_nodes(mind, lines, 0, 0);\n return mind;\n },\n\n /** @param {Mind} mind @param {string[]} lines */\n _fill_nodes: function (mind, lines) {\n let node_path = [];\n let i = 0;\n while (i < lines.length) {\n let line = lines[i];\n let level = line.match(/\\s*/)[0].length;\n let topic = line.substr(level);\n\n if (level == 0 && node_path.length > 0) {\n log.error('more than 1 root node was found: ' + topic);\n return;\n }\n if (level > node_path.length) {\n log.error('a suspended node was found: ' + topic);\n return;\n }\n let diff = node_path.length - level;\n while (diff--) {\n node_path.pop();\n }\n\n if (level == 0 && node_path.length == 0) {\n let node = mind.set_root(util.uuid.newid(), topic);\n node_path.push(node);\n } else {\n let node = mind.add_node(\n node_path[level - 1],\n util.uuid.newid(),\n topic,\n {},\n null\n );\n node_path.push(node);\n }\n i++;\n }\n node_path.length = 0;\n },\n\n /** @param {Mind} mind */\n get_data: function (mind) {\n var df = format.text;\n var json = {};\n json.meta = {\n name: mind.name,\n author: mind.author,\n version: mind.version,\n };\n json.format = 'text';\n let lines = [];\n df._build_lines(lines, [mind.root], 0);\n json.data = lines.join('\\n');\n return json;\n },\n\n /** @param {string[]} lines @param {Node[]} nodes @param {number} level */\n _build_lines: function (lines, nodes, level) {\n let prefix = new Array(level + 1).join(' ');\n for (let node of nodes) {\n lines.push(prefix + node.topic);\n if (!!node.children) {\n format.text._build_lines(lines, node.children, level + 1);\n }\n }\n },\n },\n};\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { logger } from './jsmind.common.js';\nimport { format } from './jsmind.format.js';\n\nexport class DataProvider {\n /**\n * Data provider: loads and serializes mind data by format.\n * @param {import('./jsmind.js').default} jm - jsMind instance\n */\n constructor(jm) {\n this.jm = jm;\n }\n\n /** Initialize data provider. */\n init() {\n logger.debug('data.init');\n }\n /** Reset data provider state. */\n reset() {\n logger.debug('data.reset');\n }\n /**\n * Load a Mind from mixed source.\n * @param {import('./jsmind.format.js').NodeTreeFormat|import('./jsmind.format.js').NodeArrayFormat|{meta?:{name:string,author:string,version:string},format:'freemind',data:string}|{meta?:{name:string,author:string,version:string},format:'text',data:string}} mind_data - object with {format,data} or a format-specific payload\n * @returns {import('./jsmind.mind.js').Mind|null}\n */\n load(mind_data) {\n var df = null;\n var mind = null;\n if (typeof mind_data === 'object') {\n if (!!mind_data.format) {\n df = mind_data.format;\n } else {\n df = 'node_tree';\n }\n } else {\n df = 'freemind';\n }\n\n var fieldNames = this.jm.options.fieldNames;\n if (df == 'node_array') {\n mind = format.node_array.get_mind(mind_data, fieldNames);\n } else if (df == 'node_tree') {\n mind = format.node_tree.get_mind(mind_data, fieldNames);\n } else if (df == 'freemind') {\n mind = format.freemind.get_mind(mind_data, fieldNames);\n } else if (df == 'text') {\n mind = format.text.get_mind(mind_data, fieldNames);\n } else {\n logger.warn('unsupported format');\n }\n return mind;\n }\n /**\n * Serialize current mind to target format.\n * @param {'node_tree'|'node_array'|'freemind'|'text'} data_format\n * @returns {import('./jsmind.format.js').NodeTreeFormat|import('./jsmind.format.js').NodeArrayFormat|{meta:{name:string,author:string,version:string},format:'freemind',data:string}|{meta:{name:string,author:string,version:string},format:'text',data:string}}\n */\n get_data(data_format) {\n var data = null;\n var fieldNames = this.jm.options.fieldNames;\n if (data_format == 'node_array') {\n data = format.node_array.get_data(this.jm.mind, fieldNames);\n } else if (data_format == 'node_tree') {\n data = format.node_tree.get_data(this.jm.mind, fieldNames);\n } else if (data_format == 'freemind') {\n data = format.freemind.get_data(this.jm.mind);\n } else if (data_format == 'text') {\n data = format.text.get_data(this.jm.mind);\n } else {\n logger.error('unsupported ' + data_format + ' format');\n }\n return data;\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\nimport { logger, Direction, EventType } from './jsmind.common.js';\n\nexport class LayoutProvider {\n /**\n * Layout engine for positioning nodes and lines.\n * @param {import('./jsmind.js').default} jm - jsMind instance\n * @param {{mode:'full'|'side', hspace:number, vspace:number, pspace:number, cousin_space:number}} options - Layout configuration options\n */\n constructor(jm, options) {\n this.opts = options;\n this.jm = jm;\n this.isside = this.opts.mode == 'side';\n this.bounds = null;\n\n this.cache_valid = false;\n }\n /** Initialize layout provider. */\n init() {\n logger.debug('layout.init');\n }\n /** Reset layout state and bounds. */\n reset() {\n logger.debug('layout.reset');\n this.bounds = { n: 0, s: 0, w: 0, e: 0 };\n }\n /**\n * Decide the next child's direction for a parent node.\n * @param {import('./jsmind.node.js').Node} node\n * @returns {number}\n */\n calculate_next_child_direction(node) {\n if (this.isside) {\n return Direction.right;\n }\n var children = node.children || [];\n var children_len = children.length;\n var r = 0;\n for (var i = 0; i < children_len; i++) {\n if (children[i].direction === Direction.left) {\n r--;\n } else {\n r++;\n }\n }\n return children_len > 1 && r > 0 ? Direction.left : Direction.right;\n }\n /** Perform layout and offsets recalculation. */\n layout() {\n logger.debug('layout.layout');\n this.layout_direction();\n this.layout_offset();\n }\n /** Calculate and set direction for all nodes. */\n layout_direction() {\n this._layout_direction_root();\n }\n /**\n * Set direction layout for root node and its children.\n * @private\n */\n _layout_direction_root() {\n var node = this.jm.mind.root;\n var layout_data = null;\n if ('layout' in node._data) {\n layout_data = node._data.layout;\n } else {\n layout_data = {};\n node._data.layout = layout_data;\n }\n var children = node.children;\n var children_count = children.length;\n layout_data.direction = Direction.center;\n layout_data.side_index = 0;\n if (this.isside) {\n var i = children_count;\n while (i--) {\n this._layout_direction_side(children[i], Direction.right, i);\n }\n } else {\n var i = children_count;\n var subnode = null;\n while (i--) {\n subnode = children[i];\n if (subnode.direction == Direction.left) {\n this._layout_direction_side(subnode, Direction.left, i);\n } else {\n this._layout_direction_side(subnode, Direction.right, i);\n }\n }\n }\n }\n /**\n * Set direction layout for a node and its descendants.\n * @private\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @param {number} direction - Direction constant (-1, 0, 1)\n * @param {number} side_index - Index among siblings\n */\n _layout_direction_side(node, direction, side_index) {\n var layout_data = null;\n if ('layout' in node._data) {\n layout_data = node._data.layout;\n } else {\n layout_data = {};\n node._data.layout = layout_data;\n }\n var children = node.children;\n var children_count = children.length;\n\n layout_data.direction = direction;\n layout_data.side_index = side_index;\n var i = children_count;\n while (i--) {\n this._layout_direction_side(children[i], direction, i);\n }\n }\n /** Calculate and set position offsets for all nodes. */\n layout_offset() {\n var node = this.jm.mind.root;\n var layout_data = node._data.layout;\n layout_data.offset_x = 0;\n layout_data.offset_y = 0;\n layout_data.outer_height = 0;\n var children = node.children;\n var i = children.length;\n var left_nodes = [];\n var right_nodes = [];\n var subnode = null;\n while (i--) {\n subnode = children[i];\n if (subnode._data.layout.direction == Direction.right) {\n right_nodes.unshift(subnode);\n } else {\n left_nodes.unshift(subnode);\n }\n }\n layout_data.left_nodes = left_nodes;\n layout_data.right_nodes = right_nodes;\n layout_data.outer_height_left = this._layout_offset_subnodes(left_nodes);\n layout_data.outer_height_right = this._layout_offset_subnodes(right_nodes);\n this.bounds.e = node._data.view.width / 2;\n this.bounds.w = 0 - this.bounds.e;\n this.bounds.n = 0;\n this.bounds.s = Math.max(layout_data.outer_height_left, layout_data.outer_height_right);\n }\n /**\n * Layout both the x and y axis for subnodes.\n * @private\n * @param {import('./jsmind.node.js').Node[]} nodes - Array of nodes to layout\n * @returns {number} Total height of all nodes\n */\n _layout_offset_subnodes(nodes) {\n var total_height = 0;\n var nodes_count = nodes.length;\n var i = nodes_count;\n var node = null;\n var node_outer_height = 0;\n var layout_data = null;\n var base_y = 0;\n var pd = null; // parent._data\n while (i--) {\n node = nodes[i];\n layout_data = node._data.layout;\n if (pd == null) {\n pd = node.parent._data;\n }\n\n node_outer_height = this._layout_offset_subnodes(node.children);\n if (!node.expanded) {\n node_outer_height = 0;\n this.set_visible(node.children, false);\n }\n node_outer_height = Math.max(node._data.view.height, node_outer_height);\n\n if (this._should_reserve_cousin_space(node)) {\n node_outer_height += this.opts.cousin_space;\n }\n\n layout_data.outer_height = node_outer_height;\n layout_data.offset_y = base_y - node_outer_height / 2;\n layout_data.offset_x =\n this.opts.hspace * layout_data.direction +\n (pd.view.width * (pd.layout.direction + layout_data.direction)) / 2;\n if (!node.parent.isroot) {\n layout_data.offset_x += this.opts.pspace * layout_data.direction;\n }\n\n base_y = base_y - node_outer_height - this.opts.vspace;\n total_height += node_outer_height;\n }\n if (nodes_count > 1) {\n total_height += this.opts.vspace * (nodes_count - 1);\n }\n i = nodes_count;\n var middle_height = total_height / 2;\n while (i--) {\n node = nodes[i];\n node._data.layout.offset_y += middle_height;\n }\n return total_height;\n }\n /**\n * Layout the y axis only, for collapse/expand a node.\n * @private\n * @param {import('./jsmind.node.js').Node[]} nodes - Array of nodes to layout\n * @returns {number} Total height of all nodes\n */\n _layout_offset_subnodes_height(nodes) {\n var total_height = 0;\n var nodes_count = nodes.length;\n var i = nodes_count;\n var node = null;\n var node_outer_height = 0;\n var layout_data = null;\n var base_y = 0;\n var pd = null; // parent._data\n while (i--) {\n node = nodes[i];\n layout_data = node._data.layout;\n if (pd == null) {\n pd = node.parent._data;\n }\n\n node_outer_height = this._layout_offset_subnodes_height(node.children);\n if (!node.expanded) {\n node_outer_height = 0;\n }\n node_outer_height = Math.max(node._data.view.height, node_outer_height);\n if (this._should_reserve_cousin_space(node)) {\n node_outer_height += this.opts.cousin_space;\n }\n\n layout_data.outer_height = node_outer_height;\n layout_data.offset_y = base_y - node_outer_height / 2;\n base_y = base_y - node_outer_height - this.opts.vspace;\n total_height += node_outer_height;\n }\n if (nodes_count > 1) {\n total_height += this.opts.vspace * (nodes_count - 1);\n }\n i = nodes_count;\n var middle_height = total_height / 2;\n while (i--) {\n node = nodes[i];\n node._data.layout.offset_y += middle_height;\n }\n return total_height;\n }\n /**\n * Check if node should reserve cousin space.\n * @private\n * @param {import('./jsmind.node.js').Node} node - Node to check\n * @returns {boolean} True if cousin space should be reserved\n */\n _should_reserve_cousin_space(node) {\n return node.children.length > 0 && node.parent.children.length > 1;\n }\n /**\n * Get absolute offset for a node.\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @returns {{x:number, y:number}} Absolute position offset\n */\n get_node_offset(node) {\n var layout_data = node._data.layout;\n var offset_cache = null;\n if ('_offset_' in layout_data && this.cache_valid) {\n offset_cache = layout_data._offset_;\n } else {\n offset_cache = { x: -1, y: -1 };\n layout_data._offset_ = offset_cache;\n }\n if (offset_cache.x == -1 || offset_cache.y == -1) {\n var x = layout_data.offset_x;\n var y = layout_data.offset_y;\n if (!node.isroot) {\n var offset_p = this.get_node_offset(node.parent);\n x += offset_p.x;\n y += offset_p.y;\n }\n offset_cache.x = x;\n offset_cache.y = y;\n }\n return offset_cache;\n }\n /**\n * Get anchor point for lines on a node.\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @returns {{x:number, y:number}} Anchor point coordinates\n */\n get_node_point(node) {\n var view_data = node._data.view;\n var offset_p = this.get_node_offset(node);\n var p = {};\n p.x = offset_p.x + (view_data.width * (node._data.layout.direction - 1)) / 2;\n p.y = offset_p.y - view_data.height / 2;\n return p;\n }\n /**\n * Get input point for lines on a node.\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @returns {{x:number, y:number}} Input point coordinates\n */\n get_node_point_in(node) {\n var p = this.get_node_offset(node);\n return p;\n }\n /**\n * Get output point for lines on a node.\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @returns {{x:number, y:number}} Output point coordinates\n */\n get_node_point_out(node) {\n var layout_data = node._data.layout;\n var pout_cache = null;\n if ('_pout_' in layout_data && this.cache_valid) {\n pout_cache = layout_data._pout_;\n } else {\n pout_cache = { x: -1, y: -1 };\n layout_data._pout_ = pout_cache;\n }\n if (pout_cache.x == -1 || pout_cache.y == -1) {\n if (node.isroot) {\n pout_cache.x = 0;\n pout_cache.y = 0;\n } else {\n var view_data = node._data.view;\n var offset_p = this.get_node_offset(node);\n pout_cache.x =\n offset_p.x + (view_data.width + this.opts.pspace) * node._data.layout.direction;\n pout_cache.y = offset_p.y;\n }\n }\n return pout_cache;\n }\n /**\n * Get expander point for a node.\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @returns {{x:number, y:number}} Expander point coordinates\n */\n get_expander_point(node) {\n var p = this.get_node_point_out(node);\n var ex_p = {};\n if (node._data.layout.direction == Direction.right) {\n ex_p.x = p.x - this.opts.pspace;\n } else {\n ex_p.x = p.x;\n }\n ex_p.y = p.y - Math.ceil(this.opts.pspace / 2);\n return ex_p;\n }\n /**\n * Get minimal canvas size to contain all nodes.\n * @returns {{w:number, h:number}} Minimum size required\n */\n get_min_size() {\n var nodes = this.jm.mind.nodes;\n var node = null;\n var pout = null;\n for (var node_id in nodes) {\n node = nodes[node_id];\n pout = this.get_node_point_out(node);\n if (pout.x > this.bounds.e) {\n this.bounds.e = pout.x;\n }\n if (pout.x < this.bounds.w) {\n this.bounds.w = pout.x;\n }\n }\n return {\n w: this.bounds.e - this.bounds.w,\n h: this.bounds.s - this.bounds.n,\n };\n }\n /**\n * Toggle node expanded/collapsed state.\n * @param {import('./jsmind.node.js').Node} node - Target node\n */\n toggle_node(node) {\n if (node.isroot) {\n return;\n }\n if (node.expanded) {\n this.collapse_node(node);\n } else {\n this.expand_node(node);\n }\n }\n /**\n * Expand a node and show its children.\n * @param {import('./jsmind.node.js').Node} node - Target node\n */\n expand_node(node) {\n node.expanded = true;\n this.part_layout(node);\n this.set_visible(node.children, true);\n this.jm.invoke_event_handle(EventType.show, {\n evt: 'expand_node',\n data: [],\n node: node.id,\n });\n }\n /**\n * Collapse a node and hide its children.\n * @param {import('./jsmind.node.js').Node} node - Target node\n */\n collapse_node(node) {\n node.expanded = false;\n this.part_layout(node);\n this.set_visible(node.children, false);\n this.jm.invoke_event_handle(EventType.show, {\n evt: 'collapse_node',\n data: [],\n node: node.id,\n });\n }\n /** Expand all nodes in the mind map. */\n expand_all() {\n var nodes = this.jm.mind.nodes;\n var c = 0;\n var node;\n for (var node_id in nodes) {\n node = nodes[node_id];\n if (!node.expanded) {\n node.expanded = true;\n c++;\n }\n }\n if (c > 0) {\n var root = this.jm.mind.root;\n this.part_layout(root);\n this.set_visible(root.children, true);\n }\n }\n /** Collapse all nodes in the mind map. */\n collapse_all() {\n var nodes = this.jm.mind.nodes;\n var c = 0;\n var node;\n for (var node_id in nodes) {\n node = nodes[node_id];\n if (node.expanded && !node.isroot) {\n node.expanded = false;\n c++;\n }\n }\n if (c > 0) {\n var root = this.jm.mind.root;\n this.part_layout(root);\n this.set_visible(root.children, true);\n }\n }\n /**\n * Expand nodes to a specific depth level.\n * @param {number} target_depth - Target depth level\n * @param {import('./jsmind.node.js').Node[]=} curr_nodes - Current nodes to process\n * @param {number=} curr_depth - Current depth level\n */\n expand_to_depth(target_depth, curr_nodes, curr_depth) {\n if (target_depth < 1) {\n return;\n }\n var nodes = curr_nodes || this.jm.mind.root.children;\n var depth = curr_depth || 1;\n var i = nodes.length;\n var node = null;\n while (i--) {\n node = nodes[i];\n if (depth < target_depth) {\n if (!node.expanded) {\n this.expand_node(node);\n }\n this.expand_to_depth(target_depth, node.children, depth + 1);\n }\n if (depth == target_depth) {\n if (node.expanded) {\n this.collapse_node(node);\n }\n }\n }\n }\n /**\n * Perform partial layout for a node and its subtree.\n * @param {import('./jsmind.node.js').Node} node - Target node\n */\n part_layout(node) {\n var root = this.jm.mind.root;\n if (!!root) {\n var root_layout_data = root._data.layout;\n if (node.isroot) {\n root_layout_data.outer_height_right = this._layout_offset_subnodes_height(\n root_layout_data.right_nodes\n );\n root_layout_data.outer_height_left = this._layout_offset_subnodes_height(\n root_layout_data.left_nodes\n );\n } else {\n if (node._data.layout.direction == Direction.right) {\n root_layout_data.outer_height_right = this._layout_offset_subnodes_height(\n root_layout_data.right_nodes\n );\n } else {\n root_layout_data.outer_height_left = this._layout_offset_subnodes_height(\n root_layout_data.left_nodes\n );\n }\n }\n this.bounds.s = Math.max(\n root_layout_data.outer_height_left,\n root_layout_data.outer_height_right\n );\n this.cache_valid = false;\n } else {\n logger.warn('can not found root node');\n }\n }\n /**\n * Set visibility for nodes and their children.\n * @param {import('./jsmind.node.js').Node[]} nodes - Array of nodes\n * @param {boolean} visible - Visibility state\n */\n set_visible(nodes, visible) {\n var i = nodes.length;\n var node = null;\n var layout_data = null;\n while (i--) {\n node = nodes[i];\n layout_data = node._data.layout;\n if (node.expanded) {\n this.set_visible(node.children, visible);\n } else {\n this.set_visible(node.children, false);\n }\n if (!node.isroot) {\n node._data.layout.visible = visible;\n }\n }\n }\n /**\n * Check if a node is expanded.\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @returns {boolean} True if node is expanded\n */\n is_expand(node) {\n return node.expanded;\n }\n /**\n * Check if a node is visible.\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @returns {boolean} True if node is visible\n */\n is_visible(node) {\n var layout_data = node._data.layout;\n if ('visible' in layout_data && !layout_data.visible) {\n return false;\n } else {\n return true;\n }\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { $ } from './jsmind.dom.js';\nimport { logger } from './jsmind.common.js';\n\n/**\n * SVG-based graph renderer.\n */\nclass SvgGraph {\n /**\n * Create SVG graph renderer.\n * @param {import('./jsmind.view_provider.js').ViewProvider} view - View provider instance\n */\n constructor(view) {\n this.view = view;\n this.opts = view.opts;\n this.e_svg = SvgGraph.c('svg');\n this.e_svg.setAttribute('class', 'jsmind');\n this.size = { w: 0, h: 0 };\n /** @type {SVGPathElement[]} */\n this.lines = [];\n this.line_drawing = {\n straight: this._line_to,\n curved: this._bezier_to,\n };\n this.init_line_render();\n }\n /** @param {string} tag */\n static c(tag) {\n return $.d.createElementNS('http://www.w3.org/2000/svg', tag);\n }\n /** Choose line drawing renderer. */\n init_line_render() {\n if (typeof this.opts.custom_line_render === 'function') {\n /** @type {(path:SVGPathElement,x1:number,y1:number,x2:number,y2:number)=>void} */\n this.drawing = (path, x1, y1, x2, y2) => {\n try {\n this.opts.custom_line_render.call(this, {\n ctx: path,\n start_point: { x: x1, y: y1 },\n end_point: { x: x2, y: y2 },\n });\n } catch (e) {\n logger.error('custom line renderer error: ', e);\n }\n };\n } else {\n /** @type {(path:SVGPathElement,x1:number,y1:number,x2:number,y2:number)=>void} */\n this.drawing = this.line_drawing[this.opts.line_style] || this.line_drawing.curved;\n }\n }\n /** @returns {SVGSVGElement} */\n element() {\n return this.e_svg;\n }\n /** @param {number} w @param {number} h */\n set_size(w, h) {\n this.size.w = w;\n this.size.h = h;\n this.e_svg.setAttribute('width', w);\n this.e_svg.setAttribute('height', h);\n }\n clear() {\n var len = this.lines.length;\n while (len--) {\n this.e_svg.removeChild(this.lines[len]);\n }\n this.lines.length = 0;\n }\n /** @param {{x:number,y:number}} pout @param {{x:number,y:number}} pin @param {{x:number,y:number}} offset @param {string=} color */\n draw_line(pout, pin, offset, color) {\n var line = SvgGraph.c('path');\n line.setAttribute('stroke', color || this.opts.line_color);\n line.setAttribute('stroke-width', this.opts.line_width);\n line.setAttribute('fill', 'transparent');\n this.lines.push(line);\n this.e_svg.appendChild(line);\n this.drawing(\n line,\n pin.x + offset.x,\n pin.y + offset.y,\n pout.x + offset.x,\n pout.y + offset.y\n );\n }\n\n /** @param {CanvasRenderingContext2D} dest_canvas_ctx @param {(()=>void)=} callback */\n copy_to(dest_canvas_ctx, callback) {\n var img = new Image();\n img.onload = function () {\n dest_canvas_ctx.drawImage(img, 0, 0);\n !!callback && callback();\n };\n img.src =\n 'data:image/svg+xml;base64,' + btoa(new XMLSerializer().serializeToString(this.e_svg));\n }\n /**\n * Draw bezier curve to SVG path.\n * @internal\n * @param {SVGPathElement} path - SVG path element\n * @param {number} x1 - Start x coordinate\n * @param {number} y1 - Start y coordinate\n * @param {number} x2 - End x coordinate\n * @param {number} y2 - End y coordinate\n */\n _bezier_to(path, x1, y1, x2, y2) {\n path.setAttribute(\n 'd',\n 'M ' +\n x1 +\n ' ' +\n y1 +\n ' C ' +\n (x1 + ((x2 - x1) * 2) / 3) +\n ' ' +\n y1 +\n ', ' +\n x1 +\n ' ' +\n y2 +\n ', ' +\n x2 +\n ' ' +\n y2\n );\n }\n /**\n * Draw straight line to SVG path.\n * @internal\n * @param {SVGPathElement} path - SVG path element\n * @param {number} x1 - Start x coordinate\n * @param {number} y1 - Start y coordinate\n * @param {number} x2 - End x coordinate\n * @param {number} y2 - End y coordinate\n */\n _line_to(path, x1, y1, x2, y2) {\n path.setAttribute('d', 'M ' + x1 + ' ' + y1 + ' L ' + x2 + ' ' + y2);\n }\n}\n\n/**\n * Canvas-based graph renderer.\n */\nclass CanvasGraph {\n /**\n * Create canvas graph renderer.\n * @param {import('./jsmind.view_provider.js').ViewProvider} view - View provider instance\n */\n constructor(view) {\n this.opts = view.opts;\n this.e_canvas = $.c('canvas');\n this.e_canvas.className = 'jsmind';\n this.canvas_ctx = /** @type {CanvasRenderingContext2D} */ (this.e_canvas.getContext('2d'));\n this.size = { w: 0, h: 0 };\n this.line_drawing = {\n straight: this._line_to,\n curved: this._bezier_to,\n };\n this.dpr = view.device_pixel_ratio;\n this.init_line_render();\n }\n /** Choose line drawing renderer. */\n init_line_render() {\n if (typeof this.opts.custom_line_render === 'function') {\n /** @type {(ctx:CanvasRenderingContext2D,x1:number,y1:number,x2:number,y2:number)=>void} */\n this.drawing = (ctx, x1, y1, x2, y2) => {\n try {\n this.opts.custom_line_render.call(this, {\n ctx,\n start_point: { x: x1, y: y1 },\n end_point: { x: x2, y: y2 },\n });\n } catch (e) {\n logger.error('custom line render error: ', e);\n }\n };\n } else {\n /** @type {(ctx:CanvasRenderingContext2D,x1:number,y1:number,x2:number,y2:number)=>void} */\n this.drawing = this.line_drawing[this.opts.line_style] || this.line_drawing.curved;\n }\n }\n /** @returns {HTMLCanvasElement} */\n element() {\n return this.e_canvas;\n }\n /** @param {number} w @param {number} h */\n set_size(w, h) {\n this.size.w = w;\n this.size.h = h;\n if (this.e_canvas.width && this.e_canvas.height && this.canvas_ctx.scale) {\n this.e_canvas.width = w * this.dpr;\n this.e_canvas.height = h * this.dpr;\n\n this.e_canvas.style.width = w + 'px';\n this.e_canvas.style.height = h + 'px';\n this.canvas_ctx.scale(this.dpr, this.dpr);\n } else {\n this.e_canvas.width = w;\n this.e_canvas.height = h;\n }\n }\n\n /** Clear the canvas. */\n clear() {\n this.canvas_ctx.clearRect(0, 0, this.size.w, this.size.h);\n }\n /** @param {{x:number,y:number}} pout @param {{x:number,y:number}} pin @param {{x:number,y:number}} offset @param {string=} color */\n draw_line(pout, pin, offset, color) {\n var ctx = this.canvas_ctx;\n ctx.strokeStyle = color || this.opts.line_color;\n ctx.lineWidth = this.opts.line_width;\n ctx.lineCap = 'round';\n this.drawing(ctx, pin.x + offset.x, pin.y + offset.y, pout.x + offset.x, pout.y + offset.y);\n }\n /** @param {CanvasRenderingContext2D} dest_canvas_ctx @param {(()=>void)=} callback */\n copy_to(dest_canvas_ctx, callback) {\n dest_canvas_ctx.drawImage(this.e_canvas, 0, 0, this.size.w, this.size.h);\n !!callback && callback();\n }\n /**\n * Draw bezier curve on canvas.\n * @internal\n * @param {CanvasRenderingContext2D} ctx - Canvas context\n * @param {number} x1 - Start x coordinate\n * @param {number} y1 - Start y coordinate\n * @param {number} x2 - End x coordinate\n * @param {number} y2 - End y coordinate\n */\n _bezier_to(ctx, x1, y1, x2, y2) {\n ctx.beginPath();\n ctx.moveTo(x1, y1);\n ctx.bezierCurveTo(x1 + ((x2 - x1) * 2) / 3, y1, x1, y2, x2, y2);\n ctx.stroke();\n }\n /**\n * Draw straight line on canvas.\n * @internal\n * @param {CanvasRenderingContext2D} ctx - Canvas context\n * @param {number} x1 - Start x coordinate\n * @param {number} y1 - Start y coordinate\n * @param {number} x2 - End x coordinate\n * @param {number} y2 - End y coordinate\n */\n _line_to(ctx, x1, y1, x2, y2) {\n ctx.beginPath();\n ctx.moveTo(x1, y1);\n ctx.lineTo(x2, y2);\n ctx.stroke();\n }\n}\n\n/**\n * Initialize graph renderer based on engine type.\n * @param {import('./jsmind.view_provider.js').ViewProvider} view - View provider instance\n * @param {'canvas'|'svg'} engine - Rendering engine type\n * @returns {SvgGraph|CanvasGraph} Graph renderer instance\n */\nexport function init_graph(view, engine) {\n return engine.toLowerCase() === 'svg' ? new SvgGraph(view) : new CanvasGraph(view);\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\nimport { logger, EventType } from './jsmind.common.js';\nimport { $ } from './jsmind.dom.js';\nimport { init_graph } from './jsmind.graph.js';\nimport { util } from './jsmind.util.js';\n\nexport class ViewProvider {\n /**\n * View layer: DOM nodes, editor, graph and zoom.\n * @param {import('./jsmind.js').default} jm - jsMind instance\n * @param {{\n * engine: 'canvas'|'svg',\n * enable_device_pixel_ratio: boolean,\n * hmargin: number,\n * vmargin: number,\n * line_width: number,\n * line_color: string,\n * line_style: 'curved'|'straight',\n * custom_line_render?: Function,\n * draggable: boolean,\n * hide_scrollbars_when_draggable: boolean,\n * node_overflow: 'hidden'|'wrap',\n * zoom: {min:number, max:number, step:number, mask_key:number},\n * custom_node_render?: Function,\n * expander_style: 'char'|'number'\n * }} options - View configuration options\n */\n constructor(jm, options) {\n this.opts = options;\n this.jm = jm;\n this.layout = jm.layout;\n\n this.container = null;\n this.e_panel = null;\n this.e_nodes = null;\n\n this.size = { w: 0, h: 0 };\n\n this.selected_node = null;\n this.editing_node = null;\n\n this.graph = null;\n this.render_node = !!options.custom_node_render\n ? this._custom_node_render\n : this._default_node_render;\n this.zoom_current = 1;\n this.device_pixel_ratio = this.opts.enable_device_pixel_ratio\n ? $.w.devicePixelRatio || 1\n : 1;\n this._initialized = false;\n }\n /** Initialize DOM structure, graph and editor. */\n init() {\n logger.debug(this.opts);\n logger.debug('view.init');\n\n this.container = $.i(this.opts.container)\n ? /** @type {HTMLElement} */ (this.opts.container)\n : /** @type {HTMLElement} */ ($.g(this.opts.container));\n if (!this.container) {\n logger.error('the options.view.container was not be found in dom');\n return;\n }\n this.graph = init_graph(this, this.opts.engine);\n\n this.e_panel = $.c('div');\n this.e_nodes = $.c('jmnodes');\n this.e_editor = $.c('input');\n this.e_panel.className = 'jsmind-inner jmnode-overflow-' + this.opts.node_overflow;\n this.e_panel.tabIndex = 1;\n this.e_panel.appendChild(this.graph.element());\n this.e_panel.appendChild(this.e_nodes);\n\n this.e_editor.className = 'jsmind-editor';\n this.e_editor.type = 'text';\n\n var v = this;\n $.on(this.e_editor, 'keydown', function (e) {\n var evt = e || event;\n if (evt.keyCode == 13) {\n v.edit_node_end();\n evt.stopPropagation();\n }\n });\n $.on(this.e_editor, 'blur', function (e) {\n v.edit_node_end();\n });\n\n this.container.appendChild(this.e_panel);\n\n if (!this.container.offsetParent) {\n new IntersectionObserver((entities, observer) => {\n if (entities[0].isIntersecting) {\n observer.unobserve(this.e_panel);\n this.resize();\n }\n }).observe(this.e_panel);\n }\n }\n\n /**\n * Add a delegated event handler.\n * @param {import('./jsmind.js').default} obj\n * @param {string} event_name\n * @param {(e:Event)=>void} event_handle\n * @param {boolean=} capture_by_panel\n */\n add_event(obj, event_name, event_handle, capture_by_panel) {\n let target = !!capture_by_panel ? this.e_panel : this.e_nodes;\n $.on(target, event_name, function (e) {\n var evt = e || event;\n event_handle.call(obj, evt);\n });\n }\n /**\n * @param {HTMLElement|null} element\n * @returns {string|null}\n */\n get_binded_nodeid(element) {\n if (element == null) {\n return null;\n }\n var tagName = element.tagName.toLowerCase();\n if (tagName == 'jmnode' || tagName == 'jmexpander') {\n return element.getAttribute('nodeid');\n } else if (tagName == 'jmnodes' || tagName == 'body' || tagName == 'html') {\n return null;\n } else {\n return this.get_binded_nodeid(element.parentElement);\n }\n }\n /**\n * @param {HTMLElement|null} element\n * @returns {boolean}\n */\n is_node(element) {\n if (element == null) {\n return false;\n }\n var tagName = element.tagName.toLowerCase();\n if (tagName == 'jmnode') {\n return true;\n } else if (tagName == 'jmnodes' || tagName == 'body' || tagName == 'html') {\n return false;\n } else {\n return this.is_node(element.parentElement);\n }\n }\n /**\n * @param {HTMLElement} element\n * @returns {boolean}\n */\n is_expander(element) {\n return element.tagName.toLowerCase() == 'jmexpander';\n }\n reset() {\n logger.debug('view.reset');\n this.selected_node = null;\n this.clear_lines();\n this.clear_nodes();\n this.reset_theme();\n }\n reset_theme() {\n var theme_name = this.jm.options.theme;\n if (!!theme_name) {\n this.e_nodes.className = 'theme-' + theme_name;\n } else {\n this.e_nodes.className = '';\n }\n }\n /** Reset custom styles for all nodes. */\n reset_custom_style() {\n var nodes = this.jm.mind.nodes;\n for (var nodeid in nodes) {\n this.reset_node_custom_style(nodes[nodeid]);\n }\n }\n /** Load and initialize the view. */\n load() {\n logger.debug('view.load');\n this.setup_canvas_draggable(this.opts.draggable);\n this.init_nodes();\n this._initialized = true;\n }\n /** Calculate and set the expanded canvas size. */\n expand_size() {\n var min_size = this.layout.get_min_size();\n var min_width = min_size.w + this.opts.hmargin * 2;\n var min_height = min_size.h + this.opts.vmargin * 2;\n var client_w = this.e_panel.clientWidth;\n var client_h = this.e_panel.clientHeight;\n if (client_w < min_width) {\n client_w = min_width;\n }\n if (client_h < min_height) {\n client_h = min_height;\n }\n this.size.w = client_w;\n this.size.h = client_h;\n }\n /**\n * Initialize size data for a node.\n * @param {import('./jsmind.node.js').Node} node - Target node\n */\n init_nodes_size(node) {\n var view_data = node._data.view;\n view_data.width = view_data.element.clientWidth;\n view_data.height = view_data.element.clientHeight;\n }\n /** Initialize DOM elements for all nodes. */\n init_nodes() {\n var nodes = this.jm.mind.nodes;\n var doc_frag = $.d.createDocumentFragment();\n for (var nodeid in nodes) {\n this.create_node_element(nodes[nodeid], doc_frag);\n }\n this.e_nodes.appendChild(doc_frag);\n\n this.run_in_c11y_mode_if_needed(() => {\n for (var nodeid in nodes) {\n this.init_nodes_size(nodes[nodeid]);\n }\n });\n }\n /**\n * Add a new node to the view.\n * @param {import('./jsmind.node.js').Node} node - Node to add\n */\n add_node(node) {\n this.create_node_element(node, this.e_nodes);\n this.run_in_c11y_mode_if_needed(() => {\n this.init_nodes_size(node);\n });\n }\n /**\n * Run function in compatibility mode if container is not visible.\n * @param {Function} func - Function to execute\n */\n run_in_c11y_mode_if_needed(func) {\n if (!!this.container.offsetParent) {\n func();\n return;\n }\n logger.warn(\n 'init nodes in compatibility mode. because the container or its parent has style {display:none}. '\n );\n this.e_panel.style.position = 'absolute';\n this.e_panel.style.top = '-100000';\n $.d.body.appendChild(this.e_panel);\n func();\n this.container.appendChild(this.e_panel);\n this.e_panel.style.position = null;\n this.e_panel.style.top = null;\n }\n /**\n * Create a DOM element for a node and append to parent container.\n * @param {import('./jsmind.node.js').Node} node\n * @param {HTMLElement} parent_node\n */\n create_node_element(node, parent_node) {\n var view_data = null;\n if ('view' in node._data) {\n view_data = node._data.view;\n } else {\n view_data = {};\n node._data.view = view_data;\n }\n\n var d = $.c('jmnode');\n if (node.isroot) {\n d.className = 'root';\n } else {\n var d_e = $.c('jmexpander');\n $.t(d_e, '-');\n d_e.setAttribute('nodeid', node.id);\n d_e.style.visibility = 'hidden';\n parent_node.appendChild(d_e);\n view_data.expander = d_e;\n }\n if (!!node.topic) {\n this.render_node(d, node);\n }\n d.setAttribute('nodeid', node.id);\n d.style.visibility = 'hidden';\n this._reset_node_custom_style(d, node.data);\n\n parent_node.appendChild(d);\n view_data.element = d;\n }\n /**\n * Remove a node from the view.\n * @param {import('./jsmind.node.js').Node} node - Node to remove\n */\n remove_node(node) {\n if (this.selected_node != null && this.selected_node.id == node.id) {\n this.selected_node = null;\n }\n if (this.editing_node != null && this.editing_node.id == node.id) {\n node._data.view.element.removeChild(this.e_editor);\n this.editing_node = null;\n }\n var children = node.children;\n var i = children.length;\n while (i--) {\n this.remove_node(children[i]);\n }\n if (node._data.view) {\n var element = node._data.view.element;\n var expander = node._data.view.expander;\n this.e_nodes.removeChild(element);\n this.e_nodes.removeChild(expander);\n node._data.view.element = null;\n node._data.view.expander = null;\n }\n }\n /**\n * Update a node's display.\n * @param {import('./jsmind.node.js').Node} node - Node to update\n */\n update_node(node) {\n var view_data = node._data.view;\n var element = view_data.element;\n if (!!node.topic) {\n this.render_node(element, node);\n }\n if (this.layout.is_visible(node)) {\n view_data.width = element.clientWidth;\n view_data.height = element.clientHeight;\n } else {\n let origin_style = element.getAttribute('style');\n element.style = 'visibility: visible; left:0; top:0;';\n view_data.width = element.clientWidth;\n view_data.height = element.clientHeight;\n element.style = origin_style;\n }\n }\n /**\n * Select a node visually.\n * @param {import('./jsmind.node.js').Node|null} node - Node to select\n */\n select_node(node) {\n if (!!this.selected_node) {\n var element = this.selected_node._data.view.element;\n element.className = element.className.replace(/\\s*selected\\b/i, '');\n this.restore_selected_node_custom_style(this.selected_node);\n }\n if (!!node) {\n this.selected_node = node;\n node._data.view.element.className += ' selected';\n this.clear_selected_node_custom_style(node);\n }\n }\n /** Clear node selection. */\n select_clear() {\n this.select_node(null);\n }\n /**\n * Get currently editing node.\n * @returns {import('./jsmind.node.js').Node|null} Currently editing node\n */\n get_editing_node() {\n return this.editing_node;\n }\n /**\n * Check if any node is being edited.\n * @returns {boolean} True if editing\n */\n is_editing() {\n return !!this.editing_node;\n }\n /**\n * Begin editing a node.\n * @param {import('./jsmind.node.js').Node} node - Node to edit\n */\n edit_node_begin(node) {\n if (!node.topic) {\n logger.warn(\"don't edit image nodes\");\n return;\n }\n if (this.editing_node != null) {\n this.edit_node_end();\n }\n this.editing_node = node;\n var view_data = node._data.view;\n var element = view_data.element;\n var topic = node.topic;\n var ncs = getComputedStyle(element);\n this.e_editor.value = topic;\n this.e_editor.style.width =\n element.clientWidth -\n parseInt(ncs.getPropertyValue('padding-left')) -\n parseInt(ncs.getPropertyValue('padding-right')) +\n 'px';\n element.innerHTML = '';\n element.appendChild(this.e_editor);\n element.style.zIndex = 5;\n this.e_editor.focus();\n this.e_editor.select();\n }\n /** End editing current node. */\n edit_node_end() {\n if (this.editing_node != null) {\n var node = this.editing_node;\n this.editing_node = null;\n var view_data = node._data.view;\n var element = view_data.element;\n var topic = this.e_editor.value;\n element.style.zIndex = 'auto';\n element.removeChild(this.e_editor);\n if (util.text.is_empty(topic) || node.topic === topic) {\n this.render_node(element, node);\n } else {\n this.jm.update_node(node.id, topic);\n }\n }\n this.e_panel.focus();\n }\n /** @returns {{x:number,y:number}} */\n get_view_offset() {\n var bounds = this.layout.bounds;\n var _x = (this.size.w - bounds.e - bounds.w) / 2;\n var _y = this.size.h / 2;\n return { x: _x, y: _y };\n }\n /** Resize the view to fit container. */\n resize() {\n this.graph.set_size(1, 1);\n this.e_nodes.style.width = '1px';\n this.e_nodes.style.height = '1px';\n\n this.expand_size();\n this._show();\n }\n /**\n * Internal show implementation.\n * @private\n */\n _show() {\n this.graph.set_size(this.size.w, this.size.h);\n this.e_nodes.style.width = this.size.w + 'px';\n this.e_nodes.style.height = this.size.h + 'px';\n this.show_nodes();\n this.show_lines();\n //this.layout.cache_valid = true;\n this.jm.invoke_event_handle(EventType.resize, { data: [] });\n }\n /**\n * Zoom in the view.\n * @param {MouseEvent=} e - Mouse event for zoom center\n * @returns {boolean} True if zoom succeeded\n */\n zoom_in(e) {\n return this.set_zoom(this.zoom_current + this.opts.zoom.step, e);\n }\n /**\n * Zoom out the view.\n * @param {MouseEvent=} e - Mouse event for zoom center\n * @returns {boolean} True if zoom succeeded\n */\n zoom_out(e) {\n return this.set_zoom(this.zoom_current - this.opts.zoom.step, e);\n }\n /**\n * Set zoom level and keep scroll around zoom center.\n * @param {number} zoom\n * @param {MouseEvent=} e\n */\n set_zoom(zoom, e) {\n if (zoom < this.opts.zoom.min || zoom > this.opts.zoom.max) {\n return false;\n }\n let e_panel_rect = this.e_panel.getBoundingClientRect();\n if (\n zoom < 1 &&\n zoom < this.zoom_current &&\n this.size.w * zoom < e_panel_rect.width &&\n this.size.h * zoom < e_panel_rect.height\n ) {\n return false;\n }\n let zoom_center = !!e\n ? { x: e.x - e_panel_rect.x, y: e.y - e_panel_rect.y }\n : { x: e_panel_rect.width / 2, y: e_panel_rect.height / 2 };\n let panel_scroll_x =\n ((this.e_panel.scrollLeft + zoom_center.x) * zoom) / this.zoom_current - zoom_center.x;\n let panel_scroll_y =\n ((this.e_panel.scrollTop + zoom_center.y) * zoom) / this.zoom_current - zoom_center.y;\n\n this.zoom_current = zoom;\n for (var i = 0; i < this.e_panel.children.length; i++) {\n this.e_panel.children[i].style.zoom = zoom;\n }\n this._show();\n this.e_panel.scrollLeft = panel_scroll_x;\n this.e_panel.scrollTop = panel_scroll_y;\n return true;\n }\n /** @param {boolean=} keep_center */\n show(keep_center) {\n logger.debug(`view.show: {keep_center: ${keep_center}}`);\n this.expand_size();\n this._show();\n if (!!keep_center) {\n this.center_node(this.jm.mind.root);\n }\n }\n relayout() {\n this.expand_size();\n this._show();\n }\n /** @param {import('./jsmind.node.js').Node} node */\n save_location(node) {\n var vd = node._data.view;\n vd._saved_location = {\n x: parseInt(vd.element.style.left) - this.e_panel.scrollLeft,\n y: parseInt(vd.element.style.top) - this.e_panel.scrollTop,\n };\n }\n /** @param {import('./jsmind.node.js').Node} node */\n restore_location(node) {\n var vd = node._data.view;\n this.e_panel.scrollLeft = parseInt(vd.element.style.left) - vd._saved_location.x;\n this.e_panel.scrollTop = parseInt(vd.element.style.top) - vd._saved_location.y;\n }\n clear_nodes() {\n var mind = this.jm.mind;\n if (mind == null) {\n return;\n }\n var nodes = mind.nodes;\n var node = null;\n for (var nodeid in nodes) {\n node = nodes[nodeid];\n node._data.view.element = null;\n node._data.view.expander = null;\n }\n this.e_nodes.innerHTML = '';\n }\n /** Render node elements and expanders to screen. */\n show_nodes() {\n var nodes = this.jm.mind.nodes;\n var node = null;\n var node_element = null;\n var p = null;\n var view_data = null;\n var view_offset = this.get_view_offset();\n for (var nodeid in nodes) {\n node = nodes[nodeid];\n view_data = node._data.view;\n node_element = view_data.element;\n if (!this.layout.is_visible(node)) {\n node_element.style.display = 'none';\n view_data.expander.style.display = 'none';\n continue;\n }\n this.reset_node_custom_style(node);\n p = this.layout.get_node_point(node);\n view_data.abs_x = view_offset.x + p.x;\n view_data.abs_y = view_offset.y + p.y;\n node_element.style.left = view_offset.x + p.x + 'px';\n node_element.style.top = view_offset.y + p.y + 'px';\n node_element.style.display = '';\n node_element.style.visibility = 'visible';\n this._show_expander(node, view_offset);\n }\n }\n /** @param {import('./jsmind.node.js').Node} node @param {{x:number,y:number}} view_offset */\n _show_expander(node, view_offset) {\n if (node.isroot) {\n return;\n }\n\n var expander = node._data.view.expander;\n if (node.children.length == 0) {\n expander.style.display = 'none';\n expander.style.visibility = 'hidden';\n return;\n }\n\n let expander_text = this._get_expander_text(node);\n $.t(expander, expander_text);\n\n let p_expander = this.layout.get_expander_point(node);\n expander.style.left = view_offset.x + p_expander.x + 'px';\n expander.style.top = view_offset.y + p_expander.y + 'px';\n expander.style.display = '';\n expander.style.visibility = 'visible';\n }\n\n /** @param {import('./jsmind.node.js').Node} node */\n _get_expander_text(node) {\n let style = !!this.opts.expander_style ? this.opts.expander_style.toLowerCase() : 'char';\n if (style === 'number') {\n return node.children.length > 99 ? '...' : node.children.length;\n }\n if (style === 'char') {\n return node.expanded ? '-' : '+';\n }\n }\n\n /** @param {HTMLElement} ele @param {import('./jsmind.node.js').Node} node */\n _default_node_render(ele, node) {\n if (this.opts.support_html) {\n $.h(ele, node.topic);\n } else {\n $.t(ele, node.topic);\n }\n }\n /** @param {HTMLElement} ele @param {import('./jsmind.node.js').Node} node */\n _custom_node_render(ele, node) {\n let rendered = this.opts.custom_node_render(this.jm, ele, node);\n if (!rendered) {\n this._default_node_render(ele, node);\n }\n }\n /** @param {import('./jsmind.node.js').Node} node */\n reset_node_custom_style(node) {\n this._reset_node_custom_style(node._data.view.element, node.data);\n }\n /** @param {HTMLElement} node_element @param {Record<string,string|number>} node_data */\n _reset_node_custom_style(node_element, node_data) {\n if ('background-color' in node_data) {\n node_element.style.backgroundColor = node_data['background-color'];\n }\n if ('foreground-color' in node_data) {\n node_element.style.color = node_data['foreground-color'];\n }\n if ('width' in node_data) {\n node_element.style.width = node_data['width'] + 'px';\n }\n if ('height' in node_data) {\n node_element.style.height = node_data['height'] + 'px';\n }\n if ('font-size' in node_data) {\n node_element.style.fontSize = node_data['font-size'] + 'px';\n }\n if ('font-weight' in node_data) {\n node_element.style.fontWeight = node_data['font-weight'];\n }\n if ('font-style' in node_data) {\n node_element.style.fontStyle = node_data['font-style'];\n }\n if ('background-image' in node_data) {\n var backgroundImage = node_data['background-image'];\n if (backgroundImage.startsWith('data') && node_data['width'] && node_data['height']) {\n var img = new Image();\n\n img.onload = function () {\n var c = $.c('canvas');\n c.width = node_element.clientWidth;\n c.height = node_element.clientHeight;\n var img = this;\n if (c.getContext) {\n var ctx = c.getContext('2d');\n ctx.drawImage(\n img,\n 2,\n 2,\n node_element.clientWidth,\n node_element.clientHeight\n );\n var scaledImageData = c.toDataURL();\n node_element.style.backgroundImage = 'url(' + scaledImageData + ')';\n }\n };\n img.src = backgroundImage;\n } else {\n node_element.style.backgroundImage = 'url(' + backgroundImage + ')';\n }\n node_element.style.backgroundSize = '99%';\n\n if ('background-rotation' in node_data) {\n node_element.style.transform =\n 'rotate(' + node_data['background-rotation'] + 'deg)';\n }\n }\n }\n /** @param {import('./jsmind.node.js').Node} node */\n restore_selected_node_custom_style(node) {\n var node_element = node._data.view.element;\n var node_data = node.data;\n if ('background-color' in node_data) {\n node_element.style.backgroundColor = node_data['background-color'];\n }\n if ('foreground-color' in node_data) {\n node_element.style.color = node_data['foreground-color'];\n }\n }\n /** @param {import('./jsmind.node.js').Node} node */\n clear_selected_node_custom_style(node) {\n var node_element = node._data.view.element;\n node_element.style.backgroundColor = '';\n node_element.style.color = '';\n }\n clear_lines() {\n this.graph.clear();\n }\n show_lines() {\n this.clear_lines();\n var nodes = this.jm.mind.nodes;\n var node = null;\n var pin = null;\n var pout = null;\n var color = null;\n var _offset = this.get_view_offset();\n for (var nodeid in nodes) {\n node = nodes[nodeid];\n if (!!node.isroot) {\n continue;\n }\n if (!this.layout.is_visible(node)) {\n continue;\n }\n pin = this.layout.get_node_point_in(node);\n pout = this.layout.get_node_point_out(node.parent);\n color = node.data['leading-line-color'];\n this.graph.draw_line(pout, pin, _offset, color);\n }\n }\n // Drag the whole mind map with your mouse, when it's larger that the container\n /**\n * Enable/disable dragging the whole canvas with mouse.\n * @param {boolean} enabled\n */\n setup_canvas_draggable(enabled) {\n this.opts.draggable = enabled;\n if (!this._initialized) {\n let dragging = false;\n let x, y;\n if (this.opts.hide_scrollbars_when_draggable) {\n // Avoid scrollbars when mind map is larger than the container (e_panel = id jsmind-inner)\n this.e_panel.style = 'overflow: hidden';\n }\n // Move the whole mind map with mouse moves, while button is down.\n $.on(this.container, 'mousedown', eventDown => {\n if (this.opts.draggable) {\n dragging = true;\n // Record current mouse position.\n x = eventDown.clientX;\n y = eventDown.clientY;\n }\n });\n // Stop moving mind map once mouse button is released.\n $.on(this.container, 'mouseup', () => {\n dragging = false;\n });\n // Follow current mouse position and move mind map accordingly.\n $.on(this.container, 'mousemove', eventMove => {\n if (this.opts.draggable) {\n if (dragging) {\n this.e_panel.scrollBy(x - eventMove.clientX, y - eventMove.clientY);\n // Record new current position.\n x = eventMove.clientX;\n y = eventMove.clientY;\n }\n }\n });\n }\n }\n /** @param {import('./jsmind.node.js').Node} node */\n center_node(node) {\n if (!this.layout.is_visible(node)) {\n logger.warn('can not scroll to the node, because it is invisible');\n return false;\n }\n let view_data = node._data.view;\n let e_panel_rect = this.e_panel.getBoundingClientRect();\n let node_center_point = {\n x: view_data.abs_x + view_data.width / 2,\n y: view_data.abs_y + view_data.height / 2,\n };\n this.e_panel.scrollTo(\n node_center_point.x * this.zoom_current - e_panel_rect.width / 2,\n node_center_point.y * this.zoom_current - e_panel_rect.height / 2\n );\n return true;\n }\n\n /** @param {MouseEvent=} e */\n zoomIn(e) {\n logger.warn('please use zoom_in instead');\n return this.zoom_in(e);\n }\n /** @param {MouseEvent=} e */\n zoomOut(e) {\n logger.warn('please use zoom_out instead');\n return this.zoom_out(e);\n }\n /** @param {number} zoom @param {MouseEvent=} e */\n setZoom(zoom, e) {\n logger.warn('please use set_zoom instead');\n return this.set_zoom(zoom, e);\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { $ } from './jsmind.dom.js';\nimport { util } from './jsmind.util.js';\nimport { Direction } from './jsmind.common.js';\n\nexport class ShortcutProvider {\n /**\n * @param {import('./jsmind.js').default} jm\n * @param {{ enable:boolean, handles: Record<string,(jm: import('./jsmind.js').default, e: KeyboardEvent)=>void>, mapping: Record<string, number|number[]>, id_generator?: ()=>string }} options\n */\n constructor(jm, options) {\n this.jm = jm;\n this.opts = options;\n /** @type {Record<string, number|number[]>} */\n this.mapping = options.mapping;\n /** @type {Record<string,(jm: import('./jsmind.js').default, e: KeyboardEvent)=>void>} */\n this.handles = options.handles;\n /** @type {()=>string|null} */\n this._newid = null;\n /** @type {Record<number,(jm: import('./jsmind.js').default, e: KeyboardEvent)=>void>} */\n this._mapping = {};\n }\n init() {\n $.on(this.jm.view.e_panel, 'keydown', this.handler.bind(this));\n\n this.handles['addchild'] = this.handle_addchild;\n this.handles['addbrother'] = this.handle_addbrother;\n this.handles['editnode'] = this.handle_editnode;\n this.handles['delnode'] = this.handle_delnode;\n this.handles['toggle'] = this.handle_toggle;\n this.handles['up'] = this.handle_up;\n this.handles['down'] = this.handle_down;\n this.handles['left'] = this.handle_left;\n this.handles['right'] = this.handle_right;\n\n for (var handle in this.mapping) {\n if (!!this.mapping[handle] && handle in this.handles) {\n let keys = this.mapping[handle];\n if (!Array.isArray(keys)) {\n keys = [keys];\n }\n for (let key of keys) {\n this._mapping[key] = this.handles[handle];\n }\n }\n }\n\n if (typeof this.opts.id_generator === 'function') {\n this._newid = this.opts.id_generator;\n } else {\n this._newid = util.uuid.newid;\n }\n }\n enable_shortcut() {\n this.opts.enable = true;\n }\n disable_shortcut() {\n this.opts.enable = false;\n }\n /** @param {KeyboardEvent} e */\n handler(e) {\n if (e.which == 9) {\n e.preventDefault();\n } //prevent tab to change focus in browser\n if (this.jm.view.is_editing()) {\n return;\n }\n var evt = e || event;\n if (!this.opts.enable) {\n return true;\n }\n var kc =\n evt.keyCode +\n (evt.metaKey << 13) +\n (evt.ctrlKey << 12) +\n (evt.altKey << 11) +\n (evt.shiftKey << 10);\n if (kc in this._mapping) {\n this._mapping[kc].call(this, this.jm, e);\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_addchild(_jm, e) {\n var selected_node = _jm.get_selected_node();\n if (!!selected_node) {\n var node_id = this._newid();\n var node = _jm.add_node(selected_node, node_id, 'New Node');\n if (!!node) {\n _jm.select_node(node_id);\n _jm.begin_edit(node_id);\n }\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_addbrother(_jm, e) {\n var selected_node = _jm.get_selected_node();\n if (!!selected_node && !selected_node.isroot) {\n var node_id = this._newid();\n var node = _jm.insert_node_after(selected_node, node_id, 'New Node');\n if (!!node) {\n _jm.select_node(node_id);\n _jm.begin_edit(node_id);\n }\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_editnode(_jm, e) {\n var selected_node = _jm.get_selected_node();\n if (!!selected_node) {\n _jm.begin_edit(selected_node);\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_delnode(_jm, e) {\n var selected_node = _jm.get_selected_node();\n if (!!selected_node && !selected_node.isroot) {\n _jm.select_node(selected_node.parent);\n _jm.remove_node(selected_node);\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_toggle(_jm, e) {\n var evt = e || event;\n var selected_node = _jm.get_selected_node();\n if (!!selected_node) {\n _jm.toggle_node(selected_node.id);\n evt.stopPropagation();\n evt.preventDefault();\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_up(_jm, e) {\n var evt = e || event;\n var selected_node = _jm.get_selected_node();\n if (!!selected_node) {\n var up_node = _jm.find_node_before(selected_node);\n if (!up_node) {\n var np = _jm.find_node_before(selected_node.parent);\n if (!!np && np.children.length > 0) {\n up_node = np.children[np.children.length - 1];\n }\n }\n if (!!up_node) {\n _jm.select_node(up_node);\n }\n evt.stopPropagation();\n evt.preventDefault();\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_down(_jm, e) {\n var evt = e || event;\n var selected_node = _jm.get_selected_node();\n if (!!selected_node) {\n var down_node = _jm.find_node_after(selected_node);\n if (!down_node) {\n var np = _jm.find_node_after(selected_node.parent);\n if (!!np && np.children.length > 0) {\n down_node = np.children[0];\n }\n }\n if (!!down_node) {\n _jm.select_node(down_node);\n }\n evt.stopPropagation();\n evt.preventDefault();\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_left(_jm, e) {\n this._handle_direction(_jm, e, Direction.left);\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_right(_jm, e) {\n this._handle_direction(_jm, e, Direction.right);\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e @param {number} d */\n _handle_direction(_jm, e, d) {\n var evt = e || event;\n var selected_node = _jm.get_selected_node();\n var node = null;\n if (!!selected_node) {\n if (selected_node.isroot) {\n var c = selected_node.children;\n var children = [];\n for (var i = 0; i < c.length; i++) {\n if (c[i].direction === d) {\n children.push(i);\n }\n }\n node = c[children[Math.floor((children.length - 1) / 2)]];\n } else if (selected_node.direction === d) {\n var children = selected_node.children;\n var children_count = children.length;\n if (children_count > 0) {\n node = children[Math.floor((children_count - 1) / 2)];\n }\n } else {\n node = selected_node.parent;\n }\n if (!!node) {\n _jm.select_node(node);\n }\n evt.stopPropagation();\n evt.preventDefault();\n }\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { $ } from './jsmind.dom.js';\n\n/** @type {{ plugins: Array<Plugin<object>> }} */\nconst plugin_data = {\n plugins: [],\n};\n\n/**\n * Register a plugin instance.\n * @param {Plugin<object>} plugin\n */\nexport function register(plugin) {\n if (!(plugin instanceof Plugin)) {\n throw new Error('can not register plugin, it is not an instance of Plugin');\n }\n if (plugin_data.plugins.map(p => p.name).includes(plugin.name)) {\n throw new Error('can not register plugin ' + plugin.name + ': plugin name already exist');\n }\n plugin_data.plugins.push(plugin);\n}\n\n/**\n * Apply registered plugins asynchronously.\n * @param {import('./jsmind.js').default} jm\n * @param {Record<string, object>} options\n */\nexport function apply(jm, options) {\n $.w.setTimeout(function () {\n _apply(jm, options);\n }, 0);\n}\n\n/**\n * @param {import('./jsmind.js').default} jm\n * @param {Record<string, object>} options */\nfunction _apply(jm, options) {\n plugin_data.plugins.forEach(p => p.fn_init(jm, options[p.name]));\n}\n\nexport class Plugin {\n /**\n * @template [TOptions=object]\n * @param {string} name\n * @param {(jm: import('./jsmind.js').default, options: TOptions)=>void} fn_init\n */\n constructor(name, fn_init) {\n if (!name) {\n throw new Error('plugin must has a name');\n }\n if (!fn_init || typeof fn_init !== 'function') {\n throw new Error('plugin must has an init function');\n }\n this.name = name;\n this.fn_init = fn_init;\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { logger } from './jsmind.common.js';\n\n/**\n * Enhanced Plugin Manager\n * Manages the lifecycle of enhanced plugins with synchronous initialization,\n * preload support, and lifecycle hooks.\n */\nexport class EnhancedPluginManager {\n /**\n * @param {import('./jsmind.js').default} jm - jsMind instance\n */\n constructor(jm) {\n this.jm = jm;\n /** @type {Map<string, EnhancedPlugin>} */\n this.plugins = new Map();\n }\n\n /**\n * Initialize preload plugins (before core modules)\n */\n initPreloadPlugins() {\n const preloadPlugins = this.jm.constructor.enhancedPluginList.filter(d => d.preload);\n logger.info('Initializing ' + preloadPlugins.length + ' preload plugins');\n preloadPlugins.forEach(descriptor => {\n this._initPlugin(descriptor);\n });\n }\n\n /**\n * Initialize normal plugins (after core modules)\n */\n initNormalPlugins() {\n const normalPlugins = this.jm.constructor.enhancedPluginList.filter(d => !d.preload);\n logger.info('Initializing ' + normalPlugins.length + ' normal plugins');\n normalPlugins.forEach(descriptor => {\n this._initPlugin(descriptor);\n });\n }\n\n /**\n * Internal method: Initialize a single plugin\n * @param {PluginDescriptor} descriptor\n * @private\n */\n _initPlugin(descriptor) {\n try {\n const { PluginClass, pluginOpt } = descriptor;\n\n // Check instanceName\n if (!PluginClass.instanceName) {\n throw new Error('Plugin ' + PluginClass.name + ' must define static instanceName');\n }\n\n // Check naming conflict\n if (this.plugins.has(PluginClass.instanceName)) {\n logger.warn(\n 'Plugin ' + PluginClass.instanceName + ' already exists, will be replaced'\n );\n }\n\n // Instantiate plugin\n const instance = new PluginClass({\n jm: this.jm,\n pluginOpt: pluginOpt || {},\n });\n\n // Save instance\n this.plugins.set(PluginClass.instanceName, instance);\n this.jm[PluginClass.instanceName] = instance;\n descriptor.instance = instance;\n\n logger.info('Enhanced plugin ' + PluginClass.instanceName + ' initialized');\n } catch (error) {\n logger.error('Failed to initialize plugin ' + descriptor.PluginClass.name + ':', error);\n }\n }\n\n /**\n * Remove a plugin\n * @param {typeof EnhancedPlugin} PluginClass\n */\n removePlugin(PluginClass) {\n const instanceName = PluginClass.instanceName;\n if (!instanceName) {\n return;\n }\n\n const instance = this.plugins.get(instanceName);\n if (!instance) {\n return;\n }\n\n try {\n // Call lifecycle hook\n if (typeof instance.beforePluginRemove === 'function') {\n instance.beforePluginRemove();\n }\n\n // Remove from Map\n this.plugins.delete(instanceName);\n\n // Remove from jsMind instance\n delete this.jm[instanceName];\n\n // Remove from plugin list\n const list = this.jm.constructor.enhancedPluginList;\n const index = list.findIndex(d => d.PluginClass === PluginClass);\n if (index !== -1) {\n list.splice(index, 1);\n }\n\n logger.info('Enhanced plugin ' + instanceName + ' removed');\n } catch (error) {\n logger.error('Failed to remove plugin ' + instanceName + ':', error);\n }\n }\n\n /**\n * Destroy all plugins\n */\n destroyAllPlugins() {\n this.plugins.forEach((instance, instanceName) => {\n try {\n // Call lifecycle hook\n if (typeof instance.beforePluginDestroy === 'function') {\n instance.beforePluginDestroy();\n }\n } catch (error) {\n logger.error('Failed to destroy plugin ' + instanceName + ':', error);\n }\n });\n\n this.plugins.clear();\n }\n\n /**\n * Get plugin instance by name\n * @param {string} instanceName\n * @returns {EnhancedPlugin | undefined}\n */\n getPlugin(instanceName) {\n return this.plugins.get(instanceName);\n }\n}\n\n/**\n * Enhanced Plugin Base Class\n * Provides standard interface for enhanced plugins\n */\nexport class EnhancedPlugin {\n /**\n * Plugin instance name (must be defined by subclass)\n * @type {string}\n */\n static instanceName = '';\n\n /**\n * Whether to initialize before core modules\n * @type {boolean}\n */\n static preload = false;\n\n /**\n * @param {{ jm: import('./jsmind.js').default, pluginOpt: object }} params\n */\n constructor({ jm, pluginOpt }) {\n this.jm = jm;\n this.options = pluginOpt || {};\n }\n\n /**\n * Called before plugin is removed\n * Override this method to clean up resources\n */\n beforePluginRemove() {\n // Default implementation: do nothing\n }\n\n /**\n * Called before jsMind instance is destroyed\n * Override this method to clean up resources\n */\n beforePluginDestroy() {\n // Default implementation: call beforePluginRemove\n this.beforePluginRemove();\n }\n}\n\n/**\n * Plugin descriptor\n * @typedef {object} PluginDescriptor\n * @property {typeof EnhancedPlugin} PluginClass - Plugin class\n * @property {string} instanceName - Plugin instance name\n * @property {boolean} preload - Whether to preload\n * @property {object} pluginOpt - Plugin options\n * @property {EnhancedPlugin | null} instance - Plugin instance (after initialization)\n */\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { __version__, logger, EventType, Direction, LogLevel } from './jsmind.common.js';\nimport { merge_option } from './jsmind.option.js';\nimport { Mind } from './jsmind.mind.js';\nimport { Node } from './jsmind.node.js';\nimport { DataProvider } from './jsmind.data_provider.js';\nimport { LayoutProvider } from './jsmind.layout_provider.js';\nimport { ViewProvider } from './jsmind.view_provider.js';\nimport { ShortcutProvider } from './jsmind.shortcut_provider.js';\nimport { Plugin, register as _register_plugin, apply as apply_plugins } from './jsmind.plugin.js';\nimport { EnhancedPluginManager, EnhancedPlugin } from './jsmind.enhanced-plugin.js';\nimport { format } from './jsmind.format.js';\nimport { $ } from './jsmind.dom.js';\nimport { util as _util } from './jsmind.util.js';\n\n/**\n * Event callback payload\n * @typedef {{ evt?: string, data?: unknown[], node?: string }} EventData\n */\n\n/**\n * jsMind runtime: orchestrates data/layout/view/shortcut and exposes public API.\n */\nexport default class jsMind {\n static mind = Mind;\n static node = Node;\n static direction = Direction;\n static event_type = EventType;\n static $ = $;\n static plugin = Plugin;\n static register_plugin = _register_plugin;\n static util = _util;\n static enhanced_plugin = EnhancedPlugin;\n\n /** @type {Array<import('./jsmind.enhanced-plugin.js').PluginDescriptor>} */\n static enhancedPluginList = [];\n\n /**\n * Register an enhanced plugin\n * @param {typeof EnhancedPlugin} PluginClass - Plugin class\n * @param {object} [options={}] - Plugin options\n * @returns {typeof jsMind}\n */\n static usePlugin(PluginClass, options = {}) {\n // Check if already registered\n const exists = jsMind.enhancedPluginList.some(d => d.PluginClass === PluginClass);\n if (exists) {\n logger.warn('Plugin ' + PluginClass.name + ' already registered');\n return jsMind;\n }\n\n // Check instanceName\n if (!PluginClass.instanceName) {\n throw new Error('Plugin ' + PluginClass.name + ' must define static instanceName');\n }\n\n // Add to plugin list\n jsMind.enhancedPluginList.push({\n PluginClass,\n instanceName: PluginClass.instanceName,\n preload: PluginClass.preload || false,\n pluginOpt: options,\n instance: null,\n });\n\n return jsMind;\n }\n\n /**\n * Check if an enhanced plugin is registered\n * @param {typeof EnhancedPlugin} PluginClass - Plugin class\n * @returns {boolean}\n */\n static hasEnhancedPlugin(PluginClass) {\n return jsMind.enhancedPluginList.some(d => d.PluginClass === PluginClass);\n }\n\n /**\n * Create a jsMind instance.\n * @param {import('./jsmind.option.js').JsMindRuntimeOptions} options\n */\n constructor(options) {\n jsMind.current = this;\n this.options = merge_option(options);\n logger.level(LogLevel[this.options.log_level]);\n this.version = __version__;\n this.initialized = false;\n this.mind = null;\n /** @type {Array<(type: number, data: EventData) => void>} */\n this.event_handles = [];\n this.init();\n }\n\n /** Initialize sub-systems and plugins. */\n init() {\n if (!!this.initialized) {\n return;\n }\n this.initialized = true;\n\n // Initialize enhanced plugin manager\n this.enhancedPluginManager = new EnhancedPluginManager(this);\n\n // Initialize preload plugins (before core modules)\n this.enhancedPluginManager.initPreloadPlugins();\n\n var opts_layout = {\n mode: this.options.mode,\n hspace: this.options.layout.hspace,\n vspace: this.options.layout.vspace,\n pspace: this.options.layout.pspace,\n cousin_space: this.options.layout.cousin_space,\n };\n var opts_view = {\n container: this.options.container,\n support_html: this.options.support_html,\n engine: this.options.view.engine,\n enable_device_pixel_ratio: this.options.view.enable_device_pixel_ratio,\n hmargin: this.options.view.hmargin,\n vmargin: this.options.view.vmargin,\n line_width: this.options.view.line_width,\n line_color: this.options.view.line_color,\n line_style: this.options.view.line_style,\n custom_line_render: this.options.view.custom_line_render,\n draggable: this.options.view.draggable,\n hide_scrollbars_when_draggable: this.options.view.hide_scrollbars_when_draggable,\n node_overflow: this.options.view.node_overflow,\n zoom: this.options.view.zoom,\n custom_node_render: this.options.view.custom_node_render,\n expander_style: this.options.view.expander_style,\n };\n // create instance of function provider\n this.data = new DataProvider(this);\n this.layout = new LayoutProvider(this, opts_layout);\n this.view = new ViewProvider(this, opts_view);\n this.shortcut = new ShortcutProvider(this, this.options.shortcut);\n\n this.data.init();\n this.layout.init();\n this.view.init();\n this.shortcut.init();\n\n this._event_bind();\n\n // Initialize normal plugins (after core modules)\n this.enhancedPluginManager.initNormalPlugins();\n\n // Apply old plugins (asynchronously)\n apply_plugins(this, this.options.plugin);\n }\n /** @returns {boolean} whether current mind map is editable */\n get_editable() {\n return this.options.editable;\n }\n /** enable editing */\n enable_edit() {\n this.options.editable = true;\n }\n /** disable editing */\n disable_edit() {\n this.options.editable = false;\n }\n /** @returns {boolean} whether view is draggable */\n get_view_draggable() {\n return this.options.view.draggable;\n }\n /** enable view dragging */\n enable_view_draggable() {\n this.options.view.draggable = true;\n this.view.setup_canvas_draggable(true);\n }\n /** disable view dragging */\n disable_view_draggable() {\n this.options.view.draggable = false;\n this.view.setup_canvas_draggable(false);\n }\n // options are 'mousedown', 'click', 'dblclick', 'mousewheel'\n /**\n * Enable default event handle.\n * @param {'mousedown'|'click'|'dblclick'|'mousewheel'} event_handle\n */\n enable_event_handle(event_handle) {\n this.options.default_event_handle['enable_' + event_handle + '_handle'] = true;\n }\n // options are 'mousedown', 'click', 'dblclick', 'mousewheel'\n /**\n * Disable default event handle.\n * @param {'mousedown'|'click'|'dblclick'|'mousewheel'} event_handle\n */\n disable_event_handle(event_handle) {\n this.options.default_event_handle['enable_' + event_handle + '_handle'] = false;\n }\n /**\n * Set theme name.\n * @param {string|null=} theme\n */\n set_theme(theme) {\n var theme_old = this.options.theme;\n this.options.theme = !!theme ? theme : null;\n if (theme_old != this.options.theme) {\n this.view.reset_theme();\n this.view.reset_custom_style();\n }\n }\n /** bind internal DOM events */\n _event_bind() {\n this.view.add_event(this, 'mousedown', this.mousedown_handle);\n this.view.add_event(this, 'click', this.click_handle);\n this.view.add_event(this, 'dblclick', this.dblclick_handle);\n this.view.add_event(this, 'wheel', this.mousewheel_handle, true);\n }\n /** @param {MouseEvent} e */\n mousedown_handle(e) {\n if (!this.options.default_event_handle['enable_mousedown_handle']) {\n return;\n }\n var element = e.target || event.srcElement;\n var node_id = this.view.get_binded_nodeid(element);\n if (!!node_id) {\n if (this.view.is_node(element)) {\n this.select_node(node_id);\n }\n } else {\n this.select_clear();\n }\n }\n /** @param {MouseEvent} e */\n click_handle(e) {\n if (!this.options.default_event_handle['enable_click_handle']) {\n return;\n }\n var element = e.target || event.srcElement;\n var is_expander = this.view.is_expander(element);\n if (is_expander) {\n var node_id = this.view.get_binded_nodeid(element);\n if (!!node_id) {\n this.toggle_node(node_id);\n }\n }\n }\n /** @param {MouseEvent} e */\n dblclick_handle(e) {\n if (!this.options.default_event_handle['enable_dblclick_handle']) {\n return;\n }\n if (this.get_editable()) {\n var element = e.target || event.srcElement;\n var is_node = this.view.is_node(element);\n if (is_node) {\n var node_id = this.view.get_binded_nodeid(element);\n if (!!node_id) {\n this.begin_edit(node_id);\n }\n }\n }\n }\n // Use [Ctrl] + Mousewheel, to zoom in/out.\n /** @param {WheelEvent} e */\n mousewheel_handle(e) {\n // Test if mousewheel option is enabled and Ctrl key is pressed.\n var kc = (e.metaKey << 13) + (e.ctrlKey << 12) + (e.altKey << 11) + (e.shiftKey << 10);\n if (\n !this.options.default_event_handle['enable_mousewheel_handle'] ||\n this.options.view.zoom.mask_key !== kc\n ) {\n return;\n }\n var evt = e || event;\n // Avoid default page scrolling behavior.\n evt.preventDefault();\n\n if (evt.deltaY < 0) {\n this.view.zoom_in(evt); // wheel down\n } else {\n this.view.zoom_out(evt);\n }\n }\n /**\n * Begin editing a node.\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {boolean|void}\n */\n begin_edit(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return false;\n } else {\n return this.begin_edit(the_node);\n }\n }\n if (this.get_editable()) {\n this.view.edit_node_begin(node);\n } else {\n logger.error('fail, this mind map is not editable.');\n return;\n }\n }\n /** End editing */\n end_edit() {\n this.view.edit_node_end();\n }\n /**\n * Toggle a node's expanded state.\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {void}\n */\n toggle_node(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return;\n } else {\n this.toggle_node(the_node);\n return;\n }\n }\n if (node.isroot) {\n return;\n }\n this.view.save_location(node);\n this.layout.toggle_node(node);\n this.view.relayout();\n this.view.restore_location(node);\n }\n /**\n * Expand a node.\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {void}\n */\n expand_node(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return;\n } else {\n this.expand_node(the_node);\n return;\n }\n }\n if (node.isroot) {\n return;\n }\n this.view.save_location(node);\n this.layout.expand_node(node);\n this.view.relayout();\n this.view.restore_location(node);\n }\n /**\n * Collapse a node.\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {void}\n */\n collapse_node(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return;\n } else {\n this.collapse_node(the_node);\n return;\n }\n }\n if (node.isroot) {\n return;\n }\n this.view.save_location(node);\n this.layout.collapse_node(node);\n this.view.relayout();\n this.view.restore_location(node);\n }\n /** Expand all nodes */\n expand_all() {\n this.layout.expand_all();\n this.view.relayout();\n }\n /** Collapse all nodes */\n collapse_all() {\n this.layout.collapse_all();\n this.view.relayout();\n }\n /**\n * Expand nodes up to a specified depth level.\n * @param {number} depth\n */\n expand_to_depth(depth) {\n this.layout.expand_to_depth(depth);\n this.view.relayout();\n }\n /** reset view/layout/data */\n _reset() {\n this.invoke_event_handle(EventType.reset, { data: [] });\n this.view.reset();\n this.layout.reset();\n this.data.reset();\n }\n /**\n * Internal show flow.\n * @param {object | null} mind\n * @param {boolean=} skip_centering\n */\n _show(mind, skip_centering) {\n var m = mind || format.node_array.example;\n this.mind = this.data.load(m);\n if (!this.mind) {\n logger.error('data.load error');\n return;\n } else {\n logger.debug('data.load ok');\n }\n\n this.view.load();\n logger.debug('view.load ok');\n\n this.layout.layout();\n logger.debug('layout.layout ok');\n\n this.view.show(!skip_centering);\n logger.debug('view.show ok');\n\n this.invoke_event_handle(EventType.show, { data: [mind] });\n }\n /**\n * Show a mind (or example) on the canvas.\n * @param {object | null} mind\n * @param {boolean=} skip_centering\n */\n show(mind, skip_centering) {\n this._reset();\n this._show(mind, skip_centering);\n }\n /** @returns {{name:string,author:string,version:string}} */\n get_meta() {\n return {\n name: this.mind.name,\n author: this.mind.author,\n version: this.mind.version,\n };\n }\n /**\n * Serialize current mind to given format.\n * @param {'node_tree'|'node_array'|'freemind'|'text'} [data_format]\n * @returns {object}\n */\n get_data(data_format) {\n var df = data_format || 'node_tree';\n return this.data.get_data(df);\n }\n /** @returns {import('./jsmind.node.js').Node} */\n get_root() {\n return this.mind.root;\n }\n /**\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {import('./jsmind.node.js').Node}\n */\n get_node(node) {\n if (Node.is_node(node)) {\n return node;\n }\n return this.mind.get_node(node);\n }\n /**\n * Add node data to the mind map without triggering UI refresh.\n * @private\n * @param {import('./jsmind.node.js').Node} parent_node\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction\n * @returns {import('./jsmind.node.js').Node|null}\n */\n _add_node_data(parent_node, node_id, topic, data, direction) {\n var dir = Direction.of(direction);\n if (dir === undefined) {\n dir = this.layout.calculate_next_child_direction(parent_node);\n }\n\n var node = this.mind.add_node(parent_node, node_id, topic, data, dir);\n if (!!node) {\n this.view.add_node(node);\n this.view.reset_node_custom_style(node);\n }\n return node;\n }\n\n /**\n * Refresh UI after node changes.\n * @private\n * @param {import('./jsmind.node.js').Node} parent_node\n */\n _refresh_node_ui(parent_node) {\n this.layout.layout();\n this.view.show(false);\n this.expand_node(parent_node);\n }\n\n /**\n * Add a new node to the mind map.\n * @param {string | import('./jsmind.node.js').Node} parent_node\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @returns {import('./jsmind.node.js').Node|null}\n */\n add_node(parent_node, node_id, topic, data, direction) {\n if (!this.get_editable()) {\n logger.error('fail, this mind map is not editable');\n return null;\n }\n\n var the_parent_node = this.get_node(parent_node);\n if (!the_parent_node) {\n logger.error('parent node not found');\n return null;\n }\n\n var node = this._add_node_data(the_parent_node, node_id, topic, data, direction);\n if (!!node) {\n this._refresh_node_ui(the_parent_node);\n this.invoke_event_handle(EventType.edit, {\n evt: 'add_node',\n data: [the_parent_node.id, node_id, topic, data, Direction.of(direction)],\n node: node_id,\n });\n }\n return node;\n }\n\n /**\n * Add multiple nodes in batch.\n *\n * This method provides atomic batch node creation with automatic rollback on failure.\n * All nodes are created in a single operation, and if any node fails to create,\n * all previously created nodes in this batch will be automatically removed.\n *\n * **Note**: This is a batch operation API that uses standard field names only.\n * For data import with custom fieldNames, use `show()` instead.\n *\n * @example\n * // Using standard field names\n * jm.add_nodes('parent_id', [\n * { id: 'node1', topic: 'Node 1', data: { color: 'red' }, children: [\n * { id: 'node1-1', topic: 'Child 1' }\n * ]}\n * ]);\n *\n * @param {string | import('./jsmind.node.js').Node} parent_node - Parent node for all new nodes\n * @param {Array<{id: string, topic: string, data?: Record<string, any>, direction?: ('left'|'center'|'right'|'-1'|'0'|'1'|number), children?: Array}>} nodes_data - Array of node data objects with standard field names (id, topic, children, data, direction)\n * @returns {Array<import('./jsmind.node.js').Node|null>} Array of created nodes (flattened from all levels)\n */\n add_nodes(parent_node, nodes_data) {\n if (!this.get_editable()) {\n logger.error('fail, this mind map is not editable');\n return [];\n }\n\n var the_parent_node = this.get_node(parent_node);\n if (!the_parent_node) {\n logger.error('parent node not found');\n return [];\n }\n\n if (!Array.isArray(nodes_data) || nodes_data.length === 0) {\n logger.warn('nodes_data should be a non-empty array');\n return [];\n }\n\n const expected_count = this._count_expected_nodes(nodes_data);\n let created_nodes = nodes_data\n .map(node_data => this._add_nodes_recursive(the_parent_node, node_data))\n .flat()\n .filter(n => n !== null);\n\n const actual_count = created_nodes.length;\n\n // Atomic operation: either all nodes succeed or cleanup all partial nodes\n if (actual_count === expected_count) {\n // All nodes created successfully, refresh UI\n this._refresh_node_ui(the_parent_node);\n this.invoke_event_handle(EventType.edit, {\n evt: 'add_nodes',\n data: [the_parent_node.id, nodes_data],\n nodes: created_nodes.map(node => node.id),\n });\n return created_nodes;\n } else {\n // Cleanup partially created nodes to ensure atomicity\n logger.warn(\n `Expected ${expected_count} nodes, but only created ${actual_count}. Cleaning up...`\n );\n this._cleanup_partial_nodes(created_nodes);\n return [];\n }\n }\n\n /**\n * Recursively add nodes using standard field names.\n * This is a batch operation API that uses standard field names only.\n * For data import with custom fieldNames, use `show()` instead.\n * @private\n * @param {import('./jsmind.node.js').Node} parent_node\n * @param {object} node_data - Node data object with standard field names (id, topic, children, data, direction)\n * @returns {Array<import('./jsmind.node.js').Node|null>}\n */\n _add_nodes_recursive(parent_node, node_data) {\n var created_nodes = [];\n\n // Validate required fields (using standard field names only)\n if (!node_data.id || !node_data.topic) {\n logger.warn('invalid node data:', node_data);\n return [];\n }\n\n // Create the node using standard field names\n var new_node = this._add_node_data(\n parent_node,\n node_data.id,\n node_data.topic,\n node_data.data || {},\n node_data.direction\n );\n\n if (new_node) {\n created_nodes.push(new_node);\n // Process children using standard field name\n if (Array.isArray(node_data.children)) {\n const sub_nodes = node_data.children\n .map(child => this._add_nodes_recursive(new_node, child))\n .flat();\n created_nodes = created_nodes.concat(sub_nodes);\n }\n }\n\n return created_nodes;\n }\n\n /**\n * Count expected nodes recursively.\n * Supports custom field names via options.fieldNames configuration.\n * @private\n * @param {Array} nodes_data\n * @returns {number}\n */\n _count_expected_nodes(nodes_data) {\n if (!Array.isArray(nodes_data)) {\n return 0;\n }\n\n // Get field names from options (support custom field names)\n var fn = this.options.fieldNames || {};\n var childrenKey = fn.children || 'children';\n\n return nodes_data.reduce((count, node_data) => {\n count++; // Count current node\n // Use custom children field name\n count += this._count_expected_nodes(node_data && node_data[childrenKey]);\n return count;\n }, 0);\n }\n\n /**\n * Clean up partially created nodes without triggering UI refresh for each node.\n * @private\n * @param {Array<import('./jsmind.node.js').Node>} created_nodes\n */\n _cleanup_partial_nodes(created_nodes) {\n if (created_nodes.length === 0) return;\n // Remove all created nodes in reverse order to avoid parent-child issues\n // Use direct view and mind operations without triggering layout/show\n [...created_nodes].reverse().forEach(node => {\n if (node && !node.isroot) {\n // Remove from view without triggering layout\n this.view.remove_node(node);\n // Remove from mind model without triggering layout\n this.mind.remove_node(node);\n }\n });\n }\n\n /**\n * Insert a node before target node.\n * @param {string | import('./jsmind.node.js').Node} node_before\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @returns {import('./jsmind.node.js').Node|null}\n */\n insert_node_before(node_before, node_id, topic, data, direction) {\n if (this.get_editable()) {\n var the_node_before = this.get_node(node_before);\n var dir = Direction.of(direction);\n if (dir === undefined) {\n dir = this.layout.calculate_next_child_direction(the_node_before.parent);\n }\n var node = this.mind.insert_node_before(the_node_before, node_id, topic, data, dir);\n if (!!node) {\n this.view.add_node(node);\n this.layout.layout();\n this.view.show(false);\n this.invoke_event_handle(EventType.edit, {\n evt: 'insert_node_before',\n data: [the_node_before.id, node_id, topic, data, dir],\n node: node_id,\n });\n }\n return node;\n } else {\n logger.error('fail, this mind map is not editable');\n return null;\n }\n }\n /**\n * Insert a node after target node.\n * @param {string | import('./jsmind.node.js').Node} node_after\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @returns {import('./jsmind.node.js').Node|null}\n */\n insert_node_after(node_after, node_id, topic, data, direction) {\n if (this.get_editable()) {\n var the_node_after = this.get_node(node_after);\n var dir = Direction.of(direction);\n if (dir === undefined) {\n dir = this.layout.calculate_next_child_direction(the_node_after.parent);\n }\n var node = this.mind.insert_node_after(the_node_after, node_id, topic, data, dir);\n if (!!node) {\n this.view.add_node(node);\n this.layout.layout();\n this.view.show(false);\n this.invoke_event_handle(EventType.edit, {\n evt: 'insert_node_after',\n data: [the_node_after.id, node_id, topic, data, dir],\n node: node_id,\n });\n }\n return node;\n } else {\n logger.error('fail, this mind map is not editable');\n return null;\n }\n }\n /**\n * Remove a node.\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {boolean}\n */\n remove_node(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return false;\n } else {\n return this.remove_node(the_node);\n }\n }\n if (this.get_editable()) {\n if (node.isroot) {\n logger.error('fail, can not remove root node');\n return false;\n }\n var node_id = node.id;\n var parent_id = node.parent.id;\n var parent_node = this.get_node(parent_id);\n this.view.save_location(parent_node);\n this.view.remove_node(node);\n this.mind.remove_node(node);\n this.layout.layout();\n this.view.show(false);\n this.view.restore_location(parent_node);\n this.invoke_event_handle(EventType.edit, {\n evt: 'remove_node',\n data: [node_id],\n node: parent_id,\n });\n return true;\n } else {\n logger.error('fail, this mind map is not editable');\n return false;\n }\n }\n /**\n * Update the topic (text content) and/or data of a node.\n * @param {string} node_id\n * @param {string|{topic?:string, data?:Record<string,any>}} topic_or_options - Topic string or options object\n */\n update_node(node_id, topic_or_options) {\n if (this.get_editable()) {\n var node = this.get_node(node_id);\n if (!!node) {\n var topic = null;\n var data = null;\n\n // Parse parameters\n if (typeof topic_or_options === 'string') {\n topic = topic_or_options;\n } else if (typeof topic_or_options === 'object' && topic_or_options !== null) {\n topic = topic_or_options.topic;\n data = topic_or_options.data;\n }\n\n var topicChanged = false;\n var dataChanged = false;\n\n // Update topic if provided\n if (topic !== undefined && topic !== null) {\n if (_util.text.is_empty(topic)) {\n logger.warn('fail, topic can not be empty');\n return;\n }\n if (node.topic !== topic) {\n node.topic = topic;\n topicChanged = true;\n }\n }\n\n // Merge data with existing data\n if (data && typeof data === 'object') {\n for (var key in data) {\n if (data.hasOwnProperty(key)) {\n node.data[key] = data[key];\n dataChanged = true;\n }\n }\n }\n\n if (!topicChanged && !dataChanged) {\n logger.info('nothing changed');\n this.view.update_node(node);\n return;\n }\n\n this.view.update_node(node);\n this.layout.layout();\n this.view.show(false);\n this.invoke_event_handle(EventType.edit, {\n evt: 'update_node',\n data: [node_id, topic, data],\n node: node_id,\n });\n }\n } else {\n logger.error('fail, this mind map is not editable');\n return;\n }\n }\n /**\n * Move a node and optionally change direction.\n * @param {string} node_id\n * @param {string=} before_id - The ID of the node before which to place the moved node. Special values: \"_first_\", \"_last_\"\n * @param {string=} parent_id\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1). Only effective for second-level nodes (children of root). If not provided, direction will be determined automatically.\n */\n move_node(node_id, before_id, parent_id, direction) {\n if (this.get_editable()) {\n var node = this.get_node(node_id);\n var updated_node = this.mind.move_node(node, before_id, parent_id, direction);\n if (!!updated_node) {\n this.view.update_node(updated_node);\n this.layout.layout();\n this.view.show(false);\n this.invoke_event_handle(EventType.edit, {\n evt: 'move_node',\n data: [node_id, before_id, parent_id, direction],\n node: node_id,\n });\n }\n } else {\n logger.error('fail, this mind map is not editable');\n return;\n }\n }\n /**\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {void}\n */\n select_node(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return;\n } else {\n this.select_node(the_node);\n return;\n }\n }\n if (!this.layout.is_visible(node)) {\n return;\n }\n this.mind.selected = node;\n this.view.select_node(node);\n this.invoke_event_handle(EventType.select, { evt: 'select_node', data: [], node: node.id });\n }\n /**\n * Get the currently selected node.\n *\n * This is a query API that returns the internal Node instance.\n * For data export with custom fieldNames, use `get_data()` instead.\n *\n * @returns {import('./jsmind.node.js').Node|null} Node instance or null\n */\n get_selected_node() {\n if (!!this.mind) {\n return this.mind.selected;\n } else {\n return null;\n }\n }\n /** clear selection */\n select_clear() {\n if (!!this.mind) {\n this.mind.selected = null;\n this.view.select_clear();\n }\n }\n /** @param {string | import('./jsmind.node.js').Node} node */\n is_node_visible(node) {\n return this.layout.is_visible(node);\n }\n /**\n * Scroll the mind map to center the specified node.\n * @param {string | import('./jsmind.node.js').Node} node\n */\n scroll_node_to_center(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n } else {\n this.scroll_node_to_center(the_node);\n }\n return;\n }\n this.view.center_node(node);\n }\n /**\n * Find the previous sibling node of the given node.\n *\n * @param {string | import('./jsmind.node.js').Node} node - Node id or Node instance\n * @returns {import('./jsmind.node.js').Node | null}\n */\n find_node_before(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return;\n } else {\n return this.find_node_before(the_node);\n }\n }\n if (node.isroot) {\n return null;\n }\n var n = null;\n if (node.parent.isroot) {\n var c = node.parent.children;\n var prev = null;\n var ni = null;\n for (var i = 0; i < c.length; i++) {\n ni = c[i];\n if (node.direction === ni.direction) {\n if (node.id === ni.id) {\n n = prev;\n }\n prev = ni;\n }\n }\n } else {\n n = this.mind.get_node_before(node);\n }\n return n;\n }\n /**\n * Find the next sibling node of the given node.\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {import('./jsmind.node.js').Node | null}\n */\n find_node_after(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return;\n } else {\n return this.find_node_after(the_node);\n }\n }\n if (node.isroot) {\n return null;\n }\n var n = null;\n if (node.parent.isroot) {\n var c = node.parent.children;\n var found = false;\n var ni = null;\n for (var i = 0; i < c.length; i++) {\n ni = c[i];\n if (node.direction === ni.direction) {\n if (found) {\n n = ni;\n break;\n }\n if (node.id === ni.id) {\n found = true;\n }\n }\n }\n } else {\n n = this.mind.get_node_after(node);\n }\n return n;\n }\n /**\n * Set background and foreground colors for a node.\n * @param {string} node_id\n * @param {string=} bg_color\n * @param {string=} fg_color\n * @returns {void}\n */\n set_node_color(node_id, bg_color, fg_color) {\n if (this.get_editable()) {\n var node = this.mind.get_node(node_id);\n if (!!node) {\n if (!!bg_color) {\n node.data['background-color'] = bg_color;\n }\n if (!!fg_color) {\n node.data['foreground-color'] = fg_color;\n }\n this.view.reset_node_custom_style(node);\n }\n } else {\n logger.error('fail, this mind map is not editable');\n return null;\n }\n }\n /**\n * Set font style for a node.\n * @param {string} node_id\n * @param {number=} size\n * @param {string=} weight\n * @param {string=} style\n * @returns {void}\n */\n set_node_font_style(node_id, size, weight, style) {\n if (this.get_editable()) {\n var node = this.mind.get_node(node_id);\n if (!!node) {\n if (!!size) {\n node.data['font-size'] = size;\n }\n if (!!weight) {\n node.data['font-weight'] = weight;\n }\n if (!!style) {\n node.data['font-style'] = style;\n }\n this.view.reset_node_custom_style(node);\n this.view.update_node(node);\n this.layout.layout();\n this.view.show(false);\n }\n } else {\n logger.error('fail, this mind map is not editable');\n return null;\n }\n }\n /**\n * Set background image for a node.\n * @param {string} node_id\n * @param {string=} image\n * @param {number=} width\n * @param {number=} height\n * @param {number=} rotation\n * @returns {void}\n */\n set_node_background_image(node_id, image, width, height, rotation) {\n if (this.get_editable()) {\n var node = this.mind.get_node(node_id);\n if (!!node) {\n if (!!image) {\n node.data['background-image'] = image;\n }\n if (!!width) {\n node.data['width'] = width;\n }\n if (!!height) {\n node.data['height'] = height;\n }\n if (!!rotation) {\n node.data['background-rotation'] = rotation;\n }\n this.view.reset_node_custom_style(node);\n this.view.update_node(node);\n this.layout.layout();\n this.view.show(false);\n }\n } else {\n logger.error('fail, this mind map is not editable');\n return null;\n }\n }\n /**\n * @param {string} node_id\n * @param {number} rotation\n * @returns {void}\n */\n set_node_background_rotation(node_id, rotation) {\n if (this.get_editable()) {\n var node = this.mind.get_node(node_id);\n if (!!node) {\n if (!node.data['background-image']) {\n logger.error(\n 'fail, only can change rotation angle of node with background image'\n );\n return null;\n }\n node.data['background-rotation'] = rotation;\n this.view.reset_node_custom_style(node);\n this.view.update_node(node);\n this.layout.layout();\n this.view.show(false);\n }\n } else {\n logger.error('fail, this mind map is not editable');\n return null;\n }\n }\n /** trigger view resize */\n resize() {\n this.view.resize();\n }\n // callback(type ,data)\n /** @param {(type:number, data: EventData)=>void} callback */\n add_event_listener(callback) {\n if (typeof callback === 'function') {\n this.event_handles.push(callback);\n }\n }\n /** clear event listeners */\n clear_event_listener() {\n this.event_handles = [];\n }\n /** @param {number} type @param {EventData} data */\n invoke_event_handle(type, data) {\n var j = this;\n $.w.setTimeout(function () {\n j._invoke_event_handle(type, data);\n }, 0);\n }\n /** @param {number} type @param {EventData} data */\n _invoke_event_handle(type, data) {\n var l = this.event_handles.length;\n for (var i = 0; i < l; i++) {\n this.event_handles[i](type, data);\n }\n }\n\n /**\n * Remove an enhanced plugin\n * @param {typeof EnhancedPlugin} PluginClass - Plugin class\n */\n removePlugin(PluginClass) {\n if (this.enhancedPluginManager) {\n this.enhancedPluginManager.removePlugin(PluginClass);\n }\n }\n\n /**\n * Get an enhanced plugin instance\n * @param {string} instanceName - Plugin instance name\n * @returns {EnhancedPlugin | undefined}\n */\n getPlugin(instanceName) {\n if (this.enhancedPluginManager) {\n return this.enhancedPluginManager.getPlugin(instanceName);\n }\n return undefined;\n }\n\n /**\n * Destroy the jsMind instance and clean up resources\n */\n destroy() {\n // Destroy enhanced plugins\n if (this.enhancedPluginManager) {\n this.enhancedPluginManager.destroyAllPlugins();\n }\n\n // Clear event listeners\n this.clear_event_listener();\n\n // Clean up view\n if (this.view) {\n this.view.reset();\n }\n\n // Clear mind data\n this.mind = null;\n this.initialized = false;\n }\n\n /**\n * Deprecated: static show constructor helper.\n * @param {import('./jsmind.option.js').JsMindRuntimeOptions} options\n * @param {object | null} mind\n * @returns {jsMind}\n */\n static show(options, mind) {\n logger.warn(\n '`jsMind.show(options, mind)` is deprecated, please use `jm = new jsMind(options); jm.show(mind);` instead'\n );\n var _jm = new jsMind(options);\n _jm.show(mind);\n return _jm;\n }\n}\n"],"names":["__version__","String","prototype","startsWith","p","this","slice","length","Direction","left","center","right","of","dir","parseInt","toLowerCase","EventType","show","resize","edit","select","reset","history_change","LogLevel","debug","info","warn","error","disable","_noop","logger","console","level","log","log_level","$","constructor","w","d","document","g","id","getElementById","c","tag","createElement","t","n","hasChildNodes","firstChild","nodeValue","appendChild","createTextNode","h","HTMLElement","innerHTML","i","el","nodeType","style","ownerDocument","on","e","addEventListener","attachEvent","window","util","file","read","file_data","fn_callback","reader","FileReader","onload","result","name","readAsText","save","type","blob","Blob","bb","BlobBuilder","MozBlobBuilder","WebKitBlobBuilder","MSBlobBuilder","append","getBlob","navigator","msSaveBlob","blob_url","URL","webkitURL","createObjectURL","anchor","visibility","href","download","body","evt","createEvent","initEvent","dispatchEvent","removeChild","location","json","json2string","JSON","stringify","string2json","json_str","parse","merge","b","a","o","Object","toString","call","uuid","newid","Date","getTime","Math","random","substring","text","is_empty","s","replace","default_options","container","editable","theme","mode","support_html","view","engine","enable_device_pixel_ratio","hmargin","vmargin","line_width","line_color","line_style","draggable","hide_scrollbars_when_draggable","node_overflow","zoom","min","max","step","mask_key","custom_node_render","expander_style","layout","hspace","vspace","pspace","cousin_space","default_event_handle","enable_mousedown_handle","enable_click_handle","enable_dblclick_handle","enable_mousewheel_handle","shortcut","enable","handles","mapping","addchild","addbrother","editnode","delnode","toggle","up","down","fieldNames","topic","children","parentid","isroot","direction","expanded","plugin","Node","sId","iIndex","sTopic","oData","bIsRoot","oParent","eDirection","bExpanded","index","data","parent","_data","get_location","vd","x","abs_x","y","abs_y","get_size","width","height","compare","node1","node2","i1","i2","inherited","parent_node","node","pid","is_node","toObject","includeChildren","fn","idKey","topicKey","childrenKey","directionKey","expandedKey","obj","k","map","child","Mind","author","version","root","selected","nodes","get_node","node_id","set_root","_put_node","add_node","idx","push","_update_index","insert_node_before","node_before","node_index","get_node_before","the_node","insert_node_after","node_after","get_node_after","move_node","before_id","parent_id","_move_node","_flow_node_direction","len","_move_node_internal","sibling","si","splice","origin_parent","remove_node","ci","node_parent","sort","DEFAULT_META","format","node_tree","example","meta","get_mind","source","df","mind","_parse","get_data","_build_node","node_root","_extract_data","_extract_subnode","node_json","node_data","node_array","_array","reverse","root_node","_extract_root","isrootKey","root_json","parentidKey","extract_count","node_direction","sub_extract_count","_array_node","freemind","xml","xml_doc","_parse_xml","xml_root","_find_root","_load_node","xml_lines","_build_map","join","DOMParser","parseFromString","ActiveXObject","async","loadXML","childNodes","tagName","ns","xml_node","getAttribute","node_topic","node_folded","topic_children","topic_child","textContent","_load_attributes","node_expanded","node_foreground_color","node_background_color","node_position","attr","attr_data","pos","_escape","_line_regex","lines","split","_fill_nodes","node_path","line","match","substr","diff","pop","_build_lines","prefix","Array","DataProvider","jm","init","load","mind_data","options","data_format","LayoutProvider","opts","isside","bounds","cache_valid","calculate_next_child_direction","children_len","r","layout_direction","layout_offset","_layout_direction_root","layout_data","children_count","side_index","_layout_direction_side","subnode","offset_x","offset_y","outer_height","left_nodes","right_nodes","unshift","outer_height_left","_layout_offset_subnodes","outer_height_right","total_height","nodes_count","node_outer_height","base_y","pd","set_visible","_should_reserve_cousin_space","middle_height","_layout_offset_subnodes_height","get_node_offset","offset_cache","_offset_","offset_p","get_node_point","view_data","get_node_point_in","get_node_point_out","pout_cache","_pout_","get_expander_point","ex_p","ceil","get_min_size","pout","toggle_node","collapse_node","expand_node","part_layout","invoke_event_handle","expand_all","collapse_all","expand_to_depth","target_depth","curr_nodes","curr_depth","depth","root_layout_data","visible","is_expand","is_visible","SvgGraph","e_svg","setAttribute","size","line_drawing","straight","_line_to","curved","_bezier_to","init_line_render","createElementNS","custom_line_render","drawing","path","x1","y1","x2","y2","ctx","start_point","end_point","element","set_size","clear","draw_line","pin","offset","color","copy_to","dest_canvas_ctx","callback","img","Image","drawImage","src","btoa","XMLSerializer","serializeToString","CanvasGraph","e_canvas","className","canvas_ctx","getContext","dpr","device_pixel_ratio","scale","clearRect","strokeStyle","lineWidth","lineCap","beginPath","moveTo","bezierCurveTo","stroke","lineTo","ViewProvider","e_panel","e_nodes","selected_node","editing_node","graph","render_node","_custom_node_render","_default_node_render","zoom_current","devicePixelRatio","_initialized","e_editor","tabIndex","v","event","keyCode","edit_node_end","stopPropagation","offsetParent","IntersectionObserver","entities","observer","isIntersecting","unobserve","observe","add_event","event_name","event_handle","capture_by_panel","target","get_binded_nodeid","parentElement","is_expander","clear_lines","clear_nodes","reset_theme","theme_name","reset_custom_style","nodeid","reset_node_custom_style","setup_canvas_draggable","init_nodes","expand_size","min_size","min_width","min_height","client_w","clientWidth","client_h","clientHeight","init_nodes_size","doc_frag","createDocumentFragment","create_node_element","run_in_c11y_mode_if_needed","func","position","top","d_e","expander","_reset_node_custom_style","update_node","origin_style","select_node","restore_selected_node_custom_style","clear_selected_node_custom_style","select_clear","get_editing_node","is_editing","edit_node_begin","ncs","getComputedStyle","value","getPropertyValue","zIndex","focus","get_view_offset","_show","show_nodes","show_lines","zoom_in","set_zoom","zoom_out","e_panel_rect","getBoundingClientRect","zoom_center","panel_scroll_x","scrollLeft","panel_scroll_y","scrollTop","keep_center","center_node","relayout","save_location","_saved_location","restore_location","node_element","view_offset","display","_show_expander","expander_text","_get_expander_text","p_expander","ele","backgroundColor","fontSize","fontWeight","fontStyle","backgroundImage","scaledImageData","toDataURL","backgroundSize","transform","_offset","enabled","dragging","eventDown","clientX","clientY","eventMove","scrollBy","node_center_point","scrollTo","zoomIn","zoomOut","setZoom","ShortcutProvider","_newid","_mapping","handle","handler","bind","handle_addchild","handle_addbrother","handle_editnode","handle_delnode","handle_toggle","handle_up","handle_down","handle_left","handle_right","keys","isArray","key","id_generator","enable_shortcut","disable_shortcut","which","preventDefault","kc","metaKey","ctrlKey","altKey","shiftKey","_jm","get_selected_node","begin_edit","up_node","find_node_before","np","down_node","find_node_after","_handle_direction","floor","plugin_data","plugins","register","Plugin","Error","includes","apply","setTimeout","forEach","fn_init","_apply","EnhancedPluginManager","Map","initPreloadPlugins","preloadPlugins","enhancedPluginList","filter","preload","descriptor","_initPlugin","initNormalPlugins","normalPlugins","PluginClass","pluginOpt","instanceName","has","instance","set","removePlugin","get","beforePluginRemove","delete","list","findIndex","destroyAllPlugins","beforePluginDestroy","getPlugin","EnhancedPlugin","static","jsMind","_register_plugin","_util","usePlugin","some","hasEnhancedPlugin","current","merge_option","initialized","event_handles","enhancedPluginManager","opts_layout","opts_view","_event_bind","apply_plugins","get_editable","enable_edit","disable_edit","get_view_draggable","enable_view_draggable","disable_view_draggable","enable_event_handle","disable_event_handle","set_theme","theme_old","mousedown_handle","click_handle","dblclick_handle","mousewheel_handle","srcElement","deltaY","end_edit","_reset","skip_centering","m","get_meta","get_root","_add_node_data","undefined","_refresh_node_ui","the_parent_node","add_nodes","nodes_data","expected_count","_count_expected_nodes","created_nodes","_add_nodes_recursive","flat","actual_count","_cleanup_partial_nodes","new_node","sub_nodes","concat","reduce","count","the_node_before","the_node_after","topic_or_options","topicChanged","dataChanged","hasOwnProperty","updated_node","is_node_visible","scroll_node_to_center","prev","ni","found","set_node_color","bg_color","fg_color","set_node_font_style","weight","set_node_background_image","image","rotation","set_node_background_rotation","add_event_listener","clear_event_listener","j","_invoke_event_handle","l","destroy"],"mappings":";;;;;;;AAYO,MAAMA,EAAc,QAOe,mBAA/BC,OAAOC,UAAUC,aACxBF,OAAOC,UAAUC,WAAa,SAAUC,GACpC,OAAOC,KAAKC,MAAM,EAAGF,EAAEG,UAAYH,CAC3C,GAQO,MAAMI,EAAY,CACrBC,MAAO,EACPC,OAAQ,EACRC,MAAO,EACPC,GAAI,SAAUC,GACV,OAAKA,IAAgB,IAATA,GAAsB,IAARA,GAAqB,IAARA,EAG3B,OAARA,GAAwB,MAARA,GAAuB,MAARA,EACxBC,SAASD,GAEM,SAAtBA,EAAIE,cACGV,KAAKI,KAEU,UAAtBI,EAAIE,cACGV,KAAKM,MAEU,WAAtBE,EAAIE,cACGV,KAAKK,YADhB,EAXWG,CAcd,GAGQG,EAAY,CAAEC,KAAM,EAAGC,OAAQ,EAAGC,KAAM,EAAGC,OAAQ,EAAGC,MAAO,EAAGC,eAAgB,GAIhFC,EAAW,CAAEC,MAAO,EAAGC,KAAM,EAAGC,KAAM,EAAGC,MAAO,EAAGC,QAAS,GAGzE,IAAIC,EAAQ,WAAY,EAKjB,IAAIC,EACY,oBAAZC,QACD,CACIC,MAAOH,EACPI,IAAKJ,EACLL,MAAOK,EACPJ,KAAMI,EACNH,KAAMG,EACNF,MAAOE,GAEX,CACIG,MAYd,SAA4BE,GAEpBJ,EAAON,MADPU,EAAYX,EAASC,MACNK,EAEAE,QAAQP,MAGvBM,EAAOL,KADPS,EAAYX,EAASE,KACPI,EAEAE,QAAQN,KAGtBK,EAAOJ,KADPQ,EAAYX,EAASG,KACPG,EAEAE,QAAQL,KAGtBI,EAAOH,MADPO,EAAYX,EAASI,MACNE,EAEAE,QAAQJ,KAE/B,EAhCcM,IAAKF,QAAQE,IACbT,MAAOO,QAAQP,MACfC,KAAMM,QAAQN,KACdC,KAAMK,QAAQL,KACdC,MAAOI,QAAQJ,OCctB,MAAMQ,EAAI,IApFjB,MAII,WAAAC,CAAYC,GAERhC,KAAKgC,EAAIA,EAEThC,KAAKiC,EAAID,EAAEE,SAMXlC,KAAKmC,EAAI,SAAUC,GACf,OAAOpC,KAAKiC,EAAEI,eAAeD,EACzC,EAMQpC,KAAKsC,EAAI,SAAUC,GACf,OAAOvC,KAAKiC,EAAEO,cAAcD,EACxC,EAMQvC,KAAKyC,EAAI,SAAUC,EAAGD,GACdC,EAAEC,gBACFD,EAAEE,WAAWC,UAAYJ,EAEzBC,EAAEI,YAAY9C,KAAKiC,EAAEc,eAAeN,GAEpD,EAOQzC,KAAKgD,EAAI,SAAUN,EAAGD,GACdA,aAAaQ,aACbP,EAAEQ,UAAY,GACdR,EAAEI,YAAYL,IAEdC,EAAEQ,UAAYT,CAE9B,EAOQzC,KAAKmD,EAAI,SAAUC,GACf,QACMA,GACY,iBAAPA,GACS,IAAhBA,EAAGC,UACiB,iBAAbD,EAAGE,OACkB,iBAArBF,EAAGG,aAE1B,EASQvD,KAAKwD,GAAK,SAAUf,EAAGgB,EAAGT,GAChBP,EAAEiB,iBACJjB,EAAEiB,iBAAiBD,EAAGT,GAAG,GAEzBP,EAAEkB,YAAY,KAAOF,EAAGT,EAExC,CACK,GAGoBY,QC5EZC,EAAO,CAChBC,KAAM,CACFC,KAAM,SAAUC,EAAWC,GACvB,IAAIC,EAAS,IAAIC,WACjBD,EAAOE,OAAS,WACe,mBAAhBH,GACPA,EAAYjE,KAAKqE,OAAQL,EAAUM,KAEvD,EACYJ,EAAOK,WAAWP,EACrB,EAEDQ,KAAM,SAAUR,EAAWS,EAAMH,GAC7B,IAAII,EACJ,GAAwB,mBAAb5C,EAAEE,EAAE2C,KACXD,EAAO,IAAIC,KAAK,CAACX,GAAY,CAAES,KAAMA,QAClC,CACH,IAKIG,EAAK,IAJL9C,EAAEE,EAAE6C,aACJ/C,EAAEE,EAAE8C,gBACJhD,EAAEE,EAAE+C,mBACJjD,EAAEE,EAAEgD,eAERJ,EAAGK,OAAOjB,GACVU,EAAOE,EAAGM,QAAQT,EACrB,CACD,GAAIU,UAAUC,WACVD,UAAUC,WAAWV,EAAMJ,OACxB,CACH,IACIe,GADMvD,EAAEE,EAAEsD,KAAOxD,EAAEE,EAAEuD,WACNC,gBAAgBd,GAC/Be,EAAS3D,EAAEQ,EAAE,KACjB,GAAI,aAAcmD,EAAQ,CACtBA,EAAOnC,MAAMoC,WAAa,SAC1BD,EAAOE,KAAON,EACdI,EAAOG,SAAWtB,EAClBxC,EAAEG,EAAE4D,KAAK/C,YAAY2C,GACrB,IAAIK,EAAMhE,EAAEG,EAAE8D,YAAY,eAC1BD,EAAIE,UAAU,SAAS,GAAM,GAC7BP,EAAOQ,cAAcH,GACrBhE,EAAEG,EAAE4D,KAAKK,YAAYT,EACzC,MACoBU,SAASR,KAAON,CAEvB,CACJ,GAGLe,KAAM,CACFC,YAAa,SAAUD,GACnB,OAAOE,KAAKC,UAAUH,EACzB,EACDI,YAAa,SAAUC,GACnB,OAAOH,KAAKI,MAAMD,EACrB,EACDE,MAAO,SAAUC,EAAGC,GAChB,IAAK,IAAIC,KAAKD,EACNC,KAAKF,EAEe,iBAATA,EAAEE,IAC6C,mBAAtDC,OAAOlH,UAAUmH,SAASC,KAAKL,EAAEE,IAAIpG,eACpCkG,EAAEE,GAAG5G,OAIN0G,EAAEE,GAAKD,EAAEC,GAFTjD,EAAKuC,KAAKO,MAAMC,EAAEE,GAAID,EAAEC,IAK5BF,EAAEE,GAAKD,EAAEC,GAGjB,OAAOF,CACV,GAGLM,KAAM,CACFC,MAAO,WACH,QACI,IAAIC,MAAOC,UAAUL,SAAS,IAAMM,KAAKC,SAASP,SAAS,IAAIQ,UAAU,IAC3EA,UAAU,EAAG,GAClB,GAGLC,KAAM,CACFC,SAAU,SAAUC,GAChB,OAAKA,GAGiC,GAA/BA,EAAEC,QAAQ,MAAO,IAAI1H,MAC/B,IClEH2H,EAAkB,CACpBC,UAAW,GACXC,UAAU,EACVC,MAAO,KACPC,KAAM,OACNC,cAAc,EACdrG,UAAW,OAEXsG,KAAM,CACFC,OAAQ,SACRC,2BAA2B,EAC3BC,QAAS,IACTC,QAAS,GACTC,WAAY,EACZC,WAAY,OACZC,WAAY,SACZC,WAAW,EACXC,gCAAgC,EAChCC,cAAe,SACfC,KAAM,CACFC,IAAK,GACLC,IAAK,IACLC,KAAM,GACNC,SAAU,MAEdC,mBAAoB,KACpBC,eAAgB,QAEpBC,OAAQ,CACJC,OAAQ,GACRC,OAAQ,GACRC,OAAQ,GACRC,aAAc,GAElBC,qBAAsB,CAClBC,yBAAyB,EACzBC,qBAAqB,EACrBC,wBAAwB,EACxBC,0BAA0B,GAE9BC,SAAU,CACNC,QAAQ,EACRC,QAAS,CAAE,EACXC,QAAS,CACLC,SAAU,CAAC,GAAI,MACfC,WAAY,GACZC,SAAU,IACVC,QAAS,GACTC,OAAQ,GACRnK,KAAM,GACNoK,GAAI,GACJlK,MAAO,GACPmK,KAAM,KAKdC,WAAY,CACRtI,GAAI,KACJuI,MAAO,QACPC,SAAU,WACVC,SAAU,WACVC,OAAQ,SACRC,UAAW,YACXC,SAAU,YAEdC,OAAQ,CAAE,GCnGP,MAAMC,EAYT,WAAAnJ,CAAYoJ,EAAKC,EAAQC,EAAQC,EAAOC,EAASC,EAASC,EAAYC,GAC7DP,EAIgB,iBAAVC,QAIc,IAAdM,IACPA,GAAY,GAEhB1L,KAAKoC,GAAK+I,EACVnL,KAAK2L,MAAQP,EACbpL,KAAK2K,MAAQU,EAEbrL,KAAK4L,KAAON,GAAS,GACrBtL,KAAK8K,OAASS,EACdvL,KAAK6L,OAASL,EACdxL,KAAK+K,UAAYU,EACjBzL,KAAKgL,WAAaU,EAElB1L,KAAK4K,SAAW,GAChB5K,KAAK8L,MAAQ,IAjBTrK,EAAOH,MAAM,sBAJbG,EAAOH,MAAM,kBAsBpB,CAMD,YAAAyK,GACI,IAAIC,EAAKhM,KAAK8L,MAAM3D,KACpB,MAAO,CACH8D,EAAGD,EAAGE,MACNC,EAAGH,EAAGI,MAEb,CAKD,QAAAC,GACI,IAAIL,EAAKhM,KAAK8L,MAAM3D,KACpB,MAAO,CACHnG,EAAGgK,EAAGM,MACNtJ,EAAGgJ,EAAGO,OAEb,CAQD,cAAOC,CAAQC,EAAOC,GAElB,IACIC,EAAKF,EAAMd,MACXiB,EAAKF,EAAMf,MAYf,OAXIgB,GAAM,GAAKC,GAAM,EACbD,EAAKC,GACK,GAAPD,IAAmB,GAAPC,EACf,GACU,GAAPD,EACH,GACU,GAAPC,GACF,EAED,CAGX,CAOD,gBAAOC,CAAUC,EAAaC,GAC1B,GAAMD,GAAiBC,EAAM,CACzB,GAAID,EAAY1K,KAAO2K,EAAK3K,GACxB,OAAO,EAEX,GAAI0K,EAAYhC,OACZ,OAAO,EAIX,IAFA,IAAIkC,EAAMF,EAAY1K,GAClBrC,EAAIgN,GACAhN,EAAE+K,QAEN,IADA/K,EAAIA,EAAE8L,QACAzJ,KAAO4K,EACT,OAAO,CAGlB,CACD,OAAO,CACV,CAMD,cAAOC,CAAQvK,GACX,QAASA,GAAKA,aAAawI,CAC9B,CAQD,QAAAgC,CAASxC,EAAYyC,GAAkB,GACnC,IAAIC,EAAK1C,GAAc,GACnB2C,EAAQD,EAAGhL,IAAM,KACjBkL,EAAWF,EAAGzC,OAAS,QACvB4C,EAAcH,EAAGxC,UAAY,WAC7B4C,EAAeJ,EAAGrC,WAAa,YAC/B0C,EAAcL,EAAGpC,UAAY,WAE7B0C,EAAM,CAAA,EAWV,GAVAA,EAAIL,GAASrN,KAAKoC,GAClBsL,EAAIJ,GAAYtN,KAAK2K,MACrB+C,EAAID,GAAezN,KAAKgL,SAGlBhL,KAAK6L,QAAU7L,KAAK6L,OAAOf,SAC7B4C,EAAIF,IAAoC,IAApBxN,KAAK+K,UAAmB,OAAS,SAIxC,MAAb/K,KAAK4L,KACL,IAAK,IAAI+B,KAAK3N,KAAK4L,KACf8B,EAAIC,GAAK3N,KAAK4L,KAAK+B,GAS3B,OAJIR,GAAmBnN,KAAK4K,SAAS1K,OAAS,IAC1CwN,EAAIH,GAAevN,KAAK4K,SAASgD,IAAIC,GAASA,EAAMX,SAASxC,GAAY,KAGtEgD,CACV,EC1JE,MAAMI,EAIT,WAAA/L,GAEI/B,KAAKsE,KAAO,KAEZtE,KAAK+N,OAAS,KAEd/N,KAAKgO,QAAU,KAEfhO,KAAKiO,KAAO,KAEZjO,KAAKkO,SAAW,KAEhBlO,KAAKmO,MAAQ,EAChB,CAMD,QAAAC,CAASC,GACL,OAAIA,KAAWrO,KAAKmO,MACTnO,KAAKmO,MAAME,IAElB5M,EAAOJ,KAAK,eAAiBgN,EAAU,sBAChC,KAEd,CAQD,QAAAC,CAASD,EAAS1D,EAAOiB,GACrB,OAAiB,MAAb5L,KAAKiO,MACLjO,KAAKiO,KAAO,IAAI/C,EAAKmD,EAAS,EAAG1D,EAAOiB,GAAM,GAC9C5L,KAAKuO,UAAUvO,KAAKiO,MACbjO,KAAKiO,OAEZxM,EAAOH,MAAM,8BACN,KAEd,CAYD,QAAAkN,CAAS1B,EAAauB,EAAS1D,EAAOiB,EAAMb,EAAWC,EAAUyD,GAC7D,IAAKvD,EAAK+B,QAAQH,GAEd,OADArL,EAAOH,MAAM,mBAAqBwL,EAAc,mBACzC,KAEX,IACIC,EAAO,IAAI7B,EACXmD,EAFaI,IAAQ,EAIrB9D,EACAiB,GACA,EACAkB,EACAA,EAAY/B,UACZC,GAYJ,OAVI8B,EAAYhC,SACZiC,EAAKhC,UAAYA,GAAa5K,EAAUG,OAExCN,KAAKuO,UAAUxB,IACfD,EAAYlC,SAAS8D,KAAK3B,GAC1B/M,KAAK2O,cAAc7B,KAEnBrL,EAAOH,MAAM,sBAAwByL,EAAK3K,GAAK,6BAC/C2K,EAAO,MAEJA,CACV,CAUD,kBAAA6B,CAAmBC,EAAaR,EAAS1D,EAAOiB,EAAMb,GAClD,IAAKG,EAAK+B,QAAQ4B,GAEd,OADApN,EAAOH,MAAM,mBAAqBuN,EAAc,mBACzC,KAEX,IAAIC,EAAaD,EAAYlD,MAAQ,GACrC,OAAO3L,KAAKwO,SAASK,EAAYhD,OAAQwC,EAAS1D,EAAOiB,EAAMb,GAAW,EAAM+D,EACnF,CAMD,eAAAC,CAAgBhC,GACZ,IAAK7B,EAAK+B,QAAQF,GAAO,CACrB,IAAIiC,EAAWhP,KAAKoO,SAASrB,GAC7B,OAAKiC,EAIMhP,KAAK+O,gBAAgBC,IAH5BvN,EAAOH,MAAM,eAAiByL,EAAO,uBAC9B,KAId,CACD,GAAIA,EAAKjC,OACL,OAAO,KAEX,IAAI2D,EAAM1B,EAAKpB,MAAQ,EACvB,OAAI8C,GAAO,EACA1B,EAAKlB,OAAOjB,SAAS6D,GAErB,IAEd,CAUD,iBAAAQ,CAAkBC,EAAYb,EAAS1D,EAAOiB,EAAMb,GAChD,IAAKG,EAAK+B,QAAQiC,GAEd,OADAzN,EAAOH,MAAM,kBAAoB4N,EAAa,mBACvC,KAEX,IAAIJ,EAAaI,EAAWvD,MAAQ,GACpC,OAAO3L,KAAKwO,SAASU,EAAWrD,OAAQwC,EAAS1D,EAAOiB,EAAMb,GAAW,EAAM+D,EAClF,CAMD,cAAAK,CAAepC,GACX,IAAK7B,EAAK+B,QAAQF,GAAO,CACrB,IAAIiC,EAAWhP,KAAKoO,SAASrB,GAC7B,OAAKiC,EAIMhP,KAAKmP,eAAeH,IAH3BvN,EAAOH,MAAM,eAAiByL,EAAO,uBAC9B,KAId,CACD,GAAIA,EAAKjC,OACL,OAAO,KAEX,IAAI2D,EAAM1B,EAAKpB,MAEf,OADeoB,EAAKlB,OAAOjB,SACd1K,OAASuO,EACX1B,EAAKlB,OAAOjB,SAAS6D,GAErB,IAEd,CASD,SAAAW,CAAUrC,EAAMsC,EAAWC,EAAWvE,GAClC,OAAKG,EAAK+B,QAAQF,IAIbuC,IACDA,EAAYvC,EAAKlB,OAAOzJ,IAErBpC,KAAKuP,WAAWxC,EAAMsC,EAAWC,EAAWvE,KAN/CtJ,EAAOH,MAAM,sBAAwByL,EAAO,mBACrC,KAMd,CAMD,oBAAAyC,CAAqBzC,EAAMhC,QACE,IAAdA,EACPA,EAAYgC,EAAKhC,UAEjBgC,EAAKhC,UAAYA,EAGrB,IADA,IAAI0E,EAAM1C,EAAKnC,SAAS1K,OACjBuP,KACHzP,KAAKwP,qBAAqBzC,EAAKnC,SAAS6E,GAAM1E,EAErD,CAOD,mBAAA2E,CAAoB3C,EAAMsC,GACtB,GAAMtC,GAAUsC,EACZ,GAAiB,UAAbA,EACAtC,EAAKpB,OAAS,EACd3L,KAAK2O,cAAc5B,EAAKlB,aACrB,GAAiB,WAAbwD,EACPtC,EAAKpB,MAAQ,EACb3L,KAAK2O,cAAc5B,EAAKlB,YACrB,CACH,IAAIgD,EAAgBQ,EAAYrP,KAAKoO,SAASiB,GAAa,KAExC,MAAfR,GACsB,MAAtBA,EAAYhD,QACZgD,EAAYhD,OAAOzJ,IAAM2K,EAAKlB,OAAOzJ,KAErC2K,EAAKpB,MAAQkD,EAAYlD,MAAQ,GACjC3L,KAAK2O,cAAc5B,EAAKlB,QAE/B,CAEL,OAAOkB,CACV,CASD,UAAAwC,CAAWxC,EAAMsC,EAAWC,EAAWvE,GACnC,GAAMgC,GAAUuC,EAAW,CACvB,IAAIxC,EAAc9M,KAAKoO,SAASkB,GAChC,GAAIpE,EAAK2B,UAAUE,EAAMD,GAErB,OADArL,EAAOH,MAAM,uCACN,KAEX,GAAIyL,EAAKlB,OAAOzJ,IAAMkN,EAAW,CAI7B,IAFA,IAAIK,EAAU5C,EAAKlB,OAAOjB,SACtBgF,EAAKD,EAAQzP,OACV0P,KACH,GAAID,EAAQC,GAAIxN,IAAM2K,EAAK3K,GAAI,CAC3BuN,EAAQE,OAAOD,EAAI,GACnB,KACH,CAEL,IAAIE,EAAgB/C,EAAKlB,OACzBkB,EAAKlB,OAASiB,EACdA,EAAYlC,SAAS8D,KAAK3B,GAC1B/M,KAAK2O,cAAcmB,EACtB,CAEG/C,EAAKlB,OAAOf,OACRC,GAAa5K,EAAUC,KACvB2M,EAAKhC,UAAYA,EAEjBgC,EAAKhC,UAAY5K,EAAUG,MAG/ByM,EAAKhC,UAAYgC,EAAKlB,OAAOd,UAEjC/K,KAAK0P,oBAAoB3C,EAAMsC,GAC/BrP,KAAKwP,qBAAqBzC,EAC7B,CACD,OAAOA,CACV,CAMD,WAAAgD,CAAYhD,GACR,IAAK7B,EAAK+B,QAAQF,GAEd,OADAtL,EAAOH,MAAM,sBAAwByL,EAAO,oBACrC,EAEX,GAAIA,EAAKjC,OAEL,OADArJ,EAAOH,MAAM,mCACN,EAEU,MAAjBtB,KAAKkO,UAAoBlO,KAAKkO,SAAS9L,IAAM2K,EAAK3K,KAClDpC,KAAKkO,SAAW,MAKpB,IAFA,IAAItD,EAAWmC,EAAKnC,SAChBoF,EAAKpF,EAAS1K,OACX8P,KACHhQ,KAAK+P,YAAYnF,EAASoF,IAG9BpF,EAAS1K,OAAS,EAKlB,IAJA,IAAI+P,EAAclD,EAAKlB,OAEnB8D,EAAUM,EAAYrF,SACtBgF,EAAKD,EAAQzP,OACV0P,KACH,GAAID,EAAQC,GAAIxN,IAAM2K,EAAK3K,GAAI,CAC3BuN,EAAQE,OAAOD,EAAI,GACnB,KACH,CAKL,IAAK,IAAIjC,YAFF3N,KAAKmO,MAAMpB,EAAK3K,IAET2K,SACHA,EAAKY,GAKhB,OAFAZ,EAAO,KACP/M,KAAK2O,cAAcsB,IACZ,CACV,CAMD,SAAA1B,CAAUxB,GACN,OAAIA,EAAK3K,MAAMpC,KAAKmO,OAChB1M,EAAOJ,KAAK,gBAAkB0L,EAAK3K,GAAK,8BACjC,IAEPpC,KAAKmO,MAAMpB,EAAK3K,IAAM2K,GACf,EAEd,CAKD,aAAA4B,CAAc5B,GACV,GAAIA,aAAgB7B,EAAM,CACtB6B,EAAKnC,SAASsF,KAAKhF,EAAKsB,SACxB,IAAK,IAAIrJ,EAAI,EAAGA,EAAI4J,EAAKnC,SAAS1K,OAAQiD,IACtC4J,EAAKnC,SAASzH,GAAGwI,MAAQxI,EAAI,CAEpC,CACJ,ECpSL,MAAMgN,EAAe,CAAE7L,KAAM,SAAUyJ,ONpDb,UMoDiCC,QAASrO,GAWvDyQ,EAAS,CAClBC,UAAW,CACPC,QAAS,CACLC,KAAMJ,EACNC,OAAQ,YACRxE,KAAM,CAAExJ,GAAI,OAAQuI,MAAO,6BAG/B6F,SAAU,SAAUC,EAAQ/F,GACxB,IAAIgG,EAAKN,EAAOC,UACZM,EAAO,IAAI7C,EAKf,OAJA6C,EAAKrM,KAAOmM,EAAOF,KAAKjM,KACxBqM,EAAK5C,OAAS0C,EAAOF,KAAKxC,OAC1B4C,EAAK3C,QAAUyC,EAAOF,KAAKvC,QAC3B0C,EAAGE,OAAOD,EAAMF,EAAO7E,KAAMlB,GACtBiG,CACV,EAEDE,SAAU,SAAUF,EAAMjG,GACtB,IAAIgG,EAAKN,EAAOC,UACZjK,EAAO,CAAA,EAQX,OAPAA,EAAKmK,KAAO,CACRjM,KAAMqM,EAAKrM,KACXyJ,OAAQ4C,EAAK5C,OACbC,QAAS2C,EAAK3C,SAElB5H,EAAKgK,OAAS,YACdhK,EAAKwF,KAAO8E,EAAGI,YAAYH,EAAK1C,KAAMvD,GAC/BtE,CACV,EAGDwK,OAAQ,SAAUD,EAAMI,EAAWrG,GAC/B,IAAIgG,EAAKN,EAAOC,UACZjD,EAAK1C,GAAc,GACnB2C,EAAQD,EAAGhL,IAAM,KACjBkL,EAAWF,EAAGzC,OAAS,QACvB4C,EAAcH,EAAGxC,UAAY,WAE7BgB,EAAO8E,EAAGM,cAAcD,EAAWrG,GAEvC,GADAiG,EAAKrC,SAASyC,EAAU1D,GAAQ0D,EAAUzD,GAAW1B,GACjD2B,KAAewD,EAEf,IADA,IAAInG,EAAWmG,EAAUxD,GAChBpK,EAAI,EAAGA,EAAIyH,EAAS1K,OAAQiD,IACjCuN,EAAGO,iBAAiBN,EAAMA,EAAK1C,KAAMrD,EAASzH,GAAIuH,EAG7D,EASDsG,cAAe,SAAUE,EAAWxG,GAChC,IAAI0C,EAAK1C,GAAc,GACnB2C,EAAQD,EAAGhL,IAAM,KACjBkL,EAAWF,EAAGzC,OAAS,QACvB4C,EAAcH,EAAGxC,UAAY,WAC7B4C,EAAeJ,EAAGrC,WAAa,YAC/B0C,EAAcL,EAAGpC,UAAY,WAE7BY,EAAO,CAAA,EACX,IAAK,IAAI+B,KAAKuD,EAENvD,GAAKN,GACLM,GAAKL,GACLK,GAAKJ,GACLI,GAAKH,GACLG,GAAKF,IAIT7B,EAAK+B,GAAKuD,EAAUvD,IAExB,OAAO/B,CACV,EAGDqF,iBAAkB,SAAUN,EAAMV,EAAaiB,EAAWxG,GACtD,IAAIgG,EAAKN,EAAOC,UACZjD,EAAK1C,GAAc,GACnB2C,EAAQD,EAAGhL,IAAM,KACjBkL,EAAWF,EAAGzC,OAAS,QACvB4C,EAAcH,EAAGxC,UAAY,WAC7B4C,EAAeJ,EAAGrC,WAAa,YAC/B0C,EAAcL,EAAGpC,UAAY,WAE7BY,EAAO8E,EAAGM,cAAcE,EAAWxG,GACnCzI,EAAI,KACJgO,EAAYnF,SACZ7I,EAA+B,QAA3BiP,EAAU1D,GAA0BrN,EAAUC,KAAOD,EAAUG,OAEvE,IAAIyM,EAAO4D,EAAKnC,SACZyB,EACAiB,EAAU7D,GACV6D,EAAU5D,GACV1B,EACA3J,EACAiP,EAAUzD,IAEd,GAAMyD,EAAU3D,GAEZ,IADA,IAAI3C,EAAWsG,EAAU3D,GAChBpK,EAAI,EAAGA,EAAIyH,EAAS1K,OAAQiD,IACjCuN,EAAGO,iBAAiBN,EAAM5D,EAAMnC,EAASzH,GAAIuH,EAGxD,EASDoG,YAAa,SAAU/D,EAAMrC,GACzB,IAAIgG,EAAKN,EAAOC,UAChB,GAAMtD,aAAgB7B,EAAtB,CAGA,IAAIkC,EAAK1C,GAAc,GACnB2C,EAAQD,EAAGhL,IAAM,KACjBkL,EAAWF,EAAGzC,OAAS,QACvB4C,EAAcH,EAAGxC,UAAY,WAC7B4C,EAAeJ,EAAGrC,WAAa,YAC/B0C,EAAcL,EAAGpC,UAAY,WAE7BlE,EAAI,CAAA,EAQR,GAPAA,EAAEuG,GAASN,EAAK3K,GAChB0E,EAAEwG,GAAYP,EAAKpC,MACnB7D,EAAE2G,GAAeV,EAAK/B,SAEhB+B,EAAKlB,QAAUkB,EAAKlB,OAAOf,SAC7BhE,EAAE0G,GAAgBT,EAAKhC,WAAa5K,EAAUC,KAAO,OAAS,SAEjD,MAAb2M,EAAKnB,KAAc,CACnB,IAAIuF,EAAYpE,EAAKnB,KACrB,IAAK,IAAI+B,KAAKwD,EACVrK,EAAE6G,GAAKwD,EAAUxD,EAExB,CACD,IAAI/C,EAAWmC,EAAKnC,SACpB,GAAIA,EAAS1K,OAAS,EAAG,CACrB4G,EAAEyG,GAAe,GACjB,IAAK,IAAIpK,EAAI,EAAGA,EAAIyH,EAAS1K,OAAQiD,IACjC2D,EAAEyG,GAAamB,KAAKgC,EAAGI,YAAYlG,EAASzH,GAAIuH,GAEvD,CACD,OAAO5D,CA7BN,CA8BJ,GAGLsK,WAAY,CACRd,QAAS,CACLC,KAAMJ,EACNC,OAAQ,aACRxE,KAAM,CAAC,CAAExJ,GAAI,OAAQuI,MAAO,4BAA6BG,QAAQ,KAIrE0F,SAAU,SAAUC,EAAQ/F,GACxB,IAAIgG,EAAKN,EAAOgB,WACZT,EAAO,IAAI7C,EAKf,OAJA6C,EAAKrM,KAAOmM,EAAOF,KAAKjM,KACxBqM,EAAK5C,OAAS0C,EAAOF,KAAKxC,OAC1B4C,EAAK3C,QAAUyC,EAAOF,KAAKvC,QAC3B0C,EAAGE,OAAOD,EAAMF,EAAO7E,KAAMlB,GACtBiG,CACV,EAGDE,SAAU,SAAUF,EAAMjG,GACtB,IAAIgG,EAAKN,EAAOgB,WACZhL,EAAO,CAAA,EASX,OARAA,EAAKmK,KAAO,CACRjM,KAAMqM,EAAKrM,KACXyJ,OAAQ4C,EAAK5C,OACbC,QAAS2C,EAAK3C,SAElB5H,EAAKgK,OAAS,aACdhK,EAAKwF,KAAO,GACZ8E,EAAGW,OAAOV,EAAMvK,EAAKwF,KAAMlB,GACpBtE,CACV,EAGDwK,OAAQ,SAAUD,EAAMS,EAAY1G,GAChC,IAAIgG,EAAKN,EAAOgB,WACZjD,EAAQiD,EAAWnR,MAAM,GAE7BkO,EAAMmD,UACN,IAAIC,EAAYb,EAAGc,cAAcb,EAAMxC,EAAOzD,GACxC6G,EACFb,EAAGO,iBAAiBN,EAAMY,EAAWpD,EAAOzD,GAE5CjJ,EAAOH,MAAM,6BAEpB,EAGDkQ,cAAe,SAAUb,EAAMS,EAAY1G,GAQvC,IAPA,IAAIgG,EAAKN,EAAOgB,WACZhE,EAAK1C,GAAc,GACnB2C,EAAQD,EAAGhL,IAAM,KACjBkL,EAAWF,EAAGzC,OAAS,QACvB8G,EAAYrE,EAAGtC,QAAU,SAEzB3H,EAAIiO,EAAWlR,OACZiD,KACH,GAAIsO,KAAaL,EAAWjO,IAAMiO,EAAWjO,GAAGsO,GAAY,CACxD,IAAIC,EAAYN,EAAWjO,GACvByI,EAAO8E,EAAGM,cAAcU,EAAWhH,GACnCqC,EAAO4D,EAAKrC,SAASoD,EAAUrE,GAAQqE,EAAUpE,GAAW1B,GAEhE,OADAwF,EAAWvB,OAAO1M,EAAG,GACd4J,CACV,CAEL,OAAO,IACV,EAGDkE,iBAAkB,SAAUN,EAAM7D,EAAasE,EAAY1G,GAavD,IAZA,IAAIgG,EAAKN,EAAOgB,WACZhE,EAAK1C,GAAc,GACnB2C,EAAQD,EAAGhL,IAAM,KACjBkL,EAAWF,EAAGzC,OAAS,QACvBgH,EAAcvE,EAAGvC,UAAY,WAC7B2C,EAAeJ,EAAGrC,WAAa,YAC/B0C,EAAcL,EAAGpC,UAAY,WAE7B7H,EAAIiO,EAAWlR,OACfgR,EAAY,KACZtF,EAAO,KACPgG,EAAgB,EACbzO,KAEH,IADA+N,EAAYE,EAAWjO,IACTwO,IAAgB7E,EAAY1K,GAAI,CAC1CwJ,EAAO8E,EAAGM,cAAcE,EAAWxG,GACnC,IAAIzI,EAAI,KACJ4P,EAAiBX,EAAU1D,GACzBqE,IACF5P,EAAsB,QAAlB4P,EAA2B1R,EAAUC,KAAOD,EAAUG,OAE9D,IAAIyM,EAAO4D,EAAKnC,SACZ1B,EACAoE,EAAU7D,GACV6D,EAAU5D,GACV1B,EACA3J,EACAiP,EAAUzD,IAEd2D,EAAWvB,OAAO1M,EAAG,GACrByO,IACA,IAAIE,EAAoBpB,EAAGO,iBAAiBN,EAAM5D,EAAMqE,EAAY1G,GAChEoH,EAAoB,IAEpB3O,EAAIiO,EAAWlR,OACf0R,GAAiBE,EAExB,CAEL,OAAOF,CACV,EAGDZ,cAAe,SAAUE,EAAWxG,GAChC,IAAI0C,EAAK1C,GAAc,GACnB2C,EAAQD,EAAGhL,IAAM,KACjBkL,EAAWF,EAAGzC,OAAS,QACvBgH,EAAcvE,EAAGvC,UAAY,WAC7B4G,EAAYrE,EAAGtC,QAAU,SACzB0C,EAAeJ,EAAGrC,WAAa,YAC/B0C,EAAcL,EAAGpC,UAAY,WAE7BY,EAAO,CAAA,EACX,IAAK,IAAI+B,KAAKuD,EAENvD,GAAKN,GACLM,GAAKL,GACLK,GAAKgE,GACLhE,GAAK8D,GACL9D,GAAKH,GACLG,GAAKF,IAIT7B,EAAK+B,GAAKuD,EAAUvD,IAExB,OAAO/B,CACV,EAGDyF,OAAQ,SAAUV,EAAMS,EAAY1G,GACvB0F,EAAOgB,WACbW,YAAYpB,EAAK1C,KAAMmD,EAAY1G,EACzC,EAGDqH,YAAa,SAAUhF,EAAMqE,EAAY1G,GACrC,IAAIgG,EAAKN,EAAOgB,WAChB,GAAMrE,aAAgB7B,EAAtB,CAGA,IAAIkC,EAAK1C,GAAc,GACnB2C,EAAQD,EAAGhL,IAAM,KACjBkL,EAAWF,EAAGzC,OAAS,QACvBgH,EAAcvE,EAAGvC,UAAY,WAC7B4G,EAAYrE,EAAGtC,QAAU,SACzB0C,EAAeJ,EAAGrC,WAAa,YAC/B0C,EAAcL,EAAGpC,UAAY,WAE7BlE,EAAI,CAAA,EAcR,GAbAA,EAAEuG,GAASN,EAAK3K,GAChB0E,EAAEwG,GAAYP,EAAKpC,MACnB7D,EAAE2G,GAAeV,EAAK/B,SAEhB+B,EAAKlB,SACP/E,EAAE6K,GAAe5E,EAAKlB,OAAOzJ,IAE7B2K,EAAKjC,SACLhE,EAAE2K,IAAa,GAEb1E,EAAKlB,QAAUkB,EAAKlB,OAAOf,SAC7BhE,EAAE0G,GAAgBT,EAAKhC,WAAa5K,EAAUC,KAAO,OAAS,SAEjD,MAAb2M,EAAKnB,KAAc,CACnB,IAAIuF,EAAYpE,EAAKnB,KACrB,IAAK,IAAI+B,KAAKwD,EACVrK,EAAE6G,GAAKwD,EAAUxD,EAExB,CACDyD,EAAW1C,KAAK5H,GAEhB,IADA,IAAIkJ,EAAKjD,EAAKnC,SAAS1K,OACdiD,EAAI,EAAGA,EAAI6M,EAAI7M,IACpBuN,EAAGqB,YAAYhF,EAAKnC,SAASzH,GAAIiO,EAAY1G,EAhChD,CAkCJ,GAGLsH,SAAU,CACN1B,QAAS,CACLC,KAAMJ,EACNC,OAAQ,WACRxE,KAAM,+EAGV4E,SAAU,SAAUC,EAAQ/F,GACxB,IAAIgG,EAAKN,EAAO4B,SACZrB,EAAO,IAAI7C,EACf6C,EAAKrM,KAAOmM,EAAOF,KAAKjM,KACxBqM,EAAK5C,OAAS0C,EAAOF,KAAKxC,OAC1B4C,EAAK3C,QAAUyC,EAAOF,KAAKvC,QAC3B,IAAIiE,EAAMxB,EAAO7E,KACbsG,EAAUxB,EAAGyB,WAAWF,GACxBG,EAAW1B,EAAG2B,WAAWH,GAG7B,OADAxB,EAAG4B,WAAW3B,EAAM,KAAMyB,GACnBzB,CACV,EAGDE,SAAU,SAAUF,EAAMjG,GACtB,IAAIgG,EAAKN,EAAO4B,SACZ5L,EAAO,CAAA,EACXA,EAAKmK,KAAO,CACRjM,KAAMqM,EAAKrM,KACXyJ,OAAQ4C,EAAK5C,OACbC,QAAS2C,EAAK3C,SAElB5H,EAAKgK,OAAS,WACd,IAAImC,EAAY,GAMhB,OALAA,EAAU7D,KAAK,yBAEfgC,EAAG8B,WAAW7B,EAAK1C,KAAMsE,GACzBA,EAAU7D,KAAK,UACftI,EAAKwF,KAAO2G,EAAUE,KAAK,IACpBrM,CACV,EAGD+L,WAAY,SAAUF,GAClB,IAAIC,EAAU,KACVtO,OAAO8O,UAEPR,GADa,IAAIQ,WACAC,gBAAgBV,EAAK,cAGtCC,EAAU,IAAIU,cAAc,qBACpBC,OAAQ,EAChBX,EAAQY,QAAQb,IAEpB,OAAOC,CACV,EAGDG,WAAY,SAAUH,GAKlB,IAJA,IAAI/D,EAAQ+D,EAAQa,WAChBhG,EAAO,KAEPrK,EAAI,KACCS,EAAI,EAAGA,EAAIgL,EAAMjO,OAAQiD,IAE9B,GAAkB,IADlBT,EAAIyL,EAAMhL,IACJE,UAA8B,OAAbX,EAAEsQ,QAAkB,CACvCjG,EAAOrK,EACP,KACH,CAEL,GAAMqK,EAAM,CACR,IAAIkG,EAAKlG,EAAKgG,WACdhG,EAAO,KACP,IAAS5J,EAAI,EAAGA,EAAI8P,EAAG/S,OAAQiD,IAE3B,GAAkB,IADlBT,EAAIuQ,EAAG9P,IACDE,UAA8B,QAAbX,EAAEsQ,QAAmB,CACxCjG,EAAOrK,EACP,KACH,CAER,CACD,OAAOqK,CACV,EAGDuF,WAAY,SAAU3B,EAAM7D,EAAaoG,GACrC,IAAIxC,EAAKN,EAAO4B,SACZ3D,EAAU6E,EAASC,aAAa,MAChCC,EAAaF,EAASC,aAAa,QACnCE,EAAcH,EAASC,aAAa,UAExC,GAAkB,MAAdC,EAGA,IAFA,IAAIE,EAAiBJ,EAASH,WAC1BQ,EAAc,KACTpQ,EAAI,EAAGA,EAAImQ,EAAepT,OAAQiD,IAEvC,GAA4B,IAD5BoQ,EAAcD,EAAenQ,IACbE,UAAyC,gBAAxBkQ,EAAYP,QAA2B,CACpEI,EAAaG,EAAYC,YACzB,KACH,CAGT,IAAIrC,EAAYT,EAAG+C,iBAAiBP,GAChCQ,EACA,aAAcvC,EAAkC,QAAtBA,EAAUnG,SAAoC,QAAfqI,SACtDlC,EAAUnG,SAEjB,IAAI2I,EAAwBT,EAASC,aAAa,SAC5CQ,IACFxC,EAAU,oBAAsBwC,GAGpC,IAAIC,EAAwBV,EAASC,aAAa,oBAC5CS,IACFzC,EAAU,oBAAsByC,GAGpC,IAAIC,EAAgBX,EAASC,aAAa,YACtCtB,EAAiB,KACfgC,IACFhC,EAAkC,QAAjBgC,EAA0B1T,EAAUC,KAAOD,EAAUG,OAE1E,IAAIyM,EAAO,KAEPA,EADED,EACK6D,EAAKnC,SACR1B,EACAuB,EACA+E,EACAjC,EACAU,EACA6B,GAGG/C,EAAKrC,SAASD,EAAS+E,EAAYjC,GAE9C,IAAIvG,EAAWsI,EAASH,WACpBlF,EAAQ,KACZ,IAAS1K,EAAI,EAAGA,EAAIyH,EAAS1K,OAAQiD,IAEX,IADtB0K,EAAQjD,EAASzH,IACPE,UAAkC,QAAjBwK,EAAMmF,SAC7BtC,EAAG4B,WAAW3B,EAAM5D,EAAMc,EAGrC,EAGD4F,iBAAkB,SAAUP,GAIxB,IAHA,IAAItI,EAAWsI,EAASH,WACpBe,EAAO,KACPC,EAAY,CAAA,EACP5Q,EAAI,EAAGA,EAAIyH,EAAS1K,OAAQiD,IAEZ,IADrB2Q,EAAOlJ,EAASzH,IACPE,UAAkC,cAAjByQ,EAAKd,UAC3Be,EAAUD,EAAKX,aAAa,SAAWW,EAAKX,aAAa,UAGjE,OAAOY,CACV,EAGDvB,WAAY,SAAUzF,EAAMwF,GACxB,IAAI7B,EAAKN,EAAO4B,SACZgC,EAAM,KACN7C,EAAYpE,EAAKnB,KAsBrB,GApBMmB,EAAKlB,QAAUkB,EAAKlB,OAAOf,SAC7BkJ,EAAMjH,EAAKhC,YAAc5K,EAAUC,KAAO,OAAS,SAEvDmS,EAAU7D,KAAK,SACf6D,EAAU7D,KAAK,QAAU3B,EAAK3K,GAAK,KAC7B4R,GACFzB,EAAU7D,KAAK,cAAgBsF,EAAM,KAEpCjH,EAAK/B,UACNuH,EAAU7D,KAAK,kBAEbyC,EAAU,qBACZoB,EAAU7D,KAAK,WAAayC,EAAU,oBAAsB,KAE1DA,EAAU,qBACZoB,EAAU7D,KAAK,sBAAwByC,EAAU,oBAAsB,KAE3EoB,EAAU7D,KAAK,UAAYgC,EAAGuD,QAAQlH,EAAKpC,OAAS,MAGnC,MAAbwG,EACA,IAAK,IAAIxD,KAAKwD,EACA,qBAANxD,GAAkC,qBAANA,GAGhC4E,EAAU7D,KAAK,oBAAsBf,EAAI,YAAcwD,EAAUxD,GAAK,OAM9E,IADA,IAAI/C,EAAWmC,EAAKnC,SACXzH,EAAI,EAAGA,EAAIyH,EAAS1K,OAAQiD,IACjCuN,EAAG8B,WAAW5H,EAASzH,GAAIoP,GAG/BA,EAAU7D,KAAK,UAClB,EAGDuF,QAAS,SAAUxM,GACf,OAAOA,EACFG,QAAQ,KAAM,SACdA,QAAQ,KAAM,QACdA,QAAQ,KAAM,QACdA,QAAQ,KAAM,UACdA,QAAQ,KAAM,SACtB,GAELH,KAAM,CACF6I,QAAS,CACLC,KAAMJ,EACNC,OAAQ,OACRxE,KAAM,iEAEVsI,YAAa,MAEb1D,SAAU,SAAUC,EAAQ/F,GACxB,IAAIgG,EAAKN,EAAO3I,KACZkJ,EAAO,IAAI7C,EACf6C,EAAKrM,KAAOmM,EAAOF,KAAKjM,KACxBqM,EAAK5C,OAAS0C,EAAOF,KAAKxC,OAC1B4C,EAAK3C,QAAUyC,EAAOF,KAAKvC,QAC3B,IAAImG,EAAQ1D,EAAO7E,KAAKwI,MAAM,SAG9B,OADA1D,EAAG2D,YAAY1D,EAAMwD,EAAO,EAAG,GACxBxD,CACV,EAGD0D,YAAa,SAAU1D,EAAMwD,GACzB,IAAIG,EAAY,GACZnR,EAAI,EACR,KAAOA,EAAIgR,EAAMjU,QAAQ,CACrB,IAAIqU,EAAOJ,EAAMhR,GACbxB,EAAQ4S,EAAKC,MAAM,OAAO,GAAGtU,OAC7ByK,EAAQ4J,EAAKE,OAAO9S,GAExB,GAAa,GAATA,GAAc2S,EAAUpU,OAAS,EAEjC,YADA0B,IAAIN,MAAM,oCAAsCqJ,GAGpD,GAAIhJ,EAAQ2S,EAAUpU,OAElB,YADA0B,IAAIN,MAAM,+BAAiCqJ,GAG/C,IAAI+J,EAAOJ,EAAUpU,OAASyB,EAC9B,KAAO+S,KACHJ,EAAUK,MAGd,GAAa,GAAThT,GAAkC,GAApB2S,EAAUpU,OAAa,CACrC,IAAI6M,EAAO4D,EAAKrC,SAASzK,EAAKqD,KAAKC,QAASwD,GAC5C2J,EAAU5F,KAAK3B,EACnC,KAAuB,CACH,IAAIA,EAAO4D,EAAKnC,SACZ8F,EAAU3S,EAAQ,GAClBkC,EAAKqD,KAAKC,QACVwD,EACA,CAAE,EACF,MAEJ2J,EAAU5F,KAAK3B,EAClB,CACD5J,GACH,CACDmR,EAAUpU,OAAS,CACtB,EAGD2Q,SAAU,SAAUF,GAChB,IAAID,EAAKN,EAAO3I,KACZrB,EAAO,CAAA,EACXA,EAAKmK,KAAO,CACRjM,KAAMqM,EAAKrM,KACXyJ,OAAQ4C,EAAK5C,OACbC,QAAS2C,EAAK3C,SAElB5H,EAAKgK,OAAS,OACd,IAAI+D,EAAQ,GAGZ,OAFAzD,EAAGkE,aAAaT,EAAO,CAACxD,EAAK1C,MAAO,GACpC7H,EAAKwF,KAAOuI,EAAM1B,KAAK,MAChBrM,CACV,EAGDwO,aAAc,SAAUT,EAAOhG,EAAOxM,GAClC,IAAIkT,EAAS,IAAIC,MAAMnT,EAAQ,GAAG8Q,KAAK,KACvC,IAAK,IAAI1F,KAAQoB,EACbgG,EAAMzF,KAAKmG,EAAS9H,EAAKpC,OACnBoC,EAAKnC,UACPwF,EAAO3I,KAAKmN,aAAaT,EAAOpH,EAAKnC,SAAUjJ,EAAQ,EAGlE,ICnsBF,MAAMoT,EAKT,WAAAhT,CAAYiT,GACRhV,KAAKgV,GAAKA,CACb,CAGD,IAAAC,GACIxT,EAAON,MAAM,YAChB,CAED,KAAAH,GACIS,EAAON,MAAM,aAChB,CAMD,IAAA+T,CAAKC,GACD,IAAIzE,EAAK,KACLC,EAAO,KAGHD,EAFiB,iBAAdyE,EACDA,EAAU/E,OACP+E,EAAU/E,OAEV,YAGJ,WAGT,IAAI1F,EAAa1K,KAAKgV,GAAGI,QAAQ1K,WAYjC,MAXU,cAANgG,EACAC,EAAOP,EAAOgB,WAAWZ,SAAS2E,EAAWzK,GAChC,aAANgG,EACPC,EAAOP,EAAOC,UAAUG,SAAS2E,EAAWzK,GAC/B,YAANgG,EACPC,EAAOP,EAAO4B,SAASxB,SAAS2E,EAAWzK,GAC9B,QAANgG,EACPC,EAAOP,EAAO3I,KAAK+I,SAAS2E,EAAWzK,GAEvCjJ,EAAOJ,KAAK,sBAETsP,CACV,CAMD,QAAAE,CAASwE,GACL,IAAIzJ,EAAO,KACPlB,EAAa1K,KAAKgV,GAAGI,QAAQ1K,WAYjC,MAXmB,cAAf2K,EACAzJ,EAAOwE,EAAOgB,WAAWP,SAAS7Q,KAAKgV,GAAGrE,KAAMjG,GAC1B,aAAf2K,EACPzJ,EAAOwE,EAAOC,UAAUQ,SAAS7Q,KAAKgV,GAAGrE,KAAMjG,GACzB,YAAf2K,EACPzJ,EAAOwE,EAAO4B,SAASnB,SAAS7Q,KAAKgV,GAAGrE,MAClB,QAAf0E,EACPzJ,EAAOwE,EAAO3I,KAAKoJ,SAAS7Q,KAAKgV,GAAGrE,MAEpClP,EAAOH,MAAM,eAAiB+T,EAAc,WAEzCzJ,CACV,ECvEE,MAAM0J,EAMT,WAAAvT,CAAYiT,EAAII,GACZpV,KAAKuV,KAAOH,EACZpV,KAAKgV,GAAKA,EACVhV,KAAKwV,OAA2B,QAAlBxV,KAAKuV,KAAKtN,KACxBjI,KAAKyV,OAAS,KAEdzV,KAAK0V,aAAc,CACtB,CAED,IAAAT,GACIxT,EAAON,MAAM,cAChB,CAED,KAAAH,GACIS,EAAON,MAAM,gBACbnB,KAAKyV,OAAS,CAAE/S,EAAG,EAAGiF,EAAG,EAAG3F,EAAG,EAAGyB,EAAG,EACxC,CAMD,8BAAAkS,CAA+B5I,GAC3B,GAAI/M,KAAKwV,OACL,OAAOrV,EAAUG,MAKrB,IAHA,IAAIsK,EAAWmC,EAAKnC,UAAY,GAC5BgL,EAAehL,EAAS1K,OACxB2V,EAAI,EACC1S,EAAI,EAAGA,EAAIyS,EAAczS,IAC1ByH,EAASzH,GAAG4H,YAAc5K,EAAUC,KACpCyV,IAEAA,IAGR,OAAOD,EAAe,GAAKC,EAAI,EAAI1V,EAAUC,KAAOD,EAAUG,KACjE,CAED,MAAA+I,GACI5H,EAAON,MAAM,iBACbnB,KAAK8V,mBACL9V,KAAK+V,eACR,CAED,gBAAAD,GACI9V,KAAKgW,wBACR,CAKD,sBAAAA,GACI,IAAIjJ,EAAO/M,KAAKgV,GAAGrE,KAAK1C,KACpBgI,EAAc,KACd,WAAYlJ,EAAKjB,MACjBmK,EAAclJ,EAAKjB,MAAMzC,QAEzB4M,EAAc,CAAA,EACdlJ,EAAKjB,MAAMzC,OAAS4M,GAExB,IAAIrL,EAAWmC,EAAKnC,SAChBsL,EAAiBtL,EAAS1K,OAG9B,GAFA+V,EAAYlL,UAAY5K,EAAUE,OAClC4V,EAAYE,WAAa,EACrBnW,KAAKwV,OAEL,IADA,IAAIrS,EAAI+S,EACD/S,KACHnD,KAAKoW,uBAAuBxL,EAASzH,GAAIhD,EAAUG,MAAO6C,OAG9D,CAAIA,EAAI+S,EAER,IAFA,IACIG,EAAU,KACPlT,MACHkT,EAAUzL,EAASzH,IACP4H,WAAa5K,EAAUC,KAC/BJ,KAAKoW,uBAAuBC,EAASlW,EAAUC,KAAM+C,GAErDnD,KAAKoW,uBAAuBC,EAASlW,EAAUG,MAAO6C,EAPxC,CAW7B,CAQD,sBAAAiT,CAAuBrJ,EAAMhC,EAAWoL,GACpC,IAAIF,EAAc,KACd,WAAYlJ,EAAKjB,MACjBmK,EAAclJ,EAAKjB,MAAMzC,QAEzB4M,EAAc,CAAA,EACdlJ,EAAKjB,MAAMzC,OAAS4M,GAExB,IAAIrL,EAAWmC,EAAKnC,SAChBsL,EAAiBtL,EAAS1K,OAE9B+V,EAAYlL,UAAYA,EACxBkL,EAAYE,WAAaA,EAEzB,IADA,IAAIhT,EAAI+S,EACD/S,KACHnD,KAAKoW,uBAAuBxL,EAASzH,GAAI4H,EAAW5H,EAE3D,CAED,aAAA4S,GACI,IAAIhJ,EAAO/M,KAAKgV,GAAGrE,KAAK1C,KACpBgI,EAAclJ,EAAKjB,MAAMzC,OAC7B4M,EAAYK,SAAW,EACvBL,EAAYM,SAAW,EACvBN,EAAYO,aAAe,EAM3B,IALA,IAAI5L,EAAWmC,EAAKnC,SAChBzH,EAAIyH,EAAS1K,OACbuW,EAAa,GACbC,EAAc,GACdL,EAAU,KACPlT,MACHkT,EAAUzL,EAASzH,IACP2I,MAAMzC,OAAO0B,WAAa5K,EAAUG,MAC5CoW,EAAYC,QAAQN,GAEpBI,EAAWE,QAAQN,GAG3BJ,EAAYQ,WAAaA,EACzBR,EAAYS,YAAcA,EAC1BT,EAAYW,kBAAoB5W,KAAK6W,wBAAwBJ,GAC7DR,EAAYa,mBAAqB9W,KAAK6W,wBAAwBH,GAC9D1W,KAAKyV,OAAOhS,EAAIsJ,EAAKjB,MAAM3D,KAAKmE,MAAQ,EACxCtM,KAAKyV,OAAOzT,EAAI,EAAIhC,KAAKyV,OAAOhS,EAChCzD,KAAKyV,OAAO/S,EAAI,EAChB1C,KAAKyV,OAAO9N,EAAIL,KAAK0B,IAAIiN,EAAYW,kBAAmBX,EAAYa,mBACvE,CAOD,uBAAAD,CAAwB1I,GASpB,IARA,IAAI4I,EAAe,EACfC,EAAc7I,EAAMjO,OACpBiD,EAAI6T,EACJjK,EAAO,KACPkK,EAAoB,EACpBhB,EAAc,KACdiB,EAAS,EACTC,EAAK,KACFhU,KAEH8S,GADAlJ,EAAOoB,EAAMhL,IACM2I,MAAMzC,OACf,MAAN8N,IACAA,EAAKpK,EAAKlB,OAAOC,OAGrBmL,EAAoBjX,KAAK6W,wBAAwB9J,EAAKnC,UACjDmC,EAAK/B,WACNiM,EAAoB,EACpBjX,KAAKoX,YAAYrK,EAAKnC,UAAU,IAEpCqM,EAAoB3P,KAAK0B,IAAI+D,EAAKjB,MAAM3D,KAAKoE,OAAQ0K,GAEjDjX,KAAKqX,6BAA6BtK,KAClCkK,GAAqBjX,KAAKuV,KAAK9L,cAGnCwM,EAAYO,aAAeS,EAC3BhB,EAAYM,SAAWW,EAASD,EAAoB,EACpDhB,EAAYK,SACRtW,KAAKuV,KAAKjM,OAAS2M,EAAYlL,UAC9BoM,EAAGhP,KAAKmE,OAAS6K,EAAG9N,OAAO0B,UAAYkL,EAAYlL,WAAc,EACjEgC,EAAKlB,OAAOf,SACbmL,EAAYK,UAAYtW,KAAKuV,KAAK/L,OAASyM,EAAYlL,WAG3DmM,EAASA,EAASD,EAAoBjX,KAAKuV,KAAKhM,OAChDwN,GAAgBE,EAEhBD,EAAc,IACdD,GAAgB/W,KAAKuV,KAAKhM,QAAUyN,EAAc,IAEtD7T,EAAI6T,EAEJ,IADA,IAAIM,EAAgBP,EAAe,EAC5B5T,MACH4J,EAAOoB,EAAMhL,IACR2I,MAAMzC,OAAOkN,UAAYe,EAElC,OAAOP,CACV,CAOD,8BAAAQ,CAA+BpJ,GAS3B,IARA,IAAI4I,EAAe,EACfC,EAAc7I,EAAMjO,OACpBiD,EAAI6T,EACJjK,EAAO,KACPkK,EAAoB,EACpBhB,EAAc,KACdiB,EAAS,EACTC,EAAK,KACFhU,KAEH8S,GADAlJ,EAAOoB,EAAMhL,IACM2I,MAAMzC,OACf,MAAN8N,IACAA,EAAKpK,EAAKlB,OAAOC,OAGrBmL,EAAoBjX,KAAKuX,+BAA+BxK,EAAKnC,UACxDmC,EAAK/B,WACNiM,EAAoB,GAExBA,EAAoB3P,KAAK0B,IAAI+D,EAAKjB,MAAM3D,KAAKoE,OAAQ0K,GACjDjX,KAAKqX,6BAA6BtK,KAClCkK,GAAqBjX,KAAKuV,KAAK9L,cAGnCwM,EAAYO,aAAeS,EAC3BhB,EAAYM,SAAWW,EAASD,EAAoB,EACpDC,EAASA,EAASD,EAAoBjX,KAAKuV,KAAKhM,OAChDwN,GAAgBE,EAEhBD,EAAc,IACdD,GAAgB/W,KAAKuV,KAAKhM,QAAUyN,EAAc,IAEtD7T,EAAI6T,EAEJ,IADA,IAAIM,EAAgBP,EAAe,EAC5B5T,MACH4J,EAAOoB,EAAMhL,IACR2I,MAAMzC,OAAOkN,UAAYe,EAElC,OAAOP,CACV,CAOD,4BAAAM,CAA6BtK,GACzB,OAAOA,EAAKnC,SAAS1K,OAAS,GAAK6M,EAAKlB,OAAOjB,SAAS1K,OAAS,CACpE,CAMD,eAAAsX,CAAgBzK,GACZ,IAAIkJ,EAAclJ,EAAKjB,MAAMzC,OACzBoO,EAAe,KAOnB,GANI,aAAcxB,GAAejW,KAAK0V,YAClC+B,EAAexB,EAAYyB,UAE3BD,EAAe,CAAExL,GAAI,EAAGE,GAAI,GAC5B8J,EAAYyB,SAAWD,IAEJ,GAAnBA,EAAaxL,IAA8B,GAAnBwL,EAAatL,EAAS,CAC9C,IAAIF,EAAIgK,EAAYK,SAChBnK,EAAI8J,EAAYM,SACpB,IAAKxJ,EAAKjC,OAAQ,CACd,IAAI6M,EAAW3X,KAAKwX,gBAAgBzK,EAAKlB,QACzCI,GAAK0L,EAAS1L,EACdE,GAAKwL,EAASxL,CACjB,CACDsL,EAAaxL,EAAIA,EACjBwL,EAAatL,EAAIA,CACpB,CACD,OAAOsL,CACV,CAMD,cAAAG,CAAe7K,GACX,IAAI8K,EAAY9K,EAAKjB,MAAM3D,KACvBwP,EAAW3X,KAAKwX,gBAAgBzK,GAChChN,EAAI,CAAA,EAGR,OAFAA,EAAEkM,EAAI0L,EAAS1L,EAAK4L,EAAUvL,OAASS,EAAKjB,MAAMzC,OAAO0B,UAAY,GAAM,EAC3EhL,EAAEoM,EAAIwL,EAASxL,EAAI0L,EAAUtL,OAAS,EAC/BxM,CACV,CAMD,iBAAA+X,CAAkB/K,GAEd,OADQ/M,KAAKwX,gBAAgBzK,EAEhC,CAMD,kBAAAgL,CAAmBhL,GACf,IAAIkJ,EAAclJ,EAAKjB,MAAMzC,OACzB2O,EAAa,KAOjB,GANI,WAAY/B,GAAejW,KAAK0V,YAChCsC,EAAa/B,EAAYgC,QAEzBD,EAAa,CAAE/L,GAAI,EAAGE,GAAI,GAC1B8J,EAAYgC,OAASD,IAEJ,GAAjBA,EAAW/L,IAA4B,GAAjB+L,EAAW7L,EACjC,GAAIY,EAAKjC,OACLkN,EAAW/L,EAAI,EACf+L,EAAW7L,EAAI,MACZ,CACH,IAAI0L,EAAY9K,EAAKjB,MAAM3D,KACvBwP,EAAW3X,KAAKwX,gBAAgBzK,GACpCiL,EAAW/L,EACP0L,EAAS1L,GAAK4L,EAAUvL,MAAQtM,KAAKuV,KAAK/L,QAAUuD,EAAKjB,MAAMzC,OAAO0B,UAC1EiN,EAAW7L,EAAIwL,EAASxL,CAC3B,CAEL,OAAO6L,CACV,CAMD,kBAAAE,CAAmBnL,GACf,IAAIhN,EAAIC,KAAK+X,mBAAmBhL,GAC5BoL,EAAO,CAAA,EAOX,OANIpL,EAAKjB,MAAMzC,OAAO0B,WAAa5K,EAAUG,MACzC6X,EAAKlM,EAAIlM,EAAEkM,EAAIjM,KAAKuV,KAAK/L,OAEzB2O,EAAKlM,EAAIlM,EAAEkM,EAEfkM,EAAKhM,EAAIpM,EAAEoM,EAAI7E,KAAK8Q,KAAKpY,KAAKuV,KAAK/L,OAAS,GACrC2O,CACV,CAKD,YAAAE,GACI,IAAIlK,EAAQnO,KAAKgV,GAAGrE,KAAKxC,MACrBpB,EAAO,KACPuL,EAAO,KACX,IAAK,IAAIjK,KAAWF,EAChBpB,EAAOoB,EAAME,IACbiK,EAAOtY,KAAK+X,mBAAmBhL,IACtBd,EAAIjM,KAAKyV,OAAOhS,IACrBzD,KAAKyV,OAAOhS,EAAI6U,EAAKrM,GAErBqM,EAAKrM,EAAIjM,KAAKyV,OAAOzT,IACrBhC,KAAKyV,OAAOzT,EAAIsW,EAAKrM,GAG7B,MAAO,CACHjK,EAAGhC,KAAKyV,OAAOhS,EAAIzD,KAAKyV,OAAOzT,EAC/BgB,EAAGhD,KAAKyV,OAAO9N,EAAI3H,KAAKyV,OAAO/S,EAEtC,CAKD,WAAA6V,CAAYxL,GACJA,EAAKjC,SAGLiC,EAAK/B,SACLhL,KAAKwY,cAAczL,GAEnB/M,KAAKyY,YAAY1L,GAExB,CAKD,WAAA0L,CAAY1L,GACRA,EAAK/B,UAAW,EAChBhL,KAAK0Y,YAAY3L,GACjB/M,KAAKoX,YAAYrK,EAAKnC,UAAU,GAChC5K,KAAKgV,GAAG2D,oBAAoBhY,EAAUC,KAAM,CACxCkF,IAAK,cACL8F,KAAM,GACNmB,KAAMA,EAAK3K,IAElB,CAKD,aAAAoW,CAAczL,GACVA,EAAK/B,UAAW,EAChBhL,KAAK0Y,YAAY3L,GACjB/M,KAAKoX,YAAYrK,EAAKnC,UAAU,GAChC5K,KAAKgV,GAAG2D,oBAAoBhY,EAAUC,KAAM,CACxCkF,IAAK,gBACL8F,KAAM,GACNmB,KAAMA,EAAK3K,IAElB,CAED,UAAAwW,GACI,IAEI7L,EAFAoB,EAAQnO,KAAKgV,GAAGrE,KAAKxC,MACrB7L,EAAI,EAER,IAAK,IAAI+L,KAAWF,GAChBpB,EAAOoB,EAAME,IACHrD,WACN+B,EAAK/B,UAAW,EAChB1I,KAGR,GAAIA,EAAI,EAAG,CACP,IAAI2L,EAAOjO,KAAKgV,GAAGrE,KAAK1C,KACxBjO,KAAK0Y,YAAYzK,GACjBjO,KAAKoX,YAAYnJ,EAAKrD,UAAU,EACnC,CACJ,CAED,YAAAiO,GACI,IAEI9L,EAFAoB,EAAQnO,KAAKgV,GAAGrE,KAAKxC,MACrB7L,EAAI,EAER,IAAK,IAAI+L,KAAWF,GAChBpB,EAAOoB,EAAME,IACJrD,WAAa+B,EAAKjC,SACvBiC,EAAK/B,UAAW,EAChB1I,KAGR,GAAIA,EAAI,EAAG,CACP,IAAI2L,EAAOjO,KAAKgV,GAAGrE,KAAK1C,KACxBjO,KAAK0Y,YAAYzK,GACjBjO,KAAKoX,YAAYnJ,EAAKrD,UAAU,EACnC,CACJ,CAOD,eAAAkO,CAAgBC,EAAcC,EAAYC,GACtC,KAAIF,EAAe,GAOnB,IAJA,IAAI5K,EAAQ6K,GAAchZ,KAAKgV,GAAGrE,KAAK1C,KAAKrD,SACxCsO,EAAQD,GAAc,EACtB9V,EAAIgL,EAAMjO,OACV6M,EAAO,KACJ5J,KACH4J,EAAOoB,EAAMhL,GACT+V,EAAQH,IACHhM,EAAK/B,UACNhL,KAAKyY,YAAY1L,GAErB/M,KAAK8Y,gBAAgBC,EAAchM,EAAKnC,SAAUsO,EAAQ,IAE1DA,GAASH,GACLhM,EAAK/B,UACLhL,KAAKwY,cAAczL,EAIlC,CAKD,WAAA2L,CAAY3L,GACR,IAAIkB,EAAOjO,KAAKgV,GAAGrE,KAAK1C,KACxB,GAAMA,EAAM,CACR,IAAIkL,EAAmBlL,EAAKnC,MAAMzC,OAC9B0D,EAAKjC,QACLqO,EAAiBrC,mBAAqB9W,KAAKuX,+BACvC4B,EAAiBzC,aAErByC,EAAiBvC,kBAAoB5W,KAAKuX,+BACtC4B,EAAiB1C,aAGjB1J,EAAKjB,MAAMzC,OAAO0B,WAAa5K,EAAUG,MACzC6Y,EAAiBrC,mBAAqB9W,KAAKuX,+BACvC4B,EAAiBzC,aAGrByC,EAAiBvC,kBAAoB5W,KAAKuX,+BACtC4B,EAAiB1C,YAI7BzW,KAAKyV,OAAO9N,EAAIL,KAAK0B,IACjBmQ,EAAiBvC,kBACjBuC,EAAiBrC,oBAErB9W,KAAK0V,aAAc,CAC/B,MACYjU,EAAOJ,KAAK,0BAEnB,CAMD,WAAA+V,CAAYjJ,EAAOiL,GAIf,IAHA,IAAIjW,EAAIgL,EAAMjO,OACV6M,EAAO,KAEJ5J,MACH4J,EAAOoB,EAAMhL,IACM2I,MAAMzC,OACrB0D,EAAK/B,SACLhL,KAAKoX,YAAYrK,EAAKnC,SAAUwO,GAEhCpZ,KAAKoX,YAAYrK,EAAKnC,UAAU,GAE/BmC,EAAKjC,SACNiC,EAAKjB,MAAMzC,OAAO+P,QAAUA,EAGvC,CAMD,SAAAC,CAAUtM,GACN,OAAOA,EAAK/B,QACf,CAMD,UAAAsO,CAAWvM,GACP,IAAIkJ,EAAclJ,EAAKjB,MAAMzC,OAC7B,QAAI,YAAa4M,IAAgBA,EAAYmD,QAKhD,ECtiBL,MAAMG,EAKF,WAAAxX,CAAYoG,GACRnI,KAAKmI,KAAOA,EACZnI,KAAKuV,KAAOpN,EAAKoN,KACjBvV,KAAKwZ,MAAQD,EAASjX,EAAE,OACxBtC,KAAKwZ,MAAMC,aAAa,QAAS,UACjCzZ,KAAK0Z,KAAO,CAAE1X,EAAG,EAAGgB,EAAG,GAEvBhD,KAAKmU,MAAQ,GACbnU,KAAK2Z,aAAe,CAChBC,SAAU5Z,KAAK6Z,SACfC,OAAQ9Z,KAAK+Z,YAEjB/Z,KAAKga,kBACR,CAED,QAAO1X,CAAEC,GACL,OAAOT,EAAEG,EAAEgY,gBAAgB,6BAA8B1X,EAC5D,CAED,gBAAAyX,GACgD,mBAAjCha,KAAKuV,KAAK2E,mBAEjBla,KAAKma,QAAU,CAACC,EAAMC,EAAIC,EAAIC,EAAIC,KAC9B,IACIxa,KAAKuV,KAAK2E,mBAAmBjT,KAAKjH,KAAM,CACpCya,IAAKL,EACLM,YAAa,CAAEzO,EAAGoO,EAAIlO,EAAGmO,GACzBK,UAAW,CAAE1O,EAAGsO,EAAIpO,EAAGqO,IAE9B,CAAC,MAAO/W,GACLhC,EAAOH,MAAM,+BAAgCmC,EAChD,GAILzD,KAAKma,QAAUna,KAAK2Z,aAAa3Z,KAAKuV,KAAK7M,aAAe1I,KAAK2Z,aAAaG,MAEnF,CAED,OAAAc,GACI,OAAO5a,KAAKwZ,KACf,CAED,QAAAqB,CAAS7Y,EAAGgB,GACRhD,KAAK0Z,KAAK1X,EAAIA,EACdhC,KAAK0Z,KAAK1W,EAAIA,EACdhD,KAAKwZ,MAAMC,aAAa,QAASzX,GACjChC,KAAKwZ,MAAMC,aAAa,SAAUzW,EACrC,CACD,KAAA8X,GAEI,IADA,IAAIrL,EAAMzP,KAAKmU,MAAMjU,OACduP,KACHzP,KAAKwZ,MAAMtT,YAAYlG,KAAKmU,MAAM1E,IAEtCzP,KAAKmU,MAAMjU,OAAS,CACvB,CAED,SAAA6a,CAAUzC,EAAM0C,EAAKC,EAAQC,GACzB,IAAI3G,EAAOgF,EAASjX,EAAE,QACtBiS,EAAKkF,aAAa,SAAUyB,GAASlb,KAAKuV,KAAK9M,YAC/C8L,EAAKkF,aAAa,eAAgBzZ,KAAKuV,KAAK/M,YAC5C+L,EAAKkF,aAAa,OAAQ,eAC1BzZ,KAAKmU,MAAMzF,KAAK6F,GAChBvU,KAAKwZ,MAAM1W,YAAYyR,GACvBvU,KAAKma,QACD5F,EACAyG,EAAI/O,EAAIgP,EAAOhP,EACf+O,EAAI7O,EAAI8O,EAAO9O,EACfmM,EAAKrM,EAAIgP,EAAOhP,EAChBqM,EAAKnM,EAAI8O,EAAO9O,EAEvB,CAGD,OAAAgP,CAAQC,EAAiBC,GACrB,IAAIC,EAAM,IAAIC,MACdD,EAAIlX,OAAS,WACTgX,EAAgBI,UAAUF,EAAK,EAAG,GAChCD,GAAYA,GAC1B,EACQC,EAAIG,IACA,6BAA+BC,MAAK,IAAIC,eAAgBC,kBAAkB5b,KAAKwZ,OACtF,CAUD,UAAAO,CAAWK,EAAMC,EAAIC,EAAIC,EAAIC,GACzBJ,EAAKX,aACD,IACA,KACIY,EACA,IACAC,EACA,OACCD,EAAkB,GAAXE,EAAKF,GAAW,GACxB,IACAC,EACA,KACAD,EACA,IACAG,EACA,KACAD,EACA,IACAC,EAEX,CAUD,QAAAX,CAASO,EAAMC,EAAIC,EAAIC,EAAIC,GACvBJ,EAAKX,aAAa,IAAK,KAAOY,EAAK,IAAMC,EAAK,MAAQC,EAAK,IAAMC,EACpE,EAML,MAAMqB,EAKF,WAAA9Z,CAAYoG,GACRnI,KAAKuV,KAAOpN,EAAKoN,KACjBvV,KAAK8b,SAAWha,EAAEQ,EAAE,UACpBtC,KAAK8b,SAASC,UAAY,SAC1B/b,KAAKgc,WAAsDhc,KAAK8b,SAASG,WAAW,MACpFjc,KAAK0Z,KAAO,CAAE1X,EAAG,EAAGgB,EAAG,GACvBhD,KAAK2Z,aAAe,CAChBC,SAAU5Z,KAAK6Z,SACfC,OAAQ9Z,KAAK+Z,YAEjB/Z,KAAKkc,IAAM/T,EAAKgU,mBAChBnc,KAAKga,kBACR,CAED,gBAAAA,GACgD,mBAAjCha,KAAKuV,KAAK2E,mBAEjBla,KAAKma,QAAU,CAACM,EAAKJ,EAAIC,EAAIC,EAAIC,KAC7B,IACIxa,KAAKuV,KAAK2E,mBAAmBjT,KAAKjH,KAAM,CACpCya,MACAC,YAAa,CAAEzO,EAAGoO,EAAIlO,EAAGmO,GACzBK,UAAW,CAAE1O,EAAGsO,EAAIpO,EAAGqO,IAE9B,CAAC,MAAO/W,GACLhC,EAAOH,MAAM,6BAA8BmC,EAC9C,GAILzD,KAAKma,QAAUna,KAAK2Z,aAAa3Z,KAAKuV,KAAK7M,aAAe1I,KAAK2Z,aAAaG,MAEnF,CAED,OAAAc,GACI,OAAO5a,KAAK8b,QACf,CAED,QAAAjB,CAAS7Y,EAAGgB,GACRhD,KAAK0Z,KAAK1X,EAAIA,EACdhC,KAAK0Z,KAAK1W,EAAIA,EACVhD,KAAK8b,SAASxP,OAAStM,KAAK8b,SAASvP,QAAUvM,KAAKgc,WAAWI,OAC/Dpc,KAAK8b,SAASxP,MAAQtK,EAAIhC,KAAKkc,IAC/Blc,KAAK8b,SAASvP,OAASvJ,EAAIhD,KAAKkc,IAEhClc,KAAK8b,SAASxY,MAAMgJ,MAAQtK,EAAI,KAChChC,KAAK8b,SAASxY,MAAMiJ,OAASvJ,EAAI,KACjChD,KAAKgc,WAAWI,MAAMpc,KAAKkc,IAAKlc,KAAKkc,OAErClc,KAAK8b,SAASxP,MAAQtK,EACtBhC,KAAK8b,SAASvP,OAASvJ,EAE9B,CAGD,KAAA8X,GACI9a,KAAKgc,WAAWK,UAAU,EAAG,EAAGrc,KAAK0Z,KAAK1X,EAAGhC,KAAK0Z,KAAK1W,EAC1D,CAED,SAAA+X,CAAUzC,EAAM0C,EAAKC,EAAQC,GACzB,IAAIT,EAAMza,KAAKgc,WACfvB,EAAI6B,YAAcpB,GAASlb,KAAKuV,KAAK9M,WACrCgS,EAAI8B,UAAYvc,KAAKuV,KAAK/M,WAC1BiS,EAAI+B,QAAU,QACdxc,KAAKma,QAAQM,EAAKO,EAAI/O,EAAIgP,EAAOhP,EAAG+O,EAAI7O,EAAI8O,EAAO9O,EAAGmM,EAAKrM,EAAIgP,EAAOhP,EAAGqM,EAAKnM,EAAI8O,EAAO9O,EAC5F,CAED,OAAAgP,CAAQC,EAAiBC,GACrBD,EAAgBI,UAAUxb,KAAK8b,SAAU,EAAG,EAAG9b,KAAK0Z,KAAK1X,EAAGhC,KAAK0Z,KAAK1W,GACpEqY,GAAYA,GACjB,CAUD,UAAAtB,CAAWU,EAAKJ,EAAIC,EAAIC,EAAIC,GACxBC,EAAIgC,YACJhC,EAAIiC,OAAOrC,EAAIC,GACfG,EAAIkC,cAActC,EAAkB,GAAXE,EAAKF,GAAW,EAAGC,EAAID,EAAIG,EAAID,EAAIC,GAC5DC,EAAImC,QACP,CAUD,QAAA/C,CAASY,EAAKJ,EAAIC,EAAIC,EAAIC,GACtBC,EAAIgC,YACJhC,EAAIiC,OAAOrC,EAAIC,GACfG,EAAIoC,OAAOtC,EAAIC,GACfC,EAAImC,QACP,EClPE,MAAME,EAqBT,WAAA/a,CAAYiT,EAAII,GACZpV,KAAKuV,KAAOH,EACZpV,KAAKgV,GAAKA,EACVhV,KAAKqJ,OAAS2L,EAAG3L,OAEjBrJ,KAAK8H,UAAY,KACjB9H,KAAK+c,QAAU,KACf/c,KAAKgd,QAAU,KAEfhd,KAAK0Z,KAAO,CAAE1X,EAAG,EAAGgB,EAAG,GAEvBhD,KAAKid,cAAgB,KACrBjd,KAAKkd,aAAe,KAEpBld,KAAKmd,MAAQ,KACbnd,KAAKod,YAAgBhI,EAAQjM,mBACvBnJ,KAAKqd,oBACLrd,KAAKsd,qBACXtd,KAAKud,aAAe,EACpBvd,KAAKmc,mBAAqBnc,KAAKuV,KAAKlN,2BAC9BvG,EAAEE,EAAEwb,kBACJ,EACNxd,KAAKyd,cAAe,CACvB,CAED,IAAAxI,GAOI,GANAxT,EAAON,MAAMnB,KAAKuV,MAClB9T,EAAON,MAAM,aAEbnB,KAAK8H,UAAYhG,EAAEqB,EAAEnD,KAAKuV,KAAKzN,WACG9H,KAAKuV,KAAc,UACnBzT,EAAEK,EAAEnC,KAAKuV,KAAKzN,WAC3C9H,KAAK8H,UAAV,CDsMD,IAAoBK,EClMnBnI,KAAKmd,ODkMchV,EClMKnI,KDmMI,QCnMEA,KAAKuV,KAAKnN,ODmM9B1H,cAA0B,IAAI6Y,EAASpR,GAAQ,IAAI0T,EAAY1T,ICjMzEnI,KAAK+c,QAAUjb,EAAEQ,EAAE,OACnBtC,KAAKgd,QAAUlb,EAAEQ,EAAE,WACnBtC,KAAK0d,SAAW5b,EAAEQ,EAAE,SACpBtC,KAAK+c,QAAQhB,UAAY,gCAAkC/b,KAAKuV,KAAK1M,cACrE7I,KAAK+c,QAAQY,SAAW,EACxB3d,KAAK+c,QAAQja,YAAY9C,KAAKmd,MAAMvC,WACpC5a,KAAK+c,QAAQja,YAAY9C,KAAKgd,SAE9Bhd,KAAK0d,SAAS3B,UAAY,gBAC1B/b,KAAK0d,SAASjZ,KAAO,OAErB,IAAImZ,EAAI5d,KACR8B,EAAE0B,GAAGxD,KAAK0d,SAAU,UAAW,SAAUja,GACrC,IAAIqC,EAAMrC,GAAKoa,MACI,IAAf/X,EAAIgY,UACJF,EAAEG,gBACFjY,EAAIkY,kBAEpB,GACQlc,EAAE0B,GAAGxD,KAAK0d,SAAU,OAAQ,SAAUja,GAClCma,EAAEG,eACd,GAEQ/d,KAAK8H,UAAUhF,YAAY9C,KAAK+c,SAE3B/c,KAAK8H,UAAUmW,cAChB,IAAIC,qBAAqB,CAACC,EAAUC,KAC5BD,EAAS,GAAGE,iBACZD,EAASE,UAAUte,KAAK+c,SACxB/c,KAAKa,YAEV0d,QAAQve,KAAK+c,QAlCnB,MAFGtb,EAAOH,MAAM,qDAsCpB,CASD,SAAAkd,CAAU9Q,EAAK+Q,EAAYC,EAAcC,GACrC,IAAIC,EAAWD,EAAmB3e,KAAK+c,QAAU/c,KAAKgd,QACtDlb,EAAE0B,GAAGob,EAAQH,EAAY,SAAUhb,GAC/B,IAAIqC,EAAMrC,GAAKoa,MACfa,EAAazX,KAAKyG,EAAK5H,EACnC,EACK,CAKD,iBAAA+Y,CAAkBjE,GACd,GAAe,MAAXA,EACA,OAAO,KAEX,IAAI5H,EAAU4H,EAAQ5H,QAAQtS,cAC9B,MAAe,UAAXsS,GAAkC,cAAXA,EAChB4H,EAAQzH,aAAa,UACV,WAAXH,GAAmC,QAAXA,GAAgC,QAAXA,EAC7C,KAEAhT,KAAK6e,kBAAkBjE,EAAQkE,cAE7C,CAKD,OAAA7R,CAAQ2N,GACJ,GAAe,MAAXA,EACA,OAAO,EAEX,IAAI5H,EAAU4H,EAAQ5H,QAAQtS,cAC9B,MAAe,UAAXsS,GAEkB,WAAXA,GAAmC,QAAXA,GAAgC,QAAXA,GAG7ChT,KAAKiN,QAAQ2N,EAAQkE,cAEnC,CAKD,WAAAC,CAAYnE,GACR,MAAwC,cAAjCA,EAAQ5H,QAAQtS,aAC1B,CACD,KAAAM,GACIS,EAAON,MAAM,cACbnB,KAAKid,cAAgB,KACrBjd,KAAKgf,cACLhf,KAAKif,cACLjf,KAAKkf,aACR,CACD,WAAAA,GACI,IAAIC,EAAanf,KAAKgV,GAAGI,QAAQpN,MAE7BhI,KAAKgd,QAAQjB,UADXoD,EACuB,SAAWA,EAEX,EAEhC,CAED,kBAAAC,GACI,IAAIjR,EAAQnO,KAAKgV,GAAGrE,KAAKxC,MACzB,IAAK,IAAIkR,KAAUlR,EACfnO,KAAKsf,wBAAwBnR,EAAMkR,GAE1C,CAED,IAAAnK,GACIzT,EAAON,MAAM,aACbnB,KAAKuf,uBAAuBvf,KAAKuV,KAAK5M,WACtC3I,KAAKwf,aACLxf,KAAKyd,cAAe,CACvB,CAED,WAAAgC,GACI,IAAIC,EAAW1f,KAAKqJ,OAAOgP,eACvBsH,EAAYD,EAAS1d,EAAwB,EAApBhC,KAAKuV,KAAKjN,QACnCsX,EAAaF,EAAS1c,EAAwB,EAApBhD,KAAKuV,KAAKhN,QACpCsX,EAAW7f,KAAK+c,QAAQ+C,YACxBC,EAAW/f,KAAK+c,QAAQiD,aACxBH,EAAWF,IACXE,EAAWF,GAEXI,EAAWH,IACXG,EAAWH,GAEf5f,KAAK0Z,KAAK1X,EAAI6d,EACd7f,KAAK0Z,KAAK1W,EAAI+c,CACjB,CAKD,eAAAE,CAAgBlT,GACZ,IAAI8K,EAAY9K,EAAKjB,MAAM3D,KAC3B0P,EAAUvL,MAAQuL,EAAU+C,QAAQkF,YACpCjI,EAAUtL,OAASsL,EAAU+C,QAAQoF,YACxC,CAED,UAAAR,GACI,IAAIrR,EAAQnO,KAAKgV,GAAGrE,KAAKxC,MACrB+R,EAAWpe,EAAEG,EAAEke,yBACnB,IAAK,IAAId,KAAUlR,EACfnO,KAAKogB,oBAAoBjS,EAAMkR,GAASa,GAE5ClgB,KAAKgd,QAAQla,YAAYod,GAEzBlgB,KAAKqgB,2BAA2B,KAC5B,IAAK,IAAIhB,KAAUlR,EACfnO,KAAKigB,gBAAgB9R,EAAMkR,KAGtC,CAKD,QAAA7Q,CAASzB,GACL/M,KAAKogB,oBAAoBrT,EAAM/M,KAAKgd,SACpChd,KAAKqgB,2BAA2B,KAC5BrgB,KAAKigB,gBAAgBlT,IAE5B,CAKD,0BAAAsT,CAA2BC,GACjBtgB,KAAK8H,UAAUmW,aACjBqC,KAGJ7e,EAAOJ,KACH,oGAEJrB,KAAK+c,QAAQzZ,MAAMid,SAAW,WAC9BvgB,KAAK+c,QAAQzZ,MAAMkd,IAAM,UACzB1e,EAAEG,EAAE4D,KAAK/C,YAAY9C,KAAK+c,SAC1BuD,IACAtgB,KAAK8H,UAAUhF,YAAY9C,KAAK+c,SAChC/c,KAAK+c,QAAQzZ,MAAMid,SAAW,KAC9BvgB,KAAK+c,QAAQzZ,MAAMkd,IAAM,KAC5B,CAMD,mBAAAJ,CAAoBrT,EAAMD,GACtB,IAAI+K,EAAY,KACZ,SAAU9K,EAAKjB,MACf+L,EAAY9K,EAAKjB,MAAM3D,MAEvB0P,EAAY,CAAA,EACZ9K,EAAKjB,MAAM3D,KAAO0P,GAGtB,IAAI5V,EAAIH,EAAEQ,EAAE,UACZ,GAAIyK,EAAKjC,OACL7I,EAAE8Z,UAAY,WACX,CACH,IAAI0E,EAAM3e,EAAEQ,EAAE,cACdR,EAAEW,EAAEge,EAAK,KACTA,EAAIhH,aAAa,SAAU1M,EAAK3K,IAChCqe,EAAInd,MAAMoC,WAAa,SACvBoH,EAAYhK,YAAY2d,GACxB5I,EAAU6I,SAAWD,CACxB,CACK1T,EAAKpC,OACP3K,KAAKod,YAAYnb,EAAG8K,GAExB9K,EAAEwX,aAAa,SAAU1M,EAAK3K,IAC9BH,EAAEqB,MAAMoC,WAAa,SACrB1F,KAAK2gB,yBAAyB1e,EAAG8K,EAAKnB,MAEtCkB,EAAYhK,YAAYb,GACxB4V,EAAU+C,QAAU3Y,CACvB,CAKD,WAAA8N,CAAYhD,GACkB,MAAtB/M,KAAKid,eAAyBjd,KAAKid,cAAc7a,IAAM2K,EAAK3K,KAC5DpC,KAAKid,cAAgB,MAEA,MAArBjd,KAAKkd,cAAwBld,KAAKkd,aAAa9a,IAAM2K,EAAK3K,KAC1D2K,EAAKjB,MAAM3D,KAAKyS,QAAQ1U,YAAYlG,KAAK0d,UACzC1d,KAAKkd,aAAe,MAIxB,IAFA,IAAItS,EAAWmC,EAAKnC,SAChBzH,EAAIyH,EAAS1K,OACViD,KACHnD,KAAK+P,YAAYnF,EAASzH,IAE9B,GAAI4J,EAAKjB,MAAM3D,KAAM,CACjB,IAAIyS,EAAU7N,EAAKjB,MAAM3D,KAAKyS,QAC1B8F,EAAW3T,EAAKjB,MAAM3D,KAAKuY,SAC/B1gB,KAAKgd,QAAQ9W,YAAY0U,GACzB5a,KAAKgd,QAAQ9W,YAAYwa,GACzB3T,EAAKjB,MAAM3D,KAAKyS,QAAU,KAC1B7N,EAAKjB,MAAM3D,KAAKuY,SAAW,IAC9B,CACJ,CAKD,WAAAE,CAAY7T,GACR,IAAI8K,EAAY9K,EAAKjB,MAAM3D,KACvByS,EAAU/C,EAAU+C,QAIxB,GAHM7N,EAAKpC,OACP3K,KAAKod,YAAYxC,EAAS7N,GAE1B/M,KAAKqJ,OAAOiQ,WAAWvM,GACvB8K,EAAUvL,MAAQsO,EAAQkF,YAC1BjI,EAAUtL,OAASqO,EAAQoF,iBACxB,CACH,IAAIa,EAAejG,EAAQzH,aAAa,SACxCyH,EAAQtX,MAAQ,sCAChBuU,EAAUvL,MAAQsO,EAAQkF,YAC1BjI,EAAUtL,OAASqO,EAAQoF,aAC3BpF,EAAQtX,MAAQud,CACnB,CACJ,CAKD,WAAAC,CAAY/T,GACR,GAAM/M,KAAKid,cAAe,CACtB,IAAIrC,EAAU5a,KAAKid,cAAcnR,MAAM3D,KAAKyS,QAC5CA,EAAQmB,UAAYnB,EAAQmB,UAAUnU,QAAQ,iBAAkB,IAChE5H,KAAK+gB,mCAAmC/gB,KAAKid,cAChD,CACKlQ,IACF/M,KAAKid,cAAgBlQ,EACrBA,EAAKjB,MAAM3D,KAAKyS,QAAQmB,WAAa,YACrC/b,KAAKghB,iCAAiCjU,GAE7C,CAED,YAAAkU,GACIjhB,KAAK8gB,YAAY,KACpB,CAKD,gBAAAI,GACI,OAAOlhB,KAAKkd,YACf,CAKD,UAAAiE,GACI,QAASnhB,KAAKkd,YACjB,CAKD,eAAAkE,CAAgBrU,GACZ,GAAKA,EAAKpC,MAAV,CAIyB,MAArB3K,KAAKkd,cACLld,KAAK+d,gBAET/d,KAAKkd,aAAenQ,EACpB,IACI6N,EADY7N,EAAKjB,MAAM3D,KACHyS,QACpBjQ,EAAQoC,EAAKpC,MACb0W,EAAMC,iBAAiB1G,GAC3B5a,KAAK0d,SAAS6D,MAAQ5W,EACtB3K,KAAK0d,SAASpa,MAAMgJ,MAChBsO,EAAQkF,YACRrf,SAAS4gB,EAAIG,iBAAiB,iBAC9B/gB,SAAS4gB,EAAIG,iBAAiB,kBAC9B,KACJ5G,EAAQ1X,UAAY,GACpB0X,EAAQ9X,YAAY9C,KAAK0d,UACzB9C,EAAQtX,MAAMme,OAAS,EACvBzhB,KAAK0d,SAASgE,QACd1hB,KAAK0d,SAAS3c,QAnBb,MAFGU,EAAOJ,KAAK,yBAsBnB,CAED,aAAA0c,GACI,GAAyB,MAArB/d,KAAKkd,aAAsB,CAC3B,IAAInQ,EAAO/M,KAAKkd,aAChBld,KAAKkd,aAAe,KACpB,IACItC,EADY7N,EAAKjB,MAAM3D,KACHyS,QACpBjQ,EAAQ3K,KAAK0d,SAAS6D,MAC1B3G,EAAQtX,MAAMme,OAAS,OACvB7G,EAAQ1U,YAAYlG,KAAK0d,UACrB7Z,EAAK4D,KAAKC,SAASiD,IAAUoC,EAAKpC,QAAUA,EAC5C3K,KAAKod,YAAYxC,EAAS7N,GAE1B/M,KAAKgV,GAAG4L,YAAY7T,EAAK3K,GAAIuI,EAEpC,CACD3K,KAAK+c,QAAQ2E,OAChB,CAED,eAAAC,GACI,IAAIlM,EAASzV,KAAKqJ,OAAOoM,OAGzB,MAAO,CAAExJ,GAFCjM,KAAK0Z,KAAK1X,EAAIyT,EAAOhS,EAAIgS,EAAOzT,GAAK,EAE/BmK,EADPnM,KAAK0Z,KAAK1W,EAAI,EAE1B,CAED,MAAAnC,GACIb,KAAKmd,MAAMtC,SAAS,EAAG,GACvB7a,KAAKgd,QAAQ1Z,MAAMgJ,MAAQ,MAC3BtM,KAAKgd,QAAQ1Z,MAAMiJ,OAAS,MAE5BvM,KAAKyf,cACLzf,KAAK4hB,OACR,CAKD,KAAAA,GACI5hB,KAAKmd,MAAMtC,SAAS7a,KAAK0Z,KAAK1X,EAAGhC,KAAK0Z,KAAK1W,GAC3ChD,KAAKgd,QAAQ1Z,MAAMgJ,MAAQtM,KAAK0Z,KAAK1X,EAAI,KACzChC,KAAKgd,QAAQ1Z,MAAMiJ,OAASvM,KAAK0Z,KAAK1W,EAAI,KAC1ChD,KAAK6hB,aACL7hB,KAAK8hB,aAEL9hB,KAAKgV,GAAG2D,oBAAoBhY,EAAUE,OAAQ,CAAE+K,KAAM,IACzD,CAMD,OAAAmW,CAAQte,GACJ,OAAOzD,KAAKgiB,SAAShiB,KAAKud,aAAevd,KAAKuV,KAAKzM,KAAKG,KAAMxF,EACjE,CAMD,QAAAwe,CAASxe,GACL,OAAOzD,KAAKgiB,SAAShiB,KAAKud,aAAevd,KAAKuV,KAAKzM,KAAKG,KAAMxF,EACjE,CAMD,QAAAue,CAASlZ,EAAMrF,GACX,GAAIqF,EAAO9I,KAAKuV,KAAKzM,KAAKC,KAAOD,EAAO9I,KAAKuV,KAAKzM,KAAKE,IACnD,OAAO,EAEX,IAAIkZ,EAAeliB,KAAK+c,QAAQoF,wBAChC,GACIrZ,EAAO,GACPA,EAAO9I,KAAKud,cACZvd,KAAK0Z,KAAK1X,EAAI8G,EAAOoZ,EAAa5V,OAClCtM,KAAK0Z,KAAK1W,EAAI8F,EAAOoZ,EAAa3V,OAElC,OAAO,EAEX,IAAI6V,EAAgB3e,EACd,CAAEwI,EAAGxI,EAAEwI,EAAIiW,EAAajW,EAAGE,EAAG1I,EAAE0I,EAAI+V,EAAa/V,GACjD,CAAEF,EAAGiW,EAAa5V,MAAQ,EAAGH,EAAG+V,EAAa3V,OAAS,GACxD8V,GACEriB,KAAK+c,QAAQuF,WAAaF,EAAYnW,GAAKnD,EAAQ9I,KAAKud,aAAe6E,EAAYnW,EACrFsW,GACEviB,KAAK+c,QAAQyF,UAAYJ,EAAYjW,GAAKrD,EAAQ9I,KAAKud,aAAe6E,EAAYjW,EAExFnM,KAAKud,aAAezU,EACpB,IAAK,IAAI3F,EAAI,EAAGA,EAAInD,KAAK+c,QAAQnS,SAAS1K,OAAQiD,IAC9CnD,KAAK+c,QAAQnS,SAASzH,GAAGG,MAAMwF,KAAOA,EAK1C,OAHA9I,KAAK4hB,QACL5hB,KAAK+c,QAAQuF,WAAaD,EAC1BriB,KAAK+c,QAAQyF,UAAYD,GAClB,CACV,CAED,IAAA3hB,CAAK6hB,GACDhhB,EAAON,MAAM,4BAA4BshB,MACzCziB,KAAKyf,cACLzf,KAAK4hB,QACCa,GACFziB,KAAK0iB,YAAY1iB,KAAKgV,GAAGrE,KAAK1C,KAErC,CACD,QAAA0U,GACI3iB,KAAKyf,cACLzf,KAAK4hB,OACR,CAED,aAAAgB,CAAc7V,GACV,IAAIf,EAAKe,EAAKjB,MAAM3D,KACpB6D,EAAG6W,gBAAkB,CACjB5W,EAAGxL,SAASuL,EAAG4O,QAAQtX,MAAMlD,MAAQJ,KAAK+c,QAAQuF,WAClDnW,EAAG1L,SAASuL,EAAG4O,QAAQtX,MAAMkd,KAAOxgB,KAAK+c,QAAQyF,UAExD,CAED,gBAAAM,CAAiB/V,GACb,IAAIf,EAAKe,EAAKjB,MAAM3D,KACpBnI,KAAK+c,QAAQuF,WAAa7hB,SAASuL,EAAG4O,QAAQtX,MAAMlD,MAAQ4L,EAAG6W,gBAAgB5W,EAC/EjM,KAAK+c,QAAQyF,UAAY/hB,SAASuL,EAAG4O,QAAQtX,MAAMkd,KAAOxU,EAAG6W,gBAAgB1W,CAChF,CACD,WAAA8S,GACI,IAAItO,EAAO3Q,KAAKgV,GAAGrE,KACnB,GAAY,MAARA,EAAJ,CAGA,IAAIxC,EAAQwC,EAAKxC,MACbpB,EAAO,KACX,IAAK,IAAIsS,KAAUlR,GACfpB,EAAOoB,EAAMkR,IACRvT,MAAM3D,KAAKyS,QAAU,KAC1B7N,EAAKjB,MAAM3D,KAAKuY,SAAW,KAE/B1gB,KAAKgd,QAAQ9Z,UAAY,EARxB,CASJ,CAED,UAAA2e,GACI,IAAI1T,EAAQnO,KAAKgV,GAAGrE,KAAKxC,MACrBpB,EAAO,KACPgW,EAAe,KACfhjB,EAAI,KACJ8X,EAAY,KACZmL,EAAchjB,KAAK2hB,kBACvB,IAAK,IAAItC,KAAUlR,EAGf4U,GADAlL,GADA9K,EAAOoB,EAAMkR,IACIvT,MAAM3D,MACEyS,QACpB5a,KAAKqJ,OAAOiQ,WAAWvM,IAK5B/M,KAAKsf,wBAAwBvS,GAC7BhN,EAAIC,KAAKqJ,OAAOuO,eAAe7K,GAC/B8K,EAAU3L,MAAQ8W,EAAY/W,EAAIlM,EAAEkM,EACpC4L,EAAUzL,MAAQ4W,EAAY7W,EAAIpM,EAAEoM,EACpC4W,EAAazf,MAAMlD,KAAO4iB,EAAY/W,EAAIlM,EAAEkM,EAAI,KAChD8W,EAAazf,MAAMkd,IAAMwC,EAAY7W,EAAIpM,EAAEoM,EAAI,KAC/C4W,EAAazf,MAAM2f,QAAU,GAC7BF,EAAazf,MAAMoC,WAAa,UAChC1F,KAAKkjB,eAAenW,EAAMiW,KAZtBD,EAAazf,MAAM2f,QAAU,OAC7BpL,EAAU6I,SAASpd,MAAM2f,QAAU,OAa9C,CAED,cAAAC,CAAenW,EAAMiW,GACjB,GAAIjW,EAAKjC,OACL,OAGJ,IAAI4V,EAAW3T,EAAKjB,MAAM3D,KAAKuY,SAC/B,GAA4B,GAAxB3T,EAAKnC,SAAS1K,OAGd,OAFAwgB,EAASpd,MAAM2f,QAAU,YACzBvC,EAASpd,MAAMoC,WAAa,UAIhC,IAAIyd,EAAgBnjB,KAAKojB,mBAAmBrW,GAC5CjL,EAAEW,EAAEie,EAAUyC,GAEd,IAAIE,EAAarjB,KAAKqJ,OAAO6O,mBAAmBnL,GAChD2T,EAASpd,MAAMlD,KAAO4iB,EAAY/W,EAAIoX,EAAWpX,EAAI,KACrDyU,EAASpd,MAAMkd,IAAMwC,EAAY7W,EAAIkX,EAAWlX,EAAI,KACpDuU,EAASpd,MAAM2f,QAAU,GACzBvC,EAASpd,MAAMoC,WAAa,SAC/B,CAGD,kBAAA0d,CAAmBrW,GACf,IAAIzJ,EAAUtD,KAAKuV,KAAKnM,eAAiBpJ,KAAKuV,KAAKnM,eAAe1I,cAAgB,OAClF,MAAc,WAAV4C,EACOyJ,EAAKnC,SAAS1K,OAAS,GAAK,MAAQ6M,EAAKnC,SAAS1K,OAE/C,SAAVoD,EACOyJ,EAAK/B,SAAW,IAAM,SADjC,CAGH,CAGD,oBAAAsS,CAAqBgG,EAAKvW,GAClB/M,KAAKuV,KAAKrN,aACVpG,EAAEkB,EAAEsgB,EAAKvW,EAAKpC,OAEd7I,EAAEW,EAAE6gB,EAAKvW,EAAKpC,MAErB,CAED,mBAAA0S,CAAoBiG,EAAKvW,GACN/M,KAAKuV,KAAKpM,mBAAmBnJ,KAAKgV,GAAIsO,EAAKvW,IAEtD/M,KAAKsd,qBAAqBgG,EAAKvW,EAEtC,CAED,uBAAAuS,CAAwBvS,GACpB/M,KAAK2gB,yBAAyB5T,EAAKjB,MAAM3D,KAAKyS,QAAS7N,EAAKnB,KAC/D,CAED,wBAAA+U,CAAyBoC,EAAc5R,GAsBnC,GArBI,qBAAsBA,IACtB4R,EAAazf,MAAMigB,gBAAkBpS,EAAU,qBAE/C,qBAAsBA,IACtB4R,EAAazf,MAAM4X,MAAQ/J,EAAU,qBAErC,UAAWA,IACX4R,EAAazf,MAAMgJ,MAAQ6E,EAAiB,MAAI,MAEhD,WAAYA,IACZ4R,EAAazf,MAAMiJ,OAAS4E,EAAkB,OAAI,MAElD,cAAeA,IACf4R,EAAazf,MAAMkgB,SAAWrS,EAAU,aAAe,MAEvD,gBAAiBA,IACjB4R,EAAazf,MAAMmgB,WAAatS,EAAU,gBAE1C,eAAgBA,IAChB4R,EAAazf,MAAMogB,UAAYvS,EAAU,eAEzC,qBAAsBA,EAAW,CACjC,IAAIwS,EAAkBxS,EAAU,oBAChC,GAAIwS,EAAgB7jB,WAAW,SAAWqR,EAAiB,OAAKA,EAAkB,OAAG,CACjF,IAAImK,EAAM,IAAIC,MAEdD,EAAIlX,OAAS,WACT,IAAI9B,EAAIR,EAAEQ,EAAE,UACZA,EAAEgK,MAAQyW,EAAajD,YACvBxd,EAAEiK,OAASwW,EAAa/C,aAExB,GAAI1d,EAAE2Z,WAAY,CACJ3Z,EAAE2Z,WAAW,MACnBT,UAHExb,KAKF,EACA,EACA+iB,EAAajD,YACbiD,EAAa/C,cAEjB,IAAI4D,EAAkBthB,EAAEuhB,YACxBd,EAAazf,MAAMqgB,gBAAkB,OAASC,EAAkB,GACnE,CACrB,EACgBtI,EAAIG,IAAMkI,CAC1B,MACgBZ,EAAazf,MAAMqgB,gBAAkB,OAASA,EAAkB,IAEpEZ,EAAazf,MAAMwgB,eAAiB,MAEhC,wBAAyB3S,IACzB4R,EAAazf,MAAMygB,UACf,UAAY5S,EAAU,uBAAyB,OAE1D,CACJ,CAED,kCAAA4P,CAAmChU,GAC/B,IAAIgW,EAAehW,EAAKjB,MAAM3D,KAAKyS,QAC/BzJ,EAAYpE,EAAKnB,KACjB,qBAAsBuF,IACtB4R,EAAazf,MAAMigB,gBAAkBpS,EAAU,qBAE/C,qBAAsBA,IACtB4R,EAAazf,MAAM4X,MAAQ/J,EAAU,oBAE5C,CAED,gCAAA6P,CAAiCjU,GAC7B,IAAIgW,EAAehW,EAAKjB,MAAM3D,KAAKyS,QACnCmI,EAAazf,MAAMigB,gBAAkB,GACrCR,EAAazf,MAAM4X,MAAQ,EAC9B,CACD,WAAA8D,GACIhf,KAAKmd,MAAMrC,OACd,CACD,UAAAgH,GACI9hB,KAAKgf,cACL,IAAI7Q,EAAQnO,KAAKgV,GAAGrE,KAAKxC,MACrBpB,EAAO,KACPiO,EAAM,KACN1C,EAAO,KACP4C,EAAQ,KACR8I,EAAUhkB,KAAK2hB,kBACnB,IAAK,IAAItC,KAAUlR,GACfpB,EAAOoB,EAAMkR,IACFvU,QAGN9K,KAAKqJ,OAAOiQ,WAAWvM,KAG5BiO,EAAMhb,KAAKqJ,OAAOyO,kBAAkB/K,GACpCuL,EAAOtY,KAAKqJ,OAAO0O,mBAAmBhL,EAAKlB,QAC3CqP,EAAQnO,EAAKnB,KAAK,sBAClB5L,KAAKmd,MAAMpC,UAAUzC,EAAM0C,EAAKgJ,EAAS9I,GAEhD,CAMD,sBAAAqE,CAAuB0E,GAEnB,GADAjkB,KAAKuV,KAAK5M,UAAYsb,GACjBjkB,KAAKyd,aAAc,CACpB,IACIxR,EAAGE,EADH+X,GAAW,EAEXlkB,KAAKuV,KAAK3M,iCAEV5I,KAAK+c,QAAQzZ,MAAQ,oBAGzBxB,EAAE0B,GAAGxD,KAAK8H,UAAW,YAAaqc,IAC1BnkB,KAAKuV,KAAK5M,YACVub,GAAW,EAEXjY,EAAIkY,EAAUC,QACdjY,EAAIgY,EAAUE,WAItBviB,EAAE0B,GAAGxD,KAAK8H,UAAW,UAAW,KAC5Boc,GAAW,IAGfpiB,EAAE0B,GAAGxD,KAAK8H,UAAW,YAAawc,IAC1BtkB,KAAKuV,KAAK5M,WACNub,IACAlkB,KAAK+c,QAAQwH,SAAStY,EAAIqY,EAAUF,QAASjY,EAAImY,EAAUD,SAE3DpY,EAAIqY,EAAUF,QACdjY,EAAImY,EAAUD,UAI7B,CACJ,CAED,WAAA3B,CAAY3V,GACR,IAAK/M,KAAKqJ,OAAOiQ,WAAWvM,GAExB,OADAtL,EAAOJ,KAAK,wDACL,EAEX,IAAIwW,EAAY9K,EAAKjB,MAAM3D,KACvB+Z,EAAeliB,KAAK+c,QAAQoF,wBAC5BqC,EACG3M,EAAU3L,MAAQ2L,EAAUvL,MAAQ,EADvCkY,EAEG3M,EAAUzL,MAAQyL,EAAUtL,OAAS,EAM5C,OAJAvM,KAAK+c,QAAQ0H,SACTD,EAAsBxkB,KAAKud,aAAe2E,EAAa5V,MAAQ,EAC/DkY,EAAsBxkB,KAAKud,aAAe2E,EAAa3V,OAAS,IAE7D,CACV,CAGD,MAAAmY,CAAOjhB,GAEH,OADAhC,EAAOJ,KAAK,8BACLrB,KAAK+hB,QAAQte,EACvB,CAED,OAAAkhB,CAAQlhB,GAEJ,OADAhC,EAAOJ,KAAK,+BACLrB,KAAKiiB,SAASxe,EACxB,CAED,OAAAmhB,CAAQ9b,EAAMrF,GAEV,OADAhC,EAAOJ,KAAK,+BACLrB,KAAKgiB,SAASlZ,EAAMrF,EAC9B,EClxBE,MAAMohB,EAKT,WAAA9iB,CAAYiT,EAAII,GACZpV,KAAKgV,GAAKA,EACVhV,KAAKuV,KAAOH,EAEZpV,KAAKkK,QAAUkL,EAAQlL,QAEvBlK,KAAKiK,QAAUmL,EAAQnL,QAEvBjK,KAAK8kB,OAAS,KAEd9kB,KAAK+kB,SAAW,EACnB,CACD,IAAA9P,GAaI,IAAK,IAAI+P,KAZTljB,EAAE0B,GAAGxD,KAAKgV,GAAG7M,KAAK4U,QAAS,UAAW/c,KAAKilB,QAAQC,KAAKllB,OAExDA,KAAKiK,QAAkB,SAAIjK,KAAKmlB,gBAChCnlB,KAAKiK,QAAoB,WAAIjK,KAAKolB,kBAClCplB,KAAKiK,QAAkB,SAAIjK,KAAKqlB,gBAChCrlB,KAAKiK,QAAiB,QAAIjK,KAAKslB,eAC/BtlB,KAAKiK,QAAgB,OAAIjK,KAAKulB,cAC9BvlB,KAAKiK,QAAY,GAAIjK,KAAKwlB,UAC1BxlB,KAAKiK,QAAc,KAAIjK,KAAKylB,YAC5BzlB,KAAKiK,QAAc,KAAIjK,KAAK0lB,YAC5B1lB,KAAKiK,QAAe,MAAIjK,KAAK2lB,aAEV3lB,KAAKkK,QACpB,GAAMlK,KAAKkK,QAAQ8a,IAAWA,KAAUhlB,KAAKiK,QAAS,CAClD,IAAI2b,EAAO5lB,KAAKkK,QAAQ8a,GACnBlQ,MAAM+Q,QAAQD,KACfA,EAAO,CAACA,IAEZ,IAAK,IAAIE,KAAOF,EACZ5lB,KAAK+kB,SAASe,GAAO9lB,KAAKiK,QAAQ+a,EAEzC,CAGiC,mBAA3BhlB,KAAKuV,KAAKwQ,aACjB/lB,KAAK8kB,OAAS9kB,KAAKuV,KAAKwQ,aAExB/lB,KAAK8kB,OAASjhB,EAAKqD,KAAKC,KAE/B,CACD,eAAA6e,GACIhmB,KAAKuV,KAAKvL,QAAS,CACtB,CACD,gBAAAic,GACIjmB,KAAKuV,KAAKvL,QAAS,CACtB,CAED,OAAAib,CAAQxhB,GAIJ,GAHe,GAAXA,EAAEyiB,OACFziB,EAAE0iB,kBAEFnmB,KAAKgV,GAAG7M,KAAKgZ,aAAjB,CAGA,IAAIrb,EAAMrC,GAAKoa,MACf,IAAK7d,KAAKuV,KAAKvL,OACX,OAAO,EAEX,IAAIoc,EACAtgB,EAAIgY,SACHhY,EAAIugB,SAAW,KACfvgB,EAAIwgB,SAAW,KACfxgB,EAAIygB,QAAU,KACdzgB,EAAI0gB,UAAY,IACjBJ,KAAMpmB,KAAK+kB,UACX/kB,KAAK+kB,SAASqB,GAAInf,KAAKjH,KAAMA,KAAKgV,GAAIvR,EAZzC,CAcJ,CAED,eAAA0hB,CAAgBsB,EAAKhjB,GACjB,IAAIwZ,EAAgBwJ,EAAIC,oBACxB,GAAMzJ,EAAe,CACjB,IAAI5O,EAAUrO,KAAK8kB,SACR2B,EAAIjY,SAASyO,EAAe5O,EAAS,cAE5CoY,EAAI3F,YAAYzS,GAChBoY,EAAIE,WAAWtY,GAEtB,CACJ,CAED,iBAAA+W,CAAkBqB,EAAKhjB,GACnB,IAAIwZ,EAAgBwJ,EAAIC,oBACxB,GAAMzJ,IAAkBA,EAAcnS,OAAQ,CAC1C,IAAIuD,EAAUrO,KAAK8kB,SACR2B,EAAIxX,kBAAkBgO,EAAe5O,EAAS,cAErDoY,EAAI3F,YAAYzS,GAChBoY,EAAIE,WAAWtY,GAEtB,CACJ,CAED,eAAAgX,CAAgBoB,EAAKhjB,GACjB,IAAIwZ,EAAgBwJ,EAAIC,oBAClBzJ,GACFwJ,EAAIE,WAAW1J,EAEtB,CAED,cAAAqI,CAAemB,EAAKhjB,GAChB,IAAIwZ,EAAgBwJ,EAAIC,oBAClBzJ,IAAkBA,EAAcnS,SAClC2b,EAAI3F,YAAY7D,EAAcpR,QAC9B4a,EAAI1W,YAAYkN,GAEvB,CAED,aAAAsI,CAAckB,EAAKhjB,GACf,IAAIqC,EAAMrC,GAAKoa,MACXZ,EAAgBwJ,EAAIC,oBAClBzJ,IACFwJ,EAAIlO,YAAY0E,EAAc7a,IAC9B0D,EAAIkY,kBACJlY,EAAIqgB,iBAEX,CAED,SAAAX,CAAUiB,EAAKhjB,GACX,IAAIqC,EAAMrC,GAAKoa,MACXZ,EAAgBwJ,EAAIC,oBACxB,GAAMzJ,EAAe,CACjB,IAAI2J,EAAUH,EAAII,iBAAiB5J,GACnC,IAAK2J,EAAS,CACV,IAAIE,EAAKL,EAAII,iBAAiB5J,EAAcpR,QACtCib,GAAMA,EAAGlc,SAAS1K,OAAS,IAC7B0mB,EAAUE,EAAGlc,SAASkc,EAAGlc,SAAS1K,OAAS,GAElD,CACK0mB,GACFH,EAAI3F,YAAY8F,GAEpB9gB,EAAIkY,kBACJlY,EAAIqgB,gBACP,CACJ,CAED,WAAAV,CAAYgB,EAAKhjB,GACb,IAAIqC,EAAMrC,GAAKoa,MACXZ,EAAgBwJ,EAAIC,oBACxB,GAAMzJ,EAAe,CACjB,IAAI8J,EAAYN,EAAIO,gBAAgB/J,GACpC,IAAK8J,EAAW,CACZ,IAAID,EAAKL,EAAIO,gBAAgB/J,EAAcpR,QACrCib,GAAMA,EAAGlc,SAAS1K,OAAS,IAC7B6mB,EAAYD,EAAGlc,SAAS,GAE/B,CACKmc,GACFN,EAAI3F,YAAYiG,GAEpBjhB,EAAIkY,kBACJlY,EAAIqgB,gBACP,CACJ,CAED,WAAAT,CAAYe,EAAKhjB,GACbzD,KAAKinB,kBAAkBR,EAAKhjB,EAAGtD,EAAUC,KAC5C,CAED,YAAAulB,CAAac,EAAKhjB,GACdzD,KAAKinB,kBAAkBR,EAAKhjB,EAAGtD,EAAUG,MAC5C,CAED,iBAAA2mB,CAAkBR,EAAKhjB,EAAGxB,GACtB,IAAI6D,EAAMrC,GAAKoa,MACXZ,EAAgBwJ,EAAIC,oBACpB3Z,EAAO,KACX,GAAMkQ,EAAe,CACjB,GAAIA,EAAcnS,OAAQ,CAGtB,IAFA,IAAIxI,EAAI2a,EAAcrS,SAClBA,EAAW,GACNzH,EAAI,EAAGA,EAAIb,EAAEpC,OAAQiD,IACtBb,EAAEa,GAAG4H,YAAc9I,GACnB2I,EAAS8D,KAAKvL,GAGtB4J,EAAOzK,EAAEsI,EAAStD,KAAK4f,OAAOtc,EAAS1K,OAAS,GAAK,IACrE,MAAmB,GAAI+c,EAAclS,YAAc9I,EAAG,CACtC,IACIiU,GADAtL,EAAWqS,EAAcrS,UACC1K,OAC1BgW,EAAiB,IACjBnJ,EAAOnC,EAAStD,KAAK4f,OAAOhR,EAAiB,GAAK,IAEtE,MACgBnJ,EAAOkQ,EAAcpR,OAEnBkB,GACF0Z,EAAI3F,YAAY/T,GAEpBjH,EAAIkY,kBACJlY,EAAIqgB,gBACP,CACJ,EC1ML,MAAMgB,EAAc,CAChBC,QAAS,IAON,SAASC,EAASpc,GACrB,KAAMA,aAAkBqc,GACpB,MAAM,IAAIC,MAAM,4DAEpB,GAAIJ,EAAYC,QAAQxZ,IAAI7N,GAAKA,EAAEuE,MAAMkjB,SAASvc,EAAO3G,MACrD,MAAM,IAAIijB,MAAM,2BAA6Btc,EAAO3G,KAAO,+BAE/D6iB,EAAYC,QAAQ1Y,KAAKzD,EAC7B,CAOO,SAASwc,EAAMzS,EAAII,GACtBtT,EAAEE,EAAE0lB,WAAW,YAQnB,SAAgB1S,EAAII,GAChB+R,EAAYC,QAAQO,QAAQ5nB,GAAKA,EAAE6nB,QAAQ5S,EAAII,EAAQrV,EAAEuE,OAC7D,CATQujB,CAAO7S,EAAII,EACd,EAAE,EACP,CASO,MAAMkS,EAMT,WAAAvlB,CAAYuC,EAAMsjB,GACd,IAAKtjB,EACD,MAAM,IAAIijB,MAAM,0BAEpB,IAAKK,GAA8B,mBAAZA,EACnB,MAAM,IAAIL,MAAM,oCAEpBvnB,KAAKsE,KAAOA,EACZtE,KAAK4nB,QAAUA,CAClB,EC/CE,MAAME,EAIT,WAAA/lB,CAAYiT,GACRhV,KAAKgV,GAAKA,EAEVhV,KAAKonB,QAAU,IAAIW,GACtB,CAKD,kBAAAC,GACI,MAAMC,EAAiBjoB,KAAKgV,GAAGjT,YAAYmmB,mBAAmBC,OAAOlmB,GAAKA,EAAEmmB,SAC5E3mB,EAAOL,KAAK,gBAAkB6mB,EAAe/nB,OAAS,oBACtD+nB,EAAeN,QAAQU,IACnBroB,KAAKsoB,YAAYD,IAExB,CAKD,iBAAAE,GACI,MAAMC,EAAgBxoB,KAAKgV,GAAGjT,YAAYmmB,mBAAmBC,OAAOlmB,IAAMA,EAAEmmB,SAC5E3mB,EAAOL,KAAK,gBAAkBonB,EAActoB,OAAS,mBACrDsoB,EAAcb,QAAQU,IAClBroB,KAAKsoB,YAAYD,IAExB,CAOD,WAAAC,CAAYD,GACR,IACI,MAAMI,YAAEA,EAAWC,UAAEA,GAAcL,EAGnC,IAAKI,EAAYE,aACb,MAAM,IAAIpB,MAAM,UAAYkB,EAAYnkB,KAAO,oCAI/CtE,KAAKonB,QAAQwB,IAAIH,EAAYE,eAC7BlnB,EAAOJ,KACH,UAAYonB,EAAYE,aAAe,qCAK/C,MAAME,EAAW,IAAIJ,EAAY,CAC7BzT,GAAIhV,KAAKgV,GACT0T,UAAWA,GAAa,CAAE,IAI9B1oB,KAAKonB,QAAQ0B,IAAIL,EAAYE,aAAcE,GAC3C7oB,KAAKgV,GAAGyT,EAAYE,cAAgBE,EACpCR,EAAWQ,SAAWA,EAEtBpnB,EAAOL,KAAK,mBAAqBqnB,EAAYE,aAAe,eAC/D,CAAC,MAAOrnB,GACLG,EAAOH,MAAM,+BAAiC+mB,EAAWI,YAAYnkB,KAAO,IAAKhD,EACpF,CACJ,CAMD,YAAAynB,CAAaN,GACT,MAAME,EAAeF,EAAYE,aACjC,IAAKA,EACD,OAGJ,MAAME,EAAW7oB,KAAKonB,QAAQ4B,IAAIL,GAClC,GAAKE,EAIL,IAE+C,mBAAhCA,EAASI,oBAChBJ,EAASI,qBAIbjpB,KAAKonB,QAAQ8B,OAAOP,UAGb3oB,KAAKgV,GAAG2T,GAGf,MAAMQ,EAAOnpB,KAAKgV,GAAGjT,YAAYmmB,mBAC3Bvc,EAAQwd,EAAKC,UAAUnnB,GAAKA,EAAEwmB,cAAgBA,IACrC,IAAX9c,GACAwd,EAAKtZ,OAAOlE,EAAO,GAGvBlK,EAAOL,KAAK,mBAAqBunB,EAAe,WACnD,CAAC,MAAOrnB,GACLG,EAAOH,MAAM,2BAA6BqnB,EAAe,IAAKrnB,EACjE,CACJ,CAKD,iBAAA+nB,GACIrpB,KAAKonB,QAAQO,QAAQ,CAACkB,EAAUF,KAC5B,IAEgD,mBAAjCE,EAASS,qBAChBT,EAASS,qBAEhB,CAAC,MAAOhoB,GACLG,EAAOH,MAAM,4BAA8BqnB,EAAe,IAAKrnB,EAClE,IAGLtB,KAAKonB,QAAQtM,OAChB,CAOD,SAAAyO,CAAUZ,GACN,OAAO3oB,KAAKonB,QAAQ4B,IAAIL,EAC3B,EAOE,MAAMa,EAKTC,oBAAsB,GAMtBA,gBAAiB,EAKjB,WAAA1nB,EAAYiT,GAAEA,EAAE0T,UAAEA,IACd1oB,KAAKgV,GAAKA,EACVhV,KAAKoV,QAAUsT,GAAa,EAC/B,CAMD,kBAAAO,GAEC,CAMD,mBAAAK,GAEItpB,KAAKipB,oBACR,ECnKU,MAAMS,EACjBD,YAAc3b,EACd2b,YAAcve,EACdue,iBAAmBtpB,EACnBspB,kBAAoB9oB,EACpB8oB,SAAW3nB,EACX2nB,cAAgBnC,EAChBmC,uBAAyBE,EACzBF,YAAcG,EACdH,uBAAyBD,EAGzBC,0BAA4B,GAQ5B,gBAAOI,CAAUpB,EAAarT,EAAU,IAGpC,GADesU,EAAOxB,mBAAmB4B,KAAK7nB,GAAKA,EAAEwmB,cAAgBA,GAGjE,OADAhnB,EAAOJ,KAAK,UAAYonB,EAAYnkB,KAAO,uBACpColB,EAIX,IAAKjB,EAAYE,aACb,MAAM,IAAIpB,MAAM,UAAYkB,EAAYnkB,KAAO,oCAYnD,OARAolB,EAAOxB,mBAAmBxZ,KAAK,CAC3B+Z,cACAE,aAAcF,EAAYE,aAC1BP,QAASK,EAAYL,UAAW,EAChCM,UAAWtT,EACXyT,SAAU,OAGPa,CACV,CAOD,wBAAOK,CAAkBtB,GACrB,OAAOiB,EAAOxB,mBAAmB4B,KAAK7nB,GAAKA,EAAEwmB,cAAgBA,EAChE,CAMD,WAAA1mB,CAAYqT,GACRsU,EAAOM,QAAUhqB,KACjBA,KAAKoV,QX0BN,SAAsBA,GACzB,IAAIG,EAAO,CAAA,EAIX,GAHA1R,EAAKuC,KAAKO,MAAM4O,EAAM1N,GACtBhE,EAAKuC,KAAKO,MAAM4O,EAAMH,IAEjBG,EAAKzN,UACN,MAAM,IAAIyf,MAAM,sDAEpB,OAAOhS,CACX,CWnCuB0U,CAAa7U,GAC5B3T,EAAOE,MAAMT,EAASlB,KAAKoV,QAAQvT,YACnC7B,KAAKgO,QAAUrO,EACfK,KAAKkqB,aAAc,EACnBlqB,KAAK2Q,KAAO,KAEZ3Q,KAAKmqB,cAAgB,GACrBnqB,KAAKiV,MACR,CAGD,IAAAA,GACI,IAAMjV,KAAKkqB,YAAX,CAGAlqB,KAAKkqB,aAAc,EAGnBlqB,KAAKoqB,sBAAwB,IAAItC,EAAsB9nB,MAGvDA,KAAKoqB,sBAAsBpC,qBAE3B,IAAIqC,EAAc,CACdpiB,KAAMjI,KAAKoV,QAAQnN,KACnBqB,OAAQtJ,KAAKoV,QAAQ/L,OAAOC,OAC5BC,OAAQvJ,KAAKoV,QAAQ/L,OAAOE,OAC5BC,OAAQxJ,KAAKoV,QAAQ/L,OAAOG,OAC5BC,aAAczJ,KAAKoV,QAAQ/L,OAAOI,cAElC6gB,EAAY,CACZxiB,UAAW9H,KAAKoV,QAAQtN,UACxBI,aAAclI,KAAKoV,QAAQlN,aAC3BE,OAAQpI,KAAKoV,QAAQjN,KAAKC,OAC1BC,0BAA2BrI,KAAKoV,QAAQjN,KAAKE,0BAC7CC,QAAStI,KAAKoV,QAAQjN,KAAKG,QAC3BC,QAASvI,KAAKoV,QAAQjN,KAAKI,QAC3BC,WAAYxI,KAAKoV,QAAQjN,KAAKK,WAC9BC,WAAYzI,KAAKoV,QAAQjN,KAAKM,WAC9BC,WAAY1I,KAAKoV,QAAQjN,KAAKO,WAC9BwR,mBAAoBla,KAAKoV,QAAQjN,KAAK+R,mBACtCvR,UAAW3I,KAAKoV,QAAQjN,KAAKQ,UAC7BC,+BAAgC5I,KAAKoV,QAAQjN,KAAKS,+BAClDC,cAAe7I,KAAKoV,QAAQjN,KAAKU,cACjCC,KAAM9I,KAAKoV,QAAQjN,KAAKW,KACxBK,mBAAoBnJ,KAAKoV,QAAQjN,KAAKgB,mBACtCC,eAAgBpJ,KAAKoV,QAAQjN,KAAKiB,gBAGtCpJ,KAAK4L,KAAO,IAAImJ,EAAa/U,MAC7BA,KAAKqJ,OAAS,IAAIiM,EAAetV,KAAMqqB,GACvCrqB,KAAKmI,KAAO,IAAI2U,EAAa9c,KAAMsqB,GACnCtqB,KAAK+J,SAAW,IAAI8a,EAAiB7kB,KAAMA,KAAKoV,QAAQrL,UAExD/J,KAAK4L,KAAKqJ,OACVjV,KAAKqJ,OAAO4L,OACZjV,KAAKmI,KAAK8M,OACVjV,KAAK+J,SAASkL,OAEdjV,KAAKuqB,cAGLvqB,KAAKoqB,sBAAsB7B,oBAG3BiC,EAAcxqB,KAAMA,KAAKoV,QAAQnK,OAnDhC,CAoDJ,CAED,YAAAwf,GACI,OAAOzqB,KAAKoV,QAAQrN,QACvB,CAED,WAAA2iB,GACI1qB,KAAKoV,QAAQrN,UAAW,CAC3B,CAED,YAAA4iB,GACI3qB,KAAKoV,QAAQrN,UAAW,CAC3B,CAED,kBAAA6iB,GACI,OAAO5qB,KAAKoV,QAAQjN,KAAKQ,SAC5B,CAED,qBAAAkiB,GACI7qB,KAAKoV,QAAQjN,KAAKQ,WAAY,EAC9B3I,KAAKmI,KAAKoX,wBAAuB,EACpC,CAED,sBAAAuL,GACI9qB,KAAKoV,QAAQjN,KAAKQ,WAAY,EAC9B3I,KAAKmI,KAAKoX,wBAAuB,EACpC,CAMD,mBAAAwL,CAAoBrM,GAChB1e,KAAKoV,QAAQ1L,qBAAqB,UAAYgV,EAAe,YAAa,CAC7E,CAMD,oBAAAsM,CAAqBtM,GACjB1e,KAAKoV,QAAQ1L,qBAAqB,UAAYgV,EAAe,YAAa,CAC7E,CAKD,SAAAuM,CAAUjjB,GACN,IAAIkjB,EAAYlrB,KAAKoV,QAAQpN,MAC7BhI,KAAKoV,QAAQpN,MAAUA,GAAgB,KACnCkjB,GAAalrB,KAAKoV,QAAQpN,QAC1BhI,KAAKmI,KAAK+W,cACVlf,KAAKmI,KAAKiX,qBAEjB,CAED,WAAAmL,GACIvqB,KAAKmI,KAAKqW,UAAUxe,KAAM,YAAaA,KAAKmrB,kBAC5CnrB,KAAKmI,KAAKqW,UAAUxe,KAAM,QAASA,KAAKorB,cACxCprB,KAAKmI,KAAKqW,UAAUxe,KAAM,WAAYA,KAAKqrB,iBAC3CrrB,KAAKmI,KAAKqW,UAAUxe,KAAM,QAASA,KAAKsrB,mBAAmB,EAC9D,CAED,gBAAAH,CAAiB1nB,GACb,GAAKzD,KAAKoV,QAAQ1L,qBAA8C,wBAAhE,CAGA,IAAIkR,EAAUnX,EAAEmb,QAAUf,MAAM0N,WAC5Bld,EAAUrO,KAAKmI,KAAK0W,kBAAkBjE,GACpCvM,EACErO,KAAKmI,KAAK8E,QAAQ2N,IAClB5a,KAAK8gB,YAAYzS,GAGrBrO,KAAKihB,cARR,CAUJ,CAED,YAAAmK,CAAa3nB,GACT,GAAKzD,KAAKoV,QAAQ1L,qBAA0C,oBAA5D,CAGA,IAAIkR,EAAUnX,EAAEmb,QAAUf,MAAM0N,WAEhC,GADkBvrB,KAAKmI,KAAK4W,YAAYnE,GACvB,CACb,IAAIvM,EAAUrO,KAAKmI,KAAK0W,kBAAkBjE,GACpCvM,GACFrO,KAAKuY,YAAYlK,EAExB,CARA,CASJ,CAED,eAAAgd,CAAgB5nB,GACZ,GAAKzD,KAAKoV,QAAQ1L,qBAA6C,wBAG3D1J,KAAKyqB,eAAgB,CACrB,IAAI7P,EAAUnX,EAAEmb,QAAUf,MAAM0N,WAEhC,GADcvrB,KAAKmI,KAAK8E,QAAQ2N,GACnB,CACT,IAAIvM,EAAUrO,KAAKmI,KAAK0W,kBAAkBjE,GACpCvM,GACFrO,KAAK2mB,WAAWtY,EAEvB,CACJ,CACJ,CAGD,iBAAAid,CAAkB7nB,GAEd,IAAI2iB,GAAM3iB,EAAE4iB,SAAW,KAAO5iB,EAAE6iB,SAAW,KAAO7iB,EAAE8iB,QAAU,KAAO9iB,EAAE+iB,UAAY,IACnF,GACKxmB,KAAKoV,QAAQ1L,qBAA+C,0BAC7D1J,KAAKoV,QAAQjN,KAAKW,KAAKI,WAAakd,EAFxC,CAMA,IAAItgB,EAAMrC,GAAKoa,MAEf/X,EAAIqgB,iBAEArgB,EAAI0lB,OAAS,EACbxrB,KAAKmI,KAAK4Z,QAAQjc,GAElB9F,KAAKmI,KAAK8Z,SAASnc,EARtB,CAUJ,CAMD,UAAA6gB,CAAW5Z,GACP,IAAK7B,EAAK+B,QAAQF,GAAO,CACrB,IAAIiC,EAAWhP,KAAKoO,SAASrB,GAC7B,OAAKiC,EAIMhP,KAAK2mB,WAAW3X,IAHvBvN,EAAOH,MAAM,eAAiByL,EAAO,wBAC9B,EAId,CACG/M,KAAKyqB,eACLzqB,KAAKmI,KAAKiZ,gBAAgBrU,GAE1BtL,EAAOH,MAAM,uCAGpB,CAED,QAAAmqB,GACIzrB,KAAKmI,KAAK4V,eACb,CAMD,WAAAxF,CAAYxL,GACR,IAAK7B,EAAK+B,QAAQF,GAAO,CACrB,IAAIiC,EAAWhP,KAAKoO,SAASrB,GAC7B,OAAKiC,OAIDhP,KAAKuY,YAAYvJ,QAHjBvN,EAAOH,MAAM,eAAiByL,EAAO,sBAM5C,CACGA,EAAKjC,SAGT9K,KAAKmI,KAAKya,cAAc7V,GACxB/M,KAAKqJ,OAAOkP,YAAYxL,GACxB/M,KAAKmI,KAAKwa,WACV3iB,KAAKmI,KAAK2a,iBAAiB/V,GAC9B,CAMD,WAAA0L,CAAY1L,GACR,IAAK7B,EAAK+B,QAAQF,GAAO,CACrB,IAAIiC,EAAWhP,KAAKoO,SAASrB,GAC7B,OAAKiC,OAIDhP,KAAKyY,YAAYzJ,QAHjBvN,EAAOH,MAAM,eAAiByL,EAAO,sBAM5C,CACGA,EAAKjC,SAGT9K,KAAKmI,KAAKya,cAAc7V,GACxB/M,KAAKqJ,OAAOoP,YAAY1L,GACxB/M,KAAKmI,KAAKwa,WACV3iB,KAAKmI,KAAK2a,iBAAiB/V,GAC9B,CAMD,aAAAyL,CAAczL,GACV,IAAK7B,EAAK+B,QAAQF,GAAO,CACrB,IAAIiC,EAAWhP,KAAKoO,SAASrB,GAC7B,OAAKiC,OAIDhP,KAAKwY,cAAcxJ,QAHnBvN,EAAOH,MAAM,eAAiByL,EAAO,sBAM5C,CACGA,EAAKjC,SAGT9K,KAAKmI,KAAKya,cAAc7V,GACxB/M,KAAKqJ,OAAOmP,cAAczL,GAC1B/M,KAAKmI,KAAKwa,WACV3iB,KAAKmI,KAAK2a,iBAAiB/V,GAC9B,CAED,UAAA6L,GACI5Y,KAAKqJ,OAAOuP,aACZ5Y,KAAKmI,KAAKwa,UACb,CAED,YAAA9J,GACI7Y,KAAKqJ,OAAOwP,eACZ7Y,KAAKmI,KAAKwa,UACb,CAKD,eAAA7J,CAAgBI,GACZlZ,KAAKqJ,OAAOyP,gBAAgBI,GAC5BlZ,KAAKmI,KAAKwa,UACb,CAED,MAAA+I,GACI1rB,KAAK2Y,oBAAoBhY,EAAUK,MAAO,CAAE4K,KAAM,KAClD5L,KAAKmI,KAAKnH,QACVhB,KAAKqJ,OAAOrI,QACZhB,KAAK4L,KAAK5K,OACb,CAMD,KAAA4gB,CAAMjR,EAAMgb,GACR,IAAIC,EAAIjb,GAAQP,EAAOgB,WAAWd,QAClCtQ,KAAK2Q,KAAO3Q,KAAK4L,KAAKsJ,KAAK0W,GACtB5rB,KAAK2Q,MAINlP,EAAON,MAAM,gBAGjBnB,KAAKmI,KAAK+M,OACVzT,EAAON,MAAM,gBAEbnB,KAAKqJ,OAAOA,SACZ5H,EAAON,MAAM,oBAEbnB,KAAKmI,KAAKvH,MAAM+qB,GAChBlqB,EAAON,MAAM,gBAEbnB,KAAK2Y,oBAAoBhY,EAAUC,KAAM,CAAEgL,KAAM,CAAC+E,MAf9ClP,EAAOH,MAAM,kBAgBpB,CAMD,IAAAV,CAAK+P,EAAMgb,GACP3rB,KAAK0rB,SACL1rB,KAAK4hB,MAAMjR,EAAMgb,EACpB,CAED,QAAAE,GACI,MAAO,CACHvnB,KAAMtE,KAAK2Q,KAAKrM,KAChByJ,OAAQ/N,KAAK2Q,KAAK5C,OAClBC,QAAShO,KAAK2Q,KAAK3C,QAE1B,CAMD,QAAA6C,CAASwE,GACL,IAAI3E,EAAK2E,GAAe,YACxB,OAAOrV,KAAK4L,KAAKiF,SAASH,EAC7B,CAED,QAAAob,GACI,OAAO9rB,KAAK2Q,KAAK1C,IACpB,CAKD,QAAAG,CAASrB,GACL,OAAI7B,EAAK+B,QAAQF,GACNA,EAEJ/M,KAAK2Q,KAAKvC,SAASrB,EAC7B,CAWD,cAAAgf,CAAejf,EAAauB,EAAS1D,EAAOiB,EAAMb,GAC9C,IAAIvK,EAAML,EAAUI,GAAGwK,QACXihB,IAARxrB,IACAA,EAAMR,KAAKqJ,OAAOsM,+BAA+B7I,IAGrD,IAAIC,EAAO/M,KAAK2Q,KAAKnC,SAAS1B,EAAauB,EAAS1D,EAAOiB,EAAMpL,GAKjE,OAJMuM,IACF/M,KAAKmI,KAAKqG,SAASzB,GACnB/M,KAAKmI,KAAKmX,wBAAwBvS,IAE/BA,CACV,CAOD,gBAAAkf,CAAiBnf,GACb9M,KAAKqJ,OAAOA,SACZrJ,KAAKmI,KAAKvH,MAAK,GACfZ,KAAKyY,YAAY3L,EACpB,CAWD,QAAA0B,CAAS1B,EAAauB,EAAS1D,EAAOiB,EAAMb,GACxC,IAAK/K,KAAKyqB,eAEN,OADAhpB,EAAOH,MAAM,uCACN,KAGX,IAAI4qB,EAAkBlsB,KAAKoO,SAAStB,GACpC,IAAKof,EAED,OADAzqB,EAAOH,MAAM,yBACN,KAGX,IAAIyL,EAAO/M,KAAK+rB,eAAeG,EAAiB7d,EAAS1D,EAAOiB,EAAMb,GAStE,OARMgC,IACF/M,KAAKisB,iBAAiBC,GACtBlsB,KAAK2Y,oBAAoBhY,EAAUG,KAAM,CACrCgF,IAAK,WACL8F,KAAM,CAACsgB,EAAgB9pB,GAAIiM,EAAS1D,EAAOiB,EAAMzL,EAAUI,GAAGwK,IAC9DgC,KAAMsB,KAGPtB,CACV,CAwBD,SAAAof,CAAUrf,EAAasf,GACnB,IAAKpsB,KAAKyqB,eAEN,OADAhpB,EAAOH,MAAM,uCACN,GAGX,IAAI4qB,EAAkBlsB,KAAKoO,SAAStB,GACpC,IAAKof,EAED,OADAzqB,EAAOH,MAAM,yBACN,GAGX,IAAKwT,MAAM+Q,QAAQuG,IAAqC,IAAtBA,EAAWlsB,OAEzC,OADAuB,EAAOJ,KAAK,0CACL,GAGX,MAAMgrB,EAAiBrsB,KAAKssB,sBAAsBF,GAClD,IAAIG,EAAgBH,EACfxe,IAAIuD,GAAanR,KAAKwsB,qBAAqBN,EAAiB/a,IAC5Dsb,OACAtE,OAAOzlB,GAAW,OAANA,GAEjB,MAAMgqB,EAAeH,EAAcrsB,OAGnC,OAAIwsB,IAAiBL,GAEjBrsB,KAAKisB,iBAAiBC,GACtBlsB,KAAK2Y,oBAAoBhY,EAAUG,KAAM,CACrCgF,IAAK,YACL8F,KAAM,CAACsgB,EAAgB9pB,GAAIgqB,GAC3Bje,MAAOoe,EAAc3e,IAAIb,GAAQA,EAAK3K,MAEnCmqB,IAGP9qB,EAAOJ,KACH,YAAYgrB,6BAA0CK,qBAE1D1sB,KAAK2sB,uBAAuBJ,GACrB,GAEd,CAWD,oBAAAC,CAAqB1f,EAAaqE,GAC9B,IAAIob,EAAgB,GAGpB,IAAKpb,EAAU/O,KAAO+O,EAAUxG,MAE5B,OADAlJ,EAAOJ,KAAK,qBAAsB8P,GAC3B,GAIX,IAAIyb,EAAW5sB,KAAK+rB,eAChBjf,EACAqE,EAAU/O,GACV+O,EAAUxG,MACVwG,EAAUvF,MAAQ,CAAE,EACpBuF,EAAUpG,WAGd,GAAI6hB,IACAL,EAAc7d,KAAKke,GAEf9X,MAAM+Q,QAAQ1U,EAAUvG,WAAW,CACnC,MAAMiiB,EAAY1b,EAAUvG,SACvBgD,IAAIC,GAAS7N,KAAKwsB,qBAAqBI,EAAU/e,IACjD4e,OACLF,EAAgBA,EAAcO,OAAOD,EACxC,CAGL,OAAON,CACV,CASD,qBAAAD,CAAsBF,GAClB,IAAKtX,MAAM+Q,QAAQuG,GACf,OAAO,EAIX,IACI7e,GADKvN,KAAKoV,QAAQ1K,YAAc,CAAA,GACfE,UAAY,WAEjC,OAAOwhB,EAAWW,OAAO,CAACC,EAAO7b,KAC7B6b,IAEAA,GAAShtB,KAAKssB,sBAAsBnb,GAAaA,EAAU5D,KAE5D,EACN,CAOD,sBAAAof,CAAuBJ,GACU,IAAzBA,EAAcrsB,QAGlB,IAAIqsB,GAAejb,UAAUqW,QAAQ5a,IAC7BA,IAASA,EAAKjC,SAEd9K,KAAKmI,KAAK4H,YAAYhD,GAEtB/M,KAAK2Q,KAAKZ,YAAYhD,KAGjC,CAWD,kBAAA6B,CAAmBC,EAAaR,EAAS1D,EAAOiB,EAAMb,GAClD,GAAI/K,KAAKyqB,eAAgB,CACrB,IAAIwC,EAAkBjtB,KAAKoO,SAASS,GAChCrO,EAAML,EAAUI,GAAGwK,QACXihB,IAARxrB,IACAA,EAAMR,KAAKqJ,OAAOsM,+BAA+BsX,EAAgBphB,SAErE,IAAIkB,EAAO/M,KAAK2Q,KAAK/B,mBAAmBqe,EAAiB5e,EAAS1D,EAAOiB,EAAMpL,GAW/E,OAVMuM,IACF/M,KAAKmI,KAAKqG,SAASzB,GACnB/M,KAAKqJ,OAAOA,SACZrJ,KAAKmI,KAAKvH,MAAK,GACfZ,KAAK2Y,oBAAoBhY,EAAUG,KAAM,CACrCgF,IAAK,qBACL8F,KAAM,CAACqhB,EAAgB7qB,GAAIiM,EAAS1D,EAAOiB,EAAMpL,GACjDuM,KAAMsB,KAGPtB,CACnB,CAEY,OADAtL,EAAOH,MAAM,uCACN,IAEd,CAUD,iBAAA2N,CAAkBC,EAAYb,EAAS1D,EAAOiB,EAAMb,GAChD,GAAI/K,KAAKyqB,eAAgB,CACrB,IAAIyC,EAAiBltB,KAAKoO,SAASc,GAC/B1O,EAAML,EAAUI,GAAGwK,QACXihB,IAARxrB,IACAA,EAAMR,KAAKqJ,OAAOsM,+BAA+BuX,EAAerhB,SAEpE,IAAIkB,EAAO/M,KAAK2Q,KAAK1B,kBAAkBie,EAAgB7e,EAAS1D,EAAOiB,EAAMpL,GAW7E,OAVMuM,IACF/M,KAAKmI,KAAKqG,SAASzB,GACnB/M,KAAKqJ,OAAOA,SACZrJ,KAAKmI,KAAKvH,MAAK,GACfZ,KAAK2Y,oBAAoBhY,EAAUG,KAAM,CACrCgF,IAAK,oBACL8F,KAAM,CAACshB,EAAe9qB,GAAIiM,EAAS1D,EAAOiB,EAAMpL,GAChDuM,KAAMsB,KAGPtB,CACnB,CAEY,OADAtL,EAAOH,MAAM,uCACN,IAEd,CAMD,WAAAyO,CAAYhD,GACR,IAAK7B,EAAK+B,QAAQF,GAAO,CACrB,IAAIiC,EAAWhP,KAAKoO,SAASrB,GAC7B,OAAKiC,EAIMhP,KAAK+P,YAAYf,IAHxBvN,EAAOH,MAAM,eAAiByL,EAAO,wBAC9B,EAId,CACD,GAAI/M,KAAKyqB,eAAgB,CACrB,GAAI1d,EAAKjC,OAEL,OADArJ,EAAOH,MAAM,mCACN,EAEX,IAAI+M,EAAUtB,EAAK3K,GACfkN,EAAYvC,EAAKlB,OAAOzJ,GACxB0K,EAAc9M,KAAKoO,SAASkB,GAYhC,OAXAtP,KAAKmI,KAAKya,cAAc9V,GACxB9M,KAAKmI,KAAK4H,YAAYhD,GACtB/M,KAAK2Q,KAAKZ,YAAYhD,GACtB/M,KAAKqJ,OAAOA,SACZrJ,KAAKmI,KAAKvH,MAAK,GACfZ,KAAKmI,KAAK2a,iBAAiBhW,GAC3B9M,KAAK2Y,oBAAoBhY,EAAUG,KAAM,CACrCgF,IAAK,cACL8F,KAAM,CAACyC,GACPtB,KAAMuC,KAEH,CACnB,CAEY,OADA7N,EAAOH,MAAM,wCACN,CAEd,CAMD,WAAAsf,CAAYvS,EAAS8e,GACjB,GAAIntB,KAAKyqB,eAAT,CACI,IAAI1d,EAAO/M,KAAKoO,SAASC,GACzB,GAAMtB,EAAM,CACR,IAAIpC,EAAQ,KACRiB,EAAO,KAGqB,iBAArBuhB,EACPxiB,EAAQwiB,EAC2B,iBAArBA,GAAsD,OAArBA,IAC/CxiB,EAAQwiB,EAAiBxiB,MACzBiB,EAAOuhB,EAAiBvhB,MAG5B,IAAIwhB,GAAe,EACfC,GAAc,EAGlB,GAAI1iB,QAAuC,CACvC,GAAIif,EAAMniB,KAAKC,SAASiD,GAEpB,YADAlJ,EAAOJ,KAAK,gCAGZ0L,EAAKpC,QAAUA,IACfoC,EAAKpC,MAAQA,EACbyiB,GAAe,EAEtB,CAGD,GAAIxhB,GAAwB,iBAATA,EACf,IAAK,IAAIka,KAAOla,EACRA,EAAK0hB,eAAexH,KACpB/Y,EAAKnB,KAAKka,GAAOla,EAAKka,GACtBuH,GAAc,GAK1B,IAAKD,IAAiBC,EAGlB,OAFA5rB,EAAOL,KAAK,wBACZpB,KAAKmI,KAAKyY,YAAY7T,GAI1B/M,KAAKmI,KAAKyY,YAAY7T,GACtB/M,KAAKqJ,OAAOA,SACZrJ,KAAKmI,KAAKvH,MAAK,GACfZ,KAAK2Y,oBAAoBhY,EAAUG,KAAM,CACrCgF,IAAK,cACL8F,KAAM,CAACyC,EAAS1D,EAAOiB,GACvBmB,KAAMsB,GAEb,CAIJ,MAFG5M,EAAOH,MAAM,sCAGpB,CAQD,SAAA8N,CAAUf,EAASgB,EAAWC,EAAWvE,GACrC,GAAI/K,KAAKyqB,eAAT,CACI,IAAI1d,EAAO/M,KAAKoO,SAASC,GACrBkf,EAAevtB,KAAK2Q,KAAKvB,UAAUrC,EAAMsC,EAAWC,EAAWvE,GAC7DwiB,IACFvtB,KAAKmI,KAAKyY,YAAY2M,GACtBvtB,KAAKqJ,OAAOA,SACZrJ,KAAKmI,KAAKvH,MAAK,GACfZ,KAAK2Y,oBAAoBhY,EAAUG,KAAM,CACrCgF,IAAK,YACL8F,KAAM,CAACyC,EAASgB,EAAWC,EAAWvE,GACtCgC,KAAMsB,IAMjB,MAFG5M,EAAOH,MAAM,sCAGpB,CAKD,WAAAwf,CAAY/T,GACR,IAAK7B,EAAK+B,QAAQF,GAAO,CACrB,IAAIiC,EAAWhP,KAAKoO,SAASrB,GAC7B,OAAKiC,OAIDhP,KAAK8gB,YAAY9R,QAHjBvN,EAAOH,MAAM,eAAiByL,EAAO,sBAM5C,CACI/M,KAAKqJ,OAAOiQ,WAAWvM,KAG5B/M,KAAK2Q,KAAKzC,SAAWnB,EACrB/M,KAAKmI,KAAK2Y,YAAY/T,GACtB/M,KAAK2Y,oBAAoBhY,EAAUI,OAAQ,CAAE+E,IAAK,cAAe8F,KAAM,GAAImB,KAAMA,EAAK3K,KACzF,CASD,iBAAAskB,GACI,OAAM1mB,KAAK2Q,KACA3Q,KAAK2Q,KAAKzC,SAEV,IAEd,CAED,YAAA+S,GACUjhB,KAAK2Q,OACP3Q,KAAK2Q,KAAKzC,SAAW,KACrBlO,KAAKmI,KAAK8Y,eAEjB,CAED,eAAAuM,CAAgBzgB,GACZ,OAAO/M,KAAKqJ,OAAOiQ,WAAWvM,EACjC,CAKD,qBAAA0gB,CAAsB1gB,GAClB,GAAK7B,EAAK+B,QAAQF,GASlB/M,KAAKmI,KAAKua,YAAY3V,OATtB,CACI,IAAIiC,EAAWhP,KAAKoO,SAASrB,GACxBiC,EAGDhP,KAAKytB,sBAAsBze,GAF3BvN,EAAOH,MAAM,eAAiByL,EAAO,sBAK5C,CAEJ,CAOD,gBAAA8Z,CAAiB9Z,GACb,IAAK7B,EAAK+B,QAAQF,GAAO,CACrB,IAAIiC,EAAWhP,KAAKoO,SAASrB,GAC7B,OAAKiC,EAIMhP,KAAK6mB,iBAAiB7X,QAH7BvN,EAAOH,MAAM,eAAiByL,EAAO,sBAK5C,CACD,GAAIA,EAAKjC,OACL,OAAO,KAEX,IAAIpI,EAAI,KACR,GAAIqK,EAAKlB,OAAOf,OAIZ,IAHA,IAAIxI,EAAIyK,EAAKlB,OAAOjB,SAChB8iB,EAAO,KACPC,EAAK,KACAxqB,EAAI,EAAGA,EAAIb,EAAEpC,OAAQiD,IAC1BwqB,EAAKrrB,EAAEa,GACH4J,EAAKhC,YAAc4iB,EAAG5iB,YAClBgC,EAAK3K,KAAOurB,EAAGvrB,KACfM,EAAIgrB,GAERA,EAAOC,QAIfjrB,EAAI1C,KAAK2Q,KAAK5B,gBAAgBhC,GAElC,OAAOrK,CACV,CAMD,eAAAskB,CAAgBja,GACZ,IAAK7B,EAAK+B,QAAQF,GAAO,CACrB,IAAIiC,EAAWhP,KAAKoO,SAASrB,GAC7B,OAAKiC,EAIMhP,KAAKgnB,gBAAgBhY,QAH5BvN,EAAOH,MAAM,eAAiByL,EAAO,sBAK5C,CACD,GAAIA,EAAKjC,OACL,OAAO,KAEX,IAAIpI,EAAI,KACR,GAAIqK,EAAKlB,OAAOf,QAIZ,IAHA,IAAIxI,EAAIyK,EAAKlB,OAAOjB,SAChBgjB,GAAQ,EACRD,EAAK,KACAxqB,EAAI,EAAGA,EAAIb,EAAEpC,OAAQiD,IAE1B,GADAwqB,EAAKrrB,EAAEa,GACH4J,EAAKhC,YAAc4iB,EAAG5iB,UAAW,CACjC,GAAI6iB,EAAO,CACPlrB,EAAIirB,EACJ,KACH,CACG5gB,EAAK3K,KAAOurB,EAAGvrB,KACfwrB,GAAQ,EAEf,OAGLlrB,EAAI1C,KAAK2Q,KAAKxB,eAAepC,GAEjC,OAAOrK,CACV,CAQD,cAAAmrB,CAAexf,EAASyf,EAAUC,GAC9B,IAAI/tB,KAAKyqB,eAaL,OADAhpB,EAAOH,MAAM,uCACN,KAZP,IAAIyL,EAAO/M,KAAK2Q,KAAKvC,SAASC,GACxBtB,IACI+gB,IACF/gB,EAAKnB,KAAK,oBAAsBkiB,GAE9BC,IACFhhB,EAAKnB,KAAK,oBAAsBmiB,GAEpC/tB,KAAKmI,KAAKmX,wBAAwBvS,GAM7C,CASD,mBAAAihB,CAAoB3f,EAASqL,EAAMuU,EAAQ3qB,GACvC,IAAItD,KAAKyqB,eAmBL,OADAhpB,EAAOH,MAAM,uCACN,KAlBP,IAAIyL,EAAO/M,KAAK2Q,KAAKvC,SAASC,GACxBtB,IACI2M,IACF3M,EAAKnB,KAAK,aAAe8N,GAEvBuU,IACFlhB,EAAKnB,KAAK,eAAiBqiB,GAEzB3qB,IACFyJ,EAAKnB,KAAK,cAAgBtI,GAE9BtD,KAAKmI,KAAKmX,wBAAwBvS,GAClC/M,KAAKmI,KAAKyY,YAAY7T,GACtB/M,KAAKqJ,OAAOA,SACZrJ,KAAKmI,KAAKvH,MAAK,GAM1B,CAUD,yBAAAstB,CAA0B7f,EAAS8f,EAAO7hB,EAAOC,EAAQ6hB,GACrD,IAAIpuB,KAAKyqB,eAsBL,OADAhpB,EAAOH,MAAM,uCACN,KArBP,IAAIyL,EAAO/M,KAAK2Q,KAAKvC,SAASC,GACxBtB,IACIohB,IACFphB,EAAKnB,KAAK,oBAAsBuiB,GAE9B7hB,IACFS,EAAKnB,KAAY,MAAIU,GAEnBC,IACFQ,EAAKnB,KAAa,OAAIW,GAEpB6hB,IACFrhB,EAAKnB,KAAK,uBAAyBwiB,GAEvCpuB,KAAKmI,KAAKmX,wBAAwBvS,GAClC/M,KAAKmI,KAAKyY,YAAY7T,GACtB/M,KAAKqJ,OAAOA,SACZrJ,KAAKmI,KAAKvH,MAAK,GAM1B,CAMD,4BAAAytB,CAA6BhgB,EAAS+f,GAClC,IAAIpuB,KAAKyqB,eAiBL,OADAhpB,EAAOH,MAAM,uCACN,KAhBP,IAAIyL,EAAO/M,KAAK2Q,KAAKvC,SAASC,GAC9B,GAAMtB,EAAM,CACR,IAAKA,EAAKnB,KAAK,oBAIX,OAHAnK,EAAOH,MACH,sEAEG,KAEXyL,EAAKnB,KAAK,uBAAyBwiB,EACnCpuB,KAAKmI,KAAKmX,wBAAwBvS,GAClC/M,KAAKmI,KAAKyY,YAAY7T,GACtB/M,KAAKqJ,OAAOA,SACZrJ,KAAKmI,KAAKvH,MAAK,EAClB,CAKR,CAED,MAAAC,GACIb,KAAKmI,KAAKtH,QACb,CAGD,kBAAAytB,CAAmBjT,GACS,mBAAbA,GACPrb,KAAKmqB,cAAczb,KAAK2M,EAE/B,CAED,oBAAAkT,GACIvuB,KAAKmqB,cAAgB,EACxB,CAED,mBAAAxR,CAAoBlU,EAAMmH,GACtB,IAAI4iB,EAAIxuB,KACR8B,EAAEE,EAAE0lB,WAAW,WACX8G,EAAEC,qBAAqBhqB,EAAMmH,EAChC,EAAE,EACN,CAED,oBAAA6iB,CAAqBhqB,EAAMmH,GAEvB,IADA,IAAI8iB,EAAI1uB,KAAKmqB,cAAcjqB,OAClBiD,EAAI,EAAGA,EAAIurB,EAAGvrB,IACnBnD,KAAKmqB,cAAchnB,GAAGsB,EAAMmH,EAEnC,CAMD,YAAAmd,CAAaN,GACLzoB,KAAKoqB,uBACLpqB,KAAKoqB,sBAAsBrB,aAAaN,EAE/C,CAOD,SAAAc,CAAUZ,GACN,GAAI3oB,KAAKoqB,sBACL,OAAOpqB,KAAKoqB,sBAAsBb,UAAUZ,EAGnD,CAKD,OAAAgG,GAEQ3uB,KAAKoqB,uBACLpqB,KAAKoqB,sBAAsBf,oBAI/BrpB,KAAKuuB,uBAGDvuB,KAAKmI,MACLnI,KAAKmI,KAAKnH,QAIdhB,KAAK2Q,KAAO,KACZ3Q,KAAKkqB,aAAc,CACtB,CAQD,WAAOtpB,CAAKwU,EAASzE,GACjBlP,EAAOJ,KACH,6GAEJ,IAAIolB,EAAM,IAAIiD,EAAOtU,GAErB,OADAqR,EAAI7lB,KAAK+P,GACF8V,CACV"}
1
+ {"version":3,"file":"jsmind.js","sources":["../src/jsmind.common.js","../src/jsmind.dom.js","../src/jsmind.util.js","../src/jsmind.option.js","../src/jsmind.node.js","../src/jsmind.mind.js","../src/jsmind.format.js","../src/jsmind.data_provider.js","../src/jsmind.layout_provider.js","../src/jsmind.graph.js","../src/jsmind.view_provider.js","../src/jsmind.shortcut_provider.js","../src/jsmind.plugin.js","../src/jsmind.enhanced-plugin.js","../src/jsmind.js"],"sourcesContent":["/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\n/**\n * Library version string.\n * @type {string}\n */\nexport const __version__ = '0.9.0';\n/**\n * Library author.\n * @type {string}\n */\nexport const __author__ = 'UmbraCi';\n\nif (typeof String.prototype.startsWith != 'function') {\n String.prototype.startsWith = function (p) {\n return this.slice(0, p.length) === p;\n };\n}\n\n/**\n * Direction constants and parser.\n * @typedef {{left:number,center:number,right:number,of:(dir:(string|number))=>number|undefined}} DirectionType\n */\n/** @type {DirectionType} */\nexport const Direction = {\n left: -1,\n center: 0,\n right: 1,\n of: function (dir) {\n if (!dir || dir === -1 || dir === 0 || dir === 1) {\n return dir;\n }\n if (dir === '-1' || dir === '0' || dir === '1') {\n return parseInt(dir);\n }\n if (dir.toLowerCase() === 'left') {\n return this.left;\n }\n if (dir.toLowerCase() === 'right') {\n return this.right;\n }\n if (dir.toLowerCase() === 'center') {\n return this.center;\n }\n },\n};\n/** @enum {number} */\nexport const EventType = { show: 1, resize: 2, edit: 3, select: 4, reset: 5, history_change: 6 };\n/** @enum {number} */\nexport const Key = { meta: 1 << 13, ctrl: 1 << 12, alt: 1 << 11, shift: 1 << 10 };\n/** @enum {number} */\nexport const LogLevel = { debug: 1, info: 2, warn: 3, error: 4, disable: 9 };\n\n// an noop function define\nvar _noop = function () {};\n/**\n * Logger facade with dynamic level.\n * @type {{level:(lvl:number)=>void,log:Function,debug:Function,info:Function,warn:Function,error:Function}}\n */\nexport let logger =\n typeof console === 'undefined'\n ? {\n level: _noop,\n log: _noop,\n debug: _noop,\n info: _noop,\n warn: _noop,\n error: _noop,\n }\n : {\n level: setup_logger_level,\n log: console.log,\n debug: console.debug,\n info: console.info,\n warn: console.warn,\n error: console.error,\n };\n\n/**\n * Set logger level.\n * @param {number} log_level\n */\nfunction setup_logger_level(log_level) {\n if (log_level > LogLevel.debug) {\n logger.debug = _noop;\n } else {\n logger.debug = console.debug;\n }\n if (log_level > LogLevel.info) {\n logger.info = _noop;\n } else {\n logger.info = console.info;\n }\n if (log_level > LogLevel.warn) {\n logger.warn = _noop;\n } else {\n logger.warn = console.warn;\n }\n if (log_level > LogLevel.error) {\n logger.error = _noop;\n } else {\n logger.error = console.error;\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\n/**\n * Lightweight DOM helpers bound to a window.\n */\nclass Dom {\n /**\n * @param {Window} w\n */\n constructor(w) {\n /** @type {Window} */\n this.w = w;\n /** @type {Document} */\n this.d = w.document;\n /**\n * Get element by id.\n * @param {string} id\n * @returns {HTMLElement|null}\n */\n this.g = function (id) {\n return this.d.getElementById(id);\n };\n /**\n * Create element with given tag.\n * @param {string} tag\n * @returns {HTMLElement}\n */\n this.c = function (tag) {\n return this.d.createElement(tag);\n };\n /**\n * Set text content for element.\n * @param {HTMLElement} n\n * @param {string} t\n */\n this.t = function (n, t) {\n if (n.hasChildNodes()) {\n n.firstChild.nodeValue = t;\n } else {\n n.appendChild(this.d.createTextNode(t));\n }\n };\n\n /**\n * Set inner HTML or append element.\n * @param {HTMLElement} n\n * @param {string|HTMLElement} t\n */\n this.h = function (n, t) {\n if (t instanceof HTMLElement) {\n n.innerHTML = '';\n n.appendChild(t);\n } else {\n n.innerHTML = t;\n }\n };\n // detect isElement\n /**\n * Runtime check for HTMLElement.\n * @param {unknown} el\n * @returns {el is HTMLElement}\n */\n this.i = function (el) {\n return (\n !!el &&\n typeof el === 'object' &&\n el.nodeType === 1 &&\n typeof el.style === 'object' &&\n typeof el.ownerDocument === 'object'\n );\n };\n\n //target,eventType,handler\n /**\n * Add event listener with legacy fallback.\n * @param {HTMLElement} t\n * @param {string} e\n * @param {(ev:Event)=>void} h\n */\n this.on = function (t, e, h) {\n if (!!t.addEventListener) {\n t.addEventListener(e, h, false);\n } else {\n t.attachEvent('on' + e, h);\n }\n };\n }\n}\n\nexport const $ = new Dom(window);\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { $ } from './jsmind.dom.js';\n\n/**\n * Misc utility collection.\n * @type {{\n * file: { read: (file: File, cb:(result:string,name:string)=>void)=>void, save:(data:string,type:string,name:string)=>void},\n * json: { json2string:(v:unknown)=>string, string2json:(s:string)=>unknown, merge:(b:object,a:object)=>object },\n * uuid: { newid:()=>string },\n * text: { is_empty:(s?:string)=>boolean }\n * }}\n */\nexport const util = {\n file: {\n read: function (file_data, fn_callback) {\n var reader = new FileReader();\n reader.onload = function () {\n if (typeof fn_callback === 'function') {\n fn_callback(this.result, file_data.name);\n }\n };\n reader.readAsText(file_data);\n },\n\n save: function (file_data, type, name) {\n var blob;\n if (typeof $.w.Blob === 'function') {\n blob = new Blob([file_data], { type: type });\n } else {\n var BlobBuilder =\n $.w.BlobBuilder ||\n $.w.MozBlobBuilder ||\n $.w.WebKitBlobBuilder ||\n $.w.MSBlobBuilder;\n var bb = new BlobBuilder();\n bb.append(file_data);\n blob = bb.getBlob(type);\n }\n if (navigator.msSaveBlob) {\n navigator.msSaveBlob(blob, name);\n } else {\n var URL = $.w.URL || $.w.webkitURL;\n var blob_url = URL.createObjectURL(blob);\n var anchor = $.c('a');\n if ('download' in anchor) {\n anchor.style.visibility = 'hidden';\n anchor.href = blob_url;\n anchor.download = name;\n $.d.body.appendChild(anchor);\n var evt = $.d.createEvent('MouseEvents');\n evt.initEvent('click', true, true);\n anchor.dispatchEvent(evt);\n $.d.body.removeChild(anchor);\n } else {\n location.href = blob_url;\n }\n }\n },\n },\n\n json: {\n json2string: function (json) {\n return JSON.stringify(json);\n },\n string2json: function (json_str) {\n return JSON.parse(json_str);\n },\n merge: function (b, a) {\n for (var o in a) {\n if (o in b) {\n if (\n typeof b[o] === 'object' &&\n Object.prototype.toString.call(b[o]).toLowerCase() == '[object object]' &&\n !b[o].length\n ) {\n util.json.merge(b[o], a[o]);\n } else {\n b[o] = a[o];\n }\n } else {\n b[o] = a[o];\n }\n }\n return b;\n },\n },\n\n uuid: {\n newid: function () {\n return (\n new Date().getTime().toString(16) + Math.random().toString(16).substring(2)\n ).substring(2, 18);\n },\n },\n\n text: {\n is_empty: function (s) {\n if (!s) {\n return true;\n }\n return s.replace(/\\s*/, '').length == 0;\n },\n },\n};\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { util } from './jsmind.util.js';\n\n/**\n * @typedef {{\n * container: string|HTMLElement,\n * editable?: boolean,\n * theme?: (string|null),\n * mode?: ('full'|'side'),\n * support_html?: boolean,\n * log_level?: 'debug'|'info'|'warn'|'error'|'disable',\n * view?: {\n * engine?: 'canvas'|'svg',\n * enable_device_pixel_ratio?: boolean,\n * hmargin?: number,\n * vmargin?: number,\n * line_width?: number,\n * line_color?: string,\n * line_style?: 'curved'|'straight',\n * custom_line_render?: (this: object, arg:{ ctx: CanvasRenderingContext2D|SVGPathElement, start_point:{x:number,y:number}, end_point:{x:number,y:number} })=>void,\n * draggable?: boolean,\n * hide_scrollbars_when_draggable?: boolean,\n * node_overflow?: 'hidden'|'wrap'|'visible',\n * zoom?: { min?:number, max?:number, step?:number, mask_key?:number },\n * custom_node_render?: (null|((jm: import('./jsmind.js').default, ele: HTMLElement, node: import('./jsmind.node.js').Node)=>void)),\n * expander_style?: 'char'|'number'\n * },\n * layout?: { hspace?:number, vspace?:number, pspace?:number, cousin_space?:number },\n * default_event_handle?: { enable_mousedown_handle?:boolean, enable_click_handle?:boolean, enable_dblclick_handle?:boolean, enable_mousewheel_handle?:boolean },\n * shortcut?: { enable?:boolean, handles?: Record<string,(jm: import('./jsmind.js').default, e: KeyboardEvent)=>void>, mapping?: Record<string, number|number[]>, id_generator?: ()=>string },\n * fieldNames?: { id?:string, topic?:string, children?:string, parentid?:string, isroot?:string, direction?:string, expanded?:string },\n * plugin?: Record<string, object>\n * }} JsMindRuntimeOptions\n */\n/** @type {JsMindRuntimeOptions} */\nconst default_options = {\n container: '', // id of the container\n editable: false, // you can change it in your options\n theme: null,\n mode: 'full', // full or side\n support_html: true,\n log_level: 'info',\n\n view: {\n engine: 'canvas',\n enable_device_pixel_ratio: false,\n hmargin: 100,\n vmargin: 50,\n line_width: 2,\n line_color: '#555',\n line_style: 'curved', // [straight | curved]\n draggable: false, // drag the mind map with your mouse, when it's larger that the container\n hide_scrollbars_when_draggable: false, // hide container scrollbars, when mind map is larger than container and draggable option is true.\n node_overflow: 'hidden', // [hidden | wrap]\n zoom: {\n min: 0.5,\n max: 2.1,\n step: 0.1,\n mask_key: 4096,\n },\n custom_node_render: null,\n expander_style: 'char', // [char | number]\n },\n layout: {\n hspace: 30,\n vspace: 20,\n pspace: 13,\n cousin_space: 0,\n },\n default_event_handle: {\n enable_mousedown_handle: true,\n enable_click_handle: true,\n enable_dblclick_handle: true,\n enable_mousewheel_handle: true,\n },\n shortcut: {\n enable: true,\n handles: {},\n mapping: {\n addchild: [45, 4096 + 13], // Insert, Ctrl+Enter\n addbrother: 13, // Enter\n editnode: 113, // F2\n delnode: 46, // Delete\n toggle: 32, // Space\n left: 37, // Left\n up: 38, // Up\n right: 39, // Right\n down: 40, // Down\n },\n },\n // Field names mapping for custom data structure\n // Similar to Ant Design's fieldNames prop\n fieldNames: {\n id: 'id',\n topic: 'topic',\n children: 'children',\n parentid: 'parentid',\n isroot: 'isroot',\n direction: 'direction',\n expanded: 'expanded',\n },\n plugin: {},\n};\n\n/**\n * Merge user options with defaults. Throws if container missing.\n * @param {JsMindRuntimeOptions} options\n * @returns {JsMindRuntimeOptions}\n */\nexport function merge_option(options) {\n var opts = {};\n util.json.merge(opts, default_options);\n util.json.merge(opts, options);\n\n if (!opts.container) {\n throw new Error('the options.container should not be null or empty.');\n }\n return opts;\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { logger } from './jsmind.common.js';\nexport class Node {\n /**\n * Create a Node instance.\n * @param {string} sId - Node id\n * @param {number} iIndex - Node index (order among siblings). Use -1 for tail\n * @param {string} sTopic - Node topic text\n * @param {Record<string, any>=} oData - Arbitrary node data\n * @param {boolean=} bIsRoot - Whether it is the root node\n * @param {Node | null=} oParent - Parent node\n * @param {number=} eDirection - Direction for children under root (-1 left, 0 center, 1 right)\n * @param {boolean=} bExpanded - Expanded state\n */\n constructor(sId, iIndex, sTopic, oData, bIsRoot, oParent, eDirection, bExpanded) {\n if (!sId) {\n logger.error('invalid node id');\n return;\n }\n if (typeof iIndex != 'number') {\n logger.error('invalid node index');\n return;\n }\n if (typeof bExpanded === 'undefined') {\n bExpanded = true;\n }\n this.id = sId;\n this.index = iIndex;\n this.topic = sTopic;\n /** @type {Record<string, any>} */\n this.data = oData || {};\n this.isroot = bIsRoot;\n this.parent = oParent;\n this.direction = eDirection;\n this.expanded = !!bExpanded;\n /** @type {Node[]} */\n this.children = [];\n this._data = {};\n }\n\n /**\n * Get absolute location of this node in view coordinates.\n * @returns {{x:number,y:number}}\n */\n get_location() {\n var vd = this._data.view;\n return {\n x: vd.abs_x,\n y: vd.abs_y,\n };\n }\n /**\n * Get rendered size of this node.\n * @returns {{w:number,h:number}}\n */\n get_size() {\n var vd = this._data.view;\n return {\n w: vd.width,\n h: vd.height,\n };\n }\n\n /**\n * Compare two nodes by index for ordering.\n * @param {Node} node1\n * @param {Node} node2\n * @returns {number}\n */\n static compare(node1, node2) {\n // '-1' is always the latest\n var r = 0;\n var i1 = node1.index;\n var i2 = node2.index;\n if (i1 >= 0 && i2 >= 0) {\n r = i1 - i2;\n } else if (i1 == -1 && i2 == -1) {\n r = 0;\n } else if (i1 == -1) {\n r = 1;\n } else if (i2 == -1) {\n r = -1;\n } else {\n r = 0;\n }\n return r;\n }\n /**\n * Check if node is the same as or a descendant of parent_node.\n * @param {Node} parent_node\n * @param {Node} node\n * @returns {boolean}\n */\n static inherited(parent_node, node) {\n if (!!parent_node && !!node) {\n if (parent_node.id === node.id) {\n return true;\n }\n if (parent_node.isroot) {\n return true;\n }\n var pid = parent_node.id;\n var p = node;\n while (!p.isroot) {\n p = p.parent;\n if (p.id === pid) {\n return true;\n }\n }\n }\n return false;\n }\n /**\n * Runtime check for Node instance.\n * @param {unknown} n\n * @returns {n is Node}\n */\n static is_node(n) {\n return !!n && n instanceof Node;\n }\n\n /**\n * Convert node to plain object with custom field names.\n * @param {Record<string,string>=} fieldNames - Field names mapping\n * @param {boolean=} includeChildren - Whether to include children nodes (default: false)\n * @returns {Record<string, any>} Plain object representation of node\n */\n toObject(fieldNames, includeChildren = false) {\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var childrenKey = fn.children || 'children';\n var directionKey = fn.direction || 'direction';\n var expandedKey = fn.expanded || 'expanded';\n\n var obj = {};\n obj[idKey] = this.id;\n obj[topicKey] = this.topic;\n obj[expandedKey] = this.expanded;\n\n // Add direction for nodes under root\n if (!!this.parent && this.parent.isroot) {\n obj[directionKey] = this.direction === -1 ? 'left' : 'right';\n }\n\n // Add custom data properties\n if (this.data != null) {\n for (var k in this.data) {\n obj[k] = this.data[k];\n }\n }\n\n // Add children if requested\n if (includeChildren && this.children.length > 0) {\n obj[childrenKey] = this.children.map(child => child.toObject(fieldNames, true));\n }\n\n return obj;\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { Node } from './jsmind.node.js';\nimport { logger, Direction } from './jsmind.common.js';\n\nexport class Mind {\n /**\n * Mind model: holds nodes and selection.\n */\n constructor() {\n /** @type {string | null} */\n this.name = null;\n /** @type {string | null} */\n this.author = null;\n /** @type {string | null} */\n this.version = null;\n /** @type {Node | null} */\n this.root = null;\n /** @type {Node | null} */\n this.selected = null;\n /** @type {Record<string, Node>} */\n this.nodes = {};\n }\n /**\n * Get a node by id.\n * @param {string} node_id\n * @returns {Node | null}\n */\n get_node(node_id) {\n if (node_id in this.nodes) {\n return this.nodes[node_id];\n } else {\n logger.warn('the node[id=' + node_id + '] can not be found');\n return null;\n }\n }\n /**\n * Set the root node, only once.\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @returns {Node | null}\n */\n set_root(node_id, topic, data) {\n if (this.root == null) {\n this.root = new Node(node_id, 0, topic, data, true);\n this._put_node(this.root);\n return this.root;\n } else {\n logger.error('root node is already exist');\n return null;\n }\n }\n /**\n * Add a child node under parent.\n * @param {Node} parent_node\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @param {boolean=} expanded\n * @param {number=} idx\n * @returns {Node | null}\n */\n add_node(parent_node, node_id, topic, data, direction, expanded, idx) {\n if (!Node.is_node(parent_node)) {\n logger.error('the parent_node ' + parent_node + ' is not a node.');\n return null;\n }\n var node_index = idx || -1;\n var node = new Node(\n node_id,\n node_index,\n topic,\n data,\n false,\n parent_node,\n parent_node.direction,\n expanded\n );\n if (parent_node.isroot) {\n node.direction = direction || Direction.right;\n }\n if (this._put_node(node)) {\n parent_node.children.push(node);\n this._update_index(parent_node);\n } else {\n logger.error(\"fail, the node id '\" + node.id + \"' has been already exist.\");\n node = null;\n }\n return node;\n }\n /**\n * Insert a node before target node.\n * @param {Node} node_before\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @returns {Node | null}\n */\n insert_node_before(node_before, node_id, topic, data, direction) {\n if (!Node.is_node(node_before)) {\n logger.error('the node_before ' + node_before + ' is not a node.');\n return null;\n }\n var node_index = node_before.index - 0.5;\n return this.add_node(node_before.parent, node_id, topic, data, direction, true, node_index);\n }\n /**\n * Get previous sibling of a node or node id.\n * @param {string | Node} node\n * @returns {Node | null}\n */\n get_node_before(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return null;\n } else {\n return this.get_node_before(the_node);\n }\n }\n if (node.isroot) {\n return null;\n }\n var idx = node.index - 2;\n if (idx >= 0) {\n return node.parent.children[idx];\n } else {\n return null;\n }\n }\n /**\n * Insert a node after target node.\n * @param {Node} node_after\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @returns {Node | null}\n */\n insert_node_after(node_after, node_id, topic, data, direction) {\n if (!Node.is_node(node_after)) {\n logger.error('the node_after ' + node_after + ' is not a node.');\n return null;\n }\n var node_index = node_after.index + 0.5;\n return this.add_node(node_after.parent, node_id, topic, data, direction, true, node_index);\n }\n /**\n * Get next sibling of a node or node id.\n * @param {string | Node} node\n * @returns {Node | null}\n */\n get_node_after(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return null;\n } else {\n return this.get_node_after(the_node);\n }\n }\n if (node.isroot) {\n return null;\n }\n var idx = node.index;\n var brothers = node.parent.children;\n if (brothers.length > idx) {\n return node.parent.children[idx];\n } else {\n return null;\n }\n }\n /**\n * Move a node to new parent/position.\n * @param {Node} node\n * @param {string=} before_id - The ID of the node before which to place the moved node. Special values: \"_first_\", \"_last_\"\n * @param {string=} parent_id\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @returns {Node | null}\n */\n move_node(node, before_id, parent_id, direction) {\n if (!Node.is_node(node)) {\n logger.error('the parameter node ' + node + ' is not a node.');\n return null;\n }\n if (!parent_id) {\n parent_id = node.parent.id;\n }\n return this._move_node(node, before_id, parent_id, direction);\n }\n /**\n * Propagate direction to descendants.\n * @param {Node} node\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n */\n _flow_node_direction(node, direction) {\n if (typeof direction === 'undefined') {\n direction = node.direction;\n } else {\n node.direction = direction;\n }\n var len = node.children.length;\n while (len--) {\n this._flow_node_direction(node.children[len], direction);\n }\n }\n /**\n * Re-index node among siblings based on before_id marker.\n * @param {Node} node\n * @param {string} before_id\n * @returns {Node}\n */\n _move_node_internal(node, before_id) {\n if (!!node && !!before_id) {\n if (before_id == '_last_') {\n node.index = -1;\n this._update_index(node.parent);\n } else if (before_id == '_first_') {\n node.index = 0;\n this._update_index(node.parent);\n } else {\n var node_before = !!before_id ? this.get_node(before_id) : null;\n if (\n node_before != null &&\n node_before.parent != null &&\n node_before.parent.id == node.parent.id\n ) {\n node.index = node_before.index - 0.5;\n this._update_index(node.parent);\n }\n }\n }\n return node;\n }\n /**\n * Internal move implementation.\n * @param {Node} node\n * @param {string} before_id\n * @param {string} parent_id\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @returns {Node | null}\n */\n _move_node(node, before_id, parent_id, direction) {\n if (!!node && !!parent_id) {\n var parent_node = this.get_node(parent_id);\n if (Node.inherited(node, parent_node)) {\n logger.error('can not move a node to its children');\n return null;\n }\n if (node.parent.id != parent_id) {\n // remove from parent's children\n var sibling = node.parent.children;\n var si = sibling.length;\n while (si--) {\n if (sibling[si].id == node.id) {\n sibling.splice(si, 1);\n break;\n }\n }\n let origin_parent = node.parent;\n node.parent = parent_node;\n parent_node.children.push(node);\n this._update_index(origin_parent);\n }\n\n if (node.parent.isroot) {\n if (direction == Direction.left) {\n node.direction = direction;\n } else {\n node.direction = Direction.right;\n }\n } else {\n node.direction = node.parent.direction;\n }\n this._move_node_internal(node, before_id);\n this._flow_node_direction(node);\n }\n return node;\n }\n /**\n * Remove a node from the mind.\n * @param {Node} node\n * @returns {boolean}\n */\n remove_node(node) {\n if (!Node.is_node(node)) {\n logger.error('the parameter node ' + node + ' is not a node.');\n return false;\n }\n if (node.isroot) {\n logger.error('fail, can not remove root node');\n return false;\n }\n if (this.selected != null && this.selected.id == node.id) {\n this.selected = null;\n }\n // clean all subordinate nodes\n var children = node.children;\n var ci = children.length;\n while (ci--) {\n this.remove_node(children[ci]);\n }\n // clean all children\n children.length = 0;\n var node_parent = node.parent;\n // remove from parent's children\n var sibling = node_parent.children;\n var si = sibling.length;\n while (si--) {\n if (sibling[si].id == node.id) {\n sibling.splice(si, 1);\n break;\n }\n }\n // remove from global nodes\n delete this.nodes[node.id];\n // clean all properties\n for (var k in node) {\n delete node[k];\n }\n // remove it's self\n node = null;\n this._update_index(node_parent);\n return true;\n }\n /**\n * Put node into the map if id is not taken.\n * @param {Node} node\n * @returns {boolean}\n */\n _put_node(node) {\n if (node.id in this.nodes) {\n logger.warn(\"the node_id '\" + node.id + \"' has been already exist.\");\n return false;\n } else {\n this.nodes[node.id] = node;\n return true;\n }\n }\n /**\n * Re-index children by Node.compare.\n * @param {Node} node\n */\n _update_index(node) {\n if (node instanceof Node) {\n node.children.sort(Node.compare);\n for (var i = 0; i < node.children.length; i++) {\n node.children[i].index = i + 1;\n }\n }\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { __author__, __version__, logger, Direction } from './jsmind.common.js';\nimport { Mind } from './jsmind.mind.js';\nimport { Node } from './jsmind.node.js';\nimport { util } from './jsmind.util.js';\n\n/** @typedef {{name:string,author:string,version:string}} MindMapMeta */\n/**\n * Node tree data item\n *\n * Note: When using custom fieldNames configuration, the actual property names\n * in your data may differ from these type definitions. For example, if you\n * configure `fieldNames: { topic: 'name' }`, your data should use 'name'\n * instead of 'topic'. The types shown here represent the default field names.\n *\n * @typedef {{\n * id?: string,\n * topic?: string,\n * data?: Record<string, any>,\n * direction?: (number|string),\n * expanded?: boolean,\n * children?: NodeTreeData[],\n * [key: string]: any\n * }} NodeTreeData\n */\n/**\n * Node tree formatted payload\n * @typedef {{\n * meta?: MindMapMeta,\n * format: 'node_tree',\n * data: NodeTreeData\n * }} NodeTreeFormat\n */\n/**\n * Node array data item\n *\n * Note: When using custom fieldNames configuration, the actual property names\n * in your data may differ from these type definitions. For example, if you\n * configure `fieldNames: { topic: 'name', parentid: 'parent' }`, your data\n * should use 'name' and 'parent' instead of 'topic' and 'parentid'. The types\n * shown here represent the default field names.\n *\n * @typedef {{\n * id?: string,\n * topic?: string,\n * parentid?: string,\n * data?: Record<string, any>,\n * direction?: (number|string),\n * expanded?: boolean,\n * isroot?: boolean,\n * [key: string]: any\n * }} NodeArrayItem\n */\n/**\n * Node array formatted payload\n * @typedef {{\n * meta?: MindMapMeta,\n * format: 'node_array',\n * data: NodeArrayItem[]\n * }} NodeArrayFormat\n */\n/** @type {MindMapMeta} */\nconst DEFAULT_META = { name: 'jsMind', author: __author__, version: __version__ };\n\n/**\n * Mind data format handlers.\n * @type {{\n * node_tree: { example:NodeTreeFormat, get_mind:(src:NodeTreeFormat)=>Mind, get_data:(mind:Mind)=>NodeTreeFormat },\n * node_array: { example:NodeArrayFormat, get_mind:(src:NodeArrayFormat)=>Mind, get_data:(mind:Mind)=>NodeArrayFormat },\n * freemind: { example:{meta:MindMapMeta,format:'freemind',data:string}, get_mind:(src:{meta?:MindMapMeta,format:'freemind',data:string})=>Mind, get_data:(mind:Mind)=>{meta:MindMapMeta,format:'freemind',data:string} },\n * text: { example:{meta:MindMapMeta,format:'text',data:string}, get_mind:(src:{meta?:MindMapMeta,format:'text',data:string})=>Mind, get_data:(mind:Mind)=>{meta:MindMapMeta,format:'text',data:string} }\n * }}\n */\nexport const format = {\n node_tree: {\n example: {\n meta: DEFAULT_META,\n format: 'node_tree',\n data: { id: 'root', topic: 'jsMind node_tree example' },\n },\n /** @param {NodeTreeFormat} source @param {Record<string,string>=} fieldNames @returns {Mind} */\n get_mind: function (source, fieldNames) {\n var df = format.node_tree;\n var mind = new Mind();\n mind.name = source.meta.name;\n mind.author = source.meta.author;\n mind.version = source.meta.version;\n df._parse(mind, source.data, fieldNames);\n return mind;\n },\n /** @param {Mind} mind @param {Record<string,string>=} fieldNames */\n get_data: function (mind, fieldNames) {\n var df = format.node_tree;\n var json = {};\n json.meta = {\n name: mind.name,\n author: mind.author,\n version: mind.version,\n };\n json.format = 'node_tree';\n json.data = df._build_node(mind.root, fieldNames);\n return json;\n },\n\n /** @param {Mind} mind @param {NodeTreeData} node_root @param {Record<string,string>=} fieldNames */\n _parse: function (mind, node_root, fieldNames) {\n var df = format.node_tree;\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var childrenKey = fn.children || 'children';\n\n var data = df._extract_data(node_root, fieldNames);\n mind.set_root(node_root[idKey], node_root[topicKey], data);\n if (childrenKey in node_root) {\n var children = node_root[childrenKey];\n for (var i = 0; i < children.length; i++) {\n df._extract_subnode(mind, mind.root, children[i], fieldNames);\n }\n }\n },\n\n /**\n * Extract custom data from node JSON, excluding standard properties.\n * @private\n * @param {Record<string, unknown>} node_json - Node JSON object\n * @param {Record<string,string>=} fieldNames - Field names mapping\n * @returns {Record<string,any>} Custom data object\n */\n _extract_data: function (node_json, fieldNames) {\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var childrenKey = fn.children || 'children';\n var directionKey = fn.direction || 'direction';\n var expandedKey = fn.expanded || 'expanded';\n\n var data = {};\n for (var k in node_json) {\n if (\n k == idKey ||\n k == topicKey ||\n k == childrenKey ||\n k == directionKey ||\n k == expandedKey\n ) {\n continue;\n }\n data[k] = node_json[k];\n }\n return data;\n },\n\n /** @param {Mind} mind @param {Node} node_parent @param {NodeTreeData} node_json @param {Record<string,string>=} fieldNames */\n _extract_subnode: function (mind, node_parent, node_json, fieldNames) {\n var df = format.node_tree;\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var childrenKey = fn.children || 'children';\n var directionKey = fn.direction || 'direction';\n var expandedKey = fn.expanded || 'expanded';\n\n var data = df._extract_data(node_json, fieldNames);\n var d = null;\n if (node_parent.isroot) {\n d = node_json[directionKey] == 'left' ? Direction.left : Direction.right;\n }\n var node = mind.add_node(\n node_parent,\n node_json[idKey],\n node_json[topicKey],\n data,\n d,\n node_json[expandedKey]\n );\n if (!!node_json[childrenKey]) {\n var children = node_json[childrenKey];\n for (var i = 0; i < children.length; i++) {\n df._extract_subnode(mind, node, children[i], fieldNames);\n }\n }\n },\n\n /**\n * Build JSON object from a node.\n * @private\n * @param {Node} node - Node to convert\n * @param {Record<string,string>=} fieldNames - Field names mapping\n * @returns {NodeTreeData} JSON representation of node\n */\n _build_node: function (node, fieldNames) {\n var df = format.node_tree;\n if (!(node instanceof Node)) {\n return;\n }\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var childrenKey = fn.children || 'children';\n var directionKey = fn.direction || 'direction';\n var expandedKey = fn.expanded || 'expanded';\n\n var o = {};\n o[idKey] = node.id;\n o[topicKey] = node.topic;\n o[expandedKey] = node.expanded;\n\n if (!!node.parent && node.parent.isroot) {\n o[directionKey] = node.direction == Direction.left ? 'left' : 'right';\n }\n if (node.data != null) {\n var node_data = node.data;\n for (var k in node_data) {\n o[k] = node_data[k];\n }\n }\n var children = node.children;\n if (children.length > 0) {\n o[childrenKey] = [];\n for (var i = 0; i < children.length; i++) {\n o[childrenKey].push(df._build_node(children[i], fieldNames));\n }\n }\n return o;\n },\n },\n\n node_array: {\n example: {\n meta: DEFAULT_META,\n format: 'node_array',\n data: [{ id: 'root', topic: 'jsMind node_array example', isroot: true }],\n },\n\n /** @param {NodeArrayFormat} source @param {Record<string,string>=} fieldNames @returns {Mind} */\n get_mind: function (source, fieldNames) {\n var df = format.node_array;\n var mind = new Mind();\n mind.name = source.meta.name;\n mind.author = source.meta.author;\n mind.version = source.meta.version;\n df._parse(mind, source.data, fieldNames);\n return mind;\n },\n\n /** @param {Mind} mind @param {Record<string,string>=} fieldNames */\n get_data: function (mind, fieldNames) {\n var df = format.node_array;\n var json = {};\n json.meta = {\n name: mind.name,\n author: mind.author,\n version: mind.version,\n };\n json.format = 'node_array';\n json.data = [];\n df._array(mind, json.data, fieldNames);\n return json;\n },\n\n /** @param {Mind} mind @param {NodeArrayItem[]} node_array @param {Record<string,string>=} fieldNames */\n _parse: function (mind, node_array, fieldNames) {\n var df = format.node_array;\n var nodes = node_array.slice(0);\n // reverse array for improving looping performance\n nodes.reverse();\n var root_node = df._extract_root(mind, nodes, fieldNames);\n if (!!root_node) {\n df._extract_subnode(mind, root_node, nodes, fieldNames);\n } else {\n logger.error('root node can not be found');\n }\n },\n\n /** @param {Mind} mind @param {NodeArrayItem[]} node_array @param {Record<string,string>=} fieldNames */\n _extract_root: function (mind, node_array, fieldNames) {\n var df = format.node_array;\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var isrootKey = fn.isroot || 'isroot';\n\n var i = node_array.length;\n while (i--) {\n if (isrootKey in node_array[i] && node_array[i][isrootKey]) {\n var root_json = node_array[i];\n var data = df._extract_data(root_json, fieldNames);\n var node = mind.set_root(root_json[idKey], root_json[topicKey], data);\n node_array.splice(i, 1);\n return node;\n }\n }\n return null;\n },\n\n /** @param {Mind} mind @param {Node} parent_node @param {NodeArrayItem[]} node_array @param {Record<string,string>=} fieldNames */\n _extract_subnode: function (mind, parent_node, node_array, fieldNames) {\n var df = format.node_array;\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var parentidKey = fn.parentid || 'parentid';\n var directionKey = fn.direction || 'direction';\n var expandedKey = fn.expanded || 'expanded';\n\n var i = node_array.length;\n var node_json = null;\n var data = null;\n var extract_count = 0;\n while (i--) {\n node_json = node_array[i];\n if (node_json[parentidKey] == parent_node.id) {\n data = df._extract_data(node_json, fieldNames);\n var d = null;\n var node_direction = node_json[directionKey];\n if (!!node_direction) {\n d = node_direction == 'left' ? Direction.left : Direction.right;\n }\n var node = mind.add_node(\n parent_node,\n node_json[idKey],\n node_json[topicKey],\n data,\n d,\n node_json[expandedKey]\n );\n node_array.splice(i, 1);\n extract_count++;\n var sub_extract_count = df._extract_subnode(mind, node, node_array, fieldNames);\n if (sub_extract_count > 0) {\n // reset loop index after extract subordinate node\n i = node_array.length;\n extract_count += sub_extract_count;\n }\n }\n }\n return extract_count;\n },\n\n /** @param {Record<string, unknown>} node_json @param {Record<string,string>=} fieldNames */\n _extract_data: function (node_json, fieldNames) {\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var parentidKey = fn.parentid || 'parentid';\n var isrootKey = fn.isroot || 'isroot';\n var directionKey = fn.direction || 'direction';\n var expandedKey = fn.expanded || 'expanded';\n\n var data = {};\n for (var k in node_json) {\n if (\n k == idKey ||\n k == topicKey ||\n k == parentidKey ||\n k == isrootKey ||\n k == directionKey ||\n k == expandedKey\n ) {\n continue;\n }\n data[k] = node_json[k];\n }\n return data;\n },\n\n /** @param {Mind} mind @param {NodeArrayItem[]} node_array @param {Record<string,string>=} fieldNames */\n _array: function (mind, node_array, fieldNames) {\n var df = format.node_array;\n df._array_node(mind.root, node_array, fieldNames);\n },\n\n /** @param {Node} node @param {NodeArrayItem[]} node_array @param {Record<string,string>=} fieldNames */\n _array_node: function (node, node_array, fieldNames) {\n var df = format.node_array;\n if (!(node instanceof Node)) {\n return;\n }\n var fn = fieldNames || {};\n var idKey = fn.id || 'id';\n var topicKey = fn.topic || 'topic';\n var parentidKey = fn.parentid || 'parentid';\n var isrootKey = fn.isroot || 'isroot';\n var directionKey = fn.direction || 'direction';\n var expandedKey = fn.expanded || 'expanded';\n\n var o = {};\n o[idKey] = node.id;\n o[topicKey] = node.topic;\n o[expandedKey] = node.expanded;\n\n if (!!node.parent) {\n o[parentidKey] = node.parent.id;\n }\n if (node.isroot) {\n o[isrootKey] = true;\n }\n if (!!node.parent && node.parent.isroot) {\n o[directionKey] = node.direction == Direction.left ? 'left' : 'right';\n }\n if (node.data != null) {\n var node_data = node.data;\n for (var k in node_data) {\n o[k] = node_data[k];\n }\n }\n node_array.push(o);\n var ci = node.children.length;\n for (var i = 0; i < ci; i++) {\n df._array_node(node.children[i], node_array, fieldNames);\n }\n },\n },\n\n freemind: {\n example: {\n meta: DEFAULT_META,\n format: 'freemind',\n data: '<map version=\"1.0.1\"><node ID=\"root\" TEXT=\"jsMind freemind example\"/></map>',\n },\n /** @param {{meta:MindMapMeta,data:string}} source @param {Record<string,string>=} fieldNames @returns {Mind} */\n get_mind: function (source, fieldNames) {\n var df = format.freemind;\n var mind = new Mind();\n mind.name = source.meta.name;\n mind.author = source.meta.author;\n mind.version = source.meta.version;\n var xml = source.data;\n var xml_doc = df._parse_xml(xml);\n var xml_root = df._find_root(xml_doc);\n // freemind format uses fixed XML attributes (ID, TEXT), fieldNames not applicable\n df._load_node(mind, null, xml_root);\n return mind;\n },\n\n /** @param {Mind} mind @param {Record<string,string>=} fieldNames */\n get_data: function (mind, fieldNames) {\n var df = format.freemind;\n var json = {};\n json.meta = {\n name: mind.name,\n author: mind.author,\n version: mind.version,\n };\n json.format = 'freemind';\n var xml_lines = [];\n xml_lines.push('<map version=\"1.0.1\">');\n // freemind format uses fixed XML attributes, fieldNames not applicable\n df._build_map(mind.root, xml_lines);\n xml_lines.push('</map>');\n json.data = xml_lines.join('');\n return json;\n },\n\n /** @param {string} xml */\n _parse_xml: function (xml) {\n var xml_doc = null;\n if (window.DOMParser) {\n var parser = new DOMParser();\n xml_doc = parser.parseFromString(xml, 'text/xml');\n } else {\n // Internet Explorer\n xml_doc = new ActiveXObject('Microsoft.XMLDOM');\n xml_doc.async = false;\n xml_doc.loadXML(xml);\n }\n return xml_doc;\n },\n\n /** @param {Document} xml_doc */\n _find_root: function (xml_doc) {\n var nodes = xml_doc.childNodes;\n var node = null;\n var root = null;\n var n = null;\n for (var i = 0; i < nodes.length; i++) {\n n = nodes[i];\n if (n.nodeType == 1 && n.tagName == 'map') {\n node = n;\n break;\n }\n }\n if (!!node) {\n var ns = node.childNodes;\n node = null;\n for (var i = 0; i < ns.length; i++) {\n n = ns[i];\n if (n.nodeType == 1 && n.tagName == 'node') {\n node = n;\n break;\n }\n }\n }\n return node;\n },\n\n /** @param {Mind} mind @param {Node|null} parent_node @param {Element} xml_node */\n _load_node: function (mind, parent_node, xml_node) {\n var df = format.freemind;\n var node_id = xml_node.getAttribute('ID');\n var node_topic = xml_node.getAttribute('TEXT');\n var node_folded = xml_node.getAttribute('FOLDED');\n // look for richcontent\n if (node_topic == null) {\n var topic_children = xml_node.childNodes;\n var topic_child = null;\n for (var i = 0; i < topic_children.length; i++) {\n topic_child = topic_children[i];\n if (topic_child.nodeType == 1 && topic_child.tagName === 'richcontent') {\n node_topic = topic_child.textContent;\n break;\n }\n }\n }\n var node_data = df._load_attributes(xml_node);\n var node_expanded =\n 'expanded' in node_data ? node_data.expanded == 'true' : node_folded != 'true';\n delete node_data.expanded;\n\n var node_foreground_color = xml_node.getAttribute('COLOR');\n if (!!node_foreground_color) {\n node_data['foreground-color'] = node_foreground_color;\n }\n\n var node_background_color = xml_node.getAttribute('BACKGROUND_COLOR');\n if (!!node_background_color) {\n node_data['background-color'] = node_background_color;\n }\n\n var node_position = xml_node.getAttribute('POSITION');\n var node_direction = null;\n if (!!node_position) {\n node_direction = node_position == 'left' ? Direction.left : Direction.right;\n }\n var node = null;\n if (!!parent_node) {\n node = mind.add_node(\n parent_node,\n node_id,\n node_topic,\n node_data,\n node_direction,\n node_expanded\n );\n } else {\n node = mind.set_root(node_id, node_topic, node_data);\n }\n var children = xml_node.childNodes;\n var child = null;\n for (var i = 0; i < children.length; i++) {\n child = children[i];\n if (child.nodeType == 1 && child.tagName == 'node') {\n df._load_node(mind, node, child);\n }\n }\n },\n\n /** @param {Element} xml_node */\n _load_attributes: function (xml_node) {\n var children = xml_node.childNodes;\n var attr = null;\n var attr_data = {};\n for (var i = 0; i < children.length; i++) {\n attr = children[i];\n if (attr.nodeType == 1 && attr.tagName === 'attribute') {\n attr_data[attr.getAttribute('NAME')] = attr.getAttribute('VALUE');\n }\n }\n return attr_data;\n },\n\n /** @param {Node} node @param {string[]} xml_lines */\n _build_map: function (node, xml_lines) {\n var df = format.freemind;\n var pos = null;\n var node_data = node.data;\n\n if (!!node.parent && node.parent.isroot) {\n pos = node.direction === Direction.left ? 'left' : 'right';\n }\n xml_lines.push('<node');\n xml_lines.push(' ID=\"' + node.id + '\"');\n if (!!pos) {\n xml_lines.push(' POSITION=\"' + pos + '\"');\n }\n if (!node.expanded) {\n xml_lines.push(' FOLDED=\"true\"');\n }\n if (!!node_data['foreground-color']) {\n xml_lines.push(' COLOR=\"' + node_data['foreground-color'] + '\"');\n }\n if (!!node_data['background-color']) {\n xml_lines.push(' BACKGROUND_COLOR=\"' + node_data['background-color'] + '\"');\n }\n xml_lines.push(' TEXT=\"' + df._escape(node.topic) + '\">');\n\n // for attributes\n if (node_data != null) {\n for (var k in node_data) {\n if (k === 'foreground-color' || k === 'background-color') {\n continue;\n }\n xml_lines.push('<attribute NAME=\"' + k + '\" VALUE=\"' + node_data[k] + '\"/>');\n }\n }\n\n // for children\n var children = node.children;\n for (var i = 0; i < children.length; i++) {\n df._build_map(children[i], xml_lines);\n }\n\n xml_lines.push('</node>');\n },\n\n /** @param {string} text */\n _escape: function (text) {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/'/g, '&apos;')\n .replace(/\"/g, '&quot;');\n },\n },\n text: {\n example: {\n meta: DEFAULT_META,\n format: 'text',\n data: 'jsMind text example\\n node1\\n node1-sub\\n node1-sub\\n node2',\n },\n _line_regex: /\\s*/,\n /** @param {{meta:MindMapMeta,data:string}} source @param {Record<string,string>=} fieldNames @returns {Mind} */\n get_mind: function (source, fieldNames) {\n var df = format.text;\n var mind = new Mind();\n mind.name = source.meta.name;\n mind.author = source.meta.author;\n mind.version = source.meta.version;\n var lines = source.data.split(/\\n|\\r/);\n // text format uses indentation-based structure, fieldNames not applicable\n df._fill_nodes(mind, lines, 0, 0);\n return mind;\n },\n\n /** @param {Mind} mind @param {string[]} lines */\n _fill_nodes: function (mind, lines) {\n let node_path = [];\n let i = 0;\n while (i < lines.length) {\n let line = lines[i];\n let level = line.match(/\\s*/)[0].length;\n let topic = line.substr(level);\n\n if (level == 0 && node_path.length > 0) {\n log.error('more than 1 root node was found: ' + topic);\n return;\n }\n if (level > node_path.length) {\n log.error('a suspended node was found: ' + topic);\n return;\n }\n let diff = node_path.length - level;\n while (diff--) {\n node_path.pop();\n }\n\n if (level == 0 && node_path.length == 0) {\n let node = mind.set_root(util.uuid.newid(), topic);\n node_path.push(node);\n } else {\n let node = mind.add_node(\n node_path[level - 1],\n util.uuid.newid(),\n topic,\n {},\n null\n );\n node_path.push(node);\n }\n i++;\n }\n node_path.length = 0;\n },\n\n /** @param {Mind} mind */\n get_data: function (mind) {\n var df = format.text;\n var json = {};\n json.meta = {\n name: mind.name,\n author: mind.author,\n version: mind.version,\n };\n json.format = 'text';\n let lines = [];\n df._build_lines(lines, [mind.root], 0);\n json.data = lines.join('\\n');\n return json;\n },\n\n /** @param {string[]} lines @param {Node[]} nodes @param {number} level */\n _build_lines: function (lines, nodes, level) {\n let prefix = new Array(level + 1).join(' ');\n for (let node of nodes) {\n lines.push(prefix + node.topic);\n if (!!node.children) {\n format.text._build_lines(lines, node.children, level + 1);\n }\n }\n },\n },\n};\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { logger } from './jsmind.common.js';\nimport { format } from './jsmind.format.js';\n\nexport class DataProvider {\n /**\n * Data provider: loads and serializes mind data by format.\n * @param {import('./jsmind.js').default} jm - jsMind instance\n */\n constructor(jm) {\n this.jm = jm;\n }\n\n /** Initialize data provider. */\n init() {\n logger.debug('data.init');\n }\n /** Reset data provider state. */\n reset() {\n logger.debug('data.reset');\n }\n /**\n * Load a Mind from mixed source.\n * @param {import('./jsmind.format.js').NodeTreeFormat|import('./jsmind.format.js').NodeArrayFormat|{meta?:{name:string,author:string,version:string},format:'freemind',data:string}|{meta?:{name:string,author:string,version:string},format:'text',data:string}} mind_data - object with {format,data} or a format-specific payload\n * @returns {import('./jsmind.mind.js').Mind|null}\n */\n load(mind_data) {\n var df = null;\n var mind = null;\n if (typeof mind_data === 'object') {\n if (!!mind_data.format) {\n df = mind_data.format;\n } else {\n df = 'node_tree';\n }\n } else {\n df = 'freemind';\n }\n\n var fieldNames = this.jm.options.fieldNames;\n if (df == 'node_array') {\n mind = format.node_array.get_mind(mind_data, fieldNames);\n } else if (df == 'node_tree') {\n mind = format.node_tree.get_mind(mind_data, fieldNames);\n } else if (df == 'freemind') {\n mind = format.freemind.get_mind(mind_data, fieldNames);\n } else if (df == 'text') {\n mind = format.text.get_mind(mind_data, fieldNames);\n } else {\n logger.warn('unsupported format');\n }\n return mind;\n }\n /**\n * Serialize current mind to target format.\n * @param {'node_tree'|'node_array'|'freemind'|'text'} data_format\n * @returns {import('./jsmind.format.js').NodeTreeFormat|import('./jsmind.format.js').NodeArrayFormat|{meta:{name:string,author:string,version:string},format:'freemind',data:string}|{meta:{name:string,author:string,version:string},format:'text',data:string}}\n */\n get_data(data_format) {\n var data = null;\n var fieldNames = this.jm.options.fieldNames;\n if (data_format == 'node_array') {\n data = format.node_array.get_data(this.jm.mind, fieldNames);\n } else if (data_format == 'node_tree') {\n data = format.node_tree.get_data(this.jm.mind, fieldNames);\n } else if (data_format == 'freemind') {\n data = format.freemind.get_data(this.jm.mind);\n } else if (data_format == 'text') {\n data = format.text.get_data(this.jm.mind);\n } else {\n logger.error('unsupported ' + data_format + ' format');\n }\n return data;\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\nimport { logger, Direction, EventType } from './jsmind.common.js';\n\nexport class LayoutProvider {\n /**\n * Layout engine for positioning nodes and lines.\n * @param {import('./jsmind.js').default} jm - jsMind instance\n * @param {{mode:'full'|'side', hspace:number, vspace:number, pspace:number, cousin_space:number}} options - Layout configuration options\n */\n constructor(jm, options) {\n this.opts = options;\n this.jm = jm;\n this.isside = this.opts.mode == 'side';\n this.bounds = null;\n\n this.cache_valid = false;\n }\n /** Initialize layout provider. */\n init() {\n logger.debug('layout.init');\n }\n /** Reset layout state and bounds. */\n reset() {\n logger.debug('layout.reset');\n this.bounds = { n: 0, s: 0, w: 0, e: 0 };\n }\n /**\n * Decide the next child's direction for a parent node.\n * @param {import('./jsmind.node.js').Node} node\n * @returns {number}\n */\n calculate_next_child_direction(node) {\n if (this.isside) {\n return Direction.right;\n }\n var children = node.children || [];\n var children_len = children.length;\n var r = 0;\n for (var i = 0; i < children_len; i++) {\n if (children[i].direction === Direction.left) {\n r--;\n } else {\n r++;\n }\n }\n return children_len > 1 && r > 0 ? Direction.left : Direction.right;\n }\n /** Perform layout and offsets recalculation. */\n layout() {\n logger.debug('layout.layout');\n this.layout_direction();\n this.layout_offset();\n }\n /** Calculate and set direction for all nodes. */\n layout_direction() {\n this._layout_direction_root();\n }\n /**\n * Set direction layout for root node and its children.\n * @private\n */\n _layout_direction_root() {\n var node = this.jm.mind.root;\n var layout_data = null;\n if ('layout' in node._data) {\n layout_data = node._data.layout;\n } else {\n layout_data = {};\n node._data.layout = layout_data;\n }\n var children = node.children;\n var children_count = children.length;\n layout_data.direction = Direction.center;\n layout_data.side_index = 0;\n if (this.isside) {\n var i = children_count;\n while (i--) {\n this._layout_direction_side(children[i], Direction.right, i);\n }\n } else {\n var i = children_count;\n var subnode = null;\n while (i--) {\n subnode = children[i];\n if (subnode.direction == Direction.left) {\n this._layout_direction_side(subnode, Direction.left, i);\n } else {\n this._layout_direction_side(subnode, Direction.right, i);\n }\n }\n }\n }\n /**\n * Set direction layout for a node and its descendants.\n * @private\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @param {number} direction - Direction constant (-1, 0, 1)\n * @param {number} side_index - Index among siblings\n */\n _layout_direction_side(node, direction, side_index) {\n var layout_data = null;\n if ('layout' in node._data) {\n layout_data = node._data.layout;\n } else {\n layout_data = {};\n node._data.layout = layout_data;\n }\n var children = node.children;\n var children_count = children.length;\n\n layout_data.direction = direction;\n layout_data.side_index = side_index;\n var i = children_count;\n while (i--) {\n this._layout_direction_side(children[i], direction, i);\n }\n }\n /** Calculate and set position offsets for all nodes. */\n layout_offset() {\n var node = this.jm.mind.root;\n var layout_data = node._data.layout;\n layout_data.offset_x = 0;\n layout_data.offset_y = 0;\n layout_data.outer_height = 0;\n var children = node.children;\n var i = children.length;\n var left_nodes = [];\n var right_nodes = [];\n var subnode = null;\n while (i--) {\n subnode = children[i];\n if (subnode._data.layout.direction == Direction.right) {\n right_nodes.unshift(subnode);\n } else {\n left_nodes.unshift(subnode);\n }\n }\n layout_data.left_nodes = left_nodes;\n layout_data.right_nodes = right_nodes;\n layout_data.outer_height_left = this._layout_offset_subnodes(left_nodes);\n layout_data.outer_height_right = this._layout_offset_subnodes(right_nodes);\n this.bounds.e = node._data.view.width / 2;\n this.bounds.w = 0 - this.bounds.e;\n this.bounds.n = 0;\n this.bounds.s = Math.max(layout_data.outer_height_left, layout_data.outer_height_right);\n }\n /**\n * Layout both the x and y axis for subnodes.\n * @private\n * @param {import('./jsmind.node.js').Node[]} nodes - Array of nodes to layout\n * @returns {number} Total height of all nodes\n */\n _layout_offset_subnodes(nodes) {\n var total_height = 0;\n var nodes_count = nodes.length;\n var i = nodes_count;\n var node = null;\n var node_outer_height = 0;\n var layout_data = null;\n var base_y = 0;\n var pd = null; // parent._data\n while (i--) {\n node = nodes[i];\n layout_data = node._data.layout;\n if (pd == null) {\n pd = node.parent._data;\n }\n\n node_outer_height = this._layout_offset_subnodes(node.children);\n if (!node.expanded) {\n node_outer_height = 0;\n this.set_visible(node.children, false);\n }\n node_outer_height = Math.max(node._data.view.height, node_outer_height);\n\n if (this._should_reserve_cousin_space(node)) {\n node_outer_height += this.opts.cousin_space;\n }\n\n layout_data.outer_height = node_outer_height;\n layout_data.offset_y = base_y - node_outer_height / 2;\n layout_data.offset_x =\n this.opts.hspace * layout_data.direction +\n (pd.view.width * (pd.layout.direction + layout_data.direction)) / 2;\n if (!node.parent.isroot) {\n layout_data.offset_x += this.opts.pspace * layout_data.direction;\n }\n\n base_y = base_y - node_outer_height - this.opts.vspace;\n total_height += node_outer_height;\n }\n if (nodes_count > 1) {\n total_height += this.opts.vspace * (nodes_count - 1);\n }\n i = nodes_count;\n var middle_height = total_height / 2;\n while (i--) {\n node = nodes[i];\n node._data.layout.offset_y += middle_height;\n }\n return total_height;\n }\n /**\n * Layout the y axis only, for collapse/expand a node.\n * @private\n * @param {import('./jsmind.node.js').Node[]} nodes - Array of nodes to layout\n * @returns {number} Total height of all nodes\n */\n _layout_offset_subnodes_height(nodes) {\n var total_height = 0;\n var nodes_count = nodes.length;\n var i = nodes_count;\n var node = null;\n var node_outer_height = 0;\n var layout_data = null;\n var base_y = 0;\n var pd = null; // parent._data\n while (i--) {\n node = nodes[i];\n layout_data = node._data.layout;\n if (pd == null) {\n pd = node.parent._data;\n }\n\n node_outer_height = this._layout_offset_subnodes_height(node.children);\n if (!node.expanded) {\n node_outer_height = 0;\n }\n node_outer_height = Math.max(node._data.view.height, node_outer_height);\n if (this._should_reserve_cousin_space(node)) {\n node_outer_height += this.opts.cousin_space;\n }\n\n layout_data.outer_height = node_outer_height;\n layout_data.offset_y = base_y - node_outer_height / 2;\n base_y = base_y - node_outer_height - this.opts.vspace;\n total_height += node_outer_height;\n }\n if (nodes_count > 1) {\n total_height += this.opts.vspace * (nodes_count - 1);\n }\n i = nodes_count;\n var middle_height = total_height / 2;\n while (i--) {\n node = nodes[i];\n node._data.layout.offset_y += middle_height;\n }\n return total_height;\n }\n /**\n * Check if node should reserve cousin space.\n * @private\n * @param {import('./jsmind.node.js').Node} node - Node to check\n * @returns {boolean} True if cousin space should be reserved\n */\n _should_reserve_cousin_space(node) {\n return node.children.length > 0 && node.parent.children.length > 1;\n }\n /**\n * Get absolute offset for a node.\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @returns {{x:number, y:number}} Absolute position offset\n */\n get_node_offset(node) {\n var layout_data = node._data.layout;\n var offset_cache = null;\n if ('_offset_' in layout_data && this.cache_valid) {\n offset_cache = layout_data._offset_;\n } else {\n offset_cache = { x: -1, y: -1 };\n layout_data._offset_ = offset_cache;\n }\n if (offset_cache.x == -1 || offset_cache.y == -1) {\n var x = layout_data.offset_x;\n var y = layout_data.offset_y;\n if (!node.isroot) {\n var offset_p = this.get_node_offset(node.parent);\n x += offset_p.x;\n y += offset_p.y;\n }\n offset_cache.x = x;\n offset_cache.y = y;\n }\n return offset_cache;\n }\n /**\n * Get anchor point for lines on a node.\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @returns {{x:number, y:number}} Anchor point coordinates\n */\n get_node_point(node) {\n var view_data = node._data.view;\n var offset_p = this.get_node_offset(node);\n var p = {};\n p.x = offset_p.x + (view_data.width * (node._data.layout.direction - 1)) / 2;\n p.y = offset_p.y - view_data.height / 2;\n return p;\n }\n /**\n * Get input point for lines on a node.\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @returns {{x:number, y:number}} Input point coordinates\n */\n get_node_point_in(node) {\n var p = this.get_node_offset(node);\n return p;\n }\n /**\n * Get output point for lines on a node.\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @returns {{x:number, y:number}} Output point coordinates\n */\n get_node_point_out(node) {\n var layout_data = node._data.layout;\n var pout_cache = null;\n if ('_pout_' in layout_data && this.cache_valid) {\n pout_cache = layout_data._pout_;\n } else {\n pout_cache = { x: -1, y: -1 };\n layout_data._pout_ = pout_cache;\n }\n if (pout_cache.x == -1 || pout_cache.y == -1) {\n if (node.isroot) {\n pout_cache.x = 0;\n pout_cache.y = 0;\n } else {\n var view_data = node._data.view;\n var offset_p = this.get_node_offset(node);\n pout_cache.x =\n offset_p.x + (view_data.width + this.opts.pspace) * node._data.layout.direction;\n pout_cache.y = offset_p.y;\n }\n }\n return pout_cache;\n }\n /**\n * Get expander point for a node.\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @returns {{x:number, y:number}} Expander point coordinates\n */\n get_expander_point(node) {\n var p = this.get_node_point_out(node);\n var ex_p = {};\n if (node._data.layout.direction == Direction.right) {\n ex_p.x = p.x - this.opts.pspace;\n } else {\n ex_p.x = p.x;\n }\n ex_p.y = p.y - Math.ceil(this.opts.pspace / 2);\n return ex_p;\n }\n /**\n * Get minimal canvas size to contain all nodes.\n * @returns {{w:number, h:number}} Minimum size required\n */\n get_min_size() {\n var nodes = this.jm.mind.nodes;\n var node = null;\n var pout = null;\n for (var node_id in nodes) {\n node = nodes[node_id];\n pout = this.get_node_point_out(node);\n if (pout.x > this.bounds.e) {\n this.bounds.e = pout.x;\n }\n if (pout.x < this.bounds.w) {\n this.bounds.w = pout.x;\n }\n }\n return {\n w: this.bounds.e - this.bounds.w,\n h: this.bounds.s - this.bounds.n,\n };\n }\n /**\n * Toggle node expanded/collapsed state.\n * @param {import('./jsmind.node.js').Node} node - Target node\n */\n toggle_node(node) {\n if (node.isroot) {\n return;\n }\n if (node.expanded) {\n this.collapse_node(node);\n } else {\n this.expand_node(node);\n }\n }\n /**\n * Expand a node and show its children.\n * @param {import('./jsmind.node.js').Node} node - Target node\n */\n expand_node(node) {\n node.expanded = true;\n this.part_layout(node);\n this.set_visible(node.children, true);\n this.jm.invoke_event_handle(EventType.show, {\n evt: 'expand_node',\n data: [],\n node: node.id,\n });\n }\n /**\n * Collapse a node and hide its children.\n * @param {import('./jsmind.node.js').Node} node - Target node\n */\n collapse_node(node) {\n node.expanded = false;\n this.part_layout(node);\n this.set_visible(node.children, false);\n this.jm.invoke_event_handle(EventType.show, {\n evt: 'collapse_node',\n data: [],\n node: node.id,\n });\n }\n /** Expand all nodes in the mind map. */\n expand_all() {\n var nodes = this.jm.mind.nodes;\n var c = 0;\n var node;\n for (var node_id in nodes) {\n node = nodes[node_id];\n if (!node.expanded) {\n node.expanded = true;\n c++;\n }\n }\n if (c > 0) {\n var root = this.jm.mind.root;\n this.part_layout(root);\n this.set_visible(root.children, true);\n }\n }\n /** Collapse all nodes in the mind map. */\n collapse_all() {\n var nodes = this.jm.mind.nodes;\n var c = 0;\n var node;\n for (var node_id in nodes) {\n node = nodes[node_id];\n if (node.expanded && !node.isroot) {\n node.expanded = false;\n c++;\n }\n }\n if (c > 0) {\n var root = this.jm.mind.root;\n this.part_layout(root);\n this.set_visible(root.children, true);\n }\n }\n /**\n * Expand nodes to a specific depth level.\n * @param {number} target_depth - Target depth level\n * @param {import('./jsmind.node.js').Node[]=} curr_nodes - Current nodes to process\n * @param {number=} curr_depth - Current depth level\n */\n expand_to_depth(target_depth, curr_nodes, curr_depth) {\n if (target_depth < 1) {\n return;\n }\n var nodes = curr_nodes || this.jm.mind.root.children;\n var depth = curr_depth || 1;\n var i = nodes.length;\n var node = null;\n while (i--) {\n node = nodes[i];\n if (depth < target_depth) {\n if (!node.expanded) {\n this.expand_node(node);\n }\n this.expand_to_depth(target_depth, node.children, depth + 1);\n }\n if (depth == target_depth) {\n if (node.expanded) {\n this.collapse_node(node);\n }\n }\n }\n }\n /**\n * Perform partial layout for a node and its subtree.\n * @param {import('./jsmind.node.js').Node} node - Target node\n */\n part_layout(node) {\n var root = this.jm.mind.root;\n if (!!root) {\n var root_layout_data = root._data.layout;\n if (node.isroot) {\n root_layout_data.outer_height_right = this._layout_offset_subnodes_height(\n root_layout_data.right_nodes\n );\n root_layout_data.outer_height_left = this._layout_offset_subnodes_height(\n root_layout_data.left_nodes\n );\n } else {\n if (node._data.layout.direction == Direction.right) {\n root_layout_data.outer_height_right = this._layout_offset_subnodes_height(\n root_layout_data.right_nodes\n );\n } else {\n root_layout_data.outer_height_left = this._layout_offset_subnodes_height(\n root_layout_data.left_nodes\n );\n }\n }\n this.bounds.s = Math.max(\n root_layout_data.outer_height_left,\n root_layout_data.outer_height_right\n );\n this.cache_valid = false;\n } else {\n logger.warn('can not found root node');\n }\n }\n /**\n * Set visibility for nodes and their children.\n * @param {import('./jsmind.node.js').Node[]} nodes - Array of nodes\n * @param {boolean} visible - Visibility state\n */\n set_visible(nodes, visible) {\n var i = nodes.length;\n var node = null;\n var layout_data = null;\n while (i--) {\n node = nodes[i];\n layout_data = node._data.layout;\n if (node.expanded) {\n this.set_visible(node.children, visible);\n } else {\n this.set_visible(node.children, false);\n }\n if (!node.isroot) {\n node._data.layout.visible = visible;\n }\n }\n }\n /**\n * Check if a node is expanded.\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @returns {boolean} True if node is expanded\n */\n is_expand(node) {\n return node.expanded;\n }\n /**\n * Check if a node is visible.\n * @param {import('./jsmind.node.js').Node} node - Target node\n * @returns {boolean} True if node is visible\n */\n is_visible(node) {\n var layout_data = node._data.layout;\n if ('visible' in layout_data && !layout_data.visible) {\n return false;\n } else {\n return true;\n }\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { $ } from './jsmind.dom.js';\nimport { logger } from './jsmind.common.js';\n\n/**\n * SVG-based graph renderer.\n */\nclass SvgGraph {\n /**\n * Create SVG graph renderer.\n * @param {import('./jsmind.view_provider.js').ViewProvider} view - View provider instance\n */\n constructor(view) {\n this.view = view;\n this.opts = view.opts;\n this.e_svg = SvgGraph.c('svg');\n this.e_svg.setAttribute('class', 'jsmind');\n this.size = { w: 0, h: 0 };\n /** @type {SVGPathElement[]} */\n this.lines = [];\n this.line_drawing = {\n straight: this._line_to,\n curved: this._bezier_to,\n };\n this.init_line_render();\n }\n /** @param {string} tag */\n static c(tag) {\n return $.d.createElementNS('http://www.w3.org/2000/svg', tag);\n }\n /** Choose line drawing renderer. */\n init_line_render() {\n if (typeof this.opts.custom_line_render === 'function') {\n /** @type {(path:SVGPathElement,x1:number,y1:number,x2:number,y2:number)=>void} */\n this.drawing = (path, x1, y1, x2, y2) => {\n try {\n this.opts.custom_line_render.call(this, {\n ctx: path,\n start_point: { x: x1, y: y1 },\n end_point: { x: x2, y: y2 },\n });\n } catch (e) {\n logger.error('custom line renderer error: ', e);\n }\n };\n } else {\n /** @type {(path:SVGPathElement,x1:number,y1:number,x2:number,y2:number)=>void} */\n this.drawing = this.line_drawing[this.opts.line_style] || this.line_drawing.curved;\n }\n }\n /** @returns {SVGSVGElement} */\n element() {\n return this.e_svg;\n }\n /** @param {number} w @param {number} h */\n set_size(w, h) {\n this.size.w = w;\n this.size.h = h;\n this.e_svg.setAttribute('width', w);\n this.e_svg.setAttribute('height', h);\n }\n clear() {\n var len = this.lines.length;\n while (len--) {\n this.e_svg.removeChild(this.lines[len]);\n }\n this.lines.length = 0;\n }\n /** @param {{x:number,y:number}} pout @param {{x:number,y:number}} pin @param {{x:number,y:number}} offset @param {string=} color */\n draw_line(pout, pin, offset, color) {\n var line = SvgGraph.c('path');\n line.setAttribute('stroke', color || this.opts.line_color);\n line.setAttribute('stroke-width', this.opts.line_width);\n line.setAttribute('fill', 'transparent');\n this.lines.push(line);\n this.e_svg.appendChild(line);\n this.drawing(\n line,\n pin.x + offset.x,\n pin.y + offset.y,\n pout.x + offset.x,\n pout.y + offset.y\n );\n }\n\n /** @param {CanvasRenderingContext2D} dest_canvas_ctx @param {(()=>void)=} callback */\n copy_to(dest_canvas_ctx, callback) {\n var img = new Image();\n img.onload = function () {\n dest_canvas_ctx.drawImage(img, 0, 0);\n !!callback && callback();\n };\n img.src =\n 'data:image/svg+xml;base64,' + btoa(new XMLSerializer().serializeToString(this.e_svg));\n }\n /**\n * Draw bezier curve to SVG path.\n * @internal\n * @param {SVGPathElement} path - SVG path element\n * @param {number} x1 - Start x coordinate\n * @param {number} y1 - Start y coordinate\n * @param {number} x2 - End x coordinate\n * @param {number} y2 - End y coordinate\n */\n _bezier_to(path, x1, y1, x2, y2) {\n path.setAttribute(\n 'd',\n 'M ' +\n x1 +\n ' ' +\n y1 +\n ' C ' +\n (x1 + ((x2 - x1) * 2) / 3) +\n ' ' +\n y1 +\n ', ' +\n x1 +\n ' ' +\n y2 +\n ', ' +\n x2 +\n ' ' +\n y2\n );\n }\n /**\n * Draw straight line to SVG path.\n * @internal\n * @param {SVGPathElement} path - SVG path element\n * @param {number} x1 - Start x coordinate\n * @param {number} y1 - Start y coordinate\n * @param {number} x2 - End x coordinate\n * @param {number} y2 - End y coordinate\n */\n _line_to(path, x1, y1, x2, y2) {\n path.setAttribute('d', 'M ' + x1 + ' ' + y1 + ' L ' + x2 + ' ' + y2);\n }\n}\n\n/**\n * Canvas-based graph renderer.\n */\nclass CanvasGraph {\n /**\n * Create canvas graph renderer.\n * @param {import('./jsmind.view_provider.js').ViewProvider} view - View provider instance\n */\n constructor(view) {\n this.opts = view.opts;\n this.e_canvas = $.c('canvas');\n this.e_canvas.className = 'jsmind';\n this.canvas_ctx = /** @type {CanvasRenderingContext2D} */ (this.e_canvas.getContext('2d'));\n this.size = { w: 0, h: 0 };\n this.line_drawing = {\n straight: this._line_to,\n curved: this._bezier_to,\n };\n this.dpr = view.device_pixel_ratio;\n this.init_line_render();\n }\n /** Choose line drawing renderer. */\n init_line_render() {\n if (typeof this.opts.custom_line_render === 'function') {\n /** @type {(ctx:CanvasRenderingContext2D,x1:number,y1:number,x2:number,y2:number)=>void} */\n this.drawing = (ctx, x1, y1, x2, y2) => {\n try {\n this.opts.custom_line_render.call(this, {\n ctx,\n start_point: { x: x1, y: y1 },\n end_point: { x: x2, y: y2 },\n });\n } catch (e) {\n logger.error('custom line render error: ', e);\n }\n };\n } else {\n /** @type {(ctx:CanvasRenderingContext2D,x1:number,y1:number,x2:number,y2:number)=>void} */\n this.drawing = this.line_drawing[this.opts.line_style] || this.line_drawing.curved;\n }\n }\n /** @returns {HTMLCanvasElement} */\n element() {\n return this.e_canvas;\n }\n /** @param {number} w @param {number} h */\n set_size(w, h) {\n this.size.w = w;\n this.size.h = h;\n if (this.e_canvas.width && this.e_canvas.height && this.canvas_ctx.scale) {\n this.e_canvas.width = w * this.dpr;\n this.e_canvas.height = h * this.dpr;\n\n this.e_canvas.style.width = w + 'px';\n this.e_canvas.style.height = h + 'px';\n this.canvas_ctx.scale(this.dpr, this.dpr);\n } else {\n this.e_canvas.width = w;\n this.e_canvas.height = h;\n }\n }\n\n /** Clear the canvas. */\n clear() {\n this.canvas_ctx.clearRect(0, 0, this.size.w, this.size.h);\n }\n /** @param {{x:number,y:number}} pout @param {{x:number,y:number}} pin @param {{x:number,y:number}} offset @param {string=} color */\n draw_line(pout, pin, offset, color) {\n var ctx = this.canvas_ctx;\n ctx.strokeStyle = color || this.opts.line_color;\n ctx.lineWidth = this.opts.line_width;\n ctx.lineCap = 'round';\n this.drawing(ctx, pin.x + offset.x, pin.y + offset.y, pout.x + offset.x, pout.y + offset.y);\n }\n /** @param {CanvasRenderingContext2D} dest_canvas_ctx @param {(()=>void)=} callback */\n copy_to(dest_canvas_ctx, callback) {\n dest_canvas_ctx.drawImage(this.e_canvas, 0, 0, this.size.w, this.size.h);\n !!callback && callback();\n }\n /**\n * Draw bezier curve on canvas.\n * @internal\n * @param {CanvasRenderingContext2D} ctx - Canvas context\n * @param {number} x1 - Start x coordinate\n * @param {number} y1 - Start y coordinate\n * @param {number} x2 - End x coordinate\n * @param {number} y2 - End y coordinate\n */\n _bezier_to(ctx, x1, y1, x2, y2) {\n ctx.beginPath();\n ctx.moveTo(x1, y1);\n ctx.bezierCurveTo(x1 + ((x2 - x1) * 2) / 3, y1, x1, y2, x2, y2);\n ctx.stroke();\n }\n /**\n * Draw straight line on canvas.\n * @internal\n * @param {CanvasRenderingContext2D} ctx - Canvas context\n * @param {number} x1 - Start x coordinate\n * @param {number} y1 - Start y coordinate\n * @param {number} x2 - End x coordinate\n * @param {number} y2 - End y coordinate\n */\n _line_to(ctx, x1, y1, x2, y2) {\n ctx.beginPath();\n ctx.moveTo(x1, y1);\n ctx.lineTo(x2, y2);\n ctx.stroke();\n }\n}\n\n/**\n * Initialize graph renderer based on engine type.\n * @param {import('./jsmind.view_provider.js').ViewProvider} view - View provider instance\n * @param {'canvas'|'svg'} engine - Rendering engine type\n * @returns {SvgGraph|CanvasGraph} Graph renderer instance\n */\nexport function init_graph(view, engine) {\n return engine.toLowerCase() === 'svg' ? new SvgGraph(view) : new CanvasGraph(view);\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\nimport { logger, EventType } from './jsmind.common.js';\nimport { $ } from './jsmind.dom.js';\nimport { init_graph } from './jsmind.graph.js';\nimport { util } from './jsmind.util.js';\n\nexport class ViewProvider {\n /**\n * View layer: DOM nodes, editor, graph and zoom.\n * @param {import('./jsmind.js').default} jm - jsMind instance\n * @param {{\n * engine: 'canvas'|'svg',\n * enable_device_pixel_ratio: boolean,\n * hmargin: number,\n * vmargin: number,\n * line_width: number,\n * line_color: string,\n * line_style: 'curved'|'straight',\n * custom_line_render?: Function,\n * draggable: boolean,\n * hide_scrollbars_when_draggable: boolean,\n * node_overflow: 'hidden'|'wrap',\n * zoom: {min:number, max:number, step:number, mask_key:number},\n * custom_node_render?: Function,\n * expander_style: 'char'|'number'\n * }} options - View configuration options\n */\n constructor(jm, options) {\n this.opts = options;\n this.jm = jm;\n this.layout = jm.layout;\n\n this.container = null;\n this.e_panel = null;\n this.e_nodes = null;\n\n this.size = { w: 0, h: 0 };\n\n this.selected_node = null;\n this.editing_node = null;\n\n this.graph = null;\n this.render_node = !!options.custom_node_render\n ? this._custom_node_render\n : this._default_node_render;\n this.zoom_current = 1;\n this.device_pixel_ratio = this.opts.enable_device_pixel_ratio\n ? $.w.devicePixelRatio || 1\n : 1;\n this._initialized = false;\n }\n /** Initialize DOM structure, graph and editor. */\n init() {\n logger.debug(this.opts);\n logger.debug('view.init');\n\n this.container = $.i(this.opts.container)\n ? /** @type {HTMLElement} */ (this.opts.container)\n : /** @type {HTMLElement} */ ($.g(this.opts.container));\n if (!this.container) {\n logger.error('the options.view.container was not be found in dom');\n return;\n }\n this.graph = init_graph(this, this.opts.engine);\n\n this.e_panel = $.c('div');\n this.e_nodes = $.c('jmnodes');\n this.e_editor = $.c('input');\n this.e_panel.className = 'jsmind-inner jmnode-overflow-' + this.opts.node_overflow;\n this.e_panel.tabIndex = 1;\n this.e_panel.appendChild(this.graph.element());\n this.e_panel.appendChild(this.e_nodes);\n\n this.e_editor.className = 'jsmind-editor';\n this.e_editor.type = 'text';\n\n var v = this;\n $.on(this.e_editor, 'keydown', function (e) {\n var evt = e || event;\n if (evt.keyCode == 13) {\n v.edit_node_end();\n evt.stopPropagation();\n }\n });\n $.on(this.e_editor, 'blur', function (e) {\n v.edit_node_end();\n });\n\n this.container.appendChild(this.e_panel);\n\n if (!this.container.offsetParent) {\n new IntersectionObserver((entities, observer) => {\n if (entities[0].isIntersecting) {\n observer.unobserve(this.e_panel);\n this.resize();\n }\n }).observe(this.e_panel);\n }\n }\n\n /**\n * Add a delegated event handler.\n * @param {import('./jsmind.js').default} obj\n * @param {string} event_name\n * @param {(e:Event)=>void} event_handle\n * @param {boolean=} capture_by_panel\n */\n add_event(obj, event_name, event_handle, capture_by_panel) {\n let target = !!capture_by_panel ? this.e_panel : this.e_nodes;\n $.on(target, event_name, function (e) {\n var evt = e || event;\n event_handle.call(obj, evt);\n });\n }\n /**\n * @param {HTMLElement|null} element\n * @returns {string|null}\n */\n get_binded_nodeid(element) {\n if (element == null) {\n return null;\n }\n var tagName = element.tagName.toLowerCase();\n if (tagName == 'jmnode' || tagName == 'jmexpander') {\n return element.getAttribute('nodeid');\n } else if (tagName == 'jmnodes' || tagName == 'body' || tagName == 'html') {\n return null;\n } else {\n return this.get_binded_nodeid(element.parentElement);\n }\n }\n /**\n * @param {HTMLElement|null} element\n * @returns {boolean}\n */\n is_node(element) {\n if (element == null) {\n return false;\n }\n var tagName = element.tagName.toLowerCase();\n if (tagName == 'jmnode') {\n return true;\n } else if (tagName == 'jmnodes' || tagName == 'body' || tagName == 'html') {\n return false;\n } else {\n return this.is_node(element.parentElement);\n }\n }\n /**\n * @param {HTMLElement} element\n * @returns {boolean}\n */\n is_expander(element) {\n return element.tagName.toLowerCase() == 'jmexpander';\n }\n reset() {\n logger.debug('view.reset');\n this.selected_node = null;\n this.clear_lines();\n this.clear_nodes();\n this.reset_theme();\n }\n reset_theme() {\n var theme_name = this.jm.options.theme;\n if (!!theme_name) {\n this.e_nodes.className = 'theme-' + theme_name;\n } else {\n this.e_nodes.className = '';\n }\n }\n /** Reset custom styles for all nodes. */\n reset_custom_style() {\n var nodes = this.jm.mind.nodes;\n for (var nodeid in nodes) {\n this.reset_node_custom_style(nodes[nodeid]);\n }\n }\n /** Load and initialize the view. */\n load() {\n logger.debug('view.load');\n this.setup_canvas_draggable(this.opts.draggable);\n this.init_nodes();\n this._initialized = true;\n }\n /** Calculate and set the expanded canvas size. */\n expand_size() {\n var min_size = this.layout.get_min_size();\n var min_width = min_size.w + this.opts.hmargin * 2;\n var min_height = min_size.h + this.opts.vmargin * 2;\n var client_w = this.e_panel.clientWidth;\n var client_h = this.e_panel.clientHeight;\n if (client_w < min_width) {\n client_w = min_width;\n }\n if (client_h < min_height) {\n client_h = min_height;\n }\n this.size.w = client_w;\n this.size.h = client_h;\n }\n /**\n * Initialize size data for a node.\n * @param {import('./jsmind.node.js').Node} node - Target node\n */\n init_nodes_size(node) {\n var view_data = node._data.view;\n view_data.width = view_data.element.clientWidth;\n view_data.height = view_data.element.clientHeight;\n }\n /** Initialize DOM elements for all nodes. */\n init_nodes() {\n var nodes = this.jm.mind.nodes;\n var doc_frag = $.d.createDocumentFragment();\n for (var nodeid in nodes) {\n this.create_node_element(nodes[nodeid], doc_frag);\n }\n this.e_nodes.appendChild(doc_frag);\n\n this.run_in_c11y_mode_if_needed(() => {\n for (var nodeid in nodes) {\n this.init_nodes_size(nodes[nodeid]);\n }\n });\n }\n /**\n * Add a new node to the view.\n * @param {import('./jsmind.node.js').Node} node - Node to add\n */\n add_node(node) {\n this.create_node_element(node, this.e_nodes);\n this.run_in_c11y_mode_if_needed(() => {\n this.init_nodes_size(node);\n });\n }\n /**\n * Run function in compatibility mode if container is not visible.\n * @param {Function} func - Function to execute\n */\n run_in_c11y_mode_if_needed(func) {\n if (!!this.container.offsetParent) {\n func();\n return;\n }\n logger.warn(\n 'init nodes in compatibility mode. because the container or its parent has style {display:none}. '\n );\n this.e_panel.style.position = 'absolute';\n this.e_panel.style.top = '-100000';\n $.d.body.appendChild(this.e_panel);\n func();\n this.container.appendChild(this.e_panel);\n this.e_panel.style.position = null;\n this.e_panel.style.top = null;\n }\n /**\n * Create a DOM element for a node and append to parent container.\n * @param {import('./jsmind.node.js').Node} node\n * @param {HTMLElement} parent_node\n */\n create_node_element(node, parent_node) {\n var view_data = null;\n if ('view' in node._data) {\n view_data = node._data.view;\n } else {\n view_data = {};\n node._data.view = view_data;\n }\n\n var d = $.c('jmnode');\n if (node.isroot) {\n d.className = 'root';\n } else {\n var d_e = $.c('jmexpander');\n $.t(d_e, '-');\n d_e.setAttribute('nodeid', node.id);\n d_e.style.visibility = 'hidden';\n parent_node.appendChild(d_e);\n view_data.expander = d_e;\n }\n if (!!node.topic) {\n this.render_node(d, node);\n }\n d.setAttribute('nodeid', node.id);\n d.style.visibility = 'hidden';\n this._reset_node_custom_style(d, node.data);\n\n parent_node.appendChild(d);\n view_data.element = d;\n }\n /**\n * Remove a node from the view.\n * @param {import('./jsmind.node.js').Node} node - Node to remove\n */\n remove_node(node) {\n if (this.selected_node != null && this.selected_node.id == node.id) {\n this.selected_node = null;\n }\n if (this.editing_node != null && this.editing_node.id == node.id) {\n node._data.view.element.removeChild(this.e_editor);\n this.editing_node = null;\n }\n var children = node.children;\n var i = children.length;\n while (i--) {\n this.remove_node(children[i]);\n }\n if (node._data.view) {\n var element = node._data.view.element;\n var expander = node._data.view.expander;\n this.e_nodes.removeChild(element);\n this.e_nodes.removeChild(expander);\n node._data.view.element = null;\n node._data.view.expander = null;\n }\n }\n /**\n * Update a node's display.\n * @param {import('./jsmind.node.js').Node} node - Node to update\n */\n update_node(node) {\n var view_data = node._data.view;\n var element = view_data.element;\n if (!!node.topic) {\n this.render_node(element, node);\n }\n if (this.layout.is_visible(node)) {\n view_data.width = element.clientWidth;\n view_data.height = element.clientHeight;\n } else {\n let origin_style = element.getAttribute('style');\n element.style = 'visibility: visible; left:0; top:0;';\n view_data.width = element.clientWidth;\n view_data.height = element.clientHeight;\n element.style = origin_style;\n }\n }\n /**\n * Select a node visually.\n * @param {import('./jsmind.node.js').Node|null} node - Node to select\n */\n select_node(node) {\n if (!!this.selected_node) {\n var element = this.selected_node._data.view.element;\n element.className = element.className.replace(/\\s*selected\\b/i, '');\n this.restore_selected_node_custom_style(this.selected_node);\n }\n if (!!node) {\n this.selected_node = node;\n node._data.view.element.className += ' selected';\n this.clear_selected_node_custom_style(node);\n }\n }\n /** Clear node selection. */\n select_clear() {\n this.select_node(null);\n }\n /**\n * Get currently editing node.\n * @returns {import('./jsmind.node.js').Node|null} Currently editing node\n */\n get_editing_node() {\n return this.editing_node;\n }\n /**\n * Check if any node is being edited.\n * @returns {boolean} True if editing\n */\n is_editing() {\n return !!this.editing_node;\n }\n /**\n * Begin editing a node.\n * @param {import('./jsmind.node.js').Node} node - Node to edit\n */\n edit_node_begin(node) {\n if (!node.topic) {\n logger.warn(\"don't edit image nodes\");\n return;\n }\n if (this.editing_node != null) {\n this.edit_node_end();\n }\n this.editing_node = node;\n var view_data = node._data.view;\n var element = view_data.element;\n var topic = node.topic;\n var ncs = getComputedStyle(element);\n this.e_editor.value = topic;\n this.e_editor.style.width =\n element.clientWidth -\n parseInt(ncs.getPropertyValue('padding-left')) -\n parseInt(ncs.getPropertyValue('padding-right')) +\n 'px';\n element.innerHTML = '';\n element.appendChild(this.e_editor);\n element.style.zIndex = 5;\n this.e_editor.focus();\n this.e_editor.select();\n }\n /** End editing current node. */\n edit_node_end() {\n if (this.editing_node != null) {\n var node = this.editing_node;\n this.editing_node = null;\n var view_data = node._data.view;\n var element = view_data.element;\n var topic = this.e_editor.value;\n element.style.zIndex = 'auto';\n element.removeChild(this.e_editor);\n if (util.text.is_empty(topic) || node.topic === topic) {\n this.render_node(element, node);\n } else {\n this.jm.update_node(node.id, topic);\n }\n }\n this.e_panel.focus();\n }\n /** @returns {{x:number,y:number}} */\n get_view_offset() {\n var bounds = this.layout.bounds;\n var _x = (this.size.w - bounds.e - bounds.w) / 2;\n var _y = this.size.h / 2;\n return { x: _x, y: _y };\n }\n /** Resize the view to fit container. */\n resize() {\n this.graph.set_size(1, 1);\n this.e_nodes.style.width = '1px';\n this.e_nodes.style.height = '1px';\n\n this.expand_size();\n this._show();\n }\n /**\n * Internal show implementation.\n * @private\n */\n _show() {\n this.graph.set_size(this.size.w, this.size.h);\n this.e_nodes.style.width = this.size.w + 'px';\n this.e_nodes.style.height = this.size.h + 'px';\n this.show_nodes();\n this.show_lines();\n //this.layout.cache_valid = true;\n this.jm.invoke_event_handle(EventType.resize, { data: [] });\n }\n /**\n * Zoom in the view.\n * @param {MouseEvent=} e - Mouse event for zoom center\n * @returns {boolean} True if zoom succeeded\n */\n zoom_in(e) {\n return this.set_zoom(this.zoom_current + this.opts.zoom.step, e);\n }\n /**\n * Zoom out the view.\n * @param {MouseEvent=} e - Mouse event for zoom center\n * @returns {boolean} True if zoom succeeded\n */\n zoom_out(e) {\n return this.set_zoom(this.zoom_current - this.opts.zoom.step, e);\n }\n /**\n * Set zoom level and keep scroll around zoom center.\n * @param {number} zoom\n * @param {MouseEvent=} e\n */\n set_zoom(zoom, e) {\n if (zoom < this.opts.zoom.min || zoom > this.opts.zoom.max) {\n return false;\n }\n let e_panel_rect = this.e_panel.getBoundingClientRect();\n if (\n zoom < 1 &&\n zoom < this.zoom_current &&\n this.size.w * zoom < e_panel_rect.width &&\n this.size.h * zoom < e_panel_rect.height\n ) {\n return false;\n }\n let zoom_center = !!e\n ? { x: e.x - e_panel_rect.x, y: e.y - e_panel_rect.y }\n : { x: e_panel_rect.width / 2, y: e_panel_rect.height / 2 };\n let panel_scroll_x =\n ((this.e_panel.scrollLeft + zoom_center.x) * zoom) / this.zoom_current - zoom_center.x;\n let panel_scroll_y =\n ((this.e_panel.scrollTop + zoom_center.y) * zoom) / this.zoom_current - zoom_center.y;\n\n this.zoom_current = zoom;\n for (var i = 0; i < this.e_panel.children.length; i++) {\n this.e_panel.children[i].style.zoom = zoom;\n }\n this._show();\n this.e_panel.scrollLeft = panel_scroll_x;\n this.e_panel.scrollTop = panel_scroll_y;\n return true;\n }\n /** @param {boolean=} keep_center */\n show(keep_center) {\n logger.debug(`view.show: {keep_center: ${keep_center}}`);\n this.expand_size();\n this._show();\n if (!!keep_center) {\n this.center_node(this.jm.mind.root);\n }\n }\n relayout() {\n this.expand_size();\n this._show();\n }\n /** @param {import('./jsmind.node.js').Node} node */\n save_location(node) {\n var vd = node._data.view;\n vd._saved_location = {\n x: parseInt(vd.element.style.left) - this.e_panel.scrollLeft,\n y: parseInt(vd.element.style.top) - this.e_panel.scrollTop,\n };\n }\n /** @param {import('./jsmind.node.js').Node} node */\n restore_location(node) {\n var vd = node._data.view;\n this.e_panel.scrollLeft = parseInt(vd.element.style.left) - vd._saved_location.x;\n this.e_panel.scrollTop = parseInt(vd.element.style.top) - vd._saved_location.y;\n }\n clear_nodes() {\n var mind = this.jm.mind;\n if (mind == null) {\n return;\n }\n var nodes = mind.nodes;\n var node = null;\n for (var nodeid in nodes) {\n node = nodes[nodeid];\n node._data.view.element = null;\n node._data.view.expander = null;\n }\n this.e_nodes.innerHTML = '';\n }\n /** Render node elements and expanders to screen. */\n show_nodes() {\n var nodes = this.jm.mind.nodes;\n var node = null;\n var node_element = null;\n var p = null;\n var view_data = null;\n var view_offset = this.get_view_offset();\n for (var nodeid in nodes) {\n node = nodes[nodeid];\n view_data = node._data.view;\n node_element = view_data.element;\n if (!this.layout.is_visible(node)) {\n node_element.style.display = 'none';\n view_data.expander.style.display = 'none';\n continue;\n }\n this.reset_node_custom_style(node);\n p = this.layout.get_node_point(node);\n view_data.abs_x = view_offset.x + p.x;\n view_data.abs_y = view_offset.y + p.y;\n node_element.style.left = view_offset.x + p.x + 'px';\n node_element.style.top = view_offset.y + p.y + 'px';\n node_element.style.display = '';\n node_element.style.visibility = 'visible';\n this._show_expander(node, view_offset);\n }\n }\n /** @param {import('./jsmind.node.js').Node} node @param {{x:number,y:number}} view_offset */\n _show_expander(node, view_offset) {\n if (node.isroot) {\n return;\n }\n\n var expander = node._data.view.expander;\n if (node.children.length == 0) {\n expander.style.display = 'none';\n expander.style.visibility = 'hidden';\n return;\n }\n\n let expander_text = this._get_expander_text(node);\n $.t(expander, expander_text);\n\n let p_expander = this.layout.get_expander_point(node);\n expander.style.left = view_offset.x + p_expander.x + 'px';\n expander.style.top = view_offset.y + p_expander.y + 'px';\n expander.style.display = '';\n expander.style.visibility = 'visible';\n }\n\n /** @param {import('./jsmind.node.js').Node} node */\n _get_expander_text(node) {\n let style = !!this.opts.expander_style ? this.opts.expander_style.toLowerCase() : 'char';\n if (style === 'number') {\n return node.children.length > 99 ? '...' : node.children.length;\n }\n if (style === 'char') {\n return node.expanded ? '-' : '+';\n }\n }\n\n /** @param {HTMLElement} ele @param {import('./jsmind.node.js').Node} node */\n _default_node_render(ele, node) {\n if (this.opts.support_html) {\n $.h(ele, node.topic);\n } else {\n $.t(ele, node.topic);\n }\n }\n /** @param {HTMLElement} ele @param {import('./jsmind.node.js').Node} node */\n _custom_node_render(ele, node) {\n let rendered = this.opts.custom_node_render(this.jm, ele, node);\n if (!rendered) {\n this._default_node_render(ele, node);\n }\n }\n /** @param {import('./jsmind.node.js').Node} node */\n reset_node_custom_style(node) {\n this._reset_node_custom_style(node._data.view.element, node.data);\n }\n /** @param {HTMLElement} node_element @param {Record<string,string|number>} node_data */\n _reset_node_custom_style(node_element, node_data) {\n if ('background-color' in node_data) {\n node_element.style.backgroundColor = node_data['background-color'];\n }\n if ('foreground-color' in node_data) {\n node_element.style.color = node_data['foreground-color'];\n }\n if ('width' in node_data) {\n node_element.style.width = node_data['width'] + 'px';\n }\n if ('height' in node_data) {\n node_element.style.height = node_data['height'] + 'px';\n }\n if ('font-size' in node_data) {\n node_element.style.fontSize = node_data['font-size'] + 'px';\n }\n if ('font-weight' in node_data) {\n node_element.style.fontWeight = node_data['font-weight'];\n }\n if ('font-style' in node_data) {\n node_element.style.fontStyle = node_data['font-style'];\n }\n if ('background-image' in node_data) {\n var backgroundImage = node_data['background-image'];\n if (backgroundImage.startsWith('data') && node_data['width'] && node_data['height']) {\n var img = new Image();\n\n img.onload = function () {\n var c = $.c('canvas');\n c.width = node_element.clientWidth;\n c.height = node_element.clientHeight;\n var img = this;\n if (c.getContext) {\n var ctx = c.getContext('2d');\n ctx.drawImage(\n img,\n 2,\n 2,\n node_element.clientWidth,\n node_element.clientHeight\n );\n var scaledImageData = c.toDataURL();\n node_element.style.backgroundImage = 'url(' + scaledImageData + ')';\n }\n };\n img.src = backgroundImage;\n } else {\n node_element.style.backgroundImage = 'url(' + backgroundImage + ')';\n }\n node_element.style.backgroundSize = '99%';\n\n if ('background-rotation' in node_data) {\n node_element.style.transform =\n 'rotate(' + node_data['background-rotation'] + 'deg)';\n }\n }\n }\n /** @param {import('./jsmind.node.js').Node} node */\n restore_selected_node_custom_style(node) {\n var node_element = node._data.view.element;\n var node_data = node.data;\n if ('background-color' in node_data) {\n node_element.style.backgroundColor = node_data['background-color'];\n }\n if ('foreground-color' in node_data) {\n node_element.style.color = node_data['foreground-color'];\n }\n }\n /** @param {import('./jsmind.node.js').Node} node */\n clear_selected_node_custom_style(node) {\n var node_element = node._data.view.element;\n node_element.style.backgroundColor = '';\n node_element.style.color = '';\n }\n clear_lines() {\n this.graph.clear();\n }\n show_lines() {\n this.clear_lines();\n var nodes = this.jm.mind.nodes;\n var node = null;\n var pin = null;\n var pout = null;\n var color = null;\n var _offset = this.get_view_offset();\n for (var nodeid in nodes) {\n node = nodes[nodeid];\n if (!!node.isroot) {\n continue;\n }\n if (!this.layout.is_visible(node)) {\n continue;\n }\n pin = this.layout.get_node_point_in(node);\n pout = this.layout.get_node_point_out(node.parent);\n color = node.data['leading-line-color'];\n this.graph.draw_line(pout, pin, _offset, color);\n }\n }\n // Drag the whole mind map with your mouse, when it's larger that the container\n /**\n * Enable/disable dragging the whole canvas with mouse.\n * @param {boolean} enabled\n */\n setup_canvas_draggable(enabled) {\n this.opts.draggable = enabled;\n if (!this._initialized) {\n let dragging = false;\n let x, y;\n if (this.opts.hide_scrollbars_when_draggable) {\n // Avoid scrollbars when mind map is larger than the container (e_panel = id jsmind-inner)\n this.e_panel.style = 'overflow: hidden';\n }\n // Move the whole mind map with mouse moves, while button is down.\n $.on(this.container, 'mousedown', eventDown => {\n if (this.opts.draggable) {\n dragging = true;\n // Record current mouse position.\n x = eventDown.clientX;\n y = eventDown.clientY;\n }\n });\n // Stop moving mind map once mouse button is released.\n $.on(this.container, 'mouseup', () => {\n dragging = false;\n });\n // Follow current mouse position and move mind map accordingly.\n $.on(this.container, 'mousemove', eventMove => {\n if (this.opts.draggable) {\n if (dragging) {\n this.e_panel.scrollBy(x - eventMove.clientX, y - eventMove.clientY);\n // Record new current position.\n x = eventMove.clientX;\n y = eventMove.clientY;\n }\n }\n });\n }\n }\n /** @param {import('./jsmind.node.js').Node} node */\n center_node(node) {\n if (!this.layout.is_visible(node)) {\n logger.warn('can not scroll to the node, because it is invisible');\n return false;\n }\n let view_data = node._data.view;\n let e_panel_rect = this.e_panel.getBoundingClientRect();\n let node_center_point = {\n x: view_data.abs_x + view_data.width / 2,\n y: view_data.abs_y + view_data.height / 2,\n };\n this.e_panel.scrollTo(\n node_center_point.x * this.zoom_current - e_panel_rect.width / 2,\n node_center_point.y * this.zoom_current - e_panel_rect.height / 2\n );\n return true;\n }\n\n /** @param {MouseEvent=} e */\n zoomIn(e) {\n logger.warn('please use zoom_in instead');\n return this.zoom_in(e);\n }\n /** @param {MouseEvent=} e */\n zoomOut(e) {\n logger.warn('please use zoom_out instead');\n return this.zoom_out(e);\n }\n /** @param {number} zoom @param {MouseEvent=} e */\n setZoom(zoom, e) {\n logger.warn('please use set_zoom instead');\n return this.set_zoom(zoom, e);\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { $ } from './jsmind.dom.js';\nimport { util } from './jsmind.util.js';\nimport { Direction } from './jsmind.common.js';\n\nexport class ShortcutProvider {\n /**\n * @param {import('./jsmind.js').default} jm\n * @param {{ enable:boolean, handles: Record<string,(jm: import('./jsmind.js').default, e: KeyboardEvent)=>void>, mapping: Record<string, number|number[]>, id_generator?: ()=>string }} options\n */\n constructor(jm, options) {\n this.jm = jm;\n this.opts = options;\n /** @type {Record<string, number|number[]>} */\n this.mapping = options.mapping;\n /** @type {Record<string,(jm: import('./jsmind.js').default, e: KeyboardEvent)=>void>} */\n this.handles = options.handles;\n /** @type {()=>string|null} */\n this._newid = null;\n /** @type {Record<number,(jm: import('./jsmind.js').default, e: KeyboardEvent)=>void>} */\n this._mapping = {};\n }\n init() {\n $.on(this.jm.view.e_panel, 'keydown', this.handler.bind(this));\n\n this.handles['addchild'] = this.handle_addchild;\n this.handles['addbrother'] = this.handle_addbrother;\n this.handles['editnode'] = this.handle_editnode;\n this.handles['delnode'] = this.handle_delnode;\n this.handles['toggle'] = this.handle_toggle;\n this.handles['up'] = this.handle_up;\n this.handles['down'] = this.handle_down;\n this.handles['left'] = this.handle_left;\n this.handles['right'] = this.handle_right;\n\n for (var handle in this.mapping) {\n if (!!this.mapping[handle] && handle in this.handles) {\n let keys = this.mapping[handle];\n if (!Array.isArray(keys)) {\n keys = [keys];\n }\n for (let key of keys) {\n this._mapping[key] = this.handles[handle];\n }\n }\n }\n\n if (typeof this.opts.id_generator === 'function') {\n this._newid = this.opts.id_generator;\n } else {\n this._newid = util.uuid.newid;\n }\n }\n enable_shortcut() {\n this.opts.enable = true;\n }\n disable_shortcut() {\n this.opts.enable = false;\n }\n /** @param {KeyboardEvent} e */\n handler(e) {\n if (e.which == 9) {\n e.preventDefault();\n } //prevent tab to change focus in browser\n if (this.jm.view.is_editing()) {\n return;\n }\n var evt = e || event;\n if (!this.opts.enable) {\n return true;\n }\n var kc =\n evt.keyCode +\n (evt.metaKey << 13) +\n (evt.ctrlKey << 12) +\n (evt.altKey << 11) +\n (evt.shiftKey << 10);\n if (kc in this._mapping) {\n this._mapping[kc].call(this, this.jm, e);\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_addchild(_jm, e) {\n var selected_node = _jm.get_selected_node();\n if (!!selected_node) {\n var node_id = this._newid();\n var node = _jm.add_node(selected_node, node_id, 'New Node');\n if (!!node) {\n _jm.select_node(node_id);\n _jm.begin_edit(node_id);\n }\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_addbrother(_jm, e) {\n var selected_node = _jm.get_selected_node();\n if (!!selected_node && !selected_node.isroot) {\n var node_id = this._newid();\n var node = _jm.insert_node_after(selected_node, node_id, 'New Node');\n if (!!node) {\n _jm.select_node(node_id);\n _jm.begin_edit(node_id);\n }\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_editnode(_jm, e) {\n var selected_node = _jm.get_selected_node();\n if (!!selected_node) {\n _jm.begin_edit(selected_node);\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_delnode(_jm, e) {\n var selected_node = _jm.get_selected_node();\n if (!!selected_node && !selected_node.isroot) {\n _jm.select_node(selected_node.parent);\n _jm.remove_node(selected_node);\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_toggle(_jm, e) {\n var evt = e || event;\n var selected_node = _jm.get_selected_node();\n if (!!selected_node) {\n _jm.toggle_node(selected_node.id);\n evt.stopPropagation();\n evt.preventDefault();\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_up(_jm, e) {\n var evt = e || event;\n var selected_node = _jm.get_selected_node();\n if (!!selected_node) {\n var up_node = _jm.find_node_before(selected_node);\n if (!up_node) {\n var np = _jm.find_node_before(selected_node.parent);\n if (!!np && np.children.length > 0) {\n up_node = np.children[np.children.length - 1];\n }\n }\n if (!!up_node) {\n _jm.select_node(up_node);\n }\n evt.stopPropagation();\n evt.preventDefault();\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_down(_jm, e) {\n var evt = e || event;\n var selected_node = _jm.get_selected_node();\n if (!!selected_node) {\n var down_node = _jm.find_node_after(selected_node);\n if (!down_node) {\n var np = _jm.find_node_after(selected_node.parent);\n if (!!np && np.children.length > 0) {\n down_node = np.children[0];\n }\n }\n if (!!down_node) {\n _jm.select_node(down_node);\n }\n evt.stopPropagation();\n evt.preventDefault();\n }\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_left(_jm, e) {\n this._handle_direction(_jm, e, Direction.left);\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e */\n handle_right(_jm, e) {\n this._handle_direction(_jm, e, Direction.right);\n }\n /** @param {import('./jsmind.js').default} _jm @param {KeyboardEvent} e @param {number} d */\n _handle_direction(_jm, e, d) {\n var evt = e || event;\n var selected_node = _jm.get_selected_node();\n var node = null;\n if (!!selected_node) {\n if (selected_node.isroot) {\n var c = selected_node.children;\n var children = [];\n for (var i = 0; i < c.length; i++) {\n if (c[i].direction === d) {\n children.push(i);\n }\n }\n node = c[children[Math.floor((children.length - 1) / 2)]];\n } else if (selected_node.direction === d) {\n var children = selected_node.children;\n var children_count = children.length;\n if (children_count > 0) {\n node = children[Math.floor((children_count - 1) / 2)];\n }\n } else {\n node = selected_node.parent;\n }\n if (!!node) {\n _jm.select_node(node);\n }\n evt.stopPropagation();\n evt.preventDefault();\n }\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { $ } from './jsmind.dom.js';\n\n/** @type {{ plugins: Array<Plugin<object>> }} */\nconst plugin_data = {\n plugins: [],\n};\n\n/**\n * Register a plugin instance.\n * @param {Plugin<object>} plugin\n */\nexport function register(plugin) {\n if (!(plugin instanceof Plugin)) {\n throw new Error('can not register plugin, it is not an instance of Plugin');\n }\n if (plugin_data.plugins.map(p => p.name).includes(plugin.name)) {\n throw new Error('can not register plugin ' + plugin.name + ': plugin name already exist');\n }\n plugin_data.plugins.push(plugin);\n}\n\n/**\n * Apply registered plugins asynchronously.\n * @param {import('./jsmind.js').default} jm\n * @param {Record<string, object>} options\n */\nexport function apply(jm, options) {\n $.w.setTimeout(function () {\n _apply(jm, options);\n }, 0);\n}\n\n/**\n * @param {import('./jsmind.js').default} jm\n * @param {Record<string, object>} options */\nfunction _apply(jm, options) {\n plugin_data.plugins.forEach(p => p.fn_init(jm, options[p.name]));\n}\n\nexport class Plugin {\n /**\n * @template [TOptions=object]\n * @param {string} name\n * @param {(jm: import('./jsmind.js').default, options: TOptions)=>void} fn_init\n */\n constructor(name, fn_init) {\n if (!name) {\n throw new Error('plugin must has a name');\n }\n if (!fn_init || typeof fn_init !== 'function') {\n throw new Error('plugin must has an init function');\n }\n this.name = name;\n this.fn_init = fn_init;\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { logger } from './jsmind.common.js';\n\n/**\n * Enhanced Plugin Manager\n * Manages the lifecycle of enhanced plugins with synchronous initialization,\n * preload support, and lifecycle hooks.\n */\nexport class EnhancedPluginManager {\n /**\n * @param {import('./jsmind.js').default} jm - jsMind instance\n */\n constructor(jm) {\n this.jm = jm;\n /** @type {Map<string, EnhancedPlugin>} */\n this.plugins = new Map();\n }\n\n /**\n * Initialize preload plugins (before core modules)\n */\n initPreloadPlugins() {\n const preloadPlugins = this.jm.constructor.enhancedPluginList.filter(d => d.preload);\n logger.info('Initializing ' + preloadPlugins.length + ' preload plugins');\n preloadPlugins.forEach(descriptor => {\n this._initPlugin(descriptor);\n });\n }\n\n /**\n * Initialize normal plugins (after core modules)\n */\n initNormalPlugins() {\n const normalPlugins = this.jm.constructor.enhancedPluginList.filter(d => !d.preload);\n logger.info('Initializing ' + normalPlugins.length + ' normal plugins');\n normalPlugins.forEach(descriptor => {\n this._initPlugin(descriptor);\n });\n }\n\n /**\n * Internal method: Initialize a single plugin\n * @param {PluginDescriptor} descriptor\n * @private\n */\n _initPlugin(descriptor) {\n try {\n const { PluginClass, pluginOpt } = descriptor;\n\n // Check instanceName\n if (!PluginClass.instanceName) {\n throw new Error('Plugin ' + PluginClass.name + ' must define static instanceName');\n }\n\n // Check naming conflict\n if (this.plugins.has(PluginClass.instanceName)) {\n logger.warn(\n 'Plugin ' + PluginClass.instanceName + ' already exists, will be replaced'\n );\n }\n\n // Instantiate plugin\n const instance = new PluginClass({\n jm: this.jm,\n pluginOpt: pluginOpt || {},\n });\n\n // Save instance\n this.plugins.set(PluginClass.instanceName, instance);\n this.jm[PluginClass.instanceName] = instance;\n descriptor.instance = instance;\n\n logger.info('Enhanced plugin ' + PluginClass.instanceName + ' initialized');\n } catch (error) {\n logger.error('Failed to initialize plugin ' + descriptor.PluginClass.name + ':', error);\n }\n }\n\n /**\n * Remove a plugin\n * @param {typeof EnhancedPlugin} PluginClass\n */\n removePlugin(PluginClass) {\n const instanceName = PluginClass.instanceName;\n if (!instanceName) {\n return;\n }\n\n const instance = this.plugins.get(instanceName);\n if (!instance) {\n return;\n }\n\n try {\n // Call lifecycle hook\n if (typeof instance.beforePluginRemove === 'function') {\n instance.beforePluginRemove();\n }\n\n // Remove from Map\n this.plugins.delete(instanceName);\n\n // Remove from jsMind instance\n delete this.jm[instanceName];\n\n // Remove from plugin list\n const list = this.jm.constructor.enhancedPluginList;\n const index = list.findIndex(d => d.PluginClass === PluginClass);\n if (index !== -1) {\n list.splice(index, 1);\n }\n\n logger.info('Enhanced plugin ' + instanceName + ' removed');\n } catch (error) {\n logger.error('Failed to remove plugin ' + instanceName + ':', error);\n }\n }\n\n /**\n * Destroy all plugins\n */\n destroyAllPlugins() {\n this.plugins.forEach((instance, instanceName) => {\n try {\n // Call lifecycle hook\n if (typeof instance.beforePluginDestroy === 'function') {\n instance.beforePluginDestroy();\n }\n } catch (error) {\n logger.error('Failed to destroy plugin ' + instanceName + ':', error);\n }\n });\n\n this.plugins.clear();\n }\n\n /**\n * Get plugin instance by name\n * @param {string} instanceName\n * @returns {EnhancedPlugin | undefined}\n */\n getPlugin(instanceName) {\n return this.plugins.get(instanceName);\n }\n}\n\n/**\n * Enhanced Plugin Base Class\n * Provides standard interface for enhanced plugins\n */\nexport class EnhancedPlugin {\n /**\n * Plugin instance name (must be defined by subclass)\n * @type {string}\n */\n static instanceName = '';\n\n /**\n * Whether to initialize before core modules\n * @type {boolean}\n */\n static preload = false;\n\n /**\n * @param {{ jm: import('./jsmind.js').default, pluginOpt: object }} params\n */\n constructor({ jm, pluginOpt }) {\n this.jm = jm;\n this.options = pluginOpt || {};\n }\n\n /**\n * Called before plugin is removed\n * Override this method to clean up resources\n */\n beforePluginRemove() {\n // Default implementation: do nothing\n }\n\n /**\n * Called before jsMind instance is destroyed\n * Override this method to clean up resources\n */\n beforePluginDestroy() {\n // Default implementation: call beforePluginRemove\n this.beforePluginRemove();\n }\n}\n\n/**\n * Plugin descriptor\n * @typedef {object} PluginDescriptor\n * @property {typeof EnhancedPlugin} PluginClass - Plugin class\n * @property {string} instanceName - Plugin instance name\n * @property {boolean} preload - Whether to preload\n * @property {object} pluginOpt - Plugin options\n * @property {EnhancedPlugin | null} instance - Plugin instance (after initialization)\n */\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { __version__, logger, EventType, Direction, LogLevel } from './jsmind.common.js';\nimport { merge_option } from './jsmind.option.js';\nimport { Mind } from './jsmind.mind.js';\nimport { Node } from './jsmind.node.js';\nimport { DataProvider } from './jsmind.data_provider.js';\nimport { LayoutProvider } from './jsmind.layout_provider.js';\nimport { ViewProvider } from './jsmind.view_provider.js';\nimport { ShortcutProvider } from './jsmind.shortcut_provider.js';\nimport { Plugin, register as _register_plugin, apply as apply_plugins } from './jsmind.plugin.js';\nimport { EnhancedPluginManager, EnhancedPlugin } from './jsmind.enhanced-plugin.js';\nimport { format } from './jsmind.format.js';\nimport { $ } from './jsmind.dom.js';\nimport { util as _util } from './jsmind.util.js';\n\n/**\n * Event callback payload\n * @typedef {{ evt?: string, data?: unknown[], node?: string }} EventData\n */\n\n/**\n * jsMind runtime: orchestrates data/layout/view/shortcut and exposes public API.\n */\nexport default class jsMind {\n static mind = Mind;\n static node = Node;\n static direction = Direction;\n static event_type = EventType;\n static $ = $;\n static plugin = Plugin;\n static register_plugin = _register_plugin;\n static util = _util;\n static enhanced_plugin = EnhancedPlugin;\n\n /** @type {Array<import('./jsmind.enhanced-plugin.js').PluginDescriptor>} */\n static enhancedPluginList = [];\n\n /**\n * Register an enhanced plugin\n * @param {typeof EnhancedPlugin} PluginClass - Plugin class\n * @param {object} [options={}] - Plugin options\n * @returns {typeof jsMind}\n */\n static usePlugin(PluginClass, options = {}) {\n // Check if already registered\n const exists = jsMind.enhancedPluginList.some(d => d.PluginClass === PluginClass);\n if (exists) {\n logger.warn('Plugin ' + PluginClass.name + ' already registered');\n return jsMind;\n }\n\n // Check instanceName\n if (!PluginClass.instanceName) {\n throw new Error('Plugin ' + PluginClass.name + ' must define static instanceName');\n }\n\n // Add to plugin list\n jsMind.enhancedPluginList.push({\n PluginClass,\n instanceName: PluginClass.instanceName,\n preload: PluginClass.preload || false,\n pluginOpt: options,\n instance: null,\n });\n\n return jsMind;\n }\n\n /**\n * Check if an enhanced plugin is registered\n * @param {typeof EnhancedPlugin} PluginClass - Plugin class\n * @returns {boolean}\n */\n static hasEnhancedPlugin(PluginClass) {\n return jsMind.enhancedPluginList.some(d => d.PluginClass === PluginClass);\n }\n\n /**\n * Create a jsMind instance.\n * @param {import('./jsmind.option.js').JsMindRuntimeOptions} options\n */\n constructor(options) {\n jsMind.current = this;\n this.options = merge_option(options);\n logger.level(LogLevel[this.options.log_level]);\n this.version = __version__;\n this.initialized = false;\n this.mind = null;\n /** @type {Array<(type: number, data: EventData) => void>} */\n this.event_handles = [];\n this.init();\n }\n\n /** Initialize sub-systems and plugins. */\n init() {\n if (!!this.initialized) {\n return;\n }\n this.initialized = true;\n\n // Initialize enhanced plugin manager\n this.enhancedPluginManager = new EnhancedPluginManager(this);\n\n // Initialize preload plugins (before core modules)\n this.enhancedPluginManager.initPreloadPlugins();\n\n var opts_layout = {\n mode: this.options.mode,\n hspace: this.options.layout.hspace,\n vspace: this.options.layout.vspace,\n pspace: this.options.layout.pspace,\n cousin_space: this.options.layout.cousin_space,\n };\n var opts_view = {\n container: this.options.container,\n support_html: this.options.support_html,\n engine: this.options.view.engine,\n enable_device_pixel_ratio: this.options.view.enable_device_pixel_ratio,\n hmargin: this.options.view.hmargin,\n vmargin: this.options.view.vmargin,\n line_width: this.options.view.line_width,\n line_color: this.options.view.line_color,\n line_style: this.options.view.line_style,\n custom_line_render: this.options.view.custom_line_render,\n draggable: this.options.view.draggable,\n hide_scrollbars_when_draggable: this.options.view.hide_scrollbars_when_draggable,\n node_overflow: this.options.view.node_overflow,\n zoom: this.options.view.zoom,\n custom_node_render: this.options.view.custom_node_render,\n expander_style: this.options.view.expander_style,\n };\n // create instance of function provider\n this.data = new DataProvider(this);\n this.layout = new LayoutProvider(this, opts_layout);\n this.view = new ViewProvider(this, opts_view);\n this.shortcut = new ShortcutProvider(this, this.options.shortcut);\n\n this.data.init();\n this.layout.init();\n this.view.init();\n this.shortcut.init();\n\n this._event_bind();\n\n // Initialize normal plugins (after core modules)\n this.enhancedPluginManager.initNormalPlugins();\n\n // Apply old plugins (asynchronously)\n apply_plugins(this, this.options.plugin);\n }\n /** @returns {boolean} whether current mind map is editable */\n get_editable() {\n return this.options.editable;\n }\n /** enable editing */\n enable_edit() {\n this.options.editable = true;\n }\n /** disable editing */\n disable_edit() {\n this.options.editable = false;\n }\n /** @returns {boolean} whether view is draggable */\n get_view_draggable() {\n return this.options.view.draggable;\n }\n /** enable view dragging */\n enable_view_draggable() {\n this.options.view.draggable = true;\n this.view.setup_canvas_draggable(true);\n }\n /** disable view dragging */\n disable_view_draggable() {\n this.options.view.draggable = false;\n this.view.setup_canvas_draggable(false);\n }\n // options are 'mousedown', 'click', 'dblclick', 'mousewheel'\n /**\n * Enable default event handle.\n * @param {'mousedown'|'click'|'dblclick'|'mousewheel'} event_handle\n */\n enable_event_handle(event_handle) {\n this.options.default_event_handle['enable_' + event_handle + '_handle'] = true;\n }\n // options are 'mousedown', 'click', 'dblclick', 'mousewheel'\n /**\n * Disable default event handle.\n * @param {'mousedown'|'click'|'dblclick'|'mousewheel'} event_handle\n */\n disable_event_handle(event_handle) {\n this.options.default_event_handle['enable_' + event_handle + '_handle'] = false;\n }\n /**\n * Set theme name.\n * @param {string|null=} theme\n */\n set_theme(theme) {\n var theme_old = this.options.theme;\n this.options.theme = !!theme ? theme : null;\n if (theme_old != this.options.theme) {\n this.view.reset_theme();\n this.view.reset_custom_style();\n }\n }\n /** bind internal DOM events */\n _event_bind() {\n this.view.add_event(this, 'mousedown', this.mousedown_handle);\n this.view.add_event(this, 'click', this.click_handle);\n this.view.add_event(this, 'dblclick', this.dblclick_handle);\n this.view.add_event(this, 'wheel', this.mousewheel_handle, true);\n }\n /** @param {MouseEvent} e */\n mousedown_handle(e) {\n if (!this.options.default_event_handle['enable_mousedown_handle']) {\n return;\n }\n var element = e.target || event.srcElement;\n var node_id = this.view.get_binded_nodeid(element);\n if (!!node_id) {\n if (this.view.is_node(element)) {\n this.select_node(node_id);\n }\n } else {\n this.select_clear();\n }\n }\n /** @param {MouseEvent} e */\n click_handle(e) {\n if (!this.options.default_event_handle['enable_click_handle']) {\n return;\n }\n var element = e.target || event.srcElement;\n var is_expander = this.view.is_expander(element);\n if (is_expander) {\n var node_id = this.view.get_binded_nodeid(element);\n if (!!node_id) {\n this.toggle_node(node_id);\n }\n }\n }\n /** @param {MouseEvent} e */\n dblclick_handle(e) {\n if (!this.options.default_event_handle['enable_dblclick_handle']) {\n return;\n }\n if (this.get_editable()) {\n var element = e.target || event.srcElement;\n var is_node = this.view.is_node(element);\n if (is_node) {\n var node_id = this.view.get_binded_nodeid(element);\n if (!!node_id) {\n this.begin_edit(node_id);\n }\n }\n }\n }\n // Use [Ctrl] + Mousewheel, to zoom in/out.\n /** @param {WheelEvent} e */\n mousewheel_handle(e) {\n // Test if mousewheel option is enabled and Ctrl key is pressed.\n var kc = (e.metaKey << 13) + (e.ctrlKey << 12) + (e.altKey << 11) + (e.shiftKey << 10);\n if (\n !this.options.default_event_handle['enable_mousewheel_handle'] ||\n this.options.view.zoom.mask_key !== kc\n ) {\n return;\n }\n var evt = e || event;\n // Avoid default page scrolling behavior.\n evt.preventDefault();\n\n if (evt.deltaY < 0) {\n this.view.zoom_in(evt); // wheel down\n } else {\n this.view.zoom_out(evt);\n }\n }\n /**\n * Begin editing a node.\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {boolean|void}\n */\n begin_edit(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return false;\n } else {\n return this.begin_edit(the_node);\n }\n }\n if (this.get_editable()) {\n this.view.edit_node_begin(node);\n } else {\n logger.error('fail, this mind map is not editable.');\n return;\n }\n }\n /** End editing */\n end_edit() {\n this.view.edit_node_end();\n }\n /**\n * Toggle a node's expanded state.\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {void}\n */\n toggle_node(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return;\n } else {\n this.toggle_node(the_node);\n return;\n }\n }\n if (node.isroot) {\n return;\n }\n this.view.save_location(node);\n this.layout.toggle_node(node);\n this.view.relayout();\n this.view.restore_location(node);\n }\n /**\n * Expand a node.\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {void}\n */\n expand_node(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return;\n } else {\n this.expand_node(the_node);\n return;\n }\n }\n if (node.isroot) {\n return;\n }\n this.view.save_location(node);\n this.layout.expand_node(node);\n this.view.relayout();\n this.view.restore_location(node);\n }\n /**\n * Collapse a node.\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {void}\n */\n collapse_node(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return;\n } else {\n this.collapse_node(the_node);\n return;\n }\n }\n if (node.isroot) {\n return;\n }\n this.view.save_location(node);\n this.layout.collapse_node(node);\n this.view.relayout();\n this.view.restore_location(node);\n }\n /** Expand all nodes */\n expand_all() {\n this.layout.expand_all();\n this.view.relayout();\n }\n /** Collapse all nodes */\n collapse_all() {\n this.layout.collapse_all();\n this.view.relayout();\n }\n /**\n * Expand nodes up to a specified depth level.\n * @param {number} depth\n */\n expand_to_depth(depth) {\n this.layout.expand_to_depth(depth);\n this.view.relayout();\n }\n /** reset view/layout/data */\n _reset() {\n this.invoke_event_handle(EventType.reset, { data: [] });\n this.view.reset();\n this.layout.reset();\n this.data.reset();\n }\n /**\n * Internal show flow.\n * @param {object | null} mind\n * @param {boolean=} skip_centering\n */\n _show(mind, skip_centering) {\n var m = mind || format.node_array.example;\n this.mind = this.data.load(m);\n if (!this.mind) {\n logger.error('data.load error');\n return;\n } else {\n logger.debug('data.load ok');\n }\n\n this.view.load();\n logger.debug('view.load ok');\n\n this.layout.layout();\n logger.debug('layout.layout ok');\n\n this.view.show(!skip_centering);\n logger.debug('view.show ok');\n\n this.invoke_event_handle(EventType.show, { data: [mind] });\n }\n /**\n * Show a mind (or example) on the canvas.\n * @param {object | null} mind\n * @param {boolean=} skip_centering\n */\n show(mind, skip_centering) {\n this._reset();\n this._show(mind, skip_centering);\n }\n /** @returns {{name:string,author:string,version:string}} */\n get_meta() {\n return {\n name: this.mind.name,\n author: this.mind.author,\n version: this.mind.version,\n };\n }\n /**\n * Serialize current mind to given format.\n * @param {'node_tree'|'node_array'|'freemind'|'text'} [data_format]\n * @returns {object}\n */\n get_data(data_format) {\n var df = data_format || 'node_tree';\n return this.data.get_data(df);\n }\n /** @returns {import('./jsmind.node.js').Node} */\n get_root() {\n return this.mind.root;\n }\n /**\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {import('./jsmind.node.js').Node}\n */\n get_node(node) {\n if (Node.is_node(node)) {\n return node;\n }\n return this.mind.get_node(node);\n }\n /**\n * Get the level/depth of a node in the mind map.\n * @param {string | import('./jsmind.node.js').Node} node - Node id or Node instance\n * @returns {number} Node level (root node is 0, its children are 1, etc.)\n */\n get_node_level(node) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.warn('the node[id=' + node + '] can not be found.');\n return -1;\n }\n\n // Root node is at level 0\n if (the_node.isroot) {\n return 0;\n }\n\n var level = 0;\n var current = the_node;\n\n // Traverse up to root node, counting levels\n while (current.parent && !current.parent.isroot) {\n level++;\n current = current.parent;\n }\n\n // Add 1 for children of root node\n return level + 1;\n }\n /**\n * Add node data to the mind map without triggering UI refresh.\n * @private\n * @param {import('./jsmind.node.js').Node} parent_node\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction\n * @returns {import('./jsmind.node.js').Node|null}\n */\n _add_node_data(parent_node, node_id, topic, data, direction) {\n var dir = Direction.of(direction);\n if (dir === undefined) {\n dir = this.layout.calculate_next_child_direction(parent_node);\n }\n\n var node = this.mind.add_node(parent_node, node_id, topic, data, dir);\n if (!!node) {\n this.view.add_node(node);\n this.view.reset_node_custom_style(node);\n }\n return node;\n }\n\n /**\n * Refresh UI after node changes.\n * @private\n * @param {import('./jsmind.node.js').Node} parent_node\n */\n _refresh_node_ui(parent_node) {\n this.layout.layout();\n this.view.show(false);\n this.expand_node(parent_node);\n }\n\n /**\n * Add a new node to the mind map.\n * @param {string | import('./jsmind.node.js').Node} parent_node\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @returns {import('./jsmind.node.js').Node|null}\n */\n add_node(parent_node, node_id, topic, data, direction) {\n if (!this.get_editable()) {\n logger.error('fail, this mind map is not editable');\n return null;\n }\n\n var the_parent_node = this.get_node(parent_node);\n if (!the_parent_node) {\n logger.error('parent node not found');\n return null;\n }\n\n var node = this._add_node_data(the_parent_node, node_id, topic, data, direction);\n if (!!node) {\n this._refresh_node_ui(the_parent_node);\n this.invoke_event_handle(EventType.edit, {\n evt: 'add_node',\n data: [the_parent_node.id, node_id, topic, data, Direction.of(direction)],\n node: node_id,\n });\n }\n return node;\n }\n\n /**\n * Add multiple nodes in batch.\n *\n * This method provides atomic batch node creation with automatic rollback on failure.\n * All nodes are created in a single operation, and if any node fails to create,\n * all previously created nodes in this batch will be automatically removed.\n *\n * **Note**: This is a batch operation API that uses standard field names only.\n * For data import with custom fieldNames, use `show()` instead.\n *\n * @example\n * // Using standard field names\n * jm.add_nodes('parent_id', [\n * { id: 'node1', topic: 'Node 1', data: { color: 'red' }, children: [\n * { id: 'node1-1', topic: 'Child 1' }\n * ]}\n * ]);\n *\n * @param {string | import('./jsmind.node.js').Node} parent_node - Parent node for all new nodes\n * @param {Array<{id: string, topic: string, data?: Record<string, any>, direction?: ('left'|'center'|'right'|'-1'|'0'|'1'|number), children?: Array}>} nodes_data - Array of node data objects with standard field names (id, topic, children, data, direction)\n * @returns {Array<import('./jsmind.node.js').Node|null>} Array of created nodes (flattened from all levels)\n */\n add_nodes(parent_node, nodes_data) {\n if (!this.get_editable()) {\n logger.error('fail, this mind map is not editable');\n return [];\n }\n\n var the_parent_node = this.get_node(parent_node);\n if (!the_parent_node) {\n logger.error('parent node not found');\n return [];\n }\n\n if (!Array.isArray(nodes_data) || nodes_data.length === 0) {\n logger.warn('nodes_data should be a non-empty array');\n return [];\n }\n\n const expected_count = this._count_expected_nodes(nodes_data);\n let created_nodes = nodes_data\n .map(node_data => this._add_nodes_recursive(the_parent_node, node_data))\n .flat()\n .filter(n => n !== null);\n\n const actual_count = created_nodes.length;\n\n // Atomic operation: either all nodes succeed or cleanup all partial nodes\n if (actual_count === expected_count) {\n // All nodes created successfully, refresh UI\n this._refresh_node_ui(the_parent_node);\n this.invoke_event_handle(EventType.edit, {\n evt: 'add_nodes',\n data: [the_parent_node.id, nodes_data],\n nodes: created_nodes.map(node => node.id),\n });\n return created_nodes;\n } else {\n // Cleanup partially created nodes to ensure atomicity\n logger.warn(\n `Expected ${expected_count} nodes, but only created ${actual_count}. Cleaning up...`\n );\n this._cleanup_partial_nodes(created_nodes);\n return [];\n }\n }\n\n /**\n * Recursively add nodes using standard field names.\n * This is a batch operation API that uses standard field names only.\n * For data import with custom fieldNames, use `show()` instead.\n * @private\n * @param {import('./jsmind.node.js').Node} parent_node\n * @param {object} node_data - Node data object with standard field names (id, topic, children, data, direction)\n * @returns {Array<import('./jsmind.node.js').Node|null>}\n */\n _add_nodes_recursive(parent_node, node_data) {\n var created_nodes = [];\n\n // Validate required fields (using standard field names only)\n if (!node_data.id || !node_data.topic) {\n logger.warn('invalid node data:', node_data);\n return [];\n }\n\n // Create the node using standard field names\n var new_node = this._add_node_data(\n parent_node,\n node_data.id,\n node_data.topic,\n node_data.data || {},\n node_data.direction\n );\n\n if (new_node) {\n created_nodes.push(new_node);\n // Process children using standard field name\n if (Array.isArray(node_data.children)) {\n const sub_nodes = node_data.children\n .map(child => this._add_nodes_recursive(new_node, child))\n .flat();\n created_nodes = created_nodes.concat(sub_nodes);\n }\n }\n\n return created_nodes;\n }\n\n /**\n * Count expected nodes recursively.\n * Supports custom field names via options.fieldNames configuration.\n * @private\n * @param {Array} nodes_data\n * @returns {number}\n */\n _count_expected_nodes(nodes_data) {\n if (!Array.isArray(nodes_data)) {\n return 0;\n }\n\n // Get field names from options (support custom field names)\n var fn = this.options.fieldNames || {};\n var childrenKey = fn.children || 'children';\n\n return nodes_data.reduce((count, node_data) => {\n count++; // Count current node\n // Use custom children field name\n count += this._count_expected_nodes(node_data && node_data[childrenKey]);\n return count;\n }, 0);\n }\n\n /**\n * Clean up partially created nodes without triggering UI refresh for each node.\n * @private\n * @param {Array<import('./jsmind.node.js').Node>} created_nodes\n */\n _cleanup_partial_nodes(created_nodes) {\n if (created_nodes.length === 0) return;\n // Remove all created nodes in reverse order to avoid parent-child issues\n // Use direct view and mind operations without triggering layout/show\n [...created_nodes].reverse().forEach(node => {\n if (node && !node.isroot) {\n // Remove from view without triggering layout\n this.view.remove_node(node);\n // Remove from mind model without triggering layout\n this.mind.remove_node(node);\n }\n });\n }\n\n /**\n * Insert a node before target node.\n * @param {string | import('./jsmind.node.js').Node} node_before\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @returns {import('./jsmind.node.js').Node|null}\n */\n insert_node_before(node_before, node_id, topic, data, direction) {\n if (this.get_editable()) {\n var the_node_before = this.get_node(node_before);\n var dir = Direction.of(direction);\n if (dir === undefined) {\n dir = this.layout.calculate_next_child_direction(the_node_before.parent);\n }\n var node = this.mind.insert_node_before(the_node_before, node_id, topic, data, dir);\n if (!!node) {\n this.view.add_node(node);\n this.layout.layout();\n this.view.show(false);\n this.invoke_event_handle(EventType.edit, {\n evt: 'insert_node_before',\n data: [the_node_before.id, node_id, topic, data, dir],\n node: node_id,\n });\n }\n return node;\n } else {\n logger.error('fail, this mind map is not editable');\n return null;\n }\n }\n /**\n * Insert a node after target node.\n * @param {string | import('./jsmind.node.js').Node} node_after\n * @param {string} node_id\n * @param {string} topic\n * @param {Record<string, any>=} data\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1)\n * @returns {import('./jsmind.node.js').Node|null}\n */\n insert_node_after(node_after, node_id, topic, data, direction) {\n if (this.get_editable()) {\n var the_node_after = this.get_node(node_after);\n var dir = Direction.of(direction);\n if (dir === undefined) {\n dir = this.layout.calculate_next_child_direction(the_node_after.parent);\n }\n var node = this.mind.insert_node_after(the_node_after, node_id, topic, data, dir);\n if (!!node) {\n this.view.add_node(node);\n this.layout.layout();\n this.view.show(false);\n this.invoke_event_handle(EventType.edit, {\n evt: 'insert_node_after',\n data: [the_node_after.id, node_id, topic, data, dir],\n node: node_id,\n });\n }\n return node;\n } else {\n logger.error('fail, this mind map is not editable');\n return null;\n }\n }\n /**\n * Remove a node.\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {boolean}\n */\n remove_node(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return false;\n } else {\n return this.remove_node(the_node);\n }\n }\n if (this.get_editable()) {\n if (node.isroot) {\n logger.error('fail, can not remove root node');\n return false;\n }\n var node_id = node.id;\n var parent_id = node.parent.id;\n var parent_node = this.get_node(parent_id);\n this.view.save_location(parent_node);\n this.view.remove_node(node);\n this.mind.remove_node(node);\n this.layout.layout();\n this.view.show(false);\n this.view.restore_location(parent_node);\n this.invoke_event_handle(EventType.edit, {\n evt: 'remove_node',\n data: [node_id],\n node: parent_id,\n });\n return true;\n } else {\n logger.error('fail, this mind map is not editable');\n return false;\n }\n }\n /**\n * Update the topic (text content) and/or data of a node.\n * @param {string} node_id\n * @param {string|{topic?:string, data?:Record<string,any>}} topic_or_options - Topic string or options object\n */\n update_node(node_id, topic_or_options) {\n if (this.get_editable()) {\n var node = this.get_node(node_id);\n if (!!node) {\n var topic = null;\n var data = null;\n\n // Parse parameters\n if (typeof topic_or_options === 'string') {\n topic = topic_or_options;\n } else if (typeof topic_or_options === 'object' && topic_or_options !== null) {\n topic = topic_or_options.topic;\n data = topic_or_options.data;\n }\n\n var topicChanged = false;\n var dataChanged = false;\n\n // Update topic if provided\n if (topic !== undefined && topic !== null) {\n if (_util.text.is_empty(topic)) {\n logger.warn('fail, topic can not be empty');\n return;\n }\n if (node.topic !== topic) {\n node.topic = topic;\n topicChanged = true;\n }\n }\n\n // Merge data with existing data\n if (data && typeof data === 'object') {\n for (var key in data) {\n if (data.hasOwnProperty(key)) {\n node.data[key] = data[key];\n dataChanged = true;\n }\n }\n }\n\n if (!topicChanged && !dataChanged) {\n logger.info('nothing changed');\n this.view.update_node(node);\n return;\n }\n\n this.view.update_node(node);\n this.layout.layout();\n this.view.show(false);\n this.invoke_event_handle(EventType.edit, {\n evt: 'update_node',\n data: [node_id, topic, data],\n node: node_id,\n });\n }\n } else {\n logger.error('fail, this mind map is not editable');\n return;\n }\n }\n /**\n * Move a node and optionally change direction.\n * @param {string} node_id\n * @param {string=} before_id - The ID of the node before which to place the moved node. Special values: \"_first_\", \"_last_\"\n * @param {string=} parent_id\n * @param {('left'|'center'|'right'|'-1'|'0'|'1'|number)=} direction - Direction for node placement. Supports string values ('left', 'center', 'right'), numeric strings ('-1', '0', '1'), and numbers (-1, 0, 1). Only effective for second-level nodes (children of root). If not provided, direction will be determined automatically.\n */\n move_node(node_id, before_id, parent_id, direction) {\n if (this.get_editable()) {\n var node = this.get_node(node_id);\n var updated_node = this.mind.move_node(node, before_id, parent_id, direction);\n if (!!updated_node) {\n this.view.update_node(updated_node);\n this.layout.layout();\n this.view.show(false);\n this.invoke_event_handle(EventType.edit, {\n evt: 'move_node',\n data: [node_id, before_id, parent_id, direction],\n node: node_id,\n });\n }\n } else {\n logger.error('fail, this mind map is not editable');\n return;\n }\n }\n /**\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {void}\n */\n select_node(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return;\n } else {\n this.select_node(the_node);\n return;\n }\n }\n if (!this.layout.is_visible(node)) {\n return;\n }\n this.mind.selected = node;\n this.view.select_node(node);\n this.invoke_event_handle(EventType.select, { evt: 'select_node', data: [], node: node.id });\n }\n /**\n * Get the currently selected node.\n *\n * This is a query API that returns the internal Node instance.\n * For data export with custom fieldNames, use `get_data()` instead.\n *\n * @returns {import('./jsmind.node.js').Node|null} Node instance or null\n */\n get_selected_node() {\n if (!!this.mind) {\n return this.mind.selected;\n } else {\n return null;\n }\n }\n /** clear selection */\n select_clear() {\n if (!!this.mind) {\n this.mind.selected = null;\n this.view.select_clear();\n }\n }\n /** @param {string | import('./jsmind.node.js').Node} node */\n is_node_visible(node) {\n return this.layout.is_visible(node);\n }\n /**\n * Scroll the mind map to center the specified node.\n * @param {string | import('./jsmind.node.js').Node} node\n */\n scroll_node_to_center(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n } else {\n this.scroll_node_to_center(the_node);\n }\n return;\n }\n this.view.center_node(node);\n }\n /**\n * Find the previous sibling node of the given node.\n *\n * @param {string | import('./jsmind.node.js').Node} node - Node id or Node instance\n * @returns {import('./jsmind.node.js').Node | null}\n */\n find_node_before(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return;\n } else {\n return this.find_node_before(the_node);\n }\n }\n if (node.isroot) {\n return null;\n }\n var n = null;\n if (node.parent.isroot) {\n var c = node.parent.children;\n var prev = null;\n var ni = null;\n for (var i = 0; i < c.length; i++) {\n ni = c[i];\n if (node.direction === ni.direction) {\n if (node.id === ni.id) {\n n = prev;\n }\n prev = ni;\n }\n }\n } else {\n n = this.mind.get_node_before(node);\n }\n return n;\n }\n /**\n * Find the next sibling node of the given node.\n * @param {string | import('./jsmind.node.js').Node} node\n * @returns {import('./jsmind.node.js').Node | null}\n */\n find_node_after(node) {\n if (!Node.is_node(node)) {\n var the_node = this.get_node(node);\n if (!the_node) {\n logger.error('the node[id=' + node + '] can not be found.');\n return;\n } else {\n return this.find_node_after(the_node);\n }\n }\n if (node.isroot) {\n return null;\n }\n var n = null;\n if (node.parent.isroot) {\n var c = node.parent.children;\n var found = false;\n var ni = null;\n for (var i = 0; i < c.length; i++) {\n ni = c[i];\n if (node.direction === ni.direction) {\n if (found) {\n n = ni;\n break;\n }\n if (node.id === ni.id) {\n found = true;\n }\n }\n }\n } else {\n n = this.mind.get_node_after(node);\n }\n return n;\n }\n /**\n * Set background and foreground colors for a node.\n * @param {string} node_id\n * @param {string=} bg_color\n * @param {string=} fg_color\n * @returns {void}\n */\n set_node_color(node_id, bg_color, fg_color) {\n if (this.get_editable()) {\n var node = this.mind.get_node(node_id);\n if (!!node) {\n if (!!bg_color) {\n node.data['background-color'] = bg_color;\n }\n if (!!fg_color) {\n node.data['foreground-color'] = fg_color;\n }\n this.view.reset_node_custom_style(node);\n }\n } else {\n logger.error('fail, this mind map is not editable');\n return null;\n }\n }\n /**\n * Set font style for a node.\n * @param {string} node_id\n * @param {number=} size\n * @param {string=} weight\n * @param {string=} style\n * @returns {void}\n */\n set_node_font_style(node_id, size, weight, style) {\n if (this.get_editable()) {\n var node = this.mind.get_node(node_id);\n if (!!node) {\n if (!!size) {\n node.data['font-size'] = size;\n }\n if (!!weight) {\n node.data['font-weight'] = weight;\n }\n if (!!style) {\n node.data['font-style'] = style;\n }\n this.view.reset_node_custom_style(node);\n this.view.update_node(node);\n this.layout.layout();\n this.view.show(false);\n }\n } else {\n logger.error('fail, this mind map is not editable');\n return null;\n }\n }\n /**\n * Set background image for a node.\n * @param {string} node_id\n * @param {string=} image\n * @param {number=} width\n * @param {number=} height\n * @param {number=} rotation\n * @returns {void}\n */\n set_node_background_image(node_id, image, width, height, rotation) {\n if (this.get_editable()) {\n var node = this.mind.get_node(node_id);\n if (!!node) {\n if (!!image) {\n node.data['background-image'] = image;\n }\n if (!!width) {\n node.data['width'] = width;\n }\n if (!!height) {\n node.data['height'] = height;\n }\n if (!!rotation) {\n node.data['background-rotation'] = rotation;\n }\n this.view.reset_node_custom_style(node);\n this.view.update_node(node);\n this.layout.layout();\n this.view.show(false);\n }\n } else {\n logger.error('fail, this mind map is not editable');\n return null;\n }\n }\n /**\n * @param {string} node_id\n * @param {number} rotation\n * @returns {void}\n */\n set_node_background_rotation(node_id, rotation) {\n if (this.get_editable()) {\n var node = this.mind.get_node(node_id);\n if (!!node) {\n if (!node.data['background-image']) {\n logger.error(\n 'fail, only can change rotation angle of node with background image'\n );\n return null;\n }\n node.data['background-rotation'] = rotation;\n this.view.reset_node_custom_style(node);\n this.view.update_node(node);\n this.layout.layout();\n this.view.show(false);\n }\n } else {\n logger.error('fail, this mind map is not editable');\n return null;\n }\n }\n /** trigger view resize */\n resize() {\n this.view.resize();\n }\n // callback(type ,data)\n /** @param {(type:number, data: EventData)=>void} callback */\n add_event_listener(callback) {\n if (typeof callback === 'function') {\n this.event_handles.push(callback);\n }\n }\n /** clear event listeners */\n clear_event_listener() {\n this.event_handles = [];\n }\n /** @param {number} type @param {EventData} data */\n invoke_event_handle(type, data) {\n var j = this;\n $.w.setTimeout(function () {\n j._invoke_event_handle(type, data);\n }, 0);\n }\n /** @param {number} type @param {EventData} data */\n _invoke_event_handle(type, data) {\n var l = this.event_handles.length;\n for (var i = 0; i < l; i++) {\n this.event_handles[i](type, data);\n }\n }\n\n /**\n * Remove an enhanced plugin\n * @param {typeof EnhancedPlugin} PluginClass - Plugin class\n */\n removePlugin(PluginClass) {\n if (this.enhancedPluginManager) {\n this.enhancedPluginManager.removePlugin(PluginClass);\n }\n }\n\n /**\n * Get an enhanced plugin instance\n * @param {string} instanceName - Plugin instance name\n * @returns {EnhancedPlugin | undefined}\n */\n getPlugin(instanceName) {\n if (this.enhancedPluginManager) {\n return this.enhancedPluginManager.getPlugin(instanceName);\n }\n return undefined;\n }\n\n /**\n * Destroy the jsMind instance and clean up resources\n */\n destroy() {\n // Destroy enhanced plugins\n if (this.enhancedPluginManager) {\n this.enhancedPluginManager.destroyAllPlugins();\n }\n\n // Clear event listeners\n this.clear_event_listener();\n\n // Clean up view\n if (this.view) {\n this.view.reset();\n }\n\n // Clear mind data\n this.mind = null;\n this.initialized = false;\n }\n\n /**\n * Deprecated: static show constructor helper.\n * @param {import('./jsmind.option.js').JsMindRuntimeOptions} options\n * @param {object | null} mind\n * @returns {jsMind}\n */\n static show(options, mind) {\n logger.warn(\n '`jsMind.show(options, mind)` is deprecated, please use `jm = new jsMind(options); jm.show(mind);` instead'\n );\n var _jm = new jsMind(options);\n _jm.show(mind);\n return _jm;\n }\n}\n"],"names":["__version__","String","prototype","startsWith","p","this","slice","length","Direction","left","center","right","of","dir","parseInt","toLowerCase","EventType","show","resize","edit","select","reset","history_change","LogLevel","debug","info","warn","error","disable","_noop","logger","console","level","log","log_level","$","constructor","w","d","document","g","id","getElementById","c","tag","createElement","t","n","hasChildNodes","firstChild","nodeValue","appendChild","createTextNode","h","HTMLElement","innerHTML","i","el","nodeType","style","ownerDocument","on","e","addEventListener","attachEvent","window","util","file","read","file_data","fn_callback","reader","FileReader","onload","result","name","readAsText","save","type","blob","Blob","bb","BlobBuilder","MozBlobBuilder","WebKitBlobBuilder","MSBlobBuilder","append","getBlob","navigator","msSaveBlob","blob_url","URL","webkitURL","createObjectURL","anchor","visibility","href","download","body","evt","createEvent","initEvent","dispatchEvent","removeChild","location","json","json2string","JSON","stringify","string2json","json_str","parse","merge","b","a","o","Object","toString","call","uuid","newid","Date","getTime","Math","random","substring","text","is_empty","s","replace","default_options","container","editable","theme","mode","support_html","view","engine","enable_device_pixel_ratio","hmargin","vmargin","line_width","line_color","line_style","draggable","hide_scrollbars_when_draggable","node_overflow","zoom","min","max","step","mask_key","custom_node_render","expander_style","layout","hspace","vspace","pspace","cousin_space","default_event_handle","enable_mousedown_handle","enable_click_handle","enable_dblclick_handle","enable_mousewheel_handle","shortcut","enable","handles","mapping","addchild","addbrother","editnode","delnode","toggle","up","down","fieldNames","topic","children","parentid","isroot","direction","expanded","plugin","Node","sId","iIndex","sTopic","oData","bIsRoot","oParent","eDirection","bExpanded","index","data","parent","_data","get_location","vd","x","abs_x","y","abs_y","get_size","width","height","compare","node1","node2","i1","i2","inherited","parent_node","node","pid","is_node","toObject","includeChildren","fn","idKey","topicKey","childrenKey","directionKey","expandedKey","obj","k","map","child","Mind","author","version","root","selected","nodes","get_node","node_id","set_root","_put_node","add_node","idx","push","_update_index","insert_node_before","node_before","node_index","get_node_before","the_node","insert_node_after","node_after","get_node_after","move_node","before_id","parent_id","_move_node","_flow_node_direction","len","_move_node_internal","sibling","si","splice","origin_parent","remove_node","ci","node_parent","sort","DEFAULT_META","format","node_tree","example","meta","get_mind","source","df","mind","_parse","get_data","_build_node","node_root","_extract_data","_extract_subnode","node_json","node_data","node_array","_array","reverse","root_node","_extract_root","isrootKey","root_json","parentidKey","extract_count","node_direction","sub_extract_count","_array_node","freemind","xml","xml_doc","_parse_xml","xml_root","_find_root","_load_node","xml_lines","_build_map","join","DOMParser","parseFromString","ActiveXObject","async","loadXML","childNodes","tagName","ns","xml_node","getAttribute","node_topic","node_folded","topic_children","topic_child","textContent","_load_attributes","node_expanded","node_foreground_color","node_background_color","node_position","attr","attr_data","pos","_escape","_line_regex","lines","split","_fill_nodes","node_path","line","match","substr","diff","pop","_build_lines","prefix","Array","DataProvider","jm","init","load","mind_data","options","data_format","LayoutProvider","opts","isside","bounds","cache_valid","calculate_next_child_direction","children_len","r","layout_direction","layout_offset","_layout_direction_root","layout_data","children_count","side_index","_layout_direction_side","subnode","offset_x","offset_y","outer_height","left_nodes","right_nodes","unshift","outer_height_left","_layout_offset_subnodes","outer_height_right","total_height","nodes_count","node_outer_height","base_y","pd","set_visible","_should_reserve_cousin_space","middle_height","_layout_offset_subnodes_height","get_node_offset","offset_cache","_offset_","offset_p","get_node_point","view_data","get_node_point_in","get_node_point_out","pout_cache","_pout_","get_expander_point","ex_p","ceil","get_min_size","pout","toggle_node","collapse_node","expand_node","part_layout","invoke_event_handle","expand_all","collapse_all","expand_to_depth","target_depth","curr_nodes","curr_depth","depth","root_layout_data","visible","is_expand","is_visible","SvgGraph","e_svg","setAttribute","size","line_drawing","straight","_line_to","curved","_bezier_to","init_line_render","createElementNS","custom_line_render","drawing","path","x1","y1","x2","y2","ctx","start_point","end_point","element","set_size","clear","draw_line","pin","offset","color","copy_to","dest_canvas_ctx","callback","img","Image","drawImage","src","btoa","XMLSerializer","serializeToString","CanvasGraph","e_canvas","className","canvas_ctx","getContext","dpr","device_pixel_ratio","scale","clearRect","strokeStyle","lineWidth","lineCap","beginPath","moveTo","bezierCurveTo","stroke","lineTo","ViewProvider","e_panel","e_nodes","selected_node","editing_node","graph","render_node","_custom_node_render","_default_node_render","zoom_current","devicePixelRatio","_initialized","e_editor","tabIndex","v","event","keyCode","edit_node_end","stopPropagation","offsetParent","IntersectionObserver","entities","observer","isIntersecting","unobserve","observe","add_event","event_name","event_handle","capture_by_panel","target","get_binded_nodeid","parentElement","is_expander","clear_lines","clear_nodes","reset_theme","theme_name","reset_custom_style","nodeid","reset_node_custom_style","setup_canvas_draggable","init_nodes","expand_size","min_size","min_width","min_height","client_w","clientWidth","client_h","clientHeight","init_nodes_size","doc_frag","createDocumentFragment","create_node_element","run_in_c11y_mode_if_needed","func","position","top","d_e","expander","_reset_node_custom_style","update_node","origin_style","select_node","restore_selected_node_custom_style","clear_selected_node_custom_style","select_clear","get_editing_node","is_editing","edit_node_begin","ncs","getComputedStyle","value","getPropertyValue","zIndex","focus","get_view_offset","_show","show_nodes","show_lines","zoom_in","set_zoom","zoom_out","e_panel_rect","getBoundingClientRect","zoom_center","panel_scroll_x","scrollLeft","panel_scroll_y","scrollTop","keep_center","center_node","relayout","save_location","_saved_location","restore_location","node_element","view_offset","display","_show_expander","expander_text","_get_expander_text","p_expander","ele","backgroundColor","fontSize","fontWeight","fontStyle","backgroundImage","scaledImageData","toDataURL","backgroundSize","transform","_offset","enabled","dragging","eventDown","clientX","clientY","eventMove","scrollBy","node_center_point","scrollTo","zoomIn","zoomOut","setZoom","ShortcutProvider","_newid","_mapping","handle","handler","bind","handle_addchild","handle_addbrother","handle_editnode","handle_delnode","handle_toggle","handle_up","handle_down","handle_left","handle_right","keys","isArray","key","id_generator","enable_shortcut","disable_shortcut","which","preventDefault","kc","metaKey","ctrlKey","altKey","shiftKey","_jm","get_selected_node","begin_edit","up_node","find_node_before","np","down_node","find_node_after","_handle_direction","floor","plugin_data","plugins","register","Plugin","Error","includes","apply","setTimeout","forEach","fn_init","_apply","EnhancedPluginManager","Map","initPreloadPlugins","preloadPlugins","enhancedPluginList","filter","preload","descriptor","_initPlugin","initNormalPlugins","normalPlugins","PluginClass","pluginOpt","instanceName","has","instance","set","removePlugin","get","beforePluginRemove","delete","list","findIndex","destroyAllPlugins","beforePluginDestroy","getPlugin","EnhancedPlugin","static","jsMind","_register_plugin","_util","usePlugin","some","hasEnhancedPlugin","current","merge_option","initialized","event_handles","enhancedPluginManager","opts_layout","opts_view","_event_bind","apply_plugins","get_editable","enable_edit","disable_edit","get_view_draggable","enable_view_draggable","disable_view_draggable","enable_event_handle","disable_event_handle","set_theme","theme_old","mousedown_handle","click_handle","dblclick_handle","mousewheel_handle","srcElement","deltaY","end_edit","_reset","skip_centering","m","get_meta","get_root","get_node_level","_add_node_data","undefined","_refresh_node_ui","the_parent_node","add_nodes","nodes_data","expected_count","_count_expected_nodes","created_nodes","_add_nodes_recursive","flat","actual_count","_cleanup_partial_nodes","new_node","sub_nodes","concat","reduce","count","the_node_before","the_node_after","topic_or_options","topicChanged","dataChanged","hasOwnProperty","updated_node","is_node_visible","scroll_node_to_center","prev","ni","found","set_node_color","bg_color","fg_color","set_node_font_style","weight","set_node_background_image","image","rotation","set_node_background_rotation","add_event_listener","clear_event_listener","j","_invoke_event_handle","l","destroy"],"mappings":"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"}