{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "confetti",
  "title": "Confetti",
  "description": "Deterministic CSS-animated particle burst celebration effect.",
  "dependencies": [
    "@editframe/react"
  ],
  "files": [
    {
      "path": "registry/bases/editframe/components/confetti/index.tsx",
      "content": "\"use client\";\n\nimport { Timegroup } from \"@editframe/react\";\nimport type { CSSProperties } from \"react\";\n\nexport interface ConfettiProps {\n  particleCount?: number;\n  originX?: number;\n  originY?: number;\n  lifetime?: number;\n  power?: number;\n  gravity?: number;\n  size?: number;\n  seed?: number;\n  colors?: string[];\n  fps?: number;\n  durationInFrames?: number;\n  width?: number;\n  height?: number;\n  background?: string;\n  className?: string;\n  speed?: number;\n}\n\n// Park-Miller PRNG — no bitwise operations needed\nconst makePrng = (initialSeed: number) => {\n  let s = (Math.abs(initialSeed) % 2_147_483_646) + 1;\n  return () => {\n    s = (s * 16_807) % 2_147_483_647;\n    return (s - 1) / 2_147_483_646;\n  };\n};\n\nexport const Confetti = ({\n  particleCount = 80,\n  originX = 0.5,\n  originY = 0.5,\n  lifetime = 90,\n  power = 17,\n  gravity = 0.45,\n  size = 13,\n  seed = 1,\n  colors = [\"#1d9bf0\", \"#ff5da2\", \"#ffd23f\", \"#22c55e\", \"#a855f7\", \"#ff7a45\"],\n  background = \"white\",\n  fps = 30,\n  durationInFrames = 180,\n  width = 1280,\n  height = 720,\n  className,\n  speed = 1,\n}: ConfettiProps) => {\n  const durationMs = (durationInFrames / fps) * 1000;\n  const safeSpeed = Math.max(0.01, speed);\n  const lifetimeMs = ((lifetime / fps) * 1000) / safeSpeed;\n\n  const rand = makePrng(seed);\n  const safeCount = Math.min(particleCount, 120);\n\n  const particles = Array.from({ length: safeCount }, (_, i) => {\n    const angle = rand() * Math.PI * 2;\n    const spd = rand() * power;\n    const drift = (rand() - 0.5) * 2;\n    const vx = Math.cos(angle) * spd + drift;\n    const vy = Math.sin(angle) * spd;\n    const lt = lifetime;\n\n    const startX = originX * width;\n    const startY = originY * height;\n    const endX = startX + vx * lt;\n    const endY = startY + (vy * lt + 0.5 * gravity * lt * lt);\n\n    const color = colors[i % colors.length] ?? \"#fff\";\n    const rot0 = rand() * 360;\n    const rotSpeed = (rand() - 0.5) * 720;\n    const endRot = rot0 + rotSpeed;\n    const w = size * (0.5 + rand() * 0.5);\n    const h = size * (0.5 + rand() * 0.5);\n\n    return { color, endRot, endX, endY, h, i, rot0, startX, startY, w };\n  });\n\n  const keyframesCSS = particles\n    .map(\n      ({ startX, startY, endX, endY, rot0, endRot, i }) => `\n    @keyframes framecn-confetti-p-${i}-${seed} {\n      0% { opacity: 0; transform: translate(${startX - width / 2}px, ${startY - height / 2}px) rotate(${rot0}deg); }\n      5% { opacity: 1; }\n      70% { opacity: 1; }\n      100% { opacity: 0; transform: translate(${endX - width / 2}px, ${endY - height / 2}px) rotate(${endRot}deg); }\n    }\n  `\n    )\n    .join(\"\\n\");\n\n  return (\n    <Timegroup\n      className={className}\n      duration={`${durationMs}ms`}\n      mode=\"fixed\"\n      style={\n        {\n          background,\n          inset: 0,\n          overflow: \"hidden\",\n          position: \"absolute\",\n        } as CSSProperties\n      }\n    >\n      <>\n        <style>{keyframesCSS}</style>\n        <div\n          style={{\n            height: 0,\n            left: width / 2,\n            position: \"absolute\",\n            top: height / 2,\n            width: 0,\n          }}\n        >\n          {particles.map(({ color, rot0, w, h, i }) => (\n            <div\n              key={i}\n              style={{\n                animation: `framecn-confetti-p-${i}-${seed} ${lifetimeMs}ms ease-out 0ms both`,\n                backgroundColor: color,\n                borderRadius: 2,\n                height: h,\n                position: \"absolute\",\n                transform: `translate(-${w / 2}px, -${h / 2}px) rotate(${rot0}deg)`,\n                width: w,\n              }}\n            />\n          ))}\n        </div>\n      </>\n    </Timegroup>\n  );\n};\n",
      "type": "registry:component",
      "target": "components/framecn/confetti.tsx"
    }
  ],
  "type": "registry:component"
}