{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "backgrounds-bubble",
  "type": "registry:ui",
  "title": "Bubble Background",
  "description": "An interactive background featuring smoothly animated gradient bubbles, creating a playful, dynamic, and visually engaging backdrop.",
  "dependencies": [
    "@animate-ui/react",
    "cn",
    "motion"
  ],
  "files": [
    {
      "path": "registry/backgrounds/bubble/index.tsx",
      "type": "registry:ui",
      "target": "@components/animate-ui/backgrounds/bubble.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport {\n  motion,\n  useInView,\n  useMotionValue,\n  useSpring,\n  type SpringOptions,\n  type TargetAndTransition,\n  type Transition,\n} from 'motion/react';\n\nimport {\n  ReducedMotionConfig,\n  useShouldReduceMotion,\n} from '@animate-ui/react/utils/motion';\nimport { usePageVisible } from '@animate-ui/react/utils/use-page-visible';\nimport { cn } from 'cn';\n\nfunction loop(\n  playing: boolean,\n  keyframes: TargetAndTransition,\n  rest: TargetAndTransition,\n  transition: Transition,\n) {\n  return playing\n    ? { initial: rest, animate: keyframes, transition }\n    : { initial: rest, animate: rest, transition: { duration: 0 } };\n}\n\nconst spin = (from: number) => ({ rotate: [from, from + 360] });\n\ntype BubbleColors = {\n  first: string;\n  second: string;\n  third: string;\n  fourth: string;\n  fifth: string;\n  sixth: string;\n};\n\ntype BubbleBackgroundProps = React.ComponentProps<'div'> & {\n  interactive?: boolean;\n  transition?: SpringOptions;\n  colors?: BubbleColors;\n};\n\nfunction BubbleBackgroundContent({\n  ref,\n  className,\n  children,\n  interactive = false,\n  transition = { stiffness: 100, damping: 20 },\n  colors = {\n    first: '18,113,255',\n    second: '221,74,255',\n    third: '0,220,255',\n    fourth: '200,50,50',\n    fifth: '180,180,50',\n    sixth: '140,100,255',\n  },\n  ...props\n}: BubbleBackgroundProps) {\n  const containerRef = React.useRef<HTMLDivElement>(null);\n  React.useImperativeHandle(ref, () => containerRef.current as HTMLDivElement);\n\n  const mouseX = useMotionValue(0);\n  const mouseY = useMotionValue(0);\n  const springX = useSpring(mouseX, transition);\n  const springY = useSpring(mouseY, transition);\n\n  const inView = useInView(containerRef);\n  const pageVisible = usePageVisible();\n  const reduce = useShouldReduceMotion();\n  const playing = inView && pageVisible && !reduce;\n\n  const filterId = `bubble-goo-${React.useId().replace(/[^\\w-]/g, '')}`;\n\n  React.useEffect(() => {\n    if (!interactive || reduce) return;\n\n    const el = containerRef.current;\n    if (!el) return;\n\n    let frameId: number | null = null;\n    const handleMouseMove = (e: MouseEvent) => {\n      if (frameId != null) cancelAnimationFrame(frameId);\n      frameId = requestAnimationFrame(() => {\n        frameId = null;\n        const rect = el.getBoundingClientRect();\n        mouseX.set(e.clientX - (rect.left + rect.width / 2));\n        mouseY.set(e.clientY - (rect.top + rect.height / 2));\n      });\n    };\n\n    el.addEventListener('mousemove', handleMouseMove, { passive: true });\n    return () => {\n      el.removeEventListener('mousemove', handleMouseMove);\n      if (frameId != null) cancelAnimationFrame(frameId);\n    };\n  }, [interactive, reduce, mouseX, mouseY]);\n\n  return (\n    <div\n      ref={containerRef}\n      data-slot=\"bubble-background\"\n      className={cn(\n        'relative size-full overflow-hidden bg-gradient-to-br from-violet-900 to-blue-900',\n        className,\n      )}\n      {...props}\n      style={\n        {\n          '--first-color': colors.first,\n          '--second-color': colors.second,\n          '--third-color': colors.third,\n          '--fourth-color': colors.fourth,\n          '--fifth-color': colors.fifth,\n          '--sixth-color': colors.sixth,\n          ...props.style,\n        } as React.CSSProperties\n      }\n    >\n      <svg\n        aria-hidden=\"true\"\n        xmlns=\"http://www.w3.org/2000/svg\"\n        className=\"pointer-events-none absolute top-0 left-0 w-0 h-0\"\n      >\n        <defs>\n          <filter id={filterId}>\n            <feGaussianBlur\n              in=\"SourceGraphic\"\n              stdDeviation=\"16\"\n              result=\"blur\"\n            />\n            <feColorMatrix\n              in=\"blur\"\n              mode=\"matrix\"\n              values=\"1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 18 -8\"\n              result=\"goo\"\n            />\n            <feBlend in=\"SourceGraphic\" in2=\"goo\" />\n          </filter>\n        </defs>\n      </svg>\n\n      <div\n        aria-hidden=\"true\"\n        className=\"pointer-events-none absolute inset-0\"\n        style={{ filter: `url(#${filterId}) blur(40px)` }}\n      >\n        <motion.div\n          className=\"absolute rounded-full size-[80%] top-[10%] left-[10%] mix-blend-hard-light bg-[radial-gradient(circle_at_center,rgba(var(--first-color),0.8)_0%,rgba(var(--first-color),0)_50%)]\"\n          {...loop(\n            playing,\n            { y: [-50, 50, -50] },\n            { y: -50 },\n            { duration: 30, ease: 'easeInOut', repeat: Infinity },\n          )}\n          style={{ willChange: 'transform' }}\n        />\n\n        <motion.div\n          className=\"absolute inset-0 flex justify-center items-center origin-[calc(50%-400px)]\"\n          {...loop(\n            playing,\n            spin(0),\n            { rotate: reduce ? 90 : 0 },\n            {\n              duration: 20,\n              ease: 'linear',\n              repeat: Infinity,\n              repeatType: 'loop',\n            },\n          )}\n          style={{ willChange: 'transform' }}\n        >\n          <div className=\"rounded-full size-[80%] top-[10%] left-[10%] mix-blend-hard-light bg-[radial-gradient(circle_at_center,rgba(var(--second-color),0.8)_0%,rgba(var(--second-color),0)_50%)]\" />\n        </motion.div>\n\n        <motion.div\n          className=\"absolute inset-0 flex justify-center items-center origin-[calc(50%+400px)]\"\n          {...loop(\n            playing,\n            spin(0),\n            { rotate: reduce ? 180 : 0 },\n            { duration: 40, ease: 'linear', repeat: Infinity },\n          )}\n          style={{ willChange: 'transform' }}\n        >\n          <div className=\"absolute rounded-full size-[80%] bg-[radial-gradient(circle_at_center,rgba(var(--third-color),0.8)_0%,rgba(var(--third-color),0)_50%)] mix-blend-hard-light top-[calc(50%+200px)] left-[calc(50%-500px)]\" />\n        </motion.div>\n\n        <motion.div\n          className=\"absolute rounded-full size-[80%] top-[10%] left-[10%] mix-blend-hard-light bg-[radial-gradient(circle_at_center,rgba(var(--fourth-color),0.8)_0%,rgba(var(--fourth-color),0)_50%)] opacity-70\"\n          {...loop(\n            playing,\n            { x: [-50, 50, -50] },\n            { x: -50 },\n            { duration: 40, ease: 'easeInOut', repeat: Infinity },\n          )}\n          style={{ willChange: 'transform' }}\n        />\n\n        <motion.div\n          className=\"absolute inset-0 flex justify-center items-center origin-[calc(50%_-_800px)_calc(50%_+_200px)]\"\n          {...loop(\n            playing,\n            spin(0),\n            { rotate: reduce ? 45 : 0 },\n            { duration: 20, ease: 'linear', repeat: Infinity },\n          )}\n          style={{ willChange: 'transform' }}\n        >\n          <div className=\"absolute rounded-full size-[160%] mix-blend-hard-light bg-[radial-gradient(circle_at_center,rgba(var(--fifth-color),0.8)_0%,rgba(var(--fifth-color),0)_50%)] top-[calc(50%-80%)] left-[calc(50%-80%)]\" />\n        </motion.div>\n\n        {interactive && (\n          <motion.div\n            className=\"absolute rounded-full size-full mix-blend-hard-light bg-[radial-gradient(circle_at_center,rgba(var(--sixth-color),0.8)_0%,rgba(var(--sixth-color),0)_50%)] opacity-70\"\n            style={{\n              x: springX,\n              y: springY,\n              willChange: 'transform',\n            }}\n          />\n        )}\n      </div>\n\n      {children}\n    </div>\n  );\n}\n\nfunction BubbleBackground(props: BubbleBackgroundProps) {\n  return (\n    <ReducedMotionConfig>\n      <BubbleBackgroundContent {...props} />\n    </ReducedMotionConfig>\n  );\n}\n\nexport { BubbleBackground, type BubbleBackgroundProps };\n"
    }
  ]
}