import { createTheme, type MantineColorsTuple, type MantineThemeOverride } from '@mantine/core' import { generateColors } from '@mantine/colors-generator' import base from './base.json' import active from './active.json' import { palettes } from './palettes' export type Palette = { name: string description?: string primaryColor?: string bases?: Record } // Each palette extends the shared base (fonts, radius, component defaults) and // auto-expands its `bases` hexes into full 10-shade Mantine scales, so a palette // only declares one colour per semantic role. Deterministic, so a previewed // palette and a persisted one render identically. export const buildTheme = (palette: Palette): MantineThemeOverride => { const colors: Record = Object.fromEntries( Object.entries(palette.bases ?? {}).map(([role, hex]) => [role, generateColors(hex)]), ) return createTheme({ ...(base as MantineThemeOverride), ...(palette.primaryColor ? { primaryColor: palette.primaryColor } : {}), ...(Object.keys(colors).length ? { colors } : {}), }) } export const themes: Record = Object.fromEntries( Object.entries(palettes).map(([id, palette]) => [id, buildTheme(palette as Palette)]), ) export { palettes } export const activeId = active.id export const activeTheme: MantineThemeOverride = themes[active.id] ?? themes.default // Back-compat: existing imports of `theme` resolve to the active palette. export const theme = activeTheme