import React, { useEffect, useState } from 'react'; import { useTheme } from './ThemeProvider'; import { THEME_MODES } from './themeModes'; import { themesForHalf, type ThemeHalf } from '../utils/themeRegistry'; import { configStore } from '../config/configStore'; import { useConfigValue } from '../config/useConfig'; import { faviconDataUrl, type FaviconStyle } from '@plannotator/core/favicon'; interface ThemeTabProps { onPreview?: () => void; compact?: boolean; } const HALVES: { id: ThemeHalf; label: string }[] = [ { id: 'light', label: 'Light' }, { id: 'dark', label: 'Dark' }, ]; const FAVICON_STYLES: { id: FaviconStyle; label: string }[] = [ { id: 'totman', label: 'Totman' }, { id: 'classic', label: 'Classic P' }, ]; const SyntaxLinesIcon: React.FC<{ className?: string }> = ({ className }) => ( ); /** * The favicon style choices. Rendered in both layouts, so it lives in one place. * The compact layout drops the visible "Favicon" heading the full layout has, so * the group carries its own accessible name and two unlabelled image buttons are * never all a screen reader gets. */ const FaviconStyleControl: React.FC<{ selected: FaviconStyle }> = ({ selected }) => (
{FAVICON_STYLES.map(({ id, label }) => ( ))}
); export const ThemeTab: React.FC = ({ onPreview, compact }) => { const { mode, setMode, lightTheme, darkTheme, setHalfTheme, availableThemes, preferredMode, manageFavicon, } = useTheme(); const faviconStyle = useConfigValue('faviconStyle'); // Which half the grid assigns to. Follows the mode you are actually seeing, // so opening Settings in dark mode edits the dark half first. const [half, setHalf] = useState(preferredMode); useEffect(() => setHalf(preferredMode), [preferredMode]); const pair: Record = { light: lightTheme, dark: darkTheme }; const themes = themesForHalf(availableThemes, half); const nameOf = (id: string) => availableThemes.find(theme => theme.id === id)?.name ?? id; const summary = (
{HALVES.map(({ id, label }, index) => ( {index > 0 && ยท} ))}
); return (
{/* Mode */}
{!compact && }
{THEME_MODES.map(({ id, label, Icon }) => ( ))}
{!compact && manageFavicon && (
)} {!compact && (

System follows your OS and switches between the two themes below.

)} {compact && ( <> {manageFavicon && }
{summary}
)}
{/* Theme pair */}
{!compact && ( <>
= matched syntax colors {onPreview && ( )}
{summary} )} {/* Which half the grid assigns to */}
Assigning
{HALVES.map(({ id, label }) => ( ))}
{themes.map(theme => { const isSelected = pair[half] === theme.id; const colors = theme.colors[half]; return ( ); })}
); };