power-link 0.0.5 → 0.0.7
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 +140 -26
- package/dist/index.js +2 -2
- package/package.json +2 -3
- package/images/screen-shot.png +0 -0
- package/images/video.mp4 +0 -0
package/README.md
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# power-link
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/power-link)
|
|
4
|
+
[](https://github.com/Tem-man/power-link/blob/main)
|
|
5
5
|
|
|
6
6
|
A pure JavaScript visual node connector for creating draggable connections between nodes. Framework-agnostic and easy to use.
|
|
7
7
|
|
|
8
|
-

|
|
9
9
|
|
|
10
10
|
### 📹 Demo Video
|
|
11
11
|
|
|
12
12
|
<video width="100%" controls>
|
|
13
|
-
<source src="https://github.com/Tem-man/
|
|
13
|
+
<source src="https://github.com/Tem-man/power-link/blob/main/public/images/video.mp4" type="video/mp4">
|
|
14
14
|
Your browser does not support the video tag.
|
|
15
15
|
</video>
|
|
16
16
|
|
|
@@ -74,7 +74,7 @@ const connector = new Connector({
|
|
|
74
74
|
|
|
75
75
|
onDisconnect: (connection) => {
|
|
76
76
|
console.log("Connection removed:", connection);
|
|
77
|
-
}
|
|
77
|
+
}
|
|
78
78
|
});
|
|
79
79
|
|
|
80
80
|
// 3. Register nodes
|
|
@@ -82,20 +82,33 @@ const node1 = document.getElementById("node1");
|
|
|
82
82
|
const node2 = document.getElementById("node2");
|
|
83
83
|
|
|
84
84
|
connector.registerNode("node1", node1, {
|
|
85
|
-
dotPositions: ["right"]
|
|
85
|
+
dotPositions: ["right"] // Only right connection dot
|
|
86
86
|
});
|
|
87
87
|
|
|
88
88
|
connector.registerNode("node2", node2, {
|
|
89
|
-
dotPositions: ["left", "right"]
|
|
89
|
+
dotPositions: ["left", "right"] // Both left and right dots
|
|
90
90
|
});
|
|
91
91
|
```
|
|
92
92
|
|
|
93
93
|
### HTML Structure
|
|
94
94
|
|
|
95
95
|
```html
|
|
96
|
-
<div
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
<div
|
|
97
|
+
id="connector-container"
|
|
98
|
+
style="position: relative; height: 600px;"
|
|
99
|
+
>
|
|
100
|
+
<div
|
|
101
|
+
id="node1"
|
|
102
|
+
style="position: absolute; left: 100px; top: 100px;"
|
|
103
|
+
>
|
|
104
|
+
Node 1
|
|
105
|
+
</div>
|
|
106
|
+
<div
|
|
107
|
+
id="node2"
|
|
108
|
+
style="position: absolute; left: 400px; top: 100px;"
|
|
109
|
+
>
|
|
110
|
+
Node 2
|
|
111
|
+
</div>
|
|
99
112
|
</div>
|
|
100
113
|
```
|
|
101
114
|
|
|
@@ -114,6 +127,11 @@ connector.registerNode("node2", node2, {
|
|
|
114
127
|
| `enableNodeDrag` | Boolean | `true` | Enable node dragging |
|
|
115
128
|
| `enableSnap` | Boolean | `true` | Enable connection snapping |
|
|
116
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%) |
|
|
117
135
|
| `onConnect` | Function | `() => {}` | Callback when connection is created |
|
|
118
136
|
| `onDisconnect` | Function | `() => {}` | Callback when connection is removed |
|
|
119
137
|
|
|
@@ -133,6 +151,7 @@ Register a node for connection.
|
|
|
133
151
|
- `['left', 'right']`: Array format, both sides
|
|
134
152
|
- `['left']`: Only left dot
|
|
135
153
|
- `['right']`: Only right dot
|
|
154
|
+
- `info` (Object): Node extraneous information
|
|
136
155
|
|
|
137
156
|
**Returns:** Node object
|
|
138
157
|
|
|
@@ -141,6 +160,11 @@ Register a node for connection.
|
|
|
141
160
|
```javascript
|
|
142
161
|
connector.registerNode("myNode", element, {
|
|
143
162
|
dotPositions: ["right"],
|
|
163
|
+
info: {
|
|
164
|
+
id: "123",
|
|
165
|
+
name: "apple",
|
|
166
|
+
desc: "this is a red apple"
|
|
167
|
+
}
|
|
144
168
|
});
|
|
145
169
|
```
|
|
146
170
|
|
|
@@ -221,15 +245,49 @@ Destroy the connector and clean up all resources.
|
|
|
221
245
|
connector.destroy();
|
|
222
246
|
```
|
|
223
247
|
|
|
248
|
+
#### `setViewState(scale,translateX,translateY)`
|
|
249
|
+
|
|
250
|
+
Set the initial view state
|
|
251
|
+
|
|
252
|
+
**Parameters:**
|
|
253
|
+
|
|
254
|
+
- `scale` (Number): set initial view scale
|
|
255
|
+
- `translateX` (Number): set initial view x-axis translation
|
|
256
|
+
- `translateY` (Number): set initial view y-axis translation
|
|
257
|
+
|
|
258
|
+
**Example:**
|
|
259
|
+
|
|
260
|
+
````javascript
|
|
261
|
+
connector.setViewState({
|
|
262
|
+
scale: 0.8,
|
|
263
|
+
translateX: 50,
|
|
264
|
+
translateY: 30
|
|
265
|
+
})
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
|
|
224
269
|
## 🎨 Usage Examples
|
|
225
270
|
|
|
226
271
|
### Vue 3
|
|
227
272
|
|
|
228
273
|
```vue
|
|
229
274
|
<template>
|
|
230
|
-
<div
|
|
231
|
-
|
|
232
|
-
|
|
275
|
+
<div
|
|
276
|
+
class="container"
|
|
277
|
+
ref="containerRef"
|
|
278
|
+
>
|
|
279
|
+
<div
|
|
280
|
+
class="node"
|
|
281
|
+
ref="node1Ref"
|
|
282
|
+
>
|
|
283
|
+
Node 1
|
|
284
|
+
</div>
|
|
285
|
+
<div
|
|
286
|
+
class="node"
|
|
287
|
+
ref="node2Ref"
|
|
288
|
+
>
|
|
289
|
+
Node 2
|
|
290
|
+
</div>
|
|
233
291
|
</div>
|
|
234
292
|
</template>
|
|
235
293
|
|
|
@@ -251,15 +309,25 @@ connector.destroy();
|
|
|
251
309
|
},
|
|
252
310
|
onDisconnect: (connection) => {
|
|
253
311
|
console.log("Connection removed:", connection);
|
|
254
|
-
}
|
|
312
|
+
}
|
|
255
313
|
});
|
|
256
314
|
|
|
257
315
|
connector.registerNode("node1", node1Ref.value, {
|
|
258
316
|
dotPositions: ["right"],
|
|
317
|
+
info: {
|
|
318
|
+
id: "123",
|
|
319
|
+
name: "apple",
|
|
320
|
+
desc: "this is a red apple"
|
|
321
|
+
}
|
|
259
322
|
});
|
|
260
323
|
|
|
261
324
|
connector.registerNode("node2", node2Ref.value, {
|
|
262
325
|
dotPositions: ["left"],
|
|
326
|
+
info: {
|
|
327
|
+
id: "456",
|
|
328
|
+
name: "pear",
|
|
329
|
+
desc: "this is a yellow pear"
|
|
330
|
+
}
|
|
263
331
|
});
|
|
264
332
|
});
|
|
265
333
|
|
|
@@ -286,7 +354,7 @@ connector.destroy();
|
|
|
286
354
|
cursor: move;
|
|
287
355
|
}
|
|
288
356
|
</style>
|
|
289
|
-
|
|
357
|
+
````
|
|
290
358
|
|
|
291
359
|
### React
|
|
292
360
|
|
|
@@ -310,15 +378,25 @@ function App() {
|
|
|
310
378
|
},
|
|
311
379
|
onDisconnect: (connection) => {
|
|
312
380
|
console.log("Connection removed:", connection);
|
|
313
|
-
}
|
|
381
|
+
}
|
|
314
382
|
});
|
|
315
383
|
|
|
316
384
|
connectorRef.current.registerNode("node1", node1Ref.current, {
|
|
317
385
|
dotPositions: ["right"],
|
|
386
|
+
info: {
|
|
387
|
+
id: "123",
|
|
388
|
+
name: "apple",
|
|
389
|
+
desc: "this is a red apple"
|
|
390
|
+
}
|
|
318
391
|
});
|
|
319
392
|
|
|
320
393
|
connectorRef.current.registerNode("node2", node2Ref.current, {
|
|
321
394
|
dotPositions: ["left"],
|
|
395
|
+
info: {
|
|
396
|
+
id: "456",
|
|
397
|
+
name: "pear",
|
|
398
|
+
desc: "this is a yellow pear"
|
|
399
|
+
}
|
|
322
400
|
});
|
|
323
401
|
|
|
324
402
|
return () => {
|
|
@@ -329,11 +407,20 @@ function App() {
|
|
|
329
407
|
}, []);
|
|
330
408
|
|
|
331
409
|
return (
|
|
332
|
-
<div
|
|
333
|
-
|
|
410
|
+
<div
|
|
411
|
+
ref={containerRef}
|
|
412
|
+
style={{ position: "relative", height: "600px" }}
|
|
413
|
+
>
|
|
414
|
+
<div
|
|
415
|
+
ref={node1Ref}
|
|
416
|
+
style={{ position: "absolute", left: "100px", top: "100px" }}
|
|
417
|
+
>
|
|
334
418
|
Node 1
|
|
335
419
|
</div>
|
|
336
|
-
<div
|
|
420
|
+
<div
|
|
421
|
+
ref={node2Ref}
|
|
422
|
+
style={{ position: "absolute", left: "400px", top: "100px" }}
|
|
423
|
+
>
|
|
337
424
|
Node 2
|
|
338
425
|
</div>
|
|
339
426
|
</div>
|
|
@@ -365,8 +452,20 @@ function App() {
|
|
|
365
452
|
</head>
|
|
366
453
|
<body>
|
|
367
454
|
<div id="container">
|
|
368
|
-
<div
|
|
369
|
-
|
|
455
|
+
<div
|
|
456
|
+
id="node1"
|
|
457
|
+
class="node"
|
|
458
|
+
style="left: 100px; top: 100px;"
|
|
459
|
+
>
|
|
460
|
+
Node 1
|
|
461
|
+
</div>
|
|
462
|
+
<div
|
|
463
|
+
id="node2"
|
|
464
|
+
class="node"
|
|
465
|
+
style="left: 400px; top: 100px;"
|
|
466
|
+
>
|
|
467
|
+
Node 2
|
|
468
|
+
</div>
|
|
370
469
|
</div>
|
|
371
470
|
|
|
372
471
|
<script type="module">
|
|
@@ -376,15 +475,25 @@ function App() {
|
|
|
376
475
|
container: document.getElementById("container"),
|
|
377
476
|
onConnect: (connection) => {
|
|
378
477
|
console.log("Connection created:", connection);
|
|
379
|
-
}
|
|
478
|
+
}
|
|
380
479
|
});
|
|
381
480
|
|
|
382
481
|
connector.registerNode("node1", document.getElementById("node1"), {
|
|
383
482
|
dotPositions: ["right"],
|
|
483
|
+
info: {
|
|
484
|
+
id: "123",
|
|
485
|
+
name: "apple",
|
|
486
|
+
desc: "this is a red apple"
|
|
487
|
+
}
|
|
384
488
|
});
|
|
385
489
|
|
|
386
490
|
connector.registerNode("node2", document.getElementById("node2"), {
|
|
387
491
|
dotPositions: ["left"],
|
|
492
|
+
info: {
|
|
493
|
+
id: "456",
|
|
494
|
+
name: "pear",
|
|
495
|
+
desc: "this is a yellow pear"
|
|
496
|
+
}
|
|
388
497
|
});
|
|
389
498
|
</script>
|
|
390
499
|
</body>
|
|
@@ -398,17 +507,22 @@ function App() {
|
|
|
398
507
|
```javascript
|
|
399
508
|
// Node with both left and right connection points
|
|
400
509
|
connector.registerNode("centerNode", element, {
|
|
401
|
-
dotPositions: ["left", "right"]
|
|
510
|
+
dotPositions: ["left", "right"]
|
|
402
511
|
});
|
|
403
512
|
|
|
404
513
|
// Node with only left connection point
|
|
405
514
|
connector.registerNode("endNode", element, {
|
|
406
515
|
dotPositions: ["left"],
|
|
516
|
+
info: {
|
|
517
|
+
id: "456",
|
|
518
|
+
name: "pear",
|
|
519
|
+
desc: "this is a yellow pear"
|
|
520
|
+
}
|
|
407
521
|
});
|
|
408
522
|
|
|
409
523
|
// Node with only right connection point
|
|
410
524
|
connector.registerNode("startNode", element, {
|
|
411
|
-
dotPositions: ["right"]
|
|
525
|
+
dotPositions: ["right"]
|
|
412
526
|
});
|
|
413
527
|
```
|
|
414
528
|
|
|
@@ -421,7 +535,7 @@ const connector = new Connector({
|
|
|
421
535
|
lineWidth: 3, // Thicker lines
|
|
422
536
|
dotSize: 16, // Larger dots
|
|
423
537
|
dotColor: "#4ECDC4", // Teal dots
|
|
424
|
-
deleteButtonSize: 24
|
|
538
|
+
deleteButtonSize: 24 // Larger delete button
|
|
425
539
|
});
|
|
426
540
|
```
|
|
427
541
|
|
|
@@ -444,7 +558,7 @@ const connector = new Connector({
|
|
|
444
558
|
|
|
445
559
|
// Update database, state, etc.
|
|
446
560
|
removeConnection(connection);
|
|
447
|
-
}
|
|
561
|
+
}
|
|
448
562
|
});
|
|
449
563
|
```
|
|
450
564
|
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! node-link v0.0.
|
|
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 s,r=!0,a=!1;return{s:function(){n=n.call(t)},n:function(){var t=n.next();return r=t.done,t},e:function(t){a=!0,s=t},f:function(){try{r||null==n.return||n.return()}finally{if(a)throw s}}}}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 s(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 r(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=t.clientX-n.left-e.dragOffset.x,i=t.clientY-n.top-e.dragOffset.y;e.draggedNode.element.style.left="".concat(o,"px"),e.draggedNode.element.style.top="".concat(i,"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=s({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.spacePressed=!1,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){if(e.ctrlKey||e.metaKey){e.preventDefault();var n=t.container.getBoundingClientRect(),o=e.clientX-n.left,i=e.clientY-n.top,s=e.deltaY<0?t.config.zoomStep:-t.config.zoomStep,r=Math.max(t.config.minZoom,Math.min(t.config.maxZoom,t.viewState.scale+s));t.zoomAtPoint(r,o,i)}},this.container.addEventListener("wheel",this.handleWheel,{passive:!1})}},{key:"bindPanEvents",value:function(){var t=this;this.handleKeyDown=function(e){"Space"!==e.code||t.spacePressed||t.isDragging||t.isDraggingNode||(e.preventDefault(),t.spacePressed=!0,t.container.style.cursor="grab")},this.handleKeyUp=function(e){"Space"===e.code&&(t.spacePressed=!1,t.container.style.cursor="",t.isPanning&&t.stopPan())},this.handlePanStart=function(e){!t.spacePressed||t.isDragging||t.isDraggingNode||(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()},document.addEventListener("keydown",this.handleKeyDown),document.addEventListener("keyup",this.handleKeyUp),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=this.spacePressed?"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,s=(n-this.viewState.translateY)/o;this.viewState.scale=t,this.viewState.translateX=e-i*t,this.viewState.translateY=n-s*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 s({},this.viewState)}},{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=r(new Set(i)).slice(0,2);var s={};i.forEach(function(t){var o=n.createDot(t);e.appendChild(o),s[t]={element:o,position:t}});var a={id:t,element:e,info:null==o?void 0:o.info,dots:s,dotPositions:i,connections:[]};return this.nodes.push(a),Object.values(s).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")&&!e.spacePressed){o.preventDefault(),o.stopPropagation(),e.isDraggingNode=!0,e.draggedNode=t;var i=n.getBoundingClientRect(),s=e.contentWrapper.getBoundingClientRect();e.dragOffset={x:o.clientX-i.left,y:o.clientY-i.top};var r=i.left-s.left,a=i.top-s.top;n.style.left="".concat(r,"px"),n.style.top="".concat(a,"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,s=this.viewState,r=s.scale,a={x:(o-s.translateX)/r,y:(i-s.translateY)/r};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 s=this.createLine();this.svg.appendChild(s);var r=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:s,deleteButton:r};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",s=n.x-e.x,r=n.y-e.y,a=Math.sqrt(s*s+r*r),l=Math.min(.5*a,150),c="right"===o?e.x+l:e.x-l,d="right"===i?n.x+l:n.x-l,h="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",h)}},{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,s=e.y-t.y,r=Math.sqrt(i*i+s*s),a=Math.min(.5*r,150),l="right"===n?t.x+a:t.x-a,c=t.y,d="right"===o?e.x+a:e.x-a,h=e.y,u=.5,f=u*u,p=f*u;return{x:.125*t.x+.375*l+.375*d+p*e.x,y:.125*t.y+.375*c+.375*h+p*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 s=function(){o.style.opacity="1",o.style.pointerEvents="auto"},r=function(){setTimeout(function(){o.matches(":hover")||(o.style.opacity="0",o.style.pointerEvents="none")},100)};i.addEventListener("mouseenter",s),i.addEventListener("mouseleave",r),n.addEventListener("mouseenter",s),n.addEventListener("mouseleave",r),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],s={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(s)}else{r(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,s=this.viewState,r=s.scale;return{x:(o-s.translateX)/r,y:(i-s.translateY)/r}}},{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,s=n.top+n.height/2-o.top,r=this.viewState,a=r.scale;return{x:(i-r.translateX)/a,y:(s-r.translateY)/a}}},{key:"getNodeAtPosition",value:function(t,e){var o,i=n(this.nodes);try{for(i.s();!(o=i.n()).done;){var s=o.value,r=s.element.getBoundingClientRect();if(t>=r.left&&t<=r.right&&e>=r.top&&e<=r.bottom)return s}}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,s=null,r=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,s=n,r=e)})};for(l.s();!(i=l.n()).done;)c()}catch(t){l.e(t)}finally{l.f()}return s&&r?{node:s,dot:r,position:this.getDotPosition(s.element,r.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.handleKeyDown&&document.removeEventListener("keydown",this.handleKeyDown),this.handleKeyUp&&document.removeEventListener("keyup",this.handleKeyUp),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.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};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "power-link",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
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",
|
|
@@ -12,8 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
"files": [
|
|
14
14
|
"dist",
|
|
15
|
-
"README.md"
|
|
16
|
-
"images"
|
|
15
|
+
"README.md"
|
|
17
16
|
],
|
|
18
17
|
"publishConfig": {
|
|
19
18
|
"access": "public"
|
package/images/screen-shot.png
DELETED
|
Binary file
|
package/images/video.mp4
DELETED
|
Binary file
|