html-overlay-node 0.1.0
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/LICENSE +21 -0
- package/dist/example.json +522 -0
- package/dist/html-overlay-node.es.js +3596 -0
- package/dist/html-overlay-node.es.js.map +1 -0
- package/dist/html-overlay-node.umd.js +2 -0
- package/dist/html-overlay-node.umd.js.map +1 -0
- package/index.css +232 -0
- package/package.json +65 -0
- package/readme.md +437 -0
- package/src/core/CommandStack.js +26 -0
- package/src/core/Edge.js +28 -0
- package/src/core/Edge.test.js +73 -0
- package/src/core/Graph.js +267 -0
- package/src/core/Graph.test.js +256 -0
- package/src/core/Group.js +77 -0
- package/src/core/Hooks.js +12 -0
- package/src/core/Hooks.test.js +108 -0
- package/src/core/Node.js +70 -0
- package/src/core/Node.test.js +113 -0
- package/src/core/Registry.js +71 -0
- package/src/core/Registry.test.js +88 -0
- package/src/core/Runner.js +211 -0
- package/src/core/commands.js +125 -0
- package/src/groups/GroupManager.js +116 -0
- package/src/index.js +1030 -0
- package/src/interact/ContextMenu.js +400 -0
- package/src/interact/Controller.js +856 -0
- package/src/minimap/Minimap.js +146 -0
- package/src/render/CanvasRenderer.js +606 -0
- package/src/render/HtmlOverlay.js +161 -0
- package/src/render/hitTest.js +38 -0
- package/src/ui/PropertyPanel.css +277 -0
- package/src/ui/PropertyPanel.js +269 -0
- package/src/utils/utils.js +75 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimap - Shows overview of entire graph with viewport indicator
|
|
3
|
+
*/
|
|
4
|
+
export class Minimap {
|
|
5
|
+
constructor(container, { graph, renderer, width = 200, height = 150 } = {}) {
|
|
6
|
+
this.graph = graph;
|
|
7
|
+
this.renderer = renderer;
|
|
8
|
+
this.width = width;
|
|
9
|
+
this.height = height;
|
|
10
|
+
|
|
11
|
+
// Create canvas element
|
|
12
|
+
this.canvas = document.createElement("canvas");
|
|
13
|
+
this.canvas.id = "minimap";
|
|
14
|
+
this.canvas.width = width;
|
|
15
|
+
this.canvas.height = height;
|
|
16
|
+
this.canvas.style.position = "fixed";
|
|
17
|
+
this.canvas.style.bottom = "20px";
|
|
18
|
+
this.canvas.style.right = "20px";
|
|
19
|
+
this.canvas.style.border = "2px solid #444";
|
|
20
|
+
this.canvas.style.borderRadius = "8px";
|
|
21
|
+
this.canvas.style.background = "rgba(20, 20, 23, 0.9)";
|
|
22
|
+
this.canvas.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.5)";
|
|
23
|
+
this.canvas.style.pointerEvents = "none"; // Don't block clicks
|
|
24
|
+
|
|
25
|
+
this.ctx = this.canvas.getContext("2d");
|
|
26
|
+
|
|
27
|
+
// Add to container
|
|
28
|
+
container.appendChild(this.canvas);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Render the minimap
|
|
33
|
+
*/
|
|
34
|
+
render() {
|
|
35
|
+
const { graph, renderer, ctx, width: w, height: h } = this;
|
|
36
|
+
|
|
37
|
+
// Clear
|
|
38
|
+
ctx.fillStyle = "#141417";
|
|
39
|
+
ctx.fillRect(0, 0, w, h);
|
|
40
|
+
|
|
41
|
+
if (graph.nodes.size === 0) return;
|
|
42
|
+
|
|
43
|
+
// Calculate bounds of all nodes
|
|
44
|
+
let minX = Infinity,
|
|
45
|
+
minY = Infinity,
|
|
46
|
+
maxX = -Infinity,
|
|
47
|
+
maxY = -Infinity;
|
|
48
|
+
for (const node of graph.nodes.values()) {
|
|
49
|
+
const { x, y, w: nw, h: nh } = node.computed;
|
|
50
|
+
minX = Math.min(minX, x);
|
|
51
|
+
minY = Math.min(minY, y);
|
|
52
|
+
maxX = Math.max(maxX, x + nw);
|
|
53
|
+
maxY = Math.max(maxY, y + nh);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Add margin to the bounds
|
|
57
|
+
const margin = 100; // World units margin
|
|
58
|
+
const graphWidth = Math.max(300, maxX - minX + margin * 2);
|
|
59
|
+
const graphHeight = Math.max(200, maxY - minY + margin * 2);
|
|
60
|
+
|
|
61
|
+
// Adjust minX and minY to center the content
|
|
62
|
+
minX -= margin;
|
|
63
|
+
minY -= margin;
|
|
64
|
+
|
|
65
|
+
const padding = 10;
|
|
66
|
+
|
|
67
|
+
const scale = Math.min(
|
|
68
|
+
(w - padding * 2) / graphWidth,
|
|
69
|
+
(h - padding * 2) / graphHeight
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const offsetX = (w - graphWidth * scale) / 2;
|
|
73
|
+
const offsetY = (h - graphHeight * scale) / 2;
|
|
74
|
+
|
|
75
|
+
// Draw edges first (so they appear behind nodes)
|
|
76
|
+
ctx.strokeStyle = "rgba(127, 140, 255, 0.5)"; // Semi-transparent edge color
|
|
77
|
+
ctx.lineWidth = 1;
|
|
78
|
+
for (const edge of graph.edges.values()) {
|
|
79
|
+
const fromNode = graph.nodes.get(edge.fromNode);
|
|
80
|
+
const toNode = graph.nodes.get(edge.toNode);
|
|
81
|
+
if (!fromNode || !toNode) continue;
|
|
82
|
+
|
|
83
|
+
// Get center points of nodes
|
|
84
|
+
const x1 = fromNode.computed.x + fromNode.computed.w / 2;
|
|
85
|
+
const y1 = fromNode.computed.y + fromNode.computed.h / 2;
|
|
86
|
+
const x2 = toNode.computed.x + toNode.computed.w / 2;
|
|
87
|
+
const y2 = toNode.computed.y + toNode.computed.h / 2;
|
|
88
|
+
|
|
89
|
+
// Transform to minimap coordinates
|
|
90
|
+
const mx1 = (x1 - minX) * scale + offsetX;
|
|
91
|
+
const my1 = (y1 - minY) * scale + offsetY;
|
|
92
|
+
const mx2 = (x2 - minX) * scale + offsetX;
|
|
93
|
+
const my2 = (y2 - minY) * scale + offsetY;
|
|
94
|
+
|
|
95
|
+
ctx.beginPath();
|
|
96
|
+
ctx.moveTo(mx1, my1);
|
|
97
|
+
ctx.lineTo(mx2, my2);
|
|
98
|
+
ctx.stroke();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Draw nodes
|
|
102
|
+
ctx.fillStyle = "#6cf";
|
|
103
|
+
for (const node of graph.nodes.values()) {
|
|
104
|
+
const { x, y, w: nw, h: nh } = node.computed;
|
|
105
|
+
const mx = (x - minX) * scale + offsetX;
|
|
106
|
+
const my = (y - minY) * scale + offsetY;
|
|
107
|
+
const mw = nw * scale;
|
|
108
|
+
const mh = nh * scale;
|
|
109
|
+
|
|
110
|
+
if (node.type === "core/Group") {
|
|
111
|
+
ctx.fillStyle = "rgba(102, 204, 255, 0.2)";
|
|
112
|
+
ctx.strokeStyle = "#6cf";
|
|
113
|
+
ctx.lineWidth = 1;
|
|
114
|
+
ctx.fillRect(mx, my, mw, mh);
|
|
115
|
+
ctx.strokeRect(mx, my, mw, mh);
|
|
116
|
+
} else {
|
|
117
|
+
ctx.fillStyle = "#6cf";
|
|
118
|
+
ctx.fillRect(mx, my, Math.max(2, mw), Math.max(2, mh));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Draw viewport rectangle
|
|
123
|
+
const vx0 = -renderer.offsetX / renderer.scale;
|
|
124
|
+
const vy0 = -renderer.offsetY / renderer.scale;
|
|
125
|
+
const vw = renderer.canvas.width / renderer.scale;
|
|
126
|
+
const vh = renderer.canvas.height / renderer.scale;
|
|
127
|
+
|
|
128
|
+
const vmx = (vx0 - minX) * scale + offsetX;
|
|
129
|
+
const vmy = (vy0 - minY) * scale + offsetY;
|
|
130
|
+
const vmw = vw * scale;
|
|
131
|
+
const vmh = vh * scale;
|
|
132
|
+
|
|
133
|
+
ctx.strokeStyle = "#ff6b6b";
|
|
134
|
+
ctx.lineWidth = 2;
|
|
135
|
+
ctx.strokeRect(vmx, vmy, vmw, vmh);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Cleanup
|
|
140
|
+
*/
|
|
141
|
+
destroy() {
|
|
142
|
+
if (this.canvas.parentElement) {
|
|
143
|
+
this.canvas.parentElement.removeChild(this.canvas);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|