refactor: migrate frontend from shadcn/Tailwind to Mantine v9
Reescribe todos los componentes UI para usar Mantine v9 en lugar de shadcn/Tailwind. Elimina cn(), CVA, components.json, theme_provider custom y globals.css con Tailwind. Añade 25+ componentes nuevos (AppShell, AuthForm, DatePickerInput, Dropzone, etc.) y MantineProvider como wrapper estándar del sistema de temas. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
export const chartColors = [
|
||||
'hsl(var(--chart-1, 220 70% 50%))',
|
||||
'hsl(var(--chart-2, 160 60% 45%))',
|
||||
'hsl(var(--chart-3, 30 80% 55%))',
|
||||
'hsl(var(--chart-4, 280 65% 60%))',
|
||||
'hsl(var(--chart-5, 340 75% 55%))',
|
||||
'#3b82f6',
|
||||
'#10b981',
|
||||
'#f59e0b',
|
||||
'#8b5cf6',
|
||||
'#ef4444',
|
||||
]
|
||||
|
||||
export function getChartColor(index: number): string {
|
||||
return chartColors[index % chartColors.length]
|
||||
return chartColors[index % chartColors.length]!
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
---
|
||||
name: cn
|
||||
kind: function
|
||||
lang: ts
|
||||
domain: core
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "cn(...inputs: ClassValue[]): string"
|
||||
description: "Combina clases CSS con clsx y resuelve conflictos Tailwind con tailwind-merge. Utilidad fundamental para composición de estilos."
|
||||
tags: [css, tailwind, classname, merge, utility]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: ""
|
||||
imports: [clsx, tailwind-merge]
|
||||
params:
|
||||
- name: inputs
|
||||
desc: "Clases CSS en cualquier formato: strings, arrays, objetos con condiciones booleanas"
|
||||
output: "String con clases CSS combinadas y mergeadas, sin duplicados y conflictos Tailwind resueltos"
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "frontend/functions/core/cn.ts"
|
||||
source_repo: "https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com/Bl4cksmith/Frontend_Library"
|
||||
source_license: "MIT"
|
||||
source_file: "frontend/src/lib/utils.ts"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```typescript
|
||||
cn("px-4 py-2", "px-6") // "px-6 py-2" (tailwind-merge resuelve conflicto)
|
||||
cn("text-red-500", false && "hidden") // "text-red-500" (clsx filtra falsy)
|
||||
cn("rounded-lg", className) // composición con className externo
|
||||
```
|
||||
|
||||
## Notas
|
||||
|
||||
Base de todo el sistema de estilos. Todos los componentes la usan para componer className.
|
||||
@@ -1,6 +0,0 @@
|
||||
import { clsx, type ClassValue } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]): string {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
---
|
||||
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: []
|
||||
params:
|
||||
- name: colors
|
||||
desc: "Objeto con pares clave-valor de nombre variable CSS a valor de color"
|
||||
- name: selector
|
||||
desc: "Selector CSS donde inyectar variables (':root' por defecto)"
|
||||
output: "String con bloque CSS completo conteniendo definiciones de variables de tema"
|
||||
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))`.
|
||||
@@ -1,23 +0,0 @@
|
||||
/**
|
||||
* 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}`
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
const defaultColors = ['#3b82f6', '#22c55e', '#f59e0b', '#8b5cf6', '#ec4899']
|
||||
|
||||
export function getSeriesColor(index: number, color?: string): string {
|
||||
return color || defaultColors[index % defaultColors.length]
|
||||
return color ?? defaultColors[index % defaultColors.length]!
|
||||
}
|
||||
|
||||
export { defaultColors }
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
---
|
||||
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: []
|
||||
output: "Objeto ThemeTokens con todas las variables CSS de tema resueltas (colores, tipografía, espaciado)"
|
||||
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`.
|
||||
@@ -1,59 +0,0 @@
|
||||
/** 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'),
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
---
|
||||
name: theme_config_to_colors
|
||||
kind: function
|
||||
lang: ts
|
||||
domain: core
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "themeConfigToColors(config: ThemeConfig): ThemeColors"
|
||||
description: "Convierte un ThemeConfig completo a ThemeColors plano para inyectar como CSS variables. Mapea tokens semánticos a variables CSS."
|
||||
tags: [theme, colors, css-variables, conversion]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: ""
|
||||
imports: []
|
||||
params:
|
||||
- name: config
|
||||
desc: "Configuración de tema con propiedades semánticas de color"
|
||||
output: "Objeto ThemeColors con variables CSS estandarizadas mapeadas de la config"
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "frontend/functions/core/theme_config_to_colors.ts"
|
||||
source_repo: "https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com/Bl4cksmith/Frontend_Library"
|
||||
source_license: "MIT"
|
||||
source_file: "frontend/src/themes/types.ts"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```typescript
|
||||
const colors = themeConfigToColors(darkThemeConfig)
|
||||
// { background: '...', foreground: '...', primary: '...', ... }
|
||||
```
|
||||
|
||||
## Notas
|
||||
|
||||
Puente entre el sistema de temas estructurado (ThemeConfig) y el sistema plano de CSS variables que consumen los componentes.
|
||||
|
||||
Depende de los tipos ThemeConfig y ThemeColors definidos en `frontend/types/ui/theme_config.ts`. El tipo aún no está indexado en la BD (pendiente añadir theme_config.md para que fn index lo registre).
|
||||
@@ -1,49 +0,0 @@
|
||||
import type { ThemeConfig, ThemeColors } from "../../types/ui/theme_config"
|
||||
|
||||
export function themeConfigToColors(config: ThemeConfig): ThemeColors {
|
||||
const { colors } = config
|
||||
|
||||
return {
|
||||
background: colors.background.default,
|
||||
foreground: colors.foreground.default,
|
||||
card: colors.surface.raised,
|
||||
cardForeground: colors.foreground.default,
|
||||
popover: colors.surface.overlay,
|
||||
popoverForeground: colors.foreground.default,
|
||||
primary: colors.brand.primary,
|
||||
primaryForeground: colors.brand.primaryForeground,
|
||||
secondary: colors.brand.secondary,
|
||||
secondaryForeground: colors.brand.secondaryForeground,
|
||||
muted: colors.background.muted,
|
||||
mutedForeground: colors.foreground.muted,
|
||||
accent: colors.brand.accent,
|
||||
accentForeground: colors.brand.accentForeground,
|
||||
destructive: colors.status.error,
|
||||
destructiveForeground: colors.status.errorForeground,
|
||||
success: colors.status.success,
|
||||
successForeground: colors.status.successForeground,
|
||||
warning: colors.status.warning,
|
||||
warningForeground: colors.status.warningForeground,
|
||||
info: colors.status.info,
|
||||
infoForeground: colors.status.infoForeground,
|
||||
surface: colors.surface.raised,
|
||||
surfaceHover: colors.background.subtle,
|
||||
overlay: colors.surface.overlay,
|
||||
border: colors.border.default,
|
||||
input: colors.border.default,
|
||||
ring: colors.ring,
|
||||
chart1: colors.chart[1],
|
||||
chart2: colors.chart[2],
|
||||
chart3: colors.chart[3],
|
||||
chart4: colors.chart[4],
|
||||
chart5: colors.chart[5],
|
||||
sidebar: colors.sidebar.background,
|
||||
sidebarForeground: colors.sidebar.foreground,
|
||||
sidebarPrimary: colors.brand.primary,
|
||||
sidebarPrimaryForeground: colors.brand.primaryForeground,
|
||||
sidebarAccent: colors.sidebar.accent,
|
||||
sidebarAccentForeground: colors.sidebar.accentForeground,
|
||||
sidebarBorder: colors.sidebar.border,
|
||||
sidebarRing: colors.sidebar.ring,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user