@umbraci/jsmind 1.0.0-beta → 1.0.1-beta
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/dist/jsmind.multi-select.js +1 -1
- package/dist/jsmind.multi-select.js.map +1 -1
- package/es/jsmind.multi-select.js +1 -1
- package/es/jsmind.multi-select.js.map +1 -1
- package/lib/jsmind.multi-select.js +1 -1
- package/lib/jsmind.multi-select.js.map +1 -1
- package/package.json +1 -1
- package/types/generated/plugins/multi-select/jsmind.multi-select.d.ts +109 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsmind.multi-select.js","sources":["../src/jsmind.common.js","../src/jsmind.plugin.js","../src/plugins/jsmind.multi-select.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.1';\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\nimport { logger } from './jsmind.common.js';\n\n/**\n * Plugin Manager\n * Manages plugin lifecycle with synchronous initialization,\n * preload support, and lifecycle hooks.\n */\nexport class PluginManager {\n /**\n * @param {import('./jsmind.js').default} jm - jsMind instance\n */\n constructor(jm) {\n this.jm = jm;\n /** @type {Map<string, Plugin>} */\n this.plugins = new Map();\n }\n\n /**\n * Initialize preload plugins (before core modules)\n */\n initPreloadPlugins() {\n const preloadPlugins = this.jm.constructor.pluginList.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.pluginList.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 if (!PluginClass.instanceName) {\n throw new Error('Plugin ' + PluginClass.name + ' must define static instanceName');\n }\n if (this.plugins.has(PluginClass.instanceName)) {\n logger.warn(\n 'Plugin ' + PluginClass.instanceName + ' already exists, will be replaced'\n );\n }\n\n const instance = new PluginClass({\n jm: this.jm,\n pluginOpt: pluginOpt || {},\n });\n\n this.plugins.set(PluginClass.instanceName, instance);\n this.jm[PluginClass.instanceName] = instance;\n descriptor.instance = instance;\n\n logger.info('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 Plugin} 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 if (typeof instance.beforePluginRemove === 'function') {\n instance.beforePluginRemove();\n }\n\n this.plugins.delete(instanceName);\n delete this.jm[instanceName];\n\n const list = this.jm.constructor.pluginList;\n const index = list.findIndex(d => d.PluginClass === PluginClass);\n if (index !== -1) {\n list.splice(index, 1);\n }\n\n logger.info('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 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 {Plugin | undefined}\n */\n getPlugin(instanceName) {\n return this.plugins.get(instanceName);\n }\n}\n\n/**\n * Plugin Base Class\n * Provides standard plugin interface.\n */\nexport class Plugin {\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 */\n beforePluginRemove() {}\n\n /**\n * Called before jsMind instance is destroyed\n */\n beforePluginDestroy() {\n this.beforePluginRemove();\n }\n}\n\n/**\n * Plugin descriptor\n * @typedef {object} PluginDescriptor\n * @property {typeof Plugin} 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 {Plugin | 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 { Plugin } from '../jsmind.plugin.js';\nimport { EventType, logger } from '../jsmind.common.js';\n\n/**\n * Default options for multi-select plugin.\n * @typedef {Object} MultiSelectOptions\n * @property {boolean} [enable_multi_select=true] - Enable multi-select feature\n * @property {boolean} [include_descendants=true] - Include descendants in subtree selection\n * @property {boolean} [shift_simple_mode=false] - Shift mode: false=simple subtree, true=advanced range\n * @property {((node:import('../jsmind.node.js').Node)=>boolean)|null} [filter=null] - Node filter function\n */\nconst DEFAULT_OPTIONS = {\n enable_multi_select: false, // default off; can be enabled at runtime\n include_descendants: true,\n shift_simple_mode: false,\n allow_ctrl: true,\n allow_shift: true,\n filter: null,\n};\n\n/**\n * Multi-Select Core - Handles all multi-select logic\n */\nclass MultiSelectCore {\n /**\n * @param {import('../jsmind.js').default} jm - jsMind instance\n * @param {MultiSelectOptions} options - Plugin options\n */\n constructor(jm, options) {\n this.jm = jm;\n this.options = options;\n\n // Initialize selection state\n this._ensure_selection_state();\n\n this._selection_mode = null; // 'single' | 'multi' | null\n this._last_selected_node = null;\n }\n\n /**\n * Ensure selection state is initialized\n * @private\n */\n _ensure_selection_state() {\n if (!this.jm.mind) {\n this.jm.mind = {};\n }\n if (!this.jm.mind.selected_nodes) {\n this.jm.mind.selected_nodes = new Set();\n }\n\n if (!this.jm.view) {\n this.jm.view = {};\n }\n if (!this.jm.view.multi_selected_nodes) {\n this.jm.view.multi_selected_nodes = new Map();\n }\n }\n\n /**\n * Get all selected nodes\n * @returns {string[]} Array of selected node IDs\n */\n get_selected_nodes() {\n this._ensure_selection_state();\n if (!this.jm.mind || !this.jm.mind.selected_nodes) {\n return [];\n }\n return Array.from(this.jm.mind.selected_nodes).map(node => node.id);\n }\n\n /**\n * Check if a node is selected\n * @param {string|import('../jsmind.node.js').Node} node - Node ID or Node instance\n * @returns {boolean}\n */\n is_node_selected(node) {\n const nodeObj = this._resolve_node(node);\n if (!nodeObj || !this.jm.mind) {\n return false;\n }\n this._ensure_selection_state();\n return this.jm.mind.selected_nodes.has(nodeObj);\n }\n\n /**\n * Select a single node (clears other selections)\n * @param {string|import('../jsmind.node.js').Node} node - Node ID or Node instance\n */\n select_node(node) {\n const nodeObj = this._resolve_node(node);\n if (!nodeObj) {\n logger.error('[multiSelect] node not found: ' + node);\n return;\n }\n\n this._ensure_selection_state();\n\n // Clear selection state first\n this._clear_selection_state();\n\n // Ensure again after clear, in case mind was reset\n this._ensure_selection_state();\n\n if (!this.jm.mind || !this.jm.mind.selected_nodes) {\n logger.error('[multiSelect] jm.mind or selected_nodes is not available');\n return;\n }\n\n // Set selection state\n this.jm.mind.selected = nodeObj;\n this._last_selected_node = nodeObj;\n\n // Force add node to selection (since we just cleared it)\n if (!this.jm.mind.selected_nodes.has(nodeObj)) {\n this.jm.mind.selected_nodes.add(nodeObj);\n }\n\n // Mark node as selected in view\n this._mark_node_selected(nodeObj);\n\n this._selection_mode = 'single';\n\n // Always use nodeObj.id for event data\n const nodeIds = [nodeObj.id];\n\n // Invoke event with proper data structure\n this._invoke_select_event({\n evt: 'select_node',\n data: nodeIds,\n node: nodeObj.id,\n nodes: nodeIds,\n });\n }\n\n /**\n * Clear all selections\n */\n select_clear() {\n this._ensure_selection_state();\n if (this.jm.mind) {\n this.jm.mind.selected = null;\n this._last_selected_node = null;\n this._clear_selection_state();\n }\n }\n\n /**\n * Toggle node selection (equivalent to Ctrl/Cmd+Click)\n * @param {string|import('../jsmind.node.js').Node} node - Node ID or Node instance\n */\n toggle_node_selection(node) {\n const nodeObj = this._resolve_node(node);\n if (!nodeObj || !this.jm.layout.is_visible(nodeObj)) {\n return;\n }\n\n this._ensure_selection_state();\n if (this.jm.mind.selected_nodes.has(nodeObj)) {\n this._deselect_subtree(nodeObj);\n } else {\n this._selection_mode = 'multi';\n const added = this._append_selection([nodeObj]);\n if (added.length) {\n this.jm.mind.selected = nodeObj;\n this._last_selected_node = nodeObj;\n this._invoke_select_event({\n evt: 'multi_select',\n data: [nodeObj.id],\n node: nodeObj.id,\n nodes: [nodeObj.id],\n });\n }\n }\n }\n\n /**\n * Toggle subtree selection\n * @param {string|import('../jsmind.node.js').Node} node - Node ID or Node instance\n */\n toggle_subtree_selection(node, opts) {\n const nodeObj = this._resolve_node(node);\n if (!nodeObj) {\n logger.error('[multiSelect] node not found: ' + node);\n return;\n }\n\n if (!this.jm.layout.is_visible(nodeObj)) {\n return;\n }\n\n const includeDesc =\n opts && typeof opts.include_descendants !== 'undefined'\n ? !!opts.include_descendants\n : this.options.include_descendants !== false; // default true\n\n this._ensure_selection_state();\n // If node is not selected or not in multi mode, select subtree\n if (!this.jm.mind.selected_nodes.has(nodeObj) || this._selection_mode !== 'multi') {\n this._selection_mode = 'multi';\n let nodes = this._collect_subtree_nodes(nodeObj, {\n includeChildren: includeDesc,\n respectFilter: true,\n skipRootFilter: true,\n });\n if (!nodes.length) {\n nodes = [nodeObj];\n }\n\n const added = this._append_selection(nodes, { focusNode: nodeObj });\n this._ensure_selection_state();\n const ancestors =\n nodeObj.parent && !this.jm.mind.selected_nodes.has(nodeObj.parent)\n ? this._ensure_ancestor_selection([nodeObj], nodeObj, {\n requireAncestorChainSelected: true,\n })\n : [];\n const allAdded = added.concat(ancestors);\n\n if (allAdded.length) {\n this.jm.mind.selected = nodeObj;\n const nodeIds = allAdded.map(n => n.id);\n this._invoke_select_event({\n evt: 'multi_select',\n data: nodeIds,\n node: nodeObj.id,\n nodes: nodeIds,\n });\n }\n } else {\n // Deselect subtree\n let nodes = this._collect_subtree_nodes(nodeObj, {\n includeChildren: true,\n respectFilter: false,\n skipRootFilter: false,\n });\n if (!nodes.length) {\n nodes = [nodeObj];\n }\n\n const removed = this._remove_selection(nodes);\n if (removed.length) {\n if (this.jm.mind.selected && this.jm.mind.selected.id === nodeObj.id) {\n this.jm.mind.selected = null;\n }\n this._selection_mode = this._derive_selection_mode();\n const nodeIds = removed.map(n => n.id);\n this._invoke_select_event({\n evt: 'multi_deselect',\n data: nodeIds,\n node: nodeObj.id,\n nodes: nodeIds,\n });\n }\n }\n }\n\n /**\n * Get current selection mode\n * @returns {'single'|'multi'|null}\n */\n get_selection_mode() {\n return this._selection_mode;\n }\n\n /**\n * Handle node click event\n * @param {Object} payload - Click event payload\n * @param {MouseEvent} payload.e - Mouse event\n * @param {string} payload.node - Node ID\n * @param {HTMLElement} payload.element - Node element\n * @param {string} payload.evt - Event type\n */\n _handle_node_click(payload) {\n const { e, node, element } = payload;\n if (!node || !element) {\n return;\n }\n\n // Ensure selection state is initialized\n this._ensure_selection_state();\n\n const mode = this._get_multi_select_mode(e);\n\n if (mode === 'ctrl') {\n // Ctrl/Cmd + Click: Toggle node selection\n this.toggle_node_selection(node);\n } else if (mode === 'shift') {\n // Shift + Click: Range selection\n const nodeObj = this.jm.get_node(node);\n if (!nodeObj) {\n logger.warn('[multiSelect] Node not found for shift selection: ' + node);\n return;\n }\n\n if (this.options.shift_simple_mode) {\n // Advanced range mode\n if (this.is_node_selected(node)) {\n this._deselect_subtree(nodeObj);\n } else {\n this._range_select_nodes(node);\n }\n } else {\n // Simple subtree mode\n if (this.is_node_selected(node)) {\n this._deselect_subtree(nodeObj);\n } else {\n const includeChildren = this.options.include_descendants !== false;\n let nodes = this._collect_subtree_nodes(nodeObj, {\n includeChildren: includeChildren,\n respectFilter: true,\n skipRootFilter: true,\n });\n if (!nodes.length) {\n nodes = [nodeObj];\n }\n\n const added = this._append_selection(nodes, { focusNode: nodeObj });\n if (added.length) {\n this.jm.mind.selected = nodeObj;\n this._last_selected_node = nodeObj;\n this._selection_mode = this._derive_selection_mode();\n const nodeIds = added.map(n => n.id);\n this._invoke_select_event({\n evt: 'multi_select',\n data: nodeIds,\n node: nodeObj.id,\n nodes: nodeIds,\n });\n } else {\n // Fallback: at least select the clicked node\n this._ensure_selection_state();\n if (!this.jm.mind.selected_nodes.has(nodeObj)) {\n this.jm.mind.selected_nodes.add(nodeObj);\n this._mark_node_selected(nodeObj);\n }\n this.jm.mind.selected = nodeObj;\n this._last_selected_node = nodeObj;\n this._selection_mode = this._derive_selection_mode();\n this._invoke_select_event({\n evt: 'multi_select',\n data: [nodeObj.id],\n node: nodeObj.id,\n nodes: [nodeObj.id],\n });\n }\n }\n }\n } else {\n // Normal click - single select\n this.select_node(node);\n }\n }\n\n /**\n * Handle node removed event\n * @param {import('../jsmind.node.js').Node} node - Removed node\n */\n _handle_node_removed(node) {\n this._ensure_selection_state();\n if (this.jm.mind.selected_nodes.has(node)) {\n this.jm.mind.selected_nodes.delete(node);\n }\n if (this._last_selected_node && this._last_selected_node.id === node.id) {\n this._last_selected_node = null;\n }\n if (this.jm.view.multi_selected_nodes && this.jm.view.multi_selected_nodes.has(node.id)) {\n this._unmark_node_selected(node);\n }\n }\n\n /**\n * Get multi-select mode from event\n * @param {MouseEvent} e - Mouse event\n * @returns {'ctrl'|'shift'|null}\n */\n _get_multi_select_mode(e) {\n if (!e) {\n return null;\n }\n // Check shift key first (higher priority)\n if (this.options.allow_shift !== false && e.shiftKey === true) {\n return 'shift';\n }\n // Check ctrl/cmd key\n if (this.options.allow_ctrl !== false && (e.ctrlKey === true || e.metaKey === true)) {\n return 'ctrl';\n }\n return null;\n }\n\n /**\n * Append nodes to selection\n * @param {import('../jsmind.node.js').Node[]} nodes - Nodes to select\n * @param {Object} [options] - Options\n * @param {import('../jsmind.node.js').Node} [options.focusNode] - Focus node\n * @returns {import('../jsmind.node.js').Node[]} Actually added nodes\n */\n _append_selection(nodes, options) {\n if (!nodes || !nodes.length) {\n return [];\n }\n\n this._ensure_selection_state();\n if (!this.jm.mind || !this.jm.mind.selected_nodes) {\n logger.warn('[multiSelect] Cannot append selection: selected_nodes not available');\n return [];\n }\n\n const added = [];\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i];\n if (!this.jm.mind.selected_nodes.has(node)) {\n this.jm.mind.selected_nodes.add(node);\n added.push(node);\n }\n }\n\n if (added.length) {\n const focusNode = options && options.focusNode ? options.focusNode : null;\n this._mark_nodes_selected(added, focusNode || added[added.length - 1]);\n }\n\n return added;\n }\n\n /**\n * Remove nodes from selection\n * @param {import('../jsmind.node.js').Node[]} nodes - Nodes to deselect\n * @returns {import('../jsmind.node.js').Node[]} Actually removed nodes\n */\n _remove_selection(nodes) {\n if (!nodes || !nodes.length) {\n return [];\n }\n\n this._ensure_selection_state();\n const removed = [];\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i];\n if (this.jm.mind.selected_nodes.has(node)) {\n this.jm.mind.selected_nodes.delete(node);\n removed.push(node);\n }\n }\n\n if (removed.length) {\n this._unmark_nodes_selected(removed);\n }\n\n return removed;\n }\n\n /**\n * Deselect subtree\n * @param {import('../jsmind.node.js').Node} node - Root node of subtree\n */\n _deselect_subtree(node) {\n let nodes = this._collect_subtree_nodes(node, {\n includeChildren: true,\n respectFilter: false,\n skipRootFilter: false,\n });\n if (!nodes.length) {\n nodes = [node];\n }\n\n const removed = this._remove_selection(nodes);\n if (removed.length) {\n if (this.jm.mind.selected && this.jm.mind.selected.id === node.id) {\n this.jm.mind.selected = null;\n }\n this._selection_mode = this._derive_selection_mode();\n const nodeIds = removed.map(n => n.id);\n this._invoke_select_event({\n evt: 'multi_deselect',\n data: nodeIds,\n node: node.id,\n nodes: nodeIds,\n });\n }\n }\n\n /**\n * Clear selection state\n * @returns {import('../jsmind.node.js').Node[]} Removed nodes\n */\n _clear_selection_state() {\n this._ensure_selection_state();\n this._selection_mode = null;\n\n // Double check after ensure\n if (!this.jm.mind || !this.jm.mind.selected_nodes) {\n this._ensure_selection_state();\n }\n\n if (\n !this.jm.mind ||\n !this.jm.mind.selected_nodes ||\n this.jm.mind.selected_nodes.size === 0\n ) {\n this._clear_all_selected_nodes_view();\n return [];\n }\n\n const nodes = Array.from(this.jm.mind.selected_nodes);\n this.jm.mind.selected_nodes.clear();\n this._unmark_nodes_selected(nodes);\n return nodes;\n }\n\n /**\n * Collect subtree nodes\n * @param {import('../jsmind.node.js').Node} node - Root node\n * @param {Object} options - Options\n * @param {boolean} [options.includeChildren=true] - Include children\n * @param {boolean} [options.respectFilter=false] - Respect filter\n * @param {boolean} [options.skipRootFilter=false] - Skip root filter\n * @returns {import('../jsmind.node.js').Node[]}\n */\n _collect_subtree_nodes(node, options) {\n const opts = options || {};\n const includeChildren = opts.includeChildren !== false;\n const respectFilter = !!opts.respectFilter;\n const skipRootFilter = !!opts.skipRootFilter;\n\n const filter = respectFilter ? this._get_selection_filter() : null;\n const result = [];\n\n const collect = (n, isRoot) => {\n let shouldInclude = true;\n if (filter && (!skipRootFilter || !isRoot)) {\n shouldInclude = filter(n) !== false;\n }\n\n if (shouldInclude) {\n result.push(n);\n }\n\n if (includeChildren && n.children) {\n for (let i = 0; i < n.children.length; i++) {\n collect(n.children[i], false);\n }\n }\n };\n\n collect(node, true);\n return result;\n }\n\n /**\n * Ensure ancestor selection\n * @param {import('../jsmind.node.js').Node[]} nodes - Nodes\n * @param {import('../jsmind.node.js').Node} focusNode - Focus node\n * @param {Object} options - Options\n * @returns {import('../jsmind.node.js').Node[]}\n */\n _ensure_ancestor_selection(nodes, focusNode, options) {\n if (!nodes || !nodes.length) {\n return [];\n }\n\n this._ensure_selection_state();\n const requireAncestorChainSelected = !!(options && options.requireAncestorChainSelected);\n const added = [];\n const addedMap = Object.create(null);\n\n for (let i = 0; i < nodes.length; i++) {\n let parent = nodes[i].parent;\n if (!parent) {\n continue;\n }\n\n const path = [];\n let shouldAdd = !requireAncestorChainSelected;\n\n // Check if any ancestor is already selected\n while (parent) {\n if (this.jm.mind.selected_nodes.has(parent)) {\n shouldAdd = true;\n break;\n }\n path.push(parent);\n parent = parent.parent;\n }\n\n if (shouldAdd) {\n for (let j = 0; j < path.length; j++) {\n const p = path[j];\n if (!this.jm.mind.selected_nodes.has(p) && !addedMap[p.id]) {\n added.push(p);\n addedMap[p.id] = true;\n }\n }\n }\n }\n\n if (!added.length) {\n return [];\n }\n\n const focus = focusNode || nodes[nodes.length - 1];\n return this._append_selection(added, { focusNode: focus });\n }\n\n /**\n * Get selection filter\n * @returns {Function|null}\n */\n _get_selection_filter() {\n if (this.options && typeof this.options.filter === 'function') {\n return this.options.filter;\n }\n return null;\n }\n\n /**\n * Range select nodes (advanced mode)\n * @param {string} nodeId - Target node ID\n */\n _range_select_nodes(nodeId) {\n const nodeObj = this._resolve_node(nodeId);\n if (!nodeObj || !this.jm.layout.is_visible(nodeObj)) {\n return;\n }\n\n this._ensure_selection_state();\n // If no selection, select subtree\n if (this.jm.mind.selected_nodes.size === 0) {\n let nodes = this._collect_subtree_nodes(nodeObj, {\n includeChildren: true,\n respectFilter: true,\n skipRootFilter: true,\n });\n if (!nodes.length) {\n nodes = [nodeObj];\n }\n\n const added = this._append_selection(nodes);\n if (added.length) {\n this.jm.mind.selected = nodeObj;\n this._last_selected_node = nodeObj;\n this._selection_mode = this._derive_selection_mode();\n const nodeIds = added.map(n => n.id);\n this._invoke_select_event({\n evt: 'multi_select',\n data: nodeIds,\n node: nodeObj.id,\n nodes: nodeIds,\n });\n }\n return;\n }\n\n // Find anchor node\n this._ensure_selection_state();\n const selectedArray = Array.from(this.jm.mind.selected_nodes);\n const anchor =\n this._last_selected_node && this.jm.mind.selected_nodes.has(this._last_selected_node)\n ? this._last_selected_node\n : selectedArray[0];\n\n // Find nodes between anchor and target\n const nodesBetween = this._find_nodes_between(anchor, nodeObj);\n if (!nodesBetween.length) {\n const nodes = [nodeObj];\n const added = this._append_selection(nodes);\n if (added.length) {\n this.jm.mind.selected = nodeObj;\n this._last_selected_node = nodeObj;\n this._selection_mode = this._derive_selection_mode();\n const nodeIds = added.map(n => n.id);\n this._invoke_select_event({\n evt: 'multi_select',\n data: nodeIds,\n node: nodeObj.id,\n nodes: nodeIds,\n });\n }\n return;\n }\n\n // Select all nodes between anchor and target\n this._ensure_selection_state();\n const toAdd = nodesBetween.filter(n => !this.jm.mind.selected_nodes.has(n));\n const added = this._append_selection(toAdd);\n if (added.length) {\n this.jm.mind.selected = nodeObj;\n this._last_selected_node = nodeObj;\n this._selection_mode = this._derive_selection_mode();\n const nodeIds = added.map(n => n.id);\n this._invoke_select_event({\n evt: 'multi_select',\n data: nodeIds,\n node: nodeObj.id,\n nodes: nodeIds,\n });\n }\n }\n\n /**\n * Find nodes between two nodes\n * @param {import('../jsmind.node.js').Node} from - Start node\n * @param {import('../jsmind.node.js').Node} to - End node\n * @returns {import('../jsmind.node.js').Node[]}\n */\n _find_nodes_between(from, to) {\n if (!from || !to) {\n return [];\n }\n\n // Collect all visible nodes in order\n const allNodes = [];\n const collect = node => {\n if (this.jm.layout.is_visible(node)) {\n allNodes.push(node);\n }\n if (node.children) {\n for (let i = 0; i < node.children.length; i++) {\n collect(node.children[i]);\n }\n }\n };\n\n if (this.jm.mind && this.jm.mind.root) {\n collect(this.jm.mind.root);\n }\n\n // Find indices\n let fromIndex = -1;\n let toIndex = -1;\n for (let i = 0; i < allNodes.length; i++) {\n if (allNodes[i].id === from.id) {\n fromIndex = i;\n }\n if (allNodes[i].id === to.id) {\n toIndex = i;\n }\n }\n\n if (fromIndex === -1 || toIndex === -1) {\n return [];\n }\n\n const start = Math.min(fromIndex, toIndex);\n const end = Math.max(fromIndex, toIndex);\n return allNodes.slice(start, end + 1);\n }\n\n /**\n * Derive selection mode from current state\n * @returns {'single'|'multi'|null}\n */\n _derive_selection_mode() {\n this._ensure_selection_state();\n const count = this.jm.mind.selected_nodes.size;\n if (count === 0) {\n return null;\n }\n return count > 1 ? 'multi' : 'single';\n }\n\n /**\n * Mark nodes as selected in view\n * @param {import('../jsmind.node.js').Node[]} nodes - Nodes to mark\n * @param {import('../jsmind.node.js').Node} focusNode - Focus node\n */\n _mark_nodes_selected(nodes, focusNode) {\n if (nodes && nodes.length) {\n for (let i = 0; i < nodes.length; i++) {\n this._mark_node_selected(nodes[i]);\n }\n this.jm.view.selected_node = focusNode || nodes[nodes.length - 1];\n }\n }\n\n /**\n * Mark a node as selected in view\n * @param {import('../jsmind.node.js').Node} node - Node to mark\n */\n _mark_node_selected(node) {\n if (!node || this.jm.view.multi_selected_nodes.has(node.id)) {\n return;\n }\n\n const element = node._data && node._data.view && node._data.view.element;\n if (element) {\n if (element.classList) {\n element.classList.add('selected');\n } else if (!/(\\s|^)selected(\\s|$)/.test(element.className)) {\n element.className += ' selected';\n }\n this.jm.view.multi_selected_nodes.set(node.id, node);\n }\n }\n\n /**\n * Unmark nodes as selected in view\n * @param {import('../jsmind.node.js').Node[]} nodes - Nodes to unmark\n */\n _unmark_nodes_selected(nodes) {\n if (nodes && nodes.length) {\n for (let i = 0; i < nodes.length; i++) {\n this._unmark_node_selected(nodes[i]);\n }\n }\n }\n\n /**\n * Unmark a node as selected in view\n * @param {import('../jsmind.node.js').Node} node - Node to unmark\n */\n _unmark_node_selected(node) {\n if (node) {\n if (this.jm.view.multi_selected_nodes.has(node.id)) {\n const element = node._data && node._data.view && node._data.view.element;\n if (element) {\n if (element.classList) {\n element.classList.remove('selected');\n } else {\n element.className = element.className.replace(/\\s*selected\\b/i, '');\n }\n }\n this.jm.view.multi_selected_nodes.delete(node.id);\n }\n if (this.jm.view.selected_node && this.jm.view.selected_node.id === node.id) {\n this.jm.view.selected_node = null;\n }\n }\n }\n\n /**\n * Clear all selected nodes view\n */\n _clear_all_selected_nodes_view() {\n this._ensure_selection_state();\n if (!this.jm.view.multi_selected_nodes || !this.jm.view.multi_selected_nodes.size) {\n if (this.jm.view) {\n this.jm.view.selected_node = null;\n }\n return;\n }\n\n const nodes = Array.from(this.jm.view.multi_selected_nodes.values());\n for (let i = 0; i < nodes.length; i++) {\n this._unmark_node_selected(nodes[i]);\n }\n if (this.jm.view) {\n this.jm.view.selected_node = null;\n }\n }\n\n /**\n * Invoke select event\n * @param {Object} data - Event data\n */\n _invoke_select_event(data) {\n try {\n // Ensure nodes is always an array\n if (!data.nodes) {\n data.nodes = data.data || [];\n }\n // Ensure data is always an array\n if (!data.data) {\n data.data = data.nodes || [];\n }\n this.jm.invoke_event_handle(EventType.select, data);\n } catch (e) {\n logger.warn('[multiSelect] failed to invoke select event', e);\n }\n }\n\n /**\n * Resolve node from ID or Node instance\n * @param {string|import('../jsmind.node.js').Node} node - Node ID or Node instance\n * @returns {import('../jsmind.node.js').Node|null}\n */\n _resolve_node(node) {\n if (!node) {\n return null;\n }\n if (typeof node === 'string') {\n return this.jm.get_node(node);\n }\n return node;\n }\n}\n\n/**\n * Multi-Select Plugin - Plugin for jsMind\n */\nexport class MultiSelectPlugin extends Plugin {\n static instanceName = 'multiSelectPlugin';\n static preload = false;\n\n /**\n * @param {{ jm: import('../jsmind.js').default, pluginOpt: object }} params\n */\n constructor({ jm, pluginOpt }) {\n super({ jm, pluginOpt });\n\n const options = Object.assign({}, DEFAULT_OPTIONS, pluginOpt || {});\n this.options = options;\n this._mounted = false;\n this._core = null;\n this._listener = null;\n this._enabled = !!options.enable_multi_select; // runtime gate\n\n this._initCore();\n }\n\n /**\n * Initialize core and mount API\n */\n _initCore() {\n const jm = this.jm;\n const options = this.options;\n const plugin = this; // Save reference for closure\n\n // Create core instance\n this._core = new MultiSelectCore(jm, options);\n\n // Mount API\n this._mountAPI();\n\n // Setup event listener\n this._listener = (type, data) => {\n try {\n if (type === EventType.show) {\n plugin._core.select_clear();\n }\n } catch (e) {\n logger.warn('[multiSelect] listener error', e);\n }\n };\n\n jm.add_event_listener(this._listener);\n\n // Patch core selection APIs to route through plugin to avoid duplicate events\n this._original_select_node = jm.select_node.bind(jm);\n this._original_select_clear = jm.select_clear.bind(jm);\n jm.select_node = node => {\n // Route based on runtime gate\n if (plugin._enabled) return plugin._core.select_node(node);\n return plugin._original_select_node(node);\n };\n jm.select_clear = () => {\n if (plugin._enabled) return plugin._core.select_clear();\n return plugin._original_select_clear();\n };\n\n // Always bind our click handler once; gate controls interception\n const $ = jm.constructor.$;\n this._domClickHandler = function (e) {\n // Gate: only intercept when enabled\n if (!plugin._enabled) {\n return;\n }\n const element = e.target || e.currentTarget;\n const node_id = jm.view.get_binded_nodeid(element);\n\n // Only intercept jmnode, let expander clicks pass through\n if (node_id && jm.view.is_node(element)) {\n e.preventDefault();\n e.stopPropagation();\n if (e.stopImmediatePropagation) e.stopImmediatePropagation();\n\n plugin._core._handle_node_click({\n e,\n node: node_id,\n element,\n evt: 'click',\n });\n } else if (!node_id) {\n // Blank click without modifiers clears selection\n if (!e.ctrlKey && !e.metaKey && !e.shiftKey) {\n plugin._core.select_clear();\n }\n }\n };\n\n if (jm.view && jm.view.e_nodes) {\n $.on(jm.view.e_nodes, 'click', this._domClickHandler);\n logger.info('[multiSelect] plugin click handler attached');\n } else {\n logger.warn('[multiSelect] nodes container not ready; DOM handler not attached');\n }\n\n // Respect initial enabled state: toggle core default handler\n if (this._enabled && typeof jm.disable_event_handle === 'function') {\n jm.disable_event_handle('mousedown');\n }\n\n logger.info('[multiSelect] API mounted and event listener attached.');\n }\n\n /**\n * Mount API to jsMind instance\n */\n _mountAPI() {\n if (this._mounted) {\n return;\n }\n\n const jm = this.jm;\n const plugin = this; // Save reference for closure\n\n const api = {\n get_selected_nodes: () => {\n if (!plugin._core) {\n logger.warn('[multiSelect] Core not initialized');\n return [];\n }\n return plugin._core.get_selected_nodes();\n },\n is_node_selected: node => {\n if (!plugin._core) {\n return false;\n }\n return plugin._core.is_node_selected(node);\n },\n select_node: node => {\n if (!plugin._core) {\n logger.warn('[multiSelect] Core not initialized');\n return;\n }\n plugin._core.select_node(node);\n },\n select_clear: () => {\n if (!plugin._core) {\n return;\n }\n plugin._core.select_clear();\n },\n toggle_node_selection: node => {\n if (!plugin._core) {\n logger.warn('[multiSelect] Core not initialized');\n return;\n }\n plugin._core.toggle_node_selection(node);\n },\n toggle_subtree_selection: node => {\n if (!plugin._core) {\n logger.warn('[multiSelect] Core not initialized');\n return;\n }\n plugin._core.toggle_subtree_selection(node);\n },\n get_selection_mode: () => {\n if (!plugin._core) {\n return null;\n }\n return plugin._core.get_selection_mode();\n },\n getOptions: () => {\n const base = plugin._core ? plugin._core.options : plugin.options;\n return Object.assign({}, base, { enable_multi_select: plugin._enabled });\n },\n enable: () => plugin.setEnabled(true),\n disable: () => plugin.setEnabled(false),\n setEnabled: flag => plugin.setEnabled(flag),\n setOptions: partial => plugin.setOptions(partial),\n };\n\n Object.defineProperty(jm, 'multiSelect', {\n value: api,\n configurable: true,\n enumerable: false,\n writable: false,\n });\n\n this._mounted = true;\n logger.info('[multiSelect] API mounted.');\n }\n\n /**\n * Cleanup before plugin removal\n */\n beforePluginRemove() {\n try {\n // Remove event listener\n if (this._listener && this.jm && Array.isArray(this.jm.event_handles)) {\n const index = this.jm.event_handles.indexOf(this._listener);\n if (index >= 0) {\n this.jm.event_handles.splice(index, 1);\n }\n }\n\n // Re-enable core mousedown handle\n if (typeof this.jm.enable_event_handle === 'function') {\n this.jm.enable_event_handle('mousedown');\n }\n\n // Remove DOM click handler if attached\n if (this._domClickHandler && this.jm && this.jm.view && this.jm.view.e_nodes) {\n // No off() helper; leave it attached (noop when disabled). If needed, we could rebuild view.\n this._domClickHandler = null;\n }\n\n // Restore API wrappers\n if (this._original_select_node) {\n this.jm.select_node = this._original_select_node;\n }\n if (this._original_select_clear) {\n this.jm.select_clear = this._original_select_clear;\n }\n\n // Remove API namespace\n if (this.jm && Object.prototype.hasOwnProperty.call(this.jm, 'multiSelect')) {\n delete this.jm.multiSelect;\n }\n\n this._mounted = false;\n } catch (e) {\n logger.error('[multiSelect] remove failed:', e);\n }\n }\n\n // Runtime enable/disable and options update\n setEnabled(flag) {\n const next = !!flag;\n if (this._enabled === next) return;\n this._enabled = next;\n // Keep options in sync for getOptions()\n this.options.enable_multi_select = this._enabled;\n if (this._enabled) {\n if (typeof this.jm.disable_event_handle === 'function') {\n this.jm.disable_event_handle('mousedown');\n }\n } else {\n if (typeof this.jm.enable_event_handle === 'function') {\n this.jm.enable_event_handle('mousedown');\n }\n }\n }\n\n setOptions(partial) {\n const next = Object.assign({}, partial || {});\n // Update plugin-level options\n this.options = Object.assign({}, this.options, next);\n // Propagate to core so that _get_multi_select_mode sees changes\n if (this._core && this._core.options) {\n this._core.options = Object.assign({}, this._core.options, next);\n }\n }\n\n /**\n * Cleanup before plugin destroy\n */\n beforePluginDestroy() {\n logger.debug('[multiSelect] beforePluginDestroy');\n this.beforePluginRemove();\n }\n}\n\n// Export for compatibility\nexport { MultiSelectCore };\nexport default MultiSelectPlugin;\n"],"names":["String","prototype","startsWith","p","this","slice","length","EventType","LogLevel","_noop","logger","console","level","log","debug","info","warn","error","log_level","Plugin","static","constructor","jm","pluginOpt","options","beforePluginRemove","beforePluginDestroy","DEFAULT_OPTIONS","enable_multi_select","include_descendants","shift_simple_mode","allow_ctrl","allow_shift","filter","MultiSelectCore","_ensure_selection_state","_selection_mode","_last_selected_node","mind","selected_nodes","Set","view","multi_selected_nodes","Map","get_selected_nodes","Array","from","map","node","id","is_node_selected","nodeObj","_resolve_node","has","select_node","_clear_selection_state","selected","add","_mark_node_selected","nodeIds","_invoke_select_event","evt","data","nodes","select_clear","toggle_node_selection","layout","is_visible","_deselect_subtree","_append_selection","toggle_subtree_selection","opts","includeDesc","_collect_subtree_nodes","includeChildren","respectFilter","skipRootFilter","removed","_remove_selection","_derive_selection_mode","n","added","focusNode","ancestors","parent","_ensure_ancestor_selection","requireAncestorChainSelected","allAdded","concat","get_selection_mode","_handle_node_click","payload","e","element","mode","_get_multi_select_mode","get_node","_range_select_nodes","_handle_node_removed","delete","_unmark_node_selected","shiftKey","ctrlKey","metaKey","i","push","_mark_nodes_selected","_unmark_nodes_selected","size","_clear_all_selected_nodes_view","clear","_get_selection_filter","result","collect","isRoot","shouldInclude","children","addedMap","Object","create","path","shouldAdd","j","focus","nodeId","selectedArray","anchor","nodesBetween","_find_nodes_between","toAdd","to","allNodes","root","fromIndex","toIndex","start","Math","min","end","max","count","selected_node","_data","classList","test","className","set","remove","replace","values","invoke_event_handle","MultiSelectPlugin","super","assign","_mounted","_core","_listener","_enabled","_initCore","plugin","_mountAPI","type","add_event_listener","_original_select_node","bind","_original_select_clear","$","_domClickHandler","target","currentTarget","node_id","get_binded_nodeid","is_node","preventDefault","stopPropagation","stopImmediatePropagation","e_nodes","on","disable_event_handle","api","getOptions","base","enable","setEnabled","disable","flag","setOptions","partial","defineProperty","value","configurable","enumerable","writable","isArray","event_handles","index","indexOf","splice","enable_event_handle","hasOwnProperty","call","multiSelect","next"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"jsmind.multi-select.js","sources":["../src/jsmind.common.js","../src/jsmind.plugin.js","../src/plugins/multi-select/jsmind.multi-select.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.1';\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\nimport { logger } from './jsmind.common.js';\n\n/**\n * Plugin Manager\n * Manages plugin lifecycle with synchronous initialization,\n * preload support, and lifecycle hooks.\n */\nexport class PluginManager {\n /**\n * @param {import('./jsmind.js').default} jm - jsMind instance\n */\n constructor(jm) {\n this.jm = jm;\n /** @type {Map<string, Plugin>} */\n this.plugins = new Map();\n }\n\n /**\n * Initialize preload plugins (before core modules)\n */\n initPreloadPlugins() {\n const preloadPlugins = this.jm.constructor.pluginList.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.pluginList.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 if (!PluginClass.instanceName) {\n throw new Error('Plugin ' + PluginClass.name + ' must define static instanceName');\n }\n if (this.plugins.has(PluginClass.instanceName)) {\n logger.warn(\n 'Plugin ' + PluginClass.instanceName + ' already exists, will be replaced'\n );\n }\n\n const instance = new PluginClass({\n jm: this.jm,\n pluginOpt: pluginOpt || {},\n });\n\n this.plugins.set(PluginClass.instanceName, instance);\n this.jm[PluginClass.instanceName] = instance;\n descriptor.instance = instance;\n\n logger.info('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 Plugin} 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 if (typeof instance.beforePluginRemove === 'function') {\n instance.beforePluginRemove();\n }\n\n this.plugins.delete(instanceName);\n delete this.jm[instanceName];\n\n const list = this.jm.constructor.pluginList;\n const index = list.findIndex(d => d.PluginClass === PluginClass);\n if (index !== -1) {\n list.splice(index, 1);\n }\n\n logger.info('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 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 {Plugin | undefined}\n */\n getPlugin(instanceName) {\n return this.plugins.get(instanceName);\n }\n}\n\n/**\n * Plugin Base Class\n * Provides standard plugin interface.\n */\nexport class Plugin {\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 */\n beforePluginRemove() {}\n\n /**\n * Called before jsMind instance is destroyed\n */\n beforePluginDestroy() {\n this.beforePluginRemove();\n }\n}\n\n/**\n * Plugin descriptor\n * @typedef {object} PluginDescriptor\n * @property {typeof Plugin} 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 {Plugin | 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 { Plugin } from '../../jsmind.plugin.js';\nimport { EventType, logger } from '../../jsmind.common.js';\n\n/**\n * @typedef {Object} MultiSelectOptions\n * @property {boolean} [enable_multi_select=false] - Enable multi-select feature\n * @property {boolean} [enable_ctrl_key_node_selection=true] - Enable Ctrl/Cmd + click toggle\n * @property {boolean} [enable_box_selection=true] - Enable box selection\n * @property {boolean} [use_left_key_selection_right_key_drag=false] - true: left mouse drag; false: Ctrl/Cmd + right drag\n * @property {boolean} [shift_simple_mode] - Deprecated; no effect\n * @property {boolean} [include_descendants] - Deprecated; no effect\n */\n\nconst DEFAULT_OPTIONS = {\n enable_multi_select: false,\n enable_ctrl_key_node_selection: true,\n enable_box_selection: true,\n use_left_key_selection_right_key_drag: false,\n};\n\nclass MultiSelectState {\n constructor(jm) {\n this.jm = jm;\n this._mode = null;\n this._last_selected_node = null;\n this._marked_ids = new Set();\n this._ensure_state();\n }\n\n _ensure_state() {\n if (!this.jm.mind) {\n this.jm.mind = {};\n }\n if (!this.jm.mind.selected_nodes) {\n this.jm.mind.selected_nodes = new Set();\n }\n }\n\n _resolve_node(node) {\n if (!node) {\n return null;\n }\n return typeof node === 'string' ? this.jm.get_node(node) : node;\n }\n\n _is_visible(node) {\n return !!(node && this.jm.layout && this.jm.layout.is_visible(node));\n }\n\n _derive_mode() {\n this._ensure_state();\n const size = this.jm.mind.selected_nodes.size;\n if (size === 0) {\n return null;\n }\n return size === 1 ? 'single' : 'multi';\n }\n\n _set_focus(node) {\n this.jm.mind.selected = node || null;\n if (this.jm.view) {\n this.jm.view.selected_node = node || null;\n }\n this._last_selected_node = node || null;\n }\n\n _mark_node(node) {\n if (!node) {\n return;\n }\n const element = node._data && node._data.view && node._data.view.element;\n if (!element) {\n return;\n }\n if (element.classList) {\n element.classList.add('selected');\n } else if (!/(\\s|^)selected(\\s|$)/.test(element.className)) {\n element.className += ' selected';\n }\n this._marked_ids.add(node.id);\n }\n\n _unmark_node(node) {\n if (!node) {\n return;\n }\n const element = node._data && node._data.view && node._data.view.element;\n if (element) {\n if (element.classList) {\n element.classList.remove('selected');\n } else {\n element.className = element.className.replace(/\\s*selected\\b/i, '');\n }\n }\n this._marked_ids.delete(node.id);\n }\n\n _sync_view_from_state() {\n this._ensure_state();\n\n const selected_ids = new Set();\n const selected_nodes = Array.from(this.jm.mind.selected_nodes);\n for (let i = 0; i < selected_nodes.length; i++) {\n selected_ids.add(selected_nodes[i].id);\n }\n\n const stale_ids = [];\n this._marked_ids.forEach(id => {\n if (!selected_ids.has(id)) {\n stale_ids.push(id);\n }\n });\n for (let i = 0; i < stale_ids.length; i++) {\n const stale_node = this.jm.get_node(stale_ids[i]);\n if (stale_node) {\n this._unmark_node(stale_node);\n } else {\n this._marked_ids.delete(stale_ids[i]);\n }\n }\n\n for (let i = 0; i < selected_nodes.length; i++) {\n this._mark_node(selected_nodes[i]);\n }\n }\n\n _emit(evt, changedNodes, focusNode) {\n const nodeIds = (changedNodes || []).map(node => node.id);\n this.jm.invoke_event_handle(EventType.select, {\n evt,\n data: nodeIds,\n node: focusNode ? focusNode.id : null,\n nodes: nodeIds,\n });\n }\n\n get_selected_nodes() {\n this._ensure_state();\n return Array.from(this.jm.mind.selected_nodes).map(node => node.id);\n }\n\n get_selected_node_set() {\n this._ensure_state();\n return new Set(this.jm.mind.selected_nodes);\n }\n\n is_node_selected(node) {\n const nodeObj = this._resolve_node(node);\n if (!nodeObj) {\n return false;\n }\n this._ensure_state();\n return this.jm.mind.selected_nodes.has(nodeObj);\n }\n\n get_selection_mode() {\n return this._mode;\n }\n\n select_node(node) {\n const nodeObj = this._resolve_node(node);\n if (!this._is_visible(nodeObj)) {\n return;\n }\n\n this._ensure_state();\n const prev = Array.from(this.jm.mind.selected_nodes);\n\n this.jm.mind.selected_nodes.clear();\n this.jm.mind.selected_nodes.add(nodeObj);\n this._set_focus(nodeObj);\n this._mode = 'single';\n this._sync_view_from_state();\n\n const removed = prev.filter(n => n.id !== nodeObj.id);\n if (removed.length) {\n this._emit('multi_deselect', removed, nodeObj);\n }\n this._emit('select_node', [nodeObj], nodeObj);\n }\n\n select_clear() {\n this._ensure_state();\n if (this.jm.mind.selected_nodes.size === 0) {\n this._set_focus(null);\n this._mode = null;\n return;\n }\n\n const removed = Array.from(this.jm.mind.selected_nodes);\n this.jm.mind.selected_nodes.clear();\n this._set_focus(null);\n this._mode = null;\n this._sync_view_from_state();\n this._emit('clear_selection', removed, null);\n }\n\n toggle_node_selection(node) {\n const nodeObj = this._resolve_node(node);\n if (!this._is_visible(nodeObj)) {\n return;\n }\n\n this._ensure_state();\n if (this.jm.mind.selected_nodes.has(nodeObj)) {\n this.jm.mind.selected_nodes.delete(nodeObj);\n if (this.jm.mind.selected === nodeObj) {\n const remain = Array.from(this.jm.mind.selected_nodes);\n this._set_focus(remain.length ? remain[remain.length - 1] : null);\n }\n this._mode = this._derive_mode();\n this._sync_view_from_state();\n this._emit('multi_deselect', [nodeObj], this.jm.mind.selected || null);\n return;\n }\n\n this.jm.mind.selected_nodes.add(nodeObj);\n this._set_focus(nodeObj);\n this._mode = this._derive_mode();\n this._sync_view_from_state();\n this._emit('multi_select', [nodeObj], nodeObj);\n }\n\n set_selection(nodes, opts) {\n this._ensure_state();\n const options = opts || {};\n const normalized = [];\n const uniq = new Set();\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i];\n if (!node || !this._is_visible(node) || uniq.has(node.id)) {\n continue;\n }\n uniq.add(node.id);\n normalized.push(node);\n }\n\n const prev = Array.from(this.jm.mind.selected_nodes);\n this.jm.mind.selected_nodes.clear();\n for (let i = 0; i < normalized.length; i++) {\n this.jm.mind.selected_nodes.add(normalized[i]);\n }\n\n const focus = options.focusNode || (normalized.length ? normalized[normalized.length - 1] : null);\n this._set_focus(focus);\n this._mode = this._derive_mode();\n this._sync_view_from_state();\n\n if (options.emit === false) {\n return;\n }\n\n const prevIds = new Set(prev.map(n => n.id));\n const nextIds = new Set(normalized.map(n => n.id));\n\n const added = normalized.filter(n => !prevIds.has(n.id));\n const removed = prev.filter(n => !nextIds.has(n.id));\n\n if (removed.length) {\n this._emit('multi_deselect', removed, focus);\n }\n if (added.length) {\n this._emit('multi_select', added, focus);\n }\n if (!added.length && !removed.length && focus && options.forceSelectEvent) {\n this._emit('select_node', [focus], focus);\n }\n }\n\n prune_removed(nodeIds) {\n this._ensure_state();\n if (!nodeIds || !nodeIds.length || this.jm.mind.selected_nodes.size === 0) {\n return;\n }\n\n const ids = new Set(nodeIds);\n const removed = [];\n this.jm.mind.selected_nodes.forEach(node => {\n if (ids.has(node.id)) {\n removed.push(node);\n }\n });\n if (!removed.length) {\n return;\n }\n\n for (let i = 0; i < removed.length; i++) {\n this.jm.mind.selected_nodes.delete(removed[i]);\n }\n\n if (this.jm.mind.selected && ids.has(this.jm.mind.selected.id)) {\n const remain = Array.from(this.jm.mind.selected_nodes);\n this._set_focus(remain.length ? remain[remain.length - 1] : null);\n }\n this._mode = this._derive_mode();\n this._sync_view_from_state();\n this._emit('multi_deselect', removed, this.jm.mind.selected || null);\n }\n}\n\nclass SelectBox {\n constructor(jm, state, getOptions, isEnabled) {\n this.jm = jm;\n this.state = state;\n this.getOptions = getOptions;\n this.isEnabled = isEnabled;\n\n this._dragging = false;\n this._active = false;\n this._append_mode = false;\n this._base_selected = [];\n this._start_client = { x: 0, y: 0 };\n this._current_client = { x: 0, y: 0 };\n this._overlay = null;\n\n this._on_mouse_move = this._on_mouse_move.bind(this);\n this._on_mouse_up = this._on_mouse_up.bind(this);\n }\n\n is_selecting() {\n return this._dragging;\n }\n\n should_start(e) {\n if (!this.isEnabled()) {\n return false;\n }\n const options = this.getOptions();\n if (!options.enable_box_selection) {\n return false;\n }\n\n if (options.use_left_key_selection_right_key_drag) {\n return e.which === 1;\n }\n\n return (e.ctrlKey || e.metaKey) && e.which === 3;\n }\n\n start(e) {\n if (this._dragging) {\n return;\n }\n\n this._dragging = true;\n this._active = false;\n this._append_mode = !!(e.ctrlKey || e.metaKey);\n this._base_selected = Array.from(this.state.get_selected_node_set());\n this._start_client = { x: e.clientX, y: e.clientY };\n this._current_client = { x: e.clientX, y: e.clientY };\n\n if (!this._append_mode) {\n this.state.set_selection([], { emit: false });\n }\n\n this._ensure_overlay();\n this._update_overlay();\n document.addEventListener('mousemove', this._on_mouse_move, true);\n document.addEventListener('mouseup', this._on_mouse_up, true);\n }\n\n _ensure_overlay() {\n if (this._overlay) {\n return;\n }\n const overlay = document.createElement('div');\n overlay.style.position = 'fixed';\n overlay.style.pointerEvents = 'none';\n overlay.style.border = '1px solid #0984e3';\n overlay.style.background = 'rgba(9,132,227,0.2)';\n overlay.style.zIndex = '2147483000';\n overlay.style.display = 'none';\n document.body.appendChild(overlay);\n this._overlay = overlay;\n }\n\n _update_overlay() {\n if (!this._overlay) {\n return;\n }\n const x = Math.min(this._start_client.x, this._current_client.x);\n const y = Math.min(this._start_client.y, this._current_client.y);\n const w = Math.abs(this._start_client.x - this._current_client.x);\n const h = Math.abs(this._start_client.y - this._current_client.y);\n\n this._overlay.style.left = x + 'px';\n this._overlay.style.top = y + 'px';\n this._overlay.style.width = w + 'px';\n this._overlay.style.height = h + 'px';\n this._overlay.style.display = this._active ? 'block' : 'none';\n }\n\n _collect_nodes_in_rect() {\n if (!this.jm.mind || !this.jm.mind.nodes) {\n return [];\n }\n\n const x1 = Math.min(this._start_client.x, this._current_client.x);\n const y1 = Math.min(this._start_client.y, this._current_client.y);\n const x2 = Math.max(this._start_client.x, this._current_client.x);\n const y2 = Math.max(this._start_client.y, this._current_client.y);\n\n const values = Object.values(this.jm.mind.nodes);\n const selected = [];\n for (let i = 0; i < values.length; i++) {\n const node = values[i];\n if (!this.jm.layout.is_visible(node)) {\n continue;\n }\n const element = node._data && node._data.view && node._data.view.element;\n if (!element) {\n continue;\n }\n const rect = element.getBoundingClientRect();\n const overlap = !(rect.right < x1 || rect.left > x2 || rect.bottom < y1 || rect.top > y2);\n if (overlap) {\n selected.push(node);\n }\n }\n return selected;\n }\n\n _on_mouse_move(e) {\n if (!this._dragging) {\n return;\n }\n this._current_client = { x: e.clientX, y: e.clientY };\n const dx = Math.abs(this._start_client.x - this._current_client.x);\n const dy = Math.abs(this._start_client.y - this._current_client.y);\n this._active = dx > 4 || dy > 4;\n\n if (!this._active) {\n this._update_overlay();\n return;\n }\n\n const hitNodes = this._collect_nodes_in_rect();\n const merged = this._append_mode\n ? this._base_selected.concat(hitNodes.filter(node => !this._base_selected.find(n => n.id === node.id)))\n : hitNodes;\n\n this.state.set_selection(merged, {\n focusNode: merged.length ? merged[merged.length - 1] : null,\n emit: false,\n });\n this._update_overlay();\n\n e.preventDefault();\n e.stopPropagation();\n }\n\n _on_mouse_up(e) {\n if (!this._dragging) {\n return;\n }\n\n const wasActive = this._active;\n this._dragging = false;\n this._active = false;\n this._base_selected = [];\n if (this._overlay) {\n this._overlay.style.display = 'none';\n }\n\n document.removeEventListener('mousemove', this._on_mouse_move, true);\n document.removeEventListener('mouseup', this._on_mouse_up, true);\n\n if (wasActive) {\n const current = Array.from(this.state.get_selected_node_set());\n this.state.set_selection(current, {\n focusNode: current.length ? current[current.length - 1] : null,\n emit: true,\n });\n e.preventDefault();\n e.stopPropagation();\n }\n }\n\n destroy() {\n this._dragging = false;\n document.removeEventListener('mousemove', this._on_mouse_move, true);\n document.removeEventListener('mouseup', this._on_mouse_up, true);\n if (this._overlay && this._overlay.parentNode) {\n this._overlay.parentNode.removeChild(this._overlay);\n }\n this._overlay = null;\n }\n}\n\nclass MultiSelectInteraction {\n constructor(jm, state, getOptions, isEnabled) {\n this.jm = jm;\n this.state = state;\n this.getOptions = getOptions;\n this.isEnabled = isEnabled;\n this.selectBox = new SelectBox(jm, state, getOptions, isEnabled);\n\n this._on_nodes_mousedown = this._on_nodes_mousedown.bind(this);\n this._on_panel_contextmenu = this._on_panel_contextmenu.bind(this);\n }\n\n bind() {\n if (!this.jm.view || !this.jm.view.e_nodes || !this.jm.view.e_panel) {\n logger.warn('[multiSelect] view is not ready, interaction skipped');\n return;\n }\n this.jm.view.e_nodes.addEventListener('mousedown', this._on_nodes_mousedown, true);\n this.jm.view.e_panel.addEventListener('contextmenu', this._on_panel_contextmenu, true);\n }\n\n _on_panel_contextmenu(e) {\n if (!this.isEnabled()) {\n return;\n }\n if (this.selectBox.is_selecting()) {\n e.preventDefault();\n e.stopPropagation();\n }\n }\n\n _on_nodes_mousedown(e) {\n if (!this.isEnabled()) {\n return;\n }\n\n const options = this.getOptions();\n const element = e.target || e.currentTarget;\n const nodeId = this.jm.view.get_binded_nodeid(element);\n const isNode = nodeId && this.jm.view.is_node(element);\n\n if (isNode) {\n if (options.enable_ctrl_key_node_selection && (e.ctrlKey || e.metaKey)) {\n this.state.toggle_node_selection(nodeId);\n } else {\n this.state.select_node(nodeId);\n }\n e.preventDefault();\n e.stopPropagation();\n if (e.stopImmediatePropagation) {\n e.stopImmediatePropagation();\n }\n return;\n }\n\n if (!nodeId && this.selectBox.should_start(e)) {\n this.selectBox.start(e);\n e.preventDefault();\n e.stopPropagation();\n if (e.stopImmediatePropagation) {\n e.stopImmediatePropagation();\n }\n return;\n }\n\n if (!nodeId && !(e.ctrlKey || e.metaKey || e.shiftKey)) {\n this.state.select_clear();\n e.preventDefault();\n e.stopPropagation();\n if (e.stopImmediatePropagation) {\n e.stopImmediatePropagation();\n }\n }\n }\n\n destroy() {\n if (this.jm.view && this.jm.view.e_nodes) {\n this.jm.view.e_nodes.removeEventListener('mousedown', this._on_nodes_mousedown, true);\n }\n if (this.jm.view && this.jm.view.e_panel) {\n this.jm.view.e_panel.removeEventListener('contextmenu', this._on_panel_contextmenu, true);\n }\n this.selectBox.destroy();\n }\n}\n\nexport class MultiSelectPlugin extends Plugin {\n static instanceName = 'multiSelectPlugin';\n static preload = false;\n\n constructor({ jm, pluginOpt }) {\n super({ jm, pluginOpt });\n this.options = Object.assign({}, DEFAULT_OPTIONS, pluginOpt || {});\n this._enabled = !!this.options.enable_multi_select;\n\n this._state = new MultiSelectState(jm);\n this._interaction = new MultiSelectInteraction(\n jm,\n this._state,\n () => this.options,\n () => this._enabled\n );\n\n this._listener = (type, data) => {\n if (!this._enabled) {\n return;\n }\n if (type === EventType.show) {\n this._state.select_clear();\n return;\n }\n if (type === EventType.edit && data && data.evt === 'remove_node') {\n this._state.prune_removed(data.data || []);\n }\n };\n\n this._mountAPI();\n this.jm.add_event_listener(this._listener);\n this._interaction.bind();\n\n if (this._enabled && typeof this.jm.disable_event_handle === 'function') {\n this.jm.disable_event_handle('mousedown');\n }\n }\n\n _mountAPI() {\n const plugin = this;\n const api = {\n get_selected_nodes: () => plugin._state.get_selected_nodes(),\n is_node_selected: node => plugin._state.is_node_selected(node),\n select_node: node => plugin._state.select_node(node),\n select_clear: () => plugin._state.select_clear(),\n toggle_node_selection: node => plugin._state.toggle_node_selection(node),\n get_selection_mode: () => plugin._state.get_selection_mode(),\n getOptions: () => Object.assign({}, plugin.options, { enable_multi_select: plugin._enabled }),\n enable: () => plugin.setEnabled(true),\n disable: () => plugin.setEnabled(false),\n setEnabled: flag => plugin.setEnabled(flag),\n setOptions: partial => plugin.setOptions(partial),\n };\n\n Object.defineProperty(this.jm, 'multiSelect', {\n value: api,\n configurable: true,\n enumerable: false,\n writable: false,\n });\n }\n\n setEnabled(flag) {\n this._enabled = !!flag;\n this.options.enable_multi_select = this._enabled;\n if (this._enabled) {\n if (typeof this.jm.disable_event_handle === 'function') {\n this.jm.disable_event_handle('mousedown');\n }\n } else if (typeof this.jm.enable_event_handle === 'function') {\n this.jm.enable_event_handle('mousedown');\n }\n }\n\n setOptions(partial) {\n this.options = Object.assign({}, this.options, partial || {});\n }\n\n beforePluginRemove() {\n if (typeof this.jm.enable_event_handle === 'function') {\n this.jm.enable_event_handle('mousedown');\n }\n this._enabled = false;\n\n if (this._interaction) {\n this._interaction.destroy();\n }\n if (this._listener && this.jm && Array.isArray(this.jm.event_handles)) {\n const index = this.jm.event_handles.indexOf(this._listener);\n if (index >= 0) {\n this.jm.event_handles.splice(index, 1);\n }\n }\n\n if (this.jm && Object.prototype.hasOwnProperty.call(this.jm, 'multiSelect')) {\n delete this.jm.multiSelect;\n }\n }\n\n beforePluginDestroy() {\n this.beforePluginRemove();\n }\n}\n\nexport const MultiSelectCore = MultiSelectState;\nexport { MultiSelectState, MultiSelectInteraction, SelectBox };\nexport default MultiSelectPlugin;\n"],"names":["String","prototype","startsWith","p","this","slice","length","EventType","LogLevel","_noop","logger","console","level","log","debug","info","warn","error","log_level","Plugin","static","constructor","jm","pluginOpt","options","beforePluginRemove","beforePluginDestroy","DEFAULT_OPTIONS","enable_multi_select","enable_ctrl_key_node_selection","enable_box_selection","use_left_key_selection_right_key_drag","MultiSelectState","_mode","_last_selected_node","_marked_ids","Set","_ensure_state","mind","selected_nodes","_resolve_node","node","get_node","_is_visible","layout","is_visible","_derive_mode","size","_set_focus","selected","view","selected_node","_mark_node","element","_data","classList","add","test","className","id","_unmark_node","remove","replace","delete","_sync_view_from_state","selected_ids","Array","from","i","stale_ids","forEach","has","push","stale_node","_emit","evt","changedNodes","focusNode","nodeIds","map","invoke_event_handle","data","nodes","get_selected_nodes","get_selected_node_set","is_node_selected","nodeObj","get_selection_mode","select_node","prev","clear","removed","filter","n","select_clear","toggle_node_selection","remain","set_selection","opts","normalized","uniq","focus","emit","prevIds","nextIds","added","forceSelectEvent","prune_removed","ids","SelectBox","state","getOptions","isEnabled","_dragging","_active","_append_mode","_base_selected","_start_client","x","y","_current_client","_overlay","_on_mouse_move","bind","_on_mouse_up","is_selecting","should_start","e","which","ctrlKey","metaKey","start","clientX","clientY","_ensure_overlay","_update_overlay","document","addEventListener","overlay","createElement","style","position","pointerEvents","border","background","zIndex","display","body","appendChild","Math","min","w","abs","h","left","top","width","height","_collect_nodes_in_rect","x1","y1","x2","max","y2","values","Object","rect","getBoundingClientRect","right","bottom","dx","dy","hitNodes","merged","concat","find","preventDefault","stopPropagation","wasActive","removeEventListener","current","destroy","parentNode","removeChild","MultiSelectInteraction","selectBox","_on_nodes_mousedown","_on_panel_contextmenu","e_nodes","e_panel","target","currentTarget","nodeId","get_binded_nodeid","is_node","stopImmediatePropagation","shiftKey","MultiSelectPlugin","super","assign","_enabled","_state","_interaction","_listener","type","_mountAPI","add_event_listener","disable_event_handle","plugin","api","enable","setEnabled","disable","flag","setOptions","partial","defineProperty","value","configurable","enumerable","writable","enable_event_handle","isArray","event_handles","index","indexOf","splice","hasOwnProperty","call","multiSelect","MultiSelectCore"],"mappings":"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"}
|
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* Project Home:
|
|
6
6
|
* https://github.com/hizzgdev/jsmind/
|
|
7
7
|
*/
|
|
8
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),"function"!=typeof String.prototype.startsWith&&(String.prototype.startsWith=function(e){return this.slice(0,e.length)===e});const e=1,t=4,s=1,i=2,n=3,l=4;var o=function(){};let _="undefined"==typeof console?{level:o,log:o,debug:o,info:o,warn:o,error:o}:{level:function(e){_.debug=e>s?o:console.debug;_.info=e>i?o:console.info;_.warn=e>n?o:console.warn;_.error=e>l?o:console.error},log:console.log,debug:console.debug,info:console.info,warn:console.warn,error:console.error};class d{static instanceName="";static preload=!1;constructor({jm:e,pluginOpt:t}){this.jm=e,this.options=t||{}}beforePluginRemove(){}beforePluginDestroy(){this.beforePluginRemove()}}const c={enable_multi_select:!1,include_descendants:!0,shift_simple_mode:!1,allow_ctrl:!0,allow_shift:!0,filter:null};class r{constructor(e,t){this.jm=e,this.options=t,this._ensure_selection_state(),this._selection_mode=null,this._last_selected_node=null}_ensure_selection_state(){this.jm.mind||(this.jm.mind={}),this.jm.mind.selected_nodes||(this.jm.mind.selected_nodes=new Set),this.jm.view||(this.jm.view={}),this.jm.view.multi_selected_nodes||(this.jm.view.multi_selected_nodes=new Map)}get_selected_nodes(){return this._ensure_selection_state(),this.jm.mind&&this.jm.mind.selected_nodes?Array.from(this.jm.mind.selected_nodes).map(e=>e.id):[]}is_node_selected(e){const t=this._resolve_node(e);return!(!t||!this.jm.mind)&&(this._ensure_selection_state(),this.jm.mind.selected_nodes.has(t))}select_node(e){const t=this._resolve_node(e);if(!t)return void _.error("[multiSelect] node not found: "+e);if(this._ensure_selection_state(),this._clear_selection_state(),this._ensure_selection_state(),!this.jm.mind||!this.jm.mind.selected_nodes)return void _.error("[multiSelect] jm.mind or selected_nodes is not available");this.jm.mind.selected=t,this._last_selected_node=t,this.jm.mind.selected_nodes.has(t)||this.jm.mind.selected_nodes.add(t),this._mark_node_selected(t),this._selection_mode="single";const s=[t.id];this._invoke_select_event({evt:"select_node",data:s,node:t.id,nodes:s})}select_clear(){this._ensure_selection_state(),this.jm.mind&&(this.jm.mind.selected=null,this._last_selected_node=null,this._clear_selection_state())}toggle_node_selection(e){const t=this._resolve_node(e);if(t&&this.jm.layout.is_visible(t))if(this._ensure_selection_state(),this.jm.mind.selected_nodes.has(t))this._deselect_subtree(t);else{this._selection_mode="multi";this._append_selection([t]).length&&(this.jm.mind.selected=t,this._last_selected_node=t,this._invoke_select_event({evt:"multi_select",data:[t.id],node:t.id,nodes:[t.id]}))}}toggle_subtree_selection(e,t){const s=this._resolve_node(e);if(!s)return void _.error("[multiSelect] node not found: "+e);if(!this.jm.layout.is_visible(s))return;const i=t&&void 0!==t.include_descendants?!!t.include_descendants:!1!==this.options.include_descendants;if(this._ensure_selection_state(),this.jm.mind.selected_nodes.has(s)&&"multi"===this._selection_mode){let e=this._collect_subtree_nodes(s,{includeChildren:!0,respectFilter:!1,skipRootFilter:!1});e.length||(e=[s]);const t=this._remove_selection(e);if(t.length){this.jm.mind.selected&&this.jm.mind.selected.id===s.id&&(this.jm.mind.selected=null),this._selection_mode=this._derive_selection_mode();const e=t.map(e=>e.id);this._invoke_select_event({evt:"multi_deselect",data:e,node:s.id,nodes:e})}}else{this._selection_mode="multi";let e=this._collect_subtree_nodes(s,{includeChildren:i,respectFilter:!0,skipRootFilter:!0});e.length||(e=[s]);const t=this._append_selection(e,{focusNode:s});this._ensure_selection_state();const n=s.parent&&!this.jm.mind.selected_nodes.has(s.parent)?this._ensure_ancestor_selection([s],s,{requireAncestorChainSelected:!0}):[],l=t.concat(n);if(l.length){this.jm.mind.selected=s;const e=l.map(e=>e.id);this._invoke_select_event({evt:"multi_select",data:e,node:s.id,nodes:e})}}}get_selection_mode(){return this._selection_mode}_handle_node_click(e){const{e:t,node:s,element:i}=e;if(!s||!i)return;this._ensure_selection_state();const n=this._get_multi_select_mode(t);if("ctrl"===n)this.toggle_node_selection(s);else if("shift"===n){const e=this.jm.get_node(s);if(!e)return void _.warn("[multiSelect] Node not found for shift selection: "+s);if(this.options.shift_simple_mode)this.is_node_selected(s)?this._deselect_subtree(e):this._range_select_nodes(s);else if(this.is_node_selected(s))this._deselect_subtree(e);else{const t=!1!==this.options.include_descendants;let s=this._collect_subtree_nodes(e,{includeChildren:t,respectFilter:!0,skipRootFilter:!0});s.length||(s=[e]);const i=this._append_selection(s,{focusNode:e});if(i.length){this.jm.mind.selected=e,this._last_selected_node=e,this._selection_mode=this._derive_selection_mode();const t=i.map(e=>e.id);this._invoke_select_event({evt:"multi_select",data:t,node:e.id,nodes:t})}else this._ensure_selection_state(),this.jm.mind.selected_nodes.has(e)||(this.jm.mind.selected_nodes.add(e),this._mark_node_selected(e)),this.jm.mind.selected=e,this._last_selected_node=e,this._selection_mode=this._derive_selection_mode(),this._invoke_select_event({evt:"multi_select",data:[e.id],node:e.id,nodes:[e.id]})}}else this.select_node(s)}_handle_node_removed(e){this._ensure_selection_state(),this.jm.mind.selected_nodes.has(e)&&this.jm.mind.selected_nodes.delete(e),this._last_selected_node&&this._last_selected_node.id===e.id&&(this._last_selected_node=null),this.jm.view.multi_selected_nodes&&this.jm.view.multi_selected_nodes.has(e.id)&&this._unmark_node_selected(e)}_get_multi_select_mode(e){return e?!1!==this.options.allow_shift&&!0===e.shiftKey?"shift":!1===this.options.allow_ctrl||!0!==e.ctrlKey&&!0!==e.metaKey?null:"ctrl":null}_append_selection(e,t){if(!e||!e.length)return[];if(this._ensure_selection_state(),!this.jm.mind||!this.jm.mind.selected_nodes)return _.warn("[multiSelect] Cannot append selection: selected_nodes not available"),[];const s=[];for(let t=0;t<e.length;t++){const i=e[t];this.jm.mind.selected_nodes.has(i)||(this.jm.mind.selected_nodes.add(i),s.push(i))}if(s.length){const e=t&&t.focusNode?t.focusNode:null;this._mark_nodes_selected(s,e||s[s.length-1])}return s}_remove_selection(e){if(!e||!e.length)return[];this._ensure_selection_state();const t=[];for(let s=0;s<e.length;s++){const i=e[s];this.jm.mind.selected_nodes.has(i)&&(this.jm.mind.selected_nodes.delete(i),t.push(i))}return t.length&&this._unmark_nodes_selected(t),t}_deselect_subtree(e){let t=this._collect_subtree_nodes(e,{includeChildren:!0,respectFilter:!1,skipRootFilter:!1});t.length||(t=[e]);const s=this._remove_selection(t);if(s.length){this.jm.mind.selected&&this.jm.mind.selected.id===e.id&&(this.jm.mind.selected=null),this._selection_mode=this._derive_selection_mode();const t=s.map(e=>e.id);this._invoke_select_event({evt:"multi_deselect",data:t,node:e.id,nodes:t})}}_clear_selection_state(){if(this._ensure_selection_state(),this._selection_mode=null,this.jm.mind&&this.jm.mind.selected_nodes||this._ensure_selection_state(),!this.jm.mind||!this.jm.mind.selected_nodes||0===this.jm.mind.selected_nodes.size)return this._clear_all_selected_nodes_view(),[];const e=Array.from(this.jm.mind.selected_nodes);return this.jm.mind.selected_nodes.clear(),this._unmark_nodes_selected(e),e}_collect_subtree_nodes(e,t){const s=t||{},i=!1!==s.includeChildren,n=!!s.respectFilter,l=!!s.skipRootFilter,o=n?this._get_selection_filter():null,_=[],d=(e,t)=>{let s=!0;if(!o||l&&t||(s=!1!==o(e)),s&&_.push(e),i&&e.children)for(let t=0;t<e.children.length;t++)d(e.children[t],!1)};return d(e,!0),_}_ensure_ancestor_selection(e,t,s){if(!e||!e.length)return[];this._ensure_selection_state();const i=!(!s||!s.requireAncestorChainSelected),n=[],l=Object.create(null);for(let t=0;t<e.length;t++){let s=e[t].parent;if(!s)continue;const o=[];let _=!i;for(;s;){if(this.jm.mind.selected_nodes.has(s)){_=!0;break}o.push(s),s=s.parent}if(_)for(let e=0;e<o.length;e++){const t=o[e];this.jm.mind.selected_nodes.has(t)||l[t.id]||(n.push(t),l[t.id]=!0)}}if(!n.length)return[];const o=t||e[e.length-1];return this._append_selection(n,{focusNode:o})}_get_selection_filter(){return this.options&&"function"==typeof this.options.filter?this.options.filter:null}_range_select_nodes(e){const t=this._resolve_node(e);if(!t||!this.jm.layout.is_visible(t))return;if(this._ensure_selection_state(),0===this.jm.mind.selected_nodes.size){let e=this._collect_subtree_nodes(t,{includeChildren:!0,respectFilter:!0,skipRootFilter:!0});e.length||(e=[t]);const s=this._append_selection(e);if(s.length){this.jm.mind.selected=t,this._last_selected_node=t,this._selection_mode=this._derive_selection_mode();const e=s.map(e=>e.id);this._invoke_select_event({evt:"multi_select",data:e,node:t.id,nodes:e})}return}this._ensure_selection_state();const s=Array.from(this.jm.mind.selected_nodes),i=this._last_selected_node&&this.jm.mind.selected_nodes.has(this._last_selected_node)?this._last_selected_node:s[0],n=this._find_nodes_between(i,t);if(!n.length){const e=[t],s=this._append_selection(e);if(s.length){this.jm.mind.selected=t,this._last_selected_node=t,this._selection_mode=this._derive_selection_mode();const e=s.map(e=>e.id);this._invoke_select_event({evt:"multi_select",data:e,node:t.id,nodes:e})}return}this._ensure_selection_state();const l=n.filter(e=>!this.jm.mind.selected_nodes.has(e)),o=this._append_selection(l);if(o.length){this.jm.mind.selected=t,this._last_selected_node=t,this._selection_mode=this._derive_selection_mode();const e=o.map(e=>e.id);this._invoke_select_event({evt:"multi_select",data:e,node:t.id,nodes:e})}}_find_nodes_between(e,t){if(!e||!t)return[];const s=[],i=e=>{if(this.jm.layout.is_visible(e)&&s.push(e),e.children)for(let t=0;t<e.children.length;t++)i(e.children[t])};this.jm.mind&&this.jm.mind.root&&i(this.jm.mind.root);let n=-1,l=-1;for(let i=0;i<s.length;i++)s[i].id===e.id&&(n=i),s[i].id===t.id&&(l=i);if(-1===n||-1===l)return[];const o=Math.min(n,l),_=Math.max(n,l);return s.slice(o,_+1)}_derive_selection_mode(){this._ensure_selection_state();const e=this.jm.mind.selected_nodes.size;return 0===e?null:e>1?"multi":"single"}_mark_nodes_selected(e,t){if(e&&e.length){for(let t=0;t<e.length;t++)this._mark_node_selected(e[t]);this.jm.view.selected_node=t||e[e.length-1]}}_mark_node_selected(e){if(!e||this.jm.view.multi_selected_nodes.has(e.id))return;const t=e._data&&e._data.view&&e._data.view.element;t&&(t.classList?t.classList.add("selected"):/(\s|^)selected(\s|$)/.test(t.className)||(t.className+=" selected"),this.jm.view.multi_selected_nodes.set(e.id,e))}_unmark_nodes_selected(e){if(e&&e.length)for(let t=0;t<e.length;t++)this._unmark_node_selected(e[t])}_unmark_node_selected(e){if(e){if(this.jm.view.multi_selected_nodes.has(e.id)){const t=e._data&&e._data.view&&e._data.view.element;t&&(t.classList?t.classList.remove("selected"):t.className=t.className.replace(/\s*selected\b/i,"")),this.jm.view.multi_selected_nodes.delete(e.id)}this.jm.view.selected_node&&this.jm.view.selected_node.id===e.id&&(this.jm.view.selected_node=null)}}_clear_all_selected_nodes_view(){if(this._ensure_selection_state(),!this.jm.view.multi_selected_nodes||!this.jm.view.multi_selected_nodes.size)return void(this.jm.view&&(this.jm.view.selected_node=null));const e=Array.from(this.jm.view.multi_selected_nodes.values());for(let t=0;t<e.length;t++)this._unmark_node_selected(e[t]);this.jm.view&&(this.jm.view.selected_node=null)}_invoke_select_event(e){try{e.nodes||(e.nodes=e.data||[]),e.data||(e.data=e.nodes||[]),this.jm.invoke_event_handle(t,e)}catch(e){_.warn("[multiSelect] failed to invoke select event",e)}}_resolve_node(e){return e?"string"==typeof e?this.jm.get_node(e):e:null}}class h extends d{static instanceName="multiSelectPlugin";static preload=!1;constructor({jm:e,pluginOpt:t}){super({jm:e,pluginOpt:t});const s=Object.assign({},c,t||{});this.options=s,this._mounted=!1,this._core=null,this._listener=null,this._enabled=!!s.enable_multi_select,this._initCore()}_initCore(){const t=this.jm,s=this.options,i=this;this._core=new r(t,s),this._mountAPI(),this._listener=(t,s)=>{try{t===e&&i._core.select_clear()}catch(e){_.warn("[multiSelect] listener error",e)}},t.add_event_listener(this._listener),this._original_select_node=t.select_node.bind(t),this._original_select_clear=t.select_clear.bind(t),t.select_node=e=>i._enabled?i._core.select_node(e):i._original_select_node(e),t.select_clear=()=>i._enabled?i._core.select_clear():i._original_select_clear();const n=t.constructor.$;this._domClickHandler=function(e){if(!i._enabled)return;const s=e.target||e.currentTarget,n=t.view.get_binded_nodeid(s);n&&t.view.is_node(s)?(e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation&&e.stopImmediatePropagation(),i._core._handle_node_click({e:e,node:n,element:s,evt:"click"})):n||e.ctrlKey||e.metaKey||e.shiftKey||i._core.select_clear()},t.view&&t.view.e_nodes?(n.on(t.view.e_nodes,"click",this._domClickHandler),_.info("[multiSelect] plugin click handler attached")):_.warn("[multiSelect] nodes container not ready; DOM handler not attached"),this._enabled&&"function"==typeof t.disable_event_handle&&t.disable_event_handle("mousedown"),_.info("[multiSelect] API mounted and event listener attached.")}_mountAPI(){if(this._mounted)return;const e=this.jm,t=this,s={get_selected_nodes:()=>t._core?t._core.get_selected_nodes():(_.warn("[multiSelect] Core not initialized"),[]),is_node_selected:e=>!!t._core&&t._core.is_node_selected(e),select_node:e=>{t._core?t._core.select_node(e):_.warn("[multiSelect] Core not initialized")},select_clear:()=>{t._core&&t._core.select_clear()},toggle_node_selection:e=>{t._core?t._core.toggle_node_selection(e):_.warn("[multiSelect] Core not initialized")},toggle_subtree_selection:e=>{t._core?t._core.toggle_subtree_selection(e):_.warn("[multiSelect] Core not initialized")},get_selection_mode:()=>t._core?t._core.get_selection_mode():null,getOptions:()=>{const e=t._core?t._core.options:t.options;return Object.assign({},e,{enable_multi_select:t._enabled})},enable:()=>t.setEnabled(!0),disable:()=>t.setEnabled(!1),setEnabled:e=>t.setEnabled(e),setOptions:e=>t.setOptions(e)};Object.defineProperty(e,"multiSelect",{value:s,configurable:!0,enumerable:!1,writable:!1}),this._mounted=!0,_.info("[multiSelect] API mounted.")}beforePluginRemove(){try{if(this._listener&&this.jm&&Array.isArray(this.jm.event_handles)){const e=this.jm.event_handles.indexOf(this._listener);e>=0&&this.jm.event_handles.splice(e,1)}"function"==typeof this.jm.enable_event_handle&&this.jm.enable_event_handle("mousedown"),this._domClickHandler&&this.jm&&this.jm.view&&this.jm.view.e_nodes&&(this._domClickHandler=null),this._original_select_node&&(this.jm.select_node=this._original_select_node),this._original_select_clear&&(this.jm.select_clear=this._original_select_clear),this.jm&&Object.prototype.hasOwnProperty.call(this.jm,"multiSelect")&&delete this.jm.multiSelect,this._mounted=!1}catch(e){_.error("[multiSelect] remove failed:",e)}}setEnabled(e){const t=!!e;this._enabled!==t&&(this._enabled=t,this.options.enable_multi_select=this._enabled,this._enabled?"function"==typeof this.jm.disable_event_handle&&this.jm.disable_event_handle("mousedown"):"function"==typeof this.jm.enable_event_handle&&this.jm.enable_event_handle("mousedown"))}setOptions(e){const t=Object.assign({},e||{});this.options=Object.assign({},this.options,t),this._core&&this._core.options&&(this._core.options=Object.assign({},this._core.options,t))}beforePluginDestroy(){_.debug("[multiSelect] beforePluginDestroy"),this.beforePluginRemove()}}exports.MultiSelectCore=r,exports.MultiSelectPlugin=h,exports.default=h;
|
|
8
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),"function"!=typeof String.prototype.startsWith&&(String.prototype.startsWith=function(e){return this.slice(0,e.length)===e});const e=1,t=3,s=4,i=1,n=2,o=3,_=4;var l=function(){};let d="undefined"==typeof console?{level:l,log:l,debug:l,info:l,warn:l,error:l}:{level:function(e){d.debug=e>i?l:console.debug;d.info=e>n?l:console.info;d.warn=e>o?l:console.warn;d.error=e>_?l:console.error},log:console.log,debug:console.debug,info:console.info,warn:console.warn,error:console.error};class a{static instanceName="";static preload=!1;constructor({jm:e,pluginOpt:t}){this.jm=e,this.options=t||{}}beforePluginRemove(){}beforePluginDestroy(){this.beforePluginRemove()}}const r={enable_multi_select:!1,enable_ctrl_key_node_selection:!0,enable_box_selection:!0,use_left_key_selection_right_key_drag:!1};class h{constructor(e){this.jm=e,this._mode=null,this._last_selected_node=null,this._marked_ids=new Set,this._ensure_state()}_ensure_state(){this.jm.mind||(this.jm.mind={}),this.jm.mind.selected_nodes||(this.jm.mind.selected_nodes=new Set)}_resolve_node(e){return e?"string"==typeof e?this.jm.get_node(e):e:null}_is_visible(e){return!!(e&&this.jm.layout&&this.jm.layout.is_visible(e))}_derive_mode(){this._ensure_state();const e=this.jm.mind.selected_nodes.size;return 0===e?null:1===e?"single":"multi"}_set_focus(e){this.jm.mind.selected=e||null,this.jm.view&&(this.jm.view.selected_node=e||null),this._last_selected_node=e||null}_mark_node(e){if(!e)return;const t=e._data&&e._data.view&&e._data.view.element;t&&(t.classList?t.classList.add("selected"):/(\s|^)selected(\s|$)/.test(t.className)||(t.className+=" selected"),this._marked_ids.add(e.id))}_unmark_node(e){if(!e)return;const t=e._data&&e._data.view&&e._data.view.element;t&&(t.classList?t.classList.remove("selected"):t.className=t.className.replace(/\s*selected\b/i,"")),this._marked_ids.delete(e.id)}_sync_view_from_state(){this._ensure_state();const e=new Set,t=Array.from(this.jm.mind.selected_nodes);for(let s=0;s<t.length;s++)e.add(t[s].id);const s=[];this._marked_ids.forEach(t=>{e.has(t)||s.push(t)});for(let e=0;e<s.length;e++){const t=this.jm.get_node(s[e]);t?this._unmark_node(t):this._marked_ids.delete(s[e])}for(let e=0;e<t.length;e++)this._mark_node(t[e])}_emit(e,t,i){const n=(t||[]).map(e=>e.id);this.jm.invoke_event_handle(s,{evt:e,data:n,node:i?i.id:null,nodes:n})}get_selected_nodes(){return this._ensure_state(),Array.from(this.jm.mind.selected_nodes).map(e=>e.id)}get_selected_node_set(){return this._ensure_state(),new Set(this.jm.mind.selected_nodes)}is_node_selected(e){const t=this._resolve_node(e);return!!t&&(this._ensure_state(),this.jm.mind.selected_nodes.has(t))}get_selection_mode(){return this._mode}select_node(e){const t=this._resolve_node(e);if(!this._is_visible(t))return;this._ensure_state();const s=Array.from(this.jm.mind.selected_nodes);this.jm.mind.selected_nodes.clear(),this.jm.mind.selected_nodes.add(t),this._set_focus(t),this._mode="single",this._sync_view_from_state();const i=s.filter(e=>e.id!==t.id);i.length&&this._emit("multi_deselect",i,t),this._emit("select_node",[t],t)}select_clear(){if(this._ensure_state(),0===this.jm.mind.selected_nodes.size)return this._set_focus(null),void(this._mode=null);const e=Array.from(this.jm.mind.selected_nodes);this.jm.mind.selected_nodes.clear(),this._set_focus(null),this._mode=null,this._sync_view_from_state(),this._emit("clear_selection",e,null)}toggle_node_selection(e){const t=this._resolve_node(e);if(this._is_visible(t)){if(this._ensure_state(),this.jm.mind.selected_nodes.has(t)){if(this.jm.mind.selected_nodes.delete(t),this.jm.mind.selected===t){const e=Array.from(this.jm.mind.selected_nodes);this._set_focus(e.length?e[e.length-1]:null)}return this._mode=this._derive_mode(),this._sync_view_from_state(),void this._emit("multi_deselect",[t],this.jm.mind.selected||null)}this.jm.mind.selected_nodes.add(t),this._set_focus(t),this._mode=this._derive_mode(),this._sync_view_from_state(),this._emit("multi_select",[t],t)}}set_selection(e,t){this._ensure_state();const s=t||{},i=[],n=new Set;for(let t=0;t<e.length;t++){const s=e[t];s&&this._is_visible(s)&&!n.has(s.id)&&(n.add(s.id),i.push(s))}const o=Array.from(this.jm.mind.selected_nodes);this.jm.mind.selected_nodes.clear();for(let e=0;e<i.length;e++)this.jm.mind.selected_nodes.add(i[e]);const _=s.focusNode||(i.length?i[i.length-1]:null);if(this._set_focus(_),this._mode=this._derive_mode(),this._sync_view_from_state(),!1===s.emit)return;const l=new Set(o.map(e=>e.id)),d=new Set(i.map(e=>e.id)),a=i.filter(e=>!l.has(e.id)),r=o.filter(e=>!d.has(e.id));r.length&&this._emit("multi_deselect",r,_),a.length&&this._emit("multi_select",a,_),!a.length&&!r.length&&_&&s.forceSelectEvent&&this._emit("select_node",[_],_)}prune_removed(e){if(this._ensure_state(),!e||!e.length||0===this.jm.mind.selected_nodes.size)return;const t=new Set(e),s=[];if(this.jm.mind.selected_nodes.forEach(e=>{t.has(e.id)&&s.push(e)}),s.length){for(let e=0;e<s.length;e++)this.jm.mind.selected_nodes.delete(s[e]);if(this.jm.mind.selected&&t.has(this.jm.mind.selected.id)){const e=Array.from(this.jm.mind.selected_nodes);this._set_focus(e.length?e[e.length-1]:null)}this._mode=this._derive_mode(),this._sync_view_from_state(),this._emit("multi_deselect",s,this.jm.mind.selected||null)}}}class c{constructor(e,t,s,i){this.jm=e,this.state=t,this.getOptions=s,this.isEnabled=i,this._dragging=!1,this._active=!1,this._append_mode=!1,this._base_selected=[],this._start_client={x:0,y:0},this._current_client={x:0,y:0},this._overlay=null,this._on_mouse_move=this._on_mouse_move.bind(this),this._on_mouse_up=this._on_mouse_up.bind(this)}is_selecting(){return this._dragging}should_start(e){if(!this.isEnabled())return!1;const t=this.getOptions();return!!t.enable_box_selection&&(t.use_left_key_selection_right_key_drag?1===e.which:(e.ctrlKey||e.metaKey)&&3===e.which)}start(e){this._dragging||(this._dragging=!0,this._active=!1,this._append_mode=!(!e.ctrlKey&&!e.metaKey),this._base_selected=Array.from(this.state.get_selected_node_set()),this._start_client={x:e.clientX,y:e.clientY},this._current_client={x:e.clientX,y:e.clientY},this._append_mode||this.state.set_selection([],{emit:!1}),this._ensure_overlay(),this._update_overlay(),document.addEventListener("mousemove",this._on_mouse_move,!0),document.addEventListener("mouseup",this._on_mouse_up,!0))}_ensure_overlay(){if(this._overlay)return;const e=document.createElement("div");e.style.position="fixed",e.style.pointerEvents="none",e.style.border="1px solid #0984e3",e.style.background="rgba(9,132,227,0.2)",e.style.zIndex="2147483000",e.style.display="none",document.body.appendChild(e),this._overlay=e}_update_overlay(){if(!this._overlay)return;const e=Math.min(this._start_client.x,this._current_client.x),t=Math.min(this._start_client.y,this._current_client.y),s=Math.abs(this._start_client.x-this._current_client.x),i=Math.abs(this._start_client.y-this._current_client.y);this._overlay.style.left=e+"px",this._overlay.style.top=t+"px",this._overlay.style.width=s+"px",this._overlay.style.height=i+"px",this._overlay.style.display=this._active?"block":"none"}_collect_nodes_in_rect(){if(!this.jm.mind||!this.jm.mind.nodes)return[];const e=Math.min(this._start_client.x,this._current_client.x),t=Math.min(this._start_client.y,this._current_client.y),s=Math.max(this._start_client.x,this._current_client.x),i=Math.max(this._start_client.y,this._current_client.y),n=Object.values(this.jm.mind.nodes),o=[];for(let _=0;_<n.length;_++){const l=n[_];if(!this.jm.layout.is_visible(l))continue;const d=l._data&&l._data.view&&l._data.view.element;if(!d)continue;const a=d.getBoundingClientRect();!(a.right<e||a.left>s||a.bottom<t||a.top>i)&&o.push(l)}return o}_on_mouse_move(e){if(!this._dragging)return;this._current_client={x:e.clientX,y:e.clientY};const t=Math.abs(this._start_client.x-this._current_client.x),s=Math.abs(this._start_client.y-this._current_client.y);if(this._active=t>4||s>4,!this._active)return void this._update_overlay();const i=this._collect_nodes_in_rect(),n=this._append_mode?this._base_selected.concat(i.filter(e=>!this._base_selected.find(t=>t.id===e.id))):i;this.state.set_selection(n,{focusNode:n.length?n[n.length-1]:null,emit:!1}),this._update_overlay(),e.preventDefault(),e.stopPropagation()}_on_mouse_up(e){if(!this._dragging)return;const t=this._active;if(this._dragging=!1,this._active=!1,this._base_selected=[],this._overlay&&(this._overlay.style.display="none"),document.removeEventListener("mousemove",this._on_mouse_move,!0),document.removeEventListener("mouseup",this._on_mouse_up,!0),t){const t=Array.from(this.state.get_selected_node_set());this.state.set_selection(t,{focusNode:t.length?t[t.length-1]:null,emit:!0}),e.preventDefault(),e.stopPropagation()}}destroy(){this._dragging=!1,document.removeEventListener("mousemove",this._on_mouse_move,!0),document.removeEventListener("mouseup",this._on_mouse_up,!0),this._overlay&&this._overlay.parentNode&&this._overlay.parentNode.removeChild(this._overlay),this._overlay=null}}class m{constructor(e,t,s,i){this.jm=e,this.state=t,this.getOptions=s,this.isEnabled=i,this.selectBox=new c(e,t,s,i),this._on_nodes_mousedown=this._on_nodes_mousedown.bind(this),this._on_panel_contextmenu=this._on_panel_contextmenu.bind(this)}bind(){this.jm.view&&this.jm.view.e_nodes&&this.jm.view.e_panel?(this.jm.view.e_nodes.addEventListener("mousedown",this._on_nodes_mousedown,!0),this.jm.view.e_panel.addEventListener("contextmenu",this._on_panel_contextmenu,!0)):d.warn("[multiSelect] view is not ready, interaction skipped")}_on_panel_contextmenu(e){this.isEnabled()&&this.selectBox.is_selecting()&&(e.preventDefault(),e.stopPropagation())}_on_nodes_mousedown(e){if(!this.isEnabled())return;const t=this.getOptions(),s=e.target||e.currentTarget,i=this.jm.view.get_binded_nodeid(s);return i&&this.jm.view.is_node(s)?(t.enable_ctrl_key_node_selection&&(e.ctrlKey||e.metaKey)?this.state.toggle_node_selection(i):this.state.select_node(i),e.preventDefault(),e.stopPropagation(),void(e.stopImmediatePropagation&&e.stopImmediatePropagation())):!i&&this.selectBox.should_start(e)?(this.selectBox.start(e),e.preventDefault(),e.stopPropagation(),void(e.stopImmediatePropagation&&e.stopImmediatePropagation())):void(i||e.ctrlKey||e.metaKey||e.shiftKey||(this.state.select_clear(),e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation&&e.stopImmediatePropagation()))}destroy(){this.jm.view&&this.jm.view.e_nodes&&this.jm.view.e_nodes.removeEventListener("mousedown",this._on_nodes_mousedown,!0),this.jm.view&&this.jm.view.e_panel&&this.jm.view.e_panel.removeEventListener("contextmenu",this._on_panel_contextmenu,!0),this.selectBox.destroy()}}class u extends a{static instanceName="multiSelectPlugin";static preload=!1;constructor({jm:s,pluginOpt:i}){super({jm:s,pluginOpt:i}),this.options=Object.assign({},r,i||{}),this._enabled=!!this.options.enable_multi_select,this._state=new h(s),this._interaction=new m(s,this._state,()=>this.options,()=>this._enabled),this._listener=(s,i)=>{this._enabled&&(s!==e?s===t&&i&&"remove_node"===i.evt&&this._state.prune_removed(i.data||[]):this._state.select_clear())},this._mountAPI(),this.jm.add_event_listener(this._listener),this._interaction.bind(),this._enabled&&"function"==typeof this.jm.disable_event_handle&&this.jm.disable_event_handle("mousedown")}_mountAPI(){const e=this,t={get_selected_nodes:()=>e._state.get_selected_nodes(),is_node_selected:t=>e._state.is_node_selected(t),select_node:t=>e._state.select_node(t),select_clear:()=>e._state.select_clear(),toggle_node_selection:t=>e._state.toggle_node_selection(t),get_selection_mode:()=>e._state.get_selection_mode(),getOptions:()=>Object.assign({},e.options,{enable_multi_select:e._enabled}),enable:()=>e.setEnabled(!0),disable:()=>e.setEnabled(!1),setEnabled:t=>e.setEnabled(t),setOptions:t=>e.setOptions(t)};Object.defineProperty(this.jm,"multiSelect",{value:t,configurable:!0,enumerable:!1,writable:!1})}setEnabled(e){this._enabled=!!e,this.options.enable_multi_select=this._enabled,this._enabled?"function"==typeof this.jm.disable_event_handle&&this.jm.disable_event_handle("mousedown"):"function"==typeof this.jm.enable_event_handle&&this.jm.enable_event_handle("mousedown")}setOptions(e){this.options=Object.assign({},this.options,e||{})}beforePluginRemove(){if("function"==typeof this.jm.enable_event_handle&&this.jm.enable_event_handle("mousedown"),this._enabled=!1,this._interaction&&this._interaction.destroy(),this._listener&&this.jm&&Array.isArray(this.jm.event_handles)){const e=this.jm.event_handles.indexOf(this._listener);e>=0&&this.jm.event_handles.splice(e,1)}this.jm&&Object.prototype.hasOwnProperty.call(this.jm,"multiSelect")&&delete this.jm.multiSelect}beforePluginDestroy(){this.beforePluginRemove()}}const v=h;exports.MultiSelectCore=v,exports.MultiSelectInteraction=m,exports.MultiSelectPlugin=u,exports.MultiSelectState=h,exports.SelectBox=c,exports.default=u;
|
|
9
9
|
//# sourceMappingURL=jsmind.multi-select.js.map
|