@rakeyshgidwani/roger-ui-bank-theme-stan-design 0.1.4 → 0.1.6

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 (164) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/dist/index.d.ts +131 -131
  3. package/dist/index.esm.js +148 -148
  4. package/dist/index.js +148 -148
  5. package/dist/styles.css +1 -1
  6. package/package.json +1 -1
  7. package/src/components/ui/accessibility-demo.tsx +271 -0
  8. package/src/components/ui/advanced-component-architecture-demo.tsx +916 -0
  9. package/src/components/ui/advanced-transition-system-demo.tsx +670 -0
  10. package/src/components/ui/advanced-transition-system.tsx +395 -0
  11. package/src/components/ui/animation/animated-container.tsx +166 -0
  12. package/src/components/ui/animation/index.ts +19 -0
  13. package/src/components/ui/animation/staggered-container.tsx +68 -0
  14. package/src/components/ui/animation-demo.tsx +250 -0
  15. package/src/components/ui/badge.tsx +33 -0
  16. package/src/components/ui/battery-conscious-animation-demo.tsx +568 -0
  17. package/src/components/ui/border-radius-shadow-demo.tsx +187 -0
  18. package/src/components/ui/button.tsx +36 -0
  19. package/src/components/ui/card.tsx +207 -0
  20. package/src/components/ui/checkbox.tsx +30 -0
  21. package/src/components/ui/color-preview.tsx +411 -0
  22. package/src/components/ui/data-display/chart.tsx +653 -0
  23. package/src/components/ui/data-display/data-grid-simple.tsx +76 -0
  24. package/src/components/ui/data-display/data-grid.tsx +680 -0
  25. package/src/components/ui/data-display/list.tsx +456 -0
  26. package/src/components/ui/data-display/table.tsx +482 -0
  27. package/src/components/ui/data-display/timeline.tsx +441 -0
  28. package/src/components/ui/data-display/tree.tsx +602 -0
  29. package/src/components/ui/data-display/types.ts +536 -0
  30. package/src/components/ui/enterprise-mobile-experience-demo.tsx +749 -0
  31. package/src/components/ui/enterprise-mobile-experience.tsx +464 -0
  32. package/src/components/ui/feedback/alert.tsx +157 -0
  33. package/src/components/ui/feedback/progress.tsx +292 -0
  34. package/src/components/ui/feedback/skeleton.tsx +185 -0
  35. package/src/components/ui/feedback/toast.tsx +280 -0
  36. package/src/components/ui/feedback/types.ts +125 -0
  37. package/src/components/ui/font-preview.tsx +288 -0
  38. package/src/components/ui/form-demo.tsx +553 -0
  39. package/src/components/ui/hardware-acceleration-demo.tsx +547 -0
  40. package/src/components/ui/input.tsx +35 -0
  41. package/src/components/ui/label.tsx +16 -0
  42. package/src/components/ui/layout-demo.tsx +367 -0
  43. package/src/components/ui/layouts/adaptive-layout.tsx +139 -0
  44. package/src/components/ui/layouts/desktop-layout.tsx +224 -0
  45. package/src/components/ui/layouts/index.ts +10 -0
  46. package/src/components/ui/layouts/mobile-layout.tsx +162 -0
  47. package/src/components/ui/layouts/tablet-layout.tsx +197 -0
  48. package/src/components/ui/mobile-form-validation.tsx +451 -0
  49. package/src/components/ui/mobile-input-demo.tsx +201 -0
  50. package/src/components/ui/mobile-input.tsx +281 -0
  51. package/src/components/ui/mobile-skeleton-loading-demo.tsx +638 -0
  52. package/src/components/ui/navigation/breadcrumb.tsx +158 -0
  53. package/src/components/ui/navigation/index.ts +36 -0
  54. package/src/components/ui/navigation/menu.tsx +374 -0
  55. package/src/components/ui/navigation/navigation-demo.tsx +324 -0
  56. package/src/components/ui/navigation/pagination.tsx +272 -0
  57. package/src/components/ui/navigation/sidebar.tsx +383 -0
  58. package/src/components/ui/navigation/stepper.tsx +303 -0
  59. package/src/components/ui/navigation/tabs.tsx +205 -0
  60. package/src/components/ui/navigation/types.ts +299 -0
  61. package/src/components/ui/overlay/backdrop.tsx +81 -0
  62. package/src/components/ui/overlay/focus-manager.tsx +143 -0
  63. package/src/components/ui/overlay/index.ts +36 -0
  64. package/src/components/ui/overlay/modal.tsx +270 -0
  65. package/src/components/ui/overlay/overlay-manager.tsx +110 -0
  66. package/src/components/ui/overlay/popover.tsx +462 -0
  67. package/src/components/ui/overlay/portal.tsx +79 -0
  68. package/src/components/ui/overlay/tooltip.tsx +303 -0
  69. package/src/components/ui/overlay/types.ts +196 -0
  70. package/src/components/ui/performance-demo.tsx +596 -0
  71. package/src/components/ui/semantic-input-system-demo.tsx +502 -0
  72. package/src/components/ui/semantic-input-system-demo.tsx.disabled +873 -0
  73. package/src/components/ui/tablet-layout.tsx +192 -0
  74. package/src/components/ui/theme-customizer.tsx +386 -0
  75. package/src/components/ui/theme-preview.tsx +310 -0
  76. package/src/components/ui/theme-switcher.tsx +264 -0
  77. package/src/components/ui/theme-toggle.tsx +38 -0
  78. package/src/components/ui/token-demo.tsx +195 -0
  79. package/src/components/ui/touch-demo.tsx +462 -0
  80. package/src/components/ui/touch-friendly-interface-demo.tsx +519 -0
  81. package/src/components/ui/touch-friendly-interface.tsx +296 -0
  82. package/src/hooks/index.ts +190 -0
  83. package/src/hooks/use-accessibility-support.ts +518 -0
  84. package/src/hooks/use-adaptive-layout.ts +289 -0
  85. package/src/hooks/use-advanced-patterns.ts +294 -0
  86. package/src/hooks/use-advanced-transition-system.ts +393 -0
  87. package/src/hooks/use-animation-profile.ts +288 -0
  88. package/src/hooks/use-battery-animations.ts +384 -0
  89. package/src/hooks/use-battery-conscious-loading.ts +475 -0
  90. package/src/hooks/use-battery-optimization.ts +330 -0
  91. package/src/hooks/use-battery-status.ts +299 -0
  92. package/src/hooks/use-component-performance.ts +344 -0
  93. package/src/hooks/use-device-loading-states.ts +459 -0
  94. package/src/hooks/use-device.tsx +110 -0
  95. package/src/hooks/use-enterprise-mobile-experience.ts +488 -0
  96. package/src/hooks/use-form-feedback.ts +403 -0
  97. package/src/hooks/use-form-performance.ts +513 -0
  98. package/src/hooks/use-frame-rate.ts +251 -0
  99. package/src/hooks/use-gestures.ts +338 -0
  100. package/src/hooks/use-hardware-acceleration.ts +341 -0
  101. package/src/hooks/use-input-accessibility.ts +455 -0
  102. package/src/hooks/use-input-performance.ts +506 -0
  103. package/src/hooks/use-layout-performance.ts +319 -0
  104. package/src/hooks/use-loading-accessibility.ts +535 -0
  105. package/src/hooks/use-loading-performance.ts +473 -0
  106. package/src/hooks/use-memory-usage.ts +287 -0
  107. package/src/hooks/use-mobile-form-layout.ts +464 -0
  108. package/src/hooks/use-mobile-form-validation.ts +518 -0
  109. package/src/hooks/use-mobile-keyboard-optimization.ts +472 -0
  110. package/src/hooks/use-mobile-layout.ts +302 -0
  111. package/src/hooks/use-mobile-optimization.ts +406 -0
  112. package/src/hooks/use-mobile-skeleton.ts +402 -0
  113. package/src/hooks/use-mobile-touch.ts +414 -0
  114. package/src/hooks/use-performance-throttling.ts +348 -0
  115. package/src/hooks/use-performance.ts +316 -0
  116. package/src/hooks/use-reusable-architecture.ts +414 -0
  117. package/src/hooks/use-semantic-input-types.ts +357 -0
  118. package/src/hooks/use-semantic-input.ts +565 -0
  119. package/src/hooks/use-tablet-layout.ts +384 -0
  120. package/src/hooks/use-touch-friendly-input.ts +524 -0
  121. package/src/hooks/use-touch-friendly-interface.ts +331 -0
  122. package/src/hooks/use-touch-optimization.ts +375 -0
  123. package/src/index.ts +279 -279
  124. package/src/lib/utils.ts +6 -0
  125. package/src/themes/README.md +272 -0
  126. package/src/themes/ThemeContext.tsx +31 -0
  127. package/src/themes/ThemeProvider.tsx +232 -0
  128. package/src/themes/accessibility/index.ts +27 -0
  129. package/src/themes/accessibility.ts +259 -0
  130. package/src/themes/aria-patterns.ts +420 -0
  131. package/src/themes/base-themes.ts +55 -0
  132. package/src/themes/colorManager.ts +380 -0
  133. package/src/themes/examples/dark-theme.ts +154 -0
  134. package/src/themes/examples/minimal-theme.ts +108 -0
  135. package/src/themes/focus-management.ts +701 -0
  136. package/src/themes/fontLoader.ts +201 -0
  137. package/src/themes/high-contrast.ts +621 -0
  138. package/src/themes/index.ts +19 -0
  139. package/src/themes/inheritance.ts +227 -0
  140. package/src/themes/keyboard-navigation.ts +550 -0
  141. package/src/themes/motion-reduction.ts +662 -0
  142. package/src/themes/navigation.ts +238 -0
  143. package/src/themes/screen-reader.ts +645 -0
  144. package/src/themes/systemThemeDetector.ts +182 -0
  145. package/src/themes/themeCSSUpdater.ts +262 -0
  146. package/src/themes/themePersistence.ts +238 -0
  147. package/src/themes/themes/default.ts +586 -0
  148. package/src/themes/themes/harvey.ts +554 -0
  149. package/src/themes/themes/stan-design.ts +683 -0
  150. package/src/themes/types.ts +460 -0
  151. package/src/themes/useSystemTheme.ts +48 -0
  152. package/src/themes/useTheme.ts +87 -0
  153. package/src/themes/validation.ts +462 -0
  154. package/src/tokens/index.ts +34 -0
  155. package/src/tokens/tokenExporter.ts +397 -0
  156. package/src/tokens/tokenGenerator.ts +276 -0
  157. package/src/tokens/tokenManager.ts +248 -0
  158. package/src/tokens/tokenValidator.ts +543 -0
  159. package/src/tokens/types.ts +78 -0
  160. package/src/utils/bundle-analyzer.ts +260 -0
  161. package/src/utils/bundle-splitting.ts +483 -0
  162. package/src/utils/lazy-loading.ts +441 -0
  163. package/src/utils/performance-monitor.ts +513 -0
  164. package/src/utils/tree-shaking.ts +274 -0
