import { useState, useEffect, useRef } from 'react'; import { categoryColorsSync } from '../services/categoryColorsSync'; const EDITOR_FONTS = [ { name: 'Source Code Pro', value: 'Source Code Pro' }, { name: 'Roboto Mono', value: 'Roboto Mono' }, { name: 'Inconsolata', value: 'Inconsolata' }, { name: 'System Mono', value: 'ui-monospace, monospace' }, ]; const PREVIEW_FONTS = [ { name: 'Merriweather', value: 'Merriweather' }, { name: 'Crimson Pro', value: 'Crimson Pro' }, { name: 'Roboto Serif', value: 'Roboto Serif' }, { name: 'Average', value: 'Average' }, { name: 'System Serif', value: 'ui-serif, Georgia, serif' }, ]; interface CategoriesSidebarProps { categories: string[]; selectedCategory: string; onSelectCategory: (category: string) => void; onCreateCategory: (name: string) => void; onRenameCategory: (oldName: string, newName: string) => void; isCollapsed: boolean; onToggleCollapse: () => void; username: string; onLogout: () => void; theme: 'light' | 'dark' | 'system'; onThemeChange: (theme: 'light' | 'dark' | 'system') => void; editorFont: string; onEditorFontChange: (font: string) => void; editorFontSize: number; onEditorFontSizeChange: (size: number) => void; previewFont: string; onPreviewFontChange: (font: string) => void; previewFontSize: number; onPreviewFontSizeChange: (size: number) => void; } const CATEGORY_COLORS = [ { name: 'Blue', bg: 'bg-blue-100 dark:bg-blue-900/30', text: 'text-blue-700 dark:text-blue-300', preview: '#dbeafe', dot: '#3b82f6' }, { name: 'Green', bg: 'bg-green-100 dark:bg-green-900/30', text: 'text-green-700 dark:text-green-300', preview: '#dcfce7', dot: '#22c55e' }, { name: 'Purple', bg: 'bg-purple-100 dark:bg-purple-900/30', text: 'text-purple-700 dark:text-purple-300', preview: '#f3e8ff', dot: '#a855f7' }, { name: 'Pink', bg: 'bg-pink-100 dark:bg-pink-900/30', text: 'text-pink-700 dark:text-pink-300', preview: '#fce7f3', dot: '#ec4899' }, { name: 'Yellow', bg: 'bg-yellow-100 dark:bg-yellow-900/30', text: 'text-yellow-700 dark:text-yellow-300', preview: '#fef9c3', dot: '#eab308' }, { name: 'Red', bg: 'bg-red-100 dark:bg-red-900/30', text: 'text-red-700 dark:text-red-300', preview: '#fee2e2', dot: '#ef4444' }, { name: 'Orange', bg: 'bg-orange-100 dark:bg-orange-900/30', text: 'text-orange-700 dark:text-orange-300', preview: '#ffedd5', dot: '#f97316' }, { name: 'Teal', bg: 'bg-teal-100 dark:bg-teal-900/30', text: 'text-teal-700 dark:text-teal-300', preview: '#ccfbf1', dot: '#14b8a6' }, { name: 'Indigo', bg: 'bg-indigo-100 dark:bg-indigo-900/30', text: 'text-indigo-700 dark:text-indigo-300', preview: '#e0e7ff', dot: '#6366f1' }, { name: 'Cyan', bg: 'bg-cyan-100 dark:bg-cyan-900/30', text: 'text-cyan-700 dark:text-cyan-300', preview: '#cffafe', dot: '#06b6d4' }, ]; export function CategoriesSidebar({ categories, selectedCategory, onSelectCategory, onCreateCategory, onRenameCategory, isCollapsed, onToggleCollapse, username, onLogout, theme, onThemeChange, editorFont, onEditorFontChange, editorFontSize, onEditorFontSizeChange, previewFont, onPreviewFontChange, previewFontSize, onPreviewFontSizeChange, }: CategoriesSidebarProps) { const [isCreating, setIsCreating] = useState(false); const [newCategoryName, setNewCategoryName] = useState(''); const [renamingCategory, setRenamingCategory] = useState(null); const [renameCategoryValue, setRenameCategoryValue] = useState(''); const [categoryColors, setCategoryColors] = useState>(() => categoryColorsSync.getAllColors()); const [colorPickerCategory, setColorPickerCategory] = useState(null); const [isSettingsCollapsed, setIsSettingsCollapsed] = useState(true); const inputRef = useRef(null); const renameInputRef = useRef(null); useEffect(() => { const handleColorChange = () => { setCategoryColors(categoryColorsSync.getAllColors()); }; categoryColorsSync.setChangeCallback(handleColorChange); window.addEventListener('categoryColorChanged', handleColorChange); return () => { window.removeEventListener('categoryColorChanged', handleColorChange); }; }, []); const setCategoryColor = async (category: string, colorIndex: number | null) => { await categoryColorsSync.setColor(category, colorIndex); setColorPickerCategory(null); }; useEffect(() => { if (isCreating && inputRef.current) { inputRef.current.focus(); } }, [isCreating]); useEffect(() => { if (renamingCategory && renameInputRef.current) { renameInputRef.current.focus(); renameInputRef.current.select(); } }, [renamingCategory]); const handleCreateCategory = () => { if (newCategoryName.trim()) { onCreateCategory(newCategoryName.trim()); setNewCategoryName(''); setIsCreating(false); } }; const handleRenameCategory = () => { if (renameCategoryValue.trim() && renamingCategory && renameCategoryValue.trim() !== renamingCategory) { onRenameCategory(renamingCategory, renameCategoryValue.trim()); } setRenamingCategory(null); setRenameCategoryValue(''); }; const startRenaming = (category: string) => { setRenamingCategory(category); setRenameCategoryValue(category); }; const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { handleCreateCategory(); } else if (e.key === 'Escape') { setIsCreating(false); setNewCategoryName(''); } }; const handleRenameKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { handleRenameCategory(); } else if (e.key === 'Escape') { setRenamingCategory(null); setRenameCategoryValue(''); } }; if (isCollapsed) { return ( ); } return (

Categories

{categories.map((category) => ( renamingCategory === category ? (
setRenameCategoryValue(e.target.value)} onKeyDown={handleRenameKeyDown} onBlur={handleRenameCategory} className="flex-1 text-sm px-2 py-1 border-none bg-transparent text-gray-900 dark:text-gray-100 focus:outline-none" />
Press Enter to save, Esc to cancel
) : (
{colorPickerCategory === category && (
{CATEGORY_COLORS.map((color, idx) => (
)}
) ))} {isCreating && (
setNewCategoryName(e.target.value)} onKeyDown={handleKeyDown} onBlur={() => { if (newCategoryName.trim()) { handleCreateCategory(); } else { setIsCreating(false); } }} placeholder="Category name..." className="flex-1 text-sm px-0 py-0 border-none bg-transparent text-gray-900 dark:text-gray-100 focus:ring-0 focus:outline-none" />
)}
{/* User Info and Settings */}
{username.charAt(0).toUpperCase()}
{username}
{!isSettingsCollapsed && (
{/* Theme Toggle */}
Theme
{/* Font Settings */}
Fonts {/* Editor Font */}
Editor
{/* Preview Font */}
Preview
)}
); }