xertica-ui 1.0.0 → 1.2.0

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.
@@ -1,47 +1,11 @@
1
1
  import React, { createContext, useContext, useState, useEffect } from 'react';
2
2
 
3
- interface BrandColors {
4
- // Main Colors
5
- primary: string;
6
- primaryForeground: string;
7
- primaryLight: string; // Used for backgrounds
8
-
9
- // Dark Mode Overrides
10
- primaryDarkMode: string;
11
- primaryForegroundDark: string;
12
-
13
- // Sidebar Colors
14
- sidebarLight: string;
15
- sidebarDark: string;
16
-
17
- // Gradients
18
- gradientStart: string;
19
- gradientEnd: string;
20
- gradientStartDark: string;
21
- gradientEndDark: string;
22
-
23
- // Chart Colors (Light Mode) - Dark mode will be calculated or fixed
24
- chart1: string;
25
- chart2: string;
26
- chart3: string;
27
- chart4: string;
28
- chart5: string;
29
-
30
- // Optional: Radius override per theme
31
- radius?: string;
32
- }
33
-
34
- export interface ColorTheme {
35
- id: string;
36
- name: string;
37
- description: string;
38
- colors: BrandColors;
39
- preview: {
40
- primary: string;
41
- secondary: string;
42
- accent: string;
43
- };
44
- }
3
+ import {
4
+ BrandColors,
5
+ ColorTheme,
6
+ PALETTE,
7
+ colorThemes,
8
+ } from './theme-data';
45
9
 
