power-link 0.0.7 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +119 -23
  2. package/dist/index.js +2 -2
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -7,6 +7,8 @@ A pure JavaScript visual node connector for creating draggable connections betwe
7
7
 
8
8
  ![Node Link Connector Demo](https://github.com/Tem-man/power-link/blob/main/public/images/screen-shot.png)
9
9
 
10
+ ![Node Link Connector Demo](https://github.com/Tem-man/power-link/blob/main/public/images/screen-shot-2.png)
11
+
10
12
  ### 📹 Demo Video
11
13
 
12
14
  <video width="100%" controls>
@@ -116,24 +118,25 @@ connector.registerNode("node2", node2, {
116
118
 
117
119
  ### Constructor Options
118
120
 
119
- | Option | Type | Default | Description |
120
- | ------------------ | ----------- | ------------ | ----------------------------------- |
121
- | `container` | HTMLElement | **Required** | Container element for the connector |
122
- | `lineColor` | String | `'#155BD4'` | Color of connection lines |
123
- | `lineWidth` | Number | `2` | Width of connection lines |
124
- | `dotSize` | Number | `12` | Size of connection dots |
125
- | `dotColor` | String | `'#155BD4'` | Color of connection dots |
126
- | `deleteButtonSize` | Number | `20` | Size of delete button |
127
- | `enableNodeDrag` | Boolean | `true` | Enable node dragging |
128
- | `enableSnap` | Boolean | `true` | Enable connection snapping |
129
- | `snapDistance` | Number | `20` | Snap distance in pixels |
130
- | `enableZoom` | Boolean | `true` | Enable zoom functionality |
131
- | `enablePan` | Boolean | `true` | Enable pan functionality |
132
- | `minZoom` | Number | `0.1` | Minimum zoom level (10%) |
133
- | `maxZoom` | Number | `4` | Maximum zoom level (400%) |
134
- | `zoomStep` | Number | `0.1` | Zoom step size (10%) |
135
- | `onConnect` | Function | `() => {}` | Callback when connection is created |
136
- | `onDisconnect` | Function | `() => {}` | Callback when connection is removed |
121
+ | Option | Type | Default | Description |
122
+ | ------------------ | ----------- | ------------ | ----------------------------------------------- |
123
+ | `container` | HTMLElement | **Required** | Container element for the connector |
124
+ | `lineColor` | String | `'#155BD4'` | Color of connection lines |
125
+ | `lineWidth` | Number | `2` | Width of connection lines |
126
+ | `dotSize` | Number | `12` | Size of connection dots |
127
+ | `dotColor` | String | `'#155BD4'` | Color of connection dots |
128
+ | `dotHoverScale` | Number | `1.8` | Scale factor when hovering over connection dots |
129
+ | `deleteButtonSize` | Number | `20` | Size of delete button |
130
+ | `enableNodeDrag` | Boolean | `true` | Enable node dragging |
131
+ | `enableSnap` | Boolean | `true` | Enable connection snapping |
132
+ | `snapDistance` | Number | `20` | Snap distance in pixels |
133
+ | `enableZoom` | Boolean | `true` | Enable zoom functionality |
134
+ | `enablePan` | Boolean | `true` | Enable pan functionality |
135
+ | `minZoom` | Number | `0.1` | Minimum zoom level (10%) |
136
+ | `maxZoom` | Number | `4` | Maximum zoom level (400%) |
137
+ | `zoomStep` | Number | `0.1` | Zoom step size (10%) |
138
+ | `onConnect` | Function | `() => {}` | Callback when connection is created |
139
+ | `onDisconnect` | Function | `() => {}` | Callback when connection is removed |
137
140
 
138
141
  ### Methods
139
142
 
@@ -168,7 +171,7 @@ connector.registerNode("myNode", element, {
168
171
  });
169
172
  ```
170
173
 
171
- #### `createConnection(fromNode, toNode, fromDot, toDot)`
174
+ #### `createConnection(fromNode, toNode, fromDot, toDot,options)`
172
175
 
173
176
  Programmatically create a connection between nodes.
174
177
 
@@ -178,6 +181,8 @@ Programmatically create a connection between nodes.
178
181
  - `toNode` (Object): Target node object
179
182
  - `fromDot` (Object): Source connection dot (optional)
180
183
  - `toDot` (Object): Target connection dot (optional)
184
+ - `options` (Object): Configuration options (optional)
185
+ - `silent` (boolean): Whether to create silently (without triggering callbacks)
181
186
 
182
187
  **Returns:** Connection object
183
188
 
@@ -186,22 +191,26 @@ Programmatically create a connection between nodes.
186
191
  ```javascript
187
192
  const node1 = connector.nodes[0];
188
193
  const node2 = connector.nodes[1];
189
- connector.createConnection(node1, node2);
194
+ connector.createConnection(node1, node2); // Create connection with callbacks
195
+ connector.createConnection(node1, node2, null, null, { silent: true }); // Create connection silently without triggering callbacks
190
196
  ```
191
197
 
192
- #### `disconnect(connectionId)`
198
+ #### `disconnect(connectionId,options)`
193
199
 
194
200
  Remove a connection.
195
201
 
196
202
  **Parameters:**
197
203
 
198
204
  - `connectionId` (String): Connection ID (optional, if not provided, removes all connections)
205
+ - `options` (Object): Configuration options (optional)
206
+ - `silent` (boolean): Whether to disconnect silently (without triggering callbacks)
199
207
 
200
208
  **Example:**
201
209
 
202
210
  ```javascript
203
211
  connector.disconnect(); // Remove all connections
204
212
  connector.disconnect("connection-id"); // Remove specific connection
213
+ connector.disconnect("connection-id", { silent: true }); // Remove connection silently without triggering callbacks
205
214
  ```
206
215
 
207
216
  #### `getConnections()`
@@ -235,14 +244,20 @@ Update node position (called when node is moved).
235
244
 
236
245
  - `nodeId` (String): Node ID
237
246
 
238
- #### `destroy()`
247
+ #### `destroy(options)`
239
248
 
240
249
  Destroy the connector and clean up all resources.
241
250
 
251
+ **Parameters:**
252
+
253
+ - `options` (Object): Configuration options (optional)
254
+ - `silent` (boolean): Whether to destroy silently (without triggering callbacks)
255
+
242
256
  **Example:**
243
257
 
244
258
  ```javascript
245
- connector.destroy();
259
+ connector.destroy(); // Destroy silently by default (without triggering callbacks)
260
+ connector.destroy({ silent: false }); // Destroy non-silently (triggering callbacks)
246
261
  ```
247
262
 
248
263
  #### `setViewState(scale,translateX,translateY)`
@@ -526,6 +541,87 @@ connector.registerNode("startNode", element, {
526
541
  });
527
542
  ```
528
543
 
544
+ ### Silent Operations (No Callbacks)
545
+
546
+ Sometimes you may want to perform operations without triggering callbacks, such as when initializing connections from saved data or bulk operations.
547
+
548
+ ```javascript
549
+ // Silent connection creation (won't trigger onConnect callback)
550
+ const node1 = connector.nodes[0];
551
+ const node2 = connector.nodes[1];
552
+ connector.createConnection(node1, node2, null, null, { silent: true });
553
+
554
+ // Silent disconnection (won't trigger onDisconnect callback)
555
+ connector.disconnect("connection-id", { silent: true });
556
+
557
+ // Silent destroy (won't trigger callbacks, default behavior)
558
+ connector.destroy(); // Default is silent
559
+ connector.destroy({ silent: false }); // Non-silent destroy (triggers callbacks)
560
+
561
+ // Example: Restore connections from saved data without triggering callbacks
562
+ const savedConnections = [
563
+ { from: "node1", to: "node2", fromDot: "right", toDot: "left" },
564
+ { from: "node2", to: "node3", fromDot: "right", toDot: "left" }
565
+ ];
566
+
567
+ savedConnections.forEach((conn) => {
568
+ const fromNode = connector.nodes.find((n) => n.id === conn.from);
569
+ const toNode = connector.nodes.find((n) => n.id === conn.to);
570
+ const fromDot = fromNode?.dots[conn.fromDot];
571
+ const toDot = toNode?.dots[conn.toDot];
572
+
573
+ if (fromNode && toNode && fromDot && toDot) {
574
+ connector.createConnection(fromNode, toNode, fromDot, toDot, { silent: true });
575
+ }
576
+ });
577
+ ```
578
+
579
+ ### Node Info and Connection Data
580
+
581
+ You can attach custom information to nodes using the `info` parameter, which will be available in connection callbacks.
582
+
583
+ ```javascript
584
+ // Register node with custom info
585
+ const items = [
586
+ { id: "node1", name: "Apple", desc: "This is a red apple", type: "fruit" },
587
+ { id: "node2", name: "Pear", desc: "This is a yellow pear", type: "fruit" }
588
+ ];
589
+
590
+ items.forEach((item) => {
591
+ const nodeElement = document.getElementById(item.id);
592
+ connector.registerNode(item.id, nodeElement, {
593
+ dotPositions: ["left"],
594
+ info: item // Attach custom info to the node
595
+ });
596
+ });
597
+
598
+ // Access node info in connection callbacks
599
+ const connector = new Connector({
600
+ container: container,
601
+ onConnect: async (connection) => {
602
+ console.log("Connection created:", connection);
603
+ console.log("From node info:", connection.fromInfo);
604
+ // { id: "node1", name: "Apple", desc: "This is a red apple", type: "fruit" }
605
+ console.log("To node info:", connection.toInfo);
606
+ // { id: "node2", name: "Pear", desc: "This is a yellow pear", type: "fruit" }
607
+
608
+ // You can use the info for saving to database, validation, etc.
609
+ await saveConnection({
610
+ from: connection.from,
611
+ to: connection.to,
612
+ fromInfo: connection.fromInfo,
613
+ toInfo: connection.toInfo
614
+ });
615
+ },
616
+
617
+ onDisconnect: (connection) => {
618
+ console.log("Connection removed:", connection);
619
+ console.log("From node info:", connection.fromInfo);
620
+ console.log("To node info:", connection.toInfo);
621
+ }
622
+ });
623
+ ```
624
+
529
625
  ### Custom Styling
530
626
 
531
627
  ```javascript
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- /*! node-link v0.0.7 | MIT License */
2
- function t(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,o=Array(e);n<e;n++)o[n]=t[n];return o}function e(t,e,n){return e&&function(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,a(o.key),o)}}(t.prototype,e),Object.defineProperty(t,"prototype",{writable:!1}),t}function n(t,e){var n="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!n){if(Array.isArray(t)||(n=l(t))||e){n&&(t=n);var o=0,i=function(){};return{s:i,n:function(){return o>=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){n=n.call(t)},n:function(){var t=n.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==n.return||n.return()}finally{if(a)throw r}}}}function o(t,e,n){return(e=a(e))in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function i(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(t);e&&(o=o.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),n.push.apply(n,o)}return n}function r(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{};e%2?i(Object(n),!0).forEach(function(e){o(t,e,n[e])}):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach(function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(n,e))})}return t}function s(e){return function(e){if(Array.isArray(e))return t(e)}(e)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(e)||l(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function a(t){var e=function(t,e){if("object"!=typeof t||!t)return t;var n=t[Symbol.toPrimitive];if(void 0!==n){var o=n.call(t,e);if("object"!=typeof o)return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t,"string");return"symbol"==typeof e?e:e+""}function l(e,n){if(e){if("string"==typeof e)return t(e,n);var o={}.toString.call(e).slice(8,-1);return"Object"===o&&e.constructor&&(o=e.constructor.name),"Map"===o||"Set"===o?Array.from(e):"Arguments"===o||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o)?t(e,n):void 0}}var c=function(){return e(function t(){var e=this,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),o(this,"handleNodeDragMove",function(t){if(e.isDraggingNode&&e.draggedNode){var n=e.contentWrapper.getBoundingClientRect(),o=e.viewState.scale,i=(t.clientX-n.left)/o-e.dragOffset.x,r=(t.clientY-n.top)/o-e.dragOffset.y;e.draggedNode.element.style.left="".concat(i,"px"),e.draggedNode.element.style.top="".concat(r,"px"),e.updateNodeConnections(e.draggedNode.id)}}),o(this,"handleNodeDragEnd",function(){e.isDraggingNode=!1,e.draggedNode=null,document.removeEventListener("mousemove",e.handleNodeDragMove),document.removeEventListener("mouseup",e.handleNodeDragEnd)}),o(this,"handleMouseMove",function(t){e.isDragging&&e.updateTempLine(t)}),o(this,"handleMouseUp",function(t){if(e.isDragging){e.isDragging=!1;var n=e.isSnapped?e.snapTarget:e.getNodeAtPosition(t.clientX,t.clientY),o=e.isSnapped?e.snapTargetDot:null;n&&n.id!==e.startNode.id&&e.createConnection(e.startNode,n,e.startDot,o),e.clearSnapHighlight(),e.snapTarget=null,e.snapTargetDot=null,e.isSnapped=!1,e.startDot=null,e.tempLine&&(e.svg.removeChild(e.tempLine),e.tempLine=null),document.removeEventListener("mousemove",e.handleMouseMove),document.removeEventListener("mouseup",e.handleMouseUp)}}),this.container=n.container,this.nodes=[],this.connections=[],this.isDragging=!1,this.isDraggingNode=!1,this.tempLine=null,this.draggedNode=null,this.dragOffset={x:0,y:0},this.onConnect=n.onConnect||function(){},this.onDisconnect=n.onDisconnect||function(){},this.onViewChange=n.onViewChange||function(){},this.config=r({lineColor:n.lineColor||"#155BD4",lineWidth:n.lineWidth||2,dotSize:n.dotSize||12,dotColor:n.dotColor||"#155BD4",deleteButtonSize:n.deleteButtonSize||20,enableNodeDrag:!1!==n.enableNodeDrag,snapDistance:n.snapDistance||20,enableSnap:!1!==n.enableSnap,enableZoom:!1!==n.enableZoom,enablePan:!1!==n.enablePan,minZoom:n.minZoom||.1,maxZoom:n.maxZoom||4,zoomStep:n.zoomStep||.1},n.config),this.snapTarget=null,this.isSnapped=!1,this.viewState={scale:1,translateX:0,translateY:0},this.isPanning=!1,this.panStart={x:0,y:0},this.contentWrapper=null,this.init()},[{key:"init",value:function(){var t=this;if(!this.container)throw new Error("Container element is required");"static"===window.getComputedStyle(this.container).position&&(this.container.style.position="relative"),this.container.style.overflow="hidden",this.contentWrapper=document.createElement("div"),this.contentWrapper.className="connector-content-wrapper",this.contentWrapper.style.cssText="\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n transform-origin: 0 0;\n transition: none;\n ",Array.from(this.container.children).forEach(function(e){t.contentWrapper.appendChild(e)}),this.container.appendChild(this.contentWrapper),this.svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),this.svg.style.position="absolute",this.svg.style.top="0",this.svg.style.left="0",this.svg.style.width="100%",this.svg.style.height="100%",this.svg.style.pointerEvents="none",this.svg.style.zIndex="1",this.contentWrapper.appendChild(this.svg),this.config.enableZoom&&this.bindZoomEvents(),this.config.enablePan&&this.bindPanEvents(),this.bindResizeEvents(),this.updateTransform()}},{key:"updateTransform",value:function(){if(this.contentWrapper){var t=this.viewState,e=t.scale,n=t.translateX,o=t.translateY;this.contentWrapper.style.transform="translate(".concat(n,"px, ").concat(o,"px) scale(").concat(e,")"),this.onViewChange({scale:e,translateX:n,translateY:o})}}},{key:"bindZoomEvents",value:function(){var t=this;this.handleWheel=function(e){e.preventDefault();var n=t.container.getBoundingClientRect(),o=e.clientX-n.left,i=e.clientY-n.top,r=e.deltaY<0?t.config.zoomStep:-t.config.zoomStep,s=Math.max(t.config.minZoom,Math.min(t.config.maxZoom,t.viewState.scale+r));t.zoomAtPoint(s,o,i)},this.container.addEventListener("wheel",this.handleWheel,{passive:!1})}},{key:"bindPanEvents",value:function(){var t=this;this.container.style.cursor="grab",this.handlePanStart=function(e){e.target.classList.contains("connector-dot")||t.isDragging||t.isDraggingNode||(t.getNodeAtPosition(e.clientX,e.clientY)&&t.config.enableNodeDrag||(e.preventDefault(),e.stopPropagation(),t.isPanning=!0,t.panStart={x:e.clientX-t.viewState.translateX,y:e.clientY-t.viewState.translateY},t.container.style.cursor="grabbing"))},this.handlePanMove=function(e){t.isPanning&&(e.preventDefault(),t.viewState.translateX=e.clientX-t.panStart.x,t.viewState.translateY=e.clientY-t.panStart.y,t.updateTransform())},this.handlePanEnd=function(){t.isPanning&&t.stopPan()},this.container.addEventListener("mousedown",this.handlePanStart),document.addEventListener("mousemove",this.handlePanMove),document.addEventListener("mouseup",this.handlePanEnd)}},{key:"stopPan",value:function(){this.isPanning=!1,this.container.style.cursor="grab"}},{key:"bindResizeEvents",value:function(){var t=this,e=null;this.handleResize=function(){e&&clearTimeout(e),e=setTimeout(function(){t.updateAllConnections()},100)},window.addEventListener("resize",this.handleResize),"undefined"!=typeof ResizeObserver&&(this.resizeObserver=new ResizeObserver(function(){e&&clearTimeout(e),e=setTimeout(function(){t.updateAllConnections()},100)}),this.resizeObserver.observe(this.container))}},{key:"zoomAtPoint",value:function(t,e,n){var o=this.viewState.scale,i=(e-this.viewState.translateX)/o,r=(n-this.viewState.translateY)/o;this.viewState.scale=t,this.viewState.translateX=e-i*t,this.viewState.translateY=n-r*t,this.updateTransform()}},{key:"setZoom",value:function(t){var e=this.container.getBoundingClientRect(),n=e.width/2,o=e.height/2;this.zoomAtPoint(t,n,o)}},{key:"getZoom",value:function(){return this.viewState.scale}},{key:"resetView",value:function(){this.viewState.scale=1,this.viewState.translateX=0,this.viewState.translateY=0,this.updateTransform()}},{key:"zoomIn",value:function(){var t=Math.min(this.config.maxZoom,this.viewState.scale+this.config.zoomStep);this.setZoom(t)}},{key:"zoomOut",value:function(){var t=Math.max(this.config.minZoom,this.viewState.scale-this.config.zoomStep);this.setZoom(t)}},{key:"getViewState",value:function(){return r({},this.viewState)}},{key:"setViewState",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};"number"==typeof t.scale&&(this.viewState.scale=Math.max(this.config.minZoom,Math.min(this.config.maxZoom,t.scale))),"number"==typeof t.translateX&&(this.viewState.translateX=t.translateX),"number"==typeof t.translateY&&(this.viewState.translateY=t.translateY),this.updateTransform()}},{key:"registerNode",value:function(t,e){var n=this,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(!this.nodes.find(function(e){return e.id===t})){var i=[];i="both"===o.dotPositions?["left","right"]:Array.isArray(o.dotPositions)?o.dotPositions.filter(function(t){return"left"===t||"right"===t}):[0===this.nodes.length?"right":"left"],i=s(new Set(i)).slice(0,2);var r={};i.forEach(function(t){var o=n.createDot(t);e.appendChild(o),r[t]={element:o,position:t}});var a={id:t,element:e,info:null==o?void 0:o.info,dots:r,dotPositions:i,connections:[]};return this.nodes.push(a),Object.values(r).forEach(function(t){n.bindDotEvents(a,t)}),this.config.enableNodeDrag&&this.bindNodeDragEvents(a),a}console.warn("节点 ".concat(t," 已存在"))}},{key:"createDot",value:function(t){var e=document.createElement("div");e.className="connector-dot";var n="right"===t?"right: -".concat(this.config.dotSize/2,"px;"):"left: -".concat(this.config.dotSize/2,"px;");return e.style.cssText="\n position: absolute;\n width: ".concat(this.config.dotSize,"px;\n height: ").concat(this.config.dotSize,"px;\n background-color: ").concat(this.config.dotColor,";\n border: 2px solid white;\n border-radius: 50%;\n cursor: pointer;\n ").concat(n,"\n top: 50%;\n transform: translateY(-50%);\n z-index: 10;\n transition: transform 0.2s;\n "),e.dataset.baseTransform="translateY(-50%)",e.addEventListener("mouseenter",function(){e.style.transform="translateY(-50%) scale(1.2)"}),e.addEventListener("mouseleave",function(){e.style.transform="translateY(-50%) scale(1)"}),e}},{key:"bindDotEvents",value:function(t,e){var n=this;e.element.addEventListener("mousedown",function(o){o.preventDefault(),o.stopPropagation(),n.isDragging=!0,n.startNode=t,n.startDot=e,n.tempLine=n.createLine(),n.svg.appendChild(n.tempLine),n.updateTempLine(o),document.addEventListener("mousemove",n.handleMouseMove),document.addEventListener("mouseup",n.handleMouseUp)})}},{key:"bindNodeDragEvents",value:function(t){var e=this,n=t.element;n.addEventListener("mousedown",function(o){if(!o.target.classList.contains("connector-dot")){o.preventDefault(),o.stopPropagation(),e.isDraggingNode=!0,e.draggedNode=t;var i=n.getBoundingClientRect(),r=e.contentWrapper.getBoundingClientRect(),s=e.viewState.scale;e.dragOffset={x:(o.clientX-i.left)/s,y:(o.clientY-i.top)/s};var a=(i.left-r.left)/s,l=(i.top-r.top)/s;n.style.left="".concat(a,"px"),n.style.top="".concat(l,"px"),n.style.right="",n.style.bottom="",document.addEventListener("mousemove",e.handleNodeDragMove),document.addEventListener("mouseup",e.handleNodeDragEnd)}})}},{key:"updateTempLine",value:function(t){if(this.tempLine&&this.startNode&&this.startDot){var e=this.getDotPosition(this.startNode.element,this.startDot.position),n=this.container.getBoundingClientRect(),o=t.clientX-n.left,i=t.clientY-n.top,r=this.viewState,s=r.scale,a={x:(o-r.translateX)/s,y:(i-r.translateY)/s};if(this.config.enableSnap){var l=this.checkSnap(a,this.startNode);l?(a=l.position,this.snapTarget=l.node,this.snapTargetDot=l.dot,this.isSnapped=!0,this.highlightSnapTarget(l.node,l.dot)):(this.isSnapped=!1,this.clearSnapHighlight(),this.snapTarget=null,this.snapTargetDot=null)}this.updateLine(this.tempLine,e,a,this.startDot.position)}}},{key:"createConnection",value:function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,i=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{};if(!n&&t.dots&&(n=t.dots.right||t.dots.left||Object.values(t.dots)[0]),!o&&e.dots&&(o=e.dots.left||e.dots.right||Object.values(e.dots)[0]),!this.connections.find(function(i){return i.fromNode.id===t.id&&i.toNode.id===e.id&&i.fromDot.position===n.position&&i.toDot.position===o.position||i.fromNode.id===e.id&&i.toNode.id===t.id&&i.fromDot.position===o.position&&i.toDot.position===n.position})){var r=this.createLine();this.svg.appendChild(r);var s=this.createDeleteButton(),a={id:"".concat(t.id,"-").concat(e.id,"-").concat(n.position,"-").concat(o.position,"-").concat(Date.now()),fromNode:t,toNode:e,fromDot:n,toDot:o,line:r,deleteButton:s};return this.connections.push(a),t.connections.push(a),e.connections.push(a),this.updateConnection(a),this.bindConnectionEvents(a),i.silent||this.onConnect({from:t.id,fromInfo:t.info,to:e.id,toInfo:e.info,fromDot:n.position,toDot:o.position}),a}console.warn("该连接已存在")}},{key:"updateConnection",value:function(t){if(t&&t.line){var e=this.getDotPosition(t.fromNode.element,t.fromDot.position),n=this.getDotPosition(t.toNode.element,t.toDot.position);if(this.updateLine(t.line,e,n,t.fromDot.position,t.toDot.position),t.hoverPath&&this.updateLine(t.hoverPath,e,n,t.fromDot.position,t.toDot.position),t.deleteButton){var o=this.getBezierMidPoint(e,n,t.fromDot.position,t.toDot.position);t.deleteButton.style.left="".concat(o.x-this.config.deleteButtonSize/2,"px"),t.deleteButton.style.top="".concat(o.y-this.config.deleteButtonSize/2,"px")}}}},{key:"updateNodeConnections",value:function(t){var e=this;this.connections.filter(function(e){return e.fromNode.id===t||e.toNode.id===t}).forEach(function(t){return e.updateConnection(t)})}},{key:"updateAllConnections",value:function(){var t=this;this.connections.forEach(function(e){return t.updateConnection(e)})}},{key:"createLine",value:function(){var t=document.createElementNS("http://www.w3.org/2000/svg","path");return t.setAttribute("stroke",this.config.lineColor),t.setAttribute("stroke-width",this.config.lineWidth),t.setAttribute("fill","none"),t}},{key:"updateLine",value:function(t,e,n){var o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"right",i=arguments.length>4&&void 0!==arguments[4]?arguments[4]:"left",r=n.x-e.x,s=n.y-e.y,a=Math.sqrt(r*r+s*s),l=Math.min(.5*a,150),c="right"===o?e.x+l:e.x-l,d="right"===i?n.x+l:n.x-l,u="M ".concat(e.x," ").concat(e.y," C ").concat(c," ").concat(e.y,", ").concat(d," ").concat(n.y,", ").concat(n.x," ").concat(n.y);t.setAttribute("d",u)}},{key:"getBezierMidPoint",value:function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"right",o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"left",i=e.x-t.x,r=e.y-t.y,s=Math.sqrt(i*i+r*r),a=Math.min(.5*s,150),l="right"===n?t.x+a:t.x-a,c=t.y,d="right"===o?e.x+a:e.x-a,u=e.y,h=.5,f=h*h,v=f*h;return{x:.125*t.x+.375*l+.375*d+v*e.x,y:.125*t.y+.375*c+.375*u+v*e.y}}},{key:"createDeleteButton",value:function(){var t=document.createElement("div");return t.className="connector-delete-btn",t.innerHTML="×",t.style.cssText="\n position: absolute;\n width: ".concat(this.config.deleteButtonSize,"px;\n height: ").concat(this.config.deleteButtonSize,"px;\n background-color: #ff4d4f;\n color: white;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n font-size: 16px;\n font-weight: bold;\n z-index: 100;\n opacity: 0;\n transition: opacity 0.2s, transform 0.2s;\n pointer-events: none;\n "),this.contentWrapper.appendChild(t),t.addEventListener("mouseenter",function(){t.style.transform="scale(1.2)"}),t.addEventListener("mouseleave",function(){t.style.transform="scale(1)",t.style.opacity="0",t.style.pointerEvents="none"}),t}},{key:"bindConnectionEvents",value:function(t){var e=this,n=t.line,o=t.deleteButton;n.style.pointerEvents="stroke",n.style.cursor="pointer";var i=document.createElementNS("http://www.w3.org/2000/svg","path");i.setAttribute("stroke","transparent"),i.setAttribute("stroke-width","20"),i.setAttribute("fill","none"),i.style.pointerEvents="stroke",i.style.cursor="pointer",i.setAttribute("d",n.getAttribute("d")),this.svg.insertBefore(i,n),t.hoverPath=i;var r=function(){o.style.opacity="1",o.style.pointerEvents="auto"},s=function(){setTimeout(function(){o.matches(":hover")||(o.style.opacity="0",o.style.pointerEvents="none")},100)};i.addEventListener("mouseenter",r),i.addEventListener("mouseleave",s),n.addEventListener("mouseenter",r),n.addEventListener("mouseleave",s),o.addEventListener("click",function(){e.disconnect(t.id)})}},{key:"disconnect",value:function(t){var e=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(t){var o=this.connections.findIndex(function(e){return e.id===t});if(-1===o)return;var i=this.connections[o],r={from:i.fromNode.id,fromInfo:i.fromNode.info,to:i.toNode.id,toInfo:i.toNode.info,fromDot:i.fromDot.position,toDot:i.toDot.position};i.line&&i.line.parentNode&&this.svg.removeChild(i.line),i.hoverPath&&i.hoverPath.parentNode&&this.svg.removeChild(i.hoverPath),i.deleteButton&&i.deleteButton.parentNode&&i.deleteButton.parentNode.removeChild(i.deleteButton),i.fromNode.connections=i.fromNode.connections.filter(function(e){return e.id!==t}),i.toNode.connections=i.toNode.connections.filter(function(e){return e.id!==t}),this.connections.splice(o,1),n.silent||this.onDisconnect(r)}else{s(this.connections).forEach(function(t){return e.disconnect(t.id,n)})}}},{key:"getElementCenter",value:function(t){var e=t.getBoundingClientRect(),n=this.container.getBoundingClientRect(),o=e.left+e.width/2-n.left,i=e.top+e.height/2-n.top,r=this.viewState,s=r.scale;return{x:(o-r.translateX)/s,y:(i-r.translateY)/s}}},{key:"getDotPosition",value:function(t,e){var n=t.getBoundingClientRect(),o=this.container.getBoundingClientRect(),i="right"===e?n.right-o.left:n.left-o.left,r=n.top+n.height/2-o.top,s=this.viewState,a=s.scale;return{x:(i-s.translateX)/a,y:(r-s.translateY)/a}}},{key:"getNodeAtPosition",value:function(t,e){var o,i=n(this.nodes);try{for(i.s();!(o=i.n()).done;){var r=o.value,s=r.element.getBoundingClientRect();if(t>=s.left&&t<=s.right&&e>=s.top&&e<=s.bottom)return r}}catch(t){i.e(t)}finally{i.f()}return null}},{key:"checkSnap",value:function(t,e){var o=this;if(!this.config.enableSnap)return null;var i,r=null,s=null,a=1/0,l=n(this.nodes);try{var c=function(){var n=i.value;if(n.id===e.id)return 1;n.dots&&Object.values(n.dots).forEach(function(e){var i=o.getDotPosition(n.element,e.position),l=t.x-i.x,c=t.y-i.y,d=Math.sqrt(l*l+c*c);d<o.config.snapDistance&&d<a&&(a=d,r=n,s=e)})};for(l.s();!(i=l.n()).done;)c()}catch(t){l.e(t)}finally{l.f()}return r&&s?{node:r,dot:s,position:this.getDotPosition(r.element,s.position)}:null}},{key:"highlightSnapTarget",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;if(t&&t.element&&(this.clearSnapHighlight(),t.element.style.boxShadow="0 0 0 3px rgba(21, 91, 212, 0.3)",t.element.style.transform="scale(1.05)",t.element.dataset.snapped="true",e&&e.element)){var n=e.element.dataset.baseTransform||"translateY(-50%)";e.element.style.transform="".concat(n," scale(1.5)"),e.element.style.boxShadow="0 0 10px rgba(21, 91, 212, 0.6)",e.element.dataset.highlighted="true"}}},{key:"clearSnapHighlight",value:function(){this.nodes.forEach(function(t){"true"===t.element.dataset.snapped&&(t.element.style.boxShadow="",t.element.style.transform="",delete t.element.dataset.snapped,t.dots&&Object.values(t.dots).forEach(function(t){if("true"===t.element.dataset.highlighted){var e=t.element.dataset.baseTransform||"translateY(-50%)";t.element.style.transform=e,t.element.style.boxShadow="",delete t.element.dataset.highlighted}}))})}},{key:"updateNodePosition",value:function(t){var e=this,n=this.nodes.find(function(e){return e.id===t});n&&(n.dots&&Object.values(n.dots).forEach(function(t){t.coords=e.getDotPosition(n.element,t.position)}),this.updateNodeConnections(t))}},{key:"destroy",value:function(){this.disconnect(null,{silent:!0}),this.nodes.forEach(function(t){t.dots&&Object.values(t.dots).forEach(function(t){t.element&&t.element.parentNode&&t.element.parentNode.removeChild(t.element)})}),this.svg&&this.svg.parentNode&&this.svg.parentNode.removeChild(this.svg),document.removeEventListener("mousemove",this.handleMouseMove),document.removeEventListener("mouseup",this.handleMouseUp),document.removeEventListener("mousemove",this.handleNodeDragMove),document.removeEventListener("mouseup",this.handleNodeDragEnd),this.handleWheel&&this.container.removeEventListener("wheel",this.handleWheel),this.handlePanStart&&this.container.removeEventListener("mousedown",this.handlePanStart),this.handlePanMove&&document.removeEventListener("mousemove",this.handlePanMove),this.handlePanEnd&&document.removeEventListener("mouseup",this.handlePanEnd),this.handleResize&&window.removeEventListener("resize",this.handleResize),this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null),this.nodes=[],this.connections=[]}},{key:"getConnections",value:function(){return this.connections.map(function(t){return{id:t.id,from:t.fromNode.id,to:t.toNode.id,fromDot:t.fromDot.position,toDot:t.toDot.position}})}},{key:"getNodeConnections",value:function(t){return this.connections.filter(function(e){return e.fromNode.id===t||e.toNode.id===t}).map(function(t){return{id:t.id,from:t.fromNode.id,to:t.toNode.id,fromDot:t.fromDot.position,toDot:t.toDot.position}})}}])}();export{c as Connector,c as default};
1
+ /*! node-link v0.0.9 | MIT License */
2
+ function t(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,o=Array(e);n<e;n++)o[n]=t[n];return o}function e(t,e,n){return e&&function(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,a(o.key),o)}}(t.prototype,e),Object.defineProperty(t,"prototype",{writable:!1}),t}function n(t,e){var n="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!n){if(Array.isArray(t)||(n=l(t))||e){n&&(t=n);var o=0,i=function(){};return{s:i,n:function(){return o>=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){n=n.call(t)},n:function(){var t=n.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==n.return||n.return()}finally{if(a)throw r}}}}function o(t,e,n){return(e=a(e))in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function i(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(t);e&&(o=o.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),n.push.apply(n,o)}return n}function r(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{};e%2?i(Object(n),!0).forEach(function(e){o(t,e,n[e])}):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach(function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(n,e))})}return t}function s(e){return function(e){if(Array.isArray(e))return t(e)}(e)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(e)||l(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function a(t){var e=function(t,e){if("object"!=typeof t||!t)return t;var n=t[Symbol.toPrimitive];if(void 0!==n){var o=n.call(t,e);if("object"!=typeof o)return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t,"string");return"symbol"==typeof e?e:e+""}function l(e,n){if(e){if("string"==typeof e)return t(e,n);var o={}.toString.call(e).slice(8,-1);return"Object"===o&&e.constructor&&(o=e.constructor.name),"Map"===o||"Set"===o?Array.from(e):"Arguments"===o||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o)?t(e,n):void 0}}var c=function(){return e(function t(){var e=this,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),o(this,"handleNodeDragMove",function(t){if(e.isDraggingNode&&e.draggedNode){var n=e.contentWrapper.getBoundingClientRect(),o=e.viewState.scale,i=(t.clientX-n.left)/o-e.dragOffset.x,r=(t.clientY-n.top)/o-e.dragOffset.y;e.draggedNode.element.style.left="".concat(i,"px"),e.draggedNode.element.style.top="".concat(r,"px"),e.updateNodeConnections(e.draggedNode.id)}}),o(this,"handleNodeDragEnd",function(){e.isDraggingNode=!1,e.draggedNode=null,document.removeEventListener("mousemove",e.handleNodeDragMove),document.removeEventListener("mouseup",e.handleNodeDragEnd)}),o(this,"handleMouseMove",function(t){e.isDragging&&e.updateTempLine(t)}),o(this,"handleMouseUp",function(t){if(e.isDragging){e.isDragging=!1;var n=e.isSnapped?e.snapTarget:e.getNodeAtPosition(t.clientX,t.clientY),o=e.isSnapped?e.snapTargetDot:null;n&&n.id!==e.startNode.id&&e.createConnection(e.startNode,n,e.startDot,o),e.clearSnapHighlight(),e.snapTarget=null,e.snapTargetDot=null,e.isSnapped=!1,e.startDot=null,e.tempLine&&(e.svg.removeChild(e.tempLine),e.tempLine=null),document.removeEventListener("mousemove",e.handleMouseMove),document.removeEventListener("mouseup",e.handleMouseUp)}}),this.container=n.container,this.nodes=[],this.connections=[],this.isDragging=!1,this.isDraggingNode=!1,this.tempLine=null,this.draggedNode=null,this.dragOffset={x:0,y:0},this.onConnect=n.onConnect||function(){},this.onDisconnect=n.onDisconnect||function(){},this.onViewChange=n.onViewChange||function(){},this.config=r({lineColor:n.lineColor||"#155BD4",lineWidth:n.lineWidth||2,dotSize:n.dotSize||12,dotColor:n.dotColor||"#155BD4",dotHoverScale:n.dotHoverScale||1.8,deleteButtonSize:n.deleteButtonSize||20,enableNodeDrag:!1!==n.enableNodeDrag,snapDistance:n.snapDistance||20,enableSnap:!1!==n.enableSnap,enableZoom:!1!==n.enableZoom,enablePan:!1!==n.enablePan,minZoom:n.minZoom||.1,maxZoom:n.maxZoom||4,zoomStep:n.zoomStep||.1},n.config),this.snapTarget=null,this.isSnapped=!1,this.viewState={scale:1,translateX:0,translateY:0},this.isPanning=!1,this.panStart={x:0,y:0},this.contentWrapper=null,this.init()},[{key:"init",value:function(){var t=this;if(!this.container)throw new Error("Container element is required");"static"===window.getComputedStyle(this.container).position&&(this.container.style.position="relative"),this.container.style.overflow="hidden",this.contentWrapper=document.createElement("div"),this.contentWrapper.className="connector-content-wrapper",this.contentWrapper.style.cssText="\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n transform-origin: 0 0;\n transition: none;\n ",Array.from(this.container.children).forEach(function(e){t.contentWrapper.appendChild(e)}),this.container.appendChild(this.contentWrapper),this.svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),this.svg.style.position="absolute",this.svg.style.top="0",this.svg.style.left="0",this.svg.style.width="100%",this.svg.style.height="100%",this.svg.style.pointerEvents="none",this.svg.style.zIndex="1",this.contentWrapper.appendChild(this.svg),this.config.enableZoom&&this.bindZoomEvents(),this.config.enablePan&&this.bindPanEvents(),this.bindResizeEvents(),this.updateTransform()}},{key:"updateTransform",value:function(){if(this.contentWrapper){var t=this.viewState,e=t.scale,n=t.translateX,o=t.translateY;this.contentWrapper.style.transform="translate(".concat(n,"px, ").concat(o,"px) scale(").concat(e,")"),this.onViewChange({scale:e,translateX:n,translateY:o})}}},{key:"bindZoomEvents",value:function(){var t=this;this.handleWheel=function(e){e.preventDefault();var n=t.container.getBoundingClientRect(),o=e.clientX-n.left,i=e.clientY-n.top,r=e.deltaY<0?t.config.zoomStep:-t.config.zoomStep,s=Math.max(t.config.minZoom,Math.min(t.config.maxZoom,t.viewState.scale+r));t.zoomAtPoint(s,o,i)},this.container.addEventListener("wheel",this.handleWheel,{passive:!1})}},{key:"bindPanEvents",value:function(){var t=this;this.container.style.cursor="grab",this.handlePanStart=function(e){e.target.classList.contains("connector-dot")||t.isDragging||t.isDraggingNode||(t.getNodeAtPosition(e.clientX,e.clientY)&&t.config.enableNodeDrag||(e.preventDefault(),e.stopPropagation(),t.isPanning=!0,t.panStart={x:e.clientX-t.viewState.translateX,y:e.clientY-t.viewState.translateY},t.container.style.cursor="grabbing"))},this.handlePanMove=function(e){t.isPanning&&(e.preventDefault(),t.viewState.translateX=e.clientX-t.panStart.x,t.viewState.translateY=e.clientY-t.panStart.y,t.updateTransform())},this.handlePanEnd=function(){t.isPanning&&t.stopPan()},this.container.addEventListener("mousedown",this.handlePanStart),document.addEventListener("mousemove",this.handlePanMove),document.addEventListener("mouseup",this.handlePanEnd)}},{key:"stopPan",value:function(){this.isPanning=!1,this.container.style.cursor="grab"}},{key:"bindResizeEvents",value:function(){var t=this,e=null;this.handleResize=function(){e&&clearTimeout(e),e=setTimeout(function(){t.updateAllConnections()},100)},window.addEventListener("resize",this.handleResize),"undefined"!=typeof ResizeObserver&&(this.resizeObserver=new ResizeObserver(function(){e&&clearTimeout(e),e=setTimeout(function(){t.updateAllConnections()},100)}),this.resizeObserver.observe(this.container))}},{key:"zoomAtPoint",value:function(t,e,n){var o=this.viewState.scale,i=(e-this.viewState.translateX)/o,r=(n-this.viewState.translateY)/o;this.viewState.scale=t,this.viewState.translateX=e-i*t,this.viewState.translateY=n-r*t,this.updateTransform()}},{key:"setZoom",value:function(t){var e=this.container.getBoundingClientRect(),n=e.width/2,o=e.height/2;this.zoomAtPoint(t,n,o)}},{key:"getZoom",value:function(){return this.viewState.scale}},{key:"resetView",value:function(){this.viewState.scale=1,this.viewState.translateX=0,this.viewState.translateY=0,this.updateTransform()}},{key:"zoomIn",value:function(){var t=Math.min(this.config.maxZoom,this.viewState.scale+this.config.zoomStep);this.setZoom(t)}},{key:"zoomOut",value:function(){var t=Math.max(this.config.minZoom,this.viewState.scale-this.config.zoomStep);this.setZoom(t)}},{key:"getViewState",value:function(){return r({},this.viewState)}},{key:"setViewState",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};"number"==typeof t.scale&&(this.viewState.scale=Math.max(this.config.minZoom,Math.min(this.config.maxZoom,t.scale))),"number"==typeof t.translateX&&(this.viewState.translateX=t.translateX),"number"==typeof t.translateY&&(this.viewState.translateY=t.translateY),this.updateTransform()}},{key:"registerNode",value:function(t,e){var n=this,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(!this.nodes.find(function(e){return e.id===t})){var i=[];i="both"===o.dotPositions?["left","right"]:Array.isArray(o.dotPositions)?o.dotPositions.filter(function(t){return"left"===t||"right"===t}):[0===this.nodes.length?"right":"left"],i=s(new Set(i)).slice(0,2);var r={};i.forEach(function(t){var o=n.createDot(t);e.appendChild(o),r[t]={element:o,position:t}});var a={id:t,element:e,info:null==o?void 0:o.info,dots:r,dotPositions:i,connections:[]};return this.nodes.push(a),Object.values(r).forEach(function(t){n.bindDotEvents(a,t)}),this.config.enableNodeDrag&&this.bindNodeDragEvents(a),a}console.warn("节点 ".concat(t," 已存在"))}},{key:"createDot",value:function(t){var e=this,n=document.createElement("div");n.className="connector-dot";var o="right"===t?"right: -".concat(this.config.dotSize/2,"px;"):"left: -".concat(this.config.dotSize/2,"px;");return n.style.cssText="\n position: absolute;\n width: ".concat(this.config.dotSize,"px;\n height: ").concat(this.config.dotSize,"px;\n background-color: ").concat(this.config.dotColor,";\n border: 2px solid white;\n border-radius: 50%;\n cursor: pointer;\n ").concat(o,"\n top: 50%;\n transform: translateY(-50%);\n z-index: 10;\n transition: transform 0.2s;\n "),n.dataset.baseTransform="translateY(-50%)",n.addEventListener("mouseenter",function(){n.style.transform="translateY(-50%) scale(".concat(e.config.dotHoverScale,")")}),n.addEventListener("mouseleave",function(){n.style.transform="translateY(-50%) scale(1)"}),n}},{key:"bindDotEvents",value:function(t,e){var n=this;e.element.addEventListener("mousedown",function(o){o.preventDefault(),o.stopPropagation(),n.isDragging=!0,n.startNode=t,n.startDot=e,n.tempLine=n.createLine(),n.svg.appendChild(n.tempLine),n.updateTempLine(o),document.addEventListener("mousemove",n.handleMouseMove),document.addEventListener("mouseup",n.handleMouseUp)})}},{key:"bindNodeDragEvents",value:function(t){var e=this,n=t.element;n.addEventListener("mousedown",function(o){if(!o.target.classList.contains("connector-dot")){o.preventDefault(),o.stopPropagation(),e.isDraggingNode=!0,e.draggedNode=t;var i=n.getBoundingClientRect(),r=e.contentWrapper.getBoundingClientRect(),s=e.viewState.scale;e.dragOffset={x:(o.clientX-i.left)/s,y:(o.clientY-i.top)/s};var a=(i.left-r.left)/s,l=(i.top-r.top)/s;n.style.left="".concat(a,"px"),n.style.top="".concat(l,"px"),n.style.right="",n.style.bottom="",document.addEventListener("mousemove",e.handleNodeDragMove),document.addEventListener("mouseup",e.handleNodeDragEnd)}})}},{key:"updateTempLine",value:function(t){if(this.tempLine&&this.startNode&&this.startDot){var e=this.getDotPosition(this.startNode.element,this.startDot.position),n=this.container.getBoundingClientRect(),o=t.clientX-n.left,i=t.clientY-n.top,r=this.viewState,s=r.scale,a={x:(o-r.translateX)/s,y:(i-r.translateY)/s};if(this.config.enableSnap){var l=this.checkSnap(a,this.startNode);l?(a=l.position,this.snapTarget=l.node,this.snapTargetDot=l.dot,this.isSnapped=!0,this.highlightSnapTarget(l.node,l.dot)):(this.isSnapped=!1,this.clearSnapHighlight(),this.snapTarget=null,this.snapTargetDot=null)}this.updateLine(this.tempLine,e,a,this.startDot.position)}}},{key:"createConnection",value:function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,i=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{};if(!n&&t.dots&&(n=t.dots.right||t.dots.left||Object.values(t.dots)[0]),!o&&e.dots&&(o=e.dots.left||e.dots.right||Object.values(e.dots)[0]),!this.connections.find(function(i){return i.fromNode.id===t.id&&i.toNode.id===e.id&&i.fromDot.position===n.position&&i.toDot.position===o.position||i.fromNode.id===e.id&&i.toNode.id===t.id&&i.fromDot.position===o.position&&i.toDot.position===n.position})){var r=this.createLine();this.svg.appendChild(r);var s=this.createDeleteButton(),a={id:"".concat(t.id,"-").concat(e.id,"-").concat(n.position,"-").concat(o.position,"-").concat(Date.now()),fromNode:t,toNode:e,fromDot:n,toDot:o,line:r,deleteButton:s};return this.connections.push(a),t.connections.push(a),e.connections.push(a),this.updateConnection(a),this.bindConnectionEvents(a),i.silent||this.onConnect({from:t.id,fromInfo:t.info,to:e.id,toInfo:e.info,fromDot:n.position,toDot:o.position}),a}console.warn("该连接已存在")}},{key:"updateConnection",value:function(t){if(t&&t.line){var e=this.getDotPosition(t.fromNode.element,t.fromDot.position),n=this.getDotPosition(t.toNode.element,t.toDot.position);if(this.updateLine(t.line,e,n,t.fromDot.position,t.toDot.position),t.hoverPath&&this.updateLine(t.hoverPath,e,n,t.fromDot.position,t.toDot.position),t.deleteButton){var o=this.getBezierMidPoint(e,n,t.fromDot.position,t.toDot.position);t.deleteButton.style.left="".concat(o.x-this.config.deleteButtonSize/2,"px"),t.deleteButton.style.top="".concat(o.y-this.config.deleteButtonSize/2,"px")}}}},{key:"updateNodeConnections",value:function(t){var e=this;this.connections.filter(function(e){return e.fromNode.id===t||e.toNode.id===t}).forEach(function(t){return e.updateConnection(t)})}},{key:"updateAllConnections",value:function(){var t=this;this.connections.forEach(function(e){return t.updateConnection(e)})}},{key:"createLine",value:function(){var t=document.createElementNS("http://www.w3.org/2000/svg","path");return t.setAttribute("stroke",this.config.lineColor),t.setAttribute("stroke-width",this.config.lineWidth),t.setAttribute("fill","none"),t}},{key:"updateLine",value:function(t,e,n){var o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"right",i=arguments.length>4&&void 0!==arguments[4]?arguments[4]:"left",r=n.x-e.x,s=n.y-e.y,a=Math.sqrt(r*r+s*s),l=Math.min(.5*a,150),c="right"===o?e.x+l:e.x-l,d="right"===i?n.x+l:n.x-l,u="M ".concat(e.x," ").concat(e.y," C ").concat(c," ").concat(e.y,", ").concat(d," ").concat(n.y,", ").concat(n.x," ").concat(n.y);t.setAttribute("d",u)}},{key:"getBezierMidPoint",value:function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"right",o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"left",i=e.x-t.x,r=e.y-t.y,s=Math.sqrt(i*i+r*r),a=Math.min(.5*s,150),l="right"===n?t.x+a:t.x-a,c=t.y,d="right"===o?e.x+a:e.x-a,u=e.y,h=.5,f=h*h,v=f*h;return{x:.125*t.x+.375*l+.375*d+v*e.x,y:.125*t.y+.375*c+.375*u+v*e.y}}},{key:"createDeleteButton",value:function(){var t=document.createElement("div");return t.className="connector-delete-btn",t.innerHTML="×",t.style.cssText="\n position: absolute;\n width: ".concat(this.config.deleteButtonSize,"px;\n height: ").concat(this.config.deleteButtonSize,"px;\n background-color: #ff4d4f;\n color: white;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n font-size: 16px;\n font-weight: bold;\n z-index: 100;\n opacity: 0;\n transition: opacity 0.2s, transform 0.2s;\n pointer-events: none;\n "),this.contentWrapper.appendChild(t),t.addEventListener("mouseenter",function(){t.style.transform="scale(1.2)"}),t.addEventListener("mouseleave",function(){t.style.transform="scale(1)",t.style.opacity="0",t.style.pointerEvents="none"}),t}},{key:"bindConnectionEvents",value:function(t){var e=this,n=t.line,o=t.deleteButton;n.style.pointerEvents="stroke",n.style.cursor="pointer";var i=document.createElementNS("http://www.w3.org/2000/svg","path");i.setAttribute("stroke","transparent"),i.setAttribute("stroke-width","20"),i.setAttribute("fill","none"),i.style.pointerEvents="stroke",i.style.cursor="pointer",i.setAttribute("d",n.getAttribute("d")),this.svg.insertBefore(i,n),t.hoverPath=i;var r=function(){o.style.opacity="1",o.style.pointerEvents="auto"},s=function(){setTimeout(function(){o.matches(":hover")||(o.style.opacity="0",o.style.pointerEvents="none")},100)};i.addEventListener("mouseenter",r),i.addEventListener("mouseleave",s),n.addEventListener("mouseenter",r),n.addEventListener("mouseleave",s),o.addEventListener("click",function(){e.disconnect(t.id)})}},{key:"disconnect",value:function(t){var e=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(t){var o=this.connections.findIndex(function(e){return e.id===t});if(-1===o)return;var i=this.connections[o],r={from:i.fromNode.id,fromInfo:i.fromNode.info,to:i.toNode.id,toInfo:i.toNode.info,fromDot:i.fromDot.position,toDot:i.toDot.position};i.line&&i.line.parentNode&&this.svg.removeChild(i.line),i.hoverPath&&i.hoverPath.parentNode&&this.svg.removeChild(i.hoverPath),i.deleteButton&&i.deleteButton.parentNode&&i.deleteButton.parentNode.removeChild(i.deleteButton),i.fromNode.connections=i.fromNode.connections.filter(function(e){return e.id!==t}),i.toNode.connections=i.toNode.connections.filter(function(e){return e.id!==t}),this.connections.splice(o,1),n.silent||this.onDisconnect(r)}else{s(this.connections).forEach(function(t){return e.disconnect(t.id,n)})}}},{key:"getElementCenter",value:function(t){var e=t.getBoundingClientRect(),n=this.container.getBoundingClientRect(),o=e.left+e.width/2-n.left,i=e.top+e.height/2-n.top,r=this.viewState,s=r.scale;return{x:(o-r.translateX)/s,y:(i-r.translateY)/s}}},{key:"getDotPosition",value:function(t,e){var n=t.getBoundingClientRect(),o=this.container.getBoundingClientRect(),i="right"===e?n.right-o.left:n.left-o.left,r=n.top+n.height/2-o.top,s=this.viewState,a=s.scale;return{x:(i-s.translateX)/a,y:(r-s.translateY)/a}}},{key:"getNodeAtPosition",value:function(t,e){var o,i=n(this.nodes);try{for(i.s();!(o=i.n()).done;){var r=o.value,s=r.element.getBoundingClientRect();if(t>=s.left&&t<=s.right&&e>=s.top&&e<=s.bottom)return r}}catch(t){i.e(t)}finally{i.f()}return null}},{key:"checkSnap",value:function(t,e){var o=this;if(!this.config.enableSnap)return null;var i,r=null,s=null,a=1/0,l=n(this.nodes);try{var c=function(){var n=i.value;if(n.id===e.id)return 1;n.dots&&Object.values(n.dots).forEach(function(e){var i=o.getDotPosition(n.element,e.position),l=t.x-i.x,c=t.y-i.y,d=Math.sqrt(l*l+c*c);d<o.config.snapDistance&&d<a&&(a=d,r=n,s=e)})};for(l.s();!(i=l.n()).done;)c()}catch(t){l.e(t)}finally{l.f()}return r&&s?{node:r,dot:s,position:this.getDotPosition(r.element,s.position)}:null}},{key:"highlightSnapTarget",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;if(t&&t.element&&(this.clearSnapHighlight(),t.element.style.boxShadow="0 0 0 3px rgba(21, 91, 212, 0.3)",t.element.style.transform="scale(1.05)",t.element.dataset.snapped="true",e&&e.element)){var n=e.element.dataset.baseTransform||"translateY(-50%)";e.element.style.transform="".concat(n," scale(1.5)"),e.element.style.boxShadow="0 0 10px rgba(21, 91, 212, 0.6)",e.element.dataset.highlighted="true"}}},{key:"clearSnapHighlight",value:function(){this.nodes.forEach(function(t){"true"===t.element.dataset.snapped&&(t.element.style.boxShadow="",t.element.style.transform="",delete t.element.dataset.snapped,t.dots&&Object.values(t.dots).forEach(function(t){if("true"===t.element.dataset.highlighted){var e=t.element.dataset.baseTransform||"translateY(-50%)";t.element.style.transform=e,t.element.style.boxShadow="",delete t.element.dataset.highlighted}}))})}},{key:"updateNodePosition",value:function(t){var e=this,n=this.nodes.find(function(e){return e.id===t});n&&(n.dots&&Object.values(n.dots).forEach(function(t){t.coords=e.getDotPosition(n.element,t.position)}),this.updateNodeConnections(t))}},{key:"destroy",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.disconnect(null,{silent:t.silent||!0}),this.nodes.forEach(function(t){t.dots&&Object.values(t.dots).forEach(function(t){t.element&&t.element.parentNode&&t.element.parentNode.removeChild(t.element)})}),this.svg&&this.svg.parentNode&&this.svg.parentNode.removeChild(this.svg),document.removeEventListener("mousemove",this.handleMouseMove),document.removeEventListener("mouseup",this.handleMouseUp),document.removeEventListener("mousemove",this.handleNodeDragMove),document.removeEventListener("mouseup",this.handleNodeDragEnd),this.handleWheel&&this.container.removeEventListener("wheel",this.handleWheel),this.handlePanStart&&this.container.removeEventListener("mousedown",this.handlePanStart),this.handlePanMove&&document.removeEventListener("mousemove",this.handlePanMove),this.handlePanEnd&&document.removeEventListener("mouseup",this.handlePanEnd),this.handleResize&&window.removeEventListener("resize",this.handleResize),this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null),this.nodes=[],this.connections=[]}},{key:"getConnections",value:function(){return this.connections.map(function(t){return{id:t.id,from:t.fromNode.id,to:t.toNode.id,fromDot:t.fromDot.position,toDot:t.toDot.position}})}},{key:"getNodeConnections",value:function(t){return this.connections.filter(function(e){return e.fromNode.id===t||e.toNode.id===t}).map(function(t){return{id:t.id,from:t.fromNode.id,to:t.toNode.id,fromDot:t.fromDot.position,toDot:t.toDot.position}})}}])}();export{c as Connector,c as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "power-link",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "A pure JavaScript visual node connector for creating draggable connections between nodes. Framework-agnostic and easy to use",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",