"use client"; import React, { useState, useMemo } from "react"; import * as LucideIcons from "lucide-react"; // lucide-react에서 실제 아이콘만 추출 (유틸/타입 제외) const ICON_ENTRIES = Object.entries(LucideIcons).filter( ([name, comp]) => typeof comp === "object" && name !== "default" && name !== "createLucideIcon" && name !== "icons" && name[0] === name[0].toUpperCase() && !name.endsWith("Icon"), ); // 자주 쓰는 아이콘 (상단 표시) const POPULAR = [ "Search", "Plus", "Edit", "Trash2", "Save", "Check", "X", "ChevronDown", "ChevronRight", "Settings", "User", "Users", "Mail", "Calendar", "Clock", "File", "Folder", "Download", "Upload", "Eye", "EyeOff", "Lock", "Unlock", "Star", "Heart", "Home", "ArrowLeft", "ArrowRight", "RefreshCw", "Filter", "BarChart3", "PieChart", "TrendingUp", "DollarSign", "ShoppingCart", "Package", ]; interface IconPickerProps { value?: string; onChange: (iconName: string) => void; className?: string; } export const IconPicker: React.FC = ({ value, onChange, className }) => { const [open, setOpen] = useState(false); const [search, setSearch] = useState(""); const filtered = useMemo(() => { if (!search.trim()) { // 인기 아이콘 + 나머지 (최대 80개) const popularSet = new Set(POPULAR); const popular = ICON_ENTRIES.filter(([n]) => popularSet.has(n)); const rest = ICON_ENTRIES.filter(([n]) => !popularSet.has(n)).slice(0, 80 - popular.length); return [...popular, ...rest]; } const q = search.toLowerCase(); return ICON_ENTRIES.filter(([name]) => name.toLowerCase().includes(q)).slice(0, 80); }, [search]); // 현재 선택된 아이콘 렌더 const SelectedIcon = value ? (LucideIcons as any)[value] : null; return (
{open && (
setSearch(e.target.value)} placeholder="아이콘 검색..." className="border-border bg-background w-full rounded border px-2 py-1 text-[0.65rem]" autoFocus />
{/* 선택 해제 */} {filtered.map(([name, Icon]) => { const IconComp = Icon as React.FC<{ size?: number }>; return ( ); })}
{filtered.length === 0 && (
“{search}” 결과 없음
)}
)}
); }; export default IconPicker;