import React, { useState, useMemo } from "react"; import { motion, AnimatePresence } from "framer-motion"; import { // Interface & Navigation Home, Menu, Settings, User, Users, LogOut, Bell, Bookmark, Calendar, Clock, Eye, EyeOff, Hash, Heart, Info, Link, Lock, Map, MessageSquare, Mic, Music, Paperclip, Phone, Pin, Plus, Save, Share, Star, Tag, Trash, Upload, Download, Edit, Copy, // Development & Tech Bot, Brain, Code, Terminal, Cpu, Database, GitBranch, Github, Globe, HardDrive, Laptop, Monitor, Server, Wifi, Cloud, Command, FileCode, FileJson, Folder, FolderOpen, Bug, Coffee, // Business & Finance Briefcase, Building, CreditCard, DollarSign, TrendingUp, TrendingDown, BarChart, PieChart, Calculator, Receipt, Wallet, // Creative & Design Palette, Brush, Camera, Film, Image, Layers, Layout, PenTool, Scissors, Type, Zap, Sparkles, Wand2, // Nature & Science Beaker, Atom, Dna, Flame, Leaf, Mountain, Sun, Moon, CloudRain, Snowflake, TreePine, Waves, Wind, // Gaming & Entertainment Gamepad2, Dice1, Trophy, Medal, Crown, Rocket, Target, Swords, Shield, // Communication Mail, Send, MessageCircle, Video, Voicemail, Radio, Podcast, Megaphone, // Miscellaneous Activity, Anchor, Award, Battery, Bluetooth, Compass, Crosshair, Flag, Flashlight, Gift, Headphones, Key, Lightbulb, Package, Puzzle, Search as SearchIcon, Smile, ThumbsUp, Umbrella, Watch, Wrench, type LucideIcon, } from "lucide-react"; import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { cn } from "@/lib/utils"; import { useTranslation } from "@/hooks/useTranslation"; /** * Icon categories for better organization */ const ICON_CATEGORIES = { "Interface & Navigation": [ { name: "home", icon: Home }, { name: "menu", icon: Menu }, { name: "settings", icon: Settings }, { name: "user", icon: User }, { name: "users", icon: Users }, { name: "log-out", icon: LogOut }, { name: "bell", icon: Bell }, { name: "bookmark", icon: Bookmark }, { name: "calendar", icon: Calendar }, { name: "clock", icon: Clock }, { name: "eye", icon: Eye }, { name: "eye-off", icon: EyeOff }, { name: "hash", icon: Hash }, { name: "heart", icon: Heart }, { name: "info", icon: Info }, { name: "link", icon: Link }, { name: "lock", icon: Lock }, { name: "map", icon: Map }, { name: "message-square", icon: MessageSquare }, { name: "mic", icon: Mic }, { name: "music", icon: Music }, { name: "paperclip", icon: Paperclip }, { name: "phone", icon: Phone }, { name: "pin", icon: Pin }, { name: "plus", icon: Plus }, { name: "save", icon: Save }, { name: "share", icon: Share }, { name: "star", icon: Star }, { name: "tag", icon: Tag }, { name: "trash", icon: Trash }, { name: "upload", icon: Upload }, { name: "download", icon: Download }, { name: "edit", icon: Edit }, { name: "copy", icon: Copy }, ], "Development & Tech": [ { name: "bot", icon: Bot }, { name: "brain", icon: Brain }, { name: "code", icon: Code }, { name: "terminal", icon: Terminal }, { name: "cpu", icon: Cpu }, { name: "database", icon: Database }, { name: "git-branch", icon: GitBranch }, { name: "github", icon: Github }, { name: "globe", icon: Globe }, { name: "hard-drive", icon: HardDrive }, { name: "laptop", icon: Laptop }, { name: "monitor", icon: Monitor }, { name: "server", icon: Server }, { name: "wifi", icon: Wifi }, { name: "cloud", icon: Cloud }, { name: "command", icon: Command }, { name: "file-code", icon: FileCode }, { name: "file-json", icon: FileJson }, { name: "folder", icon: Folder }, { name: "folder-open", icon: FolderOpen }, { name: "bug", icon: Bug }, { name: "coffee", icon: Coffee }, ], "Business & Finance": [ { name: "briefcase", icon: Briefcase }, { name: "building", icon: Building }, { name: "credit-card", icon: CreditCard }, { name: "dollar-sign", icon: DollarSign }, { name: "trending-up", icon: TrendingUp }, { name: "trending-down", icon: TrendingDown }, { name: "bar-chart", icon: BarChart }, { name: "pie-chart", icon: PieChart }, { name: "calculator", icon: Calculator }, { name: "receipt", icon: Receipt }, { name: "wallet", icon: Wallet }, ], "Creative & Design": [ { name: "palette", icon: Palette }, { name: "brush", icon: Brush }, { name: "camera", icon: Camera }, { name: "film", icon: Film }, { name: "image", icon: Image }, { name: "layers", icon: Layers }, { name: "layout", icon: Layout }, { name: "pen-tool", icon: PenTool }, { name: "scissors", icon: Scissors }, { name: "type", icon: Type }, { name: "zap", icon: Zap }, { name: "sparkles", icon: Sparkles }, { name: "wand-2", icon: Wand2 }, ], "Nature & Science": [ { name: "beaker", icon: Beaker }, { name: "atom", icon: Atom }, { name: "dna", icon: Dna }, { name: "flame", icon: Flame }, { name: "leaf", icon: Leaf }, { name: "mountain", icon: Mountain }, { name: "sun", icon: Sun }, { name: "moon", icon: Moon }, { name: "cloud-rain", icon: CloudRain }, { name: "snowflake", icon: Snowflake }, { name: "tree-pine", icon: TreePine }, { name: "waves", icon: Waves }, { name: "wind", icon: Wind }, ], "Gaming & Entertainment": [ { name: "gamepad-2", icon: Gamepad2 }, { name: "dice-1", icon: Dice1 }, { name: "trophy", icon: Trophy }, { name: "medal", icon: Medal }, { name: "crown", icon: Crown }, { name: "rocket", icon: Rocket }, { name: "target", icon: Target }, { name: "swords", icon: Swords }, { name: "shield", icon: Shield }, ], "Communication": [ { name: "mail", icon: Mail }, { name: "send", icon: Send }, { name: "message-circle", icon: MessageCircle }, { name: "video", icon: Video }, { name: "voicemail", icon: Voicemail }, { name: "radio", icon: Radio }, { name: "podcast", icon: Podcast }, { name: "megaphone", icon: Megaphone }, ], "Miscellaneous": [ { name: "activity", icon: Activity }, { name: "anchor", icon: Anchor }, { name: "award", icon: Award }, { name: "battery", icon: Battery }, { name: "bluetooth", icon: Bluetooth }, { name: "compass", icon: Compass }, { name: "crosshair", icon: Crosshair }, { name: "flag", icon: Flag }, { name: "flashlight", icon: Flashlight }, { name: "gift", icon: Gift }, { name: "headphones", icon: Headphones }, { name: "key", icon: Key }, { name: "lightbulb", icon: Lightbulb }, { name: "package", icon: Package }, { name: "puzzle", icon: Puzzle }, { name: "search", icon: SearchIcon }, { name: "smile", icon: Smile }, { name: "thumbs-up", icon: ThumbsUp }, { name: "umbrella", icon: Umbrella }, { name: "watch", icon: Watch }, { name: "wrench", icon: Wrench }, ], } as const; type IconCategory = typeof ICON_CATEGORIES[keyof typeof ICON_CATEGORIES]; type IconItem = IconCategory[number]; interface IconPickerProps { /** * Currently selected icon name */ value: string; /** * Callback when an icon is selected */ onSelect: (iconName: string) => void; /** * Whether the picker is open */ isOpen: boolean; /** * Callback to close the picker */ onClose: () => void; } /** * Icon picker component with search and categories * Similar to Notion's icon picker interface */ export const IconPicker: React.FC = ({ value, onSelect, isOpen, onClose, }) => { const [searchQuery, setSearchQuery] = useState(""); const [hoveredIcon, setHoveredIcon] = useState(null); const { t } = useTranslation(); // Filter icons based on search query const filteredCategories = useMemo(() => { if (!searchQuery.trim()) return ICON_CATEGORIES; const query = searchQuery.toLowerCase(); const filtered: Record = {}; Object.entries(ICON_CATEGORIES).forEach(([category, icons]) => { const matchingIcons = icons.filter(({ name }) => name.toLowerCase().includes(query) ); if (matchingIcons.length > 0) { filtered[category] = matchingIcons; } }); return filtered; }, [searchQuery]); // Get all icons for search const allIcons = useMemo(() => { return Object.values(ICON_CATEGORIES).flat(); }, []); const handleSelect = (iconName: string) => { onSelect(iconName); onClose(); setSearchQuery(""); }; return ( {t('agents.chooseAnIcon')} {/* Search Bar */}
setSearchQuery(e.target.value)} className="pl-10" autoFocus />
{/* Icon Grid */}
{Object.keys(filteredCategories).length === 0 ? (

{t('agents.noIconsFound')} "{searchQuery}"

) : (
{Object.entries(filteredCategories).map(([category, icons]) => (

{category === "Interface & Navigation" ? t('agents.iconCategories.interfaceNavigation') : category === "Development & Tech" ? t('agents.iconCategories.developmentTech') : category === "Business & Finance" ? t('agents.iconCategories.businessFinance') : category === "Creative & Design" ? t('agents.iconCategories.creativeDesign') : category === "Nature & Science" ? t('agents.iconCategories.natureScience') : category === "Gaming & Entertainment" ? t('agents.iconCategories.gamingEntertainment') : category === "Communication" ? t('agents.iconCategories.communication') : category === "Miscellaneous" ? t('agents.iconCategories.miscellaneous') : category}

{icons.map((item: IconItem) => { const Icon = item.icon; return ( handleSelect(item.name)} onMouseEnter={() => setHoveredIcon(item.name)} onMouseLeave={() => setHoveredIcon(null)} className={cn( "p-2.5 rounded-lg transition-colors relative group", "hover:bg-accent hover:text-accent-foreground", value === item.name && "bg-primary/10 text-primary" )} > {hoveredIcon === item.name && (
{item.name}
)}
); })}
))}
)}
{/* Footer */}

{t('agents.clickToSelect')} • {allIcons.length} {t('agents.iconsAvailable')}

); }; // Export all available icon names for type safety export const AVAILABLE_ICONS = Object.values(ICON_CATEGORIES) .flat() .map(({ name }) => name); // Export icon map for easy access export const ICON_MAP = Object.values(ICON_CATEGORIES) .flat() .reduce((acc, { name, icon }) => ({ ...acc, [name]: icon }), {} as Record);