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