@umbraci/jsmind 0.10.17 → 1.0.0-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/README.md +7 -7
- package/dist/jsmind.draggable-node.js +1 -1
- package/dist/jsmind.draggable-node.js.map +1 -1
- package/dist/jsmind.history.js +1 -1
- package/dist/jsmind.history.js.map +1 -1
- package/dist/jsmind.js +1 -1
- package/dist/jsmind.js.map +1 -1
- package/dist/jsmind.multi-select.js.map +1 -1
- package/dist/jsmind.multiline-text.js +1 -1
- package/dist/jsmind.multiline-text.js.map +1 -1
- package/dist/jsmind.screenshot.js +1 -1
- package/dist/jsmind.screenshot.js.map +1 -1
- package/es/jsmind.draggable-node.js +1 -1
- package/es/jsmind.draggable-node.js.map +1 -1
- package/es/jsmind.history.js +1 -1
- package/es/jsmind.history.js.map +1 -1
- package/es/jsmind.js +1 -1
- package/es/jsmind.js.map +1 -1
- package/es/jsmind.multi-select.js.map +1 -1
- package/es/jsmind.multiline-text.js +1 -1
- package/es/jsmind.multiline-text.js.map +1 -1
- package/es/jsmind.screenshot.js +1 -1
- package/es/jsmind.screenshot.js.map +1 -1
- package/lib/jsmind.copy-paste.js +262 -7
- package/lib/jsmind.draggable-node.js +1 -1
- package/lib/jsmind.draggable-node.js.map +1 -1
- package/lib/jsmind.history.js +1 -1
- package/lib/jsmind.history.js.map +1 -1
- package/lib/jsmind.js +1 -1
- package/lib/jsmind.js.map +1 -1
- package/lib/jsmind.multi-select.js.map +1 -1
- package/lib/jsmind.multiline-text.js +1 -1
- package/lib/jsmind.multiline-text.js.map +1 -1
- package/lib/jsmind.screenshot.js +1 -1
- package/lib/jsmind.screenshot.js.map +1 -1
- package/package.json +26 -25
- package/types/generated/jsmind.d.ts +21 -24
- package/types/generated/jsmind.mind.d.ts +7 -0
- package/types/generated/{jsmind.enhanced-plugin.d.ts → jsmind.plugin-system.d.ts} +10 -10
- package/types/generated/jsmind.plugin.d.ts +93 -13
- package/types/generated/jsmind.view_provider.d.ts +1 -1
- package/types/generated/plugins/history/history-diff.d.ts +10 -0
- package/types/generated/plugins/history/jsmind.history.d.ts +2 -2
- package/types/generated/plugins/jsmind.draggable-node.d.ts +13 -3
- package/types/generated/plugins/jsmind.multi-select.d.ts +3 -3
- package/types/generated/plugins/jsmind.multiline-text.d.ts +67 -21
- package/types/generated/plugins/jsmind.screenshot.d.ts +12 -3
- package/types/tsconfig.declaration.json +6 -1
- package/dist/jsmind.copy-paste.js +0 -9
- package/dist/jsmind.copy-paste.js.map +0 -1
- package/es/jsmind.copy-paste.js +0 -9
- package/es/jsmind.copy-paste.js.map +0 -1
- package/types/generated/plugins/jsmind.multiline-text-v2.d.ts +0 -58
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsmind.screenshot.js","sources":["../src/plugins/jsmind.screenshot.js"],"sourcesContent":["/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport jsMind from '@umbraci/jsmind';\nimport domtoimage from 'dom-to-image';\n\nif (!jsMind) {\n throw new Error('jsMind is not defined');\n}\n\nif (!domtoimage) {\n throw new Error('dom-to-image is required');\n}\n\nconst $ = jsMind.$;\n\n/**\n * Default options for screenshot plugin.\n * @typedef {Object} ScreenshotOptions\n * @property {string|null} [filename]\n * @property {{left?:string|Location,right?:string}} [watermark]\n * @property {string} [background]\n */\nconst DEFAULT_OPTIONS = {\n filename: null,\n watermark: {\n left: $.w.location,\n right: 'https://github.com/UmbraCi/jsmind',\n },\n background: 'transparent',\n};\n\n/**\n * Screenshot plugin for jsMind.\n */\nexport class JmScreenshot {\n /**\n * Create screenshot plugin instance.\n * @param {import('../jsmind.js').default} jm - jsMind instance\n * @param {Partial<ScreenshotOptions>} options - Plugin options\n */\n constructor(jm, options) {\n var opts = {};\n jsMind.util.json.merge(opts, DEFAULT_OPTIONS);\n jsMind.util.json.merge(opts, options);\n\n this.version = '0.2.0';\n /** @type {import('../jsmind.js').default} */\n this.jm = jm;\n /** @type {ScreenshotOptions} */\n this.options = opts;\n /** @type {number} */\n this.dpr = jm.view.device_pixel_ratio;\n }\n\n /** Take a screenshot of the mind map. */\n shoot() {\n let c = this.create_canvas();\n let ctx = c.getContext('2d');\n ctx.scale(this.dpr, this.dpr);\n Promise.resolve(ctx)\n .then(() => this.draw_background(ctx))\n .then(() => this.draw_lines(ctx))\n .then(() => this.draw_nodes(ctx))\n .then(() => this.draw_watermark(c, ctx))\n .then(() => this.download(c))\n .then(() => this.clear(c));\n }\n\n /**\n * Create canvas for screenshot.\n * @returns {HTMLCanvasElement} Canvas element\n */\n create_canvas() {\n let c = $.c('canvas');\n const w = this.jm.view.size.w;\n const h = this.jm.view.size.h;\n c.width = w * this.dpr;\n c.height = h * this.dpr;\n c.style.width = w + 'px';\n c.style.height = h + 'px';\n\n c.style.visibility = 'hidden';\n this.jm.view.e_panel.appendChild(c);\n return c;\n }\n\n /**\n * Clean up canvas element.\n * @param {HTMLCanvasElement} c - Canvas to remove\n */\n clear(c) {\n c.parentNode.removeChild(c);\n }\n\n /**\n * Draw background on canvas.\n * @param {CanvasRenderingContext2D} ctx - Canvas context\n * @returns {Promise<CanvasRenderingContext2D>} Promise resolving to context\n */\n draw_background(ctx) {\n return new Promise(\n function (resolve, _) {\n const bg = this.options.background;\n if (!!bg && bg !== 'transparent') {\n ctx.fillStyle = this.options.background;\n ctx.fillRect(0, 0, this.jm.view.size.w, this.jm.view.size.h);\n }\n resolve(ctx);\n }.bind(this)\n );\n }\n\n /**\n * Draw connection lines on canvas by copying from view graph.\n * @param {CanvasRenderingContext2D} ctx\n * @returns {Promise<CanvasRenderingContext2D>}\n */\n draw_lines(ctx) {\n return new Promise(\n function (resolve, _) {\n this.jm.view.graph.copy_to(ctx, function () {\n resolve(ctx);\n });\n }.bind(this)\n );\n }\n\n /**\n * Draw node DOM into canvas via SVG snapshot.\n * @param {CanvasRenderingContext2D} ctx\n * @returns {Promise<CanvasRenderingContext2D>}\n */\n draw_nodes(ctx) {\n return domtoimage\n .toSvg(this.jm.view.e_nodes, { style: { zoom: 1 } })\n .then(this.load_image)\n .then(function (img) {\n ctx.drawImage(img, 0, 0);\n return ctx;\n });\n }\n\n /**\n * Draw watermark text on canvas.\n * @param {HTMLCanvasElement} c\n * @param {CanvasRenderingContext2D} ctx\n * @returns {CanvasRenderingContext2D}\n */\n draw_watermark(c, ctx) {\n ctx.textBaseline = 'bottom';\n ctx.fillStyle = '#000';\n ctx.font = '11px Verdana,Arial,Helvetica,sans-serif';\n if (!!this.options.watermark.left) {\n ctx.textAlign = 'left';\n ctx.fillText(this.options.watermark.left, 5.5, c.height - 2.5);\n }\n if (!!this.options.watermark.right) {\n ctx.textAlign = 'right';\n ctx.fillText(this.options.watermark.right, c.width - 5.5, c.height - 2.5);\n }\n return ctx;\n }\n\n /**\n * Load image from URL and resolve img element.\n * @param {string} url\n * @returns {Promise<HTMLImageElement>}\n */\n load_image(url) {\n return new Promise(function (resolve, reject) {\n let img = new Image();\n img.onload = function () {\n resolve(img);\n };\n img.onerror = reject;\n img.src = url;\n });\n }\n\n /**\n * Trigger download of canvas content as PNG.\n * @param {HTMLCanvasElement} c\n */\n download(c) {\n var name = (this.options.filename || this.jm.mind.name) + '.png';\n\n if (navigator.msSaveBlob && !!c.msToBlob) {\n var blob = c.msToBlob();\n navigator.msSaveBlob(blob, name);\n } else {\n var blob_url = c.toDataURL();\n var anchor = $.c('a');\n if ('download' in anchor) {\n anchor.style.visibility = 'hidden';\n anchor.href = blob_url;\n anchor.download = name;\n $.d.body.appendChild(anchor);\n var evt = $.d.createEvent('MouseEvents');\n evt.initEvent('click', true, true);\n anchor.dispatchEvent(evt);\n $.d.body.removeChild(anchor);\n } else {\n location.href = blob_url;\n }\n }\n }\n}\n\n/**\n * Screenshot plugin registration.\n * @type {import('../jsmind.plugin.js').Plugin<Partial<ScreenshotOptions>>}\n */\nexport const screenshot_plugin = new jsMind.plugin('screenshot', function (jm, options) {\n var jmss = new JmScreenshot(jm, options);\n jm.screenshot = jmss;\n jm.shoot = function () {\n jmss.shoot();\n };\n});\n\njsMind.register_plugin(screenshot_plugin);\n\nexport default JmScreenshot;\n"],"names":["jsMind","Error","domtoimage","$","DEFAULT_OPTIONS","filename","watermark","left","w","location","right","background","JmScreenshot","constructor","jm","options","opts","util","json","merge","this","version","dpr","view","device_pixel_ratio","shoot","c","create_canvas","ctx","getContext","scale","Promise","resolve","then","draw_background","draw_lines","draw_nodes","draw_watermark","download","clear","size","h","width","height","style","visibility","e_panel","appendChild","parentNode","removeChild","_","bg","fillStyle","fillRect","bind","graph","copy_to","toSvg","e_nodes","zoom","load_image","img","drawImage","textBaseline","font","textAlign","fillText","url","reject","Image","onload","onerror","src","name","mind","navigator","msSaveBlob","msToBlob","blob","blob_url","toDataURL","anchor","href","d","body","evt","createEvent","initEvent","dispatchEvent","screenshot_plugin","plugin","jmss","screenshot","register_plugin"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"jsmind.screenshot.js","sources":["../src/jsmind.common.js","../src/jsmind.plugin.js","../src/plugins/jsmind.screenshot.js"],"sourcesContent":["/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\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 jsMind from '@umbraci/jsmind';\nimport domtoimage from 'dom-to-image';\nimport { Plugin } from '../jsmind.plugin.js';\n\nif (!jsMind) {\n throw new Error('jsMind is not defined');\n}\n\nif (!domtoimage) {\n throw new Error('dom-to-image is required');\n}\n\nconst $ = jsMind.$;\n\n/**\n * Default options for screenshot plugin.\n * @typedef {Object} ScreenshotOptions\n * @property {string|null} [filename]\n * @property {{left?:string|Location,right?:string}} [watermark]\n * @property {string} [background]\n */\nconst DEFAULT_OPTIONS = {\n filename: null,\n watermark: {\n left: $.w.location,\n right: 'https://github.com/UmbraCi/jsmind',\n },\n background: 'transparent',\n};\n\n/**\n * Screenshot plugin for jsMind.\n */\nexport class JmScreenshot {\n /**\n * Create screenshot plugin instance.\n * @param {import('../jsmind.js').default} jm - jsMind instance\n * @param {Partial<ScreenshotOptions>} options - Plugin options\n */\n constructor(jm, options) {\n var opts = {};\n jsMind.util.json.merge(opts, DEFAULT_OPTIONS);\n jsMind.util.json.merge(opts, options);\n\n this.version = '0.2.0';\n /** @type {import('../jsmind.js').default} */\n this.jm = jm;\n /** @type {ScreenshotOptions} */\n this.options = opts;\n /** @type {number} */\n this.dpr = jm.view.device_pixel_ratio;\n }\n\n /** Take a screenshot of the mind map. */\n shoot() {\n let c = this.create_canvas();\n let ctx = c.getContext('2d');\n ctx.scale(this.dpr, this.dpr);\n Promise.resolve(ctx)\n .then(() => this.draw_background(ctx))\n .then(() => this.draw_lines(ctx))\n .then(() => this.draw_nodes(ctx))\n .then(() => this.draw_watermark(c, ctx))\n .then(() => this.download(c))\n .then(() => this.clear(c));\n }\n\n /**\n * Create canvas for screenshot.\n * @returns {HTMLCanvasElement} Canvas element\n */\n create_canvas() {\n let c = $.c('canvas');\n const w = this.jm.view.size.w;\n const h = this.jm.view.size.h;\n c.width = w * this.dpr;\n c.height = h * this.dpr;\n c.style.width = w + 'px';\n c.style.height = h + 'px';\n\n c.style.visibility = 'hidden';\n this.jm.view.e_panel.appendChild(c);\n return c;\n }\n\n /**\n * Clean up canvas element.\n * @param {HTMLCanvasElement} c - Canvas to remove\n */\n clear(c) {\n c.parentNode.removeChild(c);\n }\n\n /**\n * Draw background on canvas.\n * @param {CanvasRenderingContext2D} ctx - Canvas context\n * @returns {Promise<CanvasRenderingContext2D>} Promise resolving to context\n */\n draw_background(ctx) {\n return new Promise(\n function (resolve, _) {\n const bg = this.options.background;\n if (!!bg && bg !== 'transparent') {\n ctx.fillStyle = this.options.background;\n ctx.fillRect(0, 0, this.jm.view.size.w, this.jm.view.size.h);\n }\n resolve(ctx);\n }.bind(this)\n );\n }\n\n /**\n * Draw connection lines on canvas by copying from view graph.\n * @param {CanvasRenderingContext2D} ctx\n * @returns {Promise<CanvasRenderingContext2D>}\n */\n draw_lines(ctx) {\n return new Promise(\n function (resolve, _) {\n this.jm.view.graph.copy_to(ctx, function () {\n resolve(ctx);\n });\n }.bind(this)\n );\n }\n\n /**\n * Draw node DOM into canvas via SVG snapshot.\n * @param {CanvasRenderingContext2D} ctx\n * @returns {Promise<CanvasRenderingContext2D>}\n */\n draw_nodes(ctx) {\n return domtoimage\n .toSvg(this.jm.view.e_nodes, { style: { zoom: 1 } })\n .then(this.load_image)\n .then(function (img) {\n ctx.drawImage(img, 0, 0);\n return ctx;\n });\n }\n\n /**\n * Draw watermark text on canvas.\n * @param {HTMLCanvasElement} c\n * @param {CanvasRenderingContext2D} ctx\n * @returns {CanvasRenderingContext2D}\n */\n draw_watermark(c, ctx) {\n ctx.textBaseline = 'bottom';\n ctx.fillStyle = '#000';\n ctx.font = '11px Verdana,Arial,Helvetica,sans-serif';\n if (!!this.options.watermark.left) {\n ctx.textAlign = 'left';\n ctx.fillText(this.options.watermark.left, 5.5, c.height - 2.5);\n }\n if (!!this.options.watermark.right) {\n ctx.textAlign = 'right';\n ctx.fillText(this.options.watermark.right, c.width - 5.5, c.height - 2.5);\n }\n return ctx;\n }\n\n /**\n * Load image from URL and resolve img element.\n * @param {string} url\n * @returns {Promise<HTMLImageElement>}\n */\n load_image(url) {\n return new Promise(function (resolve, reject) {\n let img = new Image();\n img.onload = function () {\n resolve(img);\n };\n img.onerror = reject;\n img.src = url;\n });\n }\n\n /**\n * Trigger download of canvas content as PNG.\n * @param {HTMLCanvasElement} c\n */\n download(c) {\n var name = (this.options.filename || this.jm.mind.name) + '.png';\n\n if (navigator.msSaveBlob && !!c.msToBlob) {\n var blob = c.msToBlob();\n navigator.msSaveBlob(blob, name);\n } else {\n var blob_url = c.toDataURL();\n var anchor = $.c('a');\n if ('download' in anchor) {\n anchor.style.visibility = 'hidden';\n anchor.href = blob_url;\n anchor.download = name;\n $.d.body.appendChild(anchor);\n var evt = $.d.createEvent('MouseEvents');\n evt.initEvent('click', true, true);\n anchor.dispatchEvent(evt);\n $.d.body.removeChild(anchor);\n } else {\n location.href = blob_url;\n }\n }\n }\n}\n\n/**\n * Screenshot plugin for unified plugin system.\n */\nexport class ScreenshotPlugin extends Plugin {\n static instanceName = 'screenshot';\n static preload = false;\n\n /**\n * @param {{ jm: import('../jsmind.js').default, pluginOpt: Partial<ScreenshotOptions> }} params\n */\n constructor({ jm, pluginOpt }) {\n super({ jm, pluginOpt });\n this.screenshot = new JmScreenshot(jm, pluginOpt);\n jm.screenshot = this.screenshot;\n jm.shoot = () => {\n this.screenshot.shoot();\n };\n }\n\n beforePluginRemove() {\n delete this.jm.shoot;\n delete this.jm.screenshot;\n }\n}\n\njsMind.usePlugin(ScreenshotPlugin);\n\nexport default JmScreenshot;\n"],"names":["String","prototype","startsWith","p","this","slice","length","Plugin","static","constructor","jm","pluginOpt","options","beforePluginRemove","beforePluginDestroy","jsMind","Error","domtoimage","$","DEFAULT_OPTIONS","filename","watermark","left","w","location","right","background","JmScreenshot","opts","util","json","merge","version","dpr","view","device_pixel_ratio","shoot","c","create_canvas","ctx","getContext","scale","Promise","resolve","then","draw_background","draw_lines","draw_nodes","draw_watermark","download","clear","size","h","width","height","style","visibility","e_panel","appendChild","parentNode","removeChild","_","bg","fillStyle","fillRect","bind","graph","copy_to","toSvg","e_nodes","zoom","load_image","img","drawImage","textBaseline","font","textAlign","fillText","url","reject","Image","onload","onerror","src","name","mind","navigator","msSaveBlob","msToBlob","blob","blob_url","toDataURL","anchor","href","d","body","evt","createEvent","initEvent","dispatchEvent","ScreenshotPlugin","super","screenshot","usePlugin"],"mappings":"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"}
|
package/lib/jsmind.copy-paste.js
CHANGED
|
@@ -1,9 +1,264 @@
|
|
|
1
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
|
-
|
|
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';
|
|
9
|
+
function e(e) {
|
|
10
|
+
return e && 'object' == typeof e && 'default' in e ? e : { default: e };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(exports, '__esModule', { value: !0 });
|
|
13
|
+
var t = e(require('@umbraci/jsmind'));
|
|
14
|
+
const i = new (class {
|
|
15
|
+
constructor(e) {
|
|
16
|
+
(this.w = e),
|
|
17
|
+
(this.d = e.document),
|
|
18
|
+
(this.g = function (e) {
|
|
19
|
+
return this.d.getElementById(e);
|
|
20
|
+
}),
|
|
21
|
+
(this.c = function (e) {
|
|
22
|
+
return this.d.createElement(e);
|
|
23
|
+
}),
|
|
24
|
+
(this.t = function (e, t) {
|
|
25
|
+
e.hasChildNodes()
|
|
26
|
+
? (e.firstChild.nodeValue = t)
|
|
27
|
+
: e.appendChild(this.d.createTextNode(t));
|
|
28
|
+
}),
|
|
29
|
+
(this.h = function (e, t) {
|
|
30
|
+
t instanceof HTMLElement
|
|
31
|
+
? ((e.innerHTML = ''), e.appendChild(t))
|
|
32
|
+
: (e.innerHTML = t);
|
|
33
|
+
}),
|
|
34
|
+
(this.i = function (e) {
|
|
35
|
+
return (
|
|
36
|
+
!!e &&
|
|
37
|
+
'object' == typeof e &&
|
|
38
|
+
1 === e.nodeType &&
|
|
39
|
+
'object' == typeof e.style &&
|
|
40
|
+
'object' == typeof e.ownerDocument
|
|
41
|
+
);
|
|
42
|
+
}),
|
|
43
|
+
(this.on = function (e, t, i) {
|
|
44
|
+
e.addEventListener ? e.addEventListener(t, i, !1) : e.attachEvent('on' + t, i);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
})(window),
|
|
48
|
+
n = {
|
|
49
|
+
file: {
|
|
50
|
+
read: function (e, t) {
|
|
51
|
+
var i = new FileReader();
|
|
52
|
+
(i.onload = function () {
|
|
53
|
+
'function' == typeof t && t(this.result, e.name);
|
|
54
|
+
}),
|
|
55
|
+
i.readAsText(e);
|
|
56
|
+
},
|
|
57
|
+
save: function (e, t, n) {
|
|
58
|
+
var o;
|
|
59
|
+
if ('function' == typeof i.w.Blob) o = new Blob([e], { type: t });
|
|
60
|
+
else {
|
|
61
|
+
var r = new (i.w.BlobBuilder ||
|
|
62
|
+
i.w.MozBlobBuilder ||
|
|
63
|
+
i.w.WebKitBlobBuilder ||
|
|
64
|
+
i.w.MSBlobBuilder)();
|
|
65
|
+
r.append(e), (o = r.getBlob(t));
|
|
66
|
+
}
|
|
67
|
+
if (navigator.msSaveBlob) navigator.msSaveBlob(o, n);
|
|
68
|
+
else {
|
|
69
|
+
var a = (i.w.URL || i.w.webkitURL).createObjectURL(o),
|
|
70
|
+
s = i.c('a');
|
|
71
|
+
if ('download' in s) {
|
|
72
|
+
(s.style.visibility = 'hidden'),
|
|
73
|
+
(s.href = a),
|
|
74
|
+
(s.download = n),
|
|
75
|
+
i.d.body.appendChild(s);
|
|
76
|
+
var d = i.d.createEvent('MouseEvents');
|
|
77
|
+
d.initEvent('click', !0, !0), s.dispatchEvent(d), i.d.body.removeChild(s);
|
|
78
|
+
} else location.href = a;
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
json: {
|
|
83
|
+
json2string: function (e) {
|
|
84
|
+
return JSON.stringify(e);
|
|
85
|
+
},
|
|
86
|
+
string2json: function (e) {
|
|
87
|
+
return JSON.parse(e);
|
|
88
|
+
},
|
|
89
|
+
merge: function (e, t) {
|
|
90
|
+
for (var i in t)
|
|
91
|
+
i in e
|
|
92
|
+
? 'object' != typeof e[i] ||
|
|
93
|
+
'[object object]' != Object.prototype.toString.call(e[i]).toLowerCase() ||
|
|
94
|
+
e[i].length
|
|
95
|
+
? (e[i] = t[i])
|
|
96
|
+
: n.json.merge(e[i], t[i])
|
|
97
|
+
: (e[i] = t[i]);
|
|
98
|
+
return e;
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
uuid: {
|
|
102
|
+
newid: function () {
|
|
103
|
+
return (
|
|
104
|
+
new Date().getTime().toString(16) + Math.random().toString(16).substring(2)
|
|
105
|
+
).substring(2, 18);
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
text: {
|
|
109
|
+
is_empty: function (e) {
|
|
110
|
+
return !e || 0 == e.replace(/\s*/, '').length;
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
class o {
|
|
115
|
+
constructor(e, t = {}) {
|
|
116
|
+
(this.jsMind = e),
|
|
117
|
+
(this.options = {
|
|
118
|
+
enabled: !0,
|
|
119
|
+
shortcuts: { copy: 'meta+c', paste: 'meta+v', cut: 'meta+x' },
|
|
120
|
+
...t,
|
|
121
|
+
}),
|
|
122
|
+
(this.clipboardData = null),
|
|
123
|
+
(this.logger = {
|
|
124
|
+
info: e => console.info('[CopyPaste]', e),
|
|
125
|
+
warn: e => console.warn('[CopyPaste]', e),
|
|
126
|
+
error: e => console.error('[CopyPaste]', e),
|
|
127
|
+
debug: e => console.debug('[CopyPaste]', e),
|
|
128
|
+
}),
|
|
129
|
+
this.init();
|
|
130
|
+
}
|
|
131
|
+
init() {
|
|
132
|
+
return this.logger.info('CopyPaste plugin initialized'), !0;
|
|
133
|
+
}
|
|
134
|
+
handleCopy(e) {
|
|
135
|
+
if (!this.options.enabled) return;
|
|
136
|
+
const t = this.jsMind.get_selected_node();
|
|
137
|
+
if (t)
|
|
138
|
+
try {
|
|
139
|
+
e.preventDefault(),
|
|
140
|
+
(this.clipboardData = {
|
|
141
|
+
id: t.id,
|
|
142
|
+
topic: t.topic,
|
|
143
|
+
data: t.data || {},
|
|
144
|
+
direction: t.direction,
|
|
145
|
+
expanded: t.expanded,
|
|
146
|
+
children: this.copyChildren(t),
|
|
147
|
+
}),
|
|
148
|
+
this.logger.info('Node copied:', t.topic),
|
|
149
|
+
this.showMessage('节点已复制');
|
|
150
|
+
} catch (e) {
|
|
151
|
+
this.logger.error('Copy failed:', e), this.showMessage('复制失败', 'error');
|
|
152
|
+
}
|
|
153
|
+
else this.logger.warn('No node selected for copying');
|
|
154
|
+
}
|
|
155
|
+
handlePaste(e) {
|
|
156
|
+
if (!this.options.enabled) return;
|
|
157
|
+
if (!this.clipboardData)
|
|
158
|
+
return (
|
|
159
|
+
this.logger.warn('No data in clipboard'),
|
|
160
|
+
void this.showMessage('剪贴板为空,请先复制节点', 'warning')
|
|
161
|
+
);
|
|
162
|
+
const t = this.jsMind.get_selected_node();
|
|
163
|
+
if (!t)
|
|
164
|
+
return (
|
|
165
|
+
this.logger.warn('No target node selected for pasting'),
|
|
166
|
+
void this.showMessage('请选择目标节点', 'warning')
|
|
167
|
+
);
|
|
168
|
+
try {
|
|
169
|
+
e.preventDefault();
|
|
170
|
+
const i = this.prepareBatchData(this.clipboardData),
|
|
171
|
+
n = this.jsMind.add_nodes(t, [i]);
|
|
172
|
+
n &&
|
|
173
|
+
n.length > 0 &&
|
|
174
|
+
(this.logger.info('Nodes pasted successfully:', this.clipboardData.topic),
|
|
175
|
+
this.showMessage('粘贴成功'));
|
|
176
|
+
} catch (e) {
|
|
177
|
+
this.logger.error('Paste failed:', e), this.showMessage('粘贴失败', 'error');
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
handleCut(e) {
|
|
181
|
+
if (!this.options.enabled) return;
|
|
182
|
+
const t = this.jsMind.get_selected_node();
|
|
183
|
+
if (t) {
|
|
184
|
+
if (t.isroot)
|
|
185
|
+
return (
|
|
186
|
+
this.logger.warn('Cannot cut root node'),
|
|
187
|
+
void this.showMessage('不能剪切根节点', 'warning')
|
|
188
|
+
);
|
|
189
|
+
try {
|
|
190
|
+
e.preventDefault(),
|
|
191
|
+
(this.clipboardData = {
|
|
192
|
+
id: t.id,
|
|
193
|
+
topic: t.topic,
|
|
194
|
+
data: t.data || {},
|
|
195
|
+
direction: t.direction,
|
|
196
|
+
expanded: t.expanded,
|
|
197
|
+
children: this.copyChildren(t),
|
|
198
|
+
});
|
|
199
|
+
this.jsMind.remove_node(t) &&
|
|
200
|
+
(this.logger.info('Node cut:', t.topic), this.showMessage('节点已剪切'));
|
|
201
|
+
} catch (e) {
|
|
202
|
+
this.logger.error('Cut failed:', e), this.showMessage('剪切失败', 'error');
|
|
203
|
+
}
|
|
204
|
+
} else this.logger.warn('No node selected for cutting');
|
|
205
|
+
}
|
|
206
|
+
copyChildren(e) {
|
|
207
|
+
return e.children && 0 !== e.children.length
|
|
208
|
+
? e.children.map(e => ({
|
|
209
|
+
id: e.id,
|
|
210
|
+
topic: e.topic,
|
|
211
|
+
data: e.data || {},
|
|
212
|
+
direction: e.direction,
|
|
213
|
+
expanded: e.expanded,
|
|
214
|
+
children: this.copyChildren(e),
|
|
215
|
+
}))
|
|
216
|
+
: [];
|
|
217
|
+
}
|
|
218
|
+
prepareBatchData(e) {
|
|
219
|
+
return {
|
|
220
|
+
id: n.uuid.newid(),
|
|
221
|
+
topic: e.topic,
|
|
222
|
+
data: e.data || {},
|
|
223
|
+
children:
|
|
224
|
+
e.children && e.children.length > 0
|
|
225
|
+
? e.children.map(e => this.prepareBatchData(e))
|
|
226
|
+
: void 0,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
pasteChildren(e, t) {
|
|
230
|
+
if (!t || 0 === t.length) return [];
|
|
231
|
+
const i = t.map(e => this.prepareBatchData(e));
|
|
232
|
+
return this.jsMind.add_nodes(e, i);
|
|
233
|
+
}
|
|
234
|
+
showMessage(e, t = 'info') {
|
|
235
|
+
console.log(`[CopyPaste ${t.toUpperCase()}]: ${e}`);
|
|
236
|
+
}
|
|
237
|
+
clear() {
|
|
238
|
+
(this.clipboardData = null), this.logger.info('Clipboard cleared');
|
|
239
|
+
}
|
|
240
|
+
getStatus() {
|
|
241
|
+
return { hasData: !!this.clipboardData, data: this.clipboardData };
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const r = new t.default.plugin('copy-paste', function (e, t) {
|
|
245
|
+
var i = t || {};
|
|
246
|
+
i.shortcuts = i.shortcuts || { copy: 'meta+c', paste: 'meta+v', cut: 'meta+x' };
|
|
247
|
+
var n = new o(e, i);
|
|
248
|
+
e.view &&
|
|
249
|
+
e.view.e_panel &&
|
|
250
|
+
e.view.e_panel.addEventListener('keydown', function (e) {
|
|
251
|
+
(!e.metaKey && !e.ctrlKey) || 'c' !== e.key || e.shiftKey || e.altKey
|
|
252
|
+
? (!e.metaKey && !e.ctrlKey) || 'v' !== e.key || e.shiftKey || e.altKey
|
|
253
|
+
? (!e.metaKey && !e.ctrlKey) ||
|
|
254
|
+
'x' !== e.key ||
|
|
255
|
+
e.shiftKey ||
|
|
256
|
+
e.altKey ||
|
|
257
|
+
n.handleCut(e)
|
|
258
|
+
: n.handlePaste(e)
|
|
259
|
+
: n.handleCopy(e);
|
|
260
|
+
}),
|
|
261
|
+
(e.copy_paste_handler = n);
|
|
262
|
+
});
|
|
263
|
+
t.default.register_plugin(r), (exports.copy_paste_plugin = r), (exports.default = o);
|
|
9
264
|
//# sourceMappingURL=jsmind.copy-paste.js.map
|
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* Project Home:
|
|
6
6
|
* https://github.com/hizzgdev/jsmind/
|
|
7
7
|
*/
|
|
8
|
-
"use strict";function t(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}Object.defineProperty(exports,"__esModule",{value:!0});var e=t(require("@umbraci/jsmind"));if(!e.default)throw new Error("jsMind is not defined");const i=e.default.$,s="getSelection"in i.w?function(){i.w.getSelection().removeAllRanges()}:function(){i.d.selection.empty()},o={line_width:5,line_color:"rgba(0,0,0,0.3)",line_color_invalid:"rgba(255,51,51,0.6)",lookup_delay:200,lookup_interval:100,scrolling_trigger_width:20,scrolling_step_length:10,shadow_node_class_name:"jsmind-draggable-shadow-node"};class n{constructor(t,i){var s={};e.default.util.json.merge(s,o),e.default.util.json.merge(s,i),this.version="0.4.0",this.jm=t,this.options=s,this.is_svg_engine="svg"===t.view.opts.engine,this.e_canvas=null,this.canvas_ctx=null,this.helper_line=null,this.shadow=null,this.shadow_p_x=0,this.shadow_p_y=0,this.shadow_w=0,this.shadow_h=0,this.active_node=null,this.target_node=null,this.target_direct=null,this.client_w=0,this.client_h=0,this.offset_x=0,this.offset_y=0,this.hlookup_delay=0,this.hlookup_timer=0,this.capture=!1,this.moved=!1,this.canvas_draggable=t.get_view_draggable(),this.view_panel=t.view.e_panel,this.view_panel_rect=null}init(){this.create_canvas(),this.create_shadow(),this.event_bind()}resize(){this.jm.view.e_nodes.appendChild(this.shadow),this.is_svg_engine?(this.e_canvas.setAttribute("width",this.jm.view.size.w),this.e_canvas.setAttribute("height",this.jm.view.size.h)):(this.e_canvas.width=this.jm.view.size.w,this.e_canvas.height=this.jm.view.size.h)}create_canvas(){if(this.is_svg_engine){var t=this._create_svg_element("svg");t.setAttribute("class","jsmind-draggable-helper"),t.setAttribute("style","position: absolute; top: 0; left: 0; pointer-events: none;"),this.jm.view.e_panel.appendChild(t),this.e_canvas=t}else{var e=i.c("canvas");this.jm.view.e_panel.appendChild(e);var s=e.getContext("2d");this.e_canvas=e,this.canvas_ctx=s}}_create_svg_element(t){return i.d.createElementNS("http://www.w3.org/2000/svg",t)}create_shadow(){var t=i.c("jmnode");t.style.visibility="hidden",t.style.zIndex="3",t.style.cursor="move",t.style.opacity="0.7",t.className=this.options.shadow_node_class_name,this.shadow=t}reset_shadow(t){var e=this.shadow.style;this.shadow.innerHTML=t.innerHTML,e.left=t.style.left,e.top=t.style.top,e.width=t.style.width,e.height=t.style.height,e.backgroundImage=t.style.backgroundImage,e.backgroundSize=t.style.backgroundSize,e.transform=t.style.transform,this.shadow_w=this.shadow.clientWidth,this.shadow_h=this.shadow.clientHeight}show_shadow(){this.moved||(this.shadow.style.visibility="visible")}hide_shadow(){this.shadow.style.visibility="hidden"}magnet_shadow(t,e,i){this.clear_lines();var s=i?this.options.line_color_invalid:this.options.line_color;this.is_svg_engine?this.svg_draw_line(t.x,t.y,e.x,e.y,s):(this.canvas_ctx.lineWidth=this.options.line_width,this.canvas_ctx.strokeStyle=s,this.canvas_ctx.lineCap="round",this.canvas_lineto(t.x,t.y,e.x,e.y))}clear_lines(){this.is_svg_engine?this.helper_line&&this.helper_line.parentNode&&(this.e_canvas.removeChild(this.helper_line),this.helper_line=null):this.canvas_ctx.clearRect(0,0,this.jm.view.size.w,this.jm.view.size.h)}canvas_lineto(t,e,i,s){this.canvas_ctx.beginPath(),this.canvas_ctx.moveTo(t,e),this.canvas_ctx.lineTo(i,s),this.canvas_ctx.stroke()}svg_draw_line(t,e,i,s,o){this.helper_line=this._create_svg_element("path"),this.helper_line.setAttribute("stroke",o),this.helper_line.setAttribute("stroke-width",this.options.line_width),this.helper_line.setAttribute("fill","transparent"),this.helper_line.setAttribute("stroke-linecap","round"),this._svg_bezier_to(this.helper_line,t,e,i,s),this.e_canvas.appendChild(this.helper_line)}_svg_bezier_to(t,e,i,s,o){t.setAttribute("d","M "+e+" "+i+" C "+(e+2*(s-e)/3)+" "+i+", "+e+" "+o+", "+s+" "+o)}event_bind(){var t=this,e=this.jm.view.container;i.on(e,"mousedown",function(e){0===e.button&&t.dragstart.call(t,e)}),i.on(e,"mousemove",function(e){0===e.movementX&&0===e.movementY||t.drag.call(t,e)}),i.on(e,"mouseup",function(e){t.dragend.call(t,e)}),i.on(e,"touchstart",function(e){t.dragstart.call(t,e)}),i.on(e,"touchmove",function(e){t.drag.call(t,e)}),i.on(e,"touchend",function(e){t.dragend.call(t,e)})}dragstart(t){if(this.jm.get_editable()&&!this.capture){var e=this.jm.view;if(!e.is_editing()){this.active_node=null,this.view_draggable=this.jm.get_view_draggable();var s=this.find_node_element(t.target);if(s){this.view_draggable&&this.jm.disable_view_draggable();var o=e.get_binded_nodeid(s);if(o){var n=this.jm.get_node(o);if(!n.isroot){if(n.data&&!1===n.data.draggable)return;this.reset_shadow(s),this.view_panel_rect=this.view_panel.getBoundingClientRect(),this.active_node=n,this.offset_x=(t.clientX||t.touches[0].clientX)/e.zoom_current-s.offsetLeft,this.offset_y=(t.clientY||t.touches[0].clientY)/e.zoom_current-s.offsetTop,this.client_hw=Math.floor(s.clientWidth/2),this.client_hh=Math.floor(s.clientHeight/2),0!=this.hlookup_delay&&i.w.clearTimeout(this.hlookup_delay),0!=this.hlookup_timer&&i.w.clearInterval(this.hlookup_timer);var h=this;this.hlookup_delay=i.w.setTimeout(function(){h.hlookup_delay=0,h.hlookup_timer=i.w.setInterval(function(){h.lookup_target_node.call(h)},h.options.lookup_interval)},this.options.lookup_delay),h.capture=!0}}}}}}drag(t){if(this.jm.get_editable()&&this.capture){t.preventDefault(),this.show_shadow(),this.moved=!0,s();var e=this.jm.view,i=(t.clientX||t.touches[0].clientX)/e.zoom_current-this.offset_x,o=(t.clientY||t.touches[0].clientY)/e.zoom_current-this.offset_y;t.clientY-this.view_panel_rect.top<this.options.scrolling_trigger_width&&this.view_panel.scrollTop>this.options.scrolling_step_length?(this.view_panel.scrollBy(0,-this.options.scrolling_step_length),this.offset_y+=this.options.scrolling_step_length/e.zoom_current):this.view_panel_rect.bottom-t.clientY<this.options.scrolling_trigger_width&&this.view_panel.scrollTop<this.view_panel.scrollHeight-this.view_panel_rect.height-this.options.scrolling_step_length&&(this.view_panel.scrollBy(0,this.options.scrolling_step_length),this.offset_y-=this.options.scrolling_step_length/e.zoom_current),t.clientX-this.view_panel_rect.left<this.options.scrolling_trigger_width&&this.view_panel.scrollLeft>this.options.scrolling_step_length?(this.view_panel.scrollBy(-this.options.scrolling_step_length,0),this.offset_x+=this.options.scrolling_step_length/e.zoom_current):this.view_panel_rect.right-t.clientX<this.options.scrolling_trigger_width&&this.view_panel.scrollLeft<this.view_panel.scrollWidth-this.view_panel_rect.width-this.options.scrolling_step_length&&(this.view_panel.scrollBy(this.options.scrolling_step_length,0),this.offset_x-=this.options.scrolling_step_length/e.zoom_current),this.shadow.style.left=i+"px",this.shadow.style.top=o+"px",s()}}dragend(t){if(this.jm.get_editable()){if(this.view_draggable&&this.jm.enable_view_draggable(),this.capture){if(0!=this.hlookup_delay&&(i.w.clearTimeout(this.hlookup_delay),this.hlookup_delay=0,this.clear_lines()),0!=this.hlookup_timer&&(i.w.clearInterval(this.hlookup_timer),this.hlookup_timer=0,this.clear_lines()),this.moved){var e=this.active_node,s=this.target_node,o=this.target_direct;this.move_node(e,s,o)}this.hide_shadow()}this.view_panel_rect=null,this.moved=!1,this.capture=!1}}find_node_element(t){return t===this.jm.view.e_nodes||t===this.jm.view.e_panel||t===this.jm.view.container?null:"jmnode"===t.tagName.toLowerCase()?t:this.find_node_element(t.parentNode)}lookup_target_node(){let t=this.shadow.offsetLeft,i=this.shadow.offsetTop;if(t===this.shadow_p_x&&i===this.shadow_p_y)return;this.shadow_p_x=t,this.shadow_p_y=i;let s=this.shadow_p_x+this.shadow_w/2>=this.get_root_x()?e.default.direction.right:e.default.direction.left,o=this.lookup_overlapping_node_parent(s)||this.lookup_close_node(s);if(o){let t=this.calc_point_of_node(o,s),i=e.default.node.inherited(this.active_node,o);this.magnet_shadow(t.sp,t.np,i),this.target_node=o,this.target_direct=s}}get_root_x(){let t=this.jm.get_root(),e=t.get_location(),i=t.get_size();return e.x+i.w/2}lookup_overlapping_node_parent(t){let e=this.shadow.getBoundingClientRect(),i=e.x+e.width*(1-t)/2,s=(this.jm.options.layout.hspace+this.jm.options.layout.pspace)*t,o=e.height,n=[[i,e.y],[i,e.y+o/2],[i,e.y+o],[i+s/2,e.y],[i+s/2,e.y+o/2],[i+s/2,e.y+o],[i+s,e.y],[i+s,e.y+o/2],[i+s,e.y+o]];for(const t of n){let e=this.lookup_node_parent_by_location(t[0],t[1]);if(e)return e}}lookup_node_parent_by_location(t,e){return i.d.elementsFromPoint(t,e).filter(t=>"JMNODE"===t.tagName&&t.className!==this.options.shadow_node_class_name).map(t=>this.jm.view.get_binded_nodeid(t)).map(t=>t&&this.jm.mind.nodes[t]).map(t=>t&&t.parent).find(t=>t)}lookup_close_node(t){return Object.values(this.jm.mind.nodes).filter(e=>e.direction==t||e.isroot).filter(t=>this.jm.layout.is_visible(t)).filter(e=>this.shadow_on_target_side(e,t)).map(e=>({node:e,distance:this.shadow_to_node(e,t)})).reduce((t,e)=>t.distance<e.distance?t:e,{node:this.jm.get_root(),distance:Number.MAX_VALUE}).node}shadow_on_target_side(t,i){return i==e.default.direction.right&&this.shadow_to_right_of_node(t)>0||i==e.default.direction.left&&this.shadow_to_left_of_node(t)>0}shadow_to_right_of_node(t){return this.shadow_p_x-t.get_location().x-t.get_size().w}shadow_to_left_of_node(t){return t.get_location().x-this.shadow_p_x-this.shadow_w}shadow_to_base_line_of_node(t){return this.shadow_p_y+this.shadow_h/2-t.get_location().y-t.get_size().h/2}shadow_to_node(t,i){return(i===e.default.direction.right?Math.abs(this.shadow_to_right_of_node(t)):Math.abs(this.shadow_to_left_of_node(t)))+Math.abs(this.shadow_to_base_line_of_node(t))}calc_point_of_node(t,e){let i=t.get_size(),s=t.get_location(),o=t.isroot?s.x+i.w/2:s.x+i.w*(1+e)/2+this.options.line_width*e,n=s.y+i.h/2;return{sp:{x:this.shadow_p_x+this.shadow_w*(1-e)/2-this.options.line_width*e,y:this.shadow_p_y+this.shadow_h/2},np:{x:o,y:n}}}move_node(t,i,s){var o=this.shadow.offsetTop;if(i&&t&&!e.default.node.inherited(t,i)){if(this.options.validate_drag&&"function"==typeof this.options.validate_drag){if(!this.options.validate_drag(t,i))return this.active_node=null,this.target_node=null,void(this.target_direct=null)}for(var n=i.children,h=n.length,l=null,_=Number.MAX_VALUE,a=null,r="_last_";h--;)if((l=n[h]).direction==s&&l.id!=t.id){var d=l.get_location().y-o;d>0&&d<_&&(_=d,a=l,r="_first_")}a&&(r=a.id),this.jm.move_node(t.id,r,i.id,s)}this.active_node=null,this.target_node=null,this.target_direct=null}jm_event_handle(t,i){t===e.default.event_type.resize&&this.resize()}}const h=new e.default.plugin("draggable_node",function(t,e){var i=new n(t,e);i.init(),t.add_event_listener(function(t,e){i.jm_event_handle.call(i,t,e)})});e.default.register_plugin(h),exports.DraggableNode=n,exports.default=n,exports.draggable_plugin=h;
|
|
8
|
+
"use strict";function t(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}Object.defineProperty(exports,"__esModule",{value:!0});var e=t(require("@umbraci/jsmind"));"function"!=typeof String.prototype.startsWith&&(String.prototype.startsWith=function(t){return this.slice(0,t.length)===t});class i{static instanceName="";static preload=!1;constructor({jm:t,pluginOpt:e}){this.jm=t,this.options=e||{}}beforePluginRemove(){}beforePluginDestroy(){this.beforePluginRemove()}}if(!e.default)throw new Error("jsMind is not defined");const s=e.default.$,o="getSelection"in s.w?function(){s.w.getSelection().removeAllRanges()}:function(){s.d.selection.empty()},n={line_width:5,line_color:"rgba(0,0,0,0.3)",line_color_invalid:"rgba(255,51,51,0.6)",lookup_delay:200,lookup_interval:100,scrolling_trigger_width:20,scrolling_step_length:10,shadow_node_class_name:"jsmind-draggable-shadow-node"};class h{constructor(t,i){var s={};e.default.util.json.merge(s,n),e.default.util.json.merge(s,i),this.version="0.4.0",this.jm=t,this.options=s,this.is_svg_engine="svg"===t.view.opts.engine,this.e_canvas=null,this.canvas_ctx=null,this.helper_line=null,this.shadow=null,this.shadow_p_x=0,this.shadow_p_y=0,this.shadow_w=0,this.shadow_h=0,this.active_node=null,this.target_node=null,this.target_direct=null,this.client_w=0,this.client_h=0,this.offset_x=0,this.offset_y=0,this.hlookup_delay=0,this.hlookup_timer=0,this.capture=!1,this.moved=!1,this.canvas_draggable=t.get_view_draggable(),this.view_panel=t.view.e_panel,this.view_panel_rect=null}init(){this.create_canvas(),this.create_shadow(),this.event_bind()}resize(){this.jm.view.e_nodes.appendChild(this.shadow),this.is_svg_engine?(this.e_canvas.setAttribute("width",this.jm.view.size.w),this.e_canvas.setAttribute("height",this.jm.view.size.h)):(this.e_canvas.width=this.jm.view.size.w,this.e_canvas.height=this.jm.view.size.h)}create_canvas(){if(this.is_svg_engine){var t=this._create_svg_element("svg");t.setAttribute("class","jsmind-draggable-helper"),t.setAttribute("style","position: absolute; top: 0; left: 0; pointer-events: none;"),this.jm.view.e_panel.appendChild(t),this.e_canvas=t}else{var e=s.c("canvas");this.jm.view.e_panel.appendChild(e);var i=e.getContext("2d");this.e_canvas=e,this.canvas_ctx=i}}_create_svg_element(t){return s.d.createElementNS("http://www.w3.org/2000/svg",t)}create_shadow(){var t=s.c("jmnode");t.style.visibility="hidden",t.style.zIndex="3",t.style.cursor="move",t.style.opacity="0.7",t.className=this.options.shadow_node_class_name,this.shadow=t}reset_shadow(t){var e=this.shadow.style,i=t.style,o=s.w.getComputedStyle(t);this.shadow.innerHTML=t.innerHTML;["left","top","width","height","backgroundImage","backgroundSize","transform"].forEach(t=>{e[t]=i[t]});["whiteSpace","wordBreak","overflowWrap","maxWidth"].forEach(t=>{e[t]=i[t]||o[t]}),this.shadow_w=this.shadow.clientWidth,this.shadow_h=this.shadow.clientHeight}show_shadow(){this.moved||(this.shadow.style.visibility="visible")}hide_shadow(){this.shadow.style.visibility="hidden"}magnet_shadow(t,e,i){this.clear_lines();var s=i?this.options.line_color_invalid:this.options.line_color;this.is_svg_engine?this.svg_draw_line(t.x,t.y,e.x,e.y,s):(this.canvas_ctx.lineWidth=this.options.line_width,this.canvas_ctx.strokeStyle=s,this.canvas_ctx.lineCap="round",this.canvas_lineto(t.x,t.y,e.x,e.y))}clear_lines(){this.is_svg_engine?this.helper_line&&this.helper_line.parentNode&&(this.e_canvas.removeChild(this.helper_line),this.helper_line=null):this.canvas_ctx.clearRect(0,0,this.jm.view.size.w,this.jm.view.size.h)}canvas_lineto(t,e,i,s){this.canvas_ctx.beginPath(),this.canvas_ctx.moveTo(t,e),this.canvas_ctx.lineTo(i,s),this.canvas_ctx.stroke()}svg_draw_line(t,e,i,s,o){this.helper_line=this._create_svg_element("path"),this.helper_line.setAttribute("stroke",o),this.helper_line.setAttribute("stroke-width",this.options.line_width),this.helper_line.setAttribute("fill","transparent"),this.helper_line.setAttribute("stroke-linecap","round"),this._svg_bezier_to(this.helper_line,t,e,i,s),this.e_canvas.appendChild(this.helper_line)}_svg_bezier_to(t,e,i,s,o){t.setAttribute("d","M "+e+" "+i+" C "+(e+2*(s-e)/3)+" "+i+", "+e+" "+o+", "+s+" "+o)}event_bind(){var t=this,e=this.jm.view.container;s.on(e,"mousedown",function(e){0===e.button&&t.dragstart.call(t,e)}),s.on(e,"mousemove",function(e){0===e.movementX&&0===e.movementY||t.drag.call(t,e)}),s.on(e,"mouseup",function(e){t.dragend.call(t,e)}),s.on(e,"touchstart",function(e){t.dragstart.call(t,e)}),s.on(e,"touchmove",function(e){t.drag.call(t,e)}),s.on(e,"touchend",function(e){t.dragend.call(t,e)})}dragstart(t){if(this.jm.get_editable()&&!this.capture){var e=this.jm.view;if(!e.is_editing()){this.active_node=null,this.view_draggable=this.jm.get_view_draggable();var i=this.find_node_element(t.target);if(i){this.view_draggable&&this.jm.disable_view_draggable();var o=e.get_binded_nodeid(i);if(o){var n=this.jm.get_node(o);if(!n.isroot){if(n.data&&!1===n.data.draggable)return;this.reset_shadow(i),this.view_panel_rect=this.view_panel.getBoundingClientRect(),this.active_node=n,this.offset_x=(t.clientX||t.touches[0].clientX)/e.zoom_current-i.offsetLeft,this.offset_y=(t.clientY||t.touches[0].clientY)/e.zoom_current-i.offsetTop,this.client_hw=Math.floor(i.clientWidth/2),this.client_hh=Math.floor(i.clientHeight/2),0!=this.hlookup_delay&&s.w.clearTimeout(this.hlookup_delay),0!=this.hlookup_timer&&s.w.clearInterval(this.hlookup_timer);var h=this;this.hlookup_delay=s.w.setTimeout(function(){h.hlookup_delay=0,h.hlookup_timer=s.w.setInterval(function(){h.lookup_target_node.call(h)},h.options.lookup_interval)},this.options.lookup_delay),h.capture=!0}}}}}}drag(t){if(this.jm.get_editable()&&this.capture){t.preventDefault(),this.show_shadow(),this.moved=!0,o();var e=this.jm.view,i=(t.clientX||t.touches[0].clientX)/e.zoom_current-this.offset_x,s=(t.clientY||t.touches[0].clientY)/e.zoom_current-this.offset_y;t.clientY-this.view_panel_rect.top<this.options.scrolling_trigger_width&&this.view_panel.scrollTop>this.options.scrolling_step_length?(this.view_panel.scrollBy(0,-this.options.scrolling_step_length),this.offset_y+=this.options.scrolling_step_length/e.zoom_current):this.view_panel_rect.bottom-t.clientY<this.options.scrolling_trigger_width&&this.view_panel.scrollTop<this.view_panel.scrollHeight-this.view_panel_rect.height-this.options.scrolling_step_length&&(this.view_panel.scrollBy(0,this.options.scrolling_step_length),this.offset_y-=this.options.scrolling_step_length/e.zoom_current),t.clientX-this.view_panel_rect.left<this.options.scrolling_trigger_width&&this.view_panel.scrollLeft>this.options.scrolling_step_length?(this.view_panel.scrollBy(-this.options.scrolling_step_length,0),this.offset_x+=this.options.scrolling_step_length/e.zoom_current):this.view_panel_rect.right-t.clientX<this.options.scrolling_trigger_width&&this.view_panel.scrollLeft<this.view_panel.scrollWidth-this.view_panel_rect.width-this.options.scrolling_step_length&&(this.view_panel.scrollBy(this.options.scrolling_step_length,0),this.offset_x-=this.options.scrolling_step_length/e.zoom_current),this.shadow.style.left=i+"px",this.shadow.style.top=s+"px",o()}}dragend(t){if(this.jm.get_editable()){if(this.view_draggable&&this.jm.enable_view_draggable(),this.capture){if(0!=this.hlookup_delay&&(s.w.clearTimeout(this.hlookup_delay),this.hlookup_delay=0,this.clear_lines()),0!=this.hlookup_timer&&(s.w.clearInterval(this.hlookup_timer),this.hlookup_timer=0,this.clear_lines()),this.moved){var e=this.active_node,i=this.target_node,o=this.target_direct;this.move_node(e,i,o)}this.hide_shadow()}this.view_panel_rect=null,this.moved=!1,this.capture=!1}}find_node_element(t){return t===this.jm.view.e_nodes||t===this.jm.view.e_panel||t===this.jm.view.container?null:"jmnode"===t.tagName.toLowerCase()?t:this.find_node_element(t.parentNode)}lookup_target_node(){let t=this.shadow.offsetLeft,i=this.shadow.offsetTop;if(t===this.shadow_p_x&&i===this.shadow_p_y)return;this.shadow_p_x=t,this.shadow_p_y=i;let s=this.shadow_p_x+this.shadow_w/2>=this.get_root_x()?e.default.direction.right:e.default.direction.left,o=this.lookup_overlapping_node_parent(s)||this.lookup_close_node(s);if(o){let t=this.calc_point_of_node(o,s),i=e.default.node.inherited(this.active_node,o);this.magnet_shadow(t.sp,t.np,i),this.target_node=o,this.target_direct=s}}get_root_x(){let t=this.jm.get_root(),e=t.get_location(),i=t.get_size();return e.x+i.w/2}lookup_overlapping_node_parent(t){let e=this.shadow.getBoundingClientRect(),i=e.x+e.width*(1-t)/2,s=(this.jm.options.layout.hspace+this.jm.options.layout.pspace)*t,o=e.height,n=[[i,e.y],[i,e.y+o/2],[i,e.y+o],[i+s/2,e.y],[i+s/2,e.y+o/2],[i+s/2,e.y+o],[i+s,e.y],[i+s,e.y+o/2],[i+s,e.y+o]];for(const t of n){let e=this.lookup_node_parent_by_location(t[0],t[1]);if(e)return e}}lookup_node_parent_by_location(t,e){return s.d.elementsFromPoint(t,e).filter(t=>"JMNODE"===t.tagName&&t.className!==this.options.shadow_node_class_name).map(t=>this.jm.view.get_binded_nodeid(t)).map(t=>t&&this.jm.mind.nodes[t]).map(t=>t&&t.parent).find(t=>t)}lookup_close_node(t){return Object.values(this.jm.mind.nodes).filter(e=>e.direction==t||e.isroot).filter(t=>this.jm.layout.is_visible(t)).filter(e=>this.shadow_on_target_side(e,t)).map(e=>({node:e,distance:this.shadow_to_node(e,t)})).reduce((t,e)=>t.distance<e.distance?t:e,{node:this.jm.get_root(),distance:Number.MAX_VALUE}).node}shadow_on_target_side(t,i){return i==e.default.direction.right&&this.shadow_to_right_of_node(t)>0||i==e.default.direction.left&&this.shadow_to_left_of_node(t)>0}shadow_to_right_of_node(t){return this.shadow_p_x-t.get_location().x-t.get_size().w}shadow_to_left_of_node(t){return t.get_location().x-this.shadow_p_x-this.shadow_w}shadow_to_base_line_of_node(t){return this.shadow_p_y+this.shadow_h/2-t.get_location().y-t.get_size().h/2}shadow_to_node(t,i){return(i===e.default.direction.right?Math.abs(this.shadow_to_right_of_node(t)):Math.abs(this.shadow_to_left_of_node(t)))+Math.abs(this.shadow_to_base_line_of_node(t))}calc_point_of_node(t,e){let i=t.get_size(),s=t.get_location(),o=t.isroot?s.x+i.w/2:s.x+i.w*(1+e)/2+this.options.line_width*e,n=s.y+i.h/2;return{sp:{x:this.shadow_p_x+this.shadow_w*(1-e)/2-this.options.line_width*e,y:this.shadow_p_y+this.shadow_h/2},np:{x:o,y:n}}}move_node(t,i,s){var o=this.shadow.offsetTop;if(i&&t&&!e.default.node.inherited(t,i)){if(this.options.validate_drag&&"function"==typeof this.options.validate_drag){if(!this.options.validate_drag(t,i))return this.active_node=null,this.target_node=null,void(this.target_direct=null)}for(var n=i.children,h=n.length,l=null,a=Number.MAX_VALUE,_=null,r="_last_";h--;)if((l=n[h]).direction==s&&l.id!=t.id){var d=l.get_location().y-o;d>0&&d<a&&(a=d,_=l,r="_first_")}_&&(r=_.id),this.jm.move_node(t.id,r,i.id,s)}this.active_node=null,this.target_node=null,this.target_direct=null}jm_event_handle(t,i){t===e.default.event_type.resize&&this.resize()}}class l extends i{static instanceName="draggable";static preload=!1;constructor({jm:t,pluginOpt:e}){super({jm:t,pluginOpt:e}),this.draggable=new h(t,e),this.draggable.init(),this._eventHandle=(t,e)=>{this.draggable.jm_event_handle(t,e)},t.add_event_listener(this._eventHandle),t.draggable=this.draggable}beforePluginRemove(){delete this.jm.draggable}}e.default.usePlugin(l),exports.DraggableNode=h,exports.DraggableNodePlugin=l,exports.default=h;
|
|
9
9
|
//# sourceMappingURL=jsmind.draggable-node.js.map
|