UNPKG

lightswind

Version:

A collection of beautifully crafted React Components, Blocks & Templates for Modern Developers. Create stunning web applications effortlessly by using our 160+ professional and animated react components.

196 lines 10.1 kB
"use strict"; "use client"; Object.defineProperty(exports, "__esModule", { value: true }); const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = require("react"); const BeamGridBackground = ({ gridSize = 40, gridColor = "#e5e7eb", darkGridColor = "#27272a", beamColor = "rgba(0, 180, 255, 0.8)", darkBeamColor = "rgba(0, 255, 255, 0.8)", beamSpeed = 0.1, beamThickness = 3, beamGlow = true, glowIntensity = 50, beamCount = 8, extraBeamCount = 3, idleSpeed = 1.15, interactive = true, asBackground = true, showFade = true, fadeIntensity = 20, className, children, ...props }) => { const canvasRef = (0, react_1.useRef)(null); const containerRef = (0, react_1.useRef)(null); const bgCanvasRef = (0, react_1.useRef)(null); // Buffer for static grid const [isDarkMode, setIsDarkMode] = (0, react_1.useState)(false); const mouseRef = (0, react_1.useRef)({ x: 0, y: 0 }); const lastMouseMoveRef = (0, react_1.useRef)(Date.now()); // --- Dark Mode Detection --- (0, react_1.useEffect)(() => { const updateDarkMode = () => { const prefersDark = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; setIsDarkMode(document.documentElement.classList.contains("dark") || prefersDark); }; updateDarkMode(); const observer = new MutationObserver(() => updateDarkMode()); observer.observe(document.documentElement, { attributes: true }); return () => observer.disconnect(); }, []); // --- Drawing Logic --- (0, react_1.useEffect)(() => { const canvas = canvasRef.current; const container = containerRef.current; if (!canvas || !container) return; const ctx = canvas.getContext("2d"); const rect = container.getBoundingClientRect(); // Handle high-DPI displays for crisp rendering const dpr = window.devicePixelRatio || 1; canvas.width = rect.width * dpr; canvas.height = rect.height * dpr; canvas.style.width = `${rect.width}px`; canvas.style.height = `${rect.height}px`; ctx.scale(dpr, dpr); const cols = Math.floor(rect.width / gridSize); const rows = Math.floor(rect.height / gridSize); // Pre-render static grid to off-screen canvas if (!bgCanvasRef.current) { bgCanvasRef.current = document.createElement("canvas"); } const bgCanvas = bgCanvasRef.current; bgCanvas.width = canvas.width; bgCanvas.height = canvas.height; const bgCtx = bgCanvas.getContext("2d"); bgCtx.scale(dpr, dpr); const lineColor = isDarkMode ? darkGridColor : gridColor; bgCtx.strokeStyle = lineColor; bgCtx.lineWidth = 1; bgCtx.beginPath(); for (let x = 0; x <= rect.width; x += gridSize) { bgCtx.moveTo(x, 0); bgCtx.lineTo(x, rect.height); } for (let y = 0; y <= rect.height; y += gridSize) { bgCtx.moveTo(0, y); bgCtx.lineTo(rect.width, y); } bgCtx.stroke(); // Initialize beams const primaryBeams = Array.from({ length: beamCount }).map(() => ({ x: Math.floor(Math.random() * cols), y: Math.floor(Math.random() * rows), dir: Math.random() > 0.5 ? "x" : "y", offset: Math.random() * gridSize, speed: beamSpeed + Math.random() * 0.3, type: 'primary' })); const extraBeams = Array.from({ length: extraBeamCount }).map(() => ({ x: Math.floor(Math.random() * cols), y: Math.floor(Math.random() * rows), dir: Math.random() > 0.5 ? "x" : "y", offset: Math.random() * gridSize, speed: beamSpeed * 0.5 + Math.random() * 0.1, type: 'extra' })); const allBeams = [...primaryBeams, ...extraBeams]; const updateMouse = (e) => { const rect = container.getBoundingClientRect(); mouseRef.current.x = e.clientX - rect.left; mouseRef.current.y = e.clientY - rect.top; lastMouseMoveRef.current = Date.now(); }; if (interactive) window.addEventListener("mousemove", updateMouse); let animationFrameId; const draw = () => { // Clear main canvas ctx.clearRect(0, 0, rect.width, rect.height); // 1. Draw pre-rendered grid (super fast) ctx.drawImage(bgCanvas, 0, 0, rect.width, rect.height); const activeBeamColor = isDarkMode ? darkBeamColor : beamColor; const now = Date.now(); const idle = now - lastMouseMoveRef.current > 2000; // 2. Draw Beams allBeams.forEach((beam) => { ctx.strokeStyle = activeBeamColor; ctx.lineWidth = beam.type === 'extra' ? beamThickness * 0.75 : beamThickness; if (beamGlow) { ctx.shadowBlur = glowIntensity; ctx.shadowColor = activeBeamColor; } else { ctx.shadowBlur = 0; } ctx.beginPath(); if (beam.dir === "x") { const y = beam.y * gridSize; const beamLength = gridSize * 1.5; const start = -beamLength + (beam.offset % (rect.width + beamLength)); ctx.moveTo(start, y); ctx.lineTo(start + beamLength, y); ctx.stroke(); beam.offset += idle ? beam.speed * idleSpeed * 60 * 0.016 : beam.speed * 60 * 0.016; if (beam.offset > rect.width + beamLength) beam.offset = -beamLength; } else { const x = beam.x * gridSize; const beamLength = gridSize * 1.5; const start = -beamLength + (beam.offset % (rect.height + beamLength)); ctx.moveTo(x, start); ctx.lineTo(x, start + beamLength); ctx.stroke(); beam.offset += idle ? beam.speed * idleSpeed * 60 * 0.016 : beam.speed * 60 * 0.016; if (beam.offset > rect.height + beamLength) beam.offset = -beamLength; } }); // Reset shadow ctx.shadowBlur = 0; // 3. Draw Interactive Highlights if (interactive && !idle) { const targetX = mouseRef.current.x; const targetY = mouseRef.current.y; const centerGx = Math.floor(targetX / gridSize) * gridSize; const centerGy = Math.floor(targetY / gridSize) * gridSize; const highlights = [ { x: centerGx, y: centerGy, radius: 0, lineWidth: beamThickness * 3, glowFactor: 3 }, { x: centerGx, y: centerGy, radius: 1, lineWidth: beamThickness * 1.5, glowFactor: 1.5 }, { x: centerGx, y: centerGy, radius: 2, lineWidth: beamThickness * 0.75, glowFactor: 0.75 }, ]; highlights.forEach(({ x, y, radius, lineWidth, glowFactor }) => { ctx.strokeStyle = activeBeamColor; ctx.lineWidth = lineWidth; ctx.shadowBlur = glowIntensity * glowFactor; ctx.shadowColor = activeBeamColor; for (let dx = -radius; dx <= radius; dx++) { for (let dy = -radius; dy <= radius; dy++) { if (radius === 1 && Math.abs(dx) === 0 && Math.abs(dy) === 0) continue; if (radius === 2 && Math.abs(dx) <= 1 && Math.abs(dy) <= 1) continue; const cellX = x + dx * gridSize; const cellY = y + dy * gridSize; if (cellX >= 0 && cellX < rect.width && cellY >= 0 && cellY < rect.height) { ctx.beginPath(); ctx.rect(cellX, cellY, gridSize, gridSize); ctx.stroke(); } } } }); } animationFrameId = requestAnimationFrame(draw); }; draw(); return () => { if (interactive) window.removeEventListener("mousemove", updateMouse); cancelAnimationFrame(animationFrameId); }; }, [ gridSize, beamColor, darkBeamColor, gridColor, darkGridColor, beamSpeed, beamCount, extraBeamCount, beamThickness, glowIntensity, beamGlow, isDarkMode, idleSpeed, interactive ]); return ((0, jsx_runtime_1.jsxs)("div", { ref: containerRef, className: `relative ${className || ""}`, ...props, style: { position: asBackground ? "absolute" : "relative", top: asBackground ? 0 : undefined, left: asBackground ? 0 : undefined, width: "100%", height: "100%", overflow: "hidden", ...(props.style || {}), }, children: [(0, jsx_runtime_1.jsx)("canvas", { ref: canvasRef, className: "absolute top-0 left-0 w-full h-full z-0 pointer-events-none" }), showFade && ((0, jsx_runtime_1.jsx)("div", { className: "pointer-events-none absolute inset-0 bg-white dark:bg-black", style: { maskImage: `radial-gradient(ellipse at center, transparent ${fadeIntensity}%, black)`, WebkitMaskImage: `radial-gradient(ellipse at center, transparent ${fadeIntensity}%, black)`, } })), !asBackground && ((0, jsx_runtime_1.jsx)("div", { className: "relative z-0 w-full h-full", children: children }))] })); }; exports.default = BeamGridBackground; //# sourceMappingURL=beam-grid-background.js.map