@umbraci/jsmind 0.10.13 → 0.10.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/jsmind.js +1 -1
  2. package/dist/jsmind.js.map +1 -1
  3. package/dist/jsmind.multi-select.js +9 -0
  4. package/dist/jsmind.multi-select.js.map +1 -0
  5. package/es/jsmind.js +1 -1
  6. package/es/jsmind.js.map +1 -1
  7. package/es/jsmind.multi-select.js +9 -0
  8. package/es/jsmind.multi-select.js.map +1 -0
  9. package/lib/jsmind.js +1 -1
  10. package/lib/jsmind.js.map +1 -1
  11. package/lib/jsmind.multi-select.js +9 -0
  12. package/lib/jsmind.multi-select.js.map +1 -0
  13. package/package.json +5 -1
  14. package/types/generated/index.d.ts +0 -8
  15. package/types/generated/jsmind.common.d.ts +0 -68
  16. package/types/generated/jsmind.d.ts +0 -632
  17. package/types/generated/jsmind.data_provider.d.ts +0 -56
  18. package/types/generated/jsmind.dom.d.ts +0 -59
  19. package/types/generated/jsmind.enhanced-plugin.d.ts +0 -103
  20. package/types/generated/jsmind.format.d.ts +0 -113
  21. package/types/generated/jsmind.graph.d.ts +0 -180
  22. package/types/generated/jsmind.layout_provider.d.ts +0 -182
  23. package/types/generated/jsmind.mind.d.ts +0 -129
  24. package/types/generated/jsmind.node.d.ts +0 -69
  25. package/types/generated/jsmind.option.d.ts +0 -79
  26. package/types/generated/jsmind.plugin.d.ts +0 -21
  27. package/types/generated/jsmind.shortcut_provider.d.ts +0 -52
  28. package/types/generated/jsmind.util.d.ts +0 -26
  29. package/types/generated/jsmind.view_provider.d.ts +0 -374
  30. package/types/generated/plugins/history/history-diff.d.ts +0 -310
  31. package/types/generated/plugins/history/jsmind.history.d.ts +0 -87
  32. package/types/generated/plugins/jsmind.draggable-node.d.ts +0 -262
  33. package/types/generated/plugins/jsmind.multiline-text-v2.d.ts +0 -58
  34. package/types/generated/plugins/jsmind.multiline-text.d.ts +0 -43
  35. package/types/generated/plugins/jsmind.screenshot.d.ts +0 -83
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @license BSD-3-Clause
3
+ * @copyright 2014-2025 hizzgdev@163.com
4
+ *
5
+ * Project Home:
6
+ * https://github.com/hizzgdev/jsmind/
7
+ */
8
+ "use strict";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;
9
+ //# sourceMappingURL=jsmind.multi-select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsmind.multi-select.js","sources":["../src/jsmind.common.js","../src/jsmind.enhanced-plugin.js","../src/plugins/jsmind.multi-select.js"],"sourcesContent":["/**\r\n * @license BSD\r\n * @copyright 2014-2025 UmbraCi\r\n *\r\n * Project Home:\r\n * https://github.com/UmbraCi/jsmind/\r\n */\r\n\r\n/**\r\n * Library version string.\r\n * @type {string}\r\n */\r\nexport const __version__ = '0.9.0';\r\n/**\r\n * Library author.\r\n * @type {string}\r\n */\r\nexport const __author__ = 'UmbraCi';\r\n\r\nif (typeof String.prototype.startsWith != 'function') {\r\n String.prototype.startsWith = function (p) {\r\n return this.slice(0, p.length) === p;\r\n };\r\n}\r\n\r\n/**\r\n * Direction constants and parser.\r\n * @typedef {{left:number,center:number,right:number,of:(dir:(string|number))=>number|undefined}} DirectionType\r\n */\r\n/** @type {DirectionType} */\r\nexport const Direction = {\r\n left: -1,\r\n center: 0,\r\n right: 1,\r\n of: function (dir) {\r\n if (!dir || dir === -1 || dir === 0 || dir === 1) {\r\n return dir;\r\n }\r\n if (dir === '-1' || dir === '0' || dir === '1') {\r\n return parseInt(dir);\r\n }\r\n if (dir.toLowerCase() === 'left') {\r\n return this.left;\r\n }\r\n if (dir.toLowerCase() === 'right') {\r\n return this.right;\r\n }\r\n if (dir.toLowerCase() === 'center') {\r\n return this.center;\r\n }\r\n },\r\n};\r\n/** @enum {number} */\r\nexport const EventType = { show: 1, resize: 2, edit: 3, select: 4, reset: 5, history_change: 6 };\r\n/** @enum {number} */\r\nexport const Key = { meta: 1 << 13, ctrl: 1 << 12, alt: 1 << 11, shift: 1 << 10 };\r\n/** @enum {number} */\r\nexport const LogLevel = { debug: 1, info: 2, warn: 3, error: 4, disable: 9 };\r\n\r\n// an noop function define\r\nvar _noop = function () {};\r\n/**\r\n * Logger facade with dynamic level.\r\n * @type {{level:(lvl:number)=>void,log:Function,debug:Function,info:Function,warn:Function,error:Function}}\r\n */\r\nexport let logger =\r\n typeof console === 'undefined'\r\n ? {\r\n level: _noop,\r\n log: _noop,\r\n debug: _noop,\r\n info: _noop,\r\n warn: _noop,\r\n error: _noop,\r\n }\r\n : {\r\n level: setup_logger_level,\r\n log: console.log,\r\n debug: console.debug,\r\n info: console.info,\r\n warn: console.warn,\r\n error: console.error,\r\n };\r\n\r\n/**\r\n * Set logger level.\r\n * @param {number} log_level\r\n */\r\nfunction setup_logger_level(log_level) {\r\n if (log_level > LogLevel.debug) {\r\n logger.debug = _noop;\r\n } else {\r\n logger.debug = console.debug;\r\n }\r\n if (log_level > LogLevel.info) {\r\n logger.info = _noop;\r\n } else {\r\n logger.info = console.info;\r\n }\r\n if (log_level > LogLevel.warn) {\r\n logger.warn = _noop;\r\n } else {\r\n logger.warn = console.warn;\r\n }\r\n if (log_level > LogLevel.error) {\r\n logger.error = _noop;\r\n } else {\r\n logger.error = console.error;\r\n }\r\n}\r\n","/**\r\n * @license BSD\r\n * @copyright 2014-2025 UmbraCi\r\n *\r\n * Project Home:\r\n * https://github.com/UmbraCi/jsmind/\r\n */\r\n\r\nimport { logger } from './jsmind.common.js';\r\n\r\n/**\r\n * Enhanced Plugin Manager\r\n * Manages the lifecycle of enhanced plugins with synchronous initialization,\r\n * preload support, and lifecycle hooks.\r\n */\r\nexport class EnhancedPluginManager {\r\n /**\r\n * @param {import('./jsmind.js').default} jm - jsMind instance\r\n */\r\n constructor(jm) {\r\n this.jm = jm;\r\n /** @type {Map<string, EnhancedPlugin>} */\r\n this.plugins = new Map();\r\n }\r\n\r\n /**\r\n * Initialize preload plugins (before core modules)\r\n */\r\n initPreloadPlugins() {\r\n const preloadPlugins = this.jm.constructor.enhancedPluginList.filter(d => d.preload);\r\n logger.info('Initializing ' + preloadPlugins.length + ' preload plugins');\r\n preloadPlugins.forEach(descriptor => {\r\n this._initPlugin(descriptor);\r\n });\r\n }\r\n\r\n /**\r\n * Initialize normal plugins (after core modules)\r\n */\r\n initNormalPlugins() {\r\n const normalPlugins = this.jm.constructor.enhancedPluginList.filter(d => !d.preload);\r\n logger.info('Initializing ' + normalPlugins.length + ' normal plugins');\r\n normalPlugins.forEach(descriptor => {\r\n this._initPlugin(descriptor);\r\n });\r\n }\r\n\r\n /**\r\n * Internal method: Initialize a single plugin\r\n * @param {PluginDescriptor} descriptor\r\n * @private\r\n */\r\n _initPlugin(descriptor) {\r\n try {\r\n const { PluginClass, pluginOpt } = descriptor;\r\n\r\n // Check instanceName\r\n if (!PluginClass.instanceName) {\r\n throw new Error('Plugin ' + PluginClass.name + ' must define static instanceName');\r\n }\r\n\r\n // Check naming conflict\r\n if (this.plugins.has(PluginClass.instanceName)) {\r\n logger.warn(\r\n 'Plugin ' + PluginClass.instanceName + ' already exists, will be replaced'\r\n );\r\n }\r\n\r\n // Instantiate plugin\r\n const instance = new PluginClass({\r\n jm: this.jm,\r\n pluginOpt: pluginOpt || {},\r\n });\r\n\r\n // Save instance\r\n this.plugins.set(PluginClass.instanceName, instance);\r\n this.jm[PluginClass.instanceName] = instance;\r\n descriptor.instance = instance;\r\n\r\n logger.info('Enhanced plugin ' + PluginClass.instanceName + ' initialized');\r\n } catch (error) {\r\n logger.error('Failed to initialize plugin ' + descriptor.PluginClass.name + ':', error);\r\n }\r\n }\r\n\r\n /**\r\n * Remove a plugin\r\n * @param {typeof EnhancedPlugin} PluginClass\r\n */\r\n removePlugin(PluginClass) {\r\n const instanceName = PluginClass.instanceName;\r\n if (!instanceName) {\r\n return;\r\n }\r\n\r\n const instance = this.plugins.get(instanceName);\r\n if (!instance) {\r\n return;\r\n }\r\n\r\n try {\r\n // Call lifecycle hook\r\n if (typeof instance.beforePluginRemove === 'function') {\r\n instance.beforePluginRemove();\r\n }\r\n\r\n // Remove from Map\r\n this.plugins.delete(instanceName);\r\n\r\n // Remove from jsMind instance\r\n delete this.jm[instanceName];\r\n\r\n // Remove from plugin list\r\n const list = this.jm.constructor.enhancedPluginList;\r\n const index = list.findIndex(d => d.PluginClass === PluginClass);\r\n if (index !== -1) {\r\n list.splice(index, 1);\r\n }\r\n\r\n logger.info('Enhanced plugin ' + instanceName + ' removed');\r\n } catch (error) {\r\n logger.error('Failed to remove plugin ' + instanceName + ':', error);\r\n }\r\n }\r\n\r\n /**\r\n * Destroy all plugins\r\n */\r\n destroyAllPlugins() {\r\n this.plugins.forEach((instance, instanceName) => {\r\n try {\r\n // Call lifecycle hook\r\n if (typeof instance.beforePluginDestroy === 'function') {\r\n instance.beforePluginDestroy();\r\n }\r\n } catch (error) {\r\n logger.error('Failed to destroy plugin ' + instanceName + ':', error);\r\n }\r\n });\r\n\r\n this.plugins.clear();\r\n }\r\n\r\n /**\r\n * Get plugin instance by name\r\n * @param {string} instanceName\r\n * @returns {EnhancedPlugin | undefined}\r\n */\r\n getPlugin(instanceName) {\r\n return this.plugins.get(instanceName);\r\n }\r\n}\r\n\r\n/**\r\n * Enhanced Plugin Base Class\r\n * Provides standard interface for enhanced plugins\r\n */\r\nexport class EnhancedPlugin {\r\n /**\r\n * Plugin instance name (must be defined by subclass)\r\n * @type {string}\r\n */\r\n static instanceName = '';\r\n\r\n /**\r\n * Whether to initialize before core modules\r\n * @type {boolean}\r\n */\r\n static preload = false;\r\n\r\n /**\r\n * @param {{ jm: import('./jsmind.js').default, pluginOpt: object }} params\r\n */\r\n constructor({ jm, pluginOpt }) {\r\n this.jm = jm;\r\n this.options = pluginOpt || {};\r\n }\r\n\r\n /**\r\n * Called before plugin is removed\r\n * Override this method to clean up resources\r\n */\r\n beforePluginRemove() {\r\n // Default implementation: do nothing\r\n }\r\n\r\n /**\r\n * Called before jsMind instance is destroyed\r\n * Override this method to clean up resources\r\n */\r\n beforePluginDestroy() {\r\n // Default implementation: call beforePluginRemove\r\n this.beforePluginRemove();\r\n }\r\n}\r\n\r\n/**\r\n * Plugin descriptor\r\n * @typedef {object} PluginDescriptor\r\n * @property {typeof EnhancedPlugin} PluginClass - Plugin class\r\n * @property {string} instanceName - Plugin instance name\r\n * @property {boolean} preload - Whether to preload\r\n * @property {object} pluginOpt - Plugin options\r\n * @property {EnhancedPlugin | null} instance - Plugin instance (after initialization)\r\n */\r\n","/**\r\n * @license BSD\r\n * @copyright 2014-2025 UmbraCi\r\n *\r\n * Project Home:\r\n * https://github.com/UmbraCi/jsmind/\r\n */\r\n\r\nimport {EnhancedPlugin} from '../jsmind.enhanced-plugin.js';\r\nimport {EventType, logger} from '../jsmind.common.js';\r\n\r\n/**\r\n * Default options for multi-select plugin.\r\n * @typedef {Object} MultiSelectOptions\r\n * @property {boolean} [enable_multi_select=true] - Enable multi-select feature\r\n * @property {boolean} [include_descendants=true] - Include descendants in subtree selection\r\n * @property {boolean} [shift_simple_mode=false] - Shift mode: false=simple subtree, true=advanced range\r\n * @property {((node:import('../jsmind.node.js').Node)=>boolean)|null} [filter=null] - Node filter function\r\n */\r\nconst DEFAULT_OPTIONS = {\r\n enable_multi_select: false, // default off; can be enabled at runtime\r\n include_descendants: true,\r\n shift_simple_mode: false,\r\n allow_ctrl: true,\r\n allow_shift: true,\r\n filter: null,\r\n};\r\n\r\n/**\r\n * Multi-Select Core - Handles all multi-select logic\r\n */\r\nclass MultiSelectCore {\r\n /**\r\n * @param {import('../jsmind.js').default} jm - jsMind instance\r\n * @param {MultiSelectOptions} options - Plugin options\r\n */\r\n constructor(jm, options) {\r\n this.jm = jm;\r\n this.options = options;\r\n\r\n // Initialize selection state\r\n this._ensure_selection_state();\r\n\r\n this._selection_mode = null; // 'single' | 'multi' | null\r\n this._last_selected_node = null;\r\n }\r\n\r\n /**\r\n * Ensure selection state is initialized\r\n * @private\r\n */\r\n _ensure_selection_state() {\r\n if (!this.jm.mind) {\r\n this.jm.mind = {};\r\n }\r\n if (!this.jm.mind.selected_nodes) {\r\n this.jm.mind.selected_nodes = new Set();\r\n }\r\n\r\n if (!this.jm.view) {\r\n this.jm.view = {};\r\n }\r\n if (!this.jm.view.multi_selected_nodes) {\r\n this.jm.view.multi_selected_nodes = new Map();\r\n }\r\n }\r\n\r\n /**\r\n * Get all selected nodes\r\n * @returns {string[]} Array of selected node IDs\r\n */\r\n get_selected_nodes() {\r\n this._ensure_selection_state();\r\n if (!this.jm.mind || !this.jm.mind.selected_nodes) {\r\n return [];\r\n }\r\n return Array.from(this.jm.mind.selected_nodes).map(node => node.id);\r\n }\r\n\r\n /**\r\n * Check if a node is selected\r\n * @param {string|import('../jsmind.node.js').Node} node - Node ID or Node instance\r\n * @returns {boolean}\r\n */\r\n is_node_selected(node) {\r\n const nodeObj = this._resolve_node(node);\r\n if (!nodeObj || !this.jm.mind) {\r\n return false;\r\n }\r\n this._ensure_selection_state();\r\n return this.jm.mind.selected_nodes.has(nodeObj);\r\n }\r\n\r\n /**\r\n * Select a single node (clears other selections)\r\n * @param {string|import('../jsmind.node.js').Node} node - Node ID or Node instance\r\n */\r\n select_node(node) {\r\n const nodeObj = this._resolve_node(node);\r\n if (!nodeObj) {\r\n logger.error('[multiSelect] node not found: ' + node);\r\n return;\r\n }\r\n\r\n this._ensure_selection_state();\r\n\r\n // Clear selection state first\r\n this._clear_selection_state();\r\n\r\n // Ensure again after clear, in case mind was reset\r\n this._ensure_selection_state();\r\n\r\n if (!this.jm.mind || !this.jm.mind.selected_nodes) {\r\n logger.error('[multiSelect] jm.mind or selected_nodes is not available');\r\n return;\r\n }\r\n\r\n // Set selection state\r\n this.jm.mind.selected = nodeObj;\r\n this._last_selected_node = nodeObj;\r\n\r\n // Force add node to selection (since we just cleared it)\r\n if (!this.jm.mind.selected_nodes.has(nodeObj)) {\r\n this.jm.mind.selected_nodes.add(nodeObj);\r\n }\r\n\r\n // Mark node as selected in view\r\n this._mark_node_selected(nodeObj);\r\n\r\n this._selection_mode = 'single';\r\n\r\n // Always use nodeObj.id for event data\r\n const nodeIds = [nodeObj.id];\r\n\r\n // Invoke event with proper data structure\r\n this._invoke_select_event({\r\n evt: 'select_node',\r\n data: nodeIds,\r\n node: nodeObj.id,\r\n nodes: nodeIds,\r\n });\r\n }\r\n\r\n /**\r\n * Clear all selections\r\n */\r\n select_clear() {\r\n this._ensure_selection_state();\r\n if (this.jm.mind) {\r\n this.jm.mind.selected = null;\r\n this._last_selected_node = null;\r\n this._clear_selection_state();\r\n }\r\n }\r\n\r\n /**\r\n * Toggle node selection (equivalent to Ctrl/Cmd+Click)\r\n * @param {string|import('../jsmind.node.js').Node} node - Node ID or Node instance\r\n */\r\n toggle_node_selection(node) {\r\n const nodeObj = this._resolve_node(node);\r\n if (!nodeObj || !this.jm.layout.is_visible(nodeObj)) {\r\n return;\r\n }\r\n\r\n this._ensure_selection_state();\r\n if (this.jm.mind.selected_nodes.has(nodeObj)) {\r\n this._deselect_subtree(nodeObj);\r\n } else {\r\n this._selection_mode = 'multi';\r\n const added = this._append_selection([nodeObj]);\r\n if (added.length) {\r\n this.jm.mind.selected = nodeObj;\r\n this._last_selected_node = nodeObj;\r\n this._invoke_select_event({\r\n evt: 'multi_select',\r\n data: [nodeObj.id],\r\n node: nodeObj.id,\r\n nodes: [nodeObj.id],\r\n });\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Toggle subtree selection\r\n * @param {string|import('../jsmind.node.js').Node} node - Node ID or Node instance\r\n */\r\n toggle_subtree_selection(node, opts) {\r\n const nodeObj = this._resolve_node(node);\r\n if (!nodeObj) {\r\n logger.error('[multiSelect] node not found: ' + node);\r\n return;\r\n }\r\n\r\n if (!this.jm.layout.is_visible(nodeObj)) {\r\n return;\r\n }\r\n\r\n const includeDesc = (opts && typeof opts.include_descendants !== 'undefined')\r\n ? !!opts.include_descendants\r\n : this.options.include_descendants !== false; // default true\r\n\r\n this._ensure_selection_state();\r\n // If node is not selected or not in multi mode, select subtree\r\n if (!this.jm.mind.selected_nodes.has(nodeObj) || this._selection_mode !== 'multi') {\r\n this._selection_mode = 'multi';\r\n let nodes = this._collect_subtree_nodes(nodeObj, {\r\n includeChildren: includeDesc,\r\n respectFilter: true,\r\n skipRootFilter: true,\r\n });\r\n if (!nodes.length) {\r\n nodes = [nodeObj];\r\n }\r\n\r\n const added = this._append_selection(nodes, {focusNode: nodeObj});\r\n this._ensure_selection_state();\r\n const ancestors = nodeObj.parent && !this.jm.mind.selected_nodes.has(nodeObj.parent)\r\n ? this._ensure_ancestor_selection([nodeObj], nodeObj, {\r\n requireAncestorChainSelected: true,\r\n })\r\n : [];\r\n const allAdded = added.concat(ancestors);\r\n\r\n if (allAdded.length) {\r\n this.jm.mind.selected = nodeObj;\r\n const nodeIds = allAdded.map(n => n.id);\r\n this._invoke_select_event({\r\n evt: 'multi_select',\r\n data: nodeIds,\r\n node: nodeObj.id,\r\n nodes: nodeIds,\r\n });\r\n }\r\n } else {\r\n // Deselect subtree\r\n let nodes = this._collect_subtree_nodes(nodeObj, {\r\n includeChildren: true,\r\n respectFilter: false,\r\n skipRootFilter: false,\r\n });\r\n if (!nodes.length) {\r\n nodes = [nodeObj];\r\n }\r\n\r\n const removed = this._remove_selection(nodes);\r\n if (removed.length) {\r\n if (this.jm.mind.selected && this.jm.mind.selected.id === nodeObj.id) {\r\n this.jm.mind.selected = null;\r\n }\r\n this._selection_mode = this._derive_selection_mode();\r\n const nodeIds = removed.map(n => n.id);\r\n this._invoke_select_event({\r\n evt: 'multi_deselect',\r\n data: nodeIds,\r\n node: nodeObj.id,\r\n nodes: nodeIds,\r\n });\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get current selection mode\r\n * @returns {'single'|'multi'|null}\r\n */\r\n get_selection_mode() {\r\n return this._selection_mode;\r\n }\r\n\r\n /**\r\n * Handle node click event\r\n * @param {Object} payload - Click event payload\r\n * @param {MouseEvent} payload.e - Mouse event\r\n * @param {string} payload.node - Node ID\r\n * @param {HTMLElement} payload.element - Node element\r\n * @param {string} payload.evt - Event type\r\n */\r\n _handle_node_click(payload) {\r\n const {e, node, element} = payload;\r\n if (!node || !element) {\r\n return;\r\n }\r\n\r\n // Ensure selection state is initialized\r\n this._ensure_selection_state();\r\n\r\n const mode = this._get_multi_select_mode(e);\r\n\r\n if (mode === 'ctrl') {\r\n // Ctrl/Cmd + Click: Toggle node selection\r\n this.toggle_node_selection(node);\r\n } else if (mode === 'shift') {\r\n // Shift + Click: Range selection\r\n const nodeObj = this.jm.get_node(node);\r\n if (!nodeObj) {\r\n logger.warn('[multiSelect] Node not found for shift selection: ' + node);\r\n return;\r\n }\r\n\r\n if (this.options.shift_simple_mode) {\r\n // Advanced range mode\r\n if (this.is_node_selected(node)) {\r\n this._deselect_subtree(nodeObj);\r\n } else {\r\n this._range_select_nodes(node);\r\n }\r\n } else {\r\n // Simple subtree mode\r\n if (this.is_node_selected(node)) {\r\n this._deselect_subtree(nodeObj);\r\n } else {\r\n const includeChildren = this.options.include_descendants !== false;\r\n let nodes = this._collect_subtree_nodes(nodeObj, {\r\n includeChildren: includeChildren,\r\n respectFilter: true,\r\n skipRootFilter: true,\r\n });\r\n if (!nodes.length) {\r\n nodes = [nodeObj];\r\n }\r\n\r\n const added = this._append_selection(nodes, {focusNode: nodeObj});\r\n if (added.length) {\r\n this.jm.mind.selected = nodeObj;\r\n this._last_selected_node = nodeObj;\r\n this._selection_mode = this._derive_selection_mode();\r\n const nodeIds = added.map(n => n.id);\r\n this._invoke_select_event({\r\n evt: 'multi_select',\r\n data: nodeIds,\r\n node: nodeObj.id,\r\n nodes: nodeIds,\r\n });\r\n } else {\r\n // Fallback: at least select the clicked node\r\n this._ensure_selection_state();\r\n if (!this.jm.mind.selected_nodes.has(nodeObj)) {\r\n this.jm.mind.selected_nodes.add(nodeObj);\r\n this._mark_node_selected(nodeObj);\r\n }\r\n this.jm.mind.selected = nodeObj;\r\n this._last_selected_node = nodeObj;\r\n this._selection_mode = this._derive_selection_mode();\r\n this._invoke_select_event({\r\n evt: 'multi_select',\r\n data: [nodeObj.id],\r\n node: nodeObj.id,\r\n nodes: [nodeObj.id],\r\n });\r\n }\r\n }\r\n }\r\n } else {\r\n // Normal click - single select\r\n this.select_node(node);\r\n }\r\n }\r\n\r\n /**\r\n * Handle node removed event\r\n * @param {import('../jsmind.node.js').Node} node - Removed node\r\n */\r\n _handle_node_removed(node) {\r\n this._ensure_selection_state();\r\n if (this.jm.mind.selected_nodes.has(node)) {\r\n this.jm.mind.selected_nodes.delete(node);\r\n }\r\n if (this._last_selected_node && this._last_selected_node.id === node.id) {\r\n this._last_selected_node = null;\r\n }\r\n if (this.jm.view.multi_selected_nodes && this.jm.view.multi_selected_nodes.has(node.id)) {\r\n this._unmark_node_selected(node);\r\n }\r\n }\r\n\r\n /**\r\n * Get multi-select mode from event\r\n * @param {MouseEvent} e - Mouse event\r\n * @returns {'ctrl'|'shift'|null}\r\n */\r\n _get_multi_select_mode(e) {\r\n if (!e) {\r\n return null;\r\n }\r\n // Check shift key first (higher priority)\r\n if (this.options.allow_shift !== false && e.shiftKey === true) {\r\n return 'shift';\r\n }\r\n // Check ctrl/cmd key\r\n if (this.options.allow_ctrl !== false && (e.ctrlKey === true || e.metaKey === true)) {\r\n return 'ctrl';\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Append nodes to selection\r\n * @param {import('../jsmind.node.js').Node[]} nodes - Nodes to select\r\n * @param {Object} [options] - Options\r\n * @param {import('../jsmind.node.js').Node} [options.focusNode] - Focus node\r\n * @returns {import('../jsmind.node.js').Node[]} Actually added nodes\r\n */\r\n _append_selection(nodes, options) {\r\n if (!nodes || !nodes.length) {\r\n return [];\r\n }\r\n\r\n this._ensure_selection_state();\r\n if (!this.jm.mind || !this.jm.mind.selected_nodes) {\r\n logger.warn('[multiSelect] Cannot append selection: selected_nodes not available');\r\n return [];\r\n }\r\n\r\n const added = [];\r\n for (let i = 0; i < nodes.length; i++) {\r\n const node = nodes[i];\r\n if (!this.jm.mind.selected_nodes.has(node)) {\r\n this.jm.mind.selected_nodes.add(node);\r\n added.push(node);\r\n }\r\n }\r\n\r\n if (added.length) {\r\n const focusNode = options && options.focusNode ? options.focusNode : null;\r\n this._mark_nodes_selected(added, focusNode || added[added.length - 1]);\r\n }\r\n\r\n return added;\r\n }\r\n\r\n /**\r\n * Remove nodes from selection\r\n * @param {import('../jsmind.node.js').Node[]} nodes - Nodes to deselect\r\n * @returns {import('../jsmind.node.js').Node[]} Actually removed nodes\r\n */\r\n _remove_selection(nodes) {\r\n if (!nodes || !nodes.length) {\r\n return [];\r\n }\r\n\r\n this._ensure_selection_state();\r\n const removed = [];\r\n for (let i = 0; i < nodes.length; i++) {\r\n const node = nodes[i];\r\n if (this.jm.mind.selected_nodes.has(node)) {\r\n this.jm.mind.selected_nodes.delete(node);\r\n removed.push(node);\r\n }\r\n }\r\n\r\n if (removed.length) {\r\n this._unmark_nodes_selected(removed);\r\n }\r\n\r\n return removed;\r\n }\r\n\r\n /**\r\n * Deselect subtree\r\n * @param {import('../jsmind.node.js').Node} node - Root node of subtree\r\n */\r\n _deselect_subtree(node) {\r\n let nodes = this._collect_subtree_nodes(node, {\r\n includeChildren: true,\r\n respectFilter: false,\r\n skipRootFilter: false,\r\n });\r\n if (!nodes.length) {\r\n nodes = [node];\r\n }\r\n\r\n const removed = this._remove_selection(nodes);\r\n if (removed.length) {\r\n if (this.jm.mind.selected && this.jm.mind.selected.id === node.id) {\r\n this.jm.mind.selected = null;\r\n }\r\n this._selection_mode = this._derive_selection_mode();\r\n const nodeIds = removed.map(n => n.id);\r\n this._invoke_select_event({\r\n evt: 'multi_deselect',\r\n data: nodeIds,\r\n node: node.id,\r\n nodes: nodeIds,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Clear selection state\r\n * @returns {import('../jsmind.node.js').Node[]} Removed nodes\r\n */\r\n _clear_selection_state() {\r\n this._ensure_selection_state();\r\n this._selection_mode = null;\r\n\r\n // Double check after ensure\r\n if (!this.jm.mind || !this.jm.mind.selected_nodes) {\r\n this._ensure_selection_state();\r\n }\r\n\r\n if (!this.jm.mind || !this.jm.mind.selected_nodes || this.jm.mind.selected_nodes.size === 0) {\r\n this._clear_all_selected_nodes_view();\r\n return [];\r\n }\r\n\r\n const nodes = Array.from(this.jm.mind.selected_nodes);\r\n this.jm.mind.selected_nodes.clear();\r\n this._unmark_nodes_selected(nodes);\r\n return nodes;\r\n }\r\n\r\n /**\r\n * Collect subtree nodes\r\n * @param {import('../jsmind.node.js').Node} node - Root node\r\n * @param {Object} options - Options\r\n * @param {boolean} [options.includeChildren=true] - Include children\r\n * @param {boolean} [options.respectFilter=false] - Respect filter\r\n * @param {boolean} [options.skipRootFilter=false] - Skip root filter\r\n * @returns {import('../jsmind.node.js').Node[]}\r\n */\r\n _collect_subtree_nodes(node, options) {\r\n const opts = options || {};\r\n const includeChildren = opts.includeChildren !== false;\r\n const respectFilter = !!opts.respectFilter;\r\n const skipRootFilter = !!opts.skipRootFilter;\r\n\r\n const filter = respectFilter ? this._get_selection_filter() : null;\r\n const result = [];\r\n\r\n const collect = (n, isRoot) => {\r\n let shouldInclude = true;\r\n if (filter && (!skipRootFilter || !isRoot)) {\r\n shouldInclude = filter(n) !== false;\r\n }\r\n\r\n if (shouldInclude) {\r\n result.push(n);\r\n }\r\n\r\n if (includeChildren && n.children) {\r\n for (let i = 0; i < n.children.length; i++) {\r\n collect(n.children[i], false);\r\n }\r\n }\r\n };\r\n\r\n collect(node, true);\r\n return result;\r\n }\r\n\r\n /**\r\n * Ensure ancestor selection\r\n * @param {import('../jsmind.node.js').Node[]} nodes - Nodes\r\n * @param {import('../jsmind.node.js').Node} focusNode - Focus node\r\n * @param {Object} options - Options\r\n * @returns {import('../jsmind.node.js').Node[]}\r\n */\r\n _ensure_ancestor_selection(nodes, focusNode, options) {\r\n if (!nodes || !nodes.length) {\r\n return [];\r\n }\r\n\r\n this._ensure_selection_state();\r\n const requireAncestorChainSelected = !!(options && options.requireAncestorChainSelected);\r\n const added = [];\r\n const addedMap = Object.create(null);\r\n\r\n for (let i = 0; i < nodes.length; i++) {\r\n let parent = nodes[i].parent;\r\n if (!parent) {\r\n continue;\r\n }\r\n\r\n const path = [];\r\n let shouldAdd = !requireAncestorChainSelected;\r\n\r\n // Check if any ancestor is already selected\r\n while (parent) {\r\n if (this.jm.mind.selected_nodes.has(parent)) {\r\n shouldAdd = true;\r\n break;\r\n }\r\n path.push(parent);\r\n parent = parent.parent;\r\n }\r\n\r\n if (shouldAdd) {\r\n for (let j = 0; j < path.length; j++) {\r\n const p = path[j];\r\n if (!this.jm.mind.selected_nodes.has(p) && !addedMap[p.id]) {\r\n added.push(p);\r\n addedMap[p.id] = true;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!added.length) {\r\n return [];\r\n }\r\n\r\n const focus = focusNode || nodes[nodes.length - 1];\r\n return this._append_selection(added, {focusNode: focus});\r\n }\r\n\r\n /**\r\n * Get selection filter\r\n * @returns {Function|null}\r\n */\r\n _get_selection_filter() {\r\n if (this.options && typeof this.options.filter === 'function') {\r\n return this.options.filter;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Range select nodes (advanced mode)\r\n * @param {string} nodeId - Target node ID\r\n */\r\n _range_select_nodes(nodeId) {\r\n const nodeObj = this._resolve_node(nodeId);\r\n if (!nodeObj || !this.jm.layout.is_visible(nodeObj)) {\r\n return;\r\n }\r\n\r\n this._ensure_selection_state();\r\n // If no selection, select subtree\r\n if (this.jm.mind.selected_nodes.size === 0) {\r\n let nodes = this._collect_subtree_nodes(nodeObj, {\r\n includeChildren: true,\r\n respectFilter: true,\r\n skipRootFilter: true,\r\n });\r\n if (!nodes.length) {\r\n nodes = [nodeObj];\r\n }\r\n\r\n const added = this._append_selection(nodes);\r\n if (added.length) {\r\n this.jm.mind.selected = nodeObj;\r\n this._last_selected_node = nodeObj;\r\n this._selection_mode = this._derive_selection_mode();\r\n const nodeIds = added.map(n => n.id);\r\n this._invoke_select_event({\r\n evt: 'multi_select',\r\n data: nodeIds,\r\n node: nodeObj.id,\r\n nodes: nodeIds,\r\n });\r\n }\r\n return;\r\n }\r\n\r\n // Find anchor node\r\n this._ensure_selection_state();\r\n const selectedArray = Array.from(this.jm.mind.selected_nodes);\r\n const anchor =\r\n this._last_selected_node && this.jm.mind.selected_nodes.has(this._last_selected_node)\r\n ? this._last_selected_node\r\n : selectedArray[0];\r\n\r\n // Find nodes between anchor and target\r\n const nodesBetween = this._find_nodes_between(anchor, nodeObj);\r\n if (!nodesBetween.length) {\r\n const nodes = [nodeObj];\r\n const added = this._append_selection(nodes);\r\n if (added.length) {\r\n this.jm.mind.selected = nodeObj;\r\n this._last_selected_node = nodeObj;\r\n this._selection_mode = this._derive_selection_mode();\r\n const nodeIds = added.map(n => n.id);\r\n this._invoke_select_event({\r\n evt: 'multi_select',\r\n data: nodeIds,\r\n node: nodeObj.id,\r\n nodes: nodeIds,\r\n });\r\n }\r\n return;\r\n }\r\n\r\n // Select all nodes between anchor and target\r\n this._ensure_selection_state();\r\n const toAdd = nodesBetween.filter(n => !this.jm.mind.selected_nodes.has(n));\r\n const added = this._append_selection(toAdd);\r\n if (added.length) {\r\n this.jm.mind.selected = nodeObj;\r\n this._last_selected_node = nodeObj;\r\n this._selection_mode = this._derive_selection_mode();\r\n const nodeIds = added.map(n => n.id);\r\n this._invoke_select_event({\r\n evt: 'multi_select',\r\n data: nodeIds,\r\n node: nodeObj.id,\r\n nodes: nodeIds,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Find nodes between two nodes\r\n * @param {import('../jsmind.node.js').Node} from - Start node\r\n * @param {import('../jsmind.node.js').Node} to - End node\r\n * @returns {import('../jsmind.node.js').Node[]}\r\n */\r\n _find_nodes_between(from, to) {\r\n if (!from || !to) {\r\n return [];\r\n }\r\n\r\n // Collect all visible nodes in order\r\n const allNodes = [];\r\n const collect = node => {\r\n if (this.jm.layout.is_visible(node)) {\r\n allNodes.push(node);\r\n }\r\n if (node.children) {\r\n for (let i = 0; i < node.children.length; i++) {\r\n collect(node.children[i]);\r\n }\r\n }\r\n };\r\n\r\n if (this.jm.mind && this.jm.mind.root) {\r\n collect(this.jm.mind.root);\r\n }\r\n\r\n // Find indices\r\n let fromIndex = -1;\r\n let toIndex = -1;\r\n for (let i = 0; i < allNodes.length; i++) {\r\n if (allNodes[i].id === from.id) {\r\n fromIndex = i;\r\n }\r\n if (allNodes[i].id === to.id) {\r\n toIndex = i;\r\n }\r\n }\r\n\r\n if (fromIndex === -1 || toIndex === -1) {\r\n return [];\r\n }\r\n\r\n const start = Math.min(fromIndex, toIndex);\r\n const end = Math.max(fromIndex, toIndex);\r\n return allNodes.slice(start, end + 1);\r\n }\r\n\r\n /**\r\n * Derive selection mode from current state\r\n * @returns {'single'|'multi'|null}\r\n */\r\n _derive_selection_mode() {\r\n this._ensure_selection_state();\r\n const count = this.jm.mind.selected_nodes.size;\r\n if (count === 0) {\r\n return null;\r\n }\r\n return count > 1 ? 'multi' : 'single';\r\n }\r\n\r\n /**\r\n * Mark nodes as selected in view\r\n * @param {import('../jsmind.node.js').Node[]} nodes - Nodes to mark\r\n * @param {import('../jsmind.node.js').Node} focusNode - Focus node\r\n */\r\n _mark_nodes_selected(nodes, focusNode) {\r\n if (nodes && nodes.length) {\r\n for (let i = 0; i < nodes.length; i++) {\r\n this._mark_node_selected(nodes[i]);\r\n }\r\n this.jm.view.selected_node = focusNode || nodes[nodes.length - 1];\r\n }\r\n }\r\n\r\n /**\r\n * Mark a node as selected in view\r\n * @param {import('../jsmind.node.js').Node} node - Node to mark\r\n */\r\n _mark_node_selected(node) {\r\n if (!node || this.jm.view.multi_selected_nodes.has(node.id)) {\r\n return;\r\n }\r\n\r\n const element = node._data && node._data.view && node._data.view.element;\r\n if (element) {\r\n if (element.classList) {\r\n element.classList.add('selected');\r\n } else if (!/(\\s|^)selected(\\s|$)/.test(element.className)) {\r\n element.className += ' selected';\r\n }\r\n this.jm.view.multi_selected_nodes.set(node.id, node);\r\n }\r\n }\r\n\r\n /**\r\n * Unmark nodes as selected in view\r\n * @param {import('../jsmind.node.js').Node[]} nodes - Nodes to unmark\r\n */\r\n _unmark_nodes_selected(nodes) {\r\n if (nodes && nodes.length) {\r\n for (let i = 0; i < nodes.length; i++) {\r\n this._unmark_node_selected(nodes[i]);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Unmark a node as selected in view\r\n * @param {import('../jsmind.node.js').Node} node - Node to unmark\r\n */\r\n _unmark_node_selected(node) {\r\n if (node) {\r\n if (this.jm.view.multi_selected_nodes.has(node.id)) {\r\n const element = node._data && node._data.view && node._data.view.element;\r\n if (element) {\r\n if (element.classList) {\r\n element.classList.remove('selected');\r\n } else {\r\n element.className = element.className.replace(/\\s*selected\\b/i, '');\r\n }\r\n }\r\n this.jm.view.multi_selected_nodes.delete(node.id);\r\n }\r\n if (this.jm.view.selected_node && this.jm.view.selected_node.id === node.id) {\r\n this.jm.view.selected_node = null;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Clear all selected nodes view\r\n */\r\n _clear_all_selected_nodes_view() {\r\n this._ensure_selection_state();\r\n if (!this.jm.view.multi_selected_nodes || !this.jm.view.multi_selected_nodes.size) {\r\n if (this.jm.view) {\r\n this.jm.view.selected_node = null;\r\n }\r\n return;\r\n }\r\n\r\n const nodes = Array.from(this.jm.view.multi_selected_nodes.values());\r\n for (let i = 0; i < nodes.length; i++) {\r\n this._unmark_node_selected(nodes[i]);\r\n }\r\n if (this.jm.view) {\r\n this.jm.view.selected_node = null;\r\n }\r\n }\r\n\r\n /**\r\n * Invoke select event\r\n * @param {Object} data - Event data\r\n */\r\n _invoke_select_event(data) {\r\n try {\r\n // Ensure nodes is always an array\r\n if (!data.nodes) {\r\n data.nodes = data.data || [];\r\n }\r\n // Ensure data is always an array\r\n if (!data.data) {\r\n data.data = data.nodes || [];\r\n }\r\n this.jm.invoke_event_handle(EventType.select, data);\r\n } catch (e) {\r\n logger.warn('[multiSelect] failed to invoke select event', e);\r\n }\r\n }\r\n\r\n /**\r\n * Resolve node from ID or Node instance\r\n * @param {string|import('../jsmind.node.js').Node} node - Node ID or Node instance\r\n * @returns {import('../jsmind.node.js').Node|null}\r\n */\r\n _resolve_node(node) {\r\n if (!node) {\r\n return null;\r\n }\r\n if (typeof node === 'string') {\r\n return this.jm.get_node(node);\r\n }\r\n return node;\r\n }\r\n}\r\n\r\n/**\r\n * Multi-Select Plugin - Enhanced plugin for jsMind\r\n */\r\nexport class MultiSelectPlugin extends EnhancedPlugin {\r\n static instanceName = 'multiSelectPlugin';\r\n static preload = false;\r\n\r\n /**\r\n * @param {{ jm: import('../jsmind.js').default, pluginOpt: object }} params\r\n */\r\n constructor({jm, pluginOpt}) {\r\n super({jm, pluginOpt});\r\n\r\n const options = Object.assign({}, DEFAULT_OPTIONS, pluginOpt || {});\r\n this.options = options;\r\n this._mounted = false;\r\n this._core = null;\r\n this._listener = null;\r\n this._enabled = !!options.enable_multi_select; // runtime gate\r\n\r\n this._initCore();\r\n }\r\n\r\n /**\r\n * Initialize core and mount API\r\n */\r\n _initCore() {\r\n const jm = this.jm;\r\n const options = this.options;\r\n const plugin = this; // Save reference for closure\r\n\r\n // Create core instance\r\n this._core = new MultiSelectCore(jm, options);\r\n\r\n // Mount API\r\n this._mountAPI();\r\n\r\n // Setup event listener\r\n this._listener = (type, data) => {\r\n try {\r\n if (type === EventType.show) {\r\n plugin._core.select_clear();\r\n }\r\n } catch (e) {\r\n logger.warn('[multiSelect] listener error', e);\r\n }\r\n };\r\n\r\n jm.add_event_listener(this._listener);\r\n\r\n // Patch core selection APIs to route through plugin to avoid duplicate events\r\n this._original_select_node = jm.select_node.bind(jm);\r\n this._original_select_clear = jm.select_clear.bind(jm);\r\n jm.select_node = (node) => {\r\n // Route based on runtime gate\r\n if (plugin._enabled) return plugin._core.select_node(node);\r\n return plugin._original_select_node(node);\r\n };\r\n jm.select_clear = () => {\r\n if (plugin._enabled) return plugin._core.select_clear();\r\n return plugin._original_select_clear();\r\n };\r\n\r\n // Always bind our click handler once; gate controls interception\r\n const $ = jm.constructor.$;\r\n this._domClickHandler = function (e) {\r\n // Gate: only intercept when enabled\r\n if (!plugin._enabled) {\r\n return;\r\n }\r\n const element = e.target || e.currentTarget;\r\n const node_id = jm.view.get_binded_nodeid(element);\r\n\r\n // Only intercept jmnode, let expander clicks pass through\r\n if (node_id && jm.view.is_node(element)) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n if (e.stopImmediatePropagation) e.stopImmediatePropagation();\r\n\r\n plugin._core._handle_node_click({\r\n e,\r\n node: node_id,\r\n element,\r\n evt: 'click',\r\n });\r\n } else if (!node_id) {\r\n // Blank click without modifiers clears selection\r\n if (!e.ctrlKey && !e.metaKey && !e.shiftKey) {\r\n plugin._core.select_clear();\r\n }\r\n }\r\n };\r\n\r\n if (jm.view && jm.view.e_nodes) {\r\n $.on(jm.view.e_nodes, 'click', this._domClickHandler);\r\n logger.info('[multiSelect] plugin click handler attached');\r\n } else {\r\n logger.warn('[multiSelect] nodes container not ready; DOM handler not attached');\r\n }\r\n\r\n // Respect initial enabled state: toggle core default handler\r\n if (this._enabled && typeof jm.disable_event_handle === 'function') {\r\n jm.disable_event_handle('mousedown');\r\n }\r\n\r\n logger.info('[multiSelect] API mounted and event listener attached.');\r\n }\r\n\r\n /**\r\n * Mount API to jsMind instance\r\n */\r\n _mountAPI() {\r\n if (this._mounted) {\r\n return;\r\n }\r\n\r\n const jm = this.jm;\r\n const plugin = this; // Save reference for closure\r\n\r\n const api = {\r\n get_selected_nodes: () => {\r\n if (!plugin._core) {\r\n logger.warn('[multiSelect] Core not initialized');\r\n return [];\r\n }\r\n return plugin._core.get_selected_nodes();\r\n },\r\n is_node_selected: node => {\r\n if (!plugin._core) {\r\n return false;\r\n }\r\n return plugin._core.is_node_selected(node);\r\n },\r\n select_node: node => {\r\n if (!plugin._core) {\r\n logger.warn('[multiSelect] Core not initialized');\r\n return;\r\n }\r\n plugin._core.select_node(node);\r\n },\r\n select_clear: () => {\r\n if (!plugin._core) {\r\n return;\r\n }\r\n plugin._core.select_clear();\r\n },\r\n toggle_node_selection: node => {\r\n if (!plugin._core) {\r\n logger.warn('[multiSelect] Core not initialized');\r\n return;\r\n }\r\n plugin._core.toggle_node_selection(node);\r\n },\r\n toggle_subtree_selection: node => {\r\n if (!plugin._core) {\r\n logger.warn('[multiSelect] Core not initialized');\r\n return;\r\n }\r\n plugin._core.toggle_subtree_selection(node);\r\n },\r\n get_selection_mode: () => {\r\n if (!plugin._core) {\r\n return null;\r\n }\r\n return plugin._core.get_selection_mode();\r\n },\r\n getOptions: () => {\r\n const base = plugin._core ? plugin._core.options : plugin.options;\r\n return Object.assign({}, base, {enable_multi_select: plugin._enabled});\r\n },\r\n enable: () => plugin.setEnabled(true),\r\n disable: () => plugin.setEnabled(false),\r\n setEnabled: (flag) => plugin.setEnabled(flag),\r\n setOptions: (partial) => plugin.setOptions(partial),\r\n };\r\n\r\n Object.defineProperty(jm, 'multiSelect', {\r\n value: api,\r\n configurable: true,\r\n enumerable: false,\r\n writable: false,\r\n });\r\n\r\n this._mounted = true;\r\n logger.info('[multiSelect] API mounted.');\r\n }\r\n\r\n /**\r\n * Cleanup before plugin removal\r\n */\r\n beforePluginRemove() {\r\n try {\r\n // Remove event listener\r\n if (this._listener && this.jm && Array.isArray(this.jm.event_handles)) {\r\n const index = this.jm.event_handles.indexOf(this._listener);\r\n if (index >= 0) {\r\n this.jm.event_handles.splice(index, 1);\r\n }\r\n }\r\n\r\n // Re-enable core mousedown handle\r\n if (typeof this.jm.enable_event_handle === 'function') {\r\n this.jm.enable_event_handle('mousedown');\r\n }\r\n\r\n // Remove DOM click handler if attached\r\n if (this._domClickHandler && this.jm && this.jm.view && this.jm.view.e_nodes) {\r\n // No off() helper; leave it attached (noop when disabled). If needed, we could rebuild view.\r\n this._domClickHandler = null;\r\n }\r\n\r\n // Restore API wrappers\r\n if (this._original_select_node) {\r\n this.jm.select_node = this._original_select_node;\r\n }\r\n if (this._original_select_clear) {\r\n this.jm.select_clear = this._original_select_clear;\r\n }\r\n\r\n // Remove API namespace\r\n if (this.jm && Object.prototype.hasOwnProperty.call(this.jm, 'multiSelect')) {\r\n delete this.jm.multiSelect;\r\n }\r\n\r\n this._mounted = false;\r\n } catch (e) {\r\n logger.error('[multiSelect] remove failed:', e);\r\n }\r\n }\r\n\r\n // Runtime enable/disable and options update\r\n setEnabled(flag) {\r\n const next = !!flag;\r\n if (this._enabled === next) return;\r\n this._enabled = next;\r\n // Keep options in sync for getOptions()\r\n this.options.enable_multi_select = this._enabled;\r\n if (this._enabled) {\r\n if (typeof this.jm.disable_event_handle === 'function') {\r\n this.jm.disable_event_handle('mousedown');\r\n }\r\n } else {\r\n if (typeof this.jm.enable_event_handle === 'function') {\r\n this.jm.enable_event_handle('mousedown');\r\n }\r\n }\r\n }\r\n\r\n setOptions(partial) {\r\n const next = Object.assign({}, partial || {});\r\n // Update plugin-level options\r\n this.options = Object.assign({}, this.options, next);\r\n // Propagate to core so that _get_multi_select_mode sees changes\r\n if (this._core && this._core.options) {\r\n this._core.options = Object.assign({}, this._core.options, next);\r\n }\r\n }\r\n\r\n /**\r\n * Cleanup before plugin destroy\r\n */\r\n beforePluginDestroy() {\r\n logger.debug('[multiSelect] beforePluginDestroy');\r\n this.beforePluginRemove();\r\n }\r\n}\r\n\r\n// Export for compatibility\r\nexport {MultiSelectCore};\r\nexport default MultiSelectPlugin;\r\n\r\n"],"names":["String","prototype","startsWith","p","this","slice","length","EventType","LogLevel","_noop","logger","console","level","log","debug","info","warn","error","log_level","EnhancedPlugin","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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umbraci/jsmind",
3
- "version": "0.10.13",
3
+ "version": "0.10.14",
4
4
  "description": "jsMind is a pure javascript library for mindmap, it base on html5 canvas. jsMind was released under BSD license, you can embed it in any project, if only you observe the license.",
