"use client"; import { cn } from "@/lib/utils"; import { motion } from "motion/react"; import React, { useEffect, useId, useRef, useState } from "react"; /** * DotPattern Component Props * * @param {number} [width=16] - The horizontal spacing between dots * @param {number} [height=16] - The vertical spacing between dots * @param {number} [x=0] - The x-offset of the entire pattern * @param {number} [y=0] - The y-offset of the entire pattern * @param {number} [cx=1] - The x-offset of individual dots * @param {number} [cy=1] - The y-offset of individual dots * @param {number} [cr=1] - The radius of each dot * @param {string} [className] - Additional CSS classes to apply to the SVG container * @param {boolean} [glow=false] - Whether dots should have a glowing animation effect */ interface DotPatternProps extends React.SVGProps { width?: number; height?: number; x?: number; y?: number; cx?: number; cy?: number; cr?: number; className?: string; glow?: boolean; [key: string]: unknown; } /** * DotPattern Component * * A React component that creates an animated or static dot pattern background using SVG. * The pattern automatically adjusts to fill its container and can optionally display glowing dots. * * @component * * @see DotPatternProps for the props interface. * * @example * // Basic usage * * * // With glowing effect and custom spacing * * * @notes * - The component is client-side only ("use client") * - Automatically responds to container size changes * - When glow is enabled, dots will animate with random delays and durations * - Uses Motion for animations * - Dots color can be controlled via the text color utility classes */ export function DotPattern({ width = 16, height = 16, x = 0, y = 0, cx = 1, cy = 1, cr = 1, className, glow = false, ...props }: DotPatternProps) { const id = useId(); const containerRef = useRef(null); const [dimensions, setDimensions] = useState({ width: 0, height: 0 }); useEffect(() => { const updateDimensions = () => { if (containerRef.current) { const { width, height } = containerRef.current.getBoundingClientRect(); setDimensions({ width, height }); } }; updateDimensions(); window.addEventListener("resize", updateDimensions); return () => window.removeEventListener("resize", updateDimensions); }, []); const dots = Array.from( { length: Math.ceil(dimensions.width / width) * Math.ceil(dimensions.height / height), }, (_, i) => { const col = i % Math.ceil(dimensions.width / width); const row = Math.floor(i / Math.ceil(dimensions.width / width)); return { x: col * width + cx, y: row * height + cy, delay: Math.random() * 5, duration: Math.random() * 3 + 2, }; }, ); return ( ); }