feat: funciones core frontend — generate_theme_css, get_computed_color, get_theme_tokens
Utilidades TypeScript puras para generación de CSS desde tema, resolución de colores computados y extracción de tokens del sistema de temas. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
---
|
||||
name: generate_theme_css
|
||||
kind: function
|
||||
lang: ts
|
||||
domain: core
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "generateThemeCss(colors: Record<string, string>, selector?: string): string"
|
||||
description: "Genera un bloque CSS con variables de tema a partir de un objeto de tokens. Convierte claves camelCase a kebab-case automaticamente. Pura — solo transforma datos, no accede al DOM."
|
||||
tags: [theme, css, generator, pure]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: ""
|
||||
imports: []
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "frontend/functions/core/generate_theme_css.ts"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```typescript
|
||||
import { generateThemeCss } from './generate_theme_css'
|
||||
import { themeConfigToColors } from './theme_config_to_colors'
|
||||
import { darkTheme } from '../ui/themes'
|
||||
|
||||
// Generar CSS para inyectar en <style>
|
||||
const colors = themeConfigToColors(darkTheme)
|
||||
const css = generateThemeCss(colors)
|
||||
// Output:
|
||||
// :root {
|
||||
// --background: oklch(8% 0.015 260);
|
||||
// --foreground: oklch(95% 0.01 260);
|
||||
// --card: oklch(12% 0.015 260);
|
||||
// --card-foreground: oklch(95% 0.01 260);
|
||||
// ...
|
||||
// }
|
||||
|
||||
// Inyectar en el documento
|
||||
const style = document.createElement('style')
|
||||
style.textContent = css
|
||||
document.head.appendChild(style)
|
||||
|
||||
// Generar para selector especifico (dark mode)
|
||||
const darkCss = generateThemeCss(colors, '.dark')
|
||||
// Output: .dark { --background: oklch(...); ... }
|
||||
|
||||
// Generar para multiples selectores
|
||||
const lightCss = generateThemeCss(lightColors, ':root')
|
||||
const darkCss2 = generateThemeCss(darkColors, ':root.dark')
|
||||
const combined = [lightCss, darkCss2].join('\n\n')
|
||||
```
|
||||
|
||||
## Notas
|
||||
|
||||
Funcion pura — sin acceso al DOM, sin side effects. Util para SSR, generacion de archivos CSS estaticos, o pre-generar temas en build time.
|
||||
|
||||
La conversion camelCase → kebab-case es simple (reemplaza mayusculas con `-` + minuscula). No maneja casos especiales como `backgroundColor` → `background-color`; los tokens del registry ya usan nombres semanticos directos (`background`, `cardForeground`, etc.).
|
||||
|
||||
Compone naturalmente con `themeConfigToColors` del registry: `generateThemeCss(themeConfigToColors(config))`.
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Genera un bloque CSS con variables de tema para inyectar como <style> o
|
||||
* escribir en un archivo .css.
|
||||
*
|
||||
* Convierte claves camelCase a kebab-case automaticamente:
|
||||
* `cardForeground` → `--card-foreground`
|
||||
*
|
||||
* @param colors - Objeto con tokens de tema. Claves en camelCase, valores CSS.
|
||||
* @param selector - Selector CSS donde aplicar las variables. Por defecto `:root`.
|
||||
* @returns String CSS con el bloque completo.
|
||||
*/
|
||||
export function generateThemeCss(
|
||||
colors: Record<string, string>,
|
||||
selector: string = ':root',
|
||||
): string {
|
||||
const lines = Object.entries(colors)
|
||||
.map(([key, value]) => {
|
||||
const cssName = key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`)
|
||||
return ` --${cssName}: ${value};`
|
||||
})
|
||||
.join('\n')
|
||||
return `${selector} {\n${lines}\n}`
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
---
|
||||
name: get_computed_color
|
||||
kind: function
|
||||
lang: ts
|
||||
domain: core
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "getComputedColor(cssVar: string): string"
|
||||
description: "Resuelve una CSS variable de color a su valor RGB computado por el browser. Acepta '--primary', 'primary' o 'var(--primary)'. Util para canvas, sigma.js y APIs que no soportan CSS variables."
|
||||
tags: [theme, css, color, runtime, dom, canvas]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: []
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "frontend/functions/core/get_computed_color.ts"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```typescript
|
||||
import { getComputedColor } from './get_computed_color'
|
||||
|
||||
// Todos estos formatos son equivalentes:
|
||||
const color1 = getComputedColor('--primary') // "rgb(120, 80, 220)"
|
||||
const color2 = getComputedColor('primary') // "rgb(120, 80, 220)"
|
||||
const color3 = getComputedColor('var(--primary)') // "rgb(120, 80, 220)"
|
||||
|
||||
// Usar en canvas 2D
|
||||
const ctx = canvas.getContext('2d')
|
||||
ctx.fillStyle = getComputedColor('--background')
|
||||
ctx.strokeStyle = getComputedColor('--border')
|
||||
|
||||
// Usar en sigma.js v2
|
||||
renderer.setSetting('defaultNodeColor', getComputedColor('--primary'))
|
||||
renderer.setSetting('defaultEdgeColor', getComputedColor('--muted'))
|
||||
```
|
||||
|
||||
## Notas
|
||||
|
||||
Impura — muta el DOM temporalmente (append + remove) para forzar la resolucion del color. Solo disponible en browser.
|
||||
|
||||
El browser retorna el valor en formato `rgb(r, g, b)` o `rgba(r, g, b, a)`, no en el formato original de la CSS variable (oklch, hsl, etc.). Si necesitas el valor original sin resolver, usar `getThemeTokens` en su lugar.
|
||||
|
||||
Para multiples colores en un mismo render, llamar una vez y cachear los resultados — cada llamada hace un ciclo DOM.
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Resuelve una CSS variable de color a su valor RGB computado por el browser.
|
||||
*
|
||||
* Acepta cualquiera de los formatos:
|
||||
* - `"--primary"`
|
||||
* - `"primary"` (sin prefijo --)
|
||||
* - `"var(--primary)"`
|
||||
*
|
||||
* Retorna el valor en formato `rgb(r, g, b)` o `rgba(r, g, b, a)` segun
|
||||
* como lo expanda el browser. Util para canvas, sigma.js y cualquier API
|
||||
* que no soporte CSS variables directamente.
|
||||
*/
|
||||
export function getComputedColor(cssVar: string): string {
|
||||
const name = cssVar.startsWith('var(')
|
||||
? cssVar.slice(4, -1).trim()
|
||||
: cssVar.startsWith('--')
|
||||
? cssVar
|
||||
: `--${cssVar}`
|
||||
|
||||
const el = document.createElement('div')
|
||||
el.style.color = `var(${name})`
|
||||
el.style.display = 'none'
|
||||
document.body.appendChild(el)
|
||||
const computed = getComputedStyle(el).color
|
||||
document.body.removeChild(el)
|
||||
return computed
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
---
|
||||
name: get_theme_tokens
|
||||
kind: function
|
||||
lang: ts
|
||||
domain: core
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "getThemeTokens(): ThemeTokens"
|
||||
description: "Lee todas las CSS variables de tema del documento y devuelve un objeto tipado con los valores computados desde :root. Util para pasar colores a APIs que no entienden CSS variables (canvas, sigma.js, D3)."
|
||||
tags: [theme, css, tokens, runtime, dom]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: []
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "frontend/functions/core/get_theme_tokens.ts"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```typescript
|
||||
import { getThemeTokens } from './get_theme_tokens'
|
||||
|
||||
const tokens = getThemeTokens()
|
||||
|
||||
// Pasar colores a sigma.js (que no soporta CSS variables)
|
||||
const sigmaSettings = {
|
||||
defaultNodeColor: tokens.primary,
|
||||
defaultEdgeColor: tokens.muted,
|
||||
labelColor: { color: tokens.foreground },
|
||||
}
|
||||
|
||||
// Pasar colores a un canvas 2D
|
||||
const ctx = canvas.getContext('2d')
|
||||
ctx.fillStyle = tokens.background
|
||||
ctx.strokeStyle = tokens.border
|
||||
```
|
||||
|
||||
## Notas
|
||||
|
||||
Impura — accede a `document.documentElement` y `getComputedStyle`. Solo disponible en browser.
|
||||
|
||||
Los valores retornados son los valores sin procesar de las CSS variables (ej: `oklch(8% 0.015 260)`). Para obtener valores RGB computed (necesarios para algunas APIs), usar `getComputedColor`.
|
||||
|
||||
Funciona con cualquier tema activo: el resultado cambia automaticamente cuando se cambia el tema via `applyTheme`.
|
||||
@@ -0,0 +1,59 @@
|
||||
/** Tokens de tema leidos de las CSS variables activas en :root. */
|
||||
export interface ThemeTokens {
|
||||
background: string
|
||||
foreground: string
|
||||
card: string
|
||||
cardForeground: string
|
||||
popover: string
|
||||
popoverForeground: string
|
||||
primary: string
|
||||
primaryForeground: string
|
||||
secondary: string
|
||||
secondaryForeground: string
|
||||
muted: string
|
||||
mutedForeground: string
|
||||
accent: string
|
||||
accentForeground: string
|
||||
destructive: string
|
||||
destructiveForeground: string
|
||||
success: string
|
||||
successForeground: string
|
||||
border: string
|
||||
input: string
|
||||
ring: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Lee todas las CSS variables de tema del documento y devuelve un objeto
|
||||
* tipado con los valores computados desde :root.
|
||||
*
|
||||
* Util para pasar colores a APIs que no entienden CSS variables
|
||||
* (canvas, sigma.js, D3, etc.).
|
||||
*/
|
||||
export function getThemeTokens(): ThemeTokens {
|
||||
const style = getComputedStyle(document.documentElement)
|
||||
const get = (name: string) => style.getPropertyValue(`--${name}`).trim()
|
||||
return {
|
||||
background: get('background'),
|
||||
foreground: get('foreground'),
|
||||
card: get('card'),
|
||||
cardForeground: get('card-foreground'),
|
||||
popover: get('popover'),
|
||||
popoverForeground: get('popover-foreground'),
|
||||
primary: get('primary'),
|
||||
primaryForeground: get('primary-foreground'),
|
||||
secondary: get('secondary'),
|
||||
secondaryForeground: get('secondary-foreground'),
|
||||
muted: get('muted'),
|
||||
mutedForeground: get('muted-foreground'),
|
||||
accent: get('accent'),
|
||||
accentForeground: get('accent-foreground'),
|
||||
destructive: get('destructive'),
|
||||
destructiveForeground: get('destructive-foreground'),
|
||||
success: get('success'),
|
||||
successForeground: get('success-foreground'),
|
||||
border: get('border'),
|
||||
input: get('input'),
|
||||
ring: get('ring'),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user