{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "chat-to-preview-layout",
  "title": "Chat to Preview Layout",
  "description": "Two-column layout where chat shrinks and preview expands.",
  "dependencies": [
    "remotion"
  ],
  "files": [
    {
      "path": "registry/bases/editframe/components/chat-to-preview-layout/index.tsx",
      "content": "\"use client\";\n\nimport { Timegroup } from \"@editframe/react\";\nimport type { ReactNode, CSSProperties } from \"react\";\n\nconst FONT_FAMILY =\n  \"var(--font-geist-sans), -apple-system, BlinkMacSystemFont, sans-serif\";\n\nconst DefaultChat = () => {\n  const messages = [\n    { from: \"user\", text: \"Build me a landing page\" },\n    { from: \"ai\", text: \"Sure — what should it feature?\" },\n    { from: \"user\", text: \"Hero, pricing, footer.\" },\n    { from: \"ai\", text: \"On it. Generating now...\" },\n  ];\n  return (\n    <div\n      style={{\n        background: \"#111\",\n        display: \"flex\",\n        flexDirection: \"column\",\n        fontFamily: FONT_FAMILY,\n        gap: 12,\n        inset: 0,\n        padding: 24,\n        position: \"absolute\",\n      }}\n    >\n      <div\n        style={{\n          color: \"#888\",\n          fontSize: 12,\n          fontWeight: 600,\n          letterSpacing: \"0.08em\",\n          marginBottom: 8,\n          textTransform: \"uppercase\",\n        }}\n      >\n        Chat\n      </div>\n      {messages.map((m, i) => (\n        <div\n          key={i}\n          style={{\n            alignSelf: m.from === \"user\" ? \"flex-end\" : \"flex-start\",\n            background: m.from === \"user\" ? \"#0ea5e9\" : \"#262626\",\n            borderRadius: 14,\n            color: \"white\",\n            fontSize: 14,\n            maxWidth: \"85%\",\n            padding: \"10px 14px\",\n          }}\n        >\n          {m.text}\n        </div>\n      ))}\n    </div>\n  );\n};\n\nconst DefaultPreview = () => (\n  <div\n    style={{\n      background: \"white\",\n      display: \"flex\",\n      flexDirection: \"column\",\n      fontFamily: FONT_FAMILY,\n      inset: 0,\n      position: \"absolute\",\n    }}\n  >\n    <div\n      style={{\n        alignItems: \"center\",\n        background: \"#f4f4f5\",\n        borderBottom: \"1px solid #e4e4e7\",\n        display: \"flex\",\n        gap: 6,\n        height: 36,\n        padding: \"0 12px\",\n      }}\n    >\n      <div\n        style={{\n          background: \"#ef4444\",\n          borderRadius: 999,\n          height: 10,\n          width: 10,\n        }}\n      />\n      <div\n        style={{\n          background: \"#f59e0b\",\n          borderRadius: 999,\n          height: 10,\n          width: 10,\n        }}\n      />\n      <div\n        style={{\n          background: \"#22c55e\",\n          borderRadius: 999,\n          height: 10,\n          width: 10,\n        }}\n      />\n    </div>\n    <div\n      style={{\n        display: \"flex\",\n        flex: 1,\n        flexDirection: \"column\",\n        gap: 16,\n        padding: 32,\n      }}\n    >\n      <div\n        style={{\n          color: \"#0a0a0a\",\n          fontSize: 36,\n          fontWeight: 700,\n          letterSpacing: \"-0.03em\",\n        }}\n      >\n        Ship faster.\n      </div>\n      <div style={{ color: \"#71717a\", fontSize: 16, maxWidth: 360 }}>\n        The fastest way to launch your idea. Built with Remotion.\n      </div>\n      <div\n        style={{\n          alignSelf: \"flex-start\",\n          background: \"#0a0a0a\",\n          borderRadius: 10,\n          color: \"white\",\n          display: \"inline-flex\",\n          fontSize: 14,\n          fontWeight: 600,\n          marginTop: 12,\n          padding: \"10px 18px\",\n        }}\n      >\n        Get started\n      </div>\n    </div>\n  </div>\n);\n\nexport interface ChatToPreviewLayoutProps {\n  chat?: ReactNode;\n  preview?: ReactNode;\n  startChatRatio?: number;\n  endChatRatio?: number;\n  background?: string;\n  speed?: number;\n  fps?: number;\n  durationInFrames?: number;\n  width?: number;\n  height?: number;\n  className?: string;\n}\n\nexport const ChatToPreviewLayout = ({\n  chat,\n  preview,\n  startChatRatio = 0.5,\n  endChatRatio = 0.25,\n  background = \"#0a0a0a\",\n  speed = 1,\n  fps = 30,\n  durationInFrames = 150,\n  width = 1280,\n  height = 720,\n  className,\n}: ChatToPreviewLayoutProps) => {\n  const safeSpeed = Math.max(0.01, speed);\n  const durationMs = (durationInFrames / fps) * 1000;\n  const frameMs = 1000 / fps;\n\n  const morphStartMs = (durationInFrames * 0.1 * frameMs) / safeSpeed;\n  const morphEndMs = (durationInFrames * 0.7 * frameMs) / safeSpeed;\n  const morphDurationMs = morphEndMs - morphStartMs;\n\n  const startBasis = `${startChatRatio * 100}%`;\n  const endBasis = `${endChatRatio * 100}%`;\n\n  const containerStyle: CSSProperties = {\n    background,\n    display: \"flex\",\n    gap: 16,\n    height,\n    overflow: \"hidden\",\n    padding: 32,\n    position: \"relative\",\n    width,\n  };\n\n  const CHAT_INNER_MIN = 520;\n  const PREVIEW_INNER_MIN = 720;\n\n  return (\n    <Timegroup\n      className={className}\n      duration={`${durationMs}ms`}\n      mode=\"fixed\"\n      style={containerStyle}\n    >\n      <>\n        <style>{`\n          @keyframes framecn-chat-preview-chat {\n            from { flex-basis: ${startBasis}; }\n            to { flex-basis: ${endBasis}; }\n          }\n          @keyframes framecn-chat-preview-preview {\n            from { opacity: 0; transform: translateX(40px); }\n            to { opacity: 1; transform: translateX(0); }\n          }\n        `}</style>\n        <div\n          style={{\n            animation: `framecn-chat-preview-chat ${morphDurationMs}ms cubic-bezier(0.16, 1, 0.3, 1) ${morphStartMs}ms backwards`,\n            border: \"1px solid rgba(255,255,255,0.08)\",\n            borderRadius: 16,\n            flexBasis: startBasis,\n            flexGrow: 0,\n            flexShrink: 0,\n            overflow: \"hidden\",\n            position: \"relative\",\n          }}\n        >\n          <div\n            style={{\n              inset: 0,\n              minWidth: CHAT_INNER_MIN,\n              position: \"absolute\",\n            }}\n          >\n            {chat ?? <DefaultChat />}\n          </div>\n        </div>\n        <div\n          style={{\n            animation: `framecn-chat-preview-preview ${morphDurationMs}ms cubic-bezier(0.16, 1, 0.3, 1) ${morphStartMs}ms backwards`,\n            border: \"1px solid rgba(255,255,255,0.08)\",\n            borderRadius: 16,\n            flexBasis: `calc(100% - ${endBasis})`,\n            flexGrow: 0,\n            flexShrink: 0,\n            overflow: \"hidden\",\n            position: \"relative\",\n          }}\n        >\n          <div\n            style={{\n              inset: 0,\n              minWidth: PREVIEW_INNER_MIN,\n              position: \"absolute\",\n            }}\n          >\n            {preview ?? <DefaultPreview />}\n          </div>\n        </div>\n      </>\n    </Timegroup>\n  );\n};\n",
      "type": "registry:component",
      "target": "components/framecn/chat-to-preview-layout.tsx"
    }
  ],
  "type": "registry:component"
}