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.

156 lines 7.42 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 InteractiveGridBackground = ({ gridSize = 50, gridColor = "#cbcbcb", darkGridColor = "#303030", effectColor = "rgba(0, 0, 0, 0.6)", darkEffectColor = "rgba(255, 255, 255, 0.6)", trailLength = 3, width, height, idleSpeed = 0.2, glow = true, glowRadius = 20, children, showFade = true, fadeIntensity = 20, idleRandomCount = 5, className, ...props }) => { const canvasRef = (0, react_1.useRef)(null); const containerRef = (0, react_1.useRef)(null); const [isDarkMode, setIsDarkMode] = (0, react_1.useState)(false); const trailRef = (0, react_1.useRef)([]); const idleTargetsRef = (0, react_1.useRef)([]); const idlePositionsRef = (0, react_1.useRef)([]); const mouseActiveRef = (0, react_1.useRef)(false); const lastMouseTimeRef = (0, react_1.useRef)(Date.now()); // Detect dark mode (0, react_1.useEffect)(() => { const updateDarkMode = () => { setIsDarkMode(document.documentElement.classList.contains("dark")); }; updateDarkMode(); const observer = new MutationObserver(() => updateDarkMode()); observer.observe(document.documentElement, { attributes: true }); return () => observer.disconnect(); }, []); // Mouse tracking (0, react_1.useEffect)(() => { const handleMouseMove = (e) => { const container = containerRef.current; if (!container) return; const rect = container.getBoundingClientRect(); const rawX = e.clientX - rect.left; const rawY = e.clientY - rect.top; if (rawX < 0 || rawY < 0 || rawX > rect.width || rawY > rect.height) return; mouseActiveRef.current = true; lastMouseTimeRef.current = Date.now(); const snappedX = Math.floor(rawX / gridSize); const snappedY = Math.floor(rawY / gridSize); const last = trailRef.current[0]; if (!last || last.x !== snappedX || last.y !== snappedY) { trailRef.current.unshift({ x: snappedX, y: snappedY }); if (trailRef.current.length > trailLength) trailRef.current.pop(); } }; window.addEventListener("mousemove", handleMouseMove); return () => window.removeEventListener("mousemove", handleMouseMove); }, [gridSize, trailLength]); // Drawing logic (0, react_1.useEffect)(() => { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext("2d"); if (!ctx) return; const canvasWidth = width || window.innerWidth; const canvasHeight = height || window.innerHeight; canvas.width = canvasWidth; canvas.height = canvasHeight; const cols = Math.floor(canvasWidth / gridSize); const rows = Math.floor(canvasHeight / gridSize); const lineColor = isDarkMode ? darkGridColor : gridColor; const glowColor = isDarkMode ? darkEffectColor : effectColor; // Initialize idle positions idleTargetsRef.current = Array.from({ length: idleRandomCount }, () => ({ x: Math.floor(Math.random() * cols), y: Math.floor(Math.random() * rows), })); idlePositionsRef.current = idleTargetsRef.current.map((p) => ({ ...p })); const draw = () => { ctx.clearRect(0, 0, canvasWidth, canvasHeight); // Draw grid lines ctx.strokeStyle = lineColor; ctx.lineWidth = 1; for (let x = 0; x <= canvasWidth; x += gridSize) { ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, canvasHeight); ctx.stroke(); } for (let y = 0; y <= canvasHeight; y += gridSize) { ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(canvasWidth, y); ctx.stroke(); } // Idle animation logic const idleThreshold = 2000; if (Date.now() - lastMouseTimeRef.current > idleThreshold) { mouseActiveRef.current = false; idlePositionsRef.current.forEach((pos, i) => { const target = idleTargetsRef.current[i]; const dx = target.x - pos.x; const dy = target.y - pos.y; if (Math.abs(dx) < 0.01 && Math.abs(dy) < 0.01) { // new random target when reached idleTargetsRef.current[i] = { x: Math.floor(Math.random() * cols), y: Math.floor(Math.random() * rows), }; } else { pos.x += dx * idleSpeed; pos.y += dy * idleSpeed; } const roundedX = Math.round(pos.x); const roundedY = Math.round(pos.y); const last = trailRef.current[0]; if (!last || last.x !== roundedX || last.y !== roundedY) { trailRef.current.unshift({ x: roundedX, y: roundedY }); if (trailRef.current.length > trailLength * idleRandomCount) trailRef.current.pop(); } }); } // Draw trail glow trailRef.current.forEach((cell, idx) => { const alpha = 1 - idx * (1 / (trailLength + 1)); const rgbaColor = glowColor.replace(/[\d.]+\)$/g, `${alpha})`); ctx.fillStyle = rgbaColor; if (glow) { ctx.shadowColor = rgbaColor; ctx.shadowBlur = glowRadius; } else { ctx.shadowBlur = 0; } ctx.fillRect(cell.x * gridSize, cell.y * gridSize, gridSize, gridSize); }); requestAnimationFrame(draw); }; draw(); }, [ gridSize, width, height, gridColor, darkGridColor, effectColor, darkEffectColor, isDarkMode, trailLength, idleSpeed, glow, glowRadius, idleRandomCount, ]); return ((0, jsx_runtime_1.jsxs)("div", { ref: containerRef, className: `relative ${className}`, style: { width: width || "99vw", height: height || "100vh" }, ...props, children: [(0, jsx_runtime_1.jsx)("canvas", { ref: canvasRef, className: "absolute top-0 left-0 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)`, } })), (0, jsx_runtime_1.jsx)("div", { className: "relative z-0 w-full h-full", children: children })] })); }; exports.default = InteractiveGridBackground; //# sourceMappingURL=interactive-grid-background.js.map