'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 (
{isClient ? ( <> {selected && (
)} {relevantPrimaryColors.map(mapColor)} {relevantSecondaryColors.map(mapColor)} ) : (
)}
); }; // Create font URL for Google Fonts const fonts = useMemo(() => { return getGoogleFontDefinition({ fontFamilyDisplay, fontFamilyDefault, }); }, [fontFamilyDefault, fontFamilyDisplay]); const selectedFontImageName = `${fontFamilyDisplay.name.replace( / /g, '_', )}+${fontFamilyDefault.name.replace(/ /g, '_')}`; useEffect(() => { setIsClient(true); }, []); return ( <> {isClient ? ( <> ) : null}
{showChangeThemeLabel ? (

Change theme

) : null} {isClient ? ( ) : (
)}
{/* fonts */}

Fonts {getDisplayFontName(stateFonts)}

{fontPairings.map((fontPairing, index) => { const fontImageName = `${fontPairing.display.name.replace( / /g, '_', )}+${fontPairing.default.name.replace(/ /g, '_')}`; const isSelected = stateFonts.display.name === fontPairing.display.name && stateFonts.default.name === fontPairing.default.name; return (
{/* {getDisplayFontName(fontPairing)} */}
); })}

{/* main themes */}

Themes {stateThemeObject.name}

{themes.map((theme, index) => (
))} {/* other themes */} {showMoreThemes ? ( <>
{moreThemes.map((theme, index) => (
))} ) : null}
{showCopyThemeCodeButton ? ( <> ) : null}
); };