@shohojdhara/atomix 0.2.9 → 0.3.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.
Files changed (102) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/atomix.css +309 -105
  3. package/dist/atomix.min.css +3 -5
  4. package/dist/index.d.ts +807 -51
  5. package/dist/index.esm.js +16367 -16405
  6. package/dist/index.esm.js.map +1 -1
  7. package/dist/index.js +16277 -16330
  8. package/dist/index.js.map +1 -1
  9. package/dist/index.min.js +1 -1
  10. package/dist/index.min.js.map +1 -1
  11. package/dist/themes/applemix.css +309 -105
  12. package/dist/themes/applemix.min.css +5 -7
  13. package/dist/themes/boomdevs.css +202 -10
  14. package/dist/themes/boomdevs.min.css +3 -5
  15. package/dist/themes/esrar.css +309 -105
  16. package/dist/themes/esrar.min.css +4 -6
  17. package/dist/themes/flashtrade.css +310 -105
  18. package/dist/themes/flashtrade.min.css +5 -7
  19. package/dist/themes/mashroom.css +300 -96
  20. package/dist/themes/mashroom.min.css +4 -6
  21. package/dist/themes/shaj-default.css +300 -96
  22. package/dist/themes/shaj-default.min.css +4 -6
  23. package/package.json +1 -1
  24. package/src/components/AtomixGlass/AtomixGlass.test.tsx +21 -32
  25. package/src/components/AtomixGlass/AtomixGlass.tsx +55 -42
  26. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +205 -57
  27. package/src/components/AtomixGlass/GlassFilter.tsx +22 -8
  28. package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +221 -0
  29. package/src/components/AtomixGlass/atomixGLass.old.tsx +0 -3
  30. package/src/components/AtomixGlass/shader-utils.ts +8 -0
  31. package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +319 -100
  32. package/src/components/AtomixGlass/stories/Examples.stories.tsx +601 -105
  33. package/src/components/AtomixGlass/stories/Modes.stories.tsx +30 -12
  34. package/src/components/AtomixGlass/stories/Playground.stories.tsx +173 -38
  35. package/src/components/AtomixGlass/stories/ShaderVariants.stories.tsx +18 -18
  36. package/src/components/AtomixGlass/stories/shared-components.tsx +27 -5
  37. package/src/components/Breadcrumb/Breadcrumb.tsx +8 -3
  38. package/src/components/Button/Button.tsx +62 -17
  39. package/src/components/Callout/Callout.test.tsx +8 -14
  40. package/src/components/Card/Card.tsx +103 -1
  41. package/src/components/Card/index.ts +3 -2
  42. package/src/components/Footer/Footer.stories.tsx +1 -2
  43. package/src/components/Footer/Footer.tsx +0 -5
  44. package/src/components/Footer/FooterLink.tsx +3 -2
  45. package/src/components/Footer/FooterSection.tsx +0 -7
  46. package/src/components/Icon/index.ts +1 -1
  47. package/src/components/Modal/Modal.stories.tsx +29 -38
  48. package/src/components/Modal/Modal.tsx +4 -4
  49. package/src/components/Navigation/Nav/NavItem.tsx +8 -3
  50. package/src/components/Navigation/SideMenu/SideMenu.tsx +49 -41
  51. package/src/components/Navigation/SideMenu/SideMenuItem.tsx +63 -19
  52. package/src/components/Popover/Popover.tsx +1 -1
  53. package/src/components/VideoPlayer/VideoPlayer.stories.tsx +977 -400
  54. package/src/components/VideoPlayer/VideoPlayer.tsx +1 -6
  55. package/src/lib/composables/shared-mouse-tracker.ts +133 -0
  56. package/src/lib/composables/useAtomixGlass.ts +303 -115
  57. package/src/lib/theme/ThemeManager.integration.test.ts +124 -0
  58. package/src/lib/theme/ThemeManager.stories.tsx +13 -13
  59. package/src/lib/theme/ThemeManager.test.ts +4 -0
  60. package/src/lib/theme/ThemeManager.ts +203 -59
  61. package/src/lib/theme/ThemeProvider.tsx +183 -33
  62. package/src/lib/theme/composeTheme.ts +375 -0
  63. package/src/lib/theme/createTheme.test.ts +475 -0
  64. package/src/lib/theme/createTheme.ts +510 -0
  65. package/src/lib/theme/generateCSSVariables.ts +713 -0
  66. package/src/lib/theme/index.ts +67 -0
  67. package/src/lib/theme/themeUtils.ts +333 -0
  68. package/src/lib/theme/types.ts +337 -8
  69. package/src/lib/theme/useTheme.test.tsx +2 -1
  70. package/src/lib/theme/useTheme.ts +6 -22
  71. package/src/lib/types/components.ts +152 -57
  72. package/src/styles/01-settings/_index.scss +2 -2
  73. package/src/styles/01-settings/_settings.badge.scss +2 -2
  74. package/src/styles/01-settings/_settings.border-radius.scss +1 -1
  75. package/src/styles/01-settings/{_settings.maps.scss → _settings.design-tokens.scss} +163 -49
  76. package/src/styles/01-settings/_settings.modal.scss +1 -1
  77. package/src/styles/01-settings/_settings.spacing.scss +14 -13
  78. package/src/styles/03-generic/_generic.root.scss +131 -50
  79. package/src/styles/05-objects/_objects.block.scss +1 -1
  80. package/src/styles/06-components/_components.atomix-glass.scss +20 -22
  81. package/src/styles/06-components/_components.badge.scss +2 -2
  82. package/src/styles/06-components/_components.button.scss +1 -1
  83. package/src/styles/06-components/_components.callout.scss +1 -1
  84. package/src/styles/06-components/_components.card.scss +74 -2
  85. package/src/styles/06-components/_components.chart.scss +1 -1
  86. package/src/styles/06-components/_components.dropdown.scss +6 -0
  87. package/src/styles/06-components/_components.footer.scss +1 -1
  88. package/src/styles/06-components/_components.list-group.scss +1 -1
  89. package/src/styles/06-components/_components.list.scss +1 -1
  90. package/src/styles/06-components/_components.menu.scss +1 -1
  91. package/src/styles/06-components/_components.messages.scss +1 -1
  92. package/src/styles/06-components/_components.modal.scss +7 -2
  93. package/src/styles/06-components/_components.navbar.scss +1 -1
  94. package/src/styles/06-components/_components.popover.scss +10 -0
  95. package/src/styles/06-components/_components.product-review.scss +1 -1
  96. package/src/styles/06-components/_components.progress.scss +1 -1
  97. package/src/styles/06-components/_components.rating.scss +1 -1
  98. package/src/styles/06-components/_components.spinner.scss +1 -1
  99. package/src/styles/99-utilities/_utilities.background.scss +1 -1
  100. package/src/styles/99-utilities/_utilities.border.scss +1 -1
  101. package/src/styles/99-utilities/_utilities.link.scss +1 -1
  102. package/src/styles/99-utilities/_utilities.text.scss +1 -1
