"use client"; /** * V2FileUpload 설정 패널 * 토스식 단계별 UX: 파일 형식(카드선택) -> 제한 설정 -> 동작/표시(Switch) -> 고급 설정(접힘) */ import React, { useState, useMemo, useCallback } from "react"; import { Input } from "@/components/ui/input"; import { Switch } from "@/components/ui/switch"; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@/components/ui/collapsible"; import { Settings, ChevronDown, FileText, Image, Archive, File, FileImage, } from "lucide-react"; import { cn } from "@/lib/utils"; import { FileUploadConfig } from "@/lib/registry/components/v2-file-upload/types"; import { V2FileUploadDefaultConfig } from "@/lib/registry/components/v2-file-upload/config"; const FILE_TYPE_CARDS = [ { value: "*/*", label: "모든 파일", icon: File, desc: "제한 없음" }, { value: "image/*", label: "이미지", icon: Image, desc: "JPG, PNG 등" }, { value: ".pdf,.doc,.docx,.xls,.xlsx", label: "문서", icon: FileText, desc: "PDF, Word, Excel" }, { value: "image/*,.pdf", label: "이미지+PDF", icon: FileImage, desc: "이미지와 PDF" }, { value: ".zip,.rar,.7z", label: "압축 파일", icon: Archive, desc: "ZIP, RAR 등" }, ] as const; const VARIANT_CARDS = [ { value: "default", label: "기본", desc: "기본 스타일" }, { value: "outlined", label: "테두리", desc: "테두리 강조" }, { value: "filled", label: "채움", desc: "배경 채움" }, ] as const; const SIZE_CARDS = [ { value: "sm", label: "작게" }, { value: "md", label: "보통" }, { value: "lg", label: "크게" }, ] as const; interface V2FileUploadConfigPanelProps { config: FileUploadConfig; onChange: (config: Partial) => void; screenTableName?: string; } export const V2FileUploadConfigPanel: React.FC = ({ config: propConfig, onChange, screenTableName, }) => { const [advancedOpen, setAdvancedOpen] = useState(false); const config = useMemo(() => ({ ...V2FileUploadDefaultConfig, ...propConfig, }), [propConfig]); const maxSizeMB = useMemo(() => { return (config.maxSize || 10 * 1024 * 1024) / (1024 * 1024); }, [config.maxSize]); const updateConfig = useCallback(( field: K, value: FileUploadConfig[K] ) => { const newConfig = { ...config, [field]: value }; onChange({ [field]: value }); if (typeof window !== "undefined") { window.dispatchEvent( new CustomEvent("componentConfigChanged", { detail: { config: newConfig }, }) ); } }, [config, onChange]); const handleMaxSizeChange = useCallback((value: string) => { const mb = parseFloat(value) || 10; updateConfig("maxSize", mb * 1024 * 1024); }, [updateConfig]); return (
{/* ─── 1단계: 허용 파일 형식 카드 선택 ─── */}

허용 파일 형식

{FILE_TYPE_CARDS.map((card) => { const Icon = card.icon; const isSelected = (config.accept || "*/*") === card.value; return ( ); })}

업로드 가능한 파일 유형을 선택해요

{/* ─── 2단계: 파일 제한 설정 ─── */}

파일 제한

안내 텍스트 updateConfig("placeholder", e.target.value)} placeholder="파일을 선택하세요" className="h-7 w-[160px] text-xs" />
최대 크기 (MB) handleMaxSizeChange(e.target.value)} className="mt-1 h-7 text-xs" />
최대 파일 수 updateConfig("maxFiles", parseInt(e.target.value) || 10)} className="mt-1 h-7 text-xs" />
{/* ─── 3단계: 동작 설정 (Switch) ─── */}

동작 설정

다중 파일 선택

여러 파일을 한 번에 선택할 수 있어요

updateConfig("multiple", checked)} />

파일 삭제 허용

업로드된 파일을 삭제할 수 있어요

updateConfig("allowDelete", checked)} />

파일 다운로드 허용

업로드된 파일을 다운로드할 수 있어요

updateConfig("allowDownload", checked)} />
{/* ─── 4단계: 표시 설정 (Switch) ─── */}

표시 설정

미리보기 표시

이미지 파일의 미리보기를 보여줘요

updateConfig("showPreview", checked)} />

파일 목록 표시

업로드된 파일의 목록을 보여줘요

updateConfig("showFileList", checked)} />

파일 크기 표시

각 파일의 크기를 함께 보여줘요

updateConfig("showFileSize", checked)} />
{/* ─── 5단계: 스타일 카드 선택 ─── */}

스타일

스타일 변형
{VARIANT_CARDS.map((card) => { const isSelected = (config.variant || "default") === card.value; return ( ); })}
크기
{SIZE_CARDS.map((card) => { const isSelected = (config.size || "md") === card.value; return ( ); })}
{/* ─── 6단계: 고급 설정 (기본 접혀있음) ─── */}
{/* 도움말 */}
도움말 updateConfig("helperText", e.target.value)} placeholder="안내 문구 입력" className="h-7 w-[160px] text-xs" />
{/* 필수 입력 */}

필수 입력

파일 첨부를 필수로 해요

updateConfig("required", checked)} />
{/* 읽기 전용 */}

읽기 전용

파일 목록만 볼 수 있어요

updateConfig("readonly", checked)} />
{/* 비활성화 */}

비활성화

컴포넌트를 비활성화해요

updateConfig("disabled", checked)} />
); }; V2FileUploadConfigPanel.displayName = "V2FileUploadConfigPanel"; export default V2FileUploadConfigPanel;