Compare commits

...

2 Commits

Author SHA1 Message Date
e14821c699 fix HMR support 2026-01-16 08:30:44 -08:00
50054b014f extendThemes() 2026-01-16 08:30:41 -08:00
2 changed files with 17 additions and 26 deletions

View File

@ -1,5 +1,6 @@
{ {
"lockfileVersion": 1, "lockfileVersion": 1,
"configVersion": 0,
"workspaces": { "workspaces": {
"": { "": {
"name": "forge", "name": "forge",

View File

@ -4,26 +4,16 @@ import { type TagDef, UnitlessProps, NonStyleKeys } from './types'
export const styles: Record<string, Record<string, string>> = {} export const styles: Record<string, Record<string, string>> = {}
const themes: Record<string, Record<string, any>> = {} const themes: Record<string, Record<string, any>> = {}
// Type registry for theme variables (will be auto-populated)
let registeredThemeKeys: Set<string> = new Set()
// Clear all registered styles
export function clearStyles() { export function clearStyles() {
for (const key in styles) delete styles[key] for (const key in styles) delete styles[key]
for (const key in themes) delete themes[key] for (const key in themes) delete themes[key]
registeredThemeKeys.clear()
} }
// Register a theme with CSS custom properties // HMR support - clear styles when module is replaced
export function createTheme<const T extends Record<string, string | number>>( import.meta.hot?.dispose(() => clearStyles())
name: string,
values: T
): T {
themes[name] = values as Record<string, string>
// track for runtime validation
Object.keys(values).forEach(key => registeredThemeKeys.add(key))
export function createTheme<const T extends Record<string, string | number>>(name: string, values: T): T {
themes[name] = values as Record<string, string | number>
return values return values
} }
@ -52,16 +42,20 @@ export function createThemedVar<T extends Record<string, any>>(_themes: T) {
} }
} }
// Simplified API: register multiple themes and get typed themeVar in one call
type Theme = Record<string, string | number> type Theme = Record<string, string | number>
export function createThemes<T extends Record<string, Theme>>(themes: T) {
const registeredThemes = {} as T
for (const [name, values] of Object.entries(themes)) { export function createThemes<T extends Record<string, Theme>>(themeDefs: T) {
(registeredThemes as any)[name] = createTheme(name, values) for (const [name, values] of Object.entries(themeDefs))
} createTheme(name, values)
return createThemedVar(registeredThemes) return (name: keyof T[keyof T]) => `var(--theme-${name as string})`
}
export function extendThemes(overrides: Record<string, Theme>) {
for (const [name, values] of Object.entries(overrides))
themes[name] = { ...themes[name], ...values }
return (name: string) => `var(--theme-${name})`
} }
// Generic themeVar (untyped fallback) // Generic themeVar (untyped fallback)
@ -288,11 +282,7 @@ export function define(nameOrDef: string | TagDef, defIfNamed?: TagDef) {
const def = defIfNamed ?? nameOrDef as TagDef const def = defIfNamed ?? nameOrDef as TagDef
const name = defIfNamed ? (nameOrDef as string) : anonName(def) const name = defIfNamed ? (nameOrDef as string) : anonName(def)
// Clear any existing styles for this component (supports HMR/hot reload) if (styles[name]) throw `${name} is already defined! Must use unique names.`
for (const key in styles) {
if (key === name || key.startsWith(`${name}_`) || key.startsWith(`${name}.`) || key.startsWith(`${name}:`))
delete styles[key]
}
registerStyles(name, def) registerStyles(name, def)
return (props: Record<string, any>) => { return (props: Record<string, any>) => {