@@ -0,0 +1,510 @@
1
+ /**
2
+ * createTheme - Create a theme object with computed values
3
+ *
4
+ * Similar to Material-UI's createTheme, this function accepts theme configuration
5
+ * options and returns a complete theme object with computed values.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * const theme = createTheme({
10
+ * palette: {
11
+ * primary: { main: '#7AFFD7' },
12
+ * secondary: { main: '#FF5733' },
13
+ * },
14
+ * typography: {
15
+ * fontFamily: 'Inter, sans-serif',
16
+ * },
17
+ * });
18
+ * ```
19
+ */
20
+
21
+ import type {
22
+ Theme,
23
+ ThemeOptions,
24
+ PaletteColor,
25
+ PaletteOptions,
26
+ TypographyOptions,
27
+ SpacingOptions,
28
+ SpacingFunction,
29
+ BreakpointsOptions,
30
+ ShadowOptions,
31
+ TransitionOptions,
32
+ ZIndexOptions,
33
+ BorderRadiusOptions,
34
+ } from './types';
35
+
36
+ // ============================================================================
37
+ // Default Theme Values
38
+ // ============================================================================
39
+
40
+ const DEFAULT_PALETTE: Theme['palette'] = {
41
+ primary: {
42
+ main: '#7AFFD7',
43
+ light: '#A3FFE5',
44
+ dark: '#00E6C3',
45
+ contrastText: '#000000',
46
+ },
47
+ secondary: {
48
+ main: '#FF5733',
49
+ light: '#FF8A65',
50
+ dark: '#C62828',
51
+ contrastText: '#FFFFFF',
52
+ },
53
+ error: {
54
+ main: '#F44336',
55
+ light: '#E57373',
56
+ dark: '#D32F2F',
57
+ contrastText: '#FFFFFF',
58
+ },
59
+ warning: {
60
+ main: '#FF9800',
61
+ light: '#FFB74D',
62
+ dark: '#F57C00',
63
+ contrastText: '#000000',
64
+ },
65
+ info: {
66
+ main: '#2196F3',
67
+ light: '#64B5F6',
68
+ dark: '#1976D2',
69
+ contrastText: '#FFFFFF',
70
+ },
71
+ success: {
72
+ main: '#4CAF50',
73
+ light: '#81C784',
74
+ dark: '#388E3C',
75
+ contrastText: '#FFFFFF',
76
+ },
77
+ background: {
78
+ default: '#FFFFFF',
79
+ paper: '#F5F5F5',
80
+ subtle: '#FAFAFA',
81
+ },
82
+ text: {
83
+ primary: 'rgba(0, 0, 0, 0.87)',
84
+ secondary: 'rgba(0, 0, 0, 0.6)',
85
+ disabled: 'rgba(0, 0, 0, 0.38)',
86
+ },
87
+ };
88
+
89
+ const DEFAULT_TYPOGRAPHY: Theme['typography'] = {
90
+ fontFamily: '"Inter", "Roboto", "Helvetica", "Arial", sans-serif',
91
+ fontSize: 14,
92
+ fontWeightLight: 300,
93
+ fontWeightRegular: 400,
94
+ fontWeightMedium: 500,
95
+ fontWeightSemiBold: 600,
96
+ fontWeightBold: 700,
97
+ h1: {
98
+ fontSize: '2.5rem',
99
+ fontWeight: 700,
100
+ lineHeight: 1.2,
101
+ letterSpacing: '-0.01562em',
102
+ },
103
+ h2: {
104
+ fontSize: '2rem',
105
+ fontWeight: 700,
106
+ lineHeight: 1.3,
107
+ letterSpacing: '-0.00833em',
108
+ },
109
+ h3: {
110
+ fontSize: '1.75rem',
111
+ fontWeight: 600,
112
+ lineHeight: 1.4,
113
+ letterSpacing: '0em',
114
+ },
115
+ h4: {
116
+ fontSize: '1.5rem',
117
+ fontWeight: 600,
118
+ lineHeight: 1.4,
119
+ letterSpacing: '0.00735em',
120
+ },
121
+ h5: {
122
+ fontSize: '1.25rem',
123
+ fontWeight: 600,
124
+ lineHeight: 1.5,
125
+ letterSpacing: '0em',
126
+ },
127
+ h6: {
128
+ fontSize: '1rem',
129
+ fontWeight: 600,
130
+ lineHeight: 1.6,
131
+ letterSpacing: '0.0075em',
132
+ },
133
+ body1: {
134
+ fontSize: '1rem',
135
+ fontWeight: 400,
136
+ lineHeight: 1.5,
137
+ },
138
+ body2: {
139
+ fontSize: '0.875rem',
140
+ fontWeight: 400,
141
+ lineHeight: 1.43,
142
+ },
143
+ };
144
+
145
+ const DEFAULT_BREAKPOINTS: Theme['breakpoints'] = {
146
+ values: {
147
+ xs: 0,
148
+ sm: 600,
149
+ md: 960,
150
+ lg: 1280,
151
+ xl: 1920,
152
+ },
153
+ unit: 'px',
154
+ up: (key) => {
155
+ const value = typeof key === 'number' ? key : DEFAULT_BREAKPOINTS.values[key] || 0;
156
+ return `@media (min-width:${value}${DEFAULT_BREAKPOINTS.unit})`;
157
+ },
158
+ down: (key) => {
159
+ const value = typeof key === 'number' ? key : DEFAULT_BREAKPOINTS.values[key] || 0;
160
+ return `@media (max-width:${value - 0.05}${DEFAULT_BREAKPOINTS.unit})`;
161
+ },
162
+ between: (start, end) => {
163
+ const startValue = typeof start === 'number' ? start : DEFAULT_BREAKPOINTS.values[start] || 0;
164
+ const endValue = typeof end === 'number' ? end : DEFAULT_BREAKPOINTS.values[end] || 0;
165
+ return `@media (min-width:${startValue}${DEFAULT_BREAKPOINTS.unit}) and (max-width:${endValue - 0.05}${DEFAULT_BREAKPOINTS.unit})`;
166
+ },
167
+ };
168
+
169
+ const DEFAULT_SHADOWS: Theme['shadows'] = {
170
+ xs: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
171
+ sm: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
172
+ md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
173
+ lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
174
+ xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
175
+ inset: 'inset 0 1px 3px 0 rgba(0, 0, 0, 0.1), inset 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
176
+ };
177
+
178
+ const DEFAULT_TRANSITIONS: Theme['transitions'] = {
179
+ duration: {
180
+ shortest: 150,
181
+ shorter: 200,
182
+ short: 250,
183
+ standard: 300,
184
+ complex: 375,
185
+ enteringScreen: 225,
186
+ leavingScreen: 195,
187
+ },
188
+ easing: {
189
+ easeInOut: 'cubic-bezier(0.4, 0, 0.2, 1)',
190
+ easeOut: 'cubic-bezier(0.0, 0, 0.2, 1)',
191
+ easeIn: 'cubic-bezier(0.4, 0, 1, 1)',
192
+ sharp: 'cubic-bezier(0.4, 0, 0.6, 1)',
193
+ },
194
+ };
195
+
196
+ const DEFAULT_ZINDEX: Theme['zIndex'] = {
197
+ mobileStepper: 1000,
198
+ speedDial: 1050,
199
+ appBar: 1020,
200
+ drawer: 1070,
201
+ modal: 1040,
202
+ snackbar: 1080,
203
+ tooltip: 1060,
204
+ };
205
+
206
+ const DEFAULT_BORDER_RADIUS: Theme['borderRadius'] = {
207
+ base: '0.5rem', // 8px (spacing-2)
208
+ sm: '0.25rem', // 4px (spacing-1)
209
+ md: '0.25rem', // 4px (spacing-1)
210
+ lg: '0.625rem', // 10px (spacing-2.5)
211
+ xl: '0.75rem', // 12px (spacing-3)
212
+ xxl: '1rem', // 16px (spacing-4)
213
+ '3xl': '1.5rem', // 24px (spacing-6)
214
+ '4xl': '2rem', // 32px (spacing-8)
215
+ pill: '50rem', // 800px (spacing-200)
216
+ };
217
+
218
+ // ============================================================================
219
+ // Helper Functions
220
+ // ============================================================================
221
+
222
+ /**
223
+ * Deep merge two objects
224
+ */
225
+ function deepMerge<T extends Record<string, any>>(target: T, ...sources: Partial<T>[]): T {
226
+ if (!sources.length) return target;
227
+ const source = sources.shift();
228
+
229
+ if (isObject(target) && isObject(source)) {
230
+ for (const key in source) {
231
+ if (!source.hasOwnProperty(key)) continue;
232
+ const sourceValue = source[key];
233
+ if (isObject(sourceValue)) {
234
+ if (!target[key]) Object.assign(target, { [key]: {} });
235
+ deepMerge(target[key] as any, sourceValue as any);
236
+ } else {
237
+ Object.assign(target, { [key]: sourceValue });
238
+ }
239
+ }
240
+ }
241
+
242
+ return deepMerge(target, ...sources);
243
+ }
244
+
245
+ /**
246
+ * Check if value is an object
247
+ */
248
+ function isObject(item: any): item is Record<string, any> {
249
+ return item && typeof item === 'object' && !Array.isArray(item);
250
+ }
251
+
252
+ /**
253
+ * Convert hex color to RGB
254
+ */
255
+ function hexToRgb(hex: string): { r: number; g: number; b: number } | null {
256
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
257
+ if (!result || !result[1] || !result[2] || !result[3]) {
258
+ return null;
259
+ }
260
+ return {
261
+ r: parseInt(result[1], 16),
262
+ g: parseInt(result[2], 16),
263
+ b: parseInt(result[3], 16),
264
+ };
265
+ }
266
+
267
+ /**
268
+ * Calculate relative luminance
269
+ */
270
+ function getLuminance(color: string): number {
271
+ const rgb = hexToRgb(color);
272
+ if (!rgb) return 0;
273
+
274
+ const { r, g, b } = rgb;
275
+ const [rs, gs, bs] = [r ?? 0, g ?? 0, b ?? 0].map((c) => {
276
+ const val = c / 255;
277
+ return val <= 0.03928 ? val / 12.92 : Math.pow((val + 0.055) / 1.055, 2.4);
278
+ });
279
+
280
+ return 0.2126 * (rs ?? 0) + 0.7152 * (gs ?? 0) + 0.0722 * (bs ?? 0);
281
+ }
282
+
283
+ /**
284
+ * Get contrast text color (black or white) based on background
285
+ */
286
+ function getContrastText(background: string): string {
287
+ const luminance = getLuminance(background);
288
+ return luminance > 0.5 ? '#000000' : '#FFFFFF';
289
+ }
290
+
291
+ /**
292
+ * Lighten a color
293
+ */
294
+ function lighten(color: string, amount: number = 0.2): string {
295
+ const rgb = hexToRgb(color);
296
+ if (!rgb) return color;
297
+
298
+ const { r, g, b } = rgb;
299
+ const lightenValue = (val: number) => Math.min(255, Math.round(val + (255 - val) * amount));
300
+
301
+ const newR = lightenValue(r ?? 0).toString(16).padStart(2, '0');
302
+ const newG = lightenValue(g ?? 0).toString(16).padStart(2, '0');
303
+ const newB = lightenValue(b ?? 0).toString(16).padStart(2, '0');
304
+
305
+ return `#${newR}${newG}${newB}`;
306
+ }
307
+
308
+ /**
309
+ * Darken a color
310
+ */
311
+ function darken(color: string, amount: number = 0.2): string {
312
+ const rgb = hexToRgb(color);
313
+ if (!rgb) return color;
314
+
315
+ const { r, g, b } = rgb;
316
+ const darkenValue = (val: number) => Math.max(0, Math.round(val * (1 - amount)));
317
+
318
+ const newR = darkenValue(r ?? 0).toString(16).padStart(2, '0');
319
+ const newG = darkenValue(g ?? 0).toString(16).padStart(2, '0');
320
+ const newB = darkenValue(b ?? 0).toString(16).padStart(2, '0');
321
+
322
+ return `#${newR}${newG}${newB}`;
323
+ }
324
+
325
+ /**
326
+ * Create a complete palette color from partial configuration
327
+ */
328
+ function createPaletteColor(color: Partial<PaletteColor> | string): PaletteColor {
329
+ if (typeof color === 'string') {
330
+ return {
331
+ main: color,
332
+ light: lighten(color),
333
+ dark: darken(color),
334
+ contrastText: getContrastText(color),
335
+ };
336
+ }
337
+
338
+ return {
339
+ main: color.main || '#000000',
340
+ light: color.light || lighten(color.main || '#000000'),
341
+ dark: color.dark || darken(color.main || '#000000'),
342
+ contrastText: color.contrastText || getContrastText(color.main || '#000000'),
343
+ };
344
+ }
345
+
346
+ /**
347
+ * Create spacing function
348
+ */
349
+ function createSpacing(spacingInput: SpacingOptions = 4): SpacingFunction {
350
+ // If it's already a function, return it
351
+ if (typeof spacingInput === 'function') {
352
+ return spacingInput;
353
+ }
354
+
355
+ // If it's a number, create a function that multiplies by that number
356
+ if (typeof spacingInput === 'number') {
357
+ return (...values: number[]) => {
358
+ if (values.length === 0) return '0px';
359
+ return values.map((value) => `${value * spacingInput}px`).join(' ');
360
+ };
361
+ }
362
+
363
+ // If it's an array, use it as a scale
364
+ if (Array.isArray(spacingInput)) {
365
+ return (...values: number[]) => {
366
+ if (values.length === 0) return '0px';
367
+ return values.map((value) => `${spacingInput[value] || value}px`).join(' ');
368
+ };
369
+ }
370
+
371
+ // Default to 4px base
372
+ return (...values: number[]) => {
373
+ if (values.length === 0) return '0px';
374
+ return values.map((value) => `${value * 4}px`).join(' ');
375
+ };
376
+ }
377
+
378
+ /**
379
+ * Create breakpoints object
380
+ */
381
+ function createBreakpoints(breakpointsInput?: BreakpointsOptions): Theme['breakpoints'] {
382
+ const values = {
383
+ xs: 0,
384
+ sm: 600,
385
+ md: 960,
386
+ lg: 1280,
387
+ xl: 1920,
388
+ ...breakpointsInput?.values,
389
+ };
390
+
391
+ const unit = breakpointsInput?.unit || 'px';
392
+
393
+ return {
394
+ values,
395
+ unit,
396
+ up: (key) => {
397
+ const value = typeof key === 'number' ? key : (values[key as keyof typeof values] ?? 0);
398
+ return `@media (min-width:${value}${unit})`;
399
+ },
400
+ down: (key) => {
401
+ const value = typeof key === 'number' ? key : (values[key as keyof typeof values] ?? 0);
402
+ return `@media (max-width:${value - 0.05}${unit})`;
403
+ },
404
+ between: (start, end) => {
405
+ const startValue = typeof start === 'number' ? start : (values[start as keyof typeof values] ?? 0);
406
+ const endValue = typeof end === 'number' ? end : (values[end as keyof typeof values] ?? 0);
407
+ return `@media (min-width:${startValue}${unit}) and (max-width:${endValue - 0.05}${unit})`;
408
+ },
409
+ };
410
+ }
411
+
412
+ // ============================================================================
413
+ // Main createTheme Function
414
+ // ============================================================================
415
+
416
+ /**
417
+ * Create a theme object with computed values
418
+ *
419
+ * @param options - Theme configuration options
420
+ * @returns Complete theme object
421
+ */
422
+ export function createTheme(...options: ThemeOptions[]): Theme {
423
+ // Merge all options
424
+ const mergedOptions = options.reduce((acc, option) => deepMerge(acc, option), {} as ThemeOptions);
425
+
426
+ // Create palette
427
+ const palette: Theme['palette'] = {
428
+ primary: createPaletteColor(mergedOptions.palette?.primary || DEFAULT_PALETTE.primary),
429
+ secondary: createPaletteColor(mergedOptions.palette?.secondary || DEFAULT_PALETTE.secondary),
430
+ error: createPaletteColor(mergedOptions.palette?.error || DEFAULT_PALETTE.error),
431
+ warning: createPaletteColor(mergedOptions.palette?.warning || DEFAULT_PALETTE.warning),
432
+ info: createPaletteColor(mergedOptions.palette?.info || DEFAULT_PALETTE.info),
433
+ success: createPaletteColor(mergedOptions.palette?.success || DEFAULT_PALETTE.success),
434
+ background: {
435
+ default: mergedOptions.palette?.background?.default || DEFAULT_PALETTE.background.default,
436
+ paper: mergedOptions.palette?.background?.paper || DEFAULT_PALETTE.background.paper,
437
+ subtle: mergedOptions.palette?.background?.subtle || DEFAULT_PALETTE.background.subtle,
438
+ },
439
+ text: {
440
+ primary: mergedOptions.palette?.text?.primary || DEFAULT_PALETTE.text.primary,
441
+ secondary: mergedOptions.palette?.text?.secondary || DEFAULT_PALETTE.text.secondary,
442
+ disabled: mergedOptions.palette?.text?.disabled || DEFAULT_PALETTE.text.disabled,
443
+ },
444
+ };
445
+
446
+ // Create typography
447
+ const typography: Theme['typography'] = deepMerge(
448
+ { ...DEFAULT_TYPOGRAPHY } as any,
449
+ (mergedOptions.typography || {}) as any
450
+ ) as Theme['typography'];
451
+
452
+ // Create spacing
453
+ const spacing = createSpacing(mergedOptions.spacing);
454
+
455
+ // Create breakpoints
456
+ const breakpoints = createBreakpoints(mergedOptions.breakpoints);
457
+
458
+ // Create shadows
459
+ const shadows: Theme['shadows'] = deepMerge({ ...DEFAULT_SHADOWS }, mergedOptions.shadows || {});
460
+
461
+ // Create transitions
462
+ const transitions: Theme['transitions'] = deepMerge(
463
+ { ...DEFAULT_TRANSITIONS },
464
+ mergedOptions.transitions || {}
465
+ );
466
+
467
+ // Create z-index
468
+ const zIndex: Theme['zIndex'] = deepMerge({ ...DEFAULT_ZINDEX }, mergedOptions.zIndex || {});
469
+
470
+ // Create border radius
471
+ const borderRadius: Theme['borderRadius'] = deepMerge(
472
+ { ...DEFAULT_BORDER_RADIUS },
473
+ mergedOptions.borderRadius || {}
474
+ );
475
+
476
+ // Create theme object
477
+ const theme: Theme = {
478
+ // Metadata
479
+ name: mergedOptions.name || 'Custom Theme',
480
+ class: mergedOptions.class,
481
+ description: mergedOptions.description,
482
+ author: mergedOptions.author,
483
+ version: mergedOptions.version || '1.0.0',
484
+ tags: mergedOptions.tags,
485
+ supportsDarkMode: mergedOptions.supportsDarkMode,
486
+ status: mergedOptions.status || 'experimental',
487
+ a11y: mergedOptions.a11y,
488
+ color: mergedOptions.color || palette.primary.main,
489
+ features: mergedOptions.features,
490
+ dependencies: mergedOptions.dependencies,
491
+
492
+ // Theme configuration
493
+ palette,
494
+ typography,
495
+ spacing,
496
+ breakpoints,
497
+ shadows,
498
+ transitions,
499
+ zIndex,
500
+ borderRadius,
501
+ custom: mergedOptions.custom || {},
502
+
503
+ // Mark as JS theme
504
+ __isJSTheme: true,
505
+ };
506
+
507
+ return theme;
508
+ }
509
+
510
+ export default createTheme;