react-grid-lights 1.0.1 → 1.0.2
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.d.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +30 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +30 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -29,7 +29,9 @@ interface GridProps {
|
|
|
29
29
|
trailFadeSpeed?: number;
|
|
30
30
|
/** Enable spawning particles from the bottom as well as the top */
|
|
31
31
|
bidirectional?: boolean;
|
|
32
|
+
/** Length of the light trail (number of history points) */
|
|
33
|
+
trailLength?: number;
|
|
32
34
|
}
|
|
33
|
-
declare function Grid({ shape, cellSize, lineColor, lineWidth, className, animated, lightColor, lightSpeed, minTravel, maxTravel, spawnRate, splitChance, trailFadeSpeed, bidirectional, }: GridProps): react_jsx_runtime.JSX.Element;
|
|
35
|
+
declare function Grid({ shape, cellSize, lineColor, lineWidth, className, animated, lightColor, lightSpeed, minTravel, maxTravel, spawnRate, splitChance, trailFadeSpeed, bidirectional, trailLength, }: GridProps): react_jsx_runtime.JSX.Element;
|
|
34
36
|
|
|
35
37
|
export { Grid, type GridProps, Grid as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -29,7 +29,9 @@ interface GridProps {
|
|
|
29
29
|
trailFadeSpeed?: number;
|
|
30
30
|
/** Enable spawning particles from the bottom as well as the top */
|
|
31
31
|
bidirectional?: boolean;
|
|
32
|
+
/** Length of the light trail (number of history points) */
|
|
33
|
+
trailLength?: number;
|
|
32
34
|
}
|
|
33
|
-
declare function Grid({ shape, cellSize, lineColor, lineWidth, className, animated, lightColor, lightSpeed, minTravel, maxTravel, spawnRate, splitChance, trailFadeSpeed, bidirectional, }: GridProps): react_jsx_runtime.JSX.Element;
|
|
35
|
+
declare function Grid({ shape, cellSize, lineColor, lineWidth, className, animated, lightColor, lightSpeed, minTravel, maxTravel, spawnRate, splitChance, trailFadeSpeed, bidirectional, trailLength, }: GridProps): react_jsx_runtime.JSX.Element;
|
|
34
36
|
|
|
35
37
|
export { Grid, type GridProps, Grid as default };
|
package/dist/index.js
CHANGED
|
@@ -43,7 +43,8 @@ function Grid({
|
|
|
43
43
|
spawnRate = 1e3,
|
|
44
44
|
splitChance = 0.3,
|
|
45
45
|
trailFadeSpeed = 0.01,
|
|
46
|
-
bidirectional = false
|
|
46
|
+
bidirectional = false,
|
|
47
|
+
trailLength = 15
|
|
47
48
|
}) {
|
|
48
49
|
const canvasRef = (0, import_react.useRef)(null);
|
|
49
50
|
const containerRef = (0, import_react.useRef)(null);
|
|
@@ -214,18 +215,38 @@ function Grid({
|
|
|
214
215
|
if (history.length >= 2) {
|
|
215
216
|
ctx.lineCap = "round";
|
|
216
217
|
ctx.lineJoin = "round";
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
218
|
+
const r = parseInt(lightColor.slice(1, 3), 16);
|
|
219
|
+
const g = parseInt(lightColor.slice(3, 5), 16);
|
|
220
|
+
const b = parseInt(lightColor.slice(5, 7), 16);
|
|
221
|
+
const lighterR = Math.floor(r + (255 - r) * 0.6);
|
|
222
|
+
const lighterG = Math.floor(g + (255 - g) * 0.6);
|
|
223
|
+
const lighterB = Math.floor(b + (255 - b) * 0.6);
|
|
224
|
+
ctx.strokeStyle = `rgb(${lighterR}, ${lighterG}, ${lighterB})`;
|
|
225
|
+
const maxWidth = 4;
|
|
226
|
+
const minWidth = 0.5;
|
|
221
227
|
for (let i = 1; i < history.length; i++) {
|
|
228
|
+
const progress = i / (history.length - 1);
|
|
229
|
+
ctx.lineWidth = minWidth + (maxWidth - minWidth) * progress;
|
|
230
|
+
ctx.beginPath();
|
|
231
|
+
ctx.moveTo(history[i - 1].x, history[i - 1].y);
|
|
222
232
|
ctx.lineTo(history[i].x, history[i].y);
|
|
233
|
+
ctx.stroke();
|
|
223
234
|
}
|
|
224
|
-
ctx.stroke();
|
|
225
235
|
}
|
|
226
236
|
ctx.fillStyle = lightColor;
|
|
227
237
|
ctx.beginPath();
|
|
228
|
-
|
|
238
|
+
let angle = 0;
|
|
239
|
+
if (history.length >= 2) {
|
|
240
|
+
const prev = history[history.length - 2];
|
|
241
|
+
angle = Math.atan2(head.y - prev.y, head.x - prev.x);
|
|
242
|
+
}
|
|
243
|
+
ctx.save();
|
|
244
|
+
ctx.translate(head.x, head.y);
|
|
245
|
+
ctx.rotate(angle);
|
|
246
|
+
ctx.moveTo(-3, 0);
|
|
247
|
+
ctx.quadraticCurveTo(1, -2.5, 2, 0);
|
|
248
|
+
ctx.quadraticCurveTo(1, 2.5, -3, 0);
|
|
249
|
+
ctx.restore();
|
|
229
250
|
ctx.fill();
|
|
230
251
|
}
|
|
231
252
|
};
|
|
@@ -342,7 +363,7 @@ function Grid({
|
|
|
342
363
|
};
|
|
343
364
|
const updateParticles = () => {
|
|
344
365
|
const newParticles = [];
|
|
345
|
-
const maxHistoryLength =
|
|
366
|
+
const maxHistoryLength = trailLength;
|
|
346
367
|
for (const particle of particlesRef.current) {
|
|
347
368
|
if (particle.dead) continue;
|
|
348
369
|
particle.progress += lightSpeed * 0.02;
|
|
@@ -531,6 +552,7 @@ function Grid({
|
|
|
531
552
|
splitChance,
|
|
532
553
|
trailFadeSpeed,
|
|
533
554
|
bidirectional,
|
|
555
|
+
trailLength,
|
|
534
556
|
buildSquareGraph,
|
|
535
557
|
buildHexGraph,
|
|
536
558
|
getConnectedNodes
|
package/dist/index.js.map
CHANGED
|
@@ -1 +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 /** Enable spawning particles from the bottom as well as the top */\n bidirectional?: boolean;\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 direction: 1 | -1;\n history: { x: number; y: number }[];\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 bidirectional = false,\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 bottomNodesRef = 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 const spawnFromTopRef = useRef<boolean>(true);\n\n const nodeKey = (x: number, y: number) =>\n `${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(\n (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 },\n [getOrCreateNode]\n );\n\n const buildSquareGraph = useCallback(\n (width: number, height: number) => {\n nodesRef.current.clear();\n edgesRef.current = [];\n adjacencyRef.current.clear();\n topNodesRef.current = [];\n bottomNodesRef.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 const maxY = rows * cellSize;\n for (let i = 0; i <= cols; i++) {\n const topNode = nodesRef.current.get(nodeKey(i * cellSize, 0));\n if (topNode) topNodesRef.current.push(topNode);\n\n const bottomNode = nodesRef.current.get(nodeKey(i * cellSize, maxY));\n if (bottomNode) bottomNodesRef.current.push(bottomNode);\n }\n },\n [cellSize, addEdge]\n );\n\n const buildHexGraph = useCallback(\n (width: number, height: number) => {\n nodesRef.current.clear();\n edgesRef.current = [];\n adjacencyRef.current.clear();\n topNodesRef.current = [];\n bottomNodesRef.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 allNodes = Array.from(nodesRef.current.values());\n\n const visibleNodes = allNodes.filter((n) => n.y >= 0 && n.y <= height);\n\n topNodesRef.current = visibleNodes\n .filter((n) => n.y <= size * 2)\n .sort((a, b) => a.x - b.x);\n\n bottomNodesRef.current = visibleNodes\n .filter((n) => n.y >= height - size * 2)\n .sort((a, b) => a.x - b.x);\n },\n [cellSize, addEdge]\n );\n\n const getConnectedNodes = useCallback(\n (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 );\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 = (\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number\n ) => {\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)\n .toString(16)\n .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 history = particle.history;\n if (history.length === 0) continue;\n\n const head = history[history.length - 1];\n\n if (history.length >= 2) {\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n ctx.strokeStyle = lightColor + '40';\n ctx.lineWidth = 2;\n ctx.beginPath();\n ctx.moveTo(history[0].x, history[0].y);\n\n for (let i = 1; i < history.length; i++) {\n ctx.lineTo(history[i].x, history[i].y);\n }\n ctx.stroke();\n }\n\n ctx.fillStyle = lightColor;\n ctx.beginPath();\n ctx.arc(head.x, head.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)\n .toString(16)\n .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(\n (e) => e.opacity > 0\n );\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)\n .toString(16)\n .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 (\n Math.floor(Math.random() * (maxTravel - minTravel + 1)) + minTravel\n );\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 trySpawn = (fromTop: boolean): boolean => {\n const sourceNodes = fromTop\n ? topNodesRef.current\n : bottomNodesRef.current;\n const direction: 1 | -1 = fromTop ? 1 : -1;\n\n if (sourceNodes.length === 0) return false;\n\n const startNode =\n sourceNodes[Math.floor(Math.random() * sourceNodes.length)];\n const connectedNodes = getConnectedNodes(startNode);\n\n const preferredNodes = connectedNodes.filter((n) =>\n fromTop ? n.y > startNode.y : n.y < startNode.y\n );\n const targetNodes =\n preferredNodes.length > 0 ? preferredNodes : 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 false;\n\n const targetNode =\n 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 direction,\n history: [{ x: startNode.x, y: startNode.y }],\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 return true;\n };\n\n const spawnParticle = () => {\n if (bidirectional) {\n const fromTop = spawnFromTopRef.current;\n spawnFromTopRef.current = !spawnFromTopRef.current;\n\n if (!trySpawn(fromTop)) {\n trySpawn(!fromTop);\n }\n } else {\n trySpawn(true);\n }\n };\n\n const updateParticles = () => {\n const newParticles: Particle[] = [];\n const maxHistoryLength = 10;\n\n for (const particle of particlesRef.current) {\n if (particle.dead) continue;\n\n particle.progress += lightSpeed * 0.02;\n\n const currentX =\n particle.currentNode.x +\n (particle.targetNode.x - particle.currentNode.x) * particle.progress;\n const currentY =\n particle.currentNode.y +\n (particle.targetNode.y - particle.currentNode.y) * particle.progress;\n particle.history.push({ x: currentX, y: currentY });\n if (particle.history.length > maxHistoryLength) {\n particle.history.shift();\n }\n\n const trailIndex = trailsRef.current.findIndex(\n (t) =>\n 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(\n particle.progress,\n 1\n );\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(\n currentNode,\n particle.currentNode\n );\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 =\n particle.canSplit &&\n Math.random() < splitChance &&\n availableNodes.length >= 2;\n\n if (shouldSplit) {\n const shuffled = [...availableNodes].sort(\n () => Math.random() - 0.5\n );\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 direction: particle.direction,\n history: [{ x: currentNode.x, y: currentNode.y }],\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 =\n 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 }, [\n shape,\n cellSize,\n lineColor,\n lineWidth,\n animated,\n lightColor,\n lightSpeed,\n minTravel,\n maxTravel,\n spawnRate,\n splitChance,\n trailFadeSpeed,\n bidirectional,\n buildSquareGraph,\n buildHexGraph,\n getConnectedNodes,\n ]);\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":[]}
|
|
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 /** Enable spawning particles from the bottom as well as the top */\n bidirectional?: boolean;\n /** Length of the light trail (number of history points) */\n trailLength?: 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 direction: 1 | -1;\n history: { x: number; y: number }[];\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 bidirectional = false,\n trailLength = 15,\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 bottomNodesRef = 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 const spawnFromTopRef = useRef<boolean>(true);\n\n const nodeKey = (x: number, y: number) =>\n `${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(\n (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 },\n [getOrCreateNode]\n );\n\n const buildSquareGraph = useCallback(\n (width: number, height: number) => {\n nodesRef.current.clear();\n edgesRef.current = [];\n adjacencyRef.current.clear();\n topNodesRef.current = [];\n bottomNodesRef.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 const maxY = rows * cellSize;\n for (let i = 0; i <= cols; i++) {\n const topNode = nodesRef.current.get(nodeKey(i * cellSize, 0));\n if (topNode) topNodesRef.current.push(topNode);\n\n const bottomNode = nodesRef.current.get(nodeKey(i * cellSize, maxY));\n if (bottomNode) bottomNodesRef.current.push(bottomNode);\n }\n },\n [cellSize, addEdge]\n );\n\n const buildHexGraph = useCallback(\n (width: number, height: number) => {\n nodesRef.current.clear();\n edgesRef.current = [];\n adjacencyRef.current.clear();\n topNodesRef.current = [];\n bottomNodesRef.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 allNodes = Array.from(nodesRef.current.values());\n\n const visibleNodes = allNodes.filter((n) => n.y >= 0 && n.y <= height);\n\n topNodesRef.current = visibleNodes\n .filter((n) => n.y <= size * 2)\n .sort((a, b) => a.x - b.x);\n\n bottomNodesRef.current = visibleNodes\n .filter((n) => n.y >= height - size * 2)\n .sort((a, b) => a.x - b.x);\n },\n [cellSize, addEdge]\n );\n\n const getConnectedNodes = useCallback(\n (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 );\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 = (\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number\n ) => {\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)\n .toString(16)\n .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 history = particle.history;\n if (history.length === 0) continue;\n\n const head = history[history.length - 1];\n\n if (history.length >= 2) {\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n const r = parseInt(lightColor.slice(1, 3), 16);\n const g = parseInt(lightColor.slice(3, 5), 16);\n const b = parseInt(lightColor.slice(5, 7), 16);\n const lighterR = Math.floor(r + (255 - r) * 0.6);\n const lighterG = Math.floor(g + (255 - g) * 0.6);\n const lighterB = Math.floor(b + (255 - b) * 0.6);\n ctx.strokeStyle = `rgb(${lighterR}, ${lighterG}, ${lighterB})`;\n\n const maxWidth = 4;\n const minWidth = 0.5;\n for (let i = 1; i < history.length; i++) {\n const progress = i / (history.length - 1);\n ctx.lineWidth = minWidth + (maxWidth - minWidth) * progress;\n ctx.beginPath();\n ctx.moveTo(history[i - 1].x, history[i - 1].y);\n ctx.lineTo(history[i].x, history[i].y);\n ctx.stroke();\n }\n }\n\n ctx.fillStyle = lightColor;\n ctx.beginPath();\n let angle = 0;\n if (history.length >= 2) {\n const prev = history[history.length - 2];\n angle = Math.atan2(head.y - prev.y, head.x - prev.x);\n }\n ctx.save();\n ctx.translate(head.x, head.y);\n ctx.rotate(angle);\n ctx.moveTo(-3, 0);\n ctx.quadraticCurveTo(1, -2.5, 2, 0);\n ctx.quadraticCurveTo(1, 2.5, -3, 0);\n ctx.restore();\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)\n .toString(16)\n .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(\n (e) => e.opacity > 0\n );\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)\n .toString(16)\n .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 (\n Math.floor(Math.random() * (maxTravel - minTravel + 1)) + minTravel\n );\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 trySpawn = (fromTop: boolean): boolean => {\n const sourceNodes = fromTop\n ? topNodesRef.current\n : bottomNodesRef.current;\n const direction: 1 | -1 = fromTop ? 1 : -1;\n\n if (sourceNodes.length === 0) return false;\n\n const startNode =\n sourceNodes[Math.floor(Math.random() * sourceNodes.length)];\n const connectedNodes = getConnectedNodes(startNode);\n\n const preferredNodes = connectedNodes.filter((n) =>\n fromTop ? n.y > startNode.y : n.y < startNode.y\n );\n const targetNodes =\n preferredNodes.length > 0 ? preferredNodes : 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 false;\n\n const targetNode =\n 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 direction,\n history: [{ x: startNode.x, y: startNode.y }],\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 return true;\n };\n\n const spawnParticle = () => {\n if (bidirectional) {\n const fromTop = spawnFromTopRef.current;\n spawnFromTopRef.current = !spawnFromTopRef.current;\n\n if (!trySpawn(fromTop)) {\n trySpawn(!fromTop);\n }\n } else {\n trySpawn(true);\n }\n };\n\n const updateParticles = () => {\n const newParticles: Particle[] = [];\n const maxHistoryLength = trailLength;\n\n for (const particle of particlesRef.current) {\n if (particle.dead) continue;\n\n particle.progress += lightSpeed * 0.02;\n\n const currentX =\n particle.currentNode.x +\n (particle.targetNode.x - particle.currentNode.x) * particle.progress;\n const currentY =\n particle.currentNode.y +\n (particle.targetNode.y - particle.currentNode.y) * particle.progress;\n particle.history.push({ x: currentX, y: currentY });\n if (particle.history.length > maxHistoryLength) {\n particle.history.shift();\n }\n\n const trailIndex = trailsRef.current.findIndex(\n (t) =>\n 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(\n particle.progress,\n 1\n );\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(\n currentNode,\n particle.currentNode\n );\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 =\n particle.canSplit &&\n Math.random() < splitChance &&\n availableNodes.length >= 2;\n\n if (shouldSplit) {\n const shuffled = [...availableNodes].sort(\n () => Math.random() - 0.5\n );\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 direction: particle.direction,\n history: [{ x: currentNode.x, y: currentNode.y }],\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 =\n 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 }, [\n shape,\n cellSize,\n lineColor,\n lineWidth,\n animated,\n lightColor,\n lightSpeed,\n minTravel,\n maxTravel,\n spawnRate,\n splitChance,\n trailFadeSpeed,\n bidirectional,\n trailLength,\n buildSquareGraph,\n buildHexGraph,\n getConnectedNodes,\n ]);\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":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -17,7 +17,8 @@ function Grid({
|
|
|
17
17
|
spawnRate = 1e3,
|
|
18
18
|
splitChance = 0.3,
|
|
19
19
|
trailFadeSpeed = 0.01,
|
|
20
|
-
bidirectional = false
|
|
20
|
+
bidirectional = false,
|
|
21
|
+
trailLength = 15
|
|
21
22
|
}) {
|
|
22
23
|
const canvasRef = useRef(null);
|
|
23
24
|
const containerRef = useRef(null);
|
|
@@ -188,18 +189,38 @@ function Grid({
|
|
|
188
189
|
if (history.length >= 2) {
|
|
189
190
|
ctx.lineCap = "round";
|
|
190
191
|
ctx.lineJoin = "round";
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
192
|
+
const r = parseInt(lightColor.slice(1, 3), 16);
|
|
193
|
+
const g = parseInt(lightColor.slice(3, 5), 16);
|
|
194
|
+
const b = parseInt(lightColor.slice(5, 7), 16);
|
|
195
|
+
const lighterR = Math.floor(r + (255 - r) * 0.6);
|
|
196
|
+
const lighterG = Math.floor(g + (255 - g) * 0.6);
|
|
197
|
+
const lighterB = Math.floor(b + (255 - b) * 0.6);
|
|
198
|
+
ctx.strokeStyle = `rgb(${lighterR}, ${lighterG}, ${lighterB})`;
|
|
199
|
+
const maxWidth = 4;
|
|
200
|
+
const minWidth = 0.5;
|
|
195
201
|
for (let i = 1; i < history.length; i++) {
|
|
202
|
+
const progress = i / (history.length - 1);
|
|
203
|
+
ctx.lineWidth = minWidth + (maxWidth - minWidth) * progress;
|
|
204
|
+
ctx.beginPath();
|
|
205
|
+
ctx.moveTo(history[i - 1].x, history[i - 1].y);
|
|
196
206
|
ctx.lineTo(history[i].x, history[i].y);
|
|
207
|
+
ctx.stroke();
|
|
197
208
|
}
|
|
198
|
-
ctx.stroke();
|
|
199
209
|
}
|
|
200
210
|
ctx.fillStyle = lightColor;
|
|
201
211
|
ctx.beginPath();
|
|
202
|
-
|
|
212
|
+
let angle = 0;
|
|
213
|
+
if (history.length >= 2) {
|
|
214
|
+
const prev = history[history.length - 2];
|
|
215
|
+
angle = Math.atan2(head.y - prev.y, head.x - prev.x);
|
|
216
|
+
}
|
|
217
|
+
ctx.save();
|
|
218
|
+
ctx.translate(head.x, head.y);
|
|
219
|
+
ctx.rotate(angle);
|
|
220
|
+
ctx.moveTo(-3, 0);
|
|
221
|
+
ctx.quadraticCurveTo(1, -2.5, 2, 0);
|
|
222
|
+
ctx.quadraticCurveTo(1, 2.5, -3, 0);
|
|
223
|
+
ctx.restore();
|
|
203
224
|
ctx.fill();
|
|
204
225
|
}
|
|
205
226
|
};
|
|
@@ -316,7 +337,7 @@ function Grid({
|
|
|
316
337
|
};
|
|
317
338
|
const updateParticles = () => {
|
|
318
339
|
const newParticles = [];
|
|
319
|
-
const maxHistoryLength =
|
|
340
|
+
const maxHistoryLength = trailLength;
|
|
320
341
|
for (const particle of particlesRef.current) {
|
|
321
342
|
if (particle.dead) continue;
|
|
322
343
|
particle.progress += lightSpeed * 0.02;
|
|
@@ -505,6 +526,7 @@ function Grid({
|
|
|
505
526
|
splitChance,
|
|
506
527
|
trailFadeSpeed,
|
|
507
528
|
bidirectional,
|
|
529
|
+
trailLength,
|
|
508
530
|
buildSquareGraph,
|
|
509
531
|
buildHexGraph,
|
|
510
532
|
getConnectedNodes
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/Grid.tsx"],"sourcesContent":["'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 /** Enable spawning particles from the bottom as well as the top */\n bidirectional?: boolean;\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 direction: 1 | -1;\n history: { x: number; y: number }[];\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 bidirectional = false,\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 bottomNodesRef = 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 const spawnFromTopRef = useRef<boolean>(true);\n\n const nodeKey = (x: number, y: number) =>\n `${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(\n (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 },\n [getOrCreateNode]\n );\n\n const buildSquareGraph = useCallback(\n (width: number, height: number) => {\n nodesRef.current.clear();\n edgesRef.current = [];\n adjacencyRef.current.clear();\n topNodesRef.current = [];\n bottomNodesRef.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 const maxY = rows * cellSize;\n for (let i = 0; i <= cols; i++) {\n const topNode = nodesRef.current.get(nodeKey(i * cellSize, 0));\n if (topNode) topNodesRef.current.push(topNode);\n\n const bottomNode = nodesRef.current.get(nodeKey(i * cellSize, maxY));\n if (bottomNode) bottomNodesRef.current.push(bottomNode);\n }\n },\n [cellSize, addEdge]\n );\n\n const buildHexGraph = useCallback(\n (width: number, height: number) => {\n nodesRef.current.clear();\n edgesRef.current = [];\n adjacencyRef.current.clear();\n topNodesRef.current = [];\n bottomNodesRef.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 allNodes = Array.from(nodesRef.current.values());\n\n const visibleNodes = allNodes.filter((n) => n.y >= 0 && n.y <= height);\n\n topNodesRef.current = visibleNodes\n .filter((n) => n.y <= size * 2)\n .sort((a, b) => a.x - b.x);\n\n bottomNodesRef.current = visibleNodes\n .filter((n) => n.y >= height - size * 2)\n .sort((a, b) => a.x - b.x);\n },\n [cellSize, addEdge]\n );\n\n const getConnectedNodes = useCallback(\n (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 );\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 = (\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number\n ) => {\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)\n .toString(16)\n .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 history = particle.history;\n if (history.length === 0) continue;\n\n const head = history[history.length - 1];\n\n if (history.length >= 2) {\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n ctx.strokeStyle = lightColor + '40';\n ctx.lineWidth = 2;\n ctx.beginPath();\n ctx.moveTo(history[0].x, history[0].y);\n\n for (let i = 1; i < history.length; i++) {\n ctx.lineTo(history[i].x, history[i].y);\n }\n ctx.stroke();\n }\n\n ctx.fillStyle = lightColor;\n ctx.beginPath();\n ctx.arc(head.x, head.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)\n .toString(16)\n .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(\n (e) => e.opacity > 0\n );\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)\n .toString(16)\n .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 (\n Math.floor(Math.random() * (maxTravel - minTravel + 1)) + minTravel\n );\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 trySpawn = (fromTop: boolean): boolean => {\n const sourceNodes = fromTop\n ? topNodesRef.current\n : bottomNodesRef.current;\n const direction: 1 | -1 = fromTop ? 1 : -1;\n\n if (sourceNodes.length === 0) return false;\n\n const startNode =\n sourceNodes[Math.floor(Math.random() * sourceNodes.length)];\n const connectedNodes = getConnectedNodes(startNode);\n\n const preferredNodes = connectedNodes.filter((n) =>\n fromTop ? n.y > startNode.y : n.y < startNode.y\n );\n const targetNodes =\n preferredNodes.length > 0 ? preferredNodes : 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 false;\n\n const targetNode =\n 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 direction,\n history: [{ x: startNode.x, y: startNode.y }],\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 return true;\n };\n\n const spawnParticle = () => {\n if (bidirectional) {\n const fromTop = spawnFromTopRef.current;\n spawnFromTopRef.current = !spawnFromTopRef.current;\n\n if (!trySpawn(fromTop)) {\n trySpawn(!fromTop);\n }\n } else {\n trySpawn(true);\n }\n };\n\n const updateParticles = () => {\n const newParticles: Particle[] = [];\n const maxHistoryLength = 10;\n\n for (const particle of particlesRef.current) {\n if (particle.dead) continue;\n\n particle.progress += lightSpeed * 0.02;\n\n const currentX =\n particle.currentNode.x +\n (particle.targetNode.x - particle.currentNode.x) * particle.progress;\n const currentY =\n particle.currentNode.y +\n (particle.targetNode.y - particle.currentNode.y) * particle.progress;\n particle.history.push({ x: currentX, y: currentY });\n if (particle.history.length > maxHistoryLength) {\n particle.history.shift();\n }\n\n const trailIndex = trailsRef.current.findIndex(\n (t) =>\n 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(\n particle.progress,\n 1\n );\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(\n currentNode,\n particle.currentNode\n );\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 =\n particle.canSplit &&\n Math.random() < splitChance &&\n availableNodes.length >= 2;\n\n if (shouldSplit) {\n const shuffled = [...availableNodes].sort(\n () => Math.random() - 0.5\n );\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 direction: particle.direction,\n history: [{ x: currentNode.x, y: currentNode.y }],\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 =\n 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 }, [\n shape,\n cellSize,\n lineColor,\n lineWidth,\n animated,\n lightColor,\n lightSpeed,\n minTravel,\n maxTravel,\n spawnRate,\n splitChance,\n trailFadeSpeed,\n bidirectional,\n buildSquareGraph,\n buildHexGraph,\n getConnectedNodes,\n ]);\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":[]}
|
|
1
|
+
{"version":3,"sources":["../src/Grid.tsx"],"sourcesContent":["'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 /** Enable spawning particles from the bottom as well as the top */\n bidirectional?: boolean;\n /** Length of the light trail (number of history points) */\n trailLength?: 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 direction: 1 | -1;\n history: { x: number; y: number }[];\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 bidirectional = false,\n trailLength = 15,\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 bottomNodesRef = 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 const spawnFromTopRef = useRef<boolean>(true);\n\n const nodeKey = (x: number, y: number) =>\n `${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(\n (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 },\n [getOrCreateNode]\n );\n\n const buildSquareGraph = useCallback(\n (width: number, height: number) => {\n nodesRef.current.clear();\n edgesRef.current = [];\n adjacencyRef.current.clear();\n topNodesRef.current = [];\n bottomNodesRef.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 const maxY = rows * cellSize;\n for (let i = 0; i <= cols; i++) {\n const topNode = nodesRef.current.get(nodeKey(i * cellSize, 0));\n if (topNode) topNodesRef.current.push(topNode);\n\n const bottomNode = nodesRef.current.get(nodeKey(i * cellSize, maxY));\n if (bottomNode) bottomNodesRef.current.push(bottomNode);\n }\n },\n [cellSize, addEdge]\n );\n\n const buildHexGraph = useCallback(\n (width: number, height: number) => {\n nodesRef.current.clear();\n edgesRef.current = [];\n adjacencyRef.current.clear();\n topNodesRef.current = [];\n bottomNodesRef.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 allNodes = Array.from(nodesRef.current.values());\n\n const visibleNodes = allNodes.filter((n) => n.y >= 0 && n.y <= height);\n\n topNodesRef.current = visibleNodes\n .filter((n) => n.y <= size * 2)\n .sort((a, b) => a.x - b.x);\n\n bottomNodesRef.current = visibleNodes\n .filter((n) => n.y >= height - size * 2)\n .sort((a, b) => a.x - b.x);\n },\n [cellSize, addEdge]\n );\n\n const getConnectedNodes = useCallback(\n (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 );\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 = (\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number\n ) => {\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)\n .toString(16)\n .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 history = particle.history;\n if (history.length === 0) continue;\n\n const head = history[history.length - 1];\n\n if (history.length >= 2) {\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n const r = parseInt(lightColor.slice(1, 3), 16);\n const g = parseInt(lightColor.slice(3, 5), 16);\n const b = parseInt(lightColor.slice(5, 7), 16);\n const lighterR = Math.floor(r + (255 - r) * 0.6);\n const lighterG = Math.floor(g + (255 - g) * 0.6);\n const lighterB = Math.floor(b + (255 - b) * 0.6);\n ctx.strokeStyle = `rgb(${lighterR}, ${lighterG}, ${lighterB})`;\n\n const maxWidth = 4;\n const minWidth = 0.5;\n for (let i = 1; i < history.length; i++) {\n const progress = i / (history.length - 1);\n ctx.lineWidth = minWidth + (maxWidth - minWidth) * progress;\n ctx.beginPath();\n ctx.moveTo(history[i - 1].x, history[i - 1].y);\n ctx.lineTo(history[i].x, history[i].y);\n ctx.stroke();\n }\n }\n\n ctx.fillStyle = lightColor;\n ctx.beginPath();\n let angle = 0;\n if (history.length >= 2) {\n const prev = history[history.length - 2];\n angle = Math.atan2(head.y - prev.y, head.x - prev.x);\n }\n ctx.save();\n ctx.translate(head.x, head.y);\n ctx.rotate(angle);\n ctx.moveTo(-3, 0);\n ctx.quadraticCurveTo(1, -2.5, 2, 0);\n ctx.quadraticCurveTo(1, 2.5, -3, 0);\n ctx.restore();\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)\n .toString(16)\n .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(\n (e) => e.opacity > 0\n );\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)\n .toString(16)\n .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 (\n Math.floor(Math.random() * (maxTravel - minTravel + 1)) + minTravel\n );\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 trySpawn = (fromTop: boolean): boolean => {\n const sourceNodes = fromTop\n ? topNodesRef.current\n : bottomNodesRef.current;\n const direction: 1 | -1 = fromTop ? 1 : -1;\n\n if (sourceNodes.length === 0) return false;\n\n const startNode =\n sourceNodes[Math.floor(Math.random() * sourceNodes.length)];\n const connectedNodes = getConnectedNodes(startNode);\n\n const preferredNodes = connectedNodes.filter((n) =>\n fromTop ? n.y > startNode.y : n.y < startNode.y\n );\n const targetNodes =\n preferredNodes.length > 0 ? preferredNodes : 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 false;\n\n const targetNode =\n 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 direction,\n history: [{ x: startNode.x, y: startNode.y }],\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 return true;\n };\n\n const spawnParticle = () => {\n if (bidirectional) {\n const fromTop = spawnFromTopRef.current;\n spawnFromTopRef.current = !spawnFromTopRef.current;\n\n if (!trySpawn(fromTop)) {\n trySpawn(!fromTop);\n }\n } else {\n trySpawn(true);\n }\n };\n\n const updateParticles = () => {\n const newParticles: Particle[] = [];\n const maxHistoryLength = trailLength;\n\n for (const particle of particlesRef.current) {\n if (particle.dead) continue;\n\n particle.progress += lightSpeed * 0.02;\n\n const currentX =\n particle.currentNode.x +\n (particle.targetNode.x - particle.currentNode.x) * particle.progress;\n const currentY =\n particle.currentNode.y +\n (particle.targetNode.y - particle.currentNode.y) * particle.progress;\n particle.history.push({ x: currentX, y: currentY });\n if (particle.history.length > maxHistoryLength) {\n particle.history.shift();\n }\n\n const trailIndex = trailsRef.current.findIndex(\n (t) =>\n 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(\n particle.progress,\n 1\n );\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(\n currentNode,\n particle.currentNode\n );\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 =\n particle.canSplit &&\n Math.random() < splitChance &&\n availableNodes.length >= 2;\n\n if (shouldSplit) {\n const shuffled = [...availableNodes].sort(\n () => Math.random() - 0.5\n );\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 direction: particle.direction,\n history: [{ x: currentNode.x, y: currentNode.y }],\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 =\n 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 }, [\n shape,\n cellSize,\n lineColor,\n lineWidth,\n animated,\n lightColor,\n lightSpeed,\n minTravel,\n maxTravel,\n spawnRate,\n splitChance,\n trailFadeSpeed,\n bidirectional,\n trailLength,\n buildSquareGraph,\n buildHexGraph,\n getConnectedNodes,\n ]);\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":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-grid-lights",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "A React component for animated grid backgrounds with traveling light particles. Supports square and hexagonal grids with customizable animations.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|