{
  "name": "background-paths",
  "type": "registry:component",
  "dependencies": [
    "motion"
  ],
  "files": [
    {
      "type": "registry:component",
      "content": "\"use client\";\n\n/**\n * @author: @dorianbaffier\n * @description: Background Paths\n * @version: 1.0.0\n * @date: 2025-06-26\n * @license: MIT\n * @website: https://kokonutui.com\n * @github: https://github.com/kokonut-labs/kokonutui\n */\n\nimport { motion } from \"motion/react\";\nimport { memo, useMemo } from \"react\";\n\ninterface Point {\n  x: number;\n  y: number;\n}\n\ninterface PathData {\n  id: string;\n  d: string;\n  opacity: number;\n  width: number;\n  duration: number;\n  delay: number;\n}\n\n// Path generation function\nfunction generateAestheticPath(\n  index: number,\n  position: number,\n  type: \"primary\" | \"secondary\" | \"accent\"\n): string {\n  const baseAmplitude =\n    type === \"primary\" ? 150 : type === \"secondary\" ? 100 : 60;\n  const phase = index * 0.2;\n  const points: Point[] = [];\n  const segments = type === \"primary\" ? 10 : type === \"secondary\" ? 8 : 6;\n\n  const startX = 2400;\n  const startY = 800;\n  const endX = -2400;\n  const endY = -800 + index * 25;\n\n  for (let i = 0; i <= segments; i++) {\n    const progress = i / segments;\n    const eased = 1 - (1 - progress) ** 2;\n\n    const baseX = startX + (endX - startX) * eased;\n    const baseY = startY + (endY - startY) * eased;\n\n    const amplitudeFactor = 1 - eased * 0.3;\n    const wave1 =\n      Math.sin(progress * Math.PI * 3 + phase) *\n      (baseAmplitude * 0.7 * amplitudeFactor);\n    const wave2 =\n      Math.cos(progress * Math.PI * 4 + phase) *\n      (baseAmplitude * 0.3 * amplitudeFactor);\n    const wave3 =\n      Math.sin(progress * Math.PI * 2 + phase) *\n      (baseAmplitude * 0.2 * amplitudeFactor);\n\n    points.push({\n      x: baseX * position,\n      y: baseY + wave1 + wave2 + wave3,\n    });\n  }\n\n  const pathCommands = points.map((point: Point, i: number) => {\n    if (i === 0) return `M ${point.x} ${point.y}`;\n    const prevPoint = points[i - 1];\n    const tension = 0.4;\n    const cp1x = prevPoint.x + (point.x - prevPoint.x) * tension;\n    const cp1y = prevPoint.y;\n    const cp2x = prevPoint.x + (point.x - prevPoint.x) * (1 - tension);\n    const cp2y = point.y;\n    return `C ${cp1x} ${cp1y}, ${cp2x} ${cp2y}, ${point.x} ${point.y}`;\n  });\n\n  return pathCommands.join(\" \");\n}\n\nconst generateUniqueId = (prefix: string): string =>\n  `${prefix}-${Math.random().toString(36).substr(2, 9)}`;\n\n// Memoized FloatingPaths component\nconst FloatingPaths = memo(function FloatingPaths({\n  position,\n}: {\n  position: number;\n}) {\n  // Increased number of paths while maintaining optimization\n  const primaryPaths: PathData[] = useMemo(\n    () =>\n      Array.from({ length: 12 }, (_, i) => ({\n        id: generateUniqueId(\"primary\"),\n        d: generateAestheticPath(i, position, \"primary\"),\n        opacity: 0.15 + i * 0.02,\n        width: 4 + i * 0.3,\n        duration: 25,\n        delay: 0,\n      })),\n    [position]\n  );\n\n  const secondaryPaths: PathData[] = useMemo(\n    () =>\n      Array.from({ length: 15 }, (_, i) => ({\n        id: generateUniqueId(\"secondary\"),\n        d: generateAestheticPath(i, position, \"secondary\"),\n        opacity: 0.12 + i * 0.015,\n        width: 3 + i * 0.25,\n        duration: 20,\n        delay: 0,\n      })),\n    [position]\n  );\n\n  const accentPaths: PathData[] = useMemo(\n    () =>\n      Array.from({ length: 10 }, (_, i) => ({\n        id: generateUniqueId(\"accent\"),\n        d: generateAestheticPath(i, position, \"accent\"),\n        opacity: 0.08 + i * 0.12,\n        width: 2 + i * 0.2,\n        duration: 15,\n        delay: 0,\n      })),\n    [position]\n  );\n\n  // Shared animation configuration\n  const sharedAnimationProps = {\n    opacity: 1,\n    scale: 1,\n    transition: {\n      opacity: { duration: 1 },\n      scale: { duration: 1 },\n    },\n  };\n\n  return (\n    <div className=\"pointer-events-none absolute inset-0 overflow-hidden\">\n      <svg\n        className=\"h-full w-full text-slate-950/40 dark:text-white/40\"\n        fill=\"none\"\n        preserveAspectRatio=\"xMidYMid slice\"\n        viewBox=\"-2400 -800 4800 1600\"\n      >\n        <title>Background Paths</title>\n        <defs>\n          <linearGradient id=\"sharedGradient\" x1=\"0%\" x2=\"100%\" y1=\"0%\" y2=\"0%\">\n            <stop offset=\"0%\" stopColor=\"rgba(147, 51, 234, 0.5)\" />\n            <stop offset=\"50%\" stopColor=\"rgba(236, 72, 153, 0.5)\" />\n            <stop offset=\"100%\" stopColor=\"rgba(59, 130, 246, 0.5)\" />\n          </linearGradient>\n        </defs>\n\n        <g className=\"primary-waves\">\n          {primaryPaths.map((path) => (\n            <motion.path\n              animate={{\n                ...sharedAnimationProps,\n                y: [0, -15, 0],\n              }}\n              d={path.d}\n              initial={{ opacity: 0, scale: 0.8 }}\n              key={path.id}\n              stroke=\"url(#sharedGradient)\"\n              strokeLinecap=\"round\"\n              strokeWidth={path.width}\n              style={{ opacity: path.opacity }}\n              transition={{\n                ...sharedAnimationProps.transition,\n                y: {\n                  duration: 8,\n                  repeat: Number.POSITIVE_INFINITY,\n                  ease: \"easeInOut\",\n                  repeatType: \"reverse\",\n                },\n              }}\n            />\n          ))}\n        </g>\n\n        <g className=\"secondary-waves\" style={{ opacity: 0.8 }}>\n          {secondaryPaths.map((path) => (\n            <motion.path\n              animate={{\n                ...sharedAnimationProps,\n                y: [0, -10, 0],\n              }}\n              d={path.d}\n              initial={{ opacity: 0, scale: 0.9 }}\n              key={path.id}\n              stroke=\"url(#sharedGradient)\"\n              strokeLinecap=\"round\"\n              strokeWidth={path.width}\n              style={{ opacity: path.opacity }}\n              transition={{\n                ...sharedAnimationProps.transition,\n                y: {\n                  duration: 6,\n                  repeat: Number.POSITIVE_INFINITY,\n                  ease: \"easeInOut\",\n                  repeatType: \"reverse\",\n                },\n              }}\n            />\n          ))}\n        </g>\n\n        <g className=\"accent-waves\" style={{ opacity: 0.6 }}>\n          {accentPaths.map((path) => (\n            <motion.path\n              animate={{\n                ...sharedAnimationProps,\n                y: [0, -5, 0],\n              }}\n              d={path.d}\n              initial={{ opacity: 0, scale: 0.95 }}\n              key={path.id}\n              stroke=\"url(#sharedGradient)\"\n              strokeLinecap=\"round\"\n              strokeWidth={path.width}\n              style={{ opacity: path.opacity }}\n              transition={{\n                ...sharedAnimationProps.transition,\n                y: {\n                  duration: 4,\n                  repeat: Number.POSITIVE_INFINITY,\n                  ease: \"easeInOut\",\n                  repeatType: \"reverse\",\n                },\n              }}\n            />\n          ))}\n        </g>\n      </svg>\n    </div>\n  );\n});\n\n// Memoized AnimatedTitle component\nconst AnimatedTitle = memo(function AnimatedTitle({\n  title,\n}: {\n  title: string;\n}) {\n  return (\n    <motion.h1\n      animate={{ opacity: 1, y: 0 }}\n      className=\"mb-8 bg-gradient-to-r from-neutral-800/90 to-neutral-600/90 bg-clip-text font-bold text-3xl text-transparent tracking-tighter sm:text-5xl md:text-5xl dark:from-white/90 dark:to-white/70\"\n      initial={{ opacity: 0, y: 20 }}\n      transition={{\n        duration: 1.2,\n        ease: [0.2, 0.65, 0.3, 0.9],\n      }}\n    >\n      {title}\n    </motion.h1>\n  );\n});\n\nexport default memo(function BackgroundPaths({\n  title = \"Background Paths\",\n}: {\n  title?: string;\n}) {\n  return (\n    <div className=\"relative flex min-h-screen w-full items-center justify-center overflow-hidden bg-white dark:bg-neutral-950\">\n      <div className=\"absolute inset-0\">\n        <FloatingPaths position={1} />\n      </div>\n\n      <div className=\"container relative z-10 mx-auto px-4 text-center md:px-6\">\n        <motion.div\n          animate={{ opacity: 1 }}\n          className=\"mx-auto max-w-4xl\"\n          initial={{ opacity: 0 }}\n          transition={{ duration: 2 }}\n        >\n          <AnimatedTitle title={title} />\n        </motion.div>\n      </div>\n    </div>\n  );\n});\n",
      "path": "/components/kokonutui/background-paths.tsx",
      "target": "components/kokonutui/background-paths.tsx"
    }
  ]
}