@refraction-ui/react 0.12.2 → 0.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/theme.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../theme/src/theme-machine.ts","../../theme/src/theme-script.ts","../../theme/src/dom-adapters.ts","../../react-theme/src/theme-provider.tsx","../../react-theme/src/theme-toggle.tsx","../../react-theme/src/theme-script-component.tsx"],"names":["React","React3"],"mappings":"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","file":"theme.js","sourcesContent":["/**\n * Headless theme state machine — pure TypeScript, zero DOM dependencies.\n * Manages light/dark/system mode with system preference tracking.\n */\n\nexport type ThemeMode = 'light' | 'dark' | 'system'\nexport type ResolvedTheme = 'light' | 'dark'\n\nexport interface ThemeState {\n /** User's chosen mode */\n mode: ThemeMode\n /** Resolved theme after system preference detection */\n resolved: ResolvedTheme\n}\n\nexport interface ThemeConfig {\n /** Initial mode. Default: 'system' */\n defaultMode?: ThemeMode\n /** localStorage key. Default: 'rfr-theme' */\n storageKey?: string\n /** HTML attribute to set. Default: 'class' */\n attribute?: 'class' | 'data-theme'\n}\n\nexport interface StorageAdapter {\n get(key: string): string | null\n set(key: string, value: string): void\n}\n\nexport interface MediaQueryAdapter {\n matches(query: string): boolean\n subscribe(query: string, callback: (matches: boolean) => void): () => void\n}\n\nexport interface ThemeAPI {\n /** Get current state */\n getState(): ThemeState\n /** Set mode (light/dark/system) */\n setMode(mode: ThemeMode): void\n /** Subscribe to state changes */\n subscribe(fn: (state: ThemeState) => void): () => void\n /** Clean up subscriptions */\n destroy(): void\n}\n\nfunction resolveTheme(mode: ThemeMode, systemPrefersDark: boolean): ResolvedTheme {\n if (mode === 'system') {\n return systemPrefersDark ? 'dark' : 'light'\n }\n return mode\n}\n\nexport function createTheme(\n config: ThemeConfig = {},\n storage?: StorageAdapter,\n mediaQuery?: MediaQueryAdapter,\n): ThemeAPI {\n const {\n defaultMode = 'system',\n storageKey = 'rfr-theme',\n } = config\n\n const listeners = new Set<(state: ThemeState) => void>()\n let cleanupMediaQuery: (() => void) | null = null\n\n // Read persisted mode or use default\n const persisted = storage?.get(storageKey) as ThemeMode | null\n let mode: ThemeMode = persisted && ['light', 'dark', 'system'].includes(persisted)\n ? persisted\n : defaultMode\n\n // Detect system preference\n let systemPrefersDark = mediaQuery?.matches('(prefers-color-scheme: dark)') ?? false\n\n let state: ThemeState = {\n mode,\n resolved: resolveTheme(mode, systemPrefersDark),\n }\n\n function notify() {\n for (const fn of listeners) {\n fn(state)\n }\n }\n\n function updateState(newMode: ThemeMode) {\n mode = newMode\n state = { mode, resolved: resolveTheme(mode, systemPrefersDark) }\n storage?.set(storageKey, mode)\n notify()\n }\n\n // Listen for system preference changes\n if (mediaQuery) {\n cleanupMediaQuery = mediaQuery.subscribe(\n '(prefers-color-scheme: dark)',\n (matches) => {\n systemPrefersDark = matches\n if (mode === 'system') {\n state = { mode, resolved: resolveTheme(mode, systemPrefersDark) }\n notify()\n }\n },\n )\n }\n\n return {\n getState() {\n return state\n },\n\n setMode(newMode: ThemeMode) {\n if (newMode !== mode) {\n updateState(newMode)\n }\n },\n\n subscribe(fn: (state: ThemeState) => void) {\n listeners.add(fn)\n return () => {\n listeners.delete(fn)\n }\n },\n\n destroy() {\n listeners.clear()\n cleanupMediaQuery?.()\n },\n }\n}\n","/**\n * Inline script for preventing theme flash on page load.\n * Inject this as a <script> tag in the <head> before any CSS.\n * Works with any framework (React, Astro, plain HTML).\n */\n\nexport function getThemeScript(\n storageKey = 'rfr-theme',\n attribute: 'class' | 'data-theme' = 'class',\n): string {\n // This string is injected as innerHTML of a <script> tag.\n // It runs before any CSS/JS loads, preventing flash of wrong theme.\n return `(function(){try{var m=localStorage.getItem('${storageKey}');var s=window.matchMedia('(prefers-color-scheme:dark)').matches;var t=m==='dark'||(m!=='light'&&s)?'dark':'light';var d=document.documentElement;${\n attribute === 'class'\n ? \"d.classList.remove('light','dark');d.classList.add(t);\"\n : `d.setAttribute('${attribute}',t);`\n }d.style.colorScheme=t;}catch(e){}})()`\n}\n","/**\n * Browser DOM adapters for the theme machine.\n * These bridge the headless core to browser APIs.\n */\n\nimport type { StorageAdapter, MediaQueryAdapter, ResolvedTheme } from './theme-machine.js'\n\n/** localStorage adapter */\nexport function createLocalStorageAdapter(): StorageAdapter {\n return {\n get(key) {\n try {\n return localStorage.getItem(key)\n } catch {\n return null\n }\n },\n set(key, value) {\n try {\n localStorage.setItem(key, value)\n } catch {\n // localStorage unavailable (SSR, incognito quota exceeded, etc.)\n }\n },\n }\n}\n\n/** matchMedia adapter */\nexport function createMediaQueryAdapter(): MediaQueryAdapter {\n return {\n matches(query) {\n if (typeof window === 'undefined') return false\n return window.matchMedia(query).matches\n },\n subscribe(query, callback) {\n if (typeof window === 'undefined') return () => {}\n const mql = window.matchMedia(query)\n const handler = (e: MediaQueryListEvent) => callback(e.matches)\n mql.addEventListener('change', handler)\n return () => mql.removeEventListener('change', handler)\n },\n }\n}\n\n/** Apply resolved theme to the document */\nexport function applyThemeToDOM(\n resolved: ResolvedTheme,\n attribute: 'class' | 'data-theme' = 'class',\n): void {\n if (typeof document === 'undefined') return\n\n const root = document.documentElement\n if (attribute === 'class') {\n root.classList.remove('light', 'dark')\n root.classList.add(resolved)\n } else {\n root.setAttribute(attribute, resolved)\n }\n root.style.colorScheme = resolved\n}\n","import * as React from 'react'\nimport {\n createTheme,\n createLocalStorageAdapter,\n createMediaQueryAdapter,\n applyThemeToDOM,\n type ThemeMode,\n type ResolvedTheme,\n type ThemeConfig,\n type ThemeAPI,\n} from '@refraction-ui/theme'\nimport { devWarn } from '@refraction-ui/shared'\n\nexport interface ThemeContextValue {\n mode: ThemeMode\n resolved: ResolvedTheme\n setMode: (mode: ThemeMode) => void\n}\n\nconst ThemeContext = React.createContext<ThemeContextValue | null>(null)\n\nexport interface ThemeProviderProps extends ThemeConfig {\n children: React.ReactNode\n}\n\nexport function ThemeProvider({\n children,\n defaultMode = 'system',\n storageKey = 'rfr-theme',\n attribute = 'class',\n}: ThemeProviderProps) {\n const themeRef = React.useRef<ThemeAPI | null>(null)\n\n // Initialize theme machine once (client-side only for adapters)\n if (!themeRef.current) {\n const isBrowser = typeof window !== 'undefined'\n themeRef.current = createTheme(\n { defaultMode, storageKey, attribute },\n isBrowser ? createLocalStorageAdapter() : undefined,\n isBrowser ? createMediaQueryAdapter() : undefined,\n )\n }\n\n const [state, setState] = React.useState(() => themeRef.current!.getState())\n\n React.useEffect(() => {\n const theme = themeRef.current!\n // Apply initial theme to DOM\n applyThemeToDOM(theme.getState().resolved, attribute)\n\n // Subscribe to changes\n const unsub = theme.subscribe((newState) => {\n setState(newState)\n applyThemeToDOM(newState.resolved, attribute)\n })\n\n return () => {\n unsub()\n theme.destroy()\n }\n }, [attribute])\n\n const contextValue = React.useMemo<ThemeContextValue>(\n () => ({\n mode: state.mode,\n resolved: state.resolved,\n setMode: (mode: ThemeMode) => themeRef.current?.setMode(mode),\n }),\n [state.mode, state.resolved],\n )\n\n return React.createElement(ThemeContext.Provider, { value: contextValue }, children)\n}\n\nexport function useTheme(): ThemeContextValue {\n const context = React.useContext(ThemeContext)\n if (!context) {\n devWarn(\n 'react-theme/use-theme-outside-provider',\n 'useTheme() was called outside a <ThemeProvider>. Wrap your app (or the consuming subtree) in <ThemeProvider> so the theme context is available.',\n )\n throw new Error('useTheme must be used within a <ThemeProvider>')\n }\n return context\n}\n","import * as React from 'react'\nimport { useTheme } from './theme-provider.js'\nimport type { ThemeMode } from '@refraction-ui/theme'\n\nconst modes: { value: ThemeMode; label: string; icon: string }[] = [\n { value: 'light', label: 'Light', icon: 'sun' },\n { value: 'dark', label: 'Dark', icon: 'moon' },\n { value: 'system', label: 'System', icon: 'monitor' },\n]\n\n// Inline SVG icons — no external icon library dependency\nconst icons: Record<string, React.ReactNode> = {\n sun: React.createElement('svg', {\n xmlns: 'http://www.w3.org/2000/svg', width: 16, height: 16, viewBox: '0 0 24 24',\n fill: 'none', stroke: 'currentColor', strokeWidth: 2, strokeLinecap: 'round', strokeLinejoin: 'round',\n },\n React.createElement('circle', { cx: 12, cy: 12, r: 5 }),\n React.createElement('path', { d: 'M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42' }),\n ),\n moon: React.createElement('svg', {\n xmlns: 'http://www.w3.org/2000/svg', width: 16, height: 16, viewBox: '0 0 24 24',\n fill: 'none', stroke: 'currentColor', strokeWidth: 2, strokeLinecap: 'round', strokeLinejoin: 'round',\n },\n React.createElement('path', { d: 'M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z' }),\n ),\n monitor: React.createElement('svg', {\n xmlns: 'http://www.w3.org/2000/svg', width: 16, height: 16, viewBox: '0 0 24 24',\n fill: 'none', stroke: 'currentColor', strokeWidth: 2, strokeLinecap: 'round', strokeLinejoin: 'round',\n },\n React.createElement('rect', { x: 2, y: 3, width: 20, height: 14, rx: 2, ry: 2 }),\n React.createElement('line', { x1: 8, y1: 21, x2: 16, y2: 21 }),\n React.createElement('line', { x1: 12, y1: 17, x2: 12, y2: 21 }),\n ),\n}\n\nexport interface ThemeToggleProps {\n className?: string\n /** 'dropdown' shows a menu, 'segmented' shows inline buttons */\n variant?: 'dropdown' | 'segmented'\n}\n\nexport function ThemeToggle({ className, variant = 'segmented' }: ThemeToggleProps) {\n const { mode, setMode } = useTheme()\n\n if (variant === 'segmented') {\n return React.createElement('div', {\n className: `inline-flex items-center gap-1 rounded-lg border p-1 ${className ?? ''}`,\n role: 'radiogroup',\n 'aria-label': 'Theme',\n },\n modes.map(({ value, label, icon }) =>\n React.createElement('button', {\n key: value,\n type: 'button',\n role: 'radio',\n 'aria-checked': mode === value,\n 'aria-label': label,\n className: `inline-flex items-center justify-center rounded-md p-1.5 text-sm transition-colors ${\n mode === value\n ? 'bg-accent text-accent-foreground'\n : 'text-muted-foreground hover:bg-muted'\n }`,\n onClick: () => setMode(value),\n }, icons[icon]),\n ),\n )\n }\n\n // Dropdown variant — simplified, no external dropdown dependency\n const [open, setOpen] = React.useState(false)\n const ref = React.useRef<HTMLDivElement>(null)\n\n React.useEffect(() => {\n if (!open) return\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false)\n }\n document.addEventListener('mousedown', handler)\n return () => document.removeEventListener('mousedown', handler)\n }, [open])\n\n const currentIcon = modes.find((m) => m.value === mode)?.icon ?? 'monitor'\n\n return React.createElement('div', { ref, className: `relative ${className ?? ''}` },\n React.createElement('button', {\n type: 'button',\n 'aria-label': 'Toggle theme',\n 'aria-expanded': open,\n className: 'inline-flex items-center justify-center rounded-md p-2 text-sm transition-colors hover:bg-muted',\n onClick: () => setOpen(!open),\n }, icons[currentIcon]),\n open && React.createElement('div', {\n className: 'absolute right-0 top-full mt-1 z-50 min-w-[8rem] rounded-md border bg-popover p-1 shadow-md',\n role: 'menu',\n },\n modes.map(({ value, label, icon }) =>\n React.createElement('button', {\n key: value,\n type: 'button',\n role: 'menuitem',\n className: `flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors hover:bg-accent ${\n mode === value ? 'bg-accent' : ''\n }`,\n onClick: () => { setMode(value); setOpen(false) },\n }, icons[icon], label),\n ),\n ),\n )\n}\n","import * as React from 'react'\nimport { getThemeScript } from '@refraction-ui/theme'\n\nexport interface ThemeScriptProps {\n storageKey?: string\n attribute?: 'class' | 'data-theme'\n}\n\n/**\n * Renders an inline <script> that prevents theme flash on SSR pages.\n * Place this in the <head> of your document (in Next.js layout.tsx, Remix root, etc.)\n */\nexport function ThemeScript({\n storageKey = 'rfr-theme',\n attribute = 'class',\n}: ThemeScriptProps) {\n return React.createElement('script', {\n dangerouslySetInnerHTML: {\n __html: getThemeScript(storageKey, attribute),\n },\n })\n}\n"]}
1
+ {"version":3,"sources":["../../theme/src/theme-machine.ts","../../theme/src/theme-script.ts","../../theme/src/dom-adapters.ts","../../react-theme/src/theme-provider.tsx","../../react-theme/src/theme-toggle.tsx","../../react-theme/src/theme-script-component.tsx"],"names":["React","React3"],"mappings":"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","file":"theme.js","sourcesContent":["/**\n * Headless theme state machine — pure TypeScript, zero DOM dependencies.\n * Manages light/dark/system mode with system preference tracking.\n */\n\nexport type ThemeMode = 'light' | 'dark' | 'system'\nexport type ResolvedTheme = 'light' | 'dark'\n\nexport interface ThemeState {\n /** User's chosen mode */\n mode: ThemeMode\n /** Resolved theme after system preference detection */\n resolved: ResolvedTheme\n}\n\nexport interface ThemeConfig {\n /** Initial mode. Default: 'system' */\n defaultMode?: ThemeMode\n /** localStorage key. Default: 'rfr-theme' */\n storageKey?: string\n /** HTML attribute to set. Default: 'class' */\n attribute?: 'class' | 'data-theme'\n}\n\nexport interface StorageAdapter {\n get(key: string): string | null\n set(key: string, value: string): void\n}\n\nexport interface MediaQueryAdapter {\n matches(query: string): boolean\n subscribe(query: string, callback: (matches: boolean) => void): () => void\n}\n\nexport interface ThemeAPI {\n /** Get current state */\n getState(): ThemeState\n /** Set mode (light/dark/system) */\n setMode(mode: ThemeMode): void\n /** Subscribe to state changes */\n subscribe(fn: (state: ThemeState) => void): () => void\n /** Clean up subscriptions */\n destroy(): void\n}\n\nfunction resolveTheme(mode: ThemeMode, systemPrefersDark: boolean): ResolvedTheme {\n if (mode === 'system') {\n return systemPrefersDark ? 'dark' : 'light'\n }\n return mode\n}\n\nexport function createTheme(\n config: ThemeConfig = {},\n storage?: StorageAdapter,\n mediaQuery?: MediaQueryAdapter,\n): ThemeAPI {\n const {\n defaultMode = 'system',\n storageKey = 'rfr-theme',\n } = config\n\n const listeners = new Set<(state: ThemeState) => void>()\n let cleanupMediaQuery: (() => void) | null = null\n\n // Read persisted mode or use default\n const persisted = storage?.get(storageKey) as ThemeMode | null\n let mode: ThemeMode = persisted && ['light', 'dark', 'system'].includes(persisted)\n ? persisted\n : defaultMode\n\n // Detect system preference\n let systemPrefersDark = mediaQuery?.matches('(prefers-color-scheme: dark)') ?? false\n\n let state: ThemeState = {\n mode,\n resolved: resolveTheme(mode, systemPrefersDark),\n }\n\n function notify() {\n for (const fn of listeners) {\n fn(state)\n }\n }\n\n function updateState(newMode: ThemeMode) {\n mode = newMode\n state = { mode, resolved: resolveTheme(mode, systemPrefersDark) }\n storage?.set(storageKey, mode)\n notify()\n }\n\n // Listen for system preference changes\n if (mediaQuery) {\n cleanupMediaQuery = mediaQuery.subscribe(\n '(prefers-color-scheme: dark)',\n (matches) => {\n systemPrefersDark = matches\n if (mode === 'system') {\n state = { mode, resolved: resolveTheme(mode, systemPrefersDark) }\n notify()\n }\n },\n )\n }\n\n return {\n getState() {\n return state\n },\n\n setMode(newMode: ThemeMode) {\n if (newMode !== mode) {\n updateState(newMode)\n }\n },\n\n subscribe(fn: (state: ThemeState) => void) {\n listeners.add(fn)\n return () => {\n listeners.delete(fn)\n }\n },\n\n destroy() {\n listeners.clear()\n cleanupMediaQuery?.()\n },\n }\n}\n","/**\n * Inline script for preventing theme flash on page load.\n * Inject this as a <script> tag in the <head> before any CSS.\n * Works with any framework (React, Astro, plain HTML).\n */\n\nimport type { ThemeMode } from './theme-machine.js'\n\nexport interface ThemeScriptOptions {\n /** localStorage key the corresponding ThemeProvider reads. */\n storageKey?: string\n /** Attribute strategy: 'class' toggles `light`/`dark` classes; otherwise an HTML attribute. */\n attribute?: 'class' | 'data-theme'\n /**\n * Theme to apply when nothing is stored AND `enableSystem` is false\n * (or `defaultMode` is explicitly 'light'/'dark'). Match this to your\n * ThemeProvider's `defaultMode` so the pre-paint script and provider agree.\n * Defaults to `'system'` — current behavior, OS preference wins.\n *\n * Issue #317.\n */\n defaultMode?: ThemeMode\n /**\n * When `true` (default) and `defaultMode === 'system'`, the script falls\n * through to `prefers-color-scheme`. When `false`, the script applies\n * `defaultMode` directly and never reads the OS preference.\n */\n enableSystem?: boolean\n}\n\n/**\n * Build the pre-paint inline script. Mirrors the resolution order used by\n * the React/Astro `ThemeProvider`:\n *\n * 1. stored value (light|dark|system)\n * 2. if no stored value: `defaultMode` (light|dark applied as-is)\n * 3. if stored or default is 'system' AND `enableSystem`: matchMedia\n * 4. else: 'light'\n *\n * Back-compat: with no options the script behaves exactly as before —\n * stored value, then matchMedia, then 'light'.\n */\nexport function getThemeScript(\n storageKeyOrOptions: string | ThemeScriptOptions = 'rfr-theme',\n attribute: 'class' | 'data-theme' = 'class',\n): string {\n const opts: Required<ThemeScriptOptions> =\n typeof storageKeyOrOptions === 'string'\n ? {\n storageKey: storageKeyOrOptions,\n attribute,\n defaultMode: 'system',\n enableSystem: true,\n }\n : {\n storageKey: storageKeyOrOptions.storageKey ?? 'rfr-theme',\n attribute: storageKeyOrOptions.attribute ?? 'class',\n defaultMode: storageKeyOrOptions.defaultMode ?? 'system',\n enableSystem: storageKeyOrOptions.enableSystem ?? true,\n }\n\n // `noSystemFallback` short-circuits matchMedia entirely when the consumer\n // wants brand consistency over OS preference (defaultMode='light'/'dark'\n // OR enableSystem=false).\n const noSystemFallback =\n opts.defaultMode === 'light' || opts.defaultMode === 'dark' || !opts.enableSystem\n const safeDefault: 'light' | 'dark' =\n opts.defaultMode === 'dark' ? 'dark' : 'light'\n\n const resolveExpr = noSystemFallback\n ? // Stored wins → else hard default. No matchMedia call at all.\n `var t=m==='dark'?'dark':(m==='light'?'light':'${safeDefault}');`\n : // Original behaviour: stored → else matchMedia → else light.\n `var s=window.matchMedia('(prefers-color-scheme:dark)').matches;var t=m==='dark'||(m!=='light'&&s)?'dark':'light';`\n\n const applyExpr =\n opts.attribute === 'class'\n ? \"d.classList.remove('light','dark');d.classList.add(t);\"\n : `d.setAttribute('${opts.attribute}',t);`\n\n return `(function(){try{var m=localStorage.getItem('${opts.storageKey}');${resolveExpr}var d=document.documentElement;${applyExpr}d.style.colorScheme=t;}catch(e){}})()`\n}\n","/**\n * Browser DOM adapters for the theme machine.\n * These bridge the headless core to browser APIs.\n */\n\nimport type { StorageAdapter, MediaQueryAdapter, ResolvedTheme } from './theme-machine.js'\n\n/** localStorage adapter */\nexport function createLocalStorageAdapter(): StorageAdapter {\n return {\n get(key) {\n try {\n return localStorage.getItem(key)\n } catch {\n return null\n }\n },\n set(key, value) {\n try {\n localStorage.setItem(key, value)\n } catch {\n // localStorage unavailable (SSR, incognito quota exceeded, etc.)\n }\n },\n }\n}\n\n/** matchMedia adapter */\nexport function createMediaQueryAdapter(): MediaQueryAdapter {\n return {\n matches(query) {\n if (typeof window === 'undefined') return false\n return window.matchMedia(query).matches\n },\n subscribe(query, callback) {\n if (typeof window === 'undefined') return () => {}\n const mql = window.matchMedia(query)\n const handler = (e: MediaQueryListEvent) => callback(e.matches)\n mql.addEventListener('change', handler)\n return () => mql.removeEventListener('change', handler)\n },\n }\n}\n\n/** Apply resolved theme to the document */\nexport function applyThemeToDOM(\n resolved: ResolvedTheme,\n attribute: 'class' | 'data-theme' = 'class',\n): void {\n if (typeof document === 'undefined') return\n\n const root = document.documentElement\n if (attribute === 'class') {\n root.classList.remove('light', 'dark')\n root.classList.add(resolved)\n } else {\n root.setAttribute(attribute, resolved)\n }\n root.style.colorScheme = resolved\n}\n","import * as React from 'react'\nimport {\n createTheme,\n createLocalStorageAdapter,\n createMediaQueryAdapter,\n applyThemeToDOM,\n type ThemeMode,\n type ResolvedTheme,\n type ThemeConfig,\n type ThemeAPI,\n} from '@refraction-ui/theme'\nimport { devWarn } from '@refraction-ui/shared'\n\nexport interface ThemeContextValue {\n mode: ThemeMode\n resolved: ResolvedTheme\n setMode: (mode: ThemeMode) => void\n}\n\nconst ThemeContext = React.createContext<ThemeContextValue | null>(null)\n\nexport interface ThemeProviderProps extends ThemeConfig {\n children: React.ReactNode\n}\n\nexport function ThemeProvider({\n children,\n defaultMode = 'system',\n storageKey = 'rfr-theme',\n attribute = 'class',\n}: ThemeProviderProps) {\n const themeRef = React.useRef<ThemeAPI | null>(null)\n\n // Initialize theme machine once (client-side only for adapters)\n if (!themeRef.current) {\n const isBrowser = typeof window !== 'undefined'\n themeRef.current = createTheme(\n { defaultMode, storageKey, attribute },\n isBrowser ? createLocalStorageAdapter() : undefined,\n isBrowser ? createMediaQueryAdapter() : undefined,\n )\n }\n\n const [state, setState] = React.useState(() => themeRef.current!.getState())\n\n React.useEffect(() => {\n const theme = themeRef.current!\n // Apply initial theme to DOM\n applyThemeToDOM(theme.getState().resolved, attribute)\n\n // Subscribe to changes\n const unsub = theme.subscribe((newState) => {\n setState(newState)\n applyThemeToDOM(newState.resolved, attribute)\n })\n\n return () => {\n unsub()\n theme.destroy()\n }\n }, [attribute])\n\n const contextValue = React.useMemo<ThemeContextValue>(\n () => ({\n mode: state.mode,\n resolved: state.resolved,\n setMode: (mode: ThemeMode) => themeRef.current?.setMode(mode),\n }),\n [state.mode, state.resolved],\n )\n\n return React.createElement(ThemeContext.Provider, { value: contextValue }, children)\n}\n\nexport function useTheme(): ThemeContextValue {\n const context = React.useContext(ThemeContext)\n if (!context) {\n devWarn(\n 'react-theme/use-theme-outside-provider',\n 'useTheme() was called outside a <ThemeProvider>. Wrap your app (or the consuming subtree) in <ThemeProvider> so the theme context is available.',\n )\n throw new Error('useTheme must be used within a <ThemeProvider>')\n }\n return context\n}\n","import * as React from 'react'\nimport { useTheme } from './theme-provider.js'\nimport type { ThemeMode } from '@refraction-ui/theme'\n\nconst modes: { value: ThemeMode; label: string; icon: string }[] = [\n { value: 'light', label: 'Light', icon: 'sun' },\n { value: 'dark', label: 'Dark', icon: 'moon' },\n { value: 'system', label: 'System', icon: 'monitor' },\n]\n\n// Inline SVG icons — no external icon library dependency\nconst icons: Record<string, React.ReactNode> = {\n sun: React.createElement('svg', {\n xmlns: 'http://www.w3.org/2000/svg', width: 16, height: 16, viewBox: '0 0 24 24',\n fill: 'none', stroke: 'currentColor', strokeWidth: 2, strokeLinecap: 'round', strokeLinejoin: 'round',\n },\n React.createElement('circle', { cx: 12, cy: 12, r: 5 }),\n React.createElement('path', { d: 'M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42' }),\n ),\n moon: React.createElement('svg', {\n xmlns: 'http://www.w3.org/2000/svg', width: 16, height: 16, viewBox: '0 0 24 24',\n fill: 'none', stroke: 'currentColor', strokeWidth: 2, strokeLinecap: 'round', strokeLinejoin: 'round',\n },\n React.createElement('path', { d: 'M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z' }),\n ),\n monitor: React.createElement('svg', {\n xmlns: 'http://www.w3.org/2000/svg', width: 16, height: 16, viewBox: '0 0 24 24',\n fill: 'none', stroke: 'currentColor', strokeWidth: 2, strokeLinecap: 'round', strokeLinejoin: 'round',\n },\n React.createElement('rect', { x: 2, y: 3, width: 20, height: 14, rx: 2, ry: 2 }),\n React.createElement('line', { x1: 8, y1: 21, x2: 16, y2: 21 }),\n React.createElement('line', { x1: 12, y1: 17, x2: 12, y2: 21 }),\n ),\n}\n\nexport interface ThemeToggleProps {\n className?: string\n /** 'dropdown' shows a menu, 'segmented' shows inline buttons */\n variant?: 'dropdown' | 'segmented'\n}\n\nexport function ThemeToggle({ className, variant = 'segmented' }: ThemeToggleProps) {\n const { mode, setMode } = useTheme()\n\n if (variant === 'segmented') {\n return React.createElement('div', {\n className: `inline-flex items-center gap-1 rounded-lg border p-1 ${className ?? ''}`,\n role: 'radiogroup',\n 'aria-label': 'Theme',\n },\n modes.map(({ value, label, icon }) =>\n React.createElement('button', {\n key: value,\n type: 'button',\n role: 'radio',\n 'aria-checked': mode === value,\n 'aria-label': label,\n className: `inline-flex items-center justify-center rounded-md p-1.5 text-sm transition-colors ${\n mode === value\n ? 'bg-accent text-accent-foreground'\n : 'text-muted-foreground hover:bg-muted'\n }`,\n onClick: () => setMode(value),\n }, icons[icon]),\n ),\n )\n }\n\n // Dropdown variant — simplified, no external dropdown dependency\n const [open, setOpen] = React.useState(false)\n const ref = React.useRef<HTMLDivElement>(null)\n\n React.useEffect(() => {\n if (!open) return\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false)\n }\n document.addEventListener('mousedown', handler)\n return () => document.removeEventListener('mousedown', handler)\n }, [open])\n\n const currentIcon = modes.find((m) => m.value === mode)?.icon ?? 'monitor'\n\n return React.createElement('div', { ref, className: `relative ${className ?? ''}` },\n React.createElement('button', {\n type: 'button',\n 'aria-label': 'Toggle theme',\n 'aria-expanded': open,\n className: 'inline-flex items-center justify-center rounded-md p-2 text-sm transition-colors hover:bg-muted',\n onClick: () => setOpen(!open),\n }, icons[currentIcon]),\n open && React.createElement('div', {\n className: 'absolute right-0 top-full mt-1 z-50 min-w-[8rem] rounded-md border bg-popover p-1 shadow-md',\n role: 'menu',\n },\n modes.map(({ value, label, icon }) =>\n React.createElement('button', {\n key: value,\n type: 'button',\n role: 'menuitem',\n className: `flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors hover:bg-accent ${\n mode === value ? 'bg-accent' : ''\n }`,\n onClick: () => { setMode(value); setOpen(false) },\n }, icons[icon], label),\n ),\n ),\n )\n}\n","import * as React from 'react'\nimport { getThemeScript, type ThemeMode } from '@refraction-ui/theme'\n\nexport interface ThemeScriptProps {\n /** localStorage key the ThemeProvider reads. */\n storageKey?: string\n /** Attribute strategy. `class` toggles `light`/`dark` on <html>; otherwise an HTML attribute. */\n attribute?: 'class' | 'data-theme'\n /**\n * Theme to apply when nothing is stored. Match this to `<ThemeProvider defaultMode>`\n * so the pre-paint script and provider agree on the no-storage path. Defaults\n * to `'system'` (current behaviour — OS preference wins). Issue #317.\n */\n defaultMode?: ThemeMode\n /**\n * When `false` the inline script never reads `prefers-color-scheme`; the\n * `defaultMode` is applied as-is for first-time visitors. Default `true`.\n */\n enableSystem?: boolean\n}\n\n/**\n * Renders an inline <script> that prevents theme flash on SSR pages.\n * Place this in the <head> of your document (in Next.js layout.tsx, Remix root, etc.)\n *\n * Mirror the props your <ThemeProvider> uses so first-paint and React mount stay in sync:\n *\n * <ThemeScript defaultMode=\"light\" storageKey=\"app_theme\" />\n * <ThemeProvider defaultMode=\"light\" storageKey=\"app_theme\">…</ThemeProvider>\n */\nexport function ThemeScript({\n storageKey = 'rfr-theme',\n attribute = 'class',\n defaultMode = 'system',\n enableSystem = true,\n}: ThemeScriptProps) {\n return React.createElement('script', {\n dangerouslySetInnerHTML: {\n __html: getThemeScript({ storageKey, attribute, defaultMode, enableSystem }),\n },\n })\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@refraction-ui/react",
3
- "version": "0.12.2",
3
+ "version": "0.12.3",
4
4
  "description": "All Refraction UI React components in one package — headless, accessible, zero-dependency",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",