UNPKG

xlibs-components

Version:

Modern React component library with Aceternity, MagicUI, and ShadCN components for building beautiful web applications

78 lines (77 loc) 3.35 kB
"use client"; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { cn } from '../../lib/utils.js'; import { motion } from "motion/react"; import { useEffect, useId, useRef, useState } from "react"; /** * 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 * <DotPattern /> * * // With glowing effect and custom spacing * <DotPattern * width={20} * height={20} * glow={true} * className="opacity-50" * /> * * @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 }) { 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 (_jsxs("svg", { ref: containerRef, "aria-hidden": "true", className: cn("pointer-events-none absolute inset-0 h-full w-full", className), ...props, children: [_jsx("defs", { children: _jsxs("radialGradient", { id: `${id}-gradient`, children: [_jsx("stop", { offset: "0%", stopColor: "currentColor", stopOpacity: "1" }), _jsx("stop", { offset: "100%", stopColor: "currentColor", stopOpacity: "0" })] }) }), dots.map((dot, index) => (_jsx(motion.circle, { cx: dot.x, cy: dot.y, r: cr, fill: glow ? `url(#${id}-gradient)` : "currentColor", className: "text-neutral-400/80", initial: glow ? { opacity: 0.4, scale: 1 } : {}, animate: glow ? { opacity: [0.4, 1, 0.4], scale: [1, 1.5, 1], } : {}, transition: glow ? { duration: dot.duration, repeat: Infinity, repeatType: "reverse", delay: dot.delay, ease: "easeInOut", } : {} }, `${dot.x}-${dot.y}`)))] })); }