@@ -0,0 +1,192 @@
1
+ import * as React from "react"
2
+ import { cn } from "../../lib/utils"
3
+ import { useDevice } from "../../hooks/use-device"
4
+
5
+ interface TabletLayoutProps {
6
+ children: React.ReactNode
7
+ className?: string
8
+ orientation?: 'auto' | 'portrait' | 'landscape'
9
+ adaptive?: boolean
10
+ }
11
+
12
+ /**
13
+ * Tablet-optimized layout container that adapts to orientation changes
14
+ * Provides optimal layouts for both portrait and landscape tablet modes
15
+ */
16
+ export const TabletLayout: React.FC<TabletLayoutProps> = ({
17
+ children,
18
+ className,
19
+ orientation = 'auto',
20
+ adaptive = true
21
+ }) => {
22
+ const device = useDevice()
23
+
24
+ const getLayoutClasses = () => {
25
+ const classes = ['coach-stan-tablet-layout']
26
+
27
+ // Add device-specific classes
28
+ if (device.isTablet) {
29
+ classes.push('tablet-optimized')
30
+
31
+ // Handle orientation-specific layouts
32
+ const targetOrientation = orientation === 'auto' ? device.orientation : orientation
33
+ classes.push(`orientation-${targetOrientation}`)
34
+
35
+ if (adaptive) {
36
+ classes.push('adaptive-layout')
37
+ }
38
+ }
39
+
40
+ return classes
41
+ }
42
+
43
+ return (
44
+ <div className={cn(getLayoutClasses(), className)}>
45
+ {children}
46
+ </div>
47
+ )
48
+ }
49
+
50
+ interface TabletGridProps {
51
+ children: React.ReactNode
52
+ columns?: {
53
+ portrait: number
54
+ landscape: number
55
+ }
56
+ gap?: string
57
+ className?: string
58
+ }
59
+
60
+ /**
61
+ * Responsive grid component optimized for tablet orientations
62
+ */
63
+ export const TabletGrid: React.FC<TabletGridProps> = ({
64
+ children,
65
+ columns = { portrait: 1, landscape: 2 },
66
+ gap = '1rem',
67
+ className
68
+ }) => {
69
+ const device = useDevice()
70
+
71
+ const gridStyle: React.CSSProperties = {
72
+ display: 'grid',
73
+ gap,
74
+ gridTemplateColumns: device.orientation === 'portrait'
75
+ ? `repeat(${columns.portrait}, 1fr)`
76
+ : `repeat(${columns.landscape}, 1fr)`
77
+ }
78
+
79
+ return (
80
+ <div
81
+ className={cn('coach-stan-tablet-grid', className)}
82
+ style={gridStyle}
83
+ >
84
+ {children}
85
+ </div>
86
+ )
87
+ }
88
+
89
+ interface TabletSidebarProps {
90
+ children: React.ReactNode
91
+ side?: 'left' | 'right'
92
+ collapsible?: boolean
93
+ width?: string
94
+ className?: string
95
+ }
96
+
97
+ /**
98
+ * Tablet-optimized sidebar that adapts to orientation
99
+ * In portrait mode, sidebar can collapse or stack vertically
100
+ */
101
+ export const TabletSidebar: React.FC<TabletSidebarProps> = ({
102
+ children,
103
+ side = 'left',
104
+ collapsible = false,
105
+ width = '280px',
106
+ className
107
+ }) => {
108
+ const device = useDevice()
109
+
110
+ const getSidebarClasses = () => {
111
+ const classes = ['coach-stan-tablet-sidebar']
112
+
113
+ if (device.isTablet) {
114
+ classes.push('tablet-optimized')
115
+
116
+ if (device.orientation === 'portrait') {
117
+ classes.push('orientation-portrait')
118
+ } else {
119
+ classes.push('orientation-landscape')
120
+ }
121
+ }
122
+
123
+ if (side === 'right') {
124
+ classes.push('sidebar-right')
125
+ }
126
+
127
+ return classes
128
+ }
129
+
130
+ const sidebarStyle: React.CSSProperties = {
131
+ width: device.orientation === 'portrait' && collapsible ? '60px' : width,
132
+ transition: 'width 0.3s ease'
133
+ }
134
+
135
+ return (
136
+ <div
137
+ className={cn(getSidebarClasses(), className)}
138
+ style={sidebarStyle}
139
+ >
140
+ {children}
141
+ </div>
142
+ )
143
+ }
144
+
145
+ interface TabletStackProps {
146
+ children: React.ReactNode
147
+ direction?: 'auto' | 'horizontal' | 'vertical'
148
+ className?: string
149
+ }
150
+
151
+ /**
152
+ * Responsive stack component that adapts to tablet orientation
153
+ */
154
+ export const TabletStack: React.FC<TabletStackProps> = ({
155
+ children,
156
+ direction = 'auto',
157
+ className
158
+ }) => {
159
+ const device = useDevice()
160
+
161
+ const getStackClasses = () => {
162
+ const classes = ['coach-stan-tablet-stack']
163
+
164
+ if (device.isTablet) {
165
+ classes.push('tablet-optimized')
166
+
167
+ const targetDirection = direction === 'auto'
168
+ ? (device.orientation === 'portrait' ? 'vertical' : 'horizontal')
169
+ : direction
170
+
171
+ classes.push(`stack-${targetDirection}`)
172
+ }
173
+
174
+ return classes
175
+ }
176
+
177
+ const stackStyle: React.CSSProperties = {
178
+ display: 'flex',
179
+ flexDirection: device.orientation === 'portrait' ? 'column' : 'row',
180
+ gap: device.orientation === 'portrait' ? '1rem' : '1.5rem',
181
+ transition: 'flex-direction 0.3s ease'
182
+ }
183
+
184
+ return (
185
+ <div
186
+ className={cn(getStackClasses(), className)}
187
+ style={stackStyle}
188
+ >
189
+ {children}
190
+ </div>
191
+ )
192
+ }
@@ -0,0 +1,386 @@
1
+ import React, { useState, useCallback, useEffect } from 'react';
2
+ import { useTheme } from '../../themes';
3
+ import { Card, CardContent, CardHeader, CardTitle } from './card';
4
+ import { Button } from './button';
5
+ import { Input } from './input';
6
+ import { ThemePreview } from './theme-preview';
7
+ import type { CompleteThemeConfig } from '../../themes/types';
8
+
9
+ export interface ThemeCustomizerProps {
10
+ initialTheme?: string;
11
+ onThemeChange?: (theme: CompleteThemeConfig) => void;
12
+ showPreview?: boolean;
13
+ allowCustomization?: boolean;
14
+ className?: string;
15
+ }
16
+
17
+ export interface CustomizationState {
18
+ colors: {
19
+ primary: string;
20
+ secondary: string;
21
+ };
22
+ fonts: {
23
+ primary: string;
24
+ secondary: string;
25
+ };
26
+ spacing: {
27
+ scale: number;
28
+ };
29
+ shadows: {
30
+ intensity: number;
31
+ };
32
+ }
33
+
34
+ export const ThemeCustomizer: React.FC<ThemeCustomizerProps> = ({
35
+ initialTheme = 'stan-design',
36
+ onThemeChange,
37
+ showPreview = true,
38
+ allowCustomization = true,
39
+ className = ''
40
+ }) => {
41
+ const { getTheme } = useTheme();
42
+ const [customizationState, setCustomizationState] = useState<CustomizationState>({
43
+ colors: {
44
+ primary: '#3b82f6',
45
+ secondary: '#10b981'
46
+ },
47
+ fonts: {
48
+ primary: 'Inter',
49
+ secondary: 'Roboto'
50
+ },
51
+ spacing: {
52
+ scale: 1.25
53
+ },
54
+ shadows: {
55
+ intensity: 0.1
56
+ }
57
+ });
58
+
59
+ const [activeTab, setActiveTab] = useState<'colors' | 'fonts' | 'spacing' | 'shadows' | 'preview'>('colors');
60
+ const [customTheme, setCustomTheme] = useState<CompleteThemeConfig | null>(null);
61
+
62
+ // Initialize with the initial theme
63
+ useEffect(() => {
64
+ const theme = getTheme(initialTheme);
65
+ if (theme) {
66
+ setCustomTheme(theme);
67
+ }
68
+ }, [initialTheme]); // Removed getTheme from dependencies as it's stable
69
+
70
+ const handleCustomizationChange = useCallback((key: keyof CustomizationState, subKey: string, value: any) => {
71
+ setCustomizationState(prev => ({
72
+ ...prev,
73
+ [key]: {
74
+ ...prev[key],
75
+ [subKey]: value
76
+ }
77
+ }));
78
+ }, []);
79
+
80
+ const generateCustomTheme = useCallback(() => {
81
+ if (!customTheme) return;
82
+
83
+ // Create a deep copy of the current theme
84
+ const newTheme: CompleteThemeConfig = JSON.parse(JSON.stringify(customTheme));
85
+
86
+ // Apply customizations
87
+ // Generate color scales based on the selected primary color
88
+ const primaryColor = customizationState.colors.primary;
89
+ const secondaryColor = customizationState.colors.secondary;
90
+
91
+ // Simple color scale generation (in a real app, you'd use a color library)
92
+ const generateColorScale = (baseColor: string) => {
93
+ return {
94
+ 50: `${baseColor}0a`,
95
+ 100: `${baseColor}1a`,
96
+ 200: `${baseColor}33`,
97
+ 300: `${baseColor}4d`,
98
+ 400: `${baseColor}66`,
99
+ 500: baseColor,
100
+ 600: `${baseColor}99`,
101
+ 700: `${baseColor}b3`,
102
+ 800: `${baseColor}cc`,
103
+ 900: `${baseColor}e6`
104
+ };
105
+ };
106
+
107
+ // Update primary colors
108
+ newTheme.colors.primary = generateColorScale(primaryColor);
109
+
110
+ // Update secondary colors if they exist
111
+ if (newTheme.colors.secondary) {
112
+ newTheme.colors.secondary = generateColorScale(secondaryColor);
113
+ }
114
+
115
+ // Update fonts
116
+ if (newTheme.fonts.primary) {
117
+ newTheme.fonts.primary.family = customizationState.fonts.primary;
118
+ }
119
+ if (newTheme.fonts.secondary) {
120
+ newTheme.fonts.secondary.family = customizationState.fonts.secondary;
121
+ }
122
+
123
+ // Update spacing scale (we'll adjust the existing scale)
124
+ if (newTheme.spacing && newTheme.spacing.scale) {
125
+ // This is a simplified approach - in reality you'd want to recalculate all spacing values
126
+ // For now, we'll just note that the scale factor has changed
127
+ console.log('Spacing scale factor updated to:', customizationState.spacing.scale);
128
+ }
129
+
130
+ // Update shadow intensity (we'll adjust the existing shadows)
131
+ if (newTheme.shadows) {
132
+ // This is a simplified approach - in reality you'd want to recalculate all shadow values
133
+ // For now, we'll just note that the intensity has changed
134
+ console.log('Shadow intensity updated to:', customizationState.shadows.intensity);
135
+ }
136
+
137
+ setCustomTheme(newTheme);
138
+
139
+ if (onThemeChange) {
140
+ onThemeChange(newTheme);
141
+ }
142
+ }, [customTheme, customizationState, onThemeChange]);
143
+
144
+ const exportTheme = useCallback(() => {
145
+ if (!customTheme) return;
146
+
147
+ const themeData = JSON.stringify(customTheme, null, 2);
148
+ const blob = new Blob([themeData], { type: 'application/json' });
149
+ const url = URL.createObjectURL(blob);
150
+ const a = document.createElement('a');
151
+ a.href = url;
152
+ a.download = `${customTheme.meta.name.toLowerCase().replace(/\s+/g, '-')}-theme.json`;
153
+ document.body.appendChild(a);
154
+ a.click();
155
+ document.body.removeChild(a);
156
+ URL.revokeObjectURL(url);
157
+ }, [customTheme]);
158
+
159
+ const resetTheme = useCallback(() => {
160
+ const originalTheme = getTheme(initialTheme);
161
+ if (originalTheme) {
162
+ setCustomTheme(originalTheme);
163
+ setCustomizationState({
164
+ colors: {
165
+ primary: '#3b82f6',
166
+ secondary: '#10b981'
167
+ },
168
+ fonts: {
169
+ primary: 'Inter',
170
+ secondary: 'Roboto'
171
+ },
172
+ spacing: {
173
+ scale: 1.25
174
+ },
175
+ shadows: {
176
+ intensity: 0.1
177
+ }
178
+ });
179
+ }
180
+ }, [initialTheme, getTheme]);
181
+
182
+ if (!customTheme) {
183
+ return (
184
+ <div className={`p-4 text-center text-gray-500 ${className}`}>
185
+ Loading theme...
186
+ </div>
187
+ );
188
+ }
189
+
190
+ return (
191
+ <div className={`theme-customizer ${className}`}>
192
+ <Card>
193
+ <CardHeader>
194
+ <CardTitle className="flex items-center gap-2">
195
+ 🎨 Theme Customizer
196
+ </CardTitle>
197
+ <p className="text-sm text-gray-600 dark:text-gray-400">
198
+ Customize and preview themes in real-time
199
+ </p>
200
+ </CardHeader>
201
+ <CardContent>
202
+ {/* Tab Navigation */}
203
+ <div className="flex space-x-1 mb-6 border-b">
204
+ {allowCustomization && (
205
+ <>
206
+ <Button
207
+ variant={activeTab === 'colors' ? 'default' : 'ghost'}
208
+ size="sm"
209
+ onClick={() => setActiveTab('colors')}
210
+ >
211
+ Colors
212
+ </Button>
213
+ <Button
214
+ variant={activeTab === 'fonts' ? 'default' : 'ghost'}
215
+ size="sm"
216
+ onClick={() => setActiveTab('fonts')}
217
+ >
218
+ Fonts
219
+ </Button>
220
+ <Button
221
+ variant={activeTab === 'spacing' ? 'default' : 'ghost'}
222
+ size="sm"
223
+ onClick={() => setActiveTab('spacing')}
224
+ >
225
+ Spacing
226
+ </Button>
227
+ <Button
228
+ variant={activeTab === 'shadows' ? 'default' : 'ghost'}
229
+ size="sm"
230
+ onClick={() => setActiveTab('shadows')}
231
+ >
232
+ Shadows
233
+ </Button>
234
+ </>
235
+ )}
236
+ {showPreview && (
237
+ <Button
238
+ variant={activeTab === 'preview' ? 'default' : 'ghost'}
239
+ size="sm"
240
+ onClick={() => setActiveTab('preview')}
241
+ >
242
+ Preview
243
+ </Button>
244
+ )}
245
+ </div>
246
+
247
+ {/* Tab Content */}
248
+ <div className="min-h-[400px]">
249
+ {activeTab === 'colors' && allowCustomization && (
250
+ <div className="space-y-4">
251
+ <h3 className="text-lg font-semibold">Color Customization</h3>
252
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
253
+ <div>
254
+ <label className="block text-sm font-medium mb-2">Primary Color</label>
255
+ <Input
256
+ type="color"
257
+ value={customizationState.colors.primary}
258
+ onChange={(e) => handleCustomizationChange('colors', 'primary', e.target.value)}
259
+ className="w-full h-12"
260
+ />
261
+ <Input
262
+ type="text"
263
+ value={customizationState.colors.primary}
264
+ onChange={(e) => handleCustomizationChange('colors', 'primary', e.target.value)}
265
+ placeholder="#3b82f6"
266
+ className="mt-2"
267
+ />
268
+ </div>
269
+ <div>
270
+ <label className="block text-sm font-medium mb-2">Secondary Color</label>
271
+ <Input
272
+ type="color"
273
+ value={customizationState.colors.secondary}
274
+ onChange={(e) => handleCustomizationChange('colors', 'secondary', e.target.value)}
275
+ className="w-full h-12"
276
+ />
277
+ <Input
278
+ type="text"
279
+ value={customizationState.colors.secondary}
280
+ onChange={(e) => handleCustomizationChange('colors', 'secondary', e.target.value)}
281
+ placeholder="#10b981"
282
+ className="mt-2"
283
+ />
284
+ </div>
285
+
286
+ </div>
287
+ </div>
288
+ )}
289
+
290
+ {activeTab === 'fonts' && allowCustomization && (
291
+ <div className="space-y-4">
292
+ <h3 className="text-lg font-semibold">Font Customization</h3>
293
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
294
+ <div>
295
+ <label className="block text-sm font-medium mb-2">Primary Font</label>
296
+ <Input
297
+ value={customizationState.fonts.primary}
298
+ onChange={(e) => handleCustomizationChange('fonts', 'primary', e.target.value)}
299
+ placeholder="Inter"
300
+ />
301
+ </div>
302
+ <div>
303
+ <label className="block text-sm font-medium mb-2">Secondary Font</label>
304
+ <Input
305
+ value={customizationState.fonts.secondary}
306
+ onChange={(e) => handleCustomizationChange('fonts', 'secondary', e.target.value)}
307
+ placeholder="Roboto"
308
+ />
309
+ </div>
310
+ </div>
311
+ </div>
312
+ )}
313
+
314
+ {activeTab === 'spacing' && allowCustomization && (
315
+ <div className="space-y-4">
316
+ <h3 className="text-lg font-semibold">Spacing Customization</h3>
317
+ <div className="grid grid-cols-1 gap-4">
318
+ <div>
319
+ <label className="block text-sm font-medium mb-2">Scale Factor</label>
320
+ <Input
321
+ type="number"
322
+ value={customizationState.spacing.scale}
323
+ onChange={(e) => handleCustomizationChange('spacing', 'scale', Number(e.target.value))}
324
+ min="1.1"
325
+ max="2.0"
326
+ step="0.05"
327
+ />
328
+ </div>
329
+ </div>
330
+ </div>
331
+ )}
332
+
333
+ {activeTab === 'shadows' && allowCustomization && (
334
+ <div className="space-y-4">
335
+ <h3 className="text-lg font-semibold">Shadow Customization</h3>
336
+ <div className="grid grid-cols-1 gap-4">
337
+ <div>
338
+ <label className="block text-sm font-medium mb-2">Shadow Intensity</label>
339
+ <Input
340
+ type="range"
341
+ min="0"
342
+ max="0.5"
343
+ step="0.01"
344
+ value={customizationState.shadows.intensity}
345
+ onChange={(e) => handleCustomizationChange('shadows', 'intensity', Number(e.target.value))}
346
+ className="w-full"
347
+ />
348
+ <span className="text-sm text-gray-600 dark:text-gray-400">
349
+ {customizationState.shadows.intensity}
350
+ </span>
351
+ </div>
352
+ </div>
353
+ </div>
354
+ )}
355
+
356
+ {activeTab === 'preview' && showPreview && (
357
+ <div>
358
+ <h3 className="text-lg font-semibold mb-4">Theme Preview</h3>
359
+ <ThemePreview themeName={customTheme.meta.name} />
360
+ </div>
361
+ )}
362
+ </div>
363
+
364
+ {/* Action Buttons */}
365
+ {allowCustomization && (
366
+ <div className="flex justify-between items-center pt-6 border-t">
367
+ <div className="flex gap-2">
368
+ <Button variant="outline" onClick={resetTheme}>
369
+ Reset
370
+ </Button>
371
+ <Button onClick={generateCustomTheme}>
372
+ Apply Changes
373
+ </Button>
374
+ </div>
375
+ <div className="flex gap-2">
376
+ <Button variant="secondary" onClick={exportTheme}>
377
+ Export Theme
378
+ </Button>
379
+ </div>
380
+ </div>
381
+ )}
382
+ </CardContent>
383
+ </Card>
384
+ </div>
385
+ );
386
+ };