import {
BOOK_FONT_SLOTS,
BOOK_PALETTE_KEYS,
BOOK_THEME_DECORATIONS,
BOOK_THEME_MOTIFS,
BOOK_THEME_PRESETS,
bookThemeOf,
type BookFontSlot,
type BookPaletteKey,
type BookThemeFont,
type BookThemePreset,
} from '@trek/shared';
import { Check, ImageIcon, RotateCcw } from 'lucide-react';
import { useMemo } from 'react';
import '../../../styles/studio-theme.css';
import { useToast } from '../../shared/Toast';
import { Choice, Line, Picks, Section, Switch } from '../StudioControls';
import { StudioFontPicker } from '../StudioFontPicker';
import { PanelHead, Shelf } from '../StudioPanelHead';
import type { StudioT } from '../StudioSidebar';
import { ThemeSheet } from './ThemeSheet';
import { useStudioTheme } from './useStudioTheme';
/**
* The Theme section of the rail: seventeen built-in looks, the palette, the
* typefaces and the motifs of the one being put together, and applying it to
* the book or to the page that is open.
*
* Nothing changes on the page until it is applied: picking a theme and
* trying colours is a draft, so the panel can be played with freely, and an
* apply is one undo step however many pages it recoloured.
*/
/** One built-in theme as a card: its paper, its display face in its ink, its three accents. */
function ThemeCard({
preset,
on,
inUse,
onPick,
t,
}: {
preset: BookThemePreset;
on: boolean;
inUse: boolean;
onPick: () => void;
t: StudioT;
}) {
const display = useMemo(() => bookThemeOf(preset.id).fonts.display, [preset.id]);
return (
);
}
/**
* One palette entry: its colour, which is the picker, and its name. The three
* accents share one name under them, so each shows its colour alone and says
* its own name to a screen reader and on hover.
*/
function PaletteEntry({
name,
hex,
onPick,
t,
}: {
name: BookPaletteKey;
hex: string;
onPick: (hex: string) => void;
t: StudioT;
}) {
const accent = name.startsWith('accent');
const label = t(`studio.theme.token.${name}`);
return (
);
}
/** The script a theme falls back to when one is switched on: the handwriting most themes pair with. */
const DEFAULT_SCRIPT = 'caveat';
/**
* One typeface slot, in the Studio's own font picker. The script can be
* switched off, since a calm theme sets no handwriting at all.
*/
function FontSlot({
slot,
face,
onPick,
t,
}: {
slot: BookFontSlot;
face: BookThemeFont | null;
onPick: (font: string | null, weight?: number) => void;
t: StudioT;
}) {
const label = t(`studio.theme.slot.${slot}`);
const picker = face && (
onPick(p.font, p.weight)} t={t} />
);
if (slot !== 'script')
return (
{picker}
);
return (