{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "merging-bubbles",
  "type": "registry:ui",
  "description": "Merging bubbles visualization",
  "files": [
    {
      "path": "registry/default/ui/merging-bubbles.tsx",
      "content": "\"use client\"\n\nimport { useId } from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\ninterface MergingBubblesProps {\n  size?: \"xs\" | \"sm\" | \"md\" | \"lg\"\n  className?: string\n  startIcon?: React.ReactNode\n  endIcon?: React.ReactNode\n  showPlus?: boolean\n}\n\nconst sizeConfig = {\n  xs: { width: 160, height: 72, iconSize: 24, plusSize: 12 },\n  sm: { width: 200, height: 88, iconSize: 32, plusSize: 16 },\n  md: { width: 280, height: 124, iconSize: 48, plusSize: 22 },\n  lg: { width: 400, height: 176, iconSize: 64, plusSize: 28 },\n}\n\nexport function MergingBubbles({\n  size = \"md\",\n  className,\n  startIcon,\n  endIcon,\n  showPlus = true,\n}: MergingBubblesProps) {\n  const { width, height, iconSize, plusSize } = sizeConfig[size]\n\n  const VB_X = -24\n  const VB_W = 400\n  const LEFT_CX = 88\n  const RIGHT_CX = 264\n  const CENTER_X = 176\n  const toPixelX = (vbX: number) => ((vbX - VB_X) / VB_W) * width\n\n  return (\n    <div\n      className={cn(\n        \"relative inline-flex items-center justify-center\",\n        className\n      )}\n    >\n      <svg\n        width={width}\n        height={height}\n        viewBox=\"-24 0 400 176\"\n        fill=\"none\"\n        xmlns=\"http://www.w3.org/2000/svg\"\n        className=\"overflow-visible\"\n      >\n        <title>Outer glow/shadow</title>\n        {/* Outer glow/shadow */}\n        <path\n          d=\"M88,168c-44.18,0-80-35.82-80-80S43.82,8,88,8c17.57,0,33.78,5.66,46.97,15.26,12.22,8.9,25.94,16.74,41.03,16.74h0c15.09,0,28.81-7.84,41.03-16.74C230.22,13.66,246.43,8,264,8c44.18,0,80,35.82,80,80s-35.82,80-80,80c-17.57,0-33.78-5.66-46.97-15.26-12.22-8.9-25.94-16.74-41.03-16.74h0c-15.09,0-28.81,7.84-41.03,16.74C121.78,162.34,105.57,168,88,168Z\"\n          className=\"stroke-foreground/10\"\n          strokeWidth=\"10\"\n          fill=\"none\"\n        />\n        {/* Fill */}\n        <path\n          d=\"M88,168c-44.18,0-80-35.82-80-80S43.82,8,88,8c17.57,0,33.78,5.66,46.97,15.26,12.22,8.9,25.94,16.74,41.03,16.74h0c15.09,0,28.81-7.84,41.03-16.74C230.22,13.66,246.43,8,264,8c44.18,0,80,35.82,80,80s-35.82,80-80,80c-17.57,0-33.78-5.66-46.97-15.26-12.22-8.9-25.94-16.74-41.03-16.74h0c-15.09,0-28.81,7.84-41.03,16.74C121.78,162.34,105.57,168,88,168Z\"\n          className=\"fill-muted/60\"\n        />\n        {/* Border stroke */}\n        <path\n          d=\"M88,168c-44.18,0-80-35.82-80-80S43.82,8,88,8c17.57,0,33.78,5.66,46.97,15.26,12.22,8.9,25.94,16.74,41.03,16.74h0c15.09,0,28.81-7.84,41.03-16.74C230.22,13.66,246.43,8,264,8c44.18,0,80,35.82,80,80s-35.82,80-80,80c-17.57,0-33.78-5.66-46.97-15.26-12.22-8.9-25.94-16.74-41.03-16.74h0c-15.09,0-28.81,7.84-41.03,16.74C121.78,162.34,105.57,168,88,168Z\"\n          className=\"stroke-foreground/20\"\n          strokeWidth=\"1\"\n          fill=\"none\"\n        />\n      </svg>\n\n      {/* Plus symbol in center */}\n      {showPlus && (\n        <div\n          className=\"absolute top-1/2 -translate-y-1/2 text-foreground/40 font-light leading-none select-none\"\n          style={{\n            fontSize: plusSize,\n            left: toPixelX(CENTER_X) - plusSize / 2,\n          }}\n        >\n          +\n        </div>\n      )}\n\n      {/* Start icon positioned on left circle */}\n      {startIcon && (\n        <div\n          className=\"absolute top-1/2 -translate-y-1/2 flex items-center justify-center [&>svg]:w-full [&>svg]:h-full\"\n          style={{\n            width: iconSize,\n            height: iconSize,\n            left: toPixelX(LEFT_CX) - iconSize / 2,\n          }}\n        >\n          {startIcon}\n        </div>\n      )}\n\n      {/* End icon positioned on right circle */}\n      {endIcon && (\n        <div\n          className=\"absolute top-1/2 -translate-y-1/2 flex items-center justify-center [&>svg]:w-full [&>svg]:h-full\"\n          style={{\n            width: iconSize,\n            height: iconSize,\n            left: toPixelX(RIGHT_CX) - iconSize / 2,\n          }}\n        >\n          {endIcon}\n        </div>\n      )}\n    </div>\n  )\n}\n\n// Next.js logo icon\nexport function NextLogo({ className }: { className?: string }) {\n  const gradientBaseId = useId()\n  const nextGradient1Id = `${gradientBaseId}-nextGradient1`\n  const nextGradient2Id = `${gradientBaseId}-nextGradient2`\n\n  return (\n    <svg\n      viewBox=\"0 0 16 16\"\n      className={cn(\"text-current\", className)}\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>Next Logo</title>\n      <defs>\n        <linearGradient\n          id={nextGradient1Id}\n          x1=\"11.13\"\n          y1=\"5\"\n          x2=\"11.13\"\n          y2=\"11\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop stopColor=\"white\" />\n          <stop offset=\"0.609375\" stopColor=\"white\" stopOpacity=\"0.57\" />\n          <stop offset=\"0.796875\" stopColor=\"white\" stopOpacity=\"0\" />\n          <stop offset=\"1\" stopColor=\"white\" stopOpacity=\"0\" />\n        </linearGradient>\n        <linearGradient\n          id={nextGradient2Id}\n          x1=\"9.9375\"\n          y1=\"9.0625\"\n          x2=\"13.5574\"\n          y2=\"13.3992\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop stopColor=\"white\" />\n          <stop offset=\"1\" stopColor=\"white\" stopOpacity=\"0\" />\n        </linearGradient>\n      </defs>\n      <circle\n        cx=\"8\"\n        cy=\"8\"\n        r=\"7.375\"\n        fill=\"black\"\n        stroke=\"black\"\n        strokeWidth=\"1.25\"\n      />\n      <path\n        d=\"M10.63 11V5\"\n        stroke={`url(#${nextGradient1Id})`}\n        strokeWidth=\"1.25\"\n        strokeMiterlimit=\"1.41421\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M5.995 5.00087V5H4.745V11H5.995V6.96798L12.3615 14.7076C12.712 14.4793 13.0434 14.2242 13.353 13.9453L5.99527 5.00065L5.995 5.00087Z\"\n        fill={`url(#${nextGradient2Id})`}\n      />\n    </svg>\n  )\n}\n\n// Vercel triangle icon\nexport function VercelLogo({ className }: { className?: string }) {\n  return (\n    <svg\n      viewBox=\"0 0 16 16\"\n      className={cn(\"text-current\", className)}\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>Vercel Logo</title>\n      <circle\n        cx=\"8\"\n        cy=\"8\"\n        r=\"7.25\"\n        fill=\"currentColor\"\n        stroke=\"currentColor\"\n        strokeWidth=\"1.5\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M8 4.5L11.5 10.625H4.5L8 4.5Z\"\n        className=\"fill-background\"\n      />\n    </svg>\n  )\n}\n",
      "type": "registry:ui"
    }
  ]
}