5
5
  "main": "lib/jsmind.js",
6
6
  "module": "es/jsmind.js",
@@ -33,6 +33,10 @@
33
33
  "require": "./lib/jsmind.history.js",
34
34
  "types": "./types/generated/plugins/history/jsmind.history.d.ts"
35
35
  },
36
+ "./multi-select": {
37
+ "import": "./es/jsmind.multi-select.js",
38
+ "require": "./lib/jsmind.multi-select.js"
39
+ },
36
40
  "./style/jsmind.css": "./style/jsmind.css"
37
41
  },
38
42
  "directories": {
@@ -1,8 +0,0 @@
1
- export { default } from './jsmind';
2
- export { Node } from './jsmind.node';
3
- export { Mind } from './jsmind.mind';
4
- export type { JsMindRuntimeOptions as JsMindOptions } from './jsmind.option';
5
- export type { MindMapMeta, NodeTreeData, NodeTreeFormat, NodeArrayItem, NodeArrayFormat, } from './jsmind.format';
6
- export { Direction as direction, EventType as event_type } from './jsmind.common';
7
- export { $ } from './jsmind.dom';
8
- export { util } from './jsmind.util';
@@ -1,68 +0,0 @@
1
- /**
2
- * @license BSD
3
- * @copyright 2014-2025 UmbraCi
4
- *
5
- * Project Home:
6
- * https://github.com/UmbraCi/jsmind/
7
- */
8
- /**
9
- * Library version string.
10
- * @type {string}
11
- */
12
- export const __version__: string;
13
- /**
14
- * Library author.
15
- * @type {string}
16
- */
17
- export const __author__: string;
18
- /**
19
- * Direction constants and parser.
20
- * @typedef {{left:number,center:number,right:number,of:(dir:(string|number))=>number|undefined}} DirectionType
21
- */
22
- /** @type {DirectionType} */
23
- export const Direction: DirectionType;
24
- export type EventType = number;
25
- export namespace EventType {
26
- let show: number;
27
- let resize: number;
28
- let edit: number;
29
- let select: number;
30
- let reset: number;
31
- let history_change: number;
32
- }
33
- export type Key = number;
34
- export namespace Key {
35
- let meta: number;
36
- let ctrl: number;
37
- let alt: number;
38
- let shift: number;
39
- }
40
- export type LogLevel = number;
41
- export namespace LogLevel {
42
- let debug: number;
43
- let info: number;
44
- let warn: number;
45
- let error: number;
46
- let disable: number;
47
- }
48
- /**
49
- * Logger facade with dynamic level.
50
- * @type {{level:(lvl:number)=>void,log:Function,debug:Function,info:Function,warn:Function,error:Function}}
51
- */
52
- export let logger: {
53
- level: (lvl: number) => void;
54
- log: Function;
55
- debug: Function;
56
- info: Function;
57
- warn: Function;
58
- error: Function;
59
- };
60
- /**
61
- * Direction constants and parser.
62
- */
63
- export type DirectionType = {
64
- left: number;
65
- center: number;
66
- right: number;
67
- of: (dir: (string | number)) => number | undefined;
68
- };