"use client"; import { useSyncExternalStore } from "react"; import { THEME_ATTRIBUTE } from "./use-token-registry"; import styles from "./dev-test.module.scss"; type ThemeChoice = "system" | "light" | "dark"; const CHOICES: { value: ThemeChoice; label: string }[] = [ { value: "system", label: "시스템" }, { value: "light", label: "라이트" }, { value: "dark", label: "다크" }, ]; /** * `` 자체가 SSOT이므로 React state를 두지 않고 DOM을 구독한다 — * 서버/클라이언트 출력이 갈리지 않아 hydration 불일치 표면적이 0이다. * * 개발용 미리보기 컨트롤이라 **선택을 저장하지 않는다.** 저장 키는 호스트 앱이 소유하는 * 값이라(앱마다 다르다) `@fox`가 알 필요가 없고, 알면 포터빌리티가 깨진다. */ function subscribe(onChange: () => void): () => void { const observer = new MutationObserver(onChange); observer.observe(document.documentElement, { attributes: true, attributeFilter: [THEME_ATTRIBUTE], }); return () => observer.disconnect(); } function getSnapshot(): ThemeChoice { const value = document.documentElement.getAttribute(THEME_ATTRIBUTE); return value === "light" || value === "dark" ? value : "system"; } function getServerSnapshot(): ThemeChoice { return "system"; } function apply(next: ThemeChoice): void { const root = document.documentElement; if (next === "system") { root.removeAttribute(THEME_ATTRIBUTE); } else { root.setAttribute(THEME_ATTRIBUTE, next); } } export function ThemeSwitch() { const current = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot); return (