import React, { useEffect, useId, useRef, useState } from "react" import { motion } from "motion/react" import { cn } from "@/lib/utils" /** * 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 ( ) }