/** * Shared theme list component used by both ThemeSelectPanel and ThemeSelectModal */ import React, { memo, useMemo } from 'react'; import { Check, Wand2 } from 'lucide-react'; import { useI18n } from '../application/i18n/I18nProvider'; import { TERMINAL_THEMES, USER_VISIBLE_TERMINAL_THEMES, isUiMatchTerminalThemeId } from '../infrastructure/config/terminalThemes'; import { TERMINAL_THEME_AUTO } from '../domain/terminalAppearance'; import { useCustomThemes } from '../application/state/customThemeStore'; import { cn } from '../lib/utils'; import { TerminalTheme } from '../types'; // Memoized theme item component const ThemeItem = memo(({ theme, isSelected, onSelect }: { theme: TerminalTheme; isSelected: boolean; onSelect: (id: string) => void; }) => ( )); ThemeItem.displayName = 'ThemeItem'; interface ThemeListProps { selectedThemeId: string; onSelect: (themeId: string) => void; /** Restrict the list to a single type; omit to show both sections. */ filterType?: 'dark' | 'light'; /** Render an "Auto (match app theme)" entry at the top. */ showAutoOption?: boolean; } export const ThemeList: React.FC = ({ selectedThemeId, onSelect, filterType, showAutoOption }) => { const { t } = useI18n(); const customThemes = useCustomThemes(); const deletedSelectedTheme = useMemo( () => (selectedThemeId && selectedThemeId !== TERMINAL_THEME_AUTO && !isUiMatchTerminalThemeId(selectedThemeId) && !TERMINAL_THEMES.some((theme) => theme.id === selectedThemeId) && !customThemes.some((theme) => theme.id === selectedThemeId) ? selectedThemeId : null), [customThemes, selectedThemeId], ); const hiddenSelectedTheme = useMemo( () => (isUiMatchTerminalThemeId(selectedThemeId) ? TERMINAL_THEMES.find(theme => theme.id === selectedThemeId) || null : null), [selectedThemeId], ); const { darkThemes, lightThemes } = useMemo(() => { const dark = USER_VISIBLE_TERMINAL_THEMES.filter(t => t.type === 'dark'); const light = USER_VISIBLE_TERMINAL_THEMES.filter(t => t.type === 'light'); return { darkThemes: dark, lightThemes: light }; }, []); const visibleCustomThemes = filterType ? customThemes.filter(theme => theme.type === filterType) : customThemes; const isAutoSelected = selectedThemeId === TERMINAL_THEME_AUTO; return ( <> {showAutoOption && ( )} {hiddenSelectedTheme && (
{t('terminal.hiddenTheme.title')}
{hiddenSelectedTheme.name}
{t('terminal.hiddenTheme.desc')}
)} {deletedSelectedTheme && (
Missing Theme
{deletedSelectedTheme}
This custom theme is no longer available. Pick another theme to replace it.
)} {/* Dark Themes Section */} {(!filterType || filterType === 'dark') && (
{t('settings.terminal.themeModal.darkThemes')}
{darkThemes.map(theme => ( ))}
)} {/* Light Themes Section */} {(!filterType || filterType === 'light') && (
{t('settings.terminal.themeModal.lightThemes')}
{lightThemes.map(theme => ( ))}
)} {/* Custom Themes Section */} {visibleCustomThemes.length > 0 && (
{t('terminal.customTheme.section')}
{visibleCustomThemes.map(theme => ( ))}
)} ); };