react-grid-lights 1.0.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/README.md +204 -0
- package/dist/index.d.mts +33 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +455 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +429 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +66 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/index.ts
|
|
22
|
+
var index_exports = {};
|
|
23
|
+
__export(index_exports, {
|
|
24
|
+
Grid: () => Grid,
|
|
25
|
+
default: () => Grid
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(index_exports);
|
|
28
|
+
|
|
29
|
+
// src/Grid.tsx
|
|
30
|
+
var import_react = require("react");
|
|
31
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
32
|
+
function Grid({
|
|
33
|
+
shape = 4,
|
|
34
|
+
cellSize = 40,
|
|
35
|
+
lineColor = "#e5e7eb",
|
|
36
|
+
lineWidth = 1,
|
|
37
|
+
className = "",
|
|
38
|
+
animated = false,
|
|
39
|
+
lightColor = "#3b82f6",
|
|
40
|
+
lightSpeed = 2,
|
|
41
|
+
minTravel = 2,
|
|
42
|
+
maxTravel = 6,
|
|
43
|
+
spawnRate = 1e3,
|
|
44
|
+
splitChance = 0.3,
|
|
45
|
+
trailFadeSpeed = 0.01
|
|
46
|
+
}) {
|
|
47
|
+
const canvasRef = (0, import_react.useRef)(null);
|
|
48
|
+
const containerRef = (0, import_react.useRef)(null);
|
|
49
|
+
const nodesRef = (0, import_react.useRef)(/* @__PURE__ */ new Map());
|
|
50
|
+
const edgesRef = (0, import_react.useRef)([]);
|
|
51
|
+
const adjacencyRef = (0, import_react.useRef)(/* @__PURE__ */ new Map());
|
|
52
|
+
const topNodesRef = (0, import_react.useRef)([]);
|
|
53
|
+
const animationRef = (0, import_react.useRef)(0);
|
|
54
|
+
const particlesRef = (0, import_react.useRef)([]);
|
|
55
|
+
const trailsRef = (0, import_react.useRef)([]);
|
|
56
|
+
const lastSpawnRef = (0, import_react.useRef)(0);
|
|
57
|
+
const particleIdRef = (0, import_react.useRef)(0);
|
|
58
|
+
const dimensionsRef = (0, import_react.useRef)({ width: 0, height: 0 });
|
|
59
|
+
const activeEdgesRef = (0, import_react.useRef)(/* @__PURE__ */ new Set());
|
|
60
|
+
const explosionsRef = (0, import_react.useRef)([]);
|
|
61
|
+
const nodeGlowsRef = (0, import_react.useRef)([]);
|
|
62
|
+
const nodeKey = (x, y) => `${Math.round(x * 100)},${Math.round(y * 100)}`;
|
|
63
|
+
const edgeKey = (n1, n2) => {
|
|
64
|
+
const keys = [n1.key, n2.key].sort();
|
|
65
|
+
return `${keys[0]}-${keys[1]}`;
|
|
66
|
+
};
|
|
67
|
+
const getOrCreateNode = (0, import_react.useCallback)((x, y) => {
|
|
68
|
+
const key = nodeKey(x, y);
|
|
69
|
+
if (!nodesRef.current.has(key)) {
|
|
70
|
+
nodesRef.current.set(key, { x, y, key });
|
|
71
|
+
}
|
|
72
|
+
return nodesRef.current.get(key);
|
|
73
|
+
}, []);
|
|
74
|
+
const addEdge = (0, import_react.useCallback)((x1, y1, x2, y2) => {
|
|
75
|
+
const from = getOrCreateNode(x1, y1);
|
|
76
|
+
const to = getOrCreateNode(x2, y2);
|
|
77
|
+
const key = edgeKey(from, to);
|
|
78
|
+
const existingEdge = edgesRef.current.find((e) => e.key === key);
|
|
79
|
+
if (existingEdge) return;
|
|
80
|
+
const edge = { from, to, key };
|
|
81
|
+
edgesRef.current.push(edge);
|
|
82
|
+
if (!adjacencyRef.current.has(from.key)) {
|
|
83
|
+
adjacencyRef.current.set(from.key, []);
|
|
84
|
+
}
|
|
85
|
+
if (!adjacencyRef.current.has(to.key)) {
|
|
86
|
+
adjacencyRef.current.set(to.key, []);
|
|
87
|
+
}
|
|
88
|
+
adjacencyRef.current.get(from.key).push(edge);
|
|
89
|
+
adjacencyRef.current.get(to.key).push(edge);
|
|
90
|
+
}, [getOrCreateNode]);
|
|
91
|
+
const buildSquareGraph = (0, import_react.useCallback)((width, height) => {
|
|
92
|
+
nodesRef.current.clear();
|
|
93
|
+
edgesRef.current = [];
|
|
94
|
+
adjacencyRef.current.clear();
|
|
95
|
+
topNodesRef.current = [];
|
|
96
|
+
const cols = Math.ceil(width / cellSize) + 1;
|
|
97
|
+
const rows = Math.ceil(height / cellSize) + 1;
|
|
98
|
+
for (let i = 0; i <= cols; i++) {
|
|
99
|
+
for (let j = 0; j <= rows; j++) {
|
|
100
|
+
const x = i * cellSize;
|
|
101
|
+
const y = j * cellSize;
|
|
102
|
+
if (i < cols) addEdge(x, y, x + cellSize, y);
|
|
103
|
+
if (j < rows) addEdge(x, y, x, y + cellSize);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
for (let i = 0; i <= cols; i++) {
|
|
107
|
+
const node = nodesRef.current.get(nodeKey(i * cellSize, 0));
|
|
108
|
+
if (node) topNodesRef.current.push(node);
|
|
109
|
+
}
|
|
110
|
+
}, [cellSize, addEdge]);
|
|
111
|
+
const buildHexGraph = (0, import_react.useCallback)((width, height) => {
|
|
112
|
+
nodesRef.current.clear();
|
|
113
|
+
edgesRef.current = [];
|
|
114
|
+
adjacencyRef.current.clear();
|
|
115
|
+
topNodesRef.current = [];
|
|
116
|
+
const size = cellSize / 2;
|
|
117
|
+
const hexWidth = Math.sqrt(3) * size;
|
|
118
|
+
const vertSpacing = size * 1.5;
|
|
119
|
+
const cols = Math.ceil(width / hexWidth) + 2;
|
|
120
|
+
const rows = Math.ceil(height / vertSpacing) + 2;
|
|
121
|
+
for (let row = -1; row < rows; row++) {
|
|
122
|
+
for (let col = -1; col < cols; col++) {
|
|
123
|
+
const cx = col * hexWidth + (row % 2 === 0 ? 0 : hexWidth / 2);
|
|
124
|
+
const cy = row * vertSpacing;
|
|
125
|
+
const vertices = [];
|
|
126
|
+
for (let i = 0; i < 6; i++) {
|
|
127
|
+
const angle = Math.PI / 3 * i - Math.PI / 2;
|
|
128
|
+
vertices.push({
|
|
129
|
+
x: cx + size * Math.cos(angle),
|
|
130
|
+
y: cy + size * Math.sin(angle)
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
for (let i = 0; i < 6; i++) {
|
|
134
|
+
const v1 = vertices[i];
|
|
135
|
+
const v2 = vertices[(i + 1) % 6];
|
|
136
|
+
addEdge(v1.x, v1.y, v2.x, v2.y);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const sortedNodes = Array.from(nodesRef.current.values()).filter((n) => n.y >= 0 && n.y <= size).sort((a, b) => a.x - b.x);
|
|
141
|
+
topNodesRef.current = sortedNodes;
|
|
142
|
+
}, [cellSize, addEdge]);
|
|
143
|
+
const getConnectedNodes = (0, import_react.useCallback)((node, excludeNode) => {
|
|
144
|
+
const edges = adjacencyRef.current.get(node.key) || [];
|
|
145
|
+
return edges.map((e) => e.from.key === node.key ? e.to : e.from).filter((n) => !excludeNode || n.key !== excludeNode.key);
|
|
146
|
+
}, []);
|
|
147
|
+
(0, import_react.useEffect)(() => {
|
|
148
|
+
const canvas = canvasRef.current;
|
|
149
|
+
const container = containerRef.current;
|
|
150
|
+
if (!canvas || !container) return;
|
|
151
|
+
let dpr = 1;
|
|
152
|
+
const drawGrid = (ctx, width, height) => {
|
|
153
|
+
ctx.clearRect(0, 0, width, height);
|
|
154
|
+
ctx.strokeStyle = lineColor;
|
|
155
|
+
ctx.lineWidth = lineWidth;
|
|
156
|
+
ctx.beginPath();
|
|
157
|
+
for (const edge of edgesRef.current) {
|
|
158
|
+
ctx.moveTo(edge.from.x, edge.from.y);
|
|
159
|
+
ctx.lineTo(edge.to.x, edge.to.y);
|
|
160
|
+
}
|
|
161
|
+
ctx.stroke();
|
|
162
|
+
};
|
|
163
|
+
const drawTrails = (ctx) => {
|
|
164
|
+
for (const trail of trailsRef.current) {
|
|
165
|
+
if (trail.opacity <= 0) continue;
|
|
166
|
+
const alpha = Math.floor(trail.opacity * 0.08 * 255).toString(16).padStart(2, "0");
|
|
167
|
+
ctx.strokeStyle = lightColor + alpha;
|
|
168
|
+
ctx.lineWidth = 1;
|
|
169
|
+
ctx.lineCap = "round";
|
|
170
|
+
ctx.beginPath();
|
|
171
|
+
ctx.moveTo(trail.fromX, trail.fromY);
|
|
172
|
+
if (trail.progress < 1) {
|
|
173
|
+
const endX = trail.fromX + (trail.toX - trail.fromX) * trail.progress;
|
|
174
|
+
const endY = trail.fromY + (trail.toY - trail.fromY) * trail.progress;
|
|
175
|
+
ctx.lineTo(endX, endY);
|
|
176
|
+
} else {
|
|
177
|
+
ctx.lineTo(trail.toX, trail.toY);
|
|
178
|
+
}
|
|
179
|
+
ctx.stroke();
|
|
180
|
+
ctx.shadowColor = lightColor;
|
|
181
|
+
ctx.shadowBlur = 2;
|
|
182
|
+
ctx.stroke();
|
|
183
|
+
ctx.shadowBlur = 0;
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
const drawParticles = (ctx) => {
|
|
187
|
+
for (const particle of particlesRef.current) {
|
|
188
|
+
if (particle.dead) continue;
|
|
189
|
+
const x = particle.currentNode.x + (particle.targetNode.x - particle.currentNode.x) * particle.progress;
|
|
190
|
+
const y = particle.currentNode.y + (particle.targetNode.y - particle.currentNode.y) * particle.progress;
|
|
191
|
+
ctx.fillStyle = lightColor;
|
|
192
|
+
ctx.beginPath();
|
|
193
|
+
ctx.arc(x, y, 3, 0, Math.PI * 2);
|
|
194
|
+
ctx.fill();
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
const drawExplosions = (ctx) => {
|
|
198
|
+
for (const explosion of explosionsRef.current) {
|
|
199
|
+
if (explosion.opacity <= 0) continue;
|
|
200
|
+
const alpha = Math.floor(explosion.opacity * 255).toString(16).padStart(2, "0");
|
|
201
|
+
ctx.strokeStyle = lightColor + alpha;
|
|
202
|
+
ctx.lineWidth = 2;
|
|
203
|
+
ctx.beginPath();
|
|
204
|
+
ctx.arc(explosion.x, explosion.y, explosion.radius, 0, Math.PI * 2);
|
|
205
|
+
ctx.stroke();
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
const updateExplosions = () => {
|
|
209
|
+
for (const explosion of explosionsRef.current) {
|
|
210
|
+
explosion.radius += 0.5;
|
|
211
|
+
explosion.opacity -= 0.08;
|
|
212
|
+
}
|
|
213
|
+
explosionsRef.current = explosionsRef.current.filter((e) => e.opacity > 0);
|
|
214
|
+
};
|
|
215
|
+
const createExplosion = (x, y) => {
|
|
216
|
+
explosionsRef.current.push({
|
|
217
|
+
x,
|
|
218
|
+
y,
|
|
219
|
+
radius: 2,
|
|
220
|
+
maxRadius: 8,
|
|
221
|
+
opacity: 1
|
|
222
|
+
});
|
|
223
|
+
};
|
|
224
|
+
const createNodeGlow = (x, y) => {
|
|
225
|
+
nodeGlowsRef.current.push({
|
|
226
|
+
x,
|
|
227
|
+
y,
|
|
228
|
+
opacity: 1
|
|
229
|
+
});
|
|
230
|
+
};
|
|
231
|
+
const drawNodeGlows = (ctx) => {
|
|
232
|
+
for (const glow of nodeGlowsRef.current) {
|
|
233
|
+
if (glow.opacity <= 0) continue;
|
|
234
|
+
const alpha = Math.floor(glow.opacity * 0.4 * 255).toString(16).padStart(2, "0");
|
|
235
|
+
ctx.fillStyle = lightColor + alpha;
|
|
236
|
+
ctx.beginPath();
|
|
237
|
+
ctx.arc(glow.x, glow.y, 2, 0, Math.PI * 2);
|
|
238
|
+
ctx.fill();
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
const updateNodeGlows = () => {
|
|
242
|
+
for (const glow of nodeGlowsRef.current) {
|
|
243
|
+
glow.opacity -= trailFadeSpeed * 3;
|
|
244
|
+
}
|
|
245
|
+
nodeGlowsRef.current = nodeGlowsRef.current.filter((g) => g.opacity > 0);
|
|
246
|
+
};
|
|
247
|
+
const getRandomTravel = () => {
|
|
248
|
+
return Math.floor(Math.random() * (maxTravel - minTravel + 1)) + minTravel;
|
|
249
|
+
};
|
|
250
|
+
const makeEdgeKey = (n1, n2) => {
|
|
251
|
+
const keys = [n1.key, n2.key].sort();
|
|
252
|
+
return `${keys[0]}-${keys[1]}`;
|
|
253
|
+
};
|
|
254
|
+
const spawnParticle = () => {
|
|
255
|
+
if (topNodesRef.current.length === 0) return;
|
|
256
|
+
const startNode = topNodesRef.current[Math.floor(Math.random() * topNodesRef.current.length)];
|
|
257
|
+
const connectedNodes = getConnectedNodes(startNode);
|
|
258
|
+
const downwardNodes = connectedNodes.filter((n) => n.y > startNode.y);
|
|
259
|
+
const targetNodes = downwardNodes.length > 0 ? downwardNodes : connectedNodes;
|
|
260
|
+
const availableNodes = targetNodes.filter((n) => {
|
|
261
|
+
const key = makeEdgeKey(startNode, n);
|
|
262
|
+
return !activeEdgesRef.current.has(key);
|
|
263
|
+
});
|
|
264
|
+
if (availableNodes.length === 0) return;
|
|
265
|
+
const targetNode = availableNodes[Math.floor(Math.random() * availableNodes.length)];
|
|
266
|
+
const edgeKeyStr = makeEdgeKey(startNode, targetNode);
|
|
267
|
+
activeEdgesRef.current.add(edgeKeyStr);
|
|
268
|
+
particlesRef.current.push({
|
|
269
|
+
id: particleIdRef.current++,
|
|
270
|
+
currentNode: startNode,
|
|
271
|
+
targetNode,
|
|
272
|
+
progress: 0,
|
|
273
|
+
traveled: 0,
|
|
274
|
+
maxTravel: getRandomTravel(),
|
|
275
|
+
canSplit: true,
|
|
276
|
+
dead: false
|
|
277
|
+
});
|
|
278
|
+
trailsRef.current.push({
|
|
279
|
+
fromX: startNode.x,
|
|
280
|
+
fromY: startNode.y,
|
|
281
|
+
toX: targetNode.x,
|
|
282
|
+
toY: targetNode.y,
|
|
283
|
+
progress: 0,
|
|
284
|
+
opacity: 1,
|
|
285
|
+
edgeKey: edgeKeyStr
|
|
286
|
+
});
|
|
287
|
+
};
|
|
288
|
+
const updateParticles = () => {
|
|
289
|
+
const newParticles = [];
|
|
290
|
+
for (const particle of particlesRef.current) {
|
|
291
|
+
if (particle.dead) continue;
|
|
292
|
+
particle.progress += lightSpeed * 0.02;
|
|
293
|
+
const trailIndex = trailsRef.current.findIndex(
|
|
294
|
+
(t) => t.fromX === particle.currentNode.x && t.fromY === particle.currentNode.y && t.toX === particle.targetNode.x && t.toY === particle.targetNode.y && t.progress < 1
|
|
295
|
+
);
|
|
296
|
+
if (trailIndex !== -1) {
|
|
297
|
+
trailsRef.current[trailIndex].progress = Math.min(particle.progress, 1);
|
|
298
|
+
}
|
|
299
|
+
if (particle.progress >= 1) {
|
|
300
|
+
createNodeGlow(particle.targetNode.x, particle.targetNode.y);
|
|
301
|
+
particle.traveled++;
|
|
302
|
+
if (particle.traveled >= particle.maxTravel) {
|
|
303
|
+
const x = particle.targetNode.x;
|
|
304
|
+
const y = particle.targetNode.y;
|
|
305
|
+
createExplosion(x, y);
|
|
306
|
+
particle.dead = true;
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
const currentNode = particle.targetNode;
|
|
310
|
+
const connectedNodes = getConnectedNodes(currentNode, particle.currentNode);
|
|
311
|
+
const availableNodes = connectedNodes.filter((n) => {
|
|
312
|
+
const key = makeEdgeKey(currentNode, n);
|
|
313
|
+
return !activeEdgesRef.current.has(key);
|
|
314
|
+
});
|
|
315
|
+
if (availableNodes.length === 0) {
|
|
316
|
+
createExplosion(currentNode.x, currentNode.y);
|
|
317
|
+
particle.dead = true;
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
const shouldSplit = particle.canSplit && Math.random() < splitChance && availableNodes.length >= 2;
|
|
321
|
+
if (shouldSplit) {
|
|
322
|
+
const shuffled = [...availableNodes].sort(() => Math.random() - 0.5);
|
|
323
|
+
const target1 = shuffled[0];
|
|
324
|
+
const target2 = shuffled[1];
|
|
325
|
+
const edgeKey1 = makeEdgeKey(currentNode, target1);
|
|
326
|
+
const edgeKey2 = makeEdgeKey(currentNode, target2);
|
|
327
|
+
activeEdgesRef.current.add(edgeKey1);
|
|
328
|
+
activeEdgesRef.current.add(edgeKey2);
|
|
329
|
+
particle.currentNode = currentNode;
|
|
330
|
+
particle.targetNode = target1;
|
|
331
|
+
particle.progress = 0;
|
|
332
|
+
particle.canSplit = false;
|
|
333
|
+
trailsRef.current.push({
|
|
334
|
+
fromX: currentNode.x,
|
|
335
|
+
fromY: currentNode.y,
|
|
336
|
+
toX: target1.x,
|
|
337
|
+
toY: target1.y,
|
|
338
|
+
progress: 0,
|
|
339
|
+
opacity: 1,
|
|
340
|
+
edgeKey: edgeKey1
|
|
341
|
+
});
|
|
342
|
+
newParticles.push({
|
|
343
|
+
id: particleIdRef.current++,
|
|
344
|
+
currentNode,
|
|
345
|
+
targetNode: target2,
|
|
346
|
+
progress: 0,
|
|
347
|
+
traveled: particle.traveled,
|
|
348
|
+
maxTravel: particle.maxTravel,
|
|
349
|
+
canSplit: false,
|
|
350
|
+
dead: false
|
|
351
|
+
});
|
|
352
|
+
trailsRef.current.push({
|
|
353
|
+
fromX: currentNode.x,
|
|
354
|
+
fromY: currentNode.y,
|
|
355
|
+
toX: target2.x,
|
|
356
|
+
toY: target2.y,
|
|
357
|
+
progress: 0,
|
|
358
|
+
opacity: 1,
|
|
359
|
+
edgeKey: edgeKey2
|
|
360
|
+
});
|
|
361
|
+
} else {
|
|
362
|
+
const targetNode = availableNodes[Math.floor(Math.random() * availableNodes.length)];
|
|
363
|
+
const newEdgeKey = makeEdgeKey(currentNode, targetNode);
|
|
364
|
+
activeEdgesRef.current.add(newEdgeKey);
|
|
365
|
+
particle.currentNode = currentNode;
|
|
366
|
+
particle.targetNode = targetNode;
|
|
367
|
+
particle.progress = 0;
|
|
368
|
+
trailsRef.current.push({
|
|
369
|
+
fromX: currentNode.x,
|
|
370
|
+
fromY: currentNode.y,
|
|
371
|
+
toX: targetNode.x,
|
|
372
|
+
toY: targetNode.y,
|
|
373
|
+
progress: 0,
|
|
374
|
+
opacity: 1,
|
|
375
|
+
edgeKey: newEdgeKey
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
particlesRef.current.push(...newParticles);
|
|
381
|
+
particlesRef.current = particlesRef.current.filter((p) => !p.dead);
|
|
382
|
+
};
|
|
383
|
+
const updateTrails = () => {
|
|
384
|
+
for (const trail of trailsRef.current) {
|
|
385
|
+
if (trail.progress >= 1) {
|
|
386
|
+
trail.opacity -= trailFadeSpeed;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
const fadedTrails = trailsRef.current.filter((t) => t.opacity <= 0);
|
|
390
|
+
for (const trail of fadedTrails) {
|
|
391
|
+
activeEdgesRef.current.delete(trail.edgeKey);
|
|
392
|
+
}
|
|
393
|
+
trailsRef.current = trailsRef.current.filter((t) => t.opacity > 0);
|
|
394
|
+
};
|
|
395
|
+
const animate = (timestamp) => {
|
|
396
|
+
const ctx = canvas.getContext("2d");
|
|
397
|
+
if (!ctx) return;
|
|
398
|
+
const { width, height } = dimensionsRef.current;
|
|
399
|
+
ctx.save();
|
|
400
|
+
ctx.scale(dpr, dpr);
|
|
401
|
+
drawGrid(ctx, width, height);
|
|
402
|
+
if (animated) {
|
|
403
|
+
if (timestamp - lastSpawnRef.current > spawnRate) {
|
|
404
|
+
spawnParticle();
|
|
405
|
+
lastSpawnRef.current = timestamp;
|
|
406
|
+
}
|
|
407
|
+
updateParticles();
|
|
408
|
+
updateTrails();
|
|
409
|
+
updateExplosions();
|
|
410
|
+
updateNodeGlows();
|
|
411
|
+
drawTrails(ctx);
|
|
412
|
+
drawNodeGlows(ctx);
|
|
413
|
+
drawParticles(ctx);
|
|
414
|
+
drawExplosions(ctx);
|
|
415
|
+
}
|
|
416
|
+
ctx.restore();
|
|
417
|
+
animationRef.current = requestAnimationFrame(animate);
|
|
418
|
+
};
|
|
419
|
+
const setup = () => {
|
|
420
|
+
const { width, height } = container.getBoundingClientRect();
|
|
421
|
+
dimensionsRef.current = { width, height };
|
|
422
|
+
dpr = window.devicePixelRatio || 1;
|
|
423
|
+
canvas.width = width * dpr;
|
|
424
|
+
canvas.height = height * dpr;
|
|
425
|
+
canvas.style.width = `${width}px`;
|
|
426
|
+
canvas.style.height = `${height}px`;
|
|
427
|
+
if (shape === 4) {
|
|
428
|
+
buildSquareGraph(width, height);
|
|
429
|
+
} else {
|
|
430
|
+
buildHexGraph(width, height);
|
|
431
|
+
}
|
|
432
|
+
particlesRef.current = [];
|
|
433
|
+
trailsRef.current = [];
|
|
434
|
+
activeEdgesRef.current.clear();
|
|
435
|
+
explosionsRef.current = [];
|
|
436
|
+
nodeGlowsRef.current = [];
|
|
437
|
+
};
|
|
438
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
439
|
+
setup();
|
|
440
|
+
});
|
|
441
|
+
resizeObserver.observe(container);
|
|
442
|
+
setup();
|
|
443
|
+
animationRef.current = requestAnimationFrame(animate);
|
|
444
|
+
return () => {
|
|
445
|
+
resizeObserver.disconnect();
|
|
446
|
+
cancelAnimationFrame(animationRef.current);
|
|
447
|
+
};
|
|
448
|
+
}, [shape, cellSize, lineColor, lineWidth, animated, lightColor, lightSpeed, minTravel, maxTravel, spawnRate, splitChance, trailFadeSpeed, buildSquareGraph, buildHexGraph, getConnectedNodes]);
|
|
449
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: containerRef, className: `relative w-full h-full ${className}`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("canvas", { ref: canvasRef, className: "absolute inset-0" }) });
|
|
450
|
+
}
|
|
451
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
452
|
+
0 && (module.exports = {
|
|
453
|
+
Grid
|
|
454
|
+
});
|
|
455
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/Grid.tsx"],"sourcesContent":["export { Grid, type GridProps } from \"./Grid\";\nexport { Grid as default } from \"./Grid\";\n","\"use client\";\n\nimport { useEffect, useRef, useCallback } from \"react\";\n\nexport interface GridProps {\n /** Grid shape: 4 for squares, 6 for hexagons */\n shape?: 4 | 6;\n /** Size of each cell in pixels */\n cellSize?: number;\n /** Color of the grid lines (use \"transparent\" to hide) */\n lineColor?: string;\n /** Width of the grid lines */\n lineWidth?: number;\n /** Additional CSS classes */\n className?: string;\n /** Enable animated light particles */\n animated?: boolean;\n /** Color of the light particles and trails */\n lightColor?: string;\n /** Speed of the light particles (1-5 recommended) */\n lightSpeed?: number;\n /** Minimum travel distance before particle dies */\n minTravel?: number;\n /** Maximum travel distance before particle dies */\n maxTravel?: number;\n /** Milliseconds between particle spawns */\n spawnRate?: number;\n /** Probability of particle splitting (0-1) */\n splitChance?: number;\n /** Speed at which trails fade (lower = slower fade) */\n trailFadeSpeed?: number;\n}\n\ninterface Node {\n x: number;\n y: number;\n key: string;\n}\n\ninterface Edge {\n from: Node;\n to: Node;\n key: string;\n}\n\ninterface Particle {\n id: number;\n currentNode: Node;\n targetNode: Node;\n progress: number;\n traveled: number;\n maxTravel: number;\n canSplit: boolean;\n dead: boolean;\n}\n\ninterface Trail {\n fromX: number;\n fromY: number;\n toX: number;\n toY: number;\n progress: number;\n opacity: number;\n edgeKey: string;\n}\n\ninterface Explosion {\n x: number;\n y: number;\n radius: number;\n maxRadius: number;\n opacity: number;\n}\n\ninterface NodeGlow {\n x: number;\n y: number;\n opacity: number;\n}\n\nexport function Grid({\n shape = 4,\n cellSize = 40,\n lineColor = \"#e5e7eb\",\n lineWidth = 1,\n className = \"\",\n animated = false,\n lightColor = \"#3b82f6\",\n lightSpeed = 2,\n minTravel = 2,\n maxTravel = 6,\n spawnRate = 1000,\n splitChance = 0.3,\n trailFadeSpeed = 0.01,\n}: GridProps) {\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const nodesRef = useRef<Map<string, Node>>(new Map());\n const edgesRef = useRef<Edge[]>([]);\n const adjacencyRef = useRef<Map<string, Edge[]>>(new Map());\n const topNodesRef = useRef<Node[]>([]);\n const animationRef = useRef<number>(0);\n const particlesRef = useRef<Particle[]>([]);\n const trailsRef = useRef<Trail[]>([]);\n const lastSpawnRef = useRef<number>(0);\n const particleIdRef = useRef<number>(0);\n const dimensionsRef = useRef({ width: 0, height: 0 });\n const activeEdgesRef = useRef<Set<string>>(new Set());\n const explosionsRef = useRef<Explosion[]>([]);\n const nodeGlowsRef = useRef<NodeGlow[]>([]);\n\n const nodeKey = (x: number, y: number) => `${Math.round(x * 100)},${Math.round(y * 100)}`;\n const edgeKey = (n1: Node, n2: Node) => {\n const keys = [n1.key, n2.key].sort();\n return `${keys[0]}-${keys[1]}`;\n };\n\n const getOrCreateNode = useCallback((x: number, y: number): Node => {\n const key = nodeKey(x, y);\n if (!nodesRef.current.has(key)) {\n nodesRef.current.set(key, { x, y, key });\n }\n return nodesRef.current.get(key)!;\n }, []);\n\n const addEdge = useCallback((x1: number, y1: number, x2: number, y2: number) => {\n const from = getOrCreateNode(x1, y1);\n const to = getOrCreateNode(x2, y2);\n const key = edgeKey(from, to);\n\n const existingEdge = edgesRef.current.find(e => e.key === key);\n if (existingEdge) return;\n\n const edge: Edge = { from, to, key };\n edgesRef.current.push(edge);\n\n if (!adjacencyRef.current.has(from.key)) {\n adjacencyRef.current.set(from.key, []);\n }\n if (!adjacencyRef.current.has(to.key)) {\n adjacencyRef.current.set(to.key, []);\n }\n adjacencyRef.current.get(from.key)!.push(edge);\n adjacencyRef.current.get(to.key)!.push(edge);\n }, [getOrCreateNode]);\n\n const buildSquareGraph = useCallback((width: number, height: number) => {\n nodesRef.current.clear();\n edgesRef.current = [];\n adjacencyRef.current.clear();\n topNodesRef.current = [];\n\n const cols = Math.ceil(width / cellSize) + 1;\n const rows = Math.ceil(height / cellSize) + 1;\n\n for (let i = 0; i <= cols; i++) {\n for (let j = 0; j <= rows; j++) {\n const x = i * cellSize;\n const y = j * cellSize;\n if (i < cols) addEdge(x, y, x + cellSize, y);\n if (j < rows) addEdge(x, y, x, y + cellSize);\n }\n }\n\n for (let i = 0; i <= cols; i++) {\n const node = nodesRef.current.get(nodeKey(i * cellSize, 0));\n if (node) topNodesRef.current.push(node);\n }\n }, [cellSize, addEdge]);\n\n const buildHexGraph = useCallback((width: number, height: number) => {\n nodesRef.current.clear();\n edgesRef.current = [];\n adjacencyRef.current.clear();\n topNodesRef.current = [];\n\n const size = cellSize / 2;\n const hexWidth = Math.sqrt(3) * size;\n const vertSpacing = size * 1.5;\n\n const cols = Math.ceil(width / hexWidth) + 2;\n const rows = Math.ceil(height / vertSpacing) + 2;\n\n for (let row = -1; row < rows; row++) {\n for (let col = -1; col < cols; col++) {\n const cx = col * hexWidth + (row % 2 === 0 ? 0 : hexWidth / 2);\n const cy = row * vertSpacing;\n\n const vertices: { x: number; y: number }[] = [];\n for (let i = 0; i < 6; i++) {\n const angle = (Math.PI / 3) * i - Math.PI / 2;\n vertices.push({\n x: cx + size * Math.cos(angle),\n y: cy + size * Math.sin(angle),\n });\n }\n\n for (let i = 0; i < 6; i++) {\n const v1 = vertices[i];\n const v2 = vertices[(i + 1) % 6];\n addEdge(v1.x, v1.y, v2.x, v2.y);\n }\n }\n }\n\n const sortedNodes = Array.from(nodesRef.current.values())\n .filter(n => n.y >= 0 && n.y <= size)\n .sort((a, b) => a.x - b.x);\n topNodesRef.current = sortedNodes;\n }, [cellSize, addEdge]);\n\n const getConnectedNodes = useCallback((node: Node, excludeNode?: Node): Node[] => {\n const edges = adjacencyRef.current.get(node.key) || [];\n return edges\n .map(e => (e.from.key === node.key ? e.to : e.from))\n .filter(n => !excludeNode || n.key !== excludeNode.key);\n }, []);\n\n useEffect(() => {\n const canvas = canvasRef.current;\n const container = containerRef.current;\n if (!canvas || !container) return;\n\n let dpr = 1;\n\n const drawGrid = (ctx: CanvasRenderingContext2D, width: number, height: number) => {\n ctx.clearRect(0, 0, width, height);\n ctx.strokeStyle = lineColor;\n ctx.lineWidth = lineWidth;\n ctx.beginPath();\n\n for (const edge of edgesRef.current) {\n ctx.moveTo(edge.from.x, edge.from.y);\n ctx.lineTo(edge.to.x, edge.to.y);\n }\n\n ctx.stroke();\n };\n\n const drawTrails = (ctx: CanvasRenderingContext2D) => {\n for (const trail of trailsRef.current) {\n if (trail.opacity <= 0) continue;\n\n const alpha = Math.floor(trail.opacity * 0.08 * 255).toString(16).padStart(2, '0');\n\n ctx.strokeStyle = lightColor + alpha;\n ctx.lineWidth = 1;\n ctx.lineCap = \"round\";\n ctx.beginPath();\n ctx.moveTo(trail.fromX, trail.fromY);\n\n if (trail.progress < 1) {\n const endX = trail.fromX + (trail.toX - trail.fromX) * trail.progress;\n const endY = trail.fromY + (trail.toY - trail.fromY) * trail.progress;\n ctx.lineTo(endX, endY);\n } else {\n ctx.lineTo(trail.toX, trail.toY);\n }\n ctx.stroke();\n\n ctx.shadowColor = lightColor;\n ctx.shadowBlur = 2;\n ctx.stroke();\n ctx.shadowBlur = 0;\n }\n };\n\n const drawParticles = (ctx: CanvasRenderingContext2D) => {\n for (const particle of particlesRef.current) {\n if (particle.dead) continue;\n\n const x = particle.currentNode.x + (particle.targetNode.x - particle.currentNode.x) * particle.progress;\n const y = particle.currentNode.y + (particle.targetNode.y - particle.currentNode.y) * particle.progress;\n\n ctx.fillStyle = lightColor;\n ctx.beginPath();\n ctx.arc(x, y, 3, 0, Math.PI * 2);\n ctx.fill();\n }\n };\n\n const drawExplosions = (ctx: CanvasRenderingContext2D) => {\n for (const explosion of explosionsRef.current) {\n if (explosion.opacity <= 0) continue;\n\n const alpha = Math.floor(explosion.opacity * 255).toString(16).padStart(2, '0');\n ctx.strokeStyle = lightColor + alpha;\n ctx.lineWidth = 2;\n ctx.beginPath();\n ctx.arc(explosion.x, explosion.y, explosion.radius, 0, Math.PI * 2);\n ctx.stroke();\n }\n };\n\n const updateExplosions = () => {\n for (const explosion of explosionsRef.current) {\n explosion.radius += 0.5;\n explosion.opacity -= 0.08;\n }\n explosionsRef.current = explosionsRef.current.filter(e => e.opacity > 0);\n };\n\n const createExplosion = (x: number, y: number) => {\n explosionsRef.current.push({\n x,\n y,\n radius: 2,\n maxRadius: 8,\n opacity: 1,\n });\n };\n\n const createNodeGlow = (x: number, y: number) => {\n nodeGlowsRef.current.push({\n x,\n y,\n opacity: 1,\n });\n };\n\n const drawNodeGlows = (ctx: CanvasRenderingContext2D) => {\n for (const glow of nodeGlowsRef.current) {\n if (glow.opacity <= 0) continue;\n\n const alpha = Math.floor(glow.opacity * 0.4 * 255).toString(16).padStart(2, '0');\n ctx.fillStyle = lightColor + alpha;\n ctx.beginPath();\n ctx.arc(glow.x, glow.y, 2, 0, Math.PI * 2);\n ctx.fill();\n }\n };\n\n const updateNodeGlows = () => {\n for (const glow of nodeGlowsRef.current) {\n glow.opacity -= trailFadeSpeed * 3;\n }\n nodeGlowsRef.current = nodeGlowsRef.current.filter(g => g.opacity > 0);\n };\n\n const getRandomTravel = () => {\n return Math.floor(Math.random() * (maxTravel - minTravel + 1)) + minTravel;\n };\n\n const makeEdgeKey = (n1: Node, n2: Node) => {\n const keys = [n1.key, n2.key].sort();\n return `${keys[0]}-${keys[1]}`;\n };\n\n const spawnParticle = () => {\n if (topNodesRef.current.length === 0) return;\n\n const startNode = topNodesRef.current[Math.floor(Math.random() * topNodesRef.current.length)];\n const connectedNodes = getConnectedNodes(startNode);\n\n const downwardNodes = connectedNodes.filter(n => n.y > startNode.y);\n const targetNodes = downwardNodes.length > 0 ? downwardNodes : connectedNodes;\n\n const availableNodes = targetNodes.filter(n => {\n const key = makeEdgeKey(startNode, n);\n return !activeEdgesRef.current.has(key);\n });\n\n if (availableNodes.length === 0) return;\n\n const targetNode = availableNodes[Math.floor(Math.random() * availableNodes.length)];\n const edgeKeyStr = makeEdgeKey(startNode, targetNode);\n activeEdgesRef.current.add(edgeKeyStr);\n\n particlesRef.current.push({\n id: particleIdRef.current++,\n currentNode: startNode,\n targetNode,\n progress: 0,\n traveled: 0,\n maxTravel: getRandomTravel(),\n canSplit: true,\n dead: false,\n });\n\n trailsRef.current.push({\n fromX: startNode.x,\n fromY: startNode.y,\n toX: targetNode.x,\n toY: targetNode.y,\n progress: 0,\n opacity: 1,\n edgeKey: edgeKeyStr,\n });\n };\n\n const updateParticles = () => {\n const newParticles: Particle[] = [];\n\n for (const particle of particlesRef.current) {\n if (particle.dead) continue;\n\n particle.progress += lightSpeed * 0.02;\n\n const trailIndex = trailsRef.current.findIndex(\n t => t.fromX === particle.currentNode.x &&\n t.fromY === particle.currentNode.y &&\n t.toX === particle.targetNode.x &&\n t.toY === particle.targetNode.y &&\n t.progress < 1\n );\n if (trailIndex !== -1) {\n trailsRef.current[trailIndex].progress = Math.min(particle.progress, 1);\n }\n\n if (particle.progress >= 1) {\n createNodeGlow(particle.targetNode.x, particle.targetNode.y);\n particle.traveled++;\n\n if (particle.traveled >= particle.maxTravel) {\n const x = particle.targetNode.x;\n const y = particle.targetNode.y;\n createExplosion(x, y);\n particle.dead = true;\n continue;\n }\n\n const currentNode = particle.targetNode;\n const connectedNodes = getConnectedNodes(currentNode, particle.currentNode);\n\n const availableNodes = connectedNodes.filter(n => {\n const key = makeEdgeKey(currentNode, n);\n return !activeEdgesRef.current.has(key);\n });\n\n if (availableNodes.length === 0) {\n createExplosion(currentNode.x, currentNode.y);\n particle.dead = true;\n continue;\n }\n\n const shouldSplit = particle.canSplit && Math.random() < splitChance && availableNodes.length >= 2;\n\n if (shouldSplit) {\n const shuffled = [...availableNodes].sort(() => Math.random() - 0.5);\n const target1 = shuffled[0];\n const target2 = shuffled[1];\n\n const edgeKey1 = makeEdgeKey(currentNode, target1);\n const edgeKey2 = makeEdgeKey(currentNode, target2);\n activeEdgesRef.current.add(edgeKey1);\n activeEdgesRef.current.add(edgeKey2);\n\n particle.currentNode = currentNode;\n particle.targetNode = target1;\n particle.progress = 0;\n particle.canSplit = false;\n\n trailsRef.current.push({\n fromX: currentNode.x,\n fromY: currentNode.y,\n toX: target1.x,\n toY: target1.y,\n progress: 0,\n opacity: 1,\n edgeKey: edgeKey1,\n });\n\n newParticles.push({\n id: particleIdRef.current++,\n currentNode: currentNode,\n targetNode: target2,\n progress: 0,\n traveled: particle.traveled,\n maxTravel: particle.maxTravel,\n canSplit: false,\n dead: false,\n });\n\n trailsRef.current.push({\n fromX: currentNode.x,\n fromY: currentNode.y,\n toX: target2.x,\n toY: target2.y,\n progress: 0,\n opacity: 1,\n edgeKey: edgeKey2,\n });\n } else {\n const targetNode = availableNodes[Math.floor(Math.random() * availableNodes.length)];\n const newEdgeKey = makeEdgeKey(currentNode, targetNode);\n activeEdgesRef.current.add(newEdgeKey);\n\n particle.currentNode = currentNode;\n particle.targetNode = targetNode;\n particle.progress = 0;\n\n trailsRef.current.push({\n fromX: currentNode.x,\n fromY: currentNode.y,\n toX: targetNode.x,\n toY: targetNode.y,\n progress: 0,\n opacity: 1,\n edgeKey: newEdgeKey,\n });\n }\n }\n }\n\n particlesRef.current.push(...newParticles);\n particlesRef.current = particlesRef.current.filter(p => !p.dead);\n };\n\n const updateTrails = () => {\n for (const trail of trailsRef.current) {\n if (trail.progress >= 1) {\n trail.opacity -= trailFadeSpeed;\n }\n }\n const fadedTrails = trailsRef.current.filter(t => t.opacity <= 0);\n for (const trail of fadedTrails) {\n activeEdgesRef.current.delete(trail.edgeKey);\n }\n trailsRef.current = trailsRef.current.filter(t => t.opacity > 0);\n };\n\n const animate = (timestamp: number) => {\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return;\n\n const { width, height } = dimensionsRef.current;\n\n ctx.save();\n ctx.scale(dpr, dpr);\n drawGrid(ctx, width, height);\n\n if (animated) {\n if (timestamp - lastSpawnRef.current > spawnRate) {\n spawnParticle();\n lastSpawnRef.current = timestamp;\n }\n\n updateParticles();\n updateTrails();\n updateExplosions();\n updateNodeGlows();\n drawTrails(ctx);\n drawNodeGlows(ctx);\n drawParticles(ctx);\n drawExplosions(ctx);\n }\n\n ctx.restore();\n animationRef.current = requestAnimationFrame(animate);\n };\n\n const setup = () => {\n const { width, height } = container.getBoundingClientRect();\n dimensionsRef.current = { width, height };\n dpr = window.devicePixelRatio || 1;\n\n canvas.width = width * dpr;\n canvas.height = height * dpr;\n canvas.style.width = `${width}px`;\n canvas.style.height = `${height}px`;\n\n if (shape === 4) {\n buildSquareGraph(width, height);\n } else {\n buildHexGraph(width, height);\n }\n\n particlesRef.current = [];\n trailsRef.current = [];\n activeEdgesRef.current.clear();\n explosionsRef.current = [];\n nodeGlowsRef.current = [];\n };\n\n const resizeObserver = new ResizeObserver(() => {\n setup();\n });\n\n resizeObserver.observe(container);\n setup();\n animationRef.current = requestAnimationFrame(animate);\n\n return () => {\n resizeObserver.disconnect();\n cancelAnimationFrame(animationRef.current);\n };\n }, [shape, cellSize, lineColor, lineWidth, animated, lightColor, lightSpeed, minTravel, maxTravel, spawnRate, splitChance, trailFadeSpeed, buildSquareGraph, buildHexGraph, getConnectedNodes]);\n\n return (\n <div ref={containerRef} className={`relative w-full h-full ${className}`}>\n <canvas ref={canvasRef} className=\"absolute inset-0\" />\n </div>\n );\n}\n\nexport default Grid;\n"],"mappings":"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","names":[]}
|