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 (
);
})}
);
};