"use client"; import type { IconProps } from "@phosphor-icons/react"; import { Desktop } from "@phosphor-icons/react/dist/ssr/Desktop"; import { Moon } from "@phosphor-icons/react/dist/ssr/Moon"; import { Sun } from "@phosphor-icons/react/dist/ssr/Sun"; import { type Props as ButtonProps, Button, } from "@pythnetwork/component-library/Button"; import clsx from "clsx"; import { motion } from "motion/react"; import { useTheme } from "next-themes"; import { type ReactNode, type ElementType, useCallback, useRef, useMemo, } from "react"; import { useIsSSR } from "react-aria"; import styles from "./theme-switch.module.scss"; type Props = Omit< ButtonProps, "beforeIcon" | "variant" | "size" | "hideText" | "children" | "onPress" >; export const ThemeSwitch = ({ className, ...props }: Props) => { const { theme, setTheme } = useTheme(); const toggleTheme = useCallback(() => { const nextThemeName = nextTheme(theme); setTheme(nextThemeName); }, [theme, setTheme]); return ( ); }; const IconPath = ({ className, ...props }: Omit) => { const offsets = useOffsets(); const isSSR = useIsSSR(); return isSSR ? (
) : (
} offset={offsets.desktop} /> } offset={offsets.sun} /> } offset={offsets.moon} />
); }; type IconMovementProps = { icon: ReactNode; offset: string; }; const IconMovement = ({ icon, offset }: IconMovementProps) => ( {icon} ); const useOffsets = () => { const numRotations = useRef(1); const prevTheme = useRef(undefined); const { theme } = useTheme(); if (theme !== prevTheme.current) { prevTheme.current = theme; if (theme === "light") { numRotations.current += 1; } } return useMemo(() => { const calc = (offset: number) => `${(100 * (numRotations.current + offset)).toString()}%`; switch (theme) { case "light": { return { desktop: calc(1 / 3), sun: calc(0), moon: calc(-1 / 3) }; } case "dark": { return { desktop: calc(2 / 3), sun: calc(1 / 3), moon: calc(0) }; } default: { return { desktop: calc(1), sun: calc(2 / 3), moon: calc(1 / 3) }; } } }, [theme]); }; const nextTheme = (theme: string | undefined) => { switch (theme) { case "system": { return "light"; } case "light": { return "dark"; } default: { return "system"; } } };