{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ai-generate-overlay",
  "title": "AI Generate Overlay",
  "description": "Source image blurs under a shimmering dot grid and a pulsing 'Generating…' pill before a new image fades in.",
  "dependencies": [
    "remotion"
  ],
  "files": [
    {
      "path": "registry/bases/editframe/components/ai-generate-overlay/index.tsx",
      "content": "\"use client\";\n\nimport { Timegroup } from \"@editframe/react\";\nimport type { CSSProperties } from \"react\";\n\nexport interface AIGenerateOverlayProps {\n  maxBlur?: number;\n  blurStartFrame?: number;\n  blurPeakFrame?: number;\n  revealStartFrame?: number;\n  pillText?: string;\n  accent?: string;\n  background?: string;\n  sourceImageBg?: string;\n  generatedImageBg?: string;\n  dotColor?: string;\n  dotSize?: number;\n  dotSpacing?: number;\n  speed?: number;\n  fps?: number;\n  durationInFrames?: number;\n  className?: string;\n}\n\nconst FONT_FAMILY =\n  \"var(--font-geist-sans), -apple-system, BlinkMacSystemFont, sans-serif\";\n\nconst DEFAULT_SOURCE_BG =\n  \"linear-gradient(135deg, #6b3a1a 0%, #d4a574 50%, #8b4513 100%)\";\n\nconst DEFAULT_GENERATED_BG =\n  \"radial-gradient(ellipse at center, #d4a574 0%, #8b4513 22%, #2a1a10 42%), linear-gradient(180deg, #1a1410 0%, #0a0806 50%, #1a1410 100%)\";\n\nconst hexWithAlpha = (hex: string, alpha: number): string => {\n  const m = /^#([0-9a-f]{6})$/i.exec(hex);\n  if (!m) {\n    return hex;\n  }\n  const int = Number.parseInt(m[1], 16);\n  /* eslint-disable no-bitwise */\n  const r = (int >> 16) & 255;\n  const g = (int >> 8) & 255;\n  const b = int & 255;\n  /* eslint-enable no-bitwise */\n  return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n};\n\nexport const AIGenerateOverlay = ({\n  maxBlur = 20,\n  blurStartFrame = 20,\n  blurPeakFrame = 40,\n  revealStartFrame = 110,\n  pillText = \"Generating…\",\n  accent = \"#a78bfa\",\n  background = \"#050505\",\n  sourceImageBg = DEFAULT_SOURCE_BG,\n  generatedImageBg = DEFAULT_GENERATED_BG,\n  dotColor = \"#ffffff\",\n  dotSize = 1.2,\n  dotSpacing = 20,\n  speed = 1,\n  fps = 30,\n  durationInFrames = 150,\n  className,\n}: AIGenerateOverlayProps) => {\n  const safeSpeed = Math.max(0.01, speed);\n  const durationMs = ((durationInFrames / fps) * 1000) / safeSpeed;\n\n  const blurStartPercent = (blurStartFrame / durationInFrames) * 100;\n  const blurPeakPercent = (blurPeakFrame / durationInFrames) * 100;\n  const revealStartPercent = (revealStartFrame / durationInFrames) * 100;\n\n  const style = {\n    background,\n    fontFamily: FONT_FAMILY,\n    height: \"100%\",\n    position: \"relative\",\n    width: \"100%\",\n  } as CSSProperties;\n\n  return (\n    <Timegroup\n      className={className}\n      duration={`${durationMs}ms`}\n      mode=\"fixed\"\n      style={style}\n    >\n      <>\n        <style>{`\n          @keyframes framecn-ai-overlay-blur {\n            from {\n              filter: blur(0px) scale(1.06);\n              opacity: 1;\n            }\n            ${blurStartPercent}% {\n              filter: blur(0px) scale(1.06);\n              opacity: 1;\n            }\n            ${blurPeakPercent}% {\n              filter: blur(${maxBlur}px) scale(1.06);\n              opacity: 0.6;\n            }\n            100% {\n              filter: blur(${maxBlur}px) scale(1.06);\n              opacity: 0;\n            }\n          }\n\n          @keyframes framecn-ai-overlay-grid {\n            from {\n              opacity: 0;\n            }\n            ${blurStartPercent}% {\n              opacity: 0;\n            }\n            ${blurPeakPercent}% {\n              opacity: 0.4;\n            }\n            100% {\n              opacity: 0;\n            }\n          }\n\n          @keyframes framecn-ai-overlay-reveal {\n            from {\n              opacity: 0;\n            }\n            ${revealStartPercent}% {\n              opacity: 0;\n            }\n            100% {\n              opacity: 1;\n            }\n          }\n\n          @keyframes framecn-ai-overlay-pill-in {\n            from {\n              opacity: 0;\n              transform: scale(0.98);\n            }\n            ${blurStartPercent}% {\n              opacity: 0;\n              transform: scale(0.98);\n            }\n            ${blurPeakPercent}% {\n              opacity: 1;\n              transform: scale(1);\n            }\n            100% {\n              opacity: 0;\n              transform: scale(1);\n            }\n          }\n\n          @keyframes framecn-ai-overlay-dot-pulse {\n            0%, 25% {\n              opacity: 1;\n            }\n            26%, 50% {\n              opacity: 1;\n            }\n            51%, 75% {\n              opacity: 1;\n            }\n            76%, 100% {\n              opacity: 1;\n            }\n          }\n\n          @keyframes framecn-ai-overlay-shimmer {\n            0%, 100% {\n              opacity: 0.35;\n            }\n            50% {\n              opacity: 0.45;\n            }\n          }\n        `}</style>\n\n        {/* Source (\"painting\") layer — blurs out as AI thinks. */}\n        <div\n          style={{\n            animation: `framecn-ai-overlay-blur ${durationMs}ms ease-in-out forwards`,\n            background: sourceImageBg,\n            inset: 0,\n            position: \"absolute\",\n          }}\n        />\n\n        {/* Generated image layer — fades in over the blurred source. */}\n        <div\n          style={{\n            animation: `framecn-ai-overlay-reveal ${durationMs}ms cubic-bezier(0.16, 1, 0.3, 1) forwards`,\n            background: generatedImageBg,\n            inset: 0,\n            position: \"absolute\",\n          }}\n        />\n\n        {/* Dot grid overlay — SVG pattern with animated opacity. */}\n        <svg\n          style={{\n            animation: `framecn-ai-overlay-grid ${durationMs}ms ease-in-out forwards`,\n            height: \"100%\",\n            inset: 0,\n            mixBlendMode: \"screen\",\n            pointerEvents: \"none\",\n            position: \"absolute\",\n            width: \"100%\",\n          }}\n          xmlns=\"http://www.w3.org/2000/svg\"\n        >\n          <defs>\n            <pattern\n              id=\"ai-generate-overlay-dots\"\n              width={dotSpacing}\n              height={dotSpacing}\n              patternUnits=\"userSpaceOnUse\"\n            >\n              <circle\n                cx={dotSpacing / 2}\n                cy={dotSpacing / 2}\n                r={dotSize}\n                fill={dotColor}\n              />\n            </pattern>\n          </defs>\n          <rect\n            width=\"100%\"\n            height=\"100%\"\n            fill=\"url(#ai-generate-overlay-dots)\"\n          />\n        </svg>\n\n        {/* \"Generating…\" pill */}\n        <div\n          style={{\n            alignItems: \"center\",\n            animation: `framecn-ai-overlay-pill-in ${durationMs}ms ease-in-out forwards`,\n            display: \"flex\",\n            inset: 0,\n            justifyContent: \"center\",\n            pointerEvents: \"none\",\n            position: \"absolute\",\n          }}\n        >\n          <div\n            style={{\n              WebkitBackdropFilter: \"blur(10px)\",\n              alignItems: \"center\",\n              backdropFilter: \"blur(10px)\",\n              background: \"rgba(10, 10, 10, 0.55)\",\n              border: \"1px solid rgba(255,255,255,0.12)\",\n              borderRadius: 999,\n              boxShadow: `0 0 0 1px rgba(255,255,255,0.04), 0 0 40px ${hexWithAlpha(\n                accent,\n                0.5\n              )}, 0 12px 40px rgba(0,0,0,0.45)`,\n              color: \"#fafafa\",\n              display: \"inline-flex\",\n              fontSize: 18,\n              fontWeight: 500,\n              gap: 12,\n              letterSpacing: \"-0.01em\",\n              padding: \"14px 24px\",\n            }}\n          >\n            <span\n              style={{\n                animation:\n                  \"framecn-ai-overlay-shimmer 1.6s ease-in-out infinite\",\n                background: accent,\n                borderRadius: 999,\n                boxShadow: `0 0 12px ${hexWithAlpha(accent, 0.9)}`,\n                height: 8,\n                width: 8,\n              }}\n            />\n            {pillText}\n          </div>\n        </div>\n      </>\n    </Timegroup>\n  );\n};\n",
      "type": "registry:component",
      "target": "components/framecn/ai-generate-overlay.tsx"
    }
  ],
  "type": "registry:component"
}