"use client"; /** * DynamicConfigPanel * * JSON Schema 기반으로 동적으로 설정 UI를 생성하는 패널 * 모든 Unified 컴포넌트의 설정을 단일 컴포넌트로 처리 */ import React, { useCallback, useMemo } from "react"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Switch } from "@/components/ui/switch"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Slider } from "@/components/ui/slider"; import { Textarea } from "@/components/ui/textarea"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"; import { ChevronDown } from "lucide-react"; import { JSONSchemaProperty, UnifiedConfigSchema } from "@/types/unified-components"; import { cn } from "@/lib/utils"; interface DynamicConfigPanelProps { schema: UnifiedConfigSchema; config: Record; onChange: (key: string, value: unknown) => void; className?: string; } /** * 개별 스키마 속성을 렌더링하는 컴포넌트 */ function SchemaField({ name, property, value, onChange, path = [], }: { name: string; property: JSONSchemaProperty; value: unknown; onChange: (key: string, value: unknown) => void; path?: string[]; }) { const fieldPath = [...path, name].join("."); // 값 변경 핸들러 const handleChange = useCallback( (newValue: unknown) => { onChange(fieldPath, newValue); }, [fieldPath, onChange] ); // 타입에 따른 컴포넌트 렌더링 const renderField = () => { // enum이 있으면 Select 렌더링 if (property.enum && property.enum.length > 0) { return ( ); } // 타입별 렌더링 switch (property.type) { case "string": return ( handleChange(e.target.value)} placeholder={property.description} className="h-8 text-xs" /> ); case "number": return ( handleChange(e.target.value ? Number(e.target.value) : undefined)} placeholder={property.description} className="h-8 text-xs" /> ); case "boolean": return ( ); case "array": // 배열은 간단한 텍스트 입력으로 처리 (쉼표 구분) return (