46
10
  interface BrandColorsContextType {
47
11
  colors: BrandColors;
@@ -52,304 +16,6 @@ interface BrandColorsContextType {
52
16
  setRadius: (radius: number) => void;
53
17
  }
54
18
 
55
- // Shadcn Standard Palette Values (approximate hex for compatibility)
56
- const PALETTE = {
57
- zinc: { 900: '#18181b', 50: '#fafafa' },
58
- slate: { 900: '#0f172a', 50: '#f8fafc' },
59
- stone: { 900: '#1c1917', 50: '#fafaf9' },
60
- gray: { 900: '#111827', 50: '#f9fafb' },
61
- neutral: { 900: '#171717', 50: '#fafafa' },
62
- red: { 600: '#dc2626', 500: '#ef4444' },
63
- rose: { 600: '#e11d48', 500: '#f43f5e' },
64
- orange: { 600: '#ea580c', 500: '#f97316' },
65
- green: { 600: '#16a34a', 500: '#22c55e' },
66
- blue: { 600: '#2563eb', 500: '#3b82f6' },
67
- yellow: { 600: '#ca8a04', 500: '#eab308' },
68
- violet: { 600: '#7c3aed', 500: '#8b5cf6' },
69
- };
70
-
71
- export const colorThemes: ColorTheme[] = [
72
- {
73
- id: 'xertica-original',
74
- name: 'Xertica Original',
75
- description: 'A identidade visual clássica da Xertica com o gradiente original',
76
- colors: {
77
- primary: '#2C275B',
78
- primaryForeground: '#FFFFFF',
79
- primaryLight: '#5B568F',
80
- primaryDarkMode: '#72CDFD',
81
- primaryForegroundDark: '#09090B',
82
-
83
- sidebarLight: '#2C275B', // Primary Color
84
- sidebarDark: '#1a1928', // Original Dark BG
85
-
86
- gradientStart: '#FDB0F2',
87
- gradientEnd: '#72CDFD',
88
- gradientStartDark: '#7B4A7A',
89
- gradientEndDark: '#3A5C7D',
90
-
91
- chart1: '#2C275B',
92
- chart2: '#FDB0F2',
93
- chart3: '#72CDFD',
94
- chart4: '#5B568F',
95
- chart5: '#4F46E5',
96
- },
97
- preview: {
98
- primary: '#2C275B',
99
- secondary: '#FDB0F2',
100
- accent: '#72CDFD',
101
- },
102
- },
103
- {
104
- id: 'zinc',
105
- name: 'Zinc',
106
- description: 'Minimalista, sério e elegante (Escala de Cinza)',
107
- colors: {
108
- primary: '#18181B',
109
- primaryForeground: '#FAFAFA',
110
- primaryLight: '#E4E4E7',
111
- primaryDarkMode: '#FAFAFA',
112
- primaryForegroundDark: '#18181B',
113
-
114
- sidebarLight: '#18181B', // Primary Color
115
- sidebarDark: '#09090B',
116
-
117
- gradientStart: '#52525B',
118
- gradientEnd: '#D4D4D8',
119
- gradientStartDark: '#27272A',
120
- gradientEndDark: '#52525B',
121
-
122
- chart1: '#18181B',
123
- chart2: '#52525B',
124
- chart3: '#A1A1AA',
125
- chart4: '#D4D4D8',
126
- chart5: '#E4E4E7',
127
- },
128
- preview: {
129
- primary: '#18181B',
130
- secondary: '#52525B',
131
- accent: '#E4E4E7',
132
- },
133
- },
134
- {
135
- id: 'slate',
136
- name: 'Slate',
137
- description: 'Profissional com tons de azul acinzentado',
138
- colors: {
139
- primary: '#0F172A',
140
- primaryForeground: '#F8FAFC',
141
- primaryLight: '#CBD5E1',
142
- primaryDarkMode: '#F8FAFC',
143
- primaryForegroundDark: '#0F172A',
144
-
145
- sidebarLight: '#0F172A', // Primary Color
146
- sidebarDark: '#020617',
147
-
148
- gradientStart: '#475569',
149
- gradientEnd: '#94A3B8',
150
- gradientStartDark: '#1E293B',
151
- gradientEndDark: '#475569',
152
-
153
- chart1: '#0F172A',
154
- chart2: '#475569',
155
- chart3: '#94A3B8',
156
- chart4: '#CBD5E1',
157
- chart5: '#E2E8F0',
158
- },
159
- preview: {
160
- primary: '#0F172A',
161
- secondary: '#475569',
162
- accent: '#94A3B8',
163
- },
164
- },
165
- {
166
- id: 'blue',
167
- name: 'Blue',
168
- description: 'Confiável e seguro, padrão corporativo',
169
- colors: {
170
- primary: '#2563EB',
171
- primaryForeground: '#FFFFFF',
172
- primaryLight: '#DBEAFE',
173
- primaryDarkMode: '#3B82F6',
174
- primaryForegroundDark: '#FFFFFF',
175
-
176
- sidebarLight: '#1E3A8A', // Blue 900 (High Contrast Sidebar)
177
- sidebarDark: '#172554',
178
-
179
- gradientStart: '#2563EB',
180
- gradientEnd: '#60A5FA',
181
- gradientStartDark: '#1D4ED8',
182
- gradientEndDark: '#2563EB',
183
-
184
- chart1: '#2563EB',
185
- chart2: '#3B82F6',
186
- chart3: '#60A5FA',
187
- chart4: '#93C5FD',
188
- chart5: '#BFDBFE',
189
- },
190
- preview: {
191
- primary: '#2563EB',
192
- secondary: '#60A5FA',
193
- accent: '#DBEAFE',
194
- },
195
- },
196
- {
197
- id: 'violet',
198
- name: 'Violet',
199
- description: 'Criativo e vibrante',
200
- colors: {
201
- primary: '#7C3AED',
202
- primaryForeground: '#FFFFFF',
203
- primaryLight: '#EDE9FE',
204
- primaryDarkMode: '#8B5CF6',
205
- primaryForegroundDark: '#FFFFFF',
206
-
207
- sidebarLight: '#4C1D95', // Violet 900 (High Contrast Sidebar)
208
- sidebarDark: '#2E1065',
209
-
210
- gradientStart: '#7C3AED',
211
- gradientEnd: '#A78BFA',
212
- gradientStartDark: '#5B21B6',
213
- gradientEndDark: '#7C3AED',
214
-
215
- chart1: '#7C3AED',
216
- chart2: '#8B5CF6',
217
- chart3: '#A78BFA',
218
- chart4: '#C4B5FD',
219
- chart5: '#DDD6FE',
220
- },
221
- preview: {
222
- primary: '#7C3AED',
223
- secondary: '#A78BFA',
224
- accent: '#EDE9FE',
225
- },
226
- },
227
- {
228
- id: 'rose',
229
- name: 'Rose',
230
- description: 'Elegante e suave',
231
- colors: {
232
- primary: '#BE123C', // Rose 700 (Better text contrast for Primary)
233
- primaryForeground: '#FFFFFF',
234
- primaryLight: '#FFE4E6',
235
- primaryDarkMode: '#F43F5E',
236
- primaryForegroundDark: '#FFFFFF',
237
-
238
- sidebarLight: '#881337', // Rose 900 (High Contrast Sidebar)
239
- sidebarDark: '#881337',
240
-
241
- gradientStart: '#E11D48',
242
- gradientEnd: '#FB7185',
243
- gradientStartDark: '#9F1239',
244
- gradientEndDark: '#E11D48',
245
-
246
- chart1: '#E11D48',
247
- chart2: '#F43F5E',
248
- chart3: '#FB7185',
249
- chart4: '#FDA4AF',
250
- chart5: '#FECDD3',
251
- },
252
- preview: {
253
- primary: '#BE123C',
254
- secondary: '#FB7185',
255
- accent: '#FFE4E6',
256
- },
257
- },
258
- {
259
- id: 'emerald',
260
- name: 'Emerald',
261
- description: 'Natural e equilibrado',
262
- colors: {
263
- primary: '#047857', // Emerald 700 (Better text contrast for Primary)
264
- primaryForeground: '#FFFFFF',
265
- primaryLight: '#D1FAE5',
266
- primaryDarkMode: '#10B981',
267
- primaryForegroundDark: '#FFFFFF',
268
-
269
- sidebarLight: '#064E3B', // Emerald 900 (High Contrast Sidebar)
270
- sidebarDark: '#064E3B',
271
-
272
- gradientStart: '#059669',
273
- gradientEnd: '#34D399',
274
- gradientStartDark: '#064E3B',
275
- gradientEndDark: '#059669',
276
-
277
- chart1: '#059669',
278
- chart2: '#10B981',
279
- chart3: '#34D399',
280
- chart4: '#6EE7B7',
281
- chart5: '#A7F3D0',
282
- },
283
- preview: {
284
- primary: '#047857',
285
- secondary: '#34D399',
286
- accent: '#D1FAE5',
287
- },
288
- },
289
- {
290
- id: 'amber',
291
- name: 'Amber',
292
- description: 'Quente e energético',
293
- colors: {
294
- primary: '#B45309', // Amber 700 (Better text contrast for Primary)
295
- primaryForeground: '#FFFFFF',
296
- primaryLight: '#FEF3C7',
297
- primaryDarkMode: '#F59E0B',
298
- primaryForegroundDark: '#FFFFFF',
299
-
300
- sidebarLight: '#78350F', // Amber 900 (High Contrast Sidebar)
301
- sidebarDark: '#78350F',
302
-
303
- gradientStart: '#D97706',
304
- gradientEnd: '#FBBF24',
305
- gradientStartDark: '#92400E',
306
- gradientEndDark: '#D97706',
307
-
308
- chart1: '#D97706',
309
- chart2: '#F59E0B',
310
- chart3: '#FBBF24',
311
- chart4: '#FDE68A',
312
- chart5: '#FEF3C7',
313
- },
314
- preview: {
315
- primary: '#B45309',
316
- secondary: '#FBBF24',
317
- accent: '#FEF3C7',
318
- },
319
- },
320
- {
321
- id: 'orange',
322
- name: 'Orange',
323
- description: 'Vibrante e amigável',
324
- colors: {
325
- primary: '#C2410C', // Orange 700 (Better text contrast for Primary)
326
- primaryForeground: '#FFFFFF',
327
- primaryLight: '#FFEDD5',
328
- primaryDarkMode: '#F97316',
329
- primaryForegroundDark: '#FFFFFF',
330
-
331
- sidebarLight: '#7C2D12', // Orange 900 (High Contrast Sidebar)
332
- sidebarDark: '#7C2D12',
333
-
334
- gradientStart: '#EA580C',
335
- gradientEnd: '#FB923C',
336
- gradientStartDark: '#9A3412',
337
- gradientEndDark: '#EA580C',
338
-
339
- chart1: '#EA580C',
340
- chart2: '#F97316',
341
- chart3: '#FB923C',
342
- chart4: '#FDBA74',
343
- chart5: '#FED7AA',
344
- },
345
- preview: {
346
- primary: '#C2410C',
347
- secondary: '#FB923C',
348
- accent: '#FFEDD5',
349
- },
350
- },
351
- ];
352
-
353
19
  const BrandColorsContext = createContext<BrandColorsContextType | undefined>(undefined);
354
20
 
355
21
  export const BrandColorsProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
@@ -377,10 +43,10 @@ export const BrandColorsProvider: React.FC<{ children: React.ReactNode }> = ({ c
377
43
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
378
44
  return result
379
45
  ? {
380
- r: parseInt(result[1], 16),
381
- g: parseInt(result[2], 16),
382
- b: parseInt(result[3], 16),
383
- }
46
+ r: parseInt(result[1], 16),
47
+ g: parseInt(result[2], 16),
48
+ b: parseInt(result[3], 16),
49
+ }
384
50
  : null;
385
51
  };
386
52
 
@@ -388,11 +54,11 @@ export const BrandColorsProvider: React.FC<{ children: React.ReactNode }> = ({ c
388
54
  const applyColors = React.useCallback(() => {
389
55
  const root = document.documentElement;
390
56
  const isDark = root.classList.contains('dark');
391
-
57
+
392
58
  // --- Determine Colors based on Mode ---
393
59
  const primary = isDark ? colors.primaryDarkMode : colors.primary;
394
60
  const primaryForeground = isDark ? colors.primaryForegroundDark : colors.primaryForeground;
395
-
61
+
396
62
  // Gradient Logic
397
63
  const gradientStart = isDark ? colors.gradientStartDark : colors.gradientStart;
398
64
  const gradientEnd = isDark ? colors.gradientEndDark : colors.gradientEnd;
@@ -402,10 +68,10 @@ export const BrandColorsProvider: React.FC<{ children: React.ReactNode }> = ({ c
402
68
  const semantic = {
403
69
  success: isDark ? '#4ade80' : '#22c55e', // Green 400 / 500
404
70
  warning: isDark ? '#fbbf24' : '#f59e0b', // Amber 400 / 500
405
- info: isDark ? '#60a5fa' : '#3b82f6', // Blue 400 / 500
71
+ info: isDark ? '#60a5fa' : '#3b82f6', // Blue 400 / 500
406
72
  destructive: isDark ? '#f87171' : '#ef4444', // Red 400 / 500
407
73
  };
408
-
74
+
409
75
  // --- Apply CSS Variables ---
410
76
 
411
77
  // 1. Core Primary Colors
@@ -421,29 +87,29 @@ export const BrandColorsProvider: React.FC<{ children: React.ReactNode }> = ({ c
421
87
  root.style.setProperty('--info-foreground', '#ffffff');
422
88
  root.style.setProperty('--destructive', semantic.destructive);
423
89
  root.style.setProperty('--destructive-foreground', '#ffffff');
424
-
90
+
425
91
  // 3. Secondary & Accents (Derived or Specific)
426
-
92
+
427
93
  // 2. Secondary & Accents (Derived or Specific)
428
94
  // We use primaryLight for subtle backgrounds
429
95
  // In dark mode, we might want to adjust opacity
430
96
  const primaryRGB = hexToRgb(primary);
431
97
  if (primaryRGB) {
432
- // Create a subtle tint for secondary/accent/muted
433
- const alpha = isDark ? 0.2 : 0.1;
434
- const subtle = `rgba(${primaryRGB.r}, ${primaryRGB.g}, ${primaryRGB.b}, ${alpha})`;
435
-
436
- // Note: Shadcn usually has specific greys for secondary, but for "Brand" themes
437
- // we can tint them slightly or stick to standard zinc.
438
- // For this implementation, we will keep existing "neutral" variables from CSS
439
- // but override "ring" and "sidebar-ring" to match brand.
440
-
441
- root.style.setProperty('--ring', isDark ? colors.primaryDarkMode : `rgba(${primaryRGB.r}, ${primaryRGB.g}, ${primaryRGB.b}, 0.5)`);
442
-
443
- // Also update the Xertica specific variables
444
- root.style.setProperty('--xertica-primary', primary);
445
- root.style.setProperty('--primary-light', `rgba(${primaryRGB.r}, ${primaryRGB.g}, ${primaryRGB.b}, 0.15)`);
446
- root.style.setProperty('--primary-light-foreground', primary);
98
+ // Create a subtle tint for secondary/accent/muted
99
+ const alpha = isDark ? 0.2 : 0.1;
100
+ const subtle = `rgba(${primaryRGB.r}, ${primaryRGB.g}, ${primaryRGB.b}, ${alpha})`;
101
+
102
+ // Note: Shadcn usually has specific greys for secondary, but for "Brand" themes
103
+ // we can tint them slightly or stick to standard zinc.
104
+ // For this implementation, we will keep existing "neutral" variables from CSS
105
+ // but override "ring" and "sidebar-ring" to match brand.
106
+
107
+ root.style.setProperty('--ring', isDark ? colors.primaryDarkMode : `rgba(${primaryRGB.r}, ${primaryRGB.g}, ${primaryRGB.b}, 0.5)`);
108
+
109
+ // Also update the Xertica specific variables
110
+ root.style.setProperty('--xertica-primary', primary);
111
+ root.style.setProperty('--primary-light', `rgba(${primaryRGB.r}, ${primaryRGB.g}, ${primaryRGB.b}, 0.15)`);
112
+ root.style.setProperty('--primary-light-foreground', primary);
447
113
  }
448
114
 
449
115
  // 3. Radius
@@ -459,47 +125,47 @@ export const BrandColorsProvider: React.FC<{ children: React.ReactNode }> = ({ c
459
125
  // 5. Sidebar (Override)
460
126
  // Dynamic sidebar colors based on theme and mode
461
127
  const sidebarBg = isDark ? colors.sidebarDark : colors.sidebarLight;
462
-
128
+
463
129
  // Determine if sidebar background is dark or light to set text color
464
130
  // We assume if the sidebar background is the Primary Color (which are generally dark/saturated), text should be white.
465
131
  // Xertica Original (Purple), Blue, Violet, etc. are all dark.
466
132
  // If sidebarLight is White (#FFFFFF) or very light, text should be dark.
467
-
133
+
468
134
  // Simple check: is sidebarBg roughly White/Light?
469
135
  const isSidebarLight = sidebarBg.toLowerCase() === '#ffffff' || sidebarBg.toLowerCase() === '#f3f4f6' || sidebarBg.toLowerCase() === '#fafafa';
470
-
136
+
471
137
  const sidebarFg = isSidebarLight ? '#0F172A' : '#FFFFFF'; // Dark text for light BG, White text for dark BG
472
-
138
+
473
139
  root.style.setProperty('--sidebar', sidebarBg);
474
140
  root.style.setProperty('--sidebar-foreground', sidebarFg);
475
-
141
+
476
142
  // Sidebar Accent
477
143
  if (primaryRGB) {
478
- if (isSidebarLight) {
479
- // Standard behavior for light sidebar
480
- root.style.setProperty('--sidebar-accent', `rgba(${primaryRGB.r}, ${primaryRGB.g}, ${primaryRGB.b}, 0.1)`);
481
- root.style.setProperty('--sidebar-accent-foreground', primary);
482
- root.style.setProperty('--sidebar-border', 'rgba(0,0,0,0.1)');
483
- } else {
484
- // Behavior for colored/dark sidebar
485
- // Accent should be a slightly lighter/darker shade of the sidebar bg
486
- // Or white with low opacity
487
- root.style.setProperty('--sidebar-accent', 'rgba(255, 255, 255, 0.1)');
488
- root.style.setProperty('--sidebar-accent-foreground', '#FFFFFF');
489
- root.style.setProperty('--sidebar-border', 'rgba(255,255,255,0.1)');
490
- }
491
- root.style.setProperty('--sidebar-ring', `rgba(${primaryRGB.r}, ${primaryRGB.g}, ${primaryRGB.b}, 0.5)`);
144
+ if (isSidebarLight) {
145
+ // Standard behavior for light sidebar
146
+ root.style.setProperty('--sidebar-accent', `rgba(${primaryRGB.r}, ${primaryRGB.g}, ${primaryRGB.b}, 0.1)`);
147
+ root.style.setProperty('--sidebar-accent-foreground', primary);
148
+ root.style.setProperty('--sidebar-border', 'rgba(0,0,0,0.1)');
149
+ } else {
150
+ // Behavior for colored/dark sidebar
151
+ // Accent should be a slightly lighter/darker shade of the sidebar bg
152
+ // Or white with low opacity
153
+ root.style.setProperty('--sidebar-accent', 'rgba(255, 255, 255, 0.1)');
154
+ root.style.setProperty('--sidebar-accent-foreground', '#FFFFFF');
155
+ root.style.setProperty('--sidebar-border', 'rgba(255,255,255,0.1)');
156
+ }
157
+ root.style.setProperty('--sidebar-ring', `rgba(${primaryRGB.r}, ${primaryRGB.g}, ${primaryRGB.b}, 0.5)`);
492
158
  }
493
159
 
494
160
  // Sidebar Primary (Active Item)
495
161
  // If sidebar is colored (dark), the primary active item usually looks good as white or a very bright accent.
496
162
  // But standard "Primary" might clash if it's the same color as the background.
497
163
  if (!isSidebarLight) {
498
- root.style.setProperty('--sidebar-primary', '#FFFFFF');
499
- root.style.setProperty('--sidebar-primary-foreground', primary); // Text becomes primary color
164
+ root.style.setProperty('--sidebar-primary', '#FFFFFF');
165
+ root.style.setProperty('--sidebar-primary-foreground', primary); // Text becomes primary color
500
166
  } else {
501
- root.style.setProperty('--sidebar-primary', primary);
502
- root.style.setProperty('--sidebar-primary-foreground', primaryForeground);
167
+ root.style.setProperty('--sidebar-primary', primary);
168
+ root.style.setProperty('--sidebar-primary-foreground', primaryForeground);
503
169
  }
504
170
 
505
171
  // 6. Gradients
@@ -507,7 +173,7 @@ export const BrandColorsProvider: React.FC<{ children: React.ReactNode }> = ({ c
507
173
  '--gradient-diagonal',
508
174
  `linear-gradient(135deg, ${gradientStart} 0%, ${gradientEnd} 100%)`
509
175
  );
510
-
176
+
511
177
  // Save preferences
512
178
  localStorage.setItem('color-theme', currentTheme);
513
179
  }, [colors, currentTheme, radius]);