{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "canvas-fractal-grid",
  "type": "registry:ui",
  "description": "Interactive canvas-based fractal dot grid with mouse tracking and wave effects",
  "dependencies": [
    "motion"
  ],
  "files": [
    {
      "path": "registry/default/ui/canvas-fractal-grid.tsx",
      "content": "\"use client\"\n\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\nimport { AnimatePresence, motion, useAnimation } from \"motion/react\"\n\ninterface GradientStop {\n  color: string\n  position: number\n}\n\ninterface GradientType {\n  stops: GradientStop[]\n  centerX: number\n  centerY: number\n}\n\ninterface CanvasFractalGridProps {\n  /** Size of each dot in pixels */\n  dotSize?: number\n  /** Spacing between dots in pixels */\n  dotSpacing?: number\n  /** Opacity of dots (0-1) */\n  dotOpacity?: number\n  /** Duration of the background gradient animation in seconds */\n  gradientAnimationDuration?: number\n  /** Stiffness of mouse tracking (higher values make it more responsive) */\n  mouseTrackingStiffness?: number\n  /** Damping of mouse tracking (higher values make it less bouncy) */\n  mouseTrackingDamping?: number\n  /** Intensity of the wave effect when hovering */\n  waveIntensity?: number\n  /** Radius of the wave effect in pixels */\n  waveRadius?: number\n  /** Array of gradient configurations for the background */\n  gradients?: GradientType[]\n  /** Color of the dots (supports any valid CSS color) */\n  dotColor?: string\n  /** Color of the dot glow effect (supports any valid CSS color) */\n  glowColor?: string\n  /** Enable or disable the noise overlay */\n  enableNoise?: boolean\n  /** Opacity of the noise overlay (0-1) */\n  noiseOpacity?: number\n  /** Enable or disable the mouse glow effect */\n  enableMouseGlow?: boolean\n  /** Set the initial performance level */\n  initialPerformance?: \"low\" | \"medium\" | \"high\"\n  /** Enable or disable the gradient animation */\n  enableGradient?: boolean\n}\n\nconst NoiseSVG = React.memo(() => (\n  <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"100%\" height=\"100%\">\n    <filter id=\"noise\">\n      <feTurbulence\n        type=\"fractalNoise\"\n        baseFrequency=\"0.65\"\n        numOctaves=\"3\"\n        stitchTiles=\"stitch\"\n      />\n    </filter>\n    <rect width=\"100%\" height=\"100%\" filter=\"url(#noise)\" />\n  </svg>\n))\n\nNoiseSVG.displayName = \"NoiseSVG\"\n\nconst NoiseOverlay: React.FC<{ opacity: number }> = ({ opacity }) => (\n  <div\n    className=\"absolute inset-0 h-full w-full mix-blend-overlay\"\n    style={{ opacity }}\n  >\n    <NoiseSVG />\n  </div>\n)\n\nconst useResponsive = () => {\n  const [windowSize, setWindowSize] = useState({\n    width: 0,\n    height: 0,\n  })\n\n  useEffect(() => {\n    if (typeof window === \"undefined\") return\n\n    const handleResize = () => {\n      setWindowSize({\n        width: window.innerWidth,\n        height: window.innerHeight,\n      })\n    }\n\n    // Set initial size\n    handleResize()\n\n    window.addEventListener(\"resize\", handleResize)\n    return () => window.removeEventListener(\"resize\", handleResize)\n  }, [])\n\n  return {\n    isMobile: windowSize.width < 768,\n    isTablet: windowSize.width >= 768 && windowSize.width < 1024,\n    isDesktop: windowSize.width >= 1024,\n  }\n}\n\nconst usePerformance = (\n  initialPerformance: \"low\" | \"medium\" | \"high\" = \"medium\"\n) => {\n  const [performance, setPerformance] = useState(initialPerformance)\n  const [fps, setFps] = useState(60)\n\n  useEffect(() => {\n    if (typeof window === \"undefined\") return\n\n    let frameCount = 0\n    let lastTime = globalThis.performance.now()\n    let framerId: number\n\n    const measureFps = (time: number) => {\n      frameCount++\n      if (time - lastTime > 1000) {\n        setFps(Math.round((frameCount * 1000) / (time - lastTime)))\n        frameCount = 0\n        lastTime = time\n      }\n      framerId = requestAnimationFrame(measureFps)\n    }\n\n    framerId = requestAnimationFrame(measureFps)\n\n    return () => cancelAnimationFrame(framerId)\n  }, [])\n\n  useEffect(() => {\n    if (fps < 30 && performance !== \"low\") {\n      setPerformance(\"low\")\n    } else if (fps >= 30 && fps < 50 && performance !== \"medium\") {\n      setPerformance(\"medium\")\n    } else if (fps >= 50 && performance !== \"high\") {\n      setPerformance(\"high\")\n    }\n  }, [fps, performance])\n\n  return { performance, fps }\n}\n\nconst Gradient: React.FC<{\n  gradients: GradientType[]\n  animationDuration: number\n}> = React.memo(({ gradients, animationDuration }) => {\n  const controls = useAnimation()\n\n  useEffect(() => {\n    controls.start({\n      background: gradients.map(\n        (g) =>\n          `radial-gradient(circle at ${g.centerX}% ${g.centerY}%, ${g.stops\n            .map((s) => `${s.color} ${s.position}%`)\n            .join(\", \")})`\n      ),\n      transition: {\n        duration: animationDuration,\n        repeat: Infinity,\n        repeatType: \"reverse\",\n        ease: \"linear\",\n      },\n    })\n  }, [controls, gradients, animationDuration])\n\n  return (\n    <motion.div className=\"absolute inset-0 h-full w-full\" animate={controls} />\n  )\n})\n\nGradient.displayName = \"Gradient\"\n\nconst DotCanvas: React.FC<{\n  dotSize: number\n  dotSpacing: number\n  dotOpacity: number\n  waveIntensity: number\n  waveRadius: number\n  dotColor: string\n  glowColor: string\n  performance: \"low\" | \"medium\" | \"high\"\n  mousePos: { x: number; y: number }\n}> = React.memo(\n  ({\n    dotSize,\n    dotSpacing,\n    dotOpacity,\n    waveIntensity,\n    waveRadius,\n    dotColor,\n    glowColor,\n    performance,\n    mousePos,\n  }) => {\n    const canvasRef = useRef<HTMLCanvasElement>(null)\n    const animationRef = useRef<number | null>(null)\n\n    const drawDots = useCallback(\n      (ctx: CanvasRenderingContext2D, time: number) => {\n        const { width, height } = ctx.canvas\n        ctx.clearRect(0, 0, width, height)\n\n        const performanceSettings = {\n          low: { skip: 3 },\n          medium: { skip: 2 },\n          high: { skip: 1 },\n        }\n\n        const skip = performanceSettings[performance].skip\n\n        const cols = Math.ceil(width / dotSpacing)\n        const rows = Math.ceil(height / dotSpacing)\n\n        const centerX = mousePos.x * width\n        const centerY = mousePos.y * height\n\n        for (let i = 0; i < cols; i += skip) {\n          for (let j = 0; j < rows; j += skip) {\n            const x = i * dotSpacing\n            const y = j * dotSpacing\n\n            const distanceX = x - centerX\n            const distanceY = y - centerY\n            const distance = Math.sqrt(\n              distanceX * distanceX + distanceY * distanceY\n            )\n\n            let dotX = x\n            let dotY = y\n\n            if (distance < waveRadius) {\n              const waveStrength = Math.pow(1 - distance / waveRadius, 2)\n              const angle = Math.atan2(distanceY, distanceX)\n              const waveOffset =\n                Math.sin(distance * 0.05 - time * 0.005) *\n                waveIntensity *\n                waveStrength\n              dotX += Math.cos(angle) * waveOffset\n              dotY += Math.sin(angle) * waveOffset\n\n              const glowRadius = dotSize * (1 + waveStrength)\n              const gradient = ctx.createRadialGradient(\n                dotX,\n                dotY,\n                0,\n                dotX,\n                dotY,\n                glowRadius\n              )\n              gradient.addColorStop(\n                0,\n                glowColor.replace(\"1)\", `${dotOpacity * (1 + waveStrength)})`)\n              )\n              gradient.addColorStop(1, glowColor.replace(\"1)\", \"0)\"))\n              ctx.fillStyle = gradient\n            } else {\n              ctx.fillStyle = dotColor.replace(\"1)\", `${dotOpacity})`)\n            }\n\n            ctx.beginPath()\n            ctx.arc(dotX, dotY, dotSize / 2, 0, Math.PI * 2)\n            ctx.fill()\n          }\n        }\n      },\n      [\n        dotSize,\n        dotSpacing,\n        dotOpacity,\n        waveIntensity,\n        waveRadius,\n        dotColor,\n        glowColor,\n        performance,\n        mousePos,\n      ]\n    )\n\n    useEffect(() => {\n      if (typeof window === \"undefined\") return\n\n      const canvas = canvasRef.current\n      if (!canvas) return\n\n      const ctx = canvas.getContext(\"2d\")\n      if (!ctx) return\n\n      const resizeCanvas = () => {\n        canvas.width = window.innerWidth\n        canvas.height = window.innerHeight\n      }\n\n      resizeCanvas()\n      window.addEventListener(\"resize\", resizeCanvas)\n\n      let lastTime = 0\n      const animate = (time: number) => {\n        if (time - lastTime > 16) {\n          drawDots(ctx, time)\n          lastTime = time\n        }\n        animationRef.current = requestAnimationFrame(animate)\n      }\n\n      animationRef.current = requestAnimationFrame(animate)\n\n      return () => {\n        window.removeEventListener(\"resize\", resizeCanvas)\n        if (animationRef.current) {\n          cancelAnimationFrame(animationRef.current)\n        }\n      }\n    }, [drawDots])\n\n    return (\n      <canvas\n        ref={canvasRef}\n        className=\"absolute inset-0 h-full w-full bg-gray-100\"\n        style={{ mixBlendMode: \"multiply\" }}\n      />\n    )\n  }\n)\n\nDotCanvas.displayName = \"DotCanvas\"\n\nconst MouseGlow: React.FC<{\n  glowColor: string\n  mousePos: { x: number; y: number }\n}> = React.memo(({ glowColor, mousePos }) => (\n  <>\n    <div\n      className=\"absolute w-40 h-40 rounded-full pointer-events-none\"\n      style={{\n        background: `radial-gradient(circle, ${glowColor.replace(\n          \"1)\",\n          \"0.2)\"\n        )} 0%, ${glowColor.replace(\"1)\", \"0)\")} 70%)`,\n        left: `${mousePos.x * 100}%`,\n        top: `${mousePos.y * 100}%`,\n        transform: \"translate(-50%, -50%)\",\n        filter: \"blur(10px)\",\n      }}\n    />\n    <div\n      className=\"absolute w-20 h-20 rounded-full pointer-events-none\"\n      style={{\n        background: `radial-gradient(circle, ${glowColor.replace(\n          \"1)\",\n          \"0.4)\"\n        )} 0%, ${glowColor.replace(\"1)\", \"0)\")} 70%)`,\n        left: `${mousePos.x * 100}%`,\n        top: `${mousePos.y * 100}%`,\n        transform: \"translate(-50%, -50%)\",\n      }}\n    />\n  </>\n))\n\nMouseGlow.displayName = \"MouseGlow\"\n\nconst defaultGradients: GradientType[] = [\n  {\n    stops: [\n      { color: \"#FFD6A5\", position: 0 },\n      { color: \"#FFADAD\", position: 25 },\n      { color: \"#FFC6FF\", position: 50 },\n      { color: \"transparent\", position: 75 },\n    ],\n    centerX: 50,\n    centerY: 50,\n  },\n  {\n    stops: [\n      { color: \"#A0C4FF\", position: 0 },\n      { color: \"#BDB2FF\", position: 25 },\n      { color: \"#CAFFBF\", position: 50 },\n      { color: \"transparent\", position: 75 },\n    ],\n    centerX: 60,\n    centerY: 40,\n  },\n  {\n    stops: [\n      { color: \"#9BF6FF\", position: 0 },\n      { color: \"#FDFFB6\", position: 25 },\n      { color: \"#FFAFCC\", position: 50 },\n      { color: \"transparent\", position: 75 },\n    ],\n    centerX: 40,\n    centerY: 60,\n  },\n]\n\nexport function CanvasFractalGrid({\n  dotSize = 4,\n  dotSpacing = 20,\n  dotOpacity = 0.3,\n  gradientAnimationDuration = 20,\n  waveIntensity = 30,\n  waveRadius = 200,\n  gradients = defaultGradients,\n  dotColor = \"rgba(100, 100, 255, 1)\",\n  glowColor = \"rgba(100, 100, 255, 1)\",\n  enableNoise = true,\n  noiseOpacity = 0.03,\n  enableMouseGlow = true,\n  initialPerformance = \"medium\",\n  enableGradient = false,\n}: CanvasFractalGridProps) {\n  const containerRef = useRef<HTMLDivElement>(null)\n  const { isMobile, isTablet } = useResponsive()\n  const { performance } = usePerformance(initialPerformance)\n  const [mousePos, setMousePos] = useState({ x: 0, y: 0 })\n\n  const handleMouseMove = useCallback((event: MouseEvent) => {\n    const { clientX, clientY } = event\n    const { left, top, width, height } =\n      containerRef.current?.getBoundingClientRect() ?? {\n        left: 0,\n        top: 0,\n        width: 0,\n        height: 0,\n      }\n    const x = (clientX - left) / width\n    const y = (clientY - top) / height\n    setMousePos({ x, y })\n  }, [])\n\n  useEffect(() => {\n    if (typeof window === \"undefined\") return\n\n    window.addEventListener(\"mousemove\", handleMouseMove)\n    return () => window.removeEventListener(\"mousemove\", handleMouseMove)\n  }, [handleMouseMove])\n\n  const responsiveDotSize = useMemo(() => {\n    if (isMobile) return dotSize * 0.75\n    if (isTablet) return dotSize * 0.9\n    return dotSize\n  }, [isMobile, isTablet, dotSize])\n\n  const responsiveDotSpacing = useMemo(() => {\n    if (isMobile) return dotSpacing * 1.5\n    if (isTablet) return dotSpacing * 1.25\n    return dotSpacing\n  }, [isMobile, isTablet, dotSpacing])\n\n  return (\n    <AnimatePresence>\n      <motion.div\n        ref={containerRef}\n        key=\"landing-animation\"\n        initial={{ opacity: 0 }}\n        animate={{ opacity: 1 }}\n        exit={{ opacity: 0 }}\n        transition={{ duration: 1.5, ease: \"easeOut\" }}\n        className=\"absolute inset-0 overflow-hidden w-full h-full\"\n      >\n        {enableGradient && (\n          <Gradient\n            gradients={gradients}\n            animationDuration={gradientAnimationDuration}\n          />\n        )}\n        {enableGradient && (\n          <motion.div\n            className=\"absolute inset-0 h-full w-full\"\n            style={{\n              background: \"radial-gradient(circle, transparent, #FFFFFF)\",\n              backgroundSize: \"100% 100%\",\n              backgroundPosition: \"center\",\n              mixBlendMode: \"overlay\",\n            }}\n            animate={{\n              backgroundPosition: `${mousePos.x * 100}% ${mousePos.y * 100}%`,\n            }}\n          />\n        )}\n        <DotCanvas\n          dotSize={responsiveDotSize}\n          dotSpacing={responsiveDotSpacing}\n          dotOpacity={dotOpacity}\n          waveIntensity={waveIntensity}\n          waveRadius={waveRadius}\n          dotColor={dotColor}\n          glowColor={glowColor}\n          performance={performance}\n          mousePos={mousePos}\n        />\n        {enableNoise && <NoiseOverlay opacity={noiseOpacity} />}\n        {enableMouseGlow && (\n          <MouseGlow glowColor={glowColor} mousePos={mousePos} />\n        )}\n      </motion.div>\n    </AnimatePresence>\n  )\n}\n\nexport default React.memo(CanvasFractalGrid)\n\n// export default CanvasFractalGrid\n\n// const Gradient2: React.FC<{\n//   gradients: Gradient[]\n//   animationDuration: number\n// }> = ({ gradients, animationDuration }) => {\n//   const controls = useAnimation()\n\n//   useEffect(() => {\n//     controls.start({\n//       background: gradients.map(\n//         (g) =>\n//           `radial-gradient(circle at ${g.centerX}% ${g.centerY}%, ${g.stops\n//             .map((s) => `${s.color} ${s.position}%`)\n//             .join(\", \")})`\n//       ),\n//       transition: {\n//         duration: animationDuration,\n//         repeat: Infinity,\n//         repeatType: \"reverse\",\n//         ease: \"easeInOut\",\n//       },\n//     })\n//   }, [controls, gradients, animationDuration])\n\n//   return (\n//     <motion.div className=\"absolute inset-0 h-full w-full\" animate={controls} />\n//   )\n// }\n\n// const DotCanvas2: React.FC<{\n//   dotSize: number\n//   dotSpacing: number\n//   dotOpacity: number\n//   waveIntensity: number\n//   waveRadius: number\n//   dotColor: string\n//   glowColor: string\n//   performance: \"low\" | \"medium\" | \"high\"\n//   mouseX: number\n//   mouseY: number\n// }> = ({\n//   dotSize,\n//   dotSpacing,\n//   dotOpacity,\n//   waveIntensity,\n//   waveRadius,\n//   dotColor,\n//   glowColor,\n//   performance,\n//   mouseX,\n//   mouseY,\n// }) => {\n//   const canvasRef = useRef<HTMLCanvasElement>(null)\n//   const animationRef = useRef<number>()\n//   const mouseRef = useRef({ x: mouseX, y: mouseY })\n\n//   useEffect(() => {\n//     mouseRef.current = { x: mouseX, y: mouseY }\n//   }, [mouseX, mouseY])\n\n//   const drawDots = useCallback(\n//     (ctx: CanvasRenderingContext2D, time: number) => {\n//       const { width, height } = ctx.canvas\n//       ctx.clearRect(0, 0, width, height)\n\n//       const performanceSettings = {\n//         low: { skip: 3 },\n//         medium: { skip: 2 },\n//         high: { skip: 1 },\n//       }\n\n//       const skip = performanceSettings[performance].skip\n\n//       const cols = Math.ceil(width / dotSpacing)\n//       const rows = Math.ceil(height / dotSpacing)\n\n//       const centerX = mouseRef.current.x * width\n//       const centerY = mouseRef.current.y * height\n\n//       for (let i = 0; i < cols; i += skip) {\n//         for (let j = 0; j < rows; j += skip) {\n//           const x = i * dotSpacing\n//           const y = j * dotSpacing\n\n//           const distanceX = x - centerX\n//           const distanceY = y - centerY\n//           const distance = Math.sqrt(\n//             distanceX * distanceX + distanceY * distanceY\n//           )\n\n//           let dotX = x\n//           let dotY = y\n\n//           if (distance < waveRadius) {\n//             const waveStrength = Math.pow(1 - distance / waveRadius, 2)\n//             const angle = Math.atan2(distanceY, distanceX)\n//             const waveOffset =\n//               Math.sin(distance * 0.05 - time * 0.005) *\n//               waveIntensity *\n//               waveStrength\n//             dotX += Math.cos(angle) * waveOffset\n//             dotY += Math.sin(angle) * waveOffset\n\n//             const glowRadius = dotSize * (1 + waveStrength)\n//             const gradient = ctx.createRadialGradient(\n//               dotX,\n//               dotY,\n//               0,\n//               dotX,\n//               dotY,\n//               glowRadius\n//             )\n//             gradient.addColorStop(\n//               0,\n//               glowColor.replace(\"1)\", `${dotOpacity * (1 + waveStrength)})`)\n//             )\n//             gradient.addColorStop(1, glowColor.replace(\"1)\", \"0)\"))\n//             ctx.fillStyle = gradient\n//           } else {\n//             ctx.fillStyle = dotColor.replace(\"1)\", `${dotOpacity})`)\n//           }\n\n//           ctx.beginPath()\n//           ctx.arc(dotX, dotY, dotSize / 2, 0, Math.PI * 2)\n//           ctx.fill()\n//         }\n//       }\n//     },\n//     [\n//       dotSize,\n//       dotSpacing,\n//       dotOpacity,\n//       waveIntensity,\n//       waveRadius,\n//       dotColor,\n//       glowColor,\n//       performance,\n//     ]\n//   )\n\n//   useEffect(() => {\n//     const canvas = canvasRef.current\n//     if (!canvas) return\n\n//     const ctx = canvas.getContext(\"2d\")\n//     if (!ctx) return\n\n//     const resizeCanvas = () => {\n//       canvas.width = window.innerWidth\n//       canvas.height = window.innerHeight\n//     }\n\n//     resizeCanvas()\n//     window.addEventListener(\"resize\", resizeCanvas)\n\n//     let lastTime = 0\n//     const animate = (time: number) => {\n//       if (time - lastTime > 16) {\n//         drawDots(ctx, time)\n//         lastTime = time\n//       }\n//       animationRef.current = requestAnimationFrame(animate)\n//     }\n\n//     animationRef.current = requestAnimationFrame(animate)\n\n//     return () => {\n//       window.removeEventListener(\"resize\", resizeCanvas)\n//       if (animationRef.current) {\n//         cancelAnimationFrame(animationRef.current)\n//       }\n//     }\n//   }, [drawDots])\n\n//   return (\n//     <canvas\n//       ref={canvasRef}\n//       className=\"absolute inset-0 h-full w-full bg-gray-100\"\n//       style={{ mixBlendMode: \"multiply\" }}\n//     />\n//   )\n// }\n\n// const MouseGlow2: React.FC<{\n//   glowColor: string\n//   mouseX: any\n//   mouseY: any\n// }> = ({ glowColor, mouseX, mouseY }) => (\n//   <>\n//     <motion.div\n//       className=\"absolute w-40 h-40 rounded-full pointer-events-none\"\n//       style={{\n//         background: `radial-gradient(circle, ${glowColor.replace(\n//           \"1)\",\n//           \"0.2)\"\n//         )} 0%, ${glowColor.replace(\"1)\", \"0)\")} 70%)`,\n//         x: mouseX,\n//         y: mouseY,\n//         translateX: \"-50%\",\n//         translateY: \"-50%\",\n//         filter: \"blur(10px)\",\n//       }}\n//     />\n//     <motion.div\n//       className=\"absolute w-20 h-20 rounded-full pointer-events-none\"\n//       style={{\n//         background: `radial-gradient(circle, ${glowColor.replace(\n//           \"1)\",\n//           \"0.4)\"\n//         )} 0%, ${glowColor.replace(\"1)\", \"0)\")} 70%)`,\n//         x: mouseX,\n//         y: mouseY,\n//         translateX: \"-50%\",\n//         translateY: \"-50%\",\n//       }}\n//     />\n//   </>\n// )\n// \"use client\"\n\n// import React, { useCallback, useEffect, useMemo, useRef } from \"react\"\n// import { AnimatePresence, motion, useAnimation, useSpring } from \"motion/react\"\n\n// const NoiseSVG = React.memo(() => (\n//   <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"100%\" height=\"100%\">\n//     <filter id=\"noise\">\n//       <feTurbulence\n//         type=\"fractalNoise\"\n//         baseFrequency=\"0.65\"\n//         numOctaves=\"3\"\n//         stitchTiles=\"stitch\"\n//       />\n//     </filter>\n//     <rect width=\"100%\" height=\"100%\" filter=\"url(#noise)\" opacity=\"0.03\" />\n//   </svg>\n// ))\n\n// NoiseSVG.displayName = \"NoiseSVG\"\n\n// interface GradientStop {\n//   color: string\n//   position: number\n// }\n\n// interface Gradient {\n//   stops: GradientStop[]\n//   centerX: number\n//   centerY: number\n// }\n\n// interface CanvasFractalGridProps {\n//   /** Size of each dot in pixels */\n//   dotSize?: number\n//   /** Spacing between dots in pixels */\n//   dotSpacing?: number\n//   /** Opacity of dots (0-1) */\n//   dotOpacity?: number\n//   /** Duration of the background gradient animation in seconds */\n//   gradientAnimationDuration?: number\n//   /** Stiffness of mouse tracking (higher values make it more responsive) */\n//   mouseTrackingStiffness?: number\n//   /** Damping of mouse tracking (higher values make it less bouncy) */\n//   mouseTrackingDamping?: number\n//   /** Intensity of the wave effect when hovering */\n//   waveIntensity?: number\n//   /** Radius of the wave effect in pixels */\n//   waveRadius?: number\n//   /** Array of gradient configurations for the background */\n//   gradients?: Gradient[]\n//   /** Color of the dots (supports any valid CSS color) */\n//   dotColor?: string\n//   /** Color of the dot glow effect (supports any valid CSS color) */\n//   glowColor?: string\n//   /** Enable or disable the noise overlay */\n//   enableNoise?: boolean\n//   /** Opacity of the noise overlay (0-1) */\n//   noiseOpacity?: number\n//   /** Enable or disable the mouse glow effect */\n//   enableMouseGlow?: boolean\n// }\n\n// const defaultGradients: Gradient[] = [\n//   {\n//     stops: [\n//       { color: \"#FFD6A5\", position: 0 },\n//       { color: \"#FFADAD\", position: 25 },\n//       { color: \"#FFC6FF\", position: 50 },\n//       { color: \"transparent\", position: 75 },\n//     ],\n//     centerX: 50,\n//     centerY: 50,\n//   },\n//   {\n//     stops: [\n//       { color: \"#A0C4FF\", position: 0 },\n//       { color: \"#BDB2FF\", position: 25 },\n//       { color: \"#CAFFBF\", position: 50 },\n//       { color: \"transparent\", position: 75 },\n//     ],\n//     centerX: 60,\n//     centerY: 40,\n//   },\n//   {\n//     stops: [\n//       { color: \"#9BF6FF\", position: 0 },\n//       { color: \"#FDFFB6\", position: 25 },\n//       { color: \"#FFAFCC\", position: 50 },\n//       { color: \"transparent\", position: 75 },\n//     ],\n//     centerX: 40,\n//     centerY: 60,\n//   },\n// ]\n\n// export function CanvasFractalGrid({\n//   dotSize = 4,\n//   dotSpacing = 20,\n//   dotOpacity = 0.3,\n//   gradientAnimationDuration = 20,\n//   mouseTrackingStiffness = 500,\n//   mouseTrackingDamping = 150,\n//   waveIntensity = 30,\n//   waveRadius = 200,\n//   gradients = defaultGradients,\n//   dotColor = \"rgba(100, 100, 255, 1)\",\n//   glowColor = \"rgba(100, 100, 255, 1)\",\n//   enableNoise = true,\n//   noiseOpacity = 0.03,\n//   enableMouseGlow = true,\n// }: CanvasFractalGridProps) {\n//   const containerRef = useRef<HTMLDivElement>(null)\n//   const canvasRef = useRef<HTMLCanvasElement>(null)\n//   const animationRef = useRef<number>()\n//   const mouseRef = useRef({ x: 0, y: 0 })\n\n//   const mouseX = useSpring(0, {\n//     stiffness: mouseTrackingStiffness,\n//     damping: mouseTrackingDamping,\n//   })\n//   const mouseY = useSpring(0, {\n//     stiffness: mouseTrackingStiffness,\n//     damping: mouseTrackingDamping,\n//   })\n\n//   const handleMouseMove = useCallback(\n//     (event: MouseEvent) => {\n//       const { clientX, clientY } = event\n//       const { left, top, width, height } =\n//         containerRef.current?.getBoundingClientRect() ?? {\n//           left: 0,\n//           top: 0,\n//           width: 0,\n//           height: 0,\n//         }\n//       const x = (clientX - left) / width\n//       const y = (clientY - top) / height\n//       mouseX.set(x)\n//       mouseY.set(y)\n//       mouseRef.current = { x, y }\n//     },\n//     [mouseX, mouseY]\n//   )\n\n//   useEffect(() => {\n//     window.addEventListener(\"mousemove\", handleMouseMove)\n//     return () => window.removeEventListener(\"mousemove\", handleMouseMove)\n//   }, [handleMouseMove])\n\n//   const controls = useAnimation()\n\n//   useEffect(() => {\n//     controls.start({\n//       background: gradients.map(\n//         (g) =>\n//           `radial-gradient(circle at ${g.centerX}% ${g.centerY}%, ${g.stops\n//             .map((s) => `${s.color} ${s.position}%`)\n//             .join(\", \")})`\n//       ),\n//       transition: {\n//         duration: gradientAnimationDuration,\n//         repeat: Infinity,\n//         repeatType: \"reverse\",\n//         ease: \"easeInOut\",\n//       },\n//     })\n//   }, [controls, gradients, gradientAnimationDuration])\n\n//   const drawDots = useCallback(\n//     (ctx: CanvasRenderingContext2D, time: number) => {\n//       const { width, height } = ctx.canvas\n//       ctx.clearRect(0, 0, width, height)\n\n//       const cols = Math.ceil(width / dotSpacing)\n//       const rows = Math.ceil(height / dotSpacing)\n\n//       const centerX = mouseRef.current.x * width\n//       const centerY = mouseRef.current.y * height\n\n//       for (let i = 0; i < cols; i++) {\n//         for (let j = 0; j < rows; j++) {\n//           const x = i * dotSpacing\n//           const y = j * dotSpacing\n\n//           const distanceX = x - centerX\n//           const distanceY = y - centerY\n//           const distance = Math.sqrt(\n//             distanceX * distanceX + distanceY * distanceY\n//           )\n\n//           let dotX = x\n//           let dotY = y\n\n//           if (distance < waveRadius) {\n//             const waveStrength = Math.pow(1 - distance / waveRadius, 2)\n//             const angle = Math.atan2(distanceY, distanceX)\n//             const waveOffset =\n//               Math.sin(distance * 0.05 - time * 0.005) *\n//               waveIntensity *\n//               waveStrength\n//             dotX += Math.cos(angle) * waveOffset\n//             dotY += Math.sin(angle) * waveOffset\n\n//             const glowRadius = dotSize * (1 + waveStrength)\n//             const gradient = ctx.createRadialGradient(\n//               dotX,\n//               dotY,\n//               0,\n//               dotX,\n//               dotY,\n//               glowRadius\n//             )\n//             gradient.addColorStop(\n//               0,\n//               glowColor.replace(\"1)\", `${dotOpacity * (1 + waveStrength)})`)\n//             )\n//             gradient.addColorStop(1, glowColor.replace(\"1)\", \"0)\"))\n//             ctx.fillStyle = gradient\n//           } else {\n//             ctx.fillStyle = dotColor.replace(\"1)\", `${dotOpacity})`)\n//           }\n\n//           ctx.beginPath()\n//           ctx.arc(dotX, dotY, dotSize / 2, 0, Math.PI * 2)\n//           ctx.fill()\n//         }\n//       }\n//     },\n//     [\n//       dotSize,\n//       dotSpacing,\n//       dotOpacity,\n//       waveIntensity,\n//       waveRadius,\n//       dotColor,\n//       glowColor,\n//     ]\n//   )\n\n//   useEffect(() => {\n//     const canvas = canvasRef.current\n//     if (!canvas) return\n\n//     const ctx = canvas.getContext(\"2d\")\n//     if (!ctx) return\n\n//     const resizeCanvas = () => {\n//       canvas.width = window.innerWidth\n//       canvas.height = window.innerHeight\n//     }\n\n//     resizeCanvas()\n//     window.addEventListener(\"resize\", resizeCanvas)\n\n//     let lastTime = 0\n//     const animate = (time: number) => {\n//       if (time - lastTime > 16) {\n//         drawDots(ctx, time)\n//         lastTime = time\n//       }\n//       animationRef.current = requestAnimationFrame(animate)\n//     }\n\n//     animationRef.current = requestAnimationFrame(animate)\n\n//     return () => {\n//       window.removeEventListener(\"resize\", resizeCanvas)\n//       if (animationRef.current) {\n//         cancelAnimationFrame(animationRef.current)\n//       }\n//     }\n//   }, [drawDots])\n\n//   const gradientStyle = useMemo(\n//     () =>\n//       ({\n//         \"--mouse-x\": mouseX,\n//         \"--mouse-y\": mouseY,\n//       } as React.CSSProperties),\n//     [mouseX, mouseY]\n//   )\n\n//   return (\n//     <AnimatePresence>\n//       <motion.div\n//         ref={containerRef}\n//         key=\"landing-animation\"\n//         initial={{ opacity: 0 }}\n//         animate={{ opacity: 1 }}\n//         exit={{ opacity: 0 }}\n//         transition={{ duration: 1.5, ease: \"easeOut\" }}\n//         className=\"absolute inset-0 overflow-hidden w-full h-full\"\n//         style={gradientStyle}\n//       >\n//         <motion.div\n//           className=\"absolute inset-0 h-full w-full\"\n//           animate={controls}\n//         />\n//         <motion.div\n//           className=\"absolute inset-0 h-full w-full\"\n//           style={{\n//             background: \"radial-gradient(circle, transparent, #FFFFFF)\",\n//             backgroundSize: \"100% 100%\",\n//             backgroundPosition: \"center\",\n//             mixBlendMode: \"overlay\",\n//           }}\n//           animate={{\n//             backgroundPosition: `calc(var(--mouse-x) * 100%) calc(var(--mouse-y) * 100%)`,\n//           }}\n//         />\n//         <canvas\n//           ref={canvasRef}\n//           className=\"absolute inset-0 h-full w-full bg-gray-100\"\n//           style={{ mixBlendMode: \"multiply\" }}\n//         />\n//         {enableNoise && (\n//           <div\n//             className=\"absolute inset-0 h-full w-full mix-blend-overlay\"\n//             style={{ opacity: noiseOpacity }}\n//           >\n//             <NoiseSVG />\n//           </div>\n//         )}\n//         {enableMouseGlow && (\n//           <>\n//             <motion.div\n//               className=\"absolute w-40 h-40 rounded-full pointer-events-none\"\n//               style={{\n//                 background: `radial-gradient(circle, ${glowColor.replace(\n//                   \"1)\",\n//                   \"0.2)\"\n//                 )} 0%, ${glowColor.replace(\"1)\", \"0)\")} 70%)`,\n//                 x: mouseX,\n//                 y: mouseY,\n//                 translateX: \"-50%\",\n//                 translateY: \"-50%\",\n//                 filter: \"blur(10px)\",\n//               }}\n//             />\n//             <motion.div\n//               className=\"absolute w-20 h-20 rounded-full pointer-events-none\"\n//               style={{\n//                 background: `radial-gradient(circle, ${glowColor.replace(\n//                   \"1)\",\n//                   \"0.4)\"\n//                 )} 0%, ${glowColor.replace(\"1)\", \"0)\")} 70%)`,\n//                 x: mouseX,\n//                 y: mouseY,\n//                 translateX: \"-50%\",\n//                 translateY: \"-50%\",\n//               }}\n//             />\n//           </>\n//         )}\n//       </motion.div>\n//     </AnimatePresence>\n//   )\n// }\n\n// export default CanvasFractalGrid\n\n// \"use client\"\n\n// import React, { useCallback, useEffect, useMemo, useRef } from \"react\"\n// import { AnimatePresence, motion, useAnimation, useSpring } from \"motion/react\"\n\n// const NoiseSVG = React.memo(() => (\n//   <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"100%\" height=\"100%\">\n//     <filter id=\"noise\">\n//       <feTurbulence\n//         type=\"fractalNoise\"\n//         baseFrequency=\"0.65\"\n//         numOctaves=\"3\"\n//         stitchTiles=\"stitch\"\n//       />\n//     </filter>\n//     <rect width=\"100%\" height=\"100%\" filter=\"url(#noise)\" opacity=\"0.03\" />\n//   </svg>\n// ))\n\n// NoiseSVG.displayName = \"NoiseSVG\"\n\n// interface LandingAnimationProps {\n//   dotSize?: number\n//   dotSpacing?: number\n//   dotOpacity?: number\n//   animationDuration?: number\n//   mouseTrackingStiffness?: number\n//   mouseTrackingDamping?: number\n//   waveIntensity?: number\n//   waveRadius?: number\n// }\n\n// export function CanvasFractalGrid({\n//   dotSize = 4,\n//   dotSpacing = 20,\n//   dotOpacity = 0.3,\n//   animationDuration = 5,\n//   mouseTrackingStiffness = 500,\n//   mouseTrackingDamping = 150,\n//   waveIntensity = 30,\n//   waveRadius = 200,\n// }: LandingAnimationProps) {\n//   const containerRef = useRef<HTMLDivElement>(null)\n//   const canvasRef = useRef<HTMLCanvasElement>(null)\n//   const animationRef = useRef<number>()\n//   const mouseRef = useRef({ x: 0, y: 0 })\n\n//   const mouseX = useSpring(0, {\n//     stiffness: mouseTrackingStiffness,\n//     damping: mouseTrackingDamping,\n//   })\n//   const mouseY = useSpring(0, {\n//     stiffness: mouseTrackingStiffness,\n//     damping: mouseTrackingDamping,\n//   })\n\n//   const handleMouseMove = useCallback(\n//     (event: MouseEvent) => {\n//       const { clientX, clientY } = event\n//       const { left, top, width, height } =\n//         containerRef.current?.getBoundingClientRect() ?? {\n//           left: 0,\n//           top: 0,\n//           width: 0,\n//           height: 0,\n//         }\n//       const x = (clientX - left) / width\n//       const y = (clientY - top) / height\n//       mouseX.set(x)\n//       mouseY.set(y)\n//       mouseRef.current = { x, y }\n//     },\n//     [mouseX, mouseY]\n//   )\n\n//   useEffect(() => {\n//     window.addEventListener(\"mousemove\", handleMouseMove)\n//     return () => window.removeEventListener(\"mousemove\", handleMouseMove)\n//   }, [handleMouseMove])\n\n//   const controls = useAnimation()\n\n//   useEffect(() => {\n//     controls.start({\n//       background: [\n//         \"radial-gradient(circle at 50% 50%, #FFD6A5 0%, #FFADAD 25%, #FFC6FF 50%, transparent 75%)\",\n//         \"radial-gradient(circle at 60% 40%, #A0C4FF 0%, #BDB2FF 25%, #CAFFBF 50%, transparent 75%)\",\n//         \"radial-gradient(circle at 40% 60%, #9BF6FF 0%, #FDFFB6 25%, #FFAFCC 50%, transparent 75%)\",\n//       ],\n//       transition: {\n//         duration: 20,\n//         repeat: Infinity,\n//         repeatType: \"reverse\",\n//         ease: \"easeInOut\",\n//       },\n//     })\n//   }, [controls])\n\n//   const drawDots = useCallback(\n//     (ctx: CanvasRenderingContext2D, time: number) => {\n//       const { width, height } = ctx.canvas\n//       ctx.clearRect(0, 0, width, height)\n\n//       const cols = Math.ceil(width / dotSpacing)\n//       const rows = Math.ceil(height / dotSpacing)\n\n//       const centerX = mouseRef.current.x * width\n//       const centerY = mouseRef.current.y * height\n\n//       for (let i = 0; i < cols; i++) {\n//         for (let j = 0; j < rows; j++) {\n//           const x = i * dotSpacing\n//           const y = j * dotSpacing\n\n//           const distanceX = x - centerX\n//           const distanceY = y - centerY\n//           const distance = Math.sqrt(\n//             distanceX * distanceX + distanceY * distanceY\n//           )\n\n//           let dotX = x\n//           let dotY = y\n\n//           if (distance < waveRadius) {\n//             const waveStrength = Math.pow(1 - distance / waveRadius, 2)\n//             const angle = Math.atan2(distanceY, distanceX)\n//             const waveOffset =\n//               Math.sin(distance * 0.05 - time * 0.005) *\n//               waveIntensity *\n//               waveStrength\n//             dotX += Math.cos(angle) * waveOffset\n//             dotY += Math.sin(angle) * waveOffset\n\n//             const glowRadius = dotSize * (1 + waveStrength)\n//             const gradient = ctx.createRadialGradient(\n//               dotX,\n//               dotY,\n//               0,\n//               dotX,\n//               dotY,\n//               glowRadius\n//             )\n//             gradient.addColorStop(\n//               0,\n//               `rgba(100, 100, 255, ${dotOpacity * (1 + waveStrength)})`\n//             )\n//             gradient.addColorStop(1, \"rgba(100, 100, 255, 0)\")\n//             ctx.fillStyle = gradient\n//           } else {\n//             ctx.fillStyle = `rgba(100, 100, 255, ${dotOpacity})`\n//           }\n\n//           ctx.beginPath()\n//           ctx.arc(dotX, dotY, dotSize / 2, 0, Math.PI * 2)\n//           ctx.fill()\n//         }\n//       }\n//     },\n//     [dotSize, dotSpacing, dotOpacity, waveIntensity, waveRadius]\n//   )\n\n//   useEffect(() => {\n//     const canvas = canvasRef.current\n//     if (!canvas) return\n\n//     const ctx = canvas.getContext(\"2d\")\n//     if (!ctx) return\n\n//     const resizeCanvas = () => {\n//       canvas.width = window.innerWidth\n//       canvas.height = window.innerHeight\n//     }\n\n//     resizeCanvas()\n//     window.addEventListener(\"resize\", resizeCanvas)\n\n//     let lastTime = 0\n//     const animate = (time: number) => {\n//       if (time - lastTime > 16) {\n//         drawDots(ctx, time)\n//         lastTime = time\n//       }\n//       animationRef.current = requestAnimationFrame(animate)\n//     }\n\n//     animationRef.current = requestAnimationFrame(animate)\n\n//     let animationId: number\n\n//     animationId = requestAnimationFrame(animate)\n\n//     return () => {\n//       window.removeEventListener(\"resize\", resizeCanvas)\n//       cancelAnimationFrame(animationId)\n//     }\n//   }, [drawDots])\n\n//   const gradientStyle = useMemo(\n//     () =>\n//       ({\n//         \"--mouse-x\": mouseX,\n//         \"--mouse-y\": mouseY,\n//       } as React.CSSProperties),\n//     [mouseX, mouseY]\n//   )\n\n//   return (\n//     <AnimatePresence>\n//       <motion.div\n//         ref={containerRef}\n//         key=\"landing-animation\"\n//         initial={{ opacity: 0 }}\n//         animate={{ opacity: 1 }}\n//         exit={{ opacity: 0 }}\n//         transition={{ duration: 1.5, ease: \"easeOut\" }}\n//         // add -z-10 to fix z-index issue if you want to use this component as a background with no parent element setting bg color\n//         className=\"absolute inset-0  overflow-hidden w-full h-full \"\n//         style={gradientStyle}\n//       >\n//         <motion.div\n//           className=\"absolute inset-0 h-full w-full\"\n//           animate={controls}\n//         />\n//         <motion.div\n//           className=\"absolute inset-0 h-full w-full\"\n//           animate={{\n//             background: [\n//               \"radial-gradient(circle at 25% 75%, #FFC6FF 0%, #FFADAD 25%, #FFD6A5 50%, transparent 75%)\",\n//               \"radial-gradient(circle at 25% 25%, #A0C4FF 0%, #BDB2FF 25%, #CAFFBF 50%, transparent 75%)\",\n//               \"radial-gradient(circle at 25% 75%, #9BF6FF 0%, #FDFFB6 25%, #FFAFCC 50%, transparent 75%)\",\n//             ],\n//           }}\n//           transition={{\n//             duration: 15,\n//             repeat: Infinity,\n//             repeatType: \"reverse\",\n//             ease: \"easeInOut\",\n//           }}\n//         />\n//         <motion.div\n//           className=\"absolute inset-0 h-full w-full\"\n//           style={{\n//             background: \"radial-gradient(circle, transparent, #FFFFFF)\",\n//             backgroundSize: \"100% 100%\",\n//             backgroundPosition: \"center\",\n//             mixBlendMode: \"overlay\",\n//           }}\n//           animate={{\n//             backgroundPosition: `calc(var(--mouse-x) * 100%) calc(var(--mouse-y) * 100%)`,\n//           }}\n//         />\n//         <canvas\n//           ref={canvasRef}\n//           className=\"absolute inset-0 h-full w-full bg-gray-100\"\n//           style={{ mixBlendMode: \"multiply\" }}\n//         />\n//         <div className=\"absolute inset-0 h-full w-full opacity-30 mix-blend-overlay\">\n//           <NoiseSVG />\n//         </div>\n//         <motion.div\n//           className=\"absolute w-40 h-40 rounded-full pointer-events-none\"\n//           style={{\n//             background:\n//               \"radial-gradient(circle, rgba(100,100,255,0.2) 0%, rgba(100,100,255,0) 70%)\",\n//             x: mouseX,\n//             y: mouseY,\n//             translateX: \"-50%\",\n//             translateY: \"-50%\",\n//             filter: \"blur(10px)\",\n//           }}\n//         />\n//         <motion.div\n//           className=\"absolute w-20 h-20 rounded-full pointer-events-none\"\n//           style={{\n//             background:\n//               \"radial-gradient(circle, rgba(100,100,255,0.4) 0%, rgba(100,100,255,0) 70%)\",\n//             x: mouseX,\n//             y: mouseY,\n//             translateX: \"-50%\",\n//             translateY: \"-50%\",\n//           }}\n//         />\n//       </motion.div>\n//     </AnimatePresence>\n//   )\n// }\n\n// export default CanvasFractalGrid\n",
      "type": "registry:ui"
    }
  ]
}