import { memo, useId } from "react"; import { Pressable, View } from "react-native"; import Svg, { Circle, Defs, RadialGradient, Stop } from "react-native-svg"; import { mixThemePreviewBase, THEME_PREVIEW_RENDER_SPECS } from "@t3tools/shared/themePreview"; import { SymbolView } from "../../../../components/AppSymbol"; import { AppText as Text } from "../../../../components/AppText"; import { getMobileThemeVariables, getMobileThemePreviewColors, MOBILE_THEME_OPTIONS, type MobileThemeAppearance, type MobileThemeId, type MobileThemeIds, type MobileThemeMode, type MobileThemeVariables, } from "../../../../lib/mobileTheme"; import { useThemeColor } from "../../../../lib/useThemeColor"; import { useAppearancePreferences } from "../AppearancePreferencesProvider"; const APPEARANCE_MODES: ReadonlyArray<{ readonly id: MobileThemeMode; readonly label: string; }> = [ { id: "system", label: "System" }, { id: "light", label: "Light" }, { id: "dark", label: "Dark" }, ]; const PreviewOrb = memo(function PreviewOrb(props: { readonly appearance: MobileThemeAppearance; readonly compact?: boolean; readonly themeId: MobileThemeId; }) { const idPrefix = useId().replaceAll(":", ""); const accentGradientId = `${idPrefix}-accent-glow`; const actionGradientId = `${idPrefix}-action-glow`; const colors = getMobileThemePreviewColors(props.themeId, props.appearance); const spec = THEME_PREVIEW_RENDER_SPECS[props.appearance]; const accentRadius = Math.hypot( Math.max(spec.accent.center[0], 1 - spec.accent.center[0]), Math.max(spec.accent.center[1], 1 - spec.accent.center[1]), ); const actionRadius = Math.hypot( Math.max(spec.action.center[0], 1 - spec.action.center[0]), Math.max(spec.action.center[1], 1 - spec.action.center[1]), ); const position = (value: number) => `${value * 100}%`; const radius = (value: number) => `${value * 100}%`; return ( ); }); function ThemeCard(props: { readonly disabled: boolean; readonly darkSelected: boolean; readonly label: string; readonly lightSelected: boolean; readonly onSelectBoth: () => void; readonly onSelect: (appearance: MobileThemeAppearance) => void; readonly themeId: MobileThemeId; }) { const badgeBackground = useThemeColor("--color-card"); const badgeIcon = useThemeColor("--color-icon"); const choice = (appearance: MobileThemeAppearance, selected: boolean) => ( props.onSelect(appearance)} > {selected ? ( ) : null} ); return ( {choice("light", props.lightSelected)} {choice("dark", props.darkSelected)} {props.label} ); } function PreviewPane(props: { readonly colors: MobileThemeVariables; readonly compact?: boolean }) { return ( ); } function ModePreview(props: { readonly mode: MobileThemeMode; readonly themeIds: MobileThemeIds }) { const light = getMobileThemeVariables(props.themeIds.light, "light"); const dark = getMobileThemeVariables(props.themeIds.dark, "dark"); const currentBorder = useThemeColor("--color-border"); const currentFrame = useThemeColor("--color-drawer"); const currentIndicator = useThemeColor("--color-foreground-muted"); const frameColor = props.mode === "light" ? light["--color-border"] : props.mode === "dark" ? dark["--color-border"] : currentBorder; const frameBackground = props.mode === "light" ? light["--color-drawer"] : props.mode === "dark" ? dark["--color-drawer"] : currentFrame; const indicatorColor = props.mode === "light" ? light["--color-foreground-muted"] : props.mode === "dark" ? dark["--color-foreground-muted"] : currentIndicator; return ( {props.mode === "system" ? ( <> ) : ( )} ); } function ModeCard(props: { readonly disabled: boolean; readonly label: string; readonly mode: MobileThemeMode; readonly onPress: () => void; readonly selected: boolean; readonly themeIds: MobileThemeIds; }) { return ( {props.label} ); } function SectionLabel({ children }: { readonly children: string }) { return {children}; } export function ThemeAppearanceSection() { const { isReady, setThemeIdForAppearance, setThemeIdForBothAppearances, setThemeMode, themeIds, themeMode, } = useAppearancePreferences(); return ( Color scheme {APPEARANCE_MODES.map((mode) => ( setThemeMode(mode.id)} selected={mode.id === themeMode} themeIds={themeIds} /> ))} Themes {MOBILE_THEME_OPTIONS.map((theme) => ( setThemeIdForAppearance(appearance, theme.id)} onSelectBoth={() => setThemeIdForBothAppearances(theme.id)} themeId={theme.id} /> ))} ); }