{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "model",
  "type": "registry:component",
  "title": "Model",
  "description": "Integrate 3D model",
  "dependencies": [
    "@react-three/fiber",
    "@react-three/drei",
    "three"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "components/chatcn/3d/model.tsx",
      "content": "\"use client\";\nimport { Canvas } from \"@react-three/fiber\";\nimport {\n  Environment,\n  Float,\n  OrbitControls,\n  useGLTF,\n  useAnimations,\n  Html,\n} from \"@react-three/drei\";\nimport React, { Suspense, ReactNode, useEffect } from \"react\";\n\nexport type EnvironmentPreset =\n  | \"city\"\n  | \"night\"\n  | \"sunset\"\n  | \"forest\"\n  | \"warehouse\"\n  | \"studio\"\n  | \"apartment\";\nexport type LightingType = \"soft\" | \"dramatic\" | \"studio\";\n\nexport function Loader() {\n  return (\n    <Html center>\n      <div className=\"flex flex-col items-center gap-2\">\n        <div className=\"w-8 h-8 border-2 border-gray-600 border-t-transparent rounded-full animate-spin\" />\n        <p className=\"text-xs text-gray-600\">Loading model…</p>\n      </div>\n    </Html>\n  );\n}\n\nexport interface ModelProps {\n  children: ReactNode;\n  width?: string;\n  height?: string;\n  fov?: number;\n  cameraPosition?: [number, number, number];\n  shadow?: boolean;\n}\n\nexport function ModelContent({\n  children,\n  width = \"100%\",\n  height = \"100%\",\n  fov = 45,\n  cameraPosition = [0, 0, 4],\n  shadow = false,\n}: ModelProps) {\n  return (\n    <div style={{ width, height }}>\n      <Canvas camera={{ fov, position: cameraPosition }} shadows={shadow}>\n        <Suspense fallback={<Loader />}>{children}</Suspense>\n      </Canvas>\n    </div>\n  );\n}\n\nexport function ModelScene({\n  bgColor = \"#000000\",\n  env = \"city\",\n}: {\n  bgColor?: string;\n  env?: EnvironmentPreset;\n}) {\n  return (\n    <>\n      <color attach=\"background\" args={[bgColor]} />\n      <Environment preset={env} />\n    </>\n  );\n}\n\nexport function ModelCamera({ }: {\n  fov?: number;\n  position?: [number, number, number];\n}) {\n  return null;\n}\n\nexport function ModelLighting({\n  type = \"soft\",\n  shadow = false,\n}: {\n  type?: LightingType;\n  shadow?: boolean;\n}) {\n  if (type === \"soft\") return <ambientLight intensity={0.4} />;\n  if (type === \"dramatic\")\n    return <directionalLight position={[2, 2, 5]} intensity={1.2} />;\n  if (type === \"studio\")\n    return (\n      <>\n        <ambientLight intensity={0.5} />\n        <spotLight\n          position={[10, 10, 10]}\n          intensity={1.5}\n          castShadow={shadow}\n        />\n      </>\n    );\n  return null;\n}\n\nexport function Model({\n  src,\n  scale = 1,\n  position = [0, 0, 0],\n  rotation = [0, 0, 0],\n  float = false,\n}: {\n  src: string;\n  scale?: number;\n  position?: [number, number, number];\n  rotation?: [number, number, number];\n  float?: boolean;\n}) {\n  const { scene, animations } = useGLTF(src);\n  const { actions } = useAnimations(animations, scene);\n  useEffect(() => {\n    Object.values(actions).forEach((action) => action?.play());\n  }, [actions]);\n\n  const content = (\n    <primitive\n      object={scene}\n      scale={scale}\n      position={position}\n      rotation={rotation}\n    />\n  );\n\n  return float ? <Float>{content}</Float> : content;\n}\n\nexport function ModelControls({\n  autoRotate = false,\n  rotationSpeed = 1,\n  zoom = false,\n  reverse = false,\n  ...props\n}: {\n  autoRotate?: boolean;\n  rotationSpeed?: number;\n  zoom?: boolean;\n  reverse?: boolean;\n  [key: string]: unknown;\n}) {\n  return (\n    <OrbitControls\n      enableZoom={zoom}\n      autoRotate={autoRotate}\n      autoRotateSpeed={rotationSpeed}\n      reverseOrbit={reverse}\n      {...props}\n    />\n  );\n}\n",
      "type": "registry:component"
    }
  ]
}