@valcis/brand 2.0.5 → 2.1.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 valcis
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,6 +1,11 @@
1
1
  # @valcis/brand
2
2
 
3
- Componentes React de marca **valcis**: Logo SVG y Footer con soporte SSR.
3
+ [![npm version](https://img.shields.io/npm/v/@valcis/brand.svg)](https://www.npmjs.com/package/@valcis/brand)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@valcis/brand.svg)](https://www.npmjs.com/package/@valcis/brand)
5
+ [![bundle size](https://img.shields.io/bundlephobia/minzip/@valcis/brand)](https://bundlephobia.com/package/@valcis/brand)
6
+ [![license](https://img.shields.io/npm/l/@valcis/brand.svg)](https://github.com/valcis/branding_valcis/blob/main/LICENSE)
7
+
8
+ Componentes React de marca **valcis**: Logo SVG, Footer, Spinner, Watermark y tema con soporte SSR.
4
9
 
5
10
  ## Instalación
6
11
 
@@ -48,6 +53,56 @@ import { Logo } from '@valcis/brand';
48
53
  | `lg` | 32 |
49
54
  | `xl` | 48 |
50
55
 
56
+ ## Spinner
57
+
58
+ Indicador de carga con el logo animado.
59
+
60
+ ```tsx
61
+ import { Spinner } from '@valcis/brand';
62
+
63
+ // Básico
64
+ <Spinner />
65
+
66
+ // Con opciones
67
+ <Spinner size="lg" animation="spin" label="Cargando datos..." />
68
+ ```
69
+
70
+ ### Props
71
+
72
+ | Prop | Tipo | Default | Descripción |
73
+ |------|------|---------|-------------|
74
+ | `size` | `number \| 'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | Tamaño |
75
+ | `animation` | `'pulse' \| 'spin' \| 'bounce'` | `'pulse'` | Tipo de animación |
76
+ | `accentColor` | `string` | — | Color de acento |
77
+ | `textColor` | `string` | — | Color de texto |
78
+ | `label` | `string` | `'Cargando...'` | Texto para screen readers |
79
+ | `className` | `string` | — | Clase CSS adicional |
80
+
81
+ ## Watermark
82
+
83
+ Marca de agua posicionable para imágenes o secciones.
84
+
85
+ ```tsx
86
+ import { Watermark } from '@valcis/brand';
87
+
88
+ // El contenedor padre debe tener position: relative
89
+ <div style={{ position: 'relative' }}>
90
+ <img src="foto.jpg" alt="Foto" />
91
+ <Watermark position="bottom-right" opacity={0.3} />
92
+ </div>
93
+ ```
94
+
95
+ ### Props
96
+
97
+ | Prop | Tipo | Default | Descripción |
98
+ |------|------|---------|-------------|
99
+ | `position` | `'top-left' \| 'top-right' \| 'bottom-left' \| 'bottom-right' \| 'center'` | `'bottom-right'` | Posición |
100
+ | `opacity` | `number` | `0.3` | Opacidad (0-1) |
101
+ | `size` | `number` | `48` | Tamaño del logo |
102
+ | `rotation` | `number` | `0` | Rotación en grados |
103
+ | `showOnHover` | `boolean` | `false` | Solo visible en hover |
104
+ | `className` | `string` | — | Clase CSS adicional |
105
+
51
106
  ## Footer
52
107
 
53
108
  Footer de atribución con logo, contacto y modos de copyright.
@@ -79,7 +134,7 @@ import { Footer } from '@valcis/brand';
79
134
  | `position` | `'static' \| 'sticky' \| 'fixed'` | `'sticky'` | Posicionamiento CSS |
80
135
  | `padding` | `'compact' \| 'normal' \| 'spacious' \| { x?, y? }` | `'normal'` | Densidad |
81
136
  | `border` | `boolean \| 'top' \| 'bottom' \| 'both' \| 'none'` | `'top'` | Borde separador |
82
- | `accentColor` | `string` | — | Color de acento (texto, links). No afecta al logo |
137
+ | `accentColor` | `string` | — | Color de acento (texto, links) |
83
138
  | `backgroundColor` | `string` | `'transparent'` | Fondo |
84
139
  | `textColor` | `string` | — | Color de texto override |
85
140
  | `as` | `'footer' \| 'div' \| 'section'` | `'div'` | Tag HTML |
@@ -91,12 +146,108 @@ import { Footer } from '@valcis/brand';
91
146
 
92
147
  | Modo | Resultado |
93
148
  |------|-----------|
94
- | `owner` | © 2025 >valcis\| |
95
- | `designer` | © 2025 · Diseñado por >valcis\| |
149
+ | `owner` | © 2026 >valcis\| |
150
+ | `designer` | © 2026 · Diseñado por >valcis\| |
96
151
  | `partner` | Powered by >valcis\| |
97
152
 
153
+ ## useTheme
154
+
155
+ Hook para detectar y controlar dark/light mode.
156
+
157
+ ```tsx
158
+ import { useTheme } from '@valcis/brand';
159
+
160
+ function App() {
161
+ const { theme, isDark, toggleTheme, setTheme } = useTheme();
162
+
163
+ return (
164
+ <div className={isDark ? 'dark' : 'light'}>
165
+ <button onClick={toggleTheme}>
166
+ {isDark ? '☀️' : '🌙'}
167
+ </button>
168
+
169
+ {/* Volver a preferencia del sistema */}
170
+ <button onClick={() => setTheme(null)}>Auto</button>
171
+ </div>
172
+ );
173
+ }
174
+ ```
175
+
176
+ ### Retorno
177
+
178
+ | Propiedad | Tipo | Descripción |
179
+ |-----------|------|-------------|
180
+ | `theme` | `'light' \| 'dark'` | Tema actual |
181
+ | `isDark` | `boolean` | `true` si es dark mode |
182
+ | `isLight` | `boolean` | `true` si es light mode |
183
+ | `setTheme` | `(theme: 'light' \| 'dark' \| null) => void` | Forzar tema (`null` = auto) |
184
+ | `toggleTheme` | `() => void` | Alternar entre light/dark |
185
+
186
+ ## Paleta de colores
187
+
188
+ Colores de marca exportados como constantes.
189
+
190
+ ```tsx
191
+ import { colors, primary, text, cssVariables } from '@valcis/brand';
192
+
193
+ // Usar en estilos
194
+ const style = { color: primary.DEFAULT }; // '#3B82F6'
195
+
196
+ // Paleta completa
197
+ console.log(colors.primary[500]); // '#3B82F6'
198
+ console.log(colors.text.DEFAULT); // '#1E293B'
199
+ console.log(colors.semantic.success); // '#22C55E'
200
+
201
+ // Inyectar CSS custom properties
202
+ const GlobalStyles = () => <style>{cssVariables}</style>;
203
+ ```
204
+
205
+ ### Colores disponibles
206
+
207
+ ```ts
208
+ colors.primary // Azules de marca (50-900, DEFAULT, light, dark)
209
+ colors.text // Colores de texto (DEFAULT, dark, muted, mutedDark)
210
+ colors.background // Fondos (light, dark, muted, mutedDark)
211
+ colors.border // Bordes (light, dark)
212
+ colors.semantic // Semánticos (success, warning, error, info)
213
+ ```
214
+
215
+ ### CSS Custom Properties
216
+
217
+ ```css
218
+ /* Disponibles tras inyectar cssVariables */
219
+ --valcis-primary
220
+ --valcis-primary-light
221
+ --valcis-primary-dark
222
+ --valcis-text
223
+ --valcis-text-muted
224
+ --valcis-bg
225
+ --valcis-bg-muted
226
+ --valcis-border
227
+ --valcis-logo-accent
228
+ --valcis-logo-text
229
+ ```
230
+
231
+ ## Datos del desarrollador
232
+
233
+ El Footer y el hook `useDevInfo` obtienen los datos de marca desde `https://valcis.es/api/dev-info.json`. Si el servidor no está disponible o el fetch falla (timeout de 2s, error de red, JSON inválido), se usa automáticamente un fallback local:
234
+
235
+ ```ts
236
+ {
237
+ version: 1,
238
+ brand: 'valcis',
239
+ contact: 'contacto@valcis.es',
240
+ website: 'https://valcis.es',
241
+ year: new Date().getFullYear(),
242
+ }
243
+ ```
244
+
245
+ En cliente, las respuestas se cachean en `localStorage` durante 1 hora para minimizar peticiones.
246
+
98
247
  ## SSR
99
248
 
249
+ Para evitar el fetch en cliente, puedes pre-cargar los datos en el servidor con `getDevInfo()`:
250
+
100
251
  ```tsx
101
252
  import { getDevInfo, Footer } from '@valcis/brand';
102
253
 
@@ -111,6 +262,8 @@ export default function Page({ devInfo }) {
111
262
  }
112
263
  ```
113
264
 
265
+ Si se pasa `initialDevInfo`, el componente no hace fetch.
266
+
114
267
  ## Assets estáticos
115
268
 
116
269
  El paquete incluye SVGs en `assets/` para uso fuera de React:
@@ -135,6 +288,29 @@ Para uso sin React, se exportan los paths SVG crudos:
135
288
  import { V_CALLIGRAPHIC_PATH, BRACKET_LEFT_PATH, VIEWBOXES } from '@valcis/brand';
136
289
  ```
137
290
 
291
+ ## Accesibilidad
292
+
293
+ El componente cumple con WCAG 2.2:
294
+
295
+ - **Contraste**: Colores con ratio AA (4.5:1)
296
+ - **Focus visible**: `:focus-visible` con outline
297
+ - **Target size**: Links con área mínima 44x44px
298
+ - **Semántica**: Uso de `<nav>`, `<footer>`, `aria-label`
299
+ - **Logo decorativo**: `aria-hidden="true"` (excepto si se proporciona `ariaLabel`)
300
+ - **Reduced motion**: Animaciones respetan `prefers-reduced-motion`
301
+
302
+ ## Desarrollo
303
+
304
+ ```bash
305
+ npm run build # Build de producción
306
+ npm run dev # Build en modo watch
307
+ npm run lint # Ejecutar ESLint
308
+ npm run lint:fix # Arreglar errores de lint
309
+ npm run format # Formatear con Prettier
310
+ npm test # Ejecutar tests (81 tests)
311
+ npm run test:watch # Tests en modo watch
312
+ ```
313
+
138
314
  ## Licencia
139
315
 
140
316
  MIT
package/dist/index.d.mts CHANGED
@@ -175,4 +175,217 @@ declare const FETCH_TIMEOUT = 2000;
175
175
  declare const CACHE_DURATION: number;
176
176
  declare const CACHE_KEY = "valcis-brand-dev-info";
177
177
 
178
- export { ASPECT_RATIOS, A_PATH, BRACKET_LEFT_PATH, BRACKET_RIGHT_PATH, CACHE_DURATION, CACHE_KEY, CHEVRON_RIGHT_FULL_PATH, CURSOR_PATH, C_PATH, type CopyrightMode, DEFAULT_DEV_INFO, DEV_INFO_URL, type DevInfo, FETCH_TIMEOUT, FULL_GLYPH_OFFSETS, Footer, type FooterProps, I_PATH, L_PATH, Logo, type LogoProps, type LogoSize, type LogoVariant, S_PATH, VIEWBOXES, V_CALLIGRAPHIC_FULL_TRANSFORM, V_CALLIGRAPHIC_PATH, getDevInfo, useDevInfo };
178
+ interface WatermarkProps {
179
+ /** Posición del watermark */
180
+ position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center';
181
+ /** Opacidad (0-1) */
182
+ opacity?: number;
183
+ /** Tamaño del logo */
184
+ size?: number;
185
+ /** Rotación en grados */
186
+ rotation?: number;
187
+ /** Mostrar solo en hover del contenedor padre */
188
+ showOnHover?: boolean;
189
+ /** Clase CSS adicional */
190
+ className?: string;
191
+ }
192
+ /**
193
+ * Watermark - Marca de agua con logo valcis
194
+ *
195
+ * Útil para imágenes, documentos o secciones que requieren atribución.
196
+ * Se posiciona de forma absoluta, el contenedor padre debe tener position: relative.
197
+ */
198
+ declare const Watermark: React.FC<WatermarkProps>;
199
+
200
+ interface SpinnerProps {
201
+ /** Tamaño del spinner */
202
+ size?: number | 'sm' | 'md' | 'lg' | 'xl';
203
+ /** Tipo de animación */
204
+ animation?: 'pulse' | 'spin' | 'bounce';
205
+ /** Color de acento */
206
+ accentColor?: string;
207
+ /** Color del texto/letra */
208
+ textColor?: string;
209
+ /** Texto de carga (accesibilidad) */
210
+ label?: string;
211
+ /** Clase CSS adicional */
212
+ className?: string;
213
+ }
214
+ /**
215
+ * Spinner - Indicador de carga con logo valcis animado
216
+ *
217
+ * Usa el logo icon con diferentes animaciones.
218
+ * Respeta prefers-reduced-motion.
219
+ */
220
+ declare const Spinner: React.FC<SpinnerProps>;
221
+
222
+ type Theme = 'light' | 'dark';
223
+ interface UseThemeResult {
224
+ /** Tema actual */
225
+ theme: Theme;
226
+ /** true si es dark mode */
227
+ isDark: boolean;
228
+ /** true si es light mode */
229
+ isLight: boolean;
230
+ /** Forzar tema manualmente (null = auto) */
231
+ setTheme: (theme: Theme | null) => void;
232
+ /** Alternar entre light y dark */
233
+ toggleTheme: () => void;
234
+ }
235
+ /**
236
+ * Hook para detectar y controlar el tema (dark/light mode)
237
+ *
238
+ * Por defecto detecta la preferencia del sistema (prefers-color-scheme).
239
+ * Permite override manual que persiste en localStorage.
240
+ *
241
+ * @example
242
+ * ```tsx
243
+ * const { theme, isDark, toggleTheme } = useTheme();
244
+ *
245
+ * return (
246
+ * <div className={isDark ? 'dark' : 'light'}>
247
+ * <button onClick={toggleTheme}>
248
+ * {isDark ? '☀️' : '🌙'}
249
+ * </button>
250
+ * </div>
251
+ * );
252
+ * ```
253
+ */
254
+ declare function useTheme(): UseThemeResult;
255
+
256
+ /**
257
+ * Paleta de colores de marca valcis
258
+ *
259
+ * Uso:
260
+ * ```ts
261
+ * import { colors } from '@valcis/brand';
262
+ * console.log(colors.primary.DEFAULT); // '#3B82F6'
263
+ * ```
264
+ */
265
+ /** Colores primarios de marca */
266
+ declare const primary: {
267
+ /** Azul principal */
268
+ readonly DEFAULT: "#3B82F6";
269
+ /** Azul claro (para dark mode) */
270
+ readonly light: "#60A5FA";
271
+ /** Azul oscuro (hover) */
272
+ readonly dark: "#2563EB";
273
+ /** Azul muy claro (backgrounds) */
274
+ readonly 50: "#EFF6FF";
275
+ readonly 100: "#DBEAFE";
276
+ readonly 200: "#BFDBFE";
277
+ readonly 300: "#93C5FD";
278
+ readonly 400: "#60A5FA";
279
+ readonly 500: "#3B82F6";
280
+ readonly 600: "#2563EB";
281
+ readonly 700: "#1D4ED8";
282
+ readonly 800: "#1E40AF";
283
+ readonly 900: "#1E3A8A";
284
+ };
285
+ /** Colores de texto */
286
+ declare const text: {
287
+ /** Texto principal (light mode) */
288
+ readonly DEFAULT: "#1E293B";
289
+ /** Texto principal (dark mode) */
290
+ readonly dark: "#F1F5F9";
291
+ /** Texto secundario (light mode) */
292
+ readonly muted: "#64748B";
293
+ /** Texto secundario (dark mode) */
294
+ readonly mutedDark: "#94A3B8";
295
+ };
296
+ /** Colores de fondo */
297
+ declare const background: {
298
+ /** Fondo claro */
299
+ readonly light: "#FFFFFF";
300
+ /** Fondo oscuro */
301
+ readonly dark: "#0F172A";
302
+ /** Fondo gris claro */
303
+ readonly muted: "#F8FAFC";
304
+ /** Fondo gris oscuro */
305
+ readonly mutedDark: "#1E293B";
306
+ };
307
+ /** Colores de borde */
308
+ declare const border: {
309
+ /** Borde claro */
310
+ readonly light: "#E2E8F0";
311
+ /** Borde oscuro */
312
+ readonly dark: "#334155";
313
+ };
314
+ /** Colores semánticos */
315
+ declare const semantic: {
316
+ readonly success: "#22C55E";
317
+ readonly warning: "#F59E0B";
318
+ readonly error: "#EF4444";
319
+ readonly info: "#3B82F6";
320
+ };
321
+ /** Paleta completa */
322
+ declare const colors: {
323
+ readonly primary: {
324
+ /** Azul principal */
325
+ readonly DEFAULT: "#3B82F6";
326
+ /** Azul claro (para dark mode) */
327
+ readonly light: "#60A5FA";
328
+ /** Azul oscuro (hover) */
329
+ readonly dark: "#2563EB";
330
+ /** Azul muy claro (backgrounds) */
331
+ readonly 50: "#EFF6FF";
332
+ readonly 100: "#DBEAFE";
333
+ readonly 200: "#BFDBFE";
334
+ readonly 300: "#93C5FD";
335
+ readonly 400: "#60A5FA";
336
+ readonly 500: "#3B82F6";
337
+ readonly 600: "#2563EB";
338
+ readonly 700: "#1D4ED8";
339
+ readonly 800: "#1E40AF";
340
+ readonly 900: "#1E3A8A";
341
+ };
342
+ readonly text: {
343
+ /** Texto principal (light mode) */
344
+ readonly DEFAULT: "#1E293B";
345
+ /** Texto principal (dark mode) */
346
+ readonly dark: "#F1F5F9";
347
+ /** Texto secundario (light mode) */
348
+ readonly muted: "#64748B";
349
+ /** Texto secundario (dark mode) */
350
+ readonly mutedDark: "#94A3B8";
351
+ };
352
+ readonly background: {
353
+ /** Fondo claro */
354
+ readonly light: "#FFFFFF";
355
+ /** Fondo oscuro */
356
+ readonly dark: "#0F172A";
357
+ /** Fondo gris claro */
358
+ readonly muted: "#F8FAFC";
359
+ /** Fondo gris oscuro */
360
+ readonly mutedDark: "#1E293B";
361
+ };
362
+ readonly border: {
363
+ /** Borde claro */
364
+ readonly light: "#E2E8F0";
365
+ /** Borde oscuro */
366
+ readonly dark: "#334155";
367
+ };
368
+ readonly semantic: {
369
+ readonly success: "#22C55E";
370
+ readonly warning: "#F59E0B";
371
+ readonly error: "#EF4444";
372
+ readonly info: "#3B82F6";
373
+ };
374
+ };
375
+ /**
376
+ * CSS Custom Properties para usar en estilos
377
+ *
378
+ * Uso:
379
+ * ```css
380
+ * color: var(--valcis-primary);
381
+ * ```
382
+ */
383
+ declare const cssVariables: string;
384
+ type Colors = typeof colors;
385
+ type Primary = typeof primary;
386
+ type Text = typeof text;
387
+ type Background = typeof background;
388
+ type Border = typeof border;
389
+ type Semantic = typeof semantic;
390
+
391
+ export { ASPECT_RATIOS, A_PATH, BRACKET_LEFT_PATH, BRACKET_RIGHT_PATH, type Background, type Border, CACHE_DURATION, CACHE_KEY, CHEVRON_RIGHT_FULL_PATH, CURSOR_PATH, C_PATH, type Colors, type CopyrightMode, DEFAULT_DEV_INFO, DEV_INFO_URL, type DevInfo, FETCH_TIMEOUT, FULL_GLYPH_OFFSETS, Footer, type FooterProps, I_PATH, L_PATH, Logo, type LogoProps, type LogoSize, type LogoVariant, type Primary, S_PATH, type Semantic, Spinner, type SpinnerProps, type Text, type Theme, type UseThemeResult, VIEWBOXES, V_CALLIGRAPHIC_FULL_TRANSFORM, V_CALLIGRAPHIC_PATH, Watermark, type WatermarkProps, background, border, colors, cssVariables, getDevInfo, primary, semantic, text, useDevInfo, useTheme };
package/dist/index.d.ts CHANGED
@@ -175,4 +175,217 @@ declare const FETCH_TIMEOUT = 2000;
175
175
  declare const CACHE_DURATION: number;
176
176
  declare const CACHE_KEY = "valcis-brand-dev-info";
177
177
 
178
- export { ASPECT_RATIOS, A_PATH, BRACKET_LEFT_PATH, BRACKET_RIGHT_PATH, CACHE_DURATION, CACHE_KEY, CHEVRON_RIGHT_FULL_PATH, CURSOR_PATH, C_PATH, type CopyrightMode, DEFAULT_DEV_INFO, DEV_INFO_URL, type DevInfo, FETCH_TIMEOUT, FULL_GLYPH_OFFSETS, Footer, type FooterProps, I_PATH, L_PATH, Logo, type LogoProps, type LogoSize, type LogoVariant, S_PATH, VIEWBOXES, V_CALLIGRAPHIC_FULL_TRANSFORM, V_CALLIGRAPHIC_PATH, getDevInfo, useDevInfo };
178
+ interface WatermarkProps {
179
+ /** Posición del watermark */
180
+ position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center';
181
+ /** Opacidad (0-1) */
182
+ opacity?: number;
183
+ /** Tamaño del logo */
184
+ size?: number;
185
+ /** Rotación en grados */
186
+ rotation?: number;
187
+ /** Mostrar solo en hover del contenedor padre */
188
+ showOnHover?: boolean;
189
+ /** Clase CSS adicional */
190
+ className?: string;
191
+ }
192
+ /**
193
+ * Watermark - Marca de agua con logo valcis
194
+ *
195
+ * Útil para imágenes, documentos o secciones que requieren atribución.
196
+ * Se posiciona de forma absoluta, el contenedor padre debe tener position: relative.
197
+ */
198
+ declare const Watermark: React.FC<WatermarkProps>;
199
+
200
+ interface SpinnerProps {
201
+ /** Tamaño del spinner */
202
+ size?: number | 'sm' | 'md' | 'lg' | 'xl';
203
+ /** Tipo de animación */
204
+ animation?: 'pulse' | 'spin' | 'bounce';
205
+ /** Color de acento */
206
+ accentColor?: string;
207
+ /** Color del texto/letra */
208
+ textColor?: string;
209
+ /** Texto de carga (accesibilidad) */
210
+ label?: string;
211
+ /** Clase CSS adicional */
212
+ className?: string;
213
+ }
214
+ /**
215
+ * Spinner - Indicador de carga con logo valcis animado
216
+ *
217
+ * Usa el logo icon con diferentes animaciones.
218
+ * Respeta prefers-reduced-motion.
219
+ */
220
+ declare const Spinner: React.FC<SpinnerProps>;
221
+
222
+ type Theme = 'light' | 'dark';
223
+ interface UseThemeResult {
224
+ /** Tema actual */
225
+ theme: Theme;
226
+ /** true si es dark mode */
227
+ isDark: boolean;
228
+ /** true si es light mode */
229
+ isLight: boolean;
230
+ /** Forzar tema manualmente (null = auto) */
231
+ setTheme: (theme: Theme | null) => void;
232
+ /** Alternar entre light y dark */
233
+ toggleTheme: () => void;
234
+ }
235
+ /**
236
+ * Hook para detectar y controlar el tema (dark/light mode)
237
+ *
238
+ * Por defecto detecta la preferencia del sistema (prefers-color-scheme).
239
+ * Permite override manual que persiste en localStorage.
240
+ *
241
+ * @example
242
+ * ```tsx
243
+ * const { theme, isDark, toggleTheme } = useTheme();
244
+ *
245
+ * return (
246
+ * <div className={isDark ? 'dark' : 'light'}>
247
+ * <button onClick={toggleTheme}>
248
+ * {isDark ? '☀️' : '🌙'}
249
+ * </button>
250
+ * </div>
251
+ * );
252
+ * ```
253
+ */
254
+ declare function useTheme(): UseThemeResult;
255
+
256
+ /**
257
+ * Paleta de colores de marca valcis
258
+ *
259
+ * Uso:
260
+ * ```ts
261
+ * import { colors } from '@valcis/brand';
262
+ * console.log(colors.primary.DEFAULT); // '#3B82F6'
263
+ * ```
264
+ */
265
+ /** Colores primarios de marca */
266
+ declare const primary: {
267
+ /** Azul principal */
268
+ readonly DEFAULT: "#3B82F6";
269
+ /** Azul claro (para dark mode) */
270
+ readonly light: "#60A5FA";
271
+ /** Azul oscuro (hover) */
272
+ readonly dark: "#2563EB";
273
+ /** Azul muy claro (backgrounds) */
274
+ readonly 50: "#EFF6FF";
275
+ readonly 100: "#DBEAFE";
276
+ readonly 200: "#BFDBFE";
277
+ readonly 300: "#93C5FD";
278
+ readonly 400: "#60A5FA";
279
+ readonly 500: "#3B82F6";
280
+ readonly 600: "#2563EB";
281
+ readonly 700: "#1D4ED8";
282
+ readonly 800: "#1E40AF";
283
+ readonly 900: "#1E3A8A";
284
+ };
285
+ /** Colores de texto */
286
+ declare const text: {
287
+ /** Texto principal (light mode) */
288
+ readonly DEFAULT: "#1E293B";
289
+ /** Texto principal (dark mode) */
290
+ readonly dark: "#F1F5F9";
291
+ /** Texto secundario (light mode) */
292
+ readonly muted: "#64748B";
293
+ /** Texto secundario (dark mode) */
294
+ readonly mutedDark: "#94A3B8";
295
+ };
296
+ /** Colores de fondo */
297
+ declare const background: {
298
+ /** Fondo claro */
299
+ readonly light: "#FFFFFF";
300
+ /** Fondo oscuro */
301
+ readonly dark: "#0F172A";
302
+ /** Fondo gris claro */
303
+ readonly muted: "#F8FAFC";
304
+ /** Fondo gris oscuro */
305
+ readonly mutedDark: "#1E293B";
306
+ };
307
+ /** Colores de borde */
308
+ declare const border: {
309
+ /** Borde claro */
310
+ readonly light: "#E2E8F0";
311
+ /** Borde oscuro */
312
+ readonly dark: "#334155";
313
+ };
314
+ /** Colores semánticos */
315
+ declare const semantic: {
316
+ readonly success: "#22C55E";
317
+ readonly warning: "#F59E0B";
318
+ readonly error: "#EF4444";
319
+ readonly info: "#3B82F6";
320
+ };
321
+ /** Paleta completa */
322
+ declare const colors: {
323
+ readonly primary: {
324
+ /** Azul principal */
325
+ readonly DEFAULT: "#3B82F6";
326
+ /** Azul claro (para dark mode) */
327
+ readonly light: "#60A5FA";
328
+ /** Azul oscuro (hover) */
329
+ readonly dark: "#2563EB";
330
+ /** Azul muy claro (backgrounds) */
331
+ readonly 50: "#EFF6FF";
332
+ readonly 100: "#DBEAFE";
333
+ readonly 200: "#BFDBFE";
334
+ readonly 300: "#93C5FD";
335
+ readonly 400: "#60A5FA";
336
+ readonly 500: "#3B82F6";
337
+ readonly 600: "#2563EB";
338
+ readonly 700: "#1D4ED8";
339
+ readonly 800: "#1E40AF";
340
+ readonly 900: "#1E3A8A";
341
+ };
342
+ readonly text: {
343
+ /** Texto principal (light mode) */
344
+ readonly DEFAULT: "#1E293B";
345
+ /** Texto principal (dark mode) */
346
+ readonly dark: "#F1F5F9";
347
+ /** Texto secundario (light mode) */
348
+ readonly muted: "#64748B";
349
+ /** Texto secundario (dark mode) */
350
+ readonly mutedDark: "#94A3B8";
351
+ };
352
+ readonly background: {
353
+ /** Fondo claro */
354
+ readonly light: "#FFFFFF";
355
+ /** Fondo oscuro */
356
+ readonly dark: "#0F172A";
357
+ /** Fondo gris claro */
358
+ readonly muted: "#F8FAFC";
359
+ /** Fondo gris oscuro */
360
+ readonly mutedDark: "#1E293B";
361
+ };
362
+ readonly border: {
363
+ /** Borde claro */
364
+ readonly light: "#E2E8F0";
365
+ /** Borde oscuro */
366
+ readonly dark: "#334155";
367
+ };
368
+ readonly semantic: {
369
+ readonly success: "#22C55E";
370
+ readonly warning: "#F59E0B";
371
+ readonly error: "#EF4444";
372
+ readonly info: "#3B82F6";
373
+ };
374
+ };
375
+ /**
376
+ * CSS Custom Properties para usar en estilos
377
+ *
378
+ * Uso:
379
+ * ```css
380
+ * color: var(--valcis-primary);
381
+ * ```
382
+ */
383
+ declare const cssVariables: string;
384
+ type Colors = typeof colors;
385
+ type Primary = typeof primary;
386
+ type Text = typeof text;
387
+ type Background = typeof background;
388
+ type Border = typeof border;
389
+ type Semantic = typeof semantic;
390
+
391
+ export { ASPECT_RATIOS, A_PATH, BRACKET_LEFT_PATH, BRACKET_RIGHT_PATH, type Background, type Border, CACHE_DURATION, CACHE_KEY, CHEVRON_RIGHT_FULL_PATH, CURSOR_PATH, C_PATH, type Colors, type CopyrightMode, DEFAULT_DEV_INFO, DEV_INFO_URL, type DevInfo, FETCH_TIMEOUT, FULL_GLYPH_OFFSETS, Footer, type FooterProps, I_PATH, L_PATH, Logo, type LogoProps, type LogoSize, type LogoVariant, type Primary, S_PATH, type Semantic, Spinner, type SpinnerProps, type Text, type Theme, type UseThemeResult, VIEWBOXES, V_CALLIGRAPHIC_FULL_TRANSFORM, V_CALLIGRAPHIC_PATH, Watermark, type WatermarkProps, background, border, colors, cssVariables, getDevInfo, primary, semantic, text, useDevInfo, useTheme };