Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | 462x 462x 2574x 2574x 2574x 2552x 440x 2112x 1254x 1254x 1254x 858x 462x 2574x 22x 22x 22x 2112x 22x 22x | import { useMemo } from 'react'
import themeConfig from '../theme.json'
type ThemeValue = string | number | Record<string, unknown> | unknown[]
/** Convert a nested theme config object into a flat map of CSS custom properties */
function flattenTheme(
obj: Record<string, ThemeValue>,
prefix = '--'
): Record<string, string> {
const result: Record<string, string> = {}
for (const [key, value] of Object.entries(obj)) {
const cssKey = `${prefix}${camelToKebab(key)}`
Iif (value === null || value === undefined) continue
if (Array.isArray(value)) continue // skip arrays (e.g. nestedBulletSymbols)
if (typeof value === 'object') {
Object.assign(result, flattenTheme(value as Record<string, ThemeValue>, `${cssKey}-`))
} else if (typeof value === 'number') {
// Numbers that look like px values get 'px' suffix; ratios/weights don't
// These are unitless values; everything else gets 'px'
const isUnitless = /weight|lineHeight|opacity/i.test(key) ||
cssKey.includes('line-height') ||
cssKey.includes('font-weight')
const needsPx = !isUnitless
result[cssKey] = needsPx ? `${value}px` : String(value)
} else {
result[cssKey] = String(value)
}
}
return result
}
function camelToKebab(str: string): string {
return str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()
}
export function useEditorTheme() {
const { cssVars, styleString } = useMemo(() => {
const vars = flattenTheme(themeConfig as Record<string, ThemeValue>)
const str = Object.entries(vars)
.map(([k, v]) => `${k}: ${v};`)
.join('\n')
return { cssVars: vars, styleString: str }
}, [])
return { themeConfig, cssVars, styleString }
}
|