'use client'; import { cn } from '@/lib/utils'; import { Popover, PopoverContent, PopoverTrigger, } from '@/components/shared/ui/popover'; import { useThemeSwitch } from '@/components/shared/useThemeSwitch'; import { useEffect, useMemo, useState } from 'react'; import chroma from 'chroma-js'; import { Button } from '@/components/shared/ui/button'; import { ColorThemeObject, complementaryColorThemes, expensiveColorThemes, freshColorThemes, minimalColorThemes, vividColorThemes, } from '@/components/bricks/theme/color-themes'; import { CheckIcon, Loader2, ChevronUpIcon, ChevronDownIcon, ChevronsDownIcon, } from 'lucide-react'; import { DEFAULT_THEME_INDEX, useThemeStore, } from '@/components/bricks/state/theme-state'; import { getStyleString } from '@/components/bricks/theme/code-stringifiers/get-style-string'; import { FontPairing } from '@/components/bricks/theme/font-pairing'; import { CopyThemeCode } from '@/components/bricks/theme/copy-theme-code'; import { getGoogleFontDefinition } from '@/components/bricks/theme/get-google-font-definition'; import { Separator } from '@/components/shared/ui/separator'; export const getDisplayFontName = (fontPairing: FontPairing) => { return fontPairing.display.name === fontPairing.default.name ? fontPairing.display.name : `${fontPairing.display.name} & ${fontPairing.default.name}`; }; export const ThemeAndFontSelector = ({ className, onThemeChanged, showCopyThemeCodeButton = false, showChangeThemeLabel = true, // Show input label }: { className?: string; onThemeChanged?: (theme: ColorThemeObject) => void; showCopyThemeCodeButton?: boolean; showChangeThemeLabel?: boolean; }) => { const stateThemeObject = useThemeStore((state) => state.themeObject); const stateSetThemeObject = useThemeStore((state) => state.setThemeObject); const stateFonts = useThemeStore((state) => state.fonts); const stateSetFonts = useThemeStore((state) => state.setFonts); const { default: fontFamilyDefault, display: fontFamilyDisplay } = stateFonts; const [showMoreThemes, setShowMoreThemes] = useState(false); const { currentTheme } = useThemeSwitch(); const isDarkMode = currentTheme === 'dark'; const [themeSelectorOpen, setThemeSelectorOpen] = useState(false); const [isClient, setIsClient] = useState(false); const themes = [ complementaryColorThemes[DEFAULT_THEME_INDEX], vividColorThemes[0], expensiveColorThemes[0], freshColorThemes[3], vividColorThemes[4], expensiveColorThemes[4], minimalColorThemes[0], minimalColorThemes[4], minimalColorThemes[7], ]; const moreThemes = [ freshColorThemes[1], vividColorThemes[2], expensiveColorThemes[2], freshColorThemes[2], vividColorThemes[3], expensiveColorThemes[3], ...complementaryColorThemes.slice(1, 7), ...complementaryColorThemes.slice(24), vividColorThemes[9], ...complementaryColorThemes.slice(9, 16), ...complementaryColorThemes.slice(18, 22), vividColorThemes[11], ]; const fontPairings: FontPairing[] = [ { display: { name: 'DM Serif Display', variableFont: false, weights: [400], }, default: { name: 'DM Sans', variableFont: true, }, }, { display: { name: 'Roboto Serif', variableFont: false, weights: [400, 600], }, default: { name: 'Roboto Slab', variableFont: false, weights: [400], }, }, { display: { name: 'Karla', variableFont: true, }, default: { name: 'Merriweather', variableFont: false, weights: [400, 700], }, }, { display: { name: 'Montserrat', variableFont: true, }, default: { name: 'Hind', variableFont: false, weights: [400, 600], }, }, { display: { name: 'Roboto', variableFont: false, weights: [400, 700], }, default: { name: 'Roboto Mono', variableFont: true, }, }, { display: { name: 'Rubik', variableFont: true, }, default: { name: 'Roboto Serif', variableFont: true, }, }, { display: { name: 'Syne', variableFont: true, }, default: { name: 'Inter', variableFont: true, }, }, { display: { name: 'Work Sans', variableFont: true, }, default: { name: 'Merriweather', variableFont: false, weights: [400, 700], }, }, { display: { name: 'Oswald', variableFont: true, }, default: { name: 'Source Sans 3', // Source Sans Pro variableFont: false, weights: [400, 600], }, }, ]; const theme = { primary: { lighter: stateThemeObject.colors.primary[3], light: stateThemeObject.colors.primary[4], main: stateThemeObject.colors.primary[5], dark: stateThemeObject.colors.primary[6], darker: stateThemeObject.colors.primary[7], }, secondary: { lighter: stateThemeObject.colors.secondary[3], light: stateThemeObject.colors.secondary[4], main: stateThemeObject.colors.secondary[5], dark: stateThemeObject.colors.secondary[6], darker: stateThemeObject.colors.secondary[7], }, primaryTailwindName: stateThemeObject.tailwindNames.primary, secondaryTailwindName: stateThemeObject.tailwindNames.secondary, }; const themeStyleString = getStyleString({ primary: theme.primary, secondary: theme.secondary, }); const pickColorTheme = (theme: ColorThemeObject, index: number) => { stateSetThemeObject(theme); if (onThemeChanged) { onThemeChanged(theme); } }; const mapColor = (color: string, index: number) => (
); const mapColors = ( theme: ColorThemeObject, index?: number, selected?: boolean, ) => { const relevantPrimaryColors = [ theme.colors.primary[3], theme.colors.primary[4], theme.colors.primary[5], theme.colors.primary[6], theme.colors.primary[7], ]; const relevantSecondaryColors = [ theme.colors.secondary[3], theme.colors.secondary[4], theme.colors.secondary[5], theme.colors.secondary[6], theme.colors.secondary[7], ]; return (Change theme
) : null} {isClient ? ( ) : (Fonts {getDisplayFontName(stateFonts)}
Themes {stateThemeObject.name}
{themes.map((theme, index) => (