@quantumwake/kgraph 0.1.2 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,1328 +1,3 @@
1
- import React2, { createContext, useContext, useState, useRef, useCallback, useMemo, useEffect } from 'react';
2
- import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
3
-
4
- // src/KGraphCanvas.tsx
5
- var KGraphContext = createContext(null);
6
- function useKGraphContext() {
7
- const ctx = useContext(KGraphContext);
8
- if (!ctx) {
9
- throw new Error("useKGraphContext must be used within a KGraphProvider");
10
- }
11
- return ctx;
12
- }
13
- var KGraphProvider = ({
14
- children,
15
- nodes,
16
- edges,
17
- initialViewport = { x: 0, y: 0, zoom: 1 },
18
- minZoom = 0.1,
19
- maxZoom = 4
20
- }) => {
21
- const [viewport, setViewport] = useState(initialViewport);
22
- const containerRef = useRef(null);
23
- const handlesRef = useRef(/* @__PURE__ */ new Map());
24
- const screenToCanvasPosition = useCallback((screenX, screenY) => {
25
- const rect = containerRef.current?.getBoundingClientRect();
26
- if (!rect) return { x: screenX, y: screenY };
27
- const x = (screenX - rect.left - viewport.x) / viewport.zoom;
28
- const y = (screenY - rect.top - viewport.y) / viewport.zoom;
29
- return { x, y };
30
- }, [viewport]);
31
- const canvasToScreenPosition = useCallback((canvasX, canvasY) => {
32
- const rect = containerRef.current?.getBoundingClientRect();
33
- if (!rect) return { x: canvasX, y: canvasY };
34
- const x = canvasX * viewport.zoom + viewport.x + rect.left;
35
- const y = canvasY * viewport.zoom + viewport.y + rect.top;
36
- return { x, y };
37
- }, [viewport]);
38
- const fitView = useCallback((options) => {
39
- if (nodes.length === 0) return;
40
- const rect = containerRef.current?.getBoundingClientRect();
41
- if (!rect) return;
42
- const padding = options?.padding ?? 0.2;
43
- let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
44
- for (const node of nodes) {
45
- const w = node.width || 200;
46
- const h = node.height || 100;
47
- minX = Math.min(minX, node.position.x);
48
- minY = Math.min(minY, node.position.y);
49
- maxX = Math.max(maxX, node.position.x + w);
50
- maxY = Math.max(maxY, node.position.y + h);
51
- }
52
- const graphWidth = maxX - minX;
53
- const graphHeight = maxY - minY;
54
- if (graphWidth <= 0 || graphHeight <= 0) return;
55
- const availW = rect.width * (1 - padding * 2);
56
- const availH = rect.height * (1 - padding * 2);
57
- const zoom = Math.min(
58
- Math.max(availW / graphWidth, minZoom),
59
- Math.max(availH / graphHeight, minZoom),
60
- maxZoom
61
- );
62
- const clampedZoom = Math.min(Math.max(zoom, minZoom), maxZoom);
63
- const centerX = (minX + maxX) / 2;
64
- const centerY = (minY + maxY) / 2;
65
- setViewport({
66
- x: rect.width / 2 - centerX * clampedZoom,
67
- y: rect.height / 2 - centerY * clampedZoom,
68
- zoom: clampedZoom
69
- });
70
- }, [nodes, minZoom, maxZoom]);
71
- const zoomIn = useCallback(() => {
72
- setViewport((v) => {
73
- const rect = containerRef.current?.getBoundingClientRect();
74
- const newZoom = Math.min(v.zoom * 1.2, maxZoom);
75
- if (!rect) return { ...v, zoom: newZoom };
76
- const cx = rect.width / 2;
77
- const cy = rect.height / 2;
78
- return {
79
- x: cx - (cx - v.x) * (newZoom / v.zoom),
80
- y: cy - (cy - v.y) * (newZoom / v.zoom),
81
- zoom: newZoom
82
- };
83
- });
84
- }, [maxZoom]);
85
- const zoomOut = useCallback(() => {
86
- setViewport((v) => {
87
- const rect = containerRef.current?.getBoundingClientRect();
88
- const newZoom = Math.max(v.zoom / 1.2, minZoom);
89
- if (!rect) return { ...v, zoom: newZoom };
90
- const cx = rect.width / 2;
91
- const cy = rect.height / 2;
92
- return {
93
- x: cx - (cx - v.x) * (newZoom / v.zoom),
94
- y: cy - (cy - v.y) * (newZoom / v.zoom),
95
- zoom: newZoom
96
- };
97
- });
98
- }, [minZoom]);
99
- const zoomTo = useCallback((level) => {
100
- setViewport((v) => {
101
- const rect = containerRef.current?.getBoundingClientRect();
102
- const newZoom = Math.min(Math.max(level, minZoom), maxZoom);
103
- if (!rect) return { ...v, zoom: newZoom };
104
- const cx = rect.width / 2;
105
- const cy = rect.height / 2;
106
- return {
107
- x: cx - (cx - v.x) * (newZoom / v.zoom),
108
- y: cy - (cy - v.y) * (newZoom / v.zoom),
109
- zoom: newZoom
110
- };
111
- });
112
- }, [minZoom, maxZoom]);
113
- const registerHandle = useCallback((info) => {
114
- handlesRef.current.set(`${info.nodeId}:${info.handleId}`, info);
115
- }, []);
116
- const unregisterHandle = useCallback((nodeId, handleId) => {
117
- handlesRef.current.delete(`${nodeId}:${handleId}`);
118
- }, []);
119
- const getHandlePosition = useCallback((nodeId, handleId) => {
120
- return handlesRef.current.get(`${nodeId}:${handleId}`);
121
- }, []);
122
- const getAllHandles = useCallback(() => {
123
- return handlesRef.current;
124
- }, []);
125
- const value = useMemo(() => ({
126
- viewport,
127
- setViewport,
128
- screenToCanvasPosition,
129
- canvasToScreenPosition,
130
- fitView,
131
- zoomIn,
132
- zoomOut,
133
- zoomTo,
134
- registerHandle,
135
- unregisterHandle,
136
- getHandlePosition,
137
- getAllHandles,
138
- containerRef,
139
- nodes,
140
- edges
141
- }), [viewport, screenToCanvasPosition, canvasToScreenPosition, fitView, zoomIn, zoomOut, zoomTo, registerHandle, unregisterHandle, getHandlePosition, getAllHandles, nodes, edges]);
142
- return /* @__PURE__ */ jsx(KGraphContext.Provider, { value, children });
143
- };
144
- var NodeWrapper = ({
145
- node,
146
- nodeComponent: NodeComponent,
147
- onNodesChange,
148
- snapToGrid,
149
- snapGrid,
150
- draggable,
151
- selectable,
152
- onNodeClick,
153
- onConnectionStart,
154
- zoom
155
- }) => {
156
- const wrapperRef = useRef(null);
157
- const dragRef = useRef(null);
158
- const onNodesChangeRef = useRef(onNodesChange);
159
- onNodesChangeRef.current = onNodesChange;
160
- const zoomRef = useRef(zoom);
161
- zoomRef.current = zoom;
162
- const snapRef = useRef({ snapToGrid, snapGrid });
163
- snapRef.current = { snapToGrid, snapGrid };
164
- const { registerHandle, unregisterHandle } = useKGraphContext();
165
- const updateHandlePositions = useCallback(() => {
166
- if (!wrapperRef.current) return;
167
- const handles = wrapperRef.current.querySelectorAll("[data-handleid]");
168
- handles.forEach((el) => {
169
- const handleId = el.getAttribute("data-handleid");
170
- const handleType = el.getAttribute("data-handletype");
171
- const handlePosition = el.getAttribute("data-handleposition");
172
- if (!handleId || !handleType || !handlePosition) return;
173
- const nodeW = wrapperRef.current.offsetWidth;
174
- const nodeH = wrapperRef.current.offsetHeight;
175
- let hx = node.position.x;
176
- let hy = node.position.y;
177
- switch (handlePosition) {
178
- case "top":
179
- hx += nodeW / 2;
180
- break;
181
- case "bottom":
182
- hx += nodeW / 2;
183
- hy += nodeH;
184
- break;
185
- case "left":
186
- hy += nodeH / 2;
187
- break;
188
- case "right":
189
- hx += nodeW;
190
- hy += nodeH / 2;
191
- break;
192
- }
193
- registerHandle({
194
- nodeId: node.id,
195
- handleId,
196
- type: handleType,
197
- position: handlePosition,
198
- x: hx,
199
- y: hy
200
- });
201
- });
202
- }, [node.id, node.position.x, node.position.y, registerHandle]);
203
- useEffect(() => {
204
- if (!wrapperRef.current) return;
205
- const ro = new ResizeObserver((entries) => {
206
- for (const entry of entries) {
207
- const { width, height } = entry.contentRect;
208
- if (width > 0 && height > 0 && (width !== node.width || height !== node.height)) {
209
- onNodesChangeRef.current?.([{
210
- type: "dimensions",
211
- id: node.id,
212
- dimensions: { width, height }
213
- }]);
214
- }
215
- }
216
- updateHandlePositions();
217
- });
218
- ro.observe(wrapperRef.current);
219
- return () => ro.disconnect();
220
- }, [node.id, node.width, node.height, updateHandlePositions]);
221
- useEffect(() => {
222
- updateHandlePositions();
223
- }, [updateHandlePositions]);
224
- useEffect(() => {
225
- return () => {
226
- if (!wrapperRef.current) return;
227
- const handles = wrapperRef.current.querySelectorAll("[data-handleid]");
228
- handles.forEach((el) => {
229
- const handleId = el.getAttribute("data-handleid");
230
- if (handleId) unregisterHandle(node.id, handleId);
231
- });
232
- };
233
- }, [node.id, unregisterHandle]);
234
- const handleMouseDown = useCallback((e) => {
235
- const target = e.target;
236
- if (target.closest("[data-handleid]")) return;
237
- if (target.closest('[role="dialog"]')) return;
238
- if (selectable) {
239
- onNodeClick?.(e, node);
240
- }
241
- if (!draggable) return;
242
- e.stopPropagation();
243
- e.preventDefault();
244
- dragRef.current = {
245
- startX: e.clientX,
246
- startY: e.clientY,
247
- startNodeX: node.position.x,
248
- startNodeY: node.position.y,
249
- isDragging: false,
250
- lastPosition: { x: node.position.x, y: node.position.y }
251
- };
252
- const nodeId = node.id;
253
- const handleMouseMove = (ev) => {
254
- if (!dragRef.current) return;
255
- const currentZoom = zoomRef.current;
256
- const dx = (ev.clientX - dragRef.current.startX) / currentZoom;
257
- const dy = (ev.clientY - dragRef.current.startY) / currentZoom;
258
- if (!dragRef.current.isDragging && (Math.abs(dx) > 2 || Math.abs(dy) > 2)) {
259
- dragRef.current.isDragging = true;
260
- }
261
- if (!dragRef.current.isDragging) return;
262
- let newX = dragRef.current.startNodeX + dx;
263
- let newY = dragRef.current.startNodeY + dy;
264
- const { snapToGrid: snap, snapGrid: grid } = snapRef.current;
265
- if (snap) {
266
- newX = Math.round(newX / grid[0]) * grid[0];
267
- newY = Math.round(newY / grid[1]) * grid[1];
268
- }
269
- dragRef.current.lastPosition = { x: newX, y: newY };
270
- onNodesChangeRef.current?.([{
271
- type: "position",
272
- id: nodeId,
273
- position: { x: newX, y: newY },
274
- dragging: true
275
- }]);
276
- };
277
- const handleMouseUp = () => {
278
- if (dragRef.current?.isDragging) {
279
- onNodesChangeRef.current?.([{
280
- type: "position",
281
- id: nodeId,
282
- position: dragRef.current.lastPosition,
283
- dragging: false
284
- }]);
285
- }
286
- dragRef.current = null;
287
- window.removeEventListener("mousemove", handleMouseMove);
288
- window.removeEventListener("mouseup", handleMouseUp);
289
- };
290
- window.addEventListener("mousemove", handleMouseMove);
291
- window.addEventListener("mouseup", handleMouseUp);
292
- }, [node.id, node.position.x, node.position.y, draggable, selectable, onNodeClick]);
293
- return /* @__PURE__ */ jsx(
294
- "div",
295
- {
296
- ref: wrapperRef,
297
- className: "kgraph-node-wrapper",
298
- style: {
299
- position: "absolute",
300
- left: node.position.x,
301
- top: node.position.y,
302
- cursor: draggable ? "grab" : "default",
303
- userSelect: "none"
304
- },
305
- onMouseDown: handleMouseDown,
306
- children: /* @__PURE__ */ jsx(HandleContext.Provider, { value: { nodeId: node.id, onConnectionStart }, children: /* @__PURE__ */ jsx(
307
- NodeComponent,
308
- {
309
- id: node.id,
310
- data: node.data,
311
- selected: node.selected || false,
312
- type: node.type
313
- }
314
- ) })
315
- }
316
- );
317
- };
318
- var HandleContext = React2.createContext({ nodeId: "" });
319
- var useHandleContext = () => React2.useContext(HandleContext);
320
- var NodeRenderer = ({
321
- nodes,
322
- nodeTypes,
323
- defaultNodeType,
324
- onNodesChange,
325
- snapToGrid,
326
- snapGrid,
327
- draggable,
328
- selectable,
329
- onNodeClick,
330
- onConnectionStart,
331
- zoom
332
- }) => {
333
- const DefaultNode = defaultNodeType || (({ data }) => /* @__PURE__ */ jsx("div", { style: {
334
- padding: "10px 20px",
335
- border: "2px solid #8b5cf6",
336
- borderRadius: 4,
337
- background: "#1a1a2e",
338
- color: "#fff",
339
- fontSize: 14
340
- }, children: data.label || "Node" }));
341
- return /* @__PURE__ */ jsx(Fragment, { children: nodes.filter((n) => !n.hidden).map((node) => {
342
- const Component = nodeTypes[node.type] || DefaultNode;
343
- return /* @__PURE__ */ jsx(
344
- NodeWrapper,
345
- {
346
- node,
347
- nodeComponent: Component,
348
- onNodesChange,
349
- snapToGrid,
350
- snapGrid,
351
- draggable,
352
- selectable,
353
- onNodeClick,
354
- onConnectionStart,
355
- zoom
356
- },
357
- node.id
358
- );
359
- }) });
360
- };
361
- var NodeRenderer_default = NodeRenderer;
362
-
363
- // src/bezier.ts
364
- function getBezierPath({
365
- sourceX,
366
- sourceY,
367
- sourcePosition = "bottom",
368
- targetX,
369
- targetY,
370
- targetPosition = "top",
371
- curvature = 0.25
372
- }) {
373
- const [sourceControlX, sourceControlY] = getControlWithCurvature(
374
- sourcePosition,
375
- sourceX,
376
- sourceY,
377
- targetX,
378
- targetY,
379
- curvature
380
- );
381
- const [targetControlX, targetControlY] = getControlWithCurvature(
382
- targetPosition,
383
- targetX,
384
- targetY,
385
- sourceX,
386
- sourceY,
387
- curvature
388
- );
389
- const path = `M${sourceX},${sourceY} C${sourceControlX},${sourceControlY} ${targetControlX},${targetControlY} ${targetX},${targetY}`;
390
- const labelX = sourceX * 0.125 + sourceControlX * 0.375 + targetControlX * 0.375 + targetX * 0.125;
391
- const labelY = sourceY * 0.125 + sourceControlY * 0.375 + targetControlY * 0.375 + targetY * 0.125;
392
- const offsetX = Math.abs(labelX - sourceX);
393
- const offsetY = Math.abs(labelY - sourceY);
394
- return [path, labelX, labelY, offsetX, offsetY];
395
- }
396
- function calculateControlOffset(distance, curvature) {
397
- if (distance >= 0) {
398
- return 0.5 * distance;
399
- }
400
- return curvature * 25 * Math.sqrt(-distance);
401
- }
402
- function getControlWithCurvature(pos, x1, y1, x2, y2, c) {
403
- switch (pos) {
404
- case "left":
405
- return [x1 - calculateControlOffset(x1 - x2, c), y1];
406
- case "right":
407
- return [x1 + calculateControlOffset(x2 - x1, c), y1];
408
- case "top":
409
- return [x1, y1 - calculateControlOffset(y1 - y2, c)];
410
- case "bottom":
411
- return [x1, y1 + calculateControlOffset(y2 - y1, c)];
412
- default:
413
- return [x1, y1 + calculateControlOffset(y2 - y1, c)];
414
- }
415
- }
416
- var DefaultEdge = ({
417
- sourceX,
418
- sourceY,
419
- targetX,
420
- targetY,
421
- sourcePosition,
422
- targetPosition,
423
- selected
424
- }) => {
425
- const [edgePath] = getBezierPath({
426
- sourceX,
427
- sourceY,
428
- sourcePosition,
429
- targetX,
430
- targetY,
431
- targetPosition
432
- });
433
- return /* @__PURE__ */ jsxs("g", { children: [
434
- /* @__PURE__ */ jsx(
435
- "path",
436
- {
437
- d: edgePath,
438
- fill: "none",
439
- stroke: "transparent",
440
- strokeWidth: 20,
441
- style: { cursor: "pointer" }
442
- }
443
- ),
444
- /* @__PURE__ */ jsx(
445
- "path",
446
- {
447
- d: edgePath,
448
- fill: "none",
449
- stroke: selected ? "#a78bfa" : "#8b5cf6",
450
- strokeWidth: selected ? 2.5 : 1.5,
451
- markerEnd: selected ? "url(#kgraph-arrow-selected)" : "url(#kgraph-arrow)",
452
- style: { cursor: "pointer" }
453
- }
454
- )
455
- ] });
456
- };
457
- function handleIdToPosition(handleId) {
458
- if (!handleId) return "bottom";
459
- const num = handleId.split("-")[1];
460
- switch (num) {
461
- case "1":
462
- return "top";
463
- case "2":
464
- return "left";
465
- case "3":
466
- return "right";
467
- case "4":
468
- return "bottom";
469
- default:
470
- return "bottom";
471
- }
472
- }
473
- var EdgeRenderer = ({
474
- edges,
475
- edgeTypes,
476
- onEdgeClick,
477
- selectedEdgeId
478
- }) => {
479
- const { getHandlePosition, nodes } = useKGraphContext();
480
- return /* @__PURE__ */ jsx("g", { className: "kgraph-edges", children: edges.map((edge) => {
481
- const sourceHandle = getHandlePosition(edge.source, edge.sourceHandle || "source-4");
482
- const targetHandle = getHandlePosition(edge.target, edge.targetHandle || "target-1");
483
- const sourceNode = nodes.find((n) => n.id === edge.source);
484
- const targetNode = nodes.find((n) => n.id === edge.target);
485
- if (!sourceNode && !sourceHandle) return null;
486
- if (!targetNode && !targetHandle) return null;
487
- const sourceX = sourceHandle?.x ?? sourceNode.position.x + (sourceNode.width || 200) / 2;
488
- const sourceY = sourceHandle?.y ?? sourceNode.position.y + (sourceNode.height || 100);
489
- const targetX = targetHandle?.x ?? targetNode.position.x + (targetNode.width || 200) / 2;
490
- const targetY = targetHandle?.y ?? targetNode.position.y;
491
- const sourcePosition = sourceHandle?.position ?? handleIdToPosition(edge.sourceHandle);
492
- const targetPosition = targetHandle?.position ?? handleIdToPosition(edge.targetHandle);
493
- const isSelected = edge.selected || edge.id === selectedEdgeId;
494
- const EdgeComponent = edgeTypes[edge.type || "default"] || edgeTypes["default"] || DefaultEdge;
495
- return /* @__PURE__ */ jsx(
496
- "g",
497
- {
498
- className: "kgraph-edge",
499
- onClick: (e) => onEdgeClick?.(e, edge),
500
- children: /* @__PURE__ */ jsx(
501
- EdgeComponent,
502
- {
503
- id: edge.id,
504
- sourceX,
505
- sourceY,
506
- targetX,
507
- targetY,
508
- sourcePosition,
509
- targetPosition,
510
- selected: isSelected,
511
- data: edge.data,
512
- animated: edge.animated
513
- }
514
- )
515
- },
516
- edge.id
517
- );
518
- }) });
519
- };
520
- var EdgeRenderer_default = EdgeRenderer;
521
- var ConnectionLine = ({
522
- sourceX,
523
- sourceY,
524
- sourcePosition,
525
- targetX,
526
- targetY
527
- }) => {
528
- let targetPosition = "top";
529
- const dx = targetX - sourceX;
530
- const dy = targetY - sourceY;
531
- if (Math.abs(dx) > Math.abs(dy)) {
532
- targetPosition = dx > 0 ? "left" : "right";
533
- } else {
534
- targetPosition = dy > 0 ? "top" : "bottom";
535
- }
536
- const [path] = getBezierPath({
537
- sourceX,
538
- sourceY,
539
- sourcePosition,
540
- targetX,
541
- targetY,
542
- targetPosition
543
- });
544
- return /* @__PURE__ */ jsxs("g", { className: "kgraph-connection-line", children: [
545
- /* @__PURE__ */ jsx(
546
- "path",
547
- {
548
- d: path,
549
- fill: "none",
550
- stroke: "#8b5cf6",
551
- strokeWidth: 2,
552
- strokeDasharray: "6 3",
553
- opacity: 0.8
554
- }
555
- ),
556
- /* @__PURE__ */ jsx(
557
- "circle",
558
- {
559
- cx: targetX,
560
- cy: targetY,
561
- r: 6,
562
- fill: "#8b5cf6",
563
- opacity: 0.6
564
- }
565
- )
566
- ] });
567
- };
568
- var ConnectionLine_default = ConnectionLine;
569
- var DotGrid = ({
570
- viewport,
571
- gap = 32,
572
- color = "rgba(255, 255, 255, 0.15)",
573
- size = 1.5
574
- }) => {
575
- const scaledGap = gap * viewport.zoom;
576
- const scaledSize = size * viewport.zoom;
577
- const patternId = "kgraph-dot-pattern";
578
- const offsetX = viewport.x % scaledGap;
579
- const offsetY = viewport.y % scaledGap;
580
- return /* @__PURE__ */ jsxs(
581
- "svg",
582
- {
583
- className: "kgraph-background",
584
- style: {
585
- position: "absolute",
586
- inset: 0,
587
- width: "100%",
588
- height: "100%",
589
- pointerEvents: "none"
590
- },
591
- children: [
592
- /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx(
593
- "pattern",
594
- {
595
- id: patternId,
596
- x: offsetX,
597
- y: offsetY,
598
- width: scaledGap,
599
- height: scaledGap,
600
- patternUnits: "userSpaceOnUse",
601
- children: /* @__PURE__ */ jsx(
602
- "circle",
603
- {
604
- cx: scaledSize,
605
- cy: scaledSize,
606
- r: scaledSize,
607
- fill: color
608
- }
609
- )
610
- }
611
- ) }),
612
- /* @__PURE__ */ jsx(
613
- "rect",
614
- {
615
- width: "100%",
616
- height: "100%",
617
- fill: `url(#${patternId})`
618
- }
619
- )
620
- ]
621
- }
622
- );
623
- };
624
- var DotGrid_default = DotGrid;
625
- var MiniMap = ({
626
- nodes,
627
- viewport,
628
- width = 200,
629
- height = 150,
630
- nodeColor = "#60a5fa",
631
- maskColor = "rgba(14, 14, 16, 0.9)",
632
- backgroundColor = "#161618",
633
- borderColor = "#333338",
634
- onViewportChange,
635
- containerWidth,
636
- containerHeight
637
- }) => {
638
- const miniMapRef = useRef(null);
639
- const bounds = useMemo(() => {
640
- if (nodes.length === 0) return { minX: 0, minY: 0, maxX: 1e3, maxY: 1e3 };
641
- let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
642
- for (const node of nodes) {
643
- const w = node.width || 200;
644
- const h = node.height || 100;
645
- minX = Math.min(minX, node.position.x);
646
- minY = Math.min(minY, node.position.y);
647
- maxX = Math.max(maxX, node.position.x + w);
648
- maxY = Math.max(maxY, node.position.y + h);
649
- }
650
- const padX = (maxX - minX) * 0.2;
651
- const padY = (maxY - minY) * 0.2;
652
- return {
653
- minX: minX - padX,
654
- minY: minY - padY,
655
- maxX: maxX + padX,
656
- maxY: maxY + padY
657
- };
658
- }, [nodes]);
659
- const graphW = bounds.maxX - bounds.minX;
660
- const graphH = bounds.maxY - bounds.minY;
661
- const scale = Math.min(width / graphW, height / graphH);
662
- const viewRect = useMemo(() => {
663
- const vx = (-viewport.x / viewport.zoom - bounds.minX) * scale;
664
- const vy = (-viewport.y / viewport.zoom - bounds.minY) * scale;
665
- const vw = containerWidth / viewport.zoom * scale;
666
- const vh = containerHeight / viewport.zoom * scale;
667
- return { x: vx, y: vy, width: vw, height: vh };
668
- }, [viewport, bounds, scale, containerWidth, containerHeight]);
669
- const getColor = useCallback((node) => {
670
- if (typeof nodeColor === "function") return nodeColor(node);
671
- return nodeColor;
672
- }, [nodeColor]);
673
- const handleClick = useCallback((e) => {
674
- if (!miniMapRef.current || !onViewportChange) return;
675
- const rect = miniMapRef.current.getBoundingClientRect();
676
- const clickX = e.clientX - rect.left;
677
- const clickY = e.clientY - rect.top;
678
- const canvasX = clickX / scale + bounds.minX;
679
- const canvasY = clickY / scale + bounds.minY;
680
- onViewportChange({
681
- x: -(canvasX * viewport.zoom - containerWidth / 2),
682
- y: -(canvasY * viewport.zoom - containerHeight / 2),
683
- zoom: viewport.zoom
684
- });
685
- }, [bounds, scale, viewport.zoom, containerWidth, containerHeight, onViewportChange]);
686
- return /* @__PURE__ */ jsx(
687
- "div",
688
- {
689
- className: "kgraph-minimap",
690
- style: {
691
- position: "absolute",
692
- bottom: 10,
693
- right: 10,
694
- zIndex: 20,
695
- borderRadius: 2,
696
- overflow: "hidden",
697
- border: `1px solid ${borderColor}`
698
- },
699
- children: /* @__PURE__ */ jsxs(
700
- "svg",
701
- {
702
- ref: miniMapRef,
703
- width,
704
- height,
705
- style: { backgroundColor, display: "block", cursor: "pointer" },
706
- onClick: handleClick,
707
- children: [
708
- nodes.filter((n) => !n.hidden).map((node) => {
709
- const nx = (node.position.x - bounds.minX) * scale;
710
- const ny = (node.position.y - bounds.minY) * scale;
711
- const nw = (node.width || 200) * scale;
712
- const nh = (node.height || 100) * scale;
713
- return /* @__PURE__ */ jsx(
714
- "rect",
715
- {
716
- x: nx,
717
- y: ny,
718
- width: Math.max(nw, 4),
719
- height: Math.max(nh, 3),
720
- fill: getColor(node),
721
- rx: 1
722
- },
723
- node.id
724
- );
725
- }),
726
- /* @__PURE__ */ jsx(
727
- "rect",
728
- {
729
- x: 0,
730
- y: 0,
731
- width,
732
- height: viewRect.y,
733
- fill: maskColor
734
- }
735
- ),
736
- /* @__PURE__ */ jsx(
737
- "rect",
738
- {
739
- x: 0,
740
- y: viewRect.y + viewRect.height,
741
- width,
742
- height: height - viewRect.y - viewRect.height,
743
- fill: maskColor
744
- }
745
- ),
746
- /* @__PURE__ */ jsx(
747
- "rect",
748
- {
749
- x: 0,
750
- y: viewRect.y,
751
- width: viewRect.x,
752
- height: viewRect.height,
753
- fill: maskColor
754
- }
755
- ),
756
- /* @__PURE__ */ jsx(
757
- "rect",
758
- {
759
- x: viewRect.x + viewRect.width,
760
- y: viewRect.y,
761
- width: width - viewRect.x - viewRect.width,
762
- height: viewRect.height,
763
- fill: maskColor
764
- }
765
- ),
766
- /* @__PURE__ */ jsx(
767
- "rect",
768
- {
769
- x: viewRect.x,
770
- y: viewRect.y,
771
- width: viewRect.width,
772
- height: viewRect.height,
773
- fill: "none",
774
- stroke: "rgba(96, 165, 250, 0.5)",
775
- strokeWidth: 1.5
776
- }
777
- )
778
- ]
779
- }
780
- )
781
- }
782
- );
783
- };
784
- var MiniMap_default = MiniMap;
785
- var InnerCanvas = ({
786
- nodes,
787
- edges,
788
- onNodesChange,
789
- onEdgesChange,
790
- onConnect,
791
- onNodeClick,
792
- onEdgeClick,
793
- onPaneClick,
794
- onDrop,
795
- onDragOver,
796
- nodeTypes = {},
797
- edgeTypes = {},
798
- snapToGrid = true,
799
- snapGrid = [16, 16],
800
- panOnDrag = true,
801
- zoomOnScroll = true,
802
- nodesDraggable = true,
803
- nodesConnectable = true,
804
- elementsSelectable = true,
805
- fitView: fitViewOnMount = false,
806
- showMiniMap = true,
807
- showBackground = true,
808
- backgroundGap = 32,
809
- minZoom = 0.1,
810
- maxZoom = 4,
811
- className = "",
812
- style = {},
813
- children
814
- }) => {
815
- const ctx = useKGraphContext();
816
- const { viewport, setViewport, containerRef, screenToCanvasPosition } = ctx;
817
- const panRef = useRef(null);
818
- const [connectionDrag, setConnectionDrag] = useState(null);
819
- const [containerSize, setContainerSize] = useState({ width: 0, height: 0 });
820
- const nodesRef = useRef(nodes);
821
- nodesRef.current = nodes;
822
- const edgesRef = useRef(edges);
823
- edgesRef.current = edges;
824
- const onNodesChangeRef = useRef(onNodesChange);
825
- onNodesChangeRef.current = onNodesChange;
826
- const onEdgesChangeRef = useRef(onEdgesChange);
827
- onEdgesChangeRef.current = onEdgesChange;
828
- const deselectAll = useCallback(() => {
829
- const nodeDeselects = nodesRef.current.filter((n) => n.selected).map((n) => ({ type: "select", id: n.id, selected: false }));
830
- const edgeDeselects = edgesRef.current.filter((e) => e.selected).map((e) => ({ type: "select", id: e.id, selected: false }));
831
- if (nodeDeselects.length) onNodesChangeRef.current?.(nodeDeselects);
832
- if (edgeDeselects.length) onEdgesChangeRef.current?.(edgeDeselects);
833
- }, []);
834
- useEffect(() => {
835
- if (!containerRef.current) return;
836
- const ro = new ResizeObserver((entries) => {
837
- for (const entry of entries) {
838
- setContainerSize({
839
- width: entry.contentRect.width,
840
- height: entry.contentRect.height
841
- });
842
- }
843
- });
844
- ro.observe(containerRef.current);
845
- return () => ro.disconnect();
846
- }, [containerRef]);
847
- useEffect(() => {
848
- if (fitViewOnMount && nodes.length > 0) {
849
- const t = setTimeout(() => ctx.fitView({ padding: 0.2 }), 100);
850
- return () => clearTimeout(t);
851
- }
852
- }, [fitViewOnMount, nodes.length > 0]);
853
- const handlePaneMouseDown = useCallback((e) => {
854
- if (e.target.closest(".kgraph-node-wrapper")) return;
855
- if (e.target.closest(".kgraph-edge-label")) return;
856
- if (!panOnDrag) {
857
- deselectAll();
858
- onPaneClick?.(e);
859
- return;
860
- }
861
- if (e.button !== 0) return;
862
- panRef.current = {
863
- startX: e.clientX,
864
- startY: e.clientY,
865
- startVX: viewport.x,
866
- startVY: viewport.y,
867
- isPanning: false
868
- };
869
- const handleMouseMove = (ev) => {
870
- const pan = panRef.current;
871
- if (!pan) return;
872
- const dx = ev.clientX - pan.startX;
873
- const dy = ev.clientY - pan.startY;
874
- if (!pan.isPanning && (Math.abs(dx) > 3 || Math.abs(dy) > 3)) {
875
- pan.isPanning = true;
876
- }
877
- if (!pan.isPanning) return;
878
- setViewport((v) => ({
879
- ...v,
880
- x: pan.startVX + dx,
881
- y: pan.startVY + dy
882
- }));
883
- };
884
- const handleMouseUp = (ev) => {
885
- if (panRef.current && !panRef.current.isPanning) {
886
- deselectAll();
887
- onPaneClick?.(ev);
888
- }
889
- panRef.current = null;
890
- window.removeEventListener("mousemove", handleMouseMove);
891
- window.removeEventListener("mouseup", handleMouseUp);
892
- };
893
- window.addEventListener("mousemove", handleMouseMove);
894
- window.addEventListener("mouseup", handleMouseUp);
895
- }, [panOnDrag, viewport, setViewport, onPaneClick]);
896
- useEffect(() => {
897
- const el = containerRef.current;
898
- if (!el) return;
899
- const handleWheel = (e) => {
900
- if (!zoomOnScroll) return;
901
- e.preventDefault();
902
- const rect = el.getBoundingClientRect();
903
- const mouseX = e.clientX - rect.left;
904
- const mouseY = e.clientY - rect.top;
905
- setViewport((v) => {
906
- const sensitivity = e.ctrlKey ? 0.01 : 1e-3;
907
- const zoomDelta = -e.deltaY * sensitivity;
908
- const newZoom = Math.min(Math.max(v.zoom * (1 + zoomDelta), minZoom), maxZoom);
909
- return {
910
- x: mouseX - (mouseX - v.x) * (newZoom / v.zoom),
911
- y: mouseY - (mouseY - v.y) * (newZoom / v.zoom),
912
- zoom: newZoom
913
- };
914
- });
915
- };
916
- el.addEventListener("wheel", handleWheel, { passive: false });
917
- return () => el.removeEventListener("wheel", handleWheel);
918
- }, [zoomOnScroll, setViewport, containerRef, minZoom, maxZoom]);
919
- const handleConnectionStart = useCallback((nodeId, handleId, type, e) => {
920
- if (!nodesConnectable) return;
921
- const handle = ctx.getHandlePosition(nodeId, handleId);
922
- if (!handle) return;
923
- setConnectionDrag({
924
- sourceNodeId: nodeId,
925
- sourceHandleId: handleId,
926
- sourcePosition: handle.position,
927
- sourceX: handle.x,
928
- sourceY: handle.y,
929
- mouseX: handle.x,
930
- mouseY: handle.y
931
- });
932
- const handleMouseMove = (ev) => {
933
- const pos = screenToCanvasPosition(ev.clientX, ev.clientY);
934
- setConnectionDrag((prev) => prev ? { ...prev, mouseX: pos.x, mouseY: pos.y } : null);
935
- };
936
- const handleMouseUp = (ev) => {
937
- const target = document.elementFromPoint(ev.clientX, ev.clientY);
938
- const handleEl = target?.closest?.("[data-handleid]");
939
- if (handleEl) {
940
- const targetNodeId = handleEl.getAttribute("data-nodeid");
941
- let targetHandleId = handleEl.getAttribute("data-handleid");
942
- const targetHandleType = handleEl.getAttribute("data-handletype");
943
- if (targetHandleType === "source" && targetHandleId) {
944
- targetHandleId = targetHandleId.replace("source-", "target-");
945
- }
946
- if (targetNodeId && targetHandleId && targetNodeId !== nodeId) {
947
- onConnect?.({
948
- source: nodeId,
949
- target: targetNodeId,
950
- sourceHandle: handleId,
951
- targetHandle: targetHandleId
952
- });
953
- }
954
- }
955
- setConnectionDrag(null);
956
- window.removeEventListener("mousemove", handleMouseMove);
957
- window.removeEventListener("mouseup", handleMouseUp);
958
- };
959
- window.addEventListener("mousemove", handleMouseMove);
960
- window.addEventListener("mouseup", handleMouseUp);
961
- }, [nodesConnectable, ctx, screenToCanvasPosition, onConnect]);
962
- const handleDragOver = useCallback((e) => {
963
- e.preventDefault();
964
- e.dataTransfer.dropEffect = "move";
965
- onDragOver?.(e);
966
- }, [onDragOver]);
967
- const handleDrop = useCallback((e) => {
968
- e.preventDefault();
969
- const position = screenToCanvasPosition(e.clientX, e.clientY);
970
- onDrop?.(e, position);
971
- }, [screenToCanvasPosition, onDrop]);
972
- const handleNodeClick = useCallback((e, node) => {
973
- if (!elementsSelectable) return;
974
- const isMultiSelect = e.shiftKey || e.metaKey;
975
- const nodeChanges = [];
976
- if (isMultiSelect) {
977
- nodeChanges.push({ type: "select", id: node.id, selected: !node.selected });
978
- } else {
979
- for (const n of nodes) {
980
- if (n.id === node.id && !n.selected) {
981
- nodeChanges.push({ type: "select", id: n.id, selected: true });
982
- } else if (n.id !== node.id && n.selected) {
983
- nodeChanges.push({ type: "select", id: n.id, selected: false });
984
- }
985
- }
986
- }
987
- if (nodeChanges.length) onNodesChange?.(nodeChanges);
988
- if (!isMultiSelect) {
989
- const edgeDeselects = edges.filter((ed) => ed.selected).map((ed) => ({ type: "select", id: ed.id, selected: false }));
990
- if (edgeDeselects.length) onEdgesChange?.(edgeDeselects);
991
- }
992
- onNodeClick?.(e, node);
993
- }, [elementsSelectable, nodes, edges, onNodesChange, onEdgesChange, onNodeClick]);
994
- const handleEdgeClick = useCallback((e, edge) => {
995
- if (!elementsSelectable) return;
996
- e.stopPropagation();
997
- const edgeChanges = [];
998
- for (const ed of edges) {
999
- if (ed.id === edge.id && !ed.selected) {
1000
- edgeChanges.push({ type: "select", id: ed.id, selected: true });
1001
- } else if (ed.id !== edge.id && ed.selected) {
1002
- edgeChanges.push({ type: "select", id: ed.id, selected: false });
1003
- }
1004
- }
1005
- if (edgeChanges.length) onEdgesChange?.(edgeChanges);
1006
- const nodeDeselects = nodes.filter((n) => n.selected).map((n) => ({ type: "select", id: n.id, selected: false }));
1007
- if (nodeDeselects.length) onNodesChange?.(nodeDeselects);
1008
- onEdgeClick?.(e, edge);
1009
- }, [elementsSelectable, nodes, edges, onNodesChange, onEdgesChange, onEdgeClick]);
1010
- useEffect(() => {
1011
- const handleKeyDown = (e) => {
1012
- if (e.key === "Backspace" || e.key === "Delete") {
1013
- const target = e.target;
1014
- if (target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.tagName === "SELECT" || target.isContentEditable || target.closest('[role="dialog"]') || target.closest('[role="combobox"]') || target.closest('[role="listbox"]')) return;
1015
- const selectedNodes = nodes.filter((n) => n.selected);
1016
- const selectedEdges = edges.filter((ed) => ed.selected);
1017
- if (selectedNodes.length) {
1018
- onNodesChange?.(selectedNodes.map((n) => ({ type: "remove", id: n.id })));
1019
- }
1020
- if (selectedEdges.length) {
1021
- onEdgesChange?.(selectedEdges.map((ed) => ({ type: "remove", id: ed.id })));
1022
- }
1023
- }
1024
- };
1025
- window.addEventListener("keydown", handleKeyDown);
1026
- return () => window.removeEventListener("keydown", handleKeyDown);
1027
- }, [nodes, edges, onNodesChange, onEdgesChange]);
1028
- const transformStr = `translate(${viewport.x}px, ${viewport.y}px) scale(${viewport.zoom})`;
1029
- return /* @__PURE__ */ jsxs(
1030
- "div",
1031
- {
1032
- ref: containerRef,
1033
- className: `kgraph-canvas ${className}`,
1034
- style: {
1035
- width: "100%",
1036
- height: "100%",
1037
- position: "relative",
1038
- overflow: "hidden",
1039
- backgroundColor: "#0e0e10",
1040
- ...style
1041
- },
1042
- onMouseDown: handlePaneMouseDown,
1043
- onDragOver: handleDragOver,
1044
- onDrop: handleDrop,
1045
- children: [
1046
- showBackground && /* @__PURE__ */ jsx(DotGrid_default, { viewport, gap: backgroundGap }),
1047
- /* @__PURE__ */ jsxs(
1048
- "svg",
1049
- {
1050
- className: "kgraph-svg-layer",
1051
- style: {
1052
- position: "absolute",
1053
- inset: 0,
1054
- width: "100%",
1055
- height: "100%",
1056
- pointerEvents: "none",
1057
- overflow: "visible"
1058
- },
1059
- children: [
1060
- /* @__PURE__ */ jsxs("defs", { children: [
1061
- /* @__PURE__ */ jsx("marker", { id: "kgraph-arrow", viewBox: "0 0 12 12", refX: "12", refY: "6", markerWidth: "6", markerHeight: "6", orient: "auto-start-reverse", children: /* @__PURE__ */ jsx("path", { d: "M 0 1 L 12 6 L 0 11 z", fill: "#8b5cf6" }) }),
1062
- /* @__PURE__ */ jsx("marker", { id: "kgraph-arrow-selected", viewBox: "0 0 12 12", refX: "12", refY: "6", markerWidth: "6", markerHeight: "6", orient: "auto-start-reverse", children: /* @__PURE__ */ jsx("path", { d: "M 0 1 L 12 6 L 0 11 z", fill: "#a78bfa" }) })
1063
- ] }),
1064
- /* @__PURE__ */ jsxs(
1065
- "g",
1066
- {
1067
- transform: `translate(${viewport.x}, ${viewport.y}) scale(${viewport.zoom})`,
1068
- style: { pointerEvents: "all" },
1069
- children: [
1070
- /* @__PURE__ */ jsx(
1071
- EdgeRenderer_default,
1072
- {
1073
- edges,
1074
- edgeTypes,
1075
- onEdgeClick: handleEdgeClick
1076
- }
1077
- ),
1078
- connectionDrag && /* @__PURE__ */ jsx(
1079
- ConnectionLine_default,
1080
- {
1081
- sourceX: connectionDrag.sourceX,
1082
- sourceY: connectionDrag.sourceY,
1083
- sourcePosition: connectionDrag.sourcePosition,
1084
- targetX: connectionDrag.mouseX,
1085
- targetY: connectionDrag.mouseY
1086
- }
1087
- )
1088
- ]
1089
- }
1090
- )
1091
- ]
1092
- }
1093
- ),
1094
- /* @__PURE__ */ jsx(
1095
- "div",
1096
- {
1097
- className: "kgraph-node-layer",
1098
- style: {
1099
- position: "absolute",
1100
- inset: 0,
1101
- transformOrigin: "0 0",
1102
- transform: transformStr,
1103
- pointerEvents: "none"
1104
- },
1105
- children: /* @__PURE__ */ jsx("div", { style: { pointerEvents: "all" }, children: /* @__PURE__ */ jsx(
1106
- NodeRenderer_default,
1107
- {
1108
- nodes,
1109
- nodeTypes,
1110
- onNodesChange,
1111
- snapToGrid,
1112
- snapGrid,
1113
- draggable: nodesDraggable,
1114
- selectable: elementsSelectable,
1115
- onNodeClick: handleNodeClick,
1116
- onConnectionStart: handleConnectionStart,
1117
- zoom: viewport.zoom
1118
- }
1119
- ) })
1120
- }
1121
- ),
1122
- /* @__PURE__ */ jsx(
1123
- "div",
1124
- {
1125
- className: "kgraph-edge-label-layer",
1126
- style: {
1127
- position: "absolute",
1128
- inset: 0,
1129
- transformOrigin: "0 0",
1130
- transform: transformStr,
1131
- pointerEvents: "none",
1132
- zIndex: 10
1133
- }
1134
- }
1135
- ),
1136
- showMiniMap && containerSize.width > 0 && /* @__PURE__ */ jsx(
1137
- MiniMap_default,
1138
- {
1139
- nodes,
1140
- viewport,
1141
- onViewportChange: setViewport,
1142
- containerWidth: containerSize.width,
1143
- containerHeight: containerSize.height
1144
- }
1145
- ),
1146
- children
1147
- ]
1148
- }
1149
- );
1150
- };
1151
- var KGraphCanvas = (props) => {
1152
- return /* @__PURE__ */ jsx(
1153
- KGraphProvider,
1154
- {
1155
- nodes: props.nodes,
1156
- edges: props.edges,
1157
- minZoom: props.minZoom,
1158
- maxZoom: props.maxZoom,
1159
- children: /* @__PURE__ */ jsx(InnerCanvas, { ...props })
1160
- }
1161
- );
1162
- };
1163
- var KGraphCanvas_default = KGraphCanvas;
1164
-
1165
- // src/useKGraph.ts
1166
- function useKGraph() {
1167
- const ctx = useKGraphContext();
1168
- return {
1169
- screenToCanvasPosition: ctx.screenToCanvasPosition,
1170
- fitView: ctx.fitView,
1171
- zoomIn: ctx.zoomIn,
1172
- zoomOut: ctx.zoomOut,
1173
- zoomTo: ctx.zoomTo,
1174
- getViewport: () => ctx.viewport,
1175
- setViewport: ctx.setViewport,
1176
- getNodes: () => ctx.nodes,
1177
- getEdges: () => ctx.edges
1178
- };
1179
- }
1180
- var useKGraph_default = useKGraph;
1181
- function getPositionStyle(position) {
1182
- const base = {
1183
- position: "absolute",
1184
- zIndex: 20
1185
- };
1186
- switch (position) {
1187
- case "top":
1188
- return { ...base, top: 0, left: "50%", transform: "translate(-50%, -50%)" };
1189
- case "bottom":
1190
- return { ...base, bottom: 0, left: "50%", transform: "translate(-50%, 50%)" };
1191
- case "left":
1192
- return { ...base, left: 0, top: "50%", transform: "translate(-50%, -50%)" };
1193
- case "right":
1194
- return { ...base, right: 0, top: "50%", transform: "translate(50%, -50%)" };
1195
- }
1196
- }
1197
- var Handle = ({
1198
- id,
1199
- type,
1200
- position,
1201
- style,
1202
- className = "",
1203
- nodeId: nodeIdProp,
1204
- onConnectionStart: onConnectionStartProp
1205
- }) => {
1206
- const [hovered, setHovered] = useState(false);
1207
- const handleCtx = useHandleContext();
1208
- const nodeId = nodeIdProp ?? handleCtx.nodeId;
1209
- const onConnectionStart = onConnectionStartProp ?? handleCtx.onConnectionStart;
1210
- const handleMouseDown = useCallback((e) => {
1211
- if (type === "source" && nodeId && onConnectionStart) {
1212
- e.stopPropagation();
1213
- e.preventDefault();
1214
- onConnectionStart(nodeId, id, type, e);
1215
- }
1216
- }, [type, nodeId, id, onConnectionStart]);
1217
- const posStyle = getPositionStyle(position);
1218
- const defaultBg = type === "source" ? "#8b5cf6" : "#6d28d9";
1219
- const hoverBg = type === "source" ? "#a78bfa" : "#8b5cf6";
1220
- const borderColor = type === "source" ? "#a78bfa" : "#7c3aed";
1221
- return /* @__PURE__ */ jsx(
1222
- "div",
1223
- {
1224
- className: `kgraph-handle kgraph-handle-${type} kgraph-handle-${position} ${className}`,
1225
- style: {
1226
- width: hovered ? 12 : 8,
1227
- height: hovered ? 12 : 8,
1228
- borderRadius: "50%",
1229
- background: style?.background || (hovered ? hoverBg : defaultBg),
1230
- border: `2px solid ${style?.borderColor || borderColor}`,
1231
- cursor: type === "source" ? "crosshair" : "default",
1232
- transition: "width 0.15s, height 0.15s, background 0.15s, box-shadow 0.15s",
1233
- boxShadow: hovered ? `0 0 6px ${borderColor}88` : "none",
1234
- ...posStyle,
1235
- ...style
1236
- },
1237
- "data-handleid": id,
1238
- "data-handletype": type,
1239
- "data-handleposition": position,
1240
- "data-nodeid": nodeId,
1241
- onMouseDown: handleMouseDown,
1242
- onMouseEnter: () => setHovered(true),
1243
- onMouseLeave: () => setHovered(false)
1244
- }
1245
- );
1246
- };
1247
- var Handle_default = Handle;
1248
- var EdgeLabel = ({ x, y, zoom, children }) => {
1249
- return /* @__PURE__ */ jsx(
1250
- "div",
1251
- {
1252
- className: "kgraph-edge-label",
1253
- style: {
1254
- position: "absolute",
1255
- left: x,
1256
- top: y,
1257
- transform: `translate(-50%, -50%) scale(${1 / zoom})`,
1258
- transformOrigin: "center center",
1259
- pointerEvents: "all",
1260
- zIndex: 10
1261
- },
1262
- children
1263
- }
1264
- );
1265
- };
1266
- var EdgeLabel_default = EdgeLabel;
1267
-
1268
- // src/applyChanges.ts
1269
- function applyNodeChanges(changes, nodes) {
1270
- let result = nodes;
1271
- for (const change of changes) {
1272
- switch (change.type) {
1273
- case "position":
1274
- result = result.map(
1275
- (n) => n.id === change.id ? {
1276
- ...n,
1277
- position: change.position ?? n.position,
1278
- dragging: change.dragging
1279
- } : n
1280
- );
1281
- break;
1282
- case "select":
1283
- result = result.map(
1284
- (n) => n.id === change.id ? { ...n, selected: change.selected } : n
1285
- );
1286
- break;
1287
- case "remove":
1288
- result = result.filter((n) => n.id !== change.id);
1289
- break;
1290
- case "add":
1291
- result = [...result, change.item];
1292
- break;
1293
- case "dimensions":
1294
- result = result.map(
1295
- (n) => n.id === change.id ? {
1296
- ...n,
1297
- width: change.dimensions.width,
1298
- height: change.dimensions.height
1299
- } : n
1300
- );
1301
- break;
1302
- }
1303
- }
1304
- return result;
1305
- }
1306
- function applyEdgeChanges(changes, edges) {
1307
- let result = edges;
1308
- for (const change of changes) {
1309
- switch (change.type) {
1310
- case "select":
1311
- result = result.map(
1312
- (e) => e.id === change.id ? { ...e, selected: change.selected } : e
1313
- );
1314
- break;
1315
- case "remove":
1316
- result = result.filter((e) => e.id !== change.id);
1317
- break;
1318
- case "add":
1319
- result = [...result, change.item];
1320
- break;
1321
- }
1322
- }
1323
- return result;
1324
- }
1325
-
1326
- export { ConnectionLine_default as ConnectionLine, DotGrid_default as DotGrid, EdgeLabel_default as EdgeLabel, EdgeRenderer_default as EdgeRenderer, Handle_default as Handle, KGraphCanvas_default as KGraphCanvas, KGraphProvider, MiniMap_default as MiniMap, NodeRenderer_default as NodeRenderer, applyEdgeChanges, applyNodeChanges, getBezierPath, useKGraph_default as useKGraph, useKGraphContext };
1
+ export { ConnectionLine_default as ConnectionLine, DotGrid_default as DotGrid, EdgeLabel_default as EdgeLabel, EdgeRenderer_default as EdgeRenderer, Handle_default as Handle, KGraphCanvas_default as KGraphCanvas, KGraphProvider, MiniMap_default as MiniMap, NodeRenderer_default as NodeRenderer, applyEdgeChanges, applyNodeChanges, getBezierPath, useKGraph_default as useKGraph, useKGraphContext } from './chunk-374K6PXA.js';
1327
2
  //# sourceMappingURL=index.js.map
1328
3
  //# sourceMappingURL=index.js.map