@idealyst/components 1.0.24 → 1.0.26
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/README.md +567 -567
- package/package.json +2 -2
- package/plugin/web.js +319 -185
- package/src/Avatar/Avatar.native.tsx +43 -43
- package/src/Avatar/Avatar.styles.tsx +66 -66
- package/src/Avatar/Avatar.web.tsx +50 -50
- package/src/Avatar/index.native.ts +1 -1
- package/src/Avatar/index.ts +1 -1
- package/src/Avatar/index.web.ts +1 -1
- package/src/Avatar/types.ts +42 -42
- package/src/Badge/Badge.native.tsx +42 -42
- package/src/Badge/Badge.styles.tsx +153 -153
- package/src/Badge/Badge.web.tsx +44 -44
- package/src/Badge/index.native.ts +1 -1
- package/src/Badge/index.ts +1 -1
- package/src/Badge/index.web.ts +1 -1
- package/src/Badge/types.ts +33 -33
- package/src/Button/Button.native.tsx +38 -38
- package/src/Button/Button.styles.tsx +214 -214
- package/src/Button/Button.types.ts +11 -11
- package/src/Button/Button.web.tsx +55 -55
- package/src/Button/index.native.ts +2 -2
- package/src/Button/index.ts +4 -4
- package/src/Button/index.web.ts +2 -2
- package/src/Button/types.ts +48 -48
- package/src/Card/Card.native.tsx +51 -51
- package/src/Card/Card.styles.tsx +239 -239
- package/src/Card/Card.web.tsx +61 -61
- package/src/Card/index.native.ts +2 -2
- package/src/Card/index.ts +4 -4
- package/src/Card/index.web.ts +2 -2
- package/src/Card/types.ts +58 -58
- package/src/Checkbox/Checkbox.native.tsx +98 -98
- package/src/Checkbox/Checkbox.styles.tsx +291 -291
- package/src/Checkbox/Checkbox.web.tsx +130 -130
- package/src/Checkbox/index.native.ts +2 -2
- package/src/Checkbox/index.ts +4 -4
- package/src/Checkbox/index.web.ts +2 -2
- package/src/Checkbox/types.ts +78 -78
- package/src/Divider/Divider.native.tsx +144 -144
- package/src/Divider/Divider.styles.tsx +601 -601
- package/src/Divider/Divider.web.tsx +72 -72
- package/src/Divider/index.native.ts +2 -2
- package/src/Divider/index.ts +4 -4
- package/src/Divider/index.web.ts +2 -2
- package/src/Divider/types.ts +53 -53
- package/src/Icon/Icon.native.tsx +38 -38
- package/src/Icon/Icon.styles.tsx +49 -49
- package/src/Icon/Icon.web.tsx +46 -46
- package/src/Icon/icon-types.ts +7452 -7452
- package/src/Icon/index.native.ts +2 -2
- package/src/Icon/index.ts +4 -4
- package/src/Icon/index.web.ts +2 -2
- package/src/Icon/types.ts +35 -35
- package/src/Input/Input.native.tsx +74 -74
- package/src/Input/Input.styles.tsx +176 -176
- package/src/Input/Input.web.tsx +70 -70
- package/src/Input/index.native.ts +2 -2
- package/src/Input/index.ts +4 -4
- package/src/Input/index.web.ts +2 -2
- package/src/Input/types.ts +68 -68
- package/src/Screen/Screen.native.tsx +40 -40
- package/src/Screen/Screen.styles.tsx +59 -59
- package/src/Screen/Screen.web.tsx +32 -32
- package/src/Screen/index.native.ts +1 -1
- package/src/Screen/index.ts +1 -1
- package/src/Screen/index.web.ts +1 -1
- package/src/Screen/types.ts +37 -37
- package/src/Text/Text.native.tsx +35 -35
- package/src/Text/Text.styles.tsx +66 -66
- package/src/Text/Text.web.tsx +40 -40
- package/src/Text/index.native.ts +2 -2
- package/src/Text/index.ts +4 -4
- package/src/Text/index.web.ts +2 -2
- package/src/Text/types.ts +38 -38
- package/src/View/View.native.tsx +55 -55
- package/src/View/View.styles.tsx +102 -102
- package/src/View/View.web.tsx +59 -59
- package/src/View/index.native.ts +2 -2
- package/src/View/index.ts +4 -4
- package/src/View/index.web.ts +2 -2
- package/src/View/types.ts +72 -72
- package/src/examples/AllExamples.tsx +71 -71
- package/src/examples/AvatarExamples.tsx +96 -96
- package/src/examples/BadgeExamples.tsx +199 -199
- package/src/examples/ButtonExamples.tsx +149 -149
- package/src/examples/CardExamples.tsx +175 -175
- package/src/examples/CheckboxExamples.tsx +216 -216
- package/src/examples/DividerExamples.tsx +217 -217
- package/src/examples/IconExamples.tsx +341 -341
- package/src/examples/InputExamples.tsx +133 -133
- package/src/examples/README.md +135 -135
- package/src/examples/ScreenExamples.tsx +153 -153
- package/src/examples/TextExamples.tsx +88 -88
- package/src/examples/ThemeExtensionExamples.tsx +90 -90
- package/src/examples/ValidationExamples.tsx +94 -94
- package/src/examples/ViewExamples.tsx +128 -128
- package/src/examples/extendedTheme.ts +328 -328
- package/src/examples/index.ts +14 -14
- package/src/index.native.ts +48 -48
- package/src/index.ts +47 -47
- package/src/theme/breakpoints.ts +8 -8
- package/src/theme/colorResolver.ts +217 -217
- package/src/theme/colors.ts +314 -314
- package/src/theme/defaultThemes.ts +325 -325
- package/src/theme/index.ts +187 -187
- package/src/theme/themeBuilder.ts +601 -601
- package/src/theme/unistyles.d.ts +5 -5
- package/src/theme/variantHelpers.ts +583 -583
- package/src/theme/variants.ts +55 -55
|
@@ -1,602 +1,602 @@
|
|
|
1
|
-
import { commonThemeProperties } from './defaultThemes';
|
|
2
|
-
import type { ColorPaletteShade } from './variants';
|
|
3
|
-
|
|
4
|
-
// =============================================================================
|
|
5
|
-
// TYPES
|
|
6
|
-
// =============================================================================
|
|
7
|
-
|
|
8
|
-
export interface ThemeColorPalette {
|
|
9
|
-
50: string;
|
|
10
|
-
100: string;
|
|
11
|
-
200: string;
|
|
12
|
-
300: string;
|
|
13
|
-
400: string;
|
|
14
|
-
500: string;
|
|
15
|
-
600: string;
|
|
16
|
-
700: string;
|
|
17
|
-
800: string;
|
|
18
|
-
900: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface ResolvedIntent {
|
|
22
|
-
main: string;
|
|
23
|
-
on: string;
|
|
24
|
-
container: string;
|
|
25
|
-
onContainer: string;
|
|
26
|
-
light: string;
|
|
27
|
-
dark: string;
|
|
28
|
-
border: string;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface ThemeColorSystem {
|
|
32
|
-
text: {
|
|
33
|
-
primary: string;
|
|
34
|
-
secondary: string;
|
|
35
|
-
disabled: string;
|
|
36
|
-
inverse: string;
|
|
37
|
-
muted: string;
|
|
38
|
-
placeholder: string;
|
|
39
|
-
};
|
|
40
|
-
surface: {
|
|
41
|
-
primary: string;
|
|
42
|
-
secondary: string;
|
|
43
|
-
tertiary: string;
|
|
44
|
-
elevated: string;
|
|
45
|
-
overlay: string;
|
|
46
|
-
inverse: string;
|
|
47
|
-
};
|
|
48
|
-
border: {
|
|
49
|
-
primary: string;
|
|
50
|
-
secondary: string;
|
|
51
|
-
strong: string;
|
|
52
|
-
focus: string;
|
|
53
|
-
disabled: string;
|
|
54
|
-
};
|
|
55
|
-
interactive: {
|
|
56
|
-
hover: string;
|
|
57
|
-
pressed: string;
|
|
58
|
-
focus: string;
|
|
59
|
-
disabled: string;
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export interface ThemeConfig {
|
|
64
|
-
name?: string;
|
|
65
|
-
mode?: 'light' | 'dark';
|
|
66
|
-
|
|
67
|
-
// Required: Color palettes with actual hex values
|
|
68
|
-
palettes: {
|
|
69
|
-
red: ThemeColorPalette;
|
|
70
|
-
orange: ThemeColorPalette;
|
|
71
|
-
yellow: ThemeColorPalette;
|
|
72
|
-
green: ThemeColorPalette;
|
|
73
|
-
blue: ThemeColorPalette;
|
|
74
|
-
purple: ThemeColorPalette;
|
|
75
|
-
black: ThemeColorPalette;
|
|
76
|
-
gray: ThemeColorPalette;
|
|
77
|
-
white: ThemeColorPalette;
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
// Required: Resolved intent colors (actual hex values)
|
|
81
|
-
intents: {
|
|
82
|
-
primary: ResolvedIntent;
|
|
83
|
-
success: ResolvedIntent;
|
|
84
|
-
error: ResolvedIntent;
|
|
85
|
-
warning: ResolvedIntent;
|
|
86
|
-
neutral: ResolvedIntent;
|
|
87
|
-
info: ResolvedIntent;
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
// Required: Resolved color system (actual hex values)
|
|
91
|
-
colors: ThemeColorSystem;
|
|
92
|
-
|
|
93
|
-
// Optional: Typography
|
|
94
|
-
typography?: {
|
|
95
|
-
fontFamily?: string;
|
|
96
|
-
fontSize?: Record<string, number>;
|
|
97
|
-
fontWeight?: Record<string, string>;
|
|
98
|
-
lineHeight?: Record<string, number>;
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
// Optional: Spacing
|
|
102
|
-
spacing?: Record<string, number>;
|
|
103
|
-
|
|
104
|
-
// Optional: Border radius
|
|
105
|
-
borderRadius?: Record<string, number>;
|
|
106
|
-
|
|
107
|
-
// Optional: Shadows
|
|
108
|
-
shadows?: Record<string, any>;
|
|
109
|
-
|
|
110
|
-
// Optional: Transitions
|
|
111
|
-
transitions?: Record<string, string>;
|
|
112
|
-
|
|
113
|
-
// Optional: Custom properties
|
|
114
|
-
custom?: Record<string, any>;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// =============================================================================
|
|
118
|
-
// HELPER FUNCTIONS (exported for optional use)
|
|
119
|
-
// =============================================================================
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Generates a full color palette from a single color
|
|
123
|
-
* This is a helper function that users can choose to use
|
|
124
|
-
*/
|
|
125
|
-
export function generateColorPalette(baseColor: string): ThemeColorPalette {
|
|
126
|
-
// Simple implementation - in a real app, you'd use a color manipulation library
|
|
127
|
-
const colorMap: Record<string, ThemeColorPalette> = {
|
|
128
|
-
// Red variants
|
|
129
|
-
'#ef4444': { 50: '#fef2f2', 100: '#fee2e2', 200: '#fecaca', 300: '#fca5a5', 400: '#f87171', 500: '#ef4444', 600: '#dc2626', 700: '#b91c1c', 800: '#991b1b', 900: '#7f1d1d' },
|
|
130
|
-
'#dc2626': { 50: '#fef2f2', 100: '#fee2e2', 200: '#fecaca', 300: '#fca5a5', 400: '#f87171', 500: '#ef4444', 600: '#dc2626', 700: '#b91c1c', 800: '#991b1b', 900: '#7f1d1d' },
|
|
131
|
-
|
|
132
|
-
// Blue variants
|
|
133
|
-
'#3b82f6': { 50: '#eff6ff', 100: '#dbeafe', 200: '#bfdbfe', 300: '#93c5fd', 400: '#60a5fa', 500: '#3b82f6', 600: '#2563eb', 700: '#1d4ed8', 800: '#1e40af', 900: '#1e3a8a' },
|
|
134
|
-
'#2563eb': { 50: '#eff6ff', 100: '#dbeafe', 200: '#bfdbfe', 300: '#93c5fd', 400: '#60a5fa', 500: '#3b82f6', 600: '#2563eb', 700: '#1d4ed8', 800: '#1e40af', 900: '#1e3a8a' },
|
|
135
|
-
|
|
136
|
-
// Green variants
|
|
137
|
-
'#22c55e': { 50: '#f0fdf4', 100: '#dcfce7', 200: '#bbf7d0', 300: '#86efac', 400: '#4ade80', 500: '#22c55e', 600: '#16a34a', 700: '#15803d', 800: '#166534', 900: '#14532d' },
|
|
138
|
-
'#16a34a': { 50: '#f0fdf4', 100: '#dcfce7', 200: '#bbf7d0', 300: '#86efac', 400: '#4ade80', 500: '#22c55e', 600: '#16a34a', 700: '#15803d', 800: '#166534', 900: '#14532d' },
|
|
139
|
-
|
|
140
|
-
// Orange variants
|
|
141
|
-
'#f97316': { 50: '#fff7ed', 100: '#ffedd5', 200: '#fed7aa', 300: '#fdba74', 400: '#fb923c', 500: '#f97316', 600: '#ea580c', 700: '#c2410c', 800: '#9a3412', 900: '#7c2d12' },
|
|
142
|
-
'#ea580c': { 50: '#fff7ed', 100: '#ffedd5', 200: '#fed7aa', 300: '#fdba74', 400: '#fb923c', 500: '#f97316', 600: '#ea580c', 700: '#c2410c', 800: '#9a3412', 900: '#7c2d12' },
|
|
143
|
-
|
|
144
|
-
// Purple variants
|
|
145
|
-
'#a855f7': { 50: '#faf5ff', 100: '#f3e8ff', 200: '#e9d5ff', 300: '#d8b4fe', 400: '#c084fc', 500: '#a855f7', 600: '#9333ea', 700: '#7c3aed', 800: '#6b21a8', 900: '#581c87' },
|
|
146
|
-
'#9333ea': { 50: '#faf5ff', 100: '#f3e8ff', 200: '#e9d5ff', 300: '#d8b4fe', 400: '#c084fc', 500: '#a855f7', 600: '#9333ea', 700: '#7c3aed', 800: '#6b21a8', 900: '#581c87' },
|
|
147
|
-
|
|
148
|
-
// Yellow variants
|
|
149
|
-
'#eab308': { 50: '#fefce8', 100: '#fef9c3', 200: '#fef08a', 300: '#fde047', 400: '#facc15', 500: '#eab308', 600: '#ca8a04', 700: '#a16207', 800: '#854d0e', 900: '#713f12' },
|
|
150
|
-
'#ca8a04': { 50: '#fefce8', 100: '#fef9c3', 200: '#fef08a', 300: '#fde047', 400: '#facc15', 500: '#eab308', 600: '#ca8a04', 700: '#a16207', 800: '#854d0e', 900: '#713f12' },
|
|
151
|
-
|
|
152
|
-
// Gray variants
|
|
153
|
-
'#6b7280': { 50: '#f9fafb', 100: '#f3f4f6', 200: '#e5e7eb', 300: '#d1d5db', 400: '#9ca3af', 500: '#6b7280', 600: '#4b5563', 700: '#374151', 800: '#1f2937', 900: '#111827' },
|
|
154
|
-
'#4b5563': { 50: '#f9fafb', 100: '#f3f4f6', 200: '#e5e7eb', 300: '#d1d5db', 400: '#9ca3af', 500: '#6b7280', 600: '#4b5563', 700: '#374151', 800: '#1f2937', 900: '#111827' },
|
|
155
|
-
|
|
156
|
-
// Black variants
|
|
157
|
-
'#000000': { 50: '#f8f9fa', 100: '#f1f3f4', 200: '#e8eaed', 300: '#dadce0', 400: '#bdc1c6', 500: '#9aa0a6', 600: '#80868b', 700: '#5f6368', 800: '#3c4043', 900: '#202124' },
|
|
158
|
-
'#202124': { 50: '#f8f9fa', 100: '#f1f3f4', 200: '#e8eaed', 300: '#dadce0', 400: '#bdc1c6', 500: '#9aa0a6', 600: '#80868b', 700: '#5f6368', 800: '#3c4043', 900: '#202124' },
|
|
159
|
-
|
|
160
|
-
// White variants
|
|
161
|
-
'#ffffff': { 50: '#ffffff', 100: '#fefefe', 200: '#fdfdfd', 300: '#fcfcfc', 400: '#fafafa', 500: '#f8f8f8', 600: '#f5f5f5', 700: '#f0f0f0', 800: '#e8e8e8', 900: '#d4d4d4' },
|
|
162
|
-
'#f8f8f8': { 50: '#ffffff', 100: '#fefefe', 200: '#fdfdfd', 300: '#fcfcfc', 400: '#fafafa', 500: '#f8f8f8', 600: '#f5f5f5', 700: '#f0f0f0', 800: '#e8e8e8', 900: '#d4d4d4' },
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
// Return exact match or fallback to a basic palette
|
|
166
|
-
if (colorMap[baseColor]) {
|
|
167
|
-
return colorMap[baseColor];
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// Fallback: generate a basic palette
|
|
171
|
-
return {
|
|
172
|
-
50: lighten(baseColor, 0.9),
|
|
173
|
-
100: lighten(baseColor, 0.8),
|
|
174
|
-
200: lighten(baseColor, 0.6),
|
|
175
|
-
300: lighten(baseColor, 0.4),
|
|
176
|
-
400: lighten(baseColor, 0.2),
|
|
177
|
-
500: baseColor,
|
|
178
|
-
600: darken(baseColor, 0.1),
|
|
179
|
-
700: darken(baseColor, 0.2),
|
|
180
|
-
800: darken(baseColor, 0.3),
|
|
181
|
-
900: darken(baseColor, 0.4),
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Simple color lightening function
|
|
187
|
-
*/
|
|
188
|
-
export function lighten(color: string, amount: number): string {
|
|
189
|
-
const hex = color.replace('#', '');
|
|
190
|
-
const r = parseInt(hex.substr(0, 2), 16);
|
|
191
|
-
const g = parseInt(hex.substr(2, 2), 16);
|
|
192
|
-
const b = parseInt(hex.substr(4, 2), 16);
|
|
193
|
-
|
|
194
|
-
const newR = Math.min(255, Math.round(r + (255 - r) * amount));
|
|
195
|
-
const newG = Math.min(255, Math.round(g + (255 - g) * amount));
|
|
196
|
-
const newB = Math.min(255, Math.round(b + (255 - b) * amount));
|
|
197
|
-
|
|
198
|
-
return `#${newR.toString(16).padStart(2, '0')}${newG.toString(16).padStart(2, '0')}${newB.toString(16).padStart(2, '0')}`;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Simple color darkening function
|
|
203
|
-
*/
|
|
204
|
-
export function darken(color: string, amount: number): string {
|
|
205
|
-
const hex = color.replace('#', '');
|
|
206
|
-
const r = parseInt(hex.substr(0, 2), 16);
|
|
207
|
-
const g = parseInt(hex.substr(2, 2), 16);
|
|
208
|
-
const b = parseInt(hex.substr(4, 2), 16);
|
|
209
|
-
|
|
210
|
-
const newR = Math.max(0, Math.round(r * (1 - amount)));
|
|
211
|
-
const newG = Math.max(0, Math.round(g * (1 - amount)));
|
|
212
|
-
const newB = Math.max(0, Math.round(b * (1 - amount)));
|
|
213
|
-
|
|
214
|
-
return `#${newR.toString(16).padStart(2, '0')}${newG.toString(16).padStart(2, '0')}${newB.toString(16).padStart(2, '0')}`;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Helper function to create standard light theme resolved intents
|
|
219
|
-
*/
|
|
220
|
-
export function createLightResolvedIntents(palettes: ThemeConfig['palettes']): ThemeConfig['intents'] {
|
|
221
|
-
return {
|
|
222
|
-
primary: {
|
|
223
|
-
main: palettes.blue[500],
|
|
224
|
-
on: '#ffffff',
|
|
225
|
-
container: palettes.blue[50],
|
|
226
|
-
onContainer: palettes.blue[900],
|
|
227
|
-
light: palettes.blue[100],
|
|
228
|
-
dark: palettes.blue[700],
|
|
229
|
-
border: palettes.blue[200],
|
|
230
|
-
},
|
|
231
|
-
success: {
|
|
232
|
-
main: palettes.green[500],
|
|
233
|
-
on: '#ffffff',
|
|
234
|
-
container: palettes.green[50],
|
|
235
|
-
onContainer: palettes.green[800],
|
|
236
|
-
light: palettes.green[100],
|
|
237
|
-
dark: palettes.green[700],
|
|
238
|
-
border: palettes.green[200],
|
|
239
|
-
},
|
|
240
|
-
error: {
|
|
241
|
-
main: palettes.red[500],
|
|
242
|
-
on: '#ffffff',
|
|
243
|
-
container: palettes.red[50],
|
|
244
|
-
onContainer: palettes.red[800],
|
|
245
|
-
light: palettes.red[100],
|
|
246
|
-
dark: palettes.red[700],
|
|
247
|
-
border: palettes.red[200],
|
|
248
|
-
},
|
|
249
|
-
warning: {
|
|
250
|
-
main: palettes.orange[500],
|
|
251
|
-
on: '#ffffff',
|
|
252
|
-
container: palettes.orange[50],
|
|
253
|
-
onContainer: palettes.orange[800],
|
|
254
|
-
light: palettes.orange[100],
|
|
255
|
-
dark: palettes.orange[700],
|
|
256
|
-
border: palettes.orange[200],
|
|
257
|
-
},
|
|
258
|
-
neutral: {
|
|
259
|
-
main: palettes.gray[500],
|
|
260
|
-
on: '#ffffff',
|
|
261
|
-
container: palettes.gray[50],
|
|
262
|
-
onContainer: palettes.gray[800],
|
|
263
|
-
light: palettes.gray[100],
|
|
264
|
-
dark: palettes.gray[700],
|
|
265
|
-
border: palettes.gray[200],
|
|
266
|
-
},
|
|
267
|
-
info: {
|
|
268
|
-
main: palettes.blue[500],
|
|
269
|
-
on: '#ffffff',
|
|
270
|
-
container: palettes.blue[50],
|
|
271
|
-
onContainer: palettes.blue[800],
|
|
272
|
-
light: palettes.blue[100],
|
|
273
|
-
dark: palettes.blue[700],
|
|
274
|
-
border: palettes.blue[200],
|
|
275
|
-
},
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* Helper function to create standard dark theme resolved intents
|
|
281
|
-
*/
|
|
282
|
-
export function createDarkResolvedIntents(palettes: ThemeConfig['palettes']): ThemeConfig['intents'] {
|
|
283
|
-
return {
|
|
284
|
-
primary: {
|
|
285
|
-
main: palettes.blue[400],
|
|
286
|
-
on: palettes.gray[50], // Dark text on primary background
|
|
287
|
-
container: palettes.blue[200], // Darker container for dark mode
|
|
288
|
-
onContainer: palettes.blue[800], // Light text on dark container
|
|
289
|
-
light: palettes.blue[300],
|
|
290
|
-
dark: palettes.blue[600],
|
|
291
|
-
border: palettes.blue[400],
|
|
292
|
-
},
|
|
293
|
-
success: {
|
|
294
|
-
main: palettes.green[400],
|
|
295
|
-
on: palettes.gray[50], // Dark text on success background
|
|
296
|
-
container: palettes.green[200], // Darker container for dark mode
|
|
297
|
-
onContainer: palettes.green[800], // Light text on dark container
|
|
298
|
-
light: palettes.green[300],
|
|
299
|
-
dark: palettes.green[600],
|
|
300
|
-
border: palettes.green[400],
|
|
301
|
-
},
|
|
302
|
-
error: {
|
|
303
|
-
main: palettes.red[400],
|
|
304
|
-
on: palettes.gray[50], // Dark text on error background
|
|
305
|
-
container: palettes.red[200], // Darker container for dark mode
|
|
306
|
-
onContainer: palettes.red[800], // Light text on dark container
|
|
307
|
-
light: palettes.red[300],
|
|
308
|
-
dark: palettes.red[600],
|
|
309
|
-
border: palettes.red[400],
|
|
310
|
-
},
|
|
311
|
-
warning: {
|
|
312
|
-
main: palettes.orange[400],
|
|
313
|
-
on: palettes.gray[50], // Dark text on warning background
|
|
314
|
-
container: palettes.orange[200], // Darker container for dark mode
|
|
315
|
-
onContainer: palettes.orange[800], // Light text on dark container
|
|
316
|
-
light: palettes.orange[300],
|
|
317
|
-
dark: palettes.orange[600],
|
|
318
|
-
border: palettes.orange[400],
|
|
319
|
-
},
|
|
320
|
-
neutral: {
|
|
321
|
-
main: palettes.gray[400],
|
|
322
|
-
on: palettes.gray[50], // Dark text on neutral background
|
|
323
|
-
container: palettes.gray[200], // Medium dark container
|
|
324
|
-
onContainer: palettes.gray[800], // Light text on dark container
|
|
325
|
-
light: palettes.gray[300],
|
|
326
|
-
dark: palettes.gray[600],
|
|
327
|
-
border: palettes.gray[400],
|
|
328
|
-
},
|
|
329
|
-
info: {
|
|
330
|
-
main: palettes.blue[400],
|
|
331
|
-
on: palettes.gray[50], // Dark text on info background
|
|
332
|
-
container: palettes.blue[200], // Darker container for dark mode
|
|
333
|
-
onContainer: palettes.blue[800], // Light text on dark container
|
|
334
|
-
light: palettes.blue[300],
|
|
335
|
-
dark: palettes.blue[600],
|
|
336
|
-
border: palettes.blue[400],
|
|
337
|
-
},
|
|
338
|
-
};
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
/**
|
|
342
|
-
* Helper function to create standard light theme resolved colors
|
|
343
|
-
*/
|
|
344
|
-
export function createLightResolvedColors(palettes: ThemeConfig['palettes']): ThemeColorSystem {
|
|
345
|
-
return {
|
|
346
|
-
text: {
|
|
347
|
-
primary: palettes.gray[900],
|
|
348
|
-
secondary: palettes.gray[600],
|
|
349
|
-
disabled: palettes.gray[400],
|
|
350
|
-
inverse: '#ffffff',
|
|
351
|
-
muted: palettes.gray[500],
|
|
352
|
-
placeholder: palettes.gray[400],
|
|
353
|
-
},
|
|
354
|
-
surface: {
|
|
355
|
-
primary: '#ffffff',
|
|
356
|
-
secondary: palettes.gray[50],
|
|
357
|
-
tertiary: palettes.gray[100],
|
|
358
|
-
elevated: '#ffffff',
|
|
359
|
-
overlay: 'rgba(0, 0, 0, 0.5)',
|
|
360
|
-
inverse: palettes.gray[900],
|
|
361
|
-
},
|
|
362
|
-
border: {
|
|
363
|
-
primary: palettes.gray[200],
|
|
364
|
-
secondary: palettes.gray[300],
|
|
365
|
-
strong: palettes.gray[400],
|
|
366
|
-
focus: palettes.blue[500], // Using primary color
|
|
367
|
-
disabled: palettes.gray[200],
|
|
368
|
-
},
|
|
369
|
-
interactive: {
|
|
370
|
-
hover: palettes.gray[50],
|
|
371
|
-
pressed: palettes.gray[100],
|
|
372
|
-
focus: palettes.blue[500], // Using primary color
|
|
373
|
-
disabled: palettes.gray[100],
|
|
374
|
-
},
|
|
375
|
-
};
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
/**
|
|
379
|
-
* Helper function to create standard dark theme resolved colors
|
|
380
|
-
*/
|
|
381
|
-
export function createDarkResolvedColors(palettes: ThemeConfig['palettes']): ThemeColorSystem {
|
|
382
|
-
return {
|
|
383
|
-
text: {
|
|
384
|
-
primary: palettes.gray[900], // Light text on dark background
|
|
385
|
-
secondary: palettes.gray[700], // Muted light text
|
|
386
|
-
disabled: palettes.gray[500], // Disabled gray
|
|
387
|
-
inverse: palettes.gray[100], // Dark text (inverse of primary)
|
|
388
|
-
muted: palettes.gray[600], // Muted text
|
|
389
|
-
placeholder: palettes.gray[500], // Placeholder text
|
|
390
|
-
},
|
|
391
|
-
surface: {
|
|
392
|
-
primary: palettes.gray[50], // Very dark primary surface
|
|
393
|
-
secondary: palettes.gray[100], // Dark secondary surface
|
|
394
|
-
tertiary: palettes.gray[200], // Medium dark tertiary surface
|
|
395
|
-
elevated: palettes.gray[100], // Elevated surface (slightly lighter)
|
|
396
|
-
overlay: 'rgba(0, 0, 0, 0.8)', // Dark overlay
|
|
397
|
-
inverse: palettes.gray[900], // Light surface (inverse)
|
|
398
|
-
},
|
|
399
|
-
border: {
|
|
400
|
-
primary: palettes.gray[300], // Primary border
|
|
401
|
-
secondary: palettes.gray[200], // Secondary border
|
|
402
|
-
strong: palettes.gray[400], // Strong border
|
|
403
|
-
focus: palettes.blue[400], // Focus border (primary color)
|
|
404
|
-
disabled: palettes.gray[300], // Disabled border
|
|
405
|
-
},
|
|
406
|
-
interactive: {
|
|
407
|
-
hover: palettes.gray[100], // Hover state
|
|
408
|
-
pressed: palettes.gray[200], // Pressed state
|
|
409
|
-
focus: palettes.blue[400], // Focus state (primary color)
|
|
410
|
-
disabled: palettes.gray[100], // Disabled state
|
|
411
|
-
},
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
// Default palettes and convenience functions moved to defaultThemes.ts
|
|
416
|
-
// This keeps the theme builder focused on core functionality
|
|
417
|
-
|
|
418
|
-
// =============================================================================
|
|
419
|
-
// MAIN THEME CREATION FUNCTION
|
|
420
|
-
// =============================================================================
|
|
421
|
-
|
|
422
|
-
/**
|
|
423
|
-
* Creates a theme with fully explicit resolved colors
|
|
424
|
-
* Users must provide actual hex colors, no automatic resolution
|
|
425
|
-
*/
|
|
426
|
-
export function createTheme(config: ThemeConfig): any {
|
|
427
|
-
const {
|
|
428
|
-
name = 'CustomTheme',
|
|
429
|
-
mode = 'light',
|
|
430
|
-
palettes,
|
|
431
|
-
intents,
|
|
432
|
-
colors,
|
|
433
|
-
typography = {},
|
|
434
|
-
spacing = {},
|
|
435
|
-
borderRadius = {},
|
|
436
|
-
shadows = {},
|
|
437
|
-
transitions = {},
|
|
438
|
-
custom = {},
|
|
439
|
-
} = config;
|
|
440
|
-
|
|
441
|
-
// Generate final theme - no automatic color resolution, just organization
|
|
442
|
-
const theme = {
|
|
443
|
-
name,
|
|
444
|
-
mode,
|
|
445
|
-
|
|
446
|
-
// Merge with common properties
|
|
447
|
-
...commonThemeProperties,
|
|
448
|
-
|
|
449
|
-
// Override with custom properties
|
|
450
|
-
...custom,
|
|
451
|
-
|
|
452
|
-
// Typography
|
|
453
|
-
typography: {
|
|
454
|
-
...commonThemeProperties.typography,
|
|
455
|
-
...typography,
|
|
456
|
-
},
|
|
457
|
-
|
|
458
|
-
// Spacing
|
|
459
|
-
spacing: {
|
|
460
|
-
...commonThemeProperties.spacing,
|
|
461
|
-
...spacing,
|
|
462
|
-
},
|
|
463
|
-
|
|
464
|
-
// Border radius
|
|
465
|
-
borderRadius: {
|
|
466
|
-
...commonThemeProperties.borderRadius,
|
|
467
|
-
...borderRadius,
|
|
468
|
-
},
|
|
469
|
-
|
|
470
|
-
// Shadows
|
|
471
|
-
shadows: {
|
|
472
|
-
...commonThemeProperties.shadows,
|
|
473
|
-
...shadows,
|
|
474
|
-
},
|
|
475
|
-
|
|
476
|
-
// Transitions
|
|
477
|
-
transitions: {
|
|
478
|
-
...commonThemeProperties.transitions,
|
|
479
|
-
...transitions,
|
|
480
|
-
},
|
|
481
|
-
|
|
482
|
-
// Color palettes - direct access to all color palettes
|
|
483
|
-
palettes,
|
|
484
|
-
|
|
485
|
-
// Intent system - for actionable components (all resolved)
|
|
486
|
-
intents,
|
|
487
|
-
|
|
488
|
-
// Color system - for display components (all resolved)
|
|
489
|
-
colors: {
|
|
490
|
-
// Provided color system
|
|
491
|
-
...colors,
|
|
492
|
-
|
|
493
|
-
// Status colors (references to intents)
|
|
494
|
-
primary: intents.primary.main,
|
|
495
|
-
success: intents.success.main,
|
|
496
|
-
error: intents.error.main,
|
|
497
|
-
warning: intents.warning.main,
|
|
498
|
-
neutral: intents.neutral.main,
|
|
499
|
-
info: intents.info.main,
|
|
500
|
-
|
|
501
|
-
// Legacy colors for backward compatibility
|
|
502
|
-
background: colors.surface.primary,
|
|
503
|
-
textSecondary: colors.text.secondary,
|
|
504
|
-
secondary: intents.neutral.main,
|
|
505
|
-
},
|
|
506
|
-
};
|
|
507
|
-
|
|
508
|
-
return theme;
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
// =============================================================================
|
|
512
|
-
// UTILITY FUNCTIONS
|
|
513
|
-
// =============================================================================
|
|
514
|
-
|
|
515
|
-
/**
|
|
516
|
-
* Extends an existing theme with new properties
|
|
517
|
-
*/
|
|
518
|
-
export function extendTheme(baseTheme: any, extensions: {
|
|
519
|
-
palettes?: Partial<ThemeConfig['palettes']>;
|
|
520
|
-
intents?: Partial<ThemeConfig['intents']>;
|
|
521
|
-
colors?: Partial<ThemeColorSystem>;
|
|
522
|
-
typography?: Partial<ThemeConfig['typography']>;
|
|
523
|
-
spacing?: Record<string, number>;
|
|
524
|
-
borderRadius?: Record<string, number>;
|
|
525
|
-
shadows?: Record<string, any>;
|
|
526
|
-
transitions?: Record<string, string>;
|
|
527
|
-
custom?: Record<string, any>;
|
|
528
|
-
}): any {
|
|
529
|
-
return {
|
|
530
|
-
...baseTheme,
|
|
531
|
-
|
|
532
|
-
// Merge palettes
|
|
533
|
-
palettes: {
|
|
534
|
-
...baseTheme.palettes,
|
|
535
|
-
...extensions.palettes,
|
|
536
|
-
},
|
|
537
|
-
|
|
538
|
-
// Merge intents
|
|
539
|
-
intents: {
|
|
540
|
-
...baseTheme.intents,
|
|
541
|
-
...extensions.intents,
|
|
542
|
-
},
|
|
543
|
-
|
|
544
|
-
// Merge colors
|
|
545
|
-
colors: {
|
|
546
|
-
...baseTheme.colors,
|
|
547
|
-
text: {
|
|
548
|
-
...baseTheme.colors.text,
|
|
549
|
-
...extensions.colors?.text,
|
|
550
|
-
},
|
|
551
|
-
surface: {
|
|
552
|
-
...baseTheme.colors.surface,
|
|
553
|
-
...extensions.colors?.surface,
|
|
554
|
-
},
|
|
555
|
-
border: {
|
|
556
|
-
...baseTheme.colors.border,
|
|
557
|
-
...extensions.colors?.border,
|
|
558
|
-
},
|
|
559
|
-
interactive: {
|
|
560
|
-
...baseTheme.colors.interactive,
|
|
561
|
-
...extensions.colors?.interactive,
|
|
562
|
-
},
|
|
563
|
-
},
|
|
564
|
-
|
|
565
|
-
// Merge other properties
|
|
566
|
-
typography: {
|
|
567
|
-
...baseTheme.typography,
|
|
568
|
-
...extensions.typography,
|
|
569
|
-
},
|
|
570
|
-
|
|
571
|
-
spacing: {
|
|
572
|
-
...baseTheme.spacing,
|
|
573
|
-
...extensions.spacing,
|
|
574
|
-
},
|
|
575
|
-
|
|
576
|
-
borderRadius: {
|
|
577
|
-
...baseTheme.borderRadius,
|
|
578
|
-
...extensions.borderRadius,
|
|
579
|
-
},
|
|
580
|
-
|
|
581
|
-
shadows: {
|
|
582
|
-
...baseTheme.shadows,
|
|
583
|
-
...extensions.shadows,
|
|
584
|
-
},
|
|
585
|
-
|
|
586
|
-
transitions: {
|
|
587
|
-
...baseTheme.transitions,
|
|
588
|
-
...extensions.transitions,
|
|
589
|
-
},
|
|
590
|
-
|
|
591
|
-
custom: {
|
|
592
|
-
...baseTheme.custom,
|
|
593
|
-
...extensions.custom,
|
|
594
|
-
},
|
|
595
|
-
};
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
// createThemeVariant function removed - users should create themes explicitly
|
|
599
|
-
// using createTheme with the appropriate helper functions like createDarkPalettes(),
|
|
600
|
-
// createDarkIntentMappings(), and createDarkColorMappings() (found in defaultThemes.ts)
|
|
601
|
-
|
|
1
|
+
import { commonThemeProperties } from './defaultThemes';
|
|
2
|
+
import type { ColorPaletteShade } from './variants';
|
|
3
|
+
|
|
4
|
+
// =============================================================================
|
|
5
|
+
// TYPES
|
|
6
|
+
// =============================================================================
|
|
7
|
+
|
|
8
|
+
export interface ThemeColorPalette {
|
|
9
|
+
50: string;
|
|
10
|
+
100: string;
|
|
11
|
+
200: string;
|
|
12
|
+
300: string;
|
|
13
|
+
400: string;
|
|
14
|
+
500: string;
|
|
15
|
+
600: string;
|
|
16
|
+
700: string;
|
|
17
|
+
800: string;
|
|
18
|
+
900: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ResolvedIntent {
|
|
22
|
+
main: string;
|
|
23
|
+
on: string;
|
|
24
|
+
container: string;
|
|
25
|
+
onContainer: string;
|
|
26
|
+
light: string;
|
|
27
|
+
dark: string;
|
|
28
|
+
border: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface ThemeColorSystem {
|
|
32
|
+
text: {
|
|
33
|
+
primary: string;
|
|
34
|
+
secondary: string;
|
|
35
|
+
disabled: string;
|
|
36
|
+
inverse: string;
|
|
37
|
+
muted: string;
|
|
38
|
+
placeholder: string;
|
|
39
|
+
};
|
|
40
|
+
surface: {
|
|
41
|
+
primary: string;
|
|
42
|
+
secondary: string;
|
|
43
|
+
tertiary: string;
|
|
44
|
+
elevated: string;
|
|
45
|
+
overlay: string;
|
|
46
|
+
inverse: string;
|
|
47
|
+
};
|
|
48
|
+
border: {
|
|
49
|
+
primary: string;
|
|
50
|
+
secondary: string;
|
|
51
|
+
strong: string;
|
|
52
|
+
focus: string;
|
|
53
|
+
disabled: string;
|
|
54
|
+
};
|
|
55
|
+
interactive: {
|
|
56
|
+
hover: string;
|
|
57
|
+
pressed: string;
|
|
58
|
+
focus: string;
|
|
59
|
+
disabled: string;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface ThemeConfig {
|
|
64
|
+
name?: string;
|
|
65
|
+
mode?: 'light' | 'dark';
|
|
66
|
+
|
|
67
|
+
// Required: Color palettes with actual hex values
|
|
68
|
+
palettes: {
|
|
69
|
+
red: ThemeColorPalette;
|
|
70
|
+
orange: ThemeColorPalette;
|
|
71
|
+
yellow: ThemeColorPalette;
|
|
72
|
+
green: ThemeColorPalette;
|
|
73
|
+
blue: ThemeColorPalette;
|
|
74
|
+
purple: ThemeColorPalette;
|
|
75
|
+
black: ThemeColorPalette;
|
|
76
|
+
gray: ThemeColorPalette;
|
|
77
|
+
white: ThemeColorPalette;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// Required: Resolved intent colors (actual hex values)
|
|
81
|
+
intents: {
|
|
82
|
+
primary: ResolvedIntent;
|
|
83
|
+
success: ResolvedIntent;
|
|
84
|
+
error: ResolvedIntent;
|
|
85
|
+
warning: ResolvedIntent;
|
|
86
|
+
neutral: ResolvedIntent;
|
|
87
|
+
info: ResolvedIntent;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// Required: Resolved color system (actual hex values)
|
|
91
|
+
colors: ThemeColorSystem;
|
|
92
|
+
|
|
93
|
+
// Optional: Typography
|
|
94
|
+
typography?: {
|
|
95
|
+
fontFamily?: string;
|
|
96
|
+
fontSize?: Record<string, number>;
|
|
97
|
+
fontWeight?: Record<string, string>;
|
|
98
|
+
lineHeight?: Record<string, number>;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// Optional: Spacing
|
|
102
|
+
spacing?: Record<string, number>;
|
|
103
|
+
|
|
104
|
+
// Optional: Border radius
|
|
105
|
+
borderRadius?: Record<string, number>;
|
|
106
|
+
|
|
107
|
+
// Optional: Shadows
|
|
108
|
+
shadows?: Record<string, any>;
|
|
109
|
+
|
|
110
|
+
// Optional: Transitions
|
|
111
|
+
transitions?: Record<string, string>;
|
|
112
|
+
|
|
113
|
+
// Optional: Custom properties
|
|
114
|
+
custom?: Record<string, any>;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// =============================================================================
|
|
118
|
+
// HELPER FUNCTIONS (exported for optional use)
|
|
119
|
+
// =============================================================================
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Generates a full color palette from a single color
|
|
123
|
+
* This is a helper function that users can choose to use
|
|
124
|
+
*/
|
|
125
|
+
export function generateColorPalette(baseColor: string): ThemeColorPalette {
|
|
126
|
+
// Simple implementation - in a real app, you'd use a color manipulation library
|
|
127
|
+
const colorMap: Record<string, ThemeColorPalette> = {
|
|
128
|
+
// Red variants
|
|
129
|
+
'#ef4444': { 50: '#fef2f2', 100: '#fee2e2', 200: '#fecaca', 300: '#fca5a5', 400: '#f87171', 500: '#ef4444', 600: '#dc2626', 700: '#b91c1c', 800: '#991b1b', 900: '#7f1d1d' },
|
|
130
|
+
'#dc2626': { 50: '#fef2f2', 100: '#fee2e2', 200: '#fecaca', 300: '#fca5a5', 400: '#f87171', 500: '#ef4444', 600: '#dc2626', 700: '#b91c1c', 800: '#991b1b', 900: '#7f1d1d' },
|
|
131
|
+
|
|
132
|
+
// Blue variants
|
|
133
|
+
'#3b82f6': { 50: '#eff6ff', 100: '#dbeafe', 200: '#bfdbfe', 300: '#93c5fd', 400: '#60a5fa', 500: '#3b82f6', 600: '#2563eb', 700: '#1d4ed8', 800: '#1e40af', 900: '#1e3a8a' },
|
|
134
|
+
'#2563eb': { 50: '#eff6ff', 100: '#dbeafe', 200: '#bfdbfe', 300: '#93c5fd', 400: '#60a5fa', 500: '#3b82f6', 600: '#2563eb', 700: '#1d4ed8', 800: '#1e40af', 900: '#1e3a8a' },
|
|
135
|
+
|
|
136
|
+
// Green variants
|
|
137
|
+
'#22c55e': { 50: '#f0fdf4', 100: '#dcfce7', 200: '#bbf7d0', 300: '#86efac', 400: '#4ade80', 500: '#22c55e', 600: '#16a34a', 700: '#15803d', 800: '#166534', 900: '#14532d' },
|
|
138
|
+
'#16a34a': { 50: '#f0fdf4', 100: '#dcfce7', 200: '#bbf7d0', 300: '#86efac', 400: '#4ade80', 500: '#22c55e', 600: '#16a34a', 700: '#15803d', 800: '#166534', 900: '#14532d' },
|
|
139
|
+
|
|
140
|
+
// Orange variants
|
|
141
|
+
'#f97316': { 50: '#fff7ed', 100: '#ffedd5', 200: '#fed7aa', 300: '#fdba74', 400: '#fb923c', 500: '#f97316', 600: '#ea580c', 700: '#c2410c', 800: '#9a3412', 900: '#7c2d12' },
|
|
142
|
+
'#ea580c': { 50: '#fff7ed', 100: '#ffedd5', 200: '#fed7aa', 300: '#fdba74', 400: '#fb923c', 500: '#f97316', 600: '#ea580c', 700: '#c2410c', 800: '#9a3412', 900: '#7c2d12' },
|
|
143
|
+
|
|
144
|
+
// Purple variants
|
|
145
|
+
'#a855f7': { 50: '#faf5ff', 100: '#f3e8ff', 200: '#e9d5ff', 300: '#d8b4fe', 400: '#c084fc', 500: '#a855f7', 600: '#9333ea', 700: '#7c3aed', 800: '#6b21a8', 900: '#581c87' },
|
|
146
|
+
'#9333ea': { 50: '#faf5ff', 100: '#f3e8ff', 200: '#e9d5ff', 300: '#d8b4fe', 400: '#c084fc', 500: '#a855f7', 600: '#9333ea', 700: '#7c3aed', 800: '#6b21a8', 900: '#581c87' },
|
|
147
|
+
|
|
148
|
+
// Yellow variants
|
|
149
|
+
'#eab308': { 50: '#fefce8', 100: '#fef9c3', 200: '#fef08a', 300: '#fde047', 400: '#facc15', 500: '#eab308', 600: '#ca8a04', 700: '#a16207', 800: '#854d0e', 900: '#713f12' },
|
|
150
|
+
'#ca8a04': { 50: '#fefce8', 100: '#fef9c3', 200: '#fef08a', 300: '#fde047', 400: '#facc15', 500: '#eab308', 600: '#ca8a04', 700: '#a16207', 800: '#854d0e', 900: '#713f12' },
|
|
151
|
+
|
|
152
|
+
// Gray variants
|
|
153
|
+
'#6b7280': { 50: '#f9fafb', 100: '#f3f4f6', 200: '#e5e7eb', 300: '#d1d5db', 400: '#9ca3af', 500: '#6b7280', 600: '#4b5563', 700: '#374151', 800: '#1f2937', 900: '#111827' },
|
|
154
|
+
'#4b5563': { 50: '#f9fafb', 100: '#f3f4f6', 200: '#e5e7eb', 300: '#d1d5db', 400: '#9ca3af', 500: '#6b7280', 600: '#4b5563', 700: '#374151', 800: '#1f2937', 900: '#111827' },
|
|
155
|
+
|
|
156
|
+
// Black variants
|
|
157
|
+
'#000000': { 50: '#f8f9fa', 100: '#f1f3f4', 200: '#e8eaed', 300: '#dadce0', 400: '#bdc1c6', 500: '#9aa0a6', 600: '#80868b', 700: '#5f6368', 800: '#3c4043', 900: '#202124' },
|
|
158
|
+
'#202124': { 50: '#f8f9fa', 100: '#f1f3f4', 200: '#e8eaed', 300: '#dadce0', 400: '#bdc1c6', 500: '#9aa0a6', 600: '#80868b', 700: '#5f6368', 800: '#3c4043', 900: '#202124' },
|
|
159
|
+
|
|
160
|
+
// White variants
|
|
161
|
+
'#ffffff': { 50: '#ffffff', 100: '#fefefe', 200: '#fdfdfd', 300: '#fcfcfc', 400: '#fafafa', 500: '#f8f8f8', 600: '#f5f5f5', 700: '#f0f0f0', 800: '#e8e8e8', 900: '#d4d4d4' },
|
|
162
|
+
'#f8f8f8': { 50: '#ffffff', 100: '#fefefe', 200: '#fdfdfd', 300: '#fcfcfc', 400: '#fafafa', 500: '#f8f8f8', 600: '#f5f5f5', 700: '#f0f0f0', 800: '#e8e8e8', 900: '#d4d4d4' },
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
// Return exact match or fallback to a basic palette
|
|
166
|
+
if (colorMap[baseColor]) {
|
|
167
|
+
return colorMap[baseColor];
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Fallback: generate a basic palette
|
|
171
|
+
return {
|
|
172
|
+
50: lighten(baseColor, 0.9),
|
|
173
|
+
100: lighten(baseColor, 0.8),
|
|
174
|
+
200: lighten(baseColor, 0.6),
|
|
175
|
+
300: lighten(baseColor, 0.4),
|
|
176
|
+
400: lighten(baseColor, 0.2),
|
|
177
|
+
500: baseColor,
|
|
178
|
+
600: darken(baseColor, 0.1),
|
|
179
|
+
700: darken(baseColor, 0.2),
|
|
180
|
+
800: darken(baseColor, 0.3),
|
|
181
|
+
900: darken(baseColor, 0.4),
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Simple color lightening function
|
|
187
|
+
*/
|
|
188
|
+
export function lighten(color: string, amount: number): string {
|
|
189
|
+
const hex = color.replace('#', '');
|
|
190
|
+
const r = parseInt(hex.substr(0, 2), 16);
|
|
191
|
+
const g = parseInt(hex.substr(2, 2), 16);
|
|
192
|
+
const b = parseInt(hex.substr(4, 2), 16);
|
|
193
|
+
|
|
194
|
+
const newR = Math.min(255, Math.round(r + (255 - r) * amount));
|
|
195
|
+
const newG = Math.min(255, Math.round(g + (255 - g) * amount));
|
|
196
|
+
const newB = Math.min(255, Math.round(b + (255 - b) * amount));
|
|
197
|
+
|
|
198
|
+
return `#${newR.toString(16).padStart(2, '0')}${newG.toString(16).padStart(2, '0')}${newB.toString(16).padStart(2, '0')}`;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Simple color darkening function
|
|
203
|
+
*/
|
|
204
|
+
export function darken(color: string, amount: number): string {
|
|
205
|
+
const hex = color.replace('#', '');
|
|
206
|
+
const r = parseInt(hex.substr(0, 2), 16);
|
|
207
|
+
const g = parseInt(hex.substr(2, 2), 16);
|
|
208
|
+
const b = parseInt(hex.substr(4, 2), 16);
|
|
209
|
+
|
|
210
|
+
const newR = Math.max(0, Math.round(r * (1 - amount)));
|
|
211
|
+
const newG = Math.max(0, Math.round(g * (1 - amount)));
|
|
212
|
+
const newB = Math.max(0, Math.round(b * (1 - amount)));
|
|
213
|
+
|
|
214
|
+
return `#${newR.toString(16).padStart(2, '0')}${newG.toString(16).padStart(2, '0')}${newB.toString(16).padStart(2, '0')}`;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Helper function to create standard light theme resolved intents
|
|
219
|
+
*/
|
|
220
|
+
export function createLightResolvedIntents(palettes: ThemeConfig['palettes']): ThemeConfig['intents'] {
|
|
221
|
+
return {
|
|
222
|
+
primary: {
|
|
223
|
+
main: palettes.blue[500],
|
|
224
|
+
on: '#ffffff',
|
|
225
|
+
container: palettes.blue[50],
|
|
226
|
+
onContainer: palettes.blue[900],
|
|
227
|
+
light: palettes.blue[100],
|
|
228
|
+
dark: palettes.blue[700],
|
|
229
|
+
border: palettes.blue[200],
|
|
230
|
+
},
|
|
231
|
+
success: {
|
|
232
|
+
main: palettes.green[500],
|
|
233
|
+
on: '#ffffff',
|
|
234
|
+
container: palettes.green[50],
|
|
235
|
+
onContainer: palettes.green[800],
|
|
236
|
+
light: palettes.green[100],
|
|
237
|
+
dark: palettes.green[700],
|
|
238
|
+
border: palettes.green[200],
|
|
239
|
+
},
|
|
240
|
+
error: {
|
|
241
|
+
main: palettes.red[500],
|
|
242
|
+
on: '#ffffff',
|
|
243
|
+
container: palettes.red[50],
|
|
244
|
+
onContainer: palettes.red[800],
|
|
245
|
+
light: palettes.red[100],
|
|
246
|
+
dark: palettes.red[700],
|
|
247
|
+
border: palettes.red[200],
|
|
248
|
+
},
|
|
249
|
+
warning: {
|
|
250
|
+
main: palettes.orange[500],
|
|
251
|
+
on: '#ffffff',
|
|
252
|
+
container: palettes.orange[50],
|
|
253
|
+
onContainer: palettes.orange[800],
|
|
254
|
+
light: palettes.orange[100],
|
|
255
|
+
dark: palettes.orange[700],
|
|
256
|
+
border: palettes.orange[200],
|
|
257
|
+
},
|
|
258
|
+
neutral: {
|
|
259
|
+
main: palettes.gray[500],
|
|
260
|
+
on: '#ffffff',
|
|
261
|
+
container: palettes.gray[50],
|
|
262
|
+
onContainer: palettes.gray[800],
|
|
263
|
+
light: palettes.gray[100],
|
|
264
|
+
dark: palettes.gray[700],
|
|
265
|
+
border: palettes.gray[200],
|
|
266
|
+
},
|
|
267
|
+
info: {
|
|
268
|
+
main: palettes.blue[500],
|
|
269
|
+
on: '#ffffff',
|
|
270
|
+
container: palettes.blue[50],
|
|
271
|
+
onContainer: palettes.blue[800],
|
|
272
|
+
light: palettes.blue[100],
|
|
273
|
+
dark: palettes.blue[700],
|
|
274
|
+
border: palettes.blue[200],
|
|
275
|
+
},
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Helper function to create standard dark theme resolved intents
|
|
281
|
+
*/
|
|
282
|
+
export function createDarkResolvedIntents(palettes: ThemeConfig['palettes']): ThemeConfig['intents'] {
|
|
283
|
+
return {
|
|
284
|
+
primary: {
|
|
285
|
+
main: palettes.blue[400],
|
|
286
|
+
on: palettes.gray[50], // Dark text on primary background
|
|
287
|
+
container: palettes.blue[200], // Darker container for dark mode
|
|
288
|
+
onContainer: palettes.blue[800], // Light text on dark container
|
|
289
|
+
light: palettes.blue[300],
|
|
290
|
+
dark: palettes.blue[600],
|
|
291
|
+
border: palettes.blue[400],
|
|
292
|
+
},
|
|
293
|
+
success: {
|
|
294
|
+
main: palettes.green[400],
|
|
295
|
+
on: palettes.gray[50], // Dark text on success background
|
|
296
|
+
container: palettes.green[200], // Darker container for dark mode
|
|
297
|
+
onContainer: palettes.green[800], // Light text on dark container
|
|
298
|
+
light: palettes.green[300],
|
|
299
|
+
dark: palettes.green[600],
|
|
300
|
+
border: palettes.green[400],
|
|
301
|
+
},
|
|
302
|
+
error: {
|
|
303
|
+
main: palettes.red[400],
|
|
304
|
+
on: palettes.gray[50], // Dark text on error background
|
|
305
|
+
container: palettes.red[200], // Darker container for dark mode
|
|
306
|
+
onContainer: palettes.red[800], // Light text on dark container
|
|
307
|
+
light: palettes.red[300],
|
|
308
|
+
dark: palettes.red[600],
|
|
309
|
+
border: palettes.red[400],
|
|
310
|
+
},
|
|
311
|
+
warning: {
|
|
312
|
+
main: palettes.orange[400],
|
|
313
|
+
on: palettes.gray[50], // Dark text on warning background
|
|
314
|
+
container: palettes.orange[200], // Darker container for dark mode
|
|
315
|
+
onContainer: palettes.orange[800], // Light text on dark container
|
|
316
|
+
light: palettes.orange[300],
|
|
317
|
+
dark: palettes.orange[600],
|
|
318
|
+
border: palettes.orange[400],
|
|
319
|
+
},
|
|
320
|
+
neutral: {
|
|
321
|
+
main: palettes.gray[400],
|
|
322
|
+
on: palettes.gray[50], // Dark text on neutral background
|
|
323
|
+
container: palettes.gray[200], // Medium dark container
|
|
324
|
+
onContainer: palettes.gray[800], // Light text on dark container
|
|
325
|
+
light: palettes.gray[300],
|
|
326
|
+
dark: palettes.gray[600],
|
|
327
|
+
border: palettes.gray[400],
|
|
328
|
+
},
|
|
329
|
+
info: {
|
|
330
|
+
main: palettes.blue[400],
|
|
331
|
+
on: palettes.gray[50], // Dark text on info background
|
|
332
|
+
container: palettes.blue[200], // Darker container for dark mode
|
|
333
|
+
onContainer: palettes.blue[800], // Light text on dark container
|
|
334
|
+
light: palettes.blue[300],
|
|
335
|
+
dark: palettes.blue[600],
|
|
336
|
+
border: palettes.blue[400],
|
|
337
|
+
},
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Helper function to create standard light theme resolved colors
|
|
343
|
+
*/
|
|
344
|
+
export function createLightResolvedColors(palettes: ThemeConfig['palettes']): ThemeColorSystem {
|
|
345
|
+
return {
|
|
346
|
+
text: {
|
|
347
|
+
primary: palettes.gray[900],
|
|
348
|
+
secondary: palettes.gray[600],
|
|
349
|
+
disabled: palettes.gray[400],
|
|
350
|
+
inverse: '#ffffff',
|
|
351
|
+
muted: palettes.gray[500],
|
|
352
|
+
placeholder: palettes.gray[400],
|
|
353
|
+
},
|
|
354
|
+
surface: {
|
|
355
|
+
primary: '#ffffff',
|
|
356
|
+
secondary: palettes.gray[50],
|
|
357
|
+
tertiary: palettes.gray[100],
|
|
358
|
+
elevated: '#ffffff',
|
|
359
|
+
overlay: 'rgba(0, 0, 0, 0.5)',
|
|
360
|
+
inverse: palettes.gray[900],
|
|
361
|
+
},
|
|
362
|
+
border: {
|
|
363
|
+
primary: palettes.gray[200],
|
|
364
|
+
secondary: palettes.gray[300],
|
|
365
|
+
strong: palettes.gray[400],
|
|
366
|
+
focus: palettes.blue[500], // Using primary color
|
|
367
|
+
disabled: palettes.gray[200],
|
|
368
|
+
},
|
|
369
|
+
interactive: {
|
|
370
|
+
hover: palettes.gray[50],
|
|
371
|
+
pressed: palettes.gray[100],
|
|
372
|
+
focus: palettes.blue[500], // Using primary color
|
|
373
|
+
disabled: palettes.gray[100],
|
|
374
|
+
},
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Helper function to create standard dark theme resolved colors
|
|
380
|
+
*/
|
|
381
|
+
export function createDarkResolvedColors(palettes: ThemeConfig['palettes']): ThemeColorSystem {
|
|
382
|
+
return {
|
|
383
|
+
text: {
|
|
384
|
+
primary: palettes.gray[900], // Light text on dark background
|
|
385
|
+
secondary: palettes.gray[700], // Muted light text
|
|
386
|
+
disabled: palettes.gray[500], // Disabled gray
|
|
387
|
+
inverse: palettes.gray[100], // Dark text (inverse of primary)
|
|
388
|
+
muted: palettes.gray[600], // Muted text
|
|
389
|
+
placeholder: palettes.gray[500], // Placeholder text
|
|
390
|
+
},
|
|
391
|
+
surface: {
|
|
392
|
+
primary: palettes.gray[50], // Very dark primary surface
|
|
393
|
+
secondary: palettes.gray[100], // Dark secondary surface
|
|
394
|
+
tertiary: palettes.gray[200], // Medium dark tertiary surface
|
|
395
|
+
elevated: palettes.gray[100], // Elevated surface (slightly lighter)
|
|
396
|
+
overlay: 'rgba(0, 0, 0, 0.8)', // Dark overlay
|
|
397
|
+
inverse: palettes.gray[900], // Light surface (inverse)
|
|
398
|
+
},
|
|
399
|
+
border: {
|
|
400
|
+
primary: palettes.gray[300], // Primary border
|
|
401
|
+
secondary: palettes.gray[200], // Secondary border
|
|
402
|
+
strong: palettes.gray[400], // Strong border
|
|
403
|
+
focus: palettes.blue[400], // Focus border (primary color)
|
|
404
|
+
disabled: palettes.gray[300], // Disabled border
|
|
405
|
+
},
|
|
406
|
+
interactive: {
|
|
407
|
+
hover: palettes.gray[100], // Hover state
|
|
408
|
+
pressed: palettes.gray[200], // Pressed state
|
|
409
|
+
focus: palettes.blue[400], // Focus state (primary color)
|
|
410
|
+
disabled: palettes.gray[100], // Disabled state
|
|
411
|
+
},
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// Default palettes and convenience functions moved to defaultThemes.ts
|
|
416
|
+
// This keeps the theme builder focused on core functionality
|
|
417
|
+
|
|
418
|
+
// =============================================================================
|
|
419
|
+
// MAIN THEME CREATION FUNCTION
|
|
420
|
+
// =============================================================================
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Creates a theme with fully explicit resolved colors
|
|
424
|
+
* Users must provide actual hex colors, no automatic resolution
|
|
425
|
+
*/
|
|
426
|
+
export function createTheme(config: ThemeConfig): any {
|
|
427
|
+
const {
|
|
428
|
+
name = 'CustomTheme',
|
|
429
|
+
mode = 'light',
|
|
430
|
+
palettes,
|
|
431
|
+
intents,
|
|
432
|
+
colors,
|
|
433
|
+
typography = {},
|
|
434
|
+
spacing = {},
|
|
435
|
+
borderRadius = {},
|
|
436
|
+
shadows = {},
|
|
437
|
+
transitions = {},
|
|
438
|
+
custom = {},
|
|
439
|
+
} = config;
|
|
440
|
+
|
|
441
|
+
// Generate final theme - no automatic color resolution, just organization
|
|
442
|
+
const theme = {
|
|
443
|
+
name,
|
|
444
|
+
mode,
|
|
445
|
+
|
|
446
|
+
// Merge with common properties
|
|
447
|
+
...commonThemeProperties,
|
|
448
|
+
|
|
449
|
+
// Override with custom properties
|
|
450
|
+
...custom,
|
|
451
|
+
|
|
452
|
+
// Typography
|
|
453
|
+
typography: {
|
|
454
|
+
...commonThemeProperties.typography,
|
|
455
|
+
...typography,
|
|
456
|
+
},
|
|
457
|
+
|
|
458
|
+
// Spacing
|
|
459
|
+
spacing: {
|
|
460
|
+
...commonThemeProperties.spacing,
|
|
461
|
+
...spacing,
|
|
462
|
+
},
|
|
463
|
+
|
|
464
|
+
// Border radius
|
|
465
|
+
borderRadius: {
|
|
466
|
+
...commonThemeProperties.borderRadius,
|
|
467
|
+
...borderRadius,
|
|
468
|
+
},
|
|
469
|
+
|
|
470
|
+
// Shadows
|
|
471
|
+
shadows: {
|
|
472
|
+
...commonThemeProperties.shadows,
|
|
473
|
+
...shadows,
|
|
474
|
+
},
|
|
475
|
+
|
|
476
|
+
// Transitions
|
|
477
|
+
transitions: {
|
|
478
|
+
...commonThemeProperties.transitions,
|
|
479
|
+
...transitions,
|
|
480
|
+
},
|
|
481
|
+
|
|
482
|
+
// Color palettes - direct access to all color palettes
|
|
483
|
+
palettes,
|
|
484
|
+
|
|
485
|
+
// Intent system - for actionable components (all resolved)
|
|
486
|
+
intents,
|
|
487
|
+
|
|
488
|
+
// Color system - for display components (all resolved)
|
|
489
|
+
colors: {
|
|
490
|
+
// Provided color system
|
|
491
|
+
...colors,
|
|
492
|
+
|
|
493
|
+
// Status colors (references to intents)
|
|
494
|
+
primary: intents.primary.main,
|
|
495
|
+
success: intents.success.main,
|
|
496
|
+
error: intents.error.main,
|
|
497
|
+
warning: intents.warning.main,
|
|
498
|
+
neutral: intents.neutral.main,
|
|
499
|
+
info: intents.info.main,
|
|
500
|
+
|
|
501
|
+
// Legacy colors for backward compatibility
|
|
502
|
+
background: colors.surface.primary,
|
|
503
|
+
textSecondary: colors.text.secondary,
|
|
504
|
+
secondary: intents.neutral.main,
|
|
505
|
+
},
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
return theme;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// =============================================================================
|
|
512
|
+
// UTILITY FUNCTIONS
|
|
513
|
+
// =============================================================================
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Extends an existing theme with new properties
|
|
517
|
+
*/
|
|
518
|
+
export function extendTheme(baseTheme: any, extensions: {
|
|
519
|
+
palettes?: Partial<ThemeConfig['palettes']>;
|
|
520
|
+
intents?: Partial<ThemeConfig['intents']>;
|
|
521
|
+
colors?: Partial<ThemeColorSystem>;
|
|
522
|
+
typography?: Partial<ThemeConfig['typography']>;
|
|
523
|
+
spacing?: Record<string, number>;
|
|
524
|
+
borderRadius?: Record<string, number>;
|
|
525
|
+
shadows?: Record<string, any>;
|
|
526
|
+
transitions?: Record<string, string>;
|
|
527
|
+
custom?: Record<string, any>;
|
|
528
|
+
}): any {
|
|
529
|
+
return {
|
|
530
|
+
...baseTheme,
|
|
531
|
+
|
|
532
|
+
// Merge palettes
|
|
533
|
+
palettes: {
|
|
534
|
+
...baseTheme.palettes,
|
|
535
|
+
...extensions.palettes,
|
|
536
|
+
},
|
|
537
|
+
|
|
538
|
+
// Merge intents
|
|
539
|
+
intents: {
|
|
540
|
+
...baseTheme.intents,
|
|
541
|
+
...extensions.intents,
|
|
542
|
+
},
|
|
543
|
+
|
|
544
|
+
// Merge colors
|
|
545
|
+
colors: {
|
|
546
|
+
...baseTheme.colors,
|
|
547
|
+
text: {
|
|
548
|
+
...baseTheme.colors.text,
|
|
549
|
+
...extensions.colors?.text,
|
|
550
|
+
},
|
|
551
|
+
surface: {
|
|
552
|
+
...baseTheme.colors.surface,
|
|
553
|
+
...extensions.colors?.surface,
|
|
554
|
+
},
|
|
555
|
+
border: {
|
|
556
|
+
...baseTheme.colors.border,
|
|
557
|
+
...extensions.colors?.border,
|
|
558
|
+
},
|
|
559
|
+
interactive: {
|
|
560
|
+
...baseTheme.colors.interactive,
|
|
561
|
+
...extensions.colors?.interactive,
|
|
562
|
+
},
|
|
563
|
+
},
|
|
564
|
+
|
|
565
|
+
// Merge other properties
|
|
566
|
+
typography: {
|
|
567
|
+
...baseTheme.typography,
|
|
568
|
+
...extensions.typography,
|
|
569
|
+
},
|
|
570
|
+
|
|
571
|
+
spacing: {
|
|
572
|
+
...baseTheme.spacing,
|
|
573
|
+
...extensions.spacing,
|
|
574
|
+
},
|
|
575
|
+
|
|
576
|
+
borderRadius: {
|
|
577
|
+
...baseTheme.borderRadius,
|
|
578
|
+
...extensions.borderRadius,
|
|
579
|
+
},
|
|
580
|
+
|
|
581
|
+
shadows: {
|
|
582
|
+
...baseTheme.shadows,
|
|
583
|
+
...extensions.shadows,
|
|
584
|
+
},
|
|
585
|
+
|
|
586
|
+
transitions: {
|
|
587
|
+
...baseTheme.transitions,
|
|
588
|
+
...extensions.transitions,
|
|
589
|
+
},
|
|
590
|
+
|
|
591
|
+
custom: {
|
|
592
|
+
...baseTheme.custom,
|
|
593
|
+
...extensions.custom,
|
|
594
|
+
},
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// createThemeVariant function removed - users should create themes explicitly
|
|
599
|
+
// using createTheme with the appropriate helper functions like createDarkPalettes(),
|
|
600
|
+
// createDarkIntentMappings(), and createDarkColorMappings() (found in defaultThemes.ts)
|
|
601
|
+
|
|
602
602
|
// All exports are declared inline above
|