@rakeyshgidwani/roger-ui-bank-theme-stan-design 0.1.3 → 0.1.5
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/CHANGELOG.md +1 -1
- package/dist/index.d.ts +131 -131
- package/dist/index.esm.js +148 -148
- package/dist/index.js +148 -148
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/components/ui/accessibility-demo.tsx +271 -0
- package/src/components/ui/advanced-component-architecture-demo.tsx +916 -0
- package/src/components/ui/advanced-transition-system-demo.tsx +670 -0
- package/src/components/ui/advanced-transition-system.tsx +395 -0
- package/src/components/ui/animation/animated-container.tsx +166 -0
- package/src/components/ui/animation/index.ts +19 -0
- package/src/components/ui/animation/staggered-container.tsx +68 -0
- package/src/components/ui/animation-demo.tsx +250 -0
- package/src/components/ui/badge.tsx +33 -0
- package/src/components/ui/battery-conscious-animation-demo.tsx +568 -0
- package/src/components/ui/border-radius-shadow-demo.tsx +187 -0
- package/src/components/ui/button.tsx +36 -0
- package/src/components/ui/card.tsx +207 -0
- package/src/components/ui/checkbox.tsx +30 -0
- package/src/components/ui/color-preview.tsx +411 -0
- package/src/components/ui/data-display/chart.tsx +653 -0
- package/src/components/ui/data-display/data-grid-simple.tsx +76 -0
- package/src/components/ui/data-display/data-grid.tsx +680 -0
- package/src/components/ui/data-display/list.tsx +456 -0
- package/src/components/ui/data-display/table.tsx +482 -0
- package/src/components/ui/data-display/timeline.tsx +441 -0
- package/src/components/ui/data-display/tree.tsx +602 -0
- package/src/components/ui/data-display/types.ts +536 -0
- package/src/components/ui/enterprise-mobile-experience-demo.tsx +749 -0
- package/src/components/ui/enterprise-mobile-experience.tsx +464 -0
- package/src/components/ui/feedback/alert.tsx +157 -0
- package/src/components/ui/feedback/progress.tsx +292 -0
- package/src/components/ui/feedback/skeleton.tsx +185 -0
- package/src/components/ui/feedback/toast.tsx +280 -0
- package/src/components/ui/feedback/types.ts +125 -0
- package/src/components/ui/font-preview.tsx +288 -0
- package/src/components/ui/form-demo.tsx +553 -0
- package/src/components/ui/hardware-acceleration-demo.tsx +547 -0
- package/src/components/ui/input.tsx +35 -0
- package/src/components/ui/label.tsx +16 -0
- package/src/components/ui/layout-demo.tsx +367 -0
- package/src/components/ui/layouts/adaptive-layout.tsx +139 -0
- package/src/components/ui/layouts/desktop-layout.tsx +224 -0
- package/src/components/ui/layouts/index.ts +10 -0
- package/src/components/ui/layouts/mobile-layout.tsx +162 -0
- package/src/components/ui/layouts/tablet-layout.tsx +197 -0
- package/src/components/ui/mobile-form-validation.tsx +451 -0
- package/src/components/ui/mobile-input-demo.tsx +201 -0
- package/src/components/ui/mobile-input.tsx +281 -0
- package/src/components/ui/mobile-skeleton-loading-demo.tsx +638 -0
- package/src/components/ui/navigation/breadcrumb.tsx +158 -0
- package/src/components/ui/navigation/index.ts +36 -0
- package/src/components/ui/navigation/menu.tsx +374 -0
- package/src/components/ui/navigation/navigation-demo.tsx +324 -0
- package/src/components/ui/navigation/pagination.tsx +272 -0
- package/src/components/ui/navigation/sidebar.tsx +383 -0
- package/src/components/ui/navigation/stepper.tsx +303 -0
- package/src/components/ui/navigation/tabs.tsx +205 -0
- package/src/components/ui/navigation/types.ts +299 -0
- package/src/components/ui/overlay/backdrop.tsx +81 -0
- package/src/components/ui/overlay/focus-manager.tsx +143 -0
- package/src/components/ui/overlay/index.ts +36 -0
- package/src/components/ui/overlay/modal.tsx +270 -0
- package/src/components/ui/overlay/overlay-manager.tsx +110 -0
- package/src/components/ui/overlay/popover.tsx +462 -0
- package/src/components/ui/overlay/portal.tsx +79 -0
- package/src/components/ui/overlay/tooltip.tsx +303 -0
- package/src/components/ui/overlay/types.ts +196 -0
- package/src/components/ui/performance-demo.tsx +596 -0
- package/src/components/ui/semantic-input-system-demo.tsx +502 -0
- package/src/components/ui/semantic-input-system-demo.tsx.disabled +873 -0
- package/src/components/ui/tablet-layout.tsx +192 -0
- package/src/components/ui/theme-customizer.tsx +386 -0
- package/src/components/ui/theme-preview.tsx +310 -0
- package/src/components/ui/theme-switcher.tsx +264 -0
- package/src/components/ui/theme-toggle.tsx +38 -0
- package/src/components/ui/token-demo.tsx +195 -0
- package/src/components/ui/touch-demo.tsx +462 -0
- package/src/components/ui/touch-friendly-interface-demo.tsx +519 -0
- package/src/components/ui/touch-friendly-interface.tsx +296 -0
- package/src/hooks/index.ts +190 -0
- package/src/hooks/use-accessibility-support.ts +518 -0
- package/src/hooks/use-adaptive-layout.ts +289 -0
- package/src/hooks/use-advanced-patterns.ts +294 -0
- package/src/hooks/use-advanced-transition-system.ts +393 -0
- package/src/hooks/use-animation-profile.ts +288 -0
- package/src/hooks/use-battery-animations.ts +384 -0
- package/src/hooks/use-battery-conscious-loading.ts +475 -0
- package/src/hooks/use-battery-optimization.ts +330 -0
- package/src/hooks/use-battery-status.ts +299 -0
- package/src/hooks/use-component-performance.ts +344 -0
- package/src/hooks/use-device-loading-states.ts +459 -0
- package/src/hooks/use-device.tsx +110 -0
- package/src/hooks/use-enterprise-mobile-experience.ts +488 -0
- package/src/hooks/use-form-feedback.ts +403 -0
- package/src/hooks/use-form-performance.ts +513 -0
- package/src/hooks/use-frame-rate.ts +251 -0
- package/src/hooks/use-gestures.ts +338 -0
- package/src/hooks/use-hardware-acceleration.ts +341 -0
- package/src/hooks/use-input-accessibility.ts +455 -0
- package/src/hooks/use-input-performance.ts +506 -0
- package/src/hooks/use-layout-performance.ts +319 -0
- package/src/hooks/use-loading-accessibility.ts +535 -0
- package/src/hooks/use-loading-performance.ts +473 -0
- package/src/hooks/use-memory-usage.ts +287 -0
- package/src/hooks/use-mobile-form-layout.ts +464 -0
- package/src/hooks/use-mobile-form-validation.ts +518 -0
- package/src/hooks/use-mobile-keyboard-optimization.ts +472 -0
- package/src/hooks/use-mobile-layout.ts +302 -0
- package/src/hooks/use-mobile-optimization.ts +406 -0
- package/src/hooks/use-mobile-skeleton.ts +402 -0
- package/src/hooks/use-mobile-touch.ts +414 -0
- package/src/hooks/use-performance-throttling.ts +348 -0
- package/src/hooks/use-performance.ts +316 -0
- package/src/hooks/use-reusable-architecture.ts +414 -0
- package/src/hooks/use-semantic-input-types.ts +357 -0
- package/src/hooks/use-semantic-input.ts +565 -0
- package/src/hooks/use-tablet-layout.ts +384 -0
- package/src/hooks/use-touch-friendly-input.ts +524 -0
- package/src/hooks/use-touch-friendly-interface.ts +331 -0
- package/src/hooks/use-touch-optimization.ts +375 -0
- package/src/index.ts +279 -279
- package/src/lib/utils.ts +6 -0
- package/src/themes/README.md +272 -0
- package/src/themes/ThemeContext.tsx +31 -0
- package/src/themes/ThemeProvider.tsx +232 -0
- package/src/themes/accessibility/index.ts +27 -0
- package/src/themes/accessibility.ts +259 -0
- package/src/themes/aria-patterns.ts +420 -0
- package/src/themes/base-themes.ts +55 -0
- package/src/themes/colorManager.ts +380 -0
- package/src/themes/examples/dark-theme.ts +154 -0
- package/src/themes/examples/minimal-theme.ts +108 -0
- package/src/themes/focus-management.ts +701 -0
- package/src/themes/fontLoader.ts +201 -0
- package/src/themes/high-contrast.ts +621 -0
- package/src/themes/index.ts +19 -0
- package/src/themes/inheritance.ts +227 -0
- package/src/themes/keyboard-navigation.ts +550 -0
- package/src/themes/motion-reduction.ts +662 -0
- package/src/themes/navigation.ts +238 -0
- package/src/themes/screen-reader.ts +645 -0
- package/src/themes/systemThemeDetector.ts +182 -0
- package/src/themes/themeCSSUpdater.ts +262 -0
- package/src/themes/themePersistence.ts +238 -0
- package/src/themes/themes/default.ts +586 -0
- package/src/themes/themes/harvey.ts +554 -0
- package/src/themes/themes/stan-design.ts +683 -0
- package/src/themes/types.ts +460 -0
- package/src/themes/useSystemTheme.ts +48 -0
- package/src/themes/useTheme.ts +87 -0
- package/src/themes/validation.ts +462 -0
- package/src/tokens/index.ts +34 -0
- package/src/tokens/tokenExporter.ts +397 -0
- package/src/tokens/tokenGenerator.ts +276 -0
- package/src/tokens/tokenManager.ts +248 -0
- package/src/tokens/tokenValidator.ts +543 -0
- package/src/tokens/types.ts +78 -0
- package/src/utils/bundle-analyzer.ts +260 -0
- package/src/utils/bundle-splitting.ts +483 -0
- package/src/utils/lazy-loading.ts +441 -0
- package/src/utils/performance-monitor.ts +513 -0
- package/src/utils/tree-shaking.ts +274 -0
package/src/lib/utils.ts
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
# Theme System with Inheritance
|
|
2
|
+
|
|
3
|
+
A robust theme system with inheritance support that ensures no variables are undefined by providing sensible defaults.
|
|
4
|
+
|
|
5
|
+
## 🎯 Key Features
|
|
6
|
+
|
|
7
|
+
- **🏗️ Theme Inheritance**: Automatically fills in missing values from default theme
|
|
8
|
+
- **📁 Organized Structure**: Individual files for each theme
|
|
9
|
+
- **🔧 Type Safety**: Full TypeScript support with comprehensive types
|
|
10
|
+
- **⚡ Hot Reload**: Development-time CSS regeneration
|
|
11
|
+
- **🎨 CSS Generation**: Automatic CSS custom properties generation
|
|
12
|
+
- **🧩 Modular**: Import only what you need
|
|
13
|
+
|
|
14
|
+
## 📂 Directory Structure
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
src/themes/
|
|
18
|
+
├── themes/ # Individual theme files
|
|
19
|
+
│ ├── default.ts # Base theme with all default values
|
|
20
|
+
│ ├── stan-design.ts # Professional poker coaching theme
|
|
21
|
+
│ ├── enterprise.ts # Corporate business theme
|
|
22
|
+
│ └── harvey.ts # Creative orange theme
|
|
23
|
+
├── examples/ # Example themes and usage patterns
|
|
24
|
+
│ ├── minimal-theme.ts # Minimal theme with inheritance
|
|
25
|
+
│ └── dark-theme.ts # Dark mode variants
|
|
26
|
+
├── base-themes.ts # Main theme exports with inheritance applied
|
|
27
|
+
├── inheritance.ts # Theme inheritance utilities
|
|
28
|
+
├── types.ts # TypeScript type definitions
|
|
29
|
+
└── index.ts # Main export file
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 🚀 Quick Start
|
|
33
|
+
|
|
34
|
+
### Import and Use Themes
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { stanDesignTheme, enterpriseTheme, harveyTheme } from '@/themes'
|
|
38
|
+
|
|
39
|
+
// All themes are guaranteed to have complete configurations
|
|
40
|
+
console.log(stanDesignTheme.colors.primary[500]) // Always defined
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Create a New Theme with Inheritance
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import { createTheme, PartialThemeConfig } from '@/themes'
|
|
47
|
+
|
|
48
|
+
// Define only what you want to customize
|
|
49
|
+
const myTheme: PartialThemeConfig = {
|
|
50
|
+
meta: {
|
|
51
|
+
name: 'My Custom Theme',
|
|
52
|
+
description: 'A theme that only overrides colors'
|
|
53
|
+
},
|
|
54
|
+
colors: {
|
|
55
|
+
primary: {
|
|
56
|
+
500: '#ff6b35' // Only override what you need
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Everything else inherits from default theme
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Create theme with full inheritance applied
|
|
63
|
+
export const customTheme = createTheme(myTheme)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Override an Existing Theme
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { overrideTheme, stanDesignTheme } from '@/themes'
|
|
70
|
+
|
|
71
|
+
// Create a variant of Stan Design with different colors
|
|
72
|
+
export const stanDesignDark = overrideTheme(stanDesignTheme, {
|
|
73
|
+
colors: {
|
|
74
|
+
surface: {
|
|
75
|
+
background: '#0f172a',
|
|
76
|
+
surface: '#1e293b'
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## 🎨 Theme Inheritance System
|
|
83
|
+
|
|
84
|
+
### How It Works
|
|
85
|
+
|
|
86
|
+
1. **Default Theme**: `default.ts` contains sensible defaults for ALL theme properties
|
|
87
|
+
2. **Inheritance**: Any undefined values in your theme automatically fall back to defaults
|
|
88
|
+
3. **Type Safety**: TypeScript ensures your themes match the expected structure
|
|
89
|
+
4. **Validation**: Built-in validation helps catch missing properties
|
|
90
|
+
|
|
91
|
+
### Inheritance Utilities
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
import {
|
|
95
|
+
createTheme, // Create theme with inheritance
|
|
96
|
+
overrideTheme, // Override existing theme
|
|
97
|
+
applyThemeInheritance, // Apply inheritance manually
|
|
98
|
+
themeInheritanceManager // Advanced inheritance utilities
|
|
99
|
+
} from '@/themes'
|
|
100
|
+
|
|
101
|
+
// Check if theme has complete inheritance
|
|
102
|
+
const isComplete = themeInheritanceManager.hasInheritance(myTheme)
|
|
103
|
+
|
|
104
|
+
// Get specific property with fallback
|
|
105
|
+
const primaryColor = themeInheritanceManager.getProperty(
|
|
106
|
+
myTheme,
|
|
107
|
+
'colors.primary.500',
|
|
108
|
+
'#000000' // fallback
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
// Validate completeness
|
|
112
|
+
const missing = themeInheritanceManager.validateCompleteness(myTheme)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## 🎯 Theme Definition Patterns
|
|
116
|
+
|
|
117
|
+
### Pattern 1: Minimal Theme
|
|
118
|
+
|
|
119
|
+
Only define what you need to change:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
const minimalTheme: PartialThemeConfig = {
|
|
123
|
+
meta: { name: 'Minimal' },
|
|
124
|
+
colors: {
|
|
125
|
+
primary: { 500: '#2563eb' }
|
|
126
|
+
}
|
|
127
|
+
// Everything else inherited from default
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Pattern 2: Color-Only Theme
|
|
132
|
+
|
|
133
|
+
Focus on colors, inherit everything else:
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
const colorTheme: PartialThemeConfig = {
|
|
137
|
+
meta: { name: 'Blue Theme' },
|
|
138
|
+
colors: {
|
|
139
|
+
primary: { /* full primary palette */ },
|
|
140
|
+
semantic: { /* semantic colors */ }
|
|
141
|
+
}
|
|
142
|
+
// fonts, spacing, shadows, etc. inherited
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Pattern 3: Complete Custom Theme
|
|
147
|
+
|
|
148
|
+
Define everything for full control:
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
const completeTheme: MultiThemeConfig = {
|
|
152
|
+
fonts: { /* custom fonts */ },
|
|
153
|
+
colors: { /* custom colors */ },
|
|
154
|
+
navigation: { /* custom navigation */ },
|
|
155
|
+
spacing: { /* custom spacing */ },
|
|
156
|
+
shadows: { /* custom shadows */ },
|
|
157
|
+
transitions: { /* custom transitions */ },
|
|
158
|
+
meta: { /* theme metadata */ }
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## 🔧 CSS Generation
|
|
163
|
+
|
|
164
|
+
The system automatically generates CSS custom properties:
|
|
165
|
+
|
|
166
|
+
```css
|
|
167
|
+
/* Generated CSS */
|
|
168
|
+
:root {
|
|
169
|
+
--cs-primary-500: #3b82f6;
|
|
170
|
+
--cs-primary-500-rgb: 59, 130, 246;
|
|
171
|
+
--cs-success: #10b981;
|
|
172
|
+
--cs-success-rgb: 16, 185, 129;
|
|
173
|
+
/* ... all other variables */
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Using Generated CSS
|
|
178
|
+
|
|
179
|
+
```css
|
|
180
|
+
.button {
|
|
181
|
+
background-color: var(--cs-primary-500);
|
|
182
|
+
color: var(--cs-text-primary);
|
|
183
|
+
border-color: var(--cs-border);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.button:hover {
|
|
187
|
+
background-color: var(--cs-primary-hover);
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## 🎨 Available Themes
|
|
192
|
+
|
|
193
|
+
### Stan Design Theme
|
|
194
|
+
- **Focus**: Professional poker coaching
|
|
195
|
+
- **Font**: Clash Display
|
|
196
|
+
- **Colors**: Blue primary with professional palette
|
|
197
|
+
- **Style**: Modern, clean, professional
|
|
198
|
+
|
|
199
|
+
### Enterprise Theme
|
|
200
|
+
- **Focus**: Corporate business applications
|
|
201
|
+
- **Font**: Inter
|
|
202
|
+
- **Colors**: Sky blue primary with corporate palette
|
|
203
|
+
- **Style**: Business-focused, reliable
|
|
204
|
+
|
|
205
|
+
### Harvey Theme
|
|
206
|
+
- **Focus**: Creative projects
|
|
207
|
+
- **Font**: Poppins
|
|
208
|
+
- **Colors**: Orange primary with warm palette
|
|
209
|
+
- **Style**: Vibrant, creative, friendly
|
|
210
|
+
|
|
211
|
+
### Default Theme
|
|
212
|
+
- **Focus**: Sensible fallbacks
|
|
213
|
+
- **Font**: System fonts
|
|
214
|
+
- **Colors**: Neutral slate palette
|
|
215
|
+
- **Style**: Clean, minimal, accessible
|
|
216
|
+
|
|
217
|
+
## 🛠️ Development
|
|
218
|
+
|
|
219
|
+
### Hot Reload
|
|
220
|
+
|
|
221
|
+
The system automatically regenerates CSS when you modify:
|
|
222
|
+
- Individual theme files (`*.ts`)
|
|
223
|
+
- Type definitions (`types.ts`)
|
|
224
|
+
- Inheritance system (`inheritance.ts`)
|
|
225
|
+
|
|
226
|
+
### Adding New Themes
|
|
227
|
+
|
|
228
|
+
1. Create a new file in `src/themes/themes/`
|
|
229
|
+
2. Define your theme (partial or complete)
|
|
230
|
+
3. Export it from `base-themes.ts`
|
|
231
|
+
4. Update the Vite plugin if needed
|
|
232
|
+
|
|
233
|
+
### Validation
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
import { themeInheritanceManager } from '@/themes'
|
|
237
|
+
|
|
238
|
+
// Check for missing properties
|
|
239
|
+
const missing = themeInheritanceManager.validateCompleteness(myTheme)
|
|
240
|
+
if (missing.length > 0) {
|
|
241
|
+
console.warn('Missing properties:', missing)
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## 📖 Examples
|
|
246
|
+
|
|
247
|
+
See the `examples/` directory for:
|
|
248
|
+
- Minimal theme with inheritance
|
|
249
|
+
- Dark mode variants
|
|
250
|
+
- Theme override patterns
|
|
251
|
+
- Advanced inheritance usage
|
|
252
|
+
|
|
253
|
+
## 🎯 Best Practices
|
|
254
|
+
|
|
255
|
+
1. **Start Small**: Use `PartialThemeConfig` and only define what you need
|
|
256
|
+
2. **Use Inheritance**: Let the default theme fill in missing values
|
|
257
|
+
3. **Validate**: Check theme completeness during development
|
|
258
|
+
4. **Type Safety**: Leverage TypeScript for better development experience
|
|
259
|
+
5. **Hot Reload**: Use the development server for instant feedback
|
|
260
|
+
|
|
261
|
+
## 🤝 Contributing
|
|
262
|
+
|
|
263
|
+
When adding new theme properties:
|
|
264
|
+
1. Update `types.ts` with the new property
|
|
265
|
+
2. Add sensible defaults to `default.ts`
|
|
266
|
+
3. Update existing themes if needed
|
|
267
|
+
4. Add CSS generation logic if required
|
|
268
|
+
5. Update documentation
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
This inheritance system ensures robust, maintainable themes with no undefined variables! 🎉
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createContext } from 'react';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
import { MultiThemeConfig, CompleteThemeConfig } from './types';
|
|
4
|
+
|
|
5
|
+
// Theme context interface
|
|
6
|
+
export interface ThemeContextType {
|
|
7
|
+
currentTheme: string;
|
|
8
|
+
currentThemeConfig: CompleteThemeConfig | null;
|
|
9
|
+
availableThemes: string[];
|
|
10
|
+
setTheme: (themeName: string) => void;
|
|
11
|
+
addTheme: (name: string, theme: MultiThemeConfig) => void;
|
|
12
|
+
removeTheme: (name: string) => void;
|
|
13
|
+
getTheme: (name: string) => CompleteThemeConfig | null;
|
|
14
|
+
isLoading: boolean;
|
|
15
|
+
error: string | null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Create the context
|
|
19
|
+
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
|
|
20
|
+
|
|
21
|
+
// Provider props interface
|
|
22
|
+
export interface ThemeProviderProps {
|
|
23
|
+
children: ReactNode;
|
|
24
|
+
defaultTheme?: string;
|
|
25
|
+
themes?: Record<string, MultiThemeConfig>;
|
|
26
|
+
persistTheme?: boolean;
|
|
27
|
+
storageKey?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Export the context for testing and advanced usage
|
|
31
|
+
export { ThemeContext };
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
2
|
+
import { ThemeContext, ThemeContextType, ThemeProviderProps } from './ThemeContext';
|
|
3
|
+
import { MultiThemeConfig, CompleteThemeConfig } from './types';
|
|
4
|
+
import { themeInheritanceManager, toCompleteThemeConfig } from './inheritance';
|
|
5
|
+
import { defaultThemes } from './base-themes';
|
|
6
|
+
import { createThemePersistence } from './themePersistence';
|
|
7
|
+
import { themeCSSUpdater } from './themeCSSUpdater';
|
|
8
|
+
import { fontLoader } from './fontLoader';
|
|
9
|
+
import { ColorManager } from './colorManager';
|
|
10
|
+
|
|
11
|
+
export const ThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
12
|
+
children,
|
|
13
|
+
defaultTheme = 'stan-design',
|
|
14
|
+
themes = defaultThemes,
|
|
15
|
+
persistTheme = true,
|
|
16
|
+
storageKey = 'stan-design-theme'
|
|
17
|
+
}) => {
|
|
18
|
+
// State management
|
|
19
|
+
const [currentTheme, setCurrentThemeState] = useState<string>(defaultTheme);
|
|
20
|
+
const [currentThemeConfig, setCurrentThemeConfig] = useState<CompleteThemeConfig | null>(null);
|
|
21
|
+
const [availableThemes, setAvailableThemes] = useState<string[]>([]);
|
|
22
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
23
|
+
const [error, setError] = useState<string | null>(null);
|
|
24
|
+
|
|
25
|
+
// Enhance theme colors using ColorManager
|
|
26
|
+
const enhanceThemeColors = useCallback((themeConfig: CompleteThemeConfig): CompleteThemeConfig => {
|
|
27
|
+
try {
|
|
28
|
+
const enhanced = { ...themeConfig };
|
|
29
|
+
|
|
30
|
+
// Enhance primary colors if they exist
|
|
31
|
+
if (enhanced.colors?.primary?.[500]) {
|
|
32
|
+
const baseColor = enhanced.colors.primary[500];
|
|
33
|
+
|
|
34
|
+
// Generate additional color variations if they don't exist
|
|
35
|
+
if (!enhanced.colors.primary.light || !enhanced.colors.primary.dark || !enhanced.colors.primary.contrast) {
|
|
36
|
+
const enhancedScale = ColorManager.generateColorScale({
|
|
37
|
+
baseColor,
|
|
38
|
+
generateShades: true,
|
|
39
|
+
generateContrast: true
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
enhanced.colors.primary = {
|
|
43
|
+
...enhanced.colors.primary,
|
|
44
|
+
light: enhancedScale.light,
|
|
45
|
+
dark: enhancedScale.dark,
|
|
46
|
+
contrast: enhancedScale.contrast
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Enhance semantic colors if they don't exist
|
|
52
|
+
if (enhanced.colors?.primary?.[500] && !enhanced.colors.semantic?.success) {
|
|
53
|
+
const semanticColors = ColorManager.generateSemanticColors(enhanced.colors.primary[500]);
|
|
54
|
+
enhanced.colors.semantic = {
|
|
55
|
+
...enhanced.colors.semantic,
|
|
56
|
+
...semanticColors
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Enhance neutral colors if they don't exist
|
|
61
|
+
if (!enhanced.colors?.neutral?.[500]) {
|
|
62
|
+
enhanced.colors.neutral = ColorManager.generateNeutralColors('#6b7280');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return enhanced;
|
|
66
|
+
} catch (err) {
|
|
67
|
+
console.warn('Failed to enhance theme colors:', err);
|
|
68
|
+
return themeConfig;
|
|
69
|
+
}
|
|
70
|
+
}, []);
|
|
71
|
+
|
|
72
|
+
// Initialize themes in the inheritance manager
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
try {
|
|
75
|
+
// Register all provided themes
|
|
76
|
+
Object.entries(themes).forEach(([name, theme]) => {
|
|
77
|
+
try {
|
|
78
|
+
themeInheritanceManager.registerTheme(name, theme);
|
|
79
|
+
} catch (err) {
|
|
80
|
+
console.warn(`Failed to register theme '${name}':`, err);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Set available themes
|
|
85
|
+
setAvailableThemes(Object.keys(themes));
|
|
86
|
+
|
|
87
|
+
// Load persisted theme or use default
|
|
88
|
+
if (persistTheme) {
|
|
89
|
+
const persistence = createThemePersistence({
|
|
90
|
+
storageKey,
|
|
91
|
+
defaultTheme,
|
|
92
|
+
enableSystemPreference: true
|
|
93
|
+
});
|
|
94
|
+
const persistedTheme = persistence.getStoredTheme();
|
|
95
|
+
if (persistedTheme && themes[persistedTheme]) {
|
|
96
|
+
setCurrentThemeState(persistedTheme);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
} catch (err) {
|
|
100
|
+
setError(`Failed to initialize themes: ${err instanceof Error ? err.message : 'Unknown error'}`);
|
|
101
|
+
} finally {
|
|
102
|
+
setIsLoading(false);
|
|
103
|
+
}
|
|
104
|
+
}, [themes, persistTheme, storageKey, defaultTheme]);
|
|
105
|
+
|
|
106
|
+
// Update current theme config when theme changes
|
|
107
|
+
useEffect(() => {
|
|
108
|
+
try {
|
|
109
|
+
const themeConfig = themeInheritanceManager.getCompleteTheme(currentTheme);
|
|
110
|
+
|
|
111
|
+
if (themeConfig) {
|
|
112
|
+
// Enhance theme colors using ColorManager
|
|
113
|
+
const enhancedThemeConfig = enhanceThemeColors(toCompleteThemeConfig(themeConfig));
|
|
114
|
+
setCurrentThemeConfig(enhancedThemeConfig);
|
|
115
|
+
|
|
116
|
+
// Apply the enhanced theme to CSS variables and load fonts
|
|
117
|
+
themeCSSUpdater.applyTheme(enhancedThemeConfig);
|
|
118
|
+
fontLoader.loadThemeFonts(enhancedThemeConfig.fonts).catch(err => {
|
|
119
|
+
console.warn(`Failed to load fonts for theme '${currentTheme}':`, err);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
setError(null);
|
|
124
|
+
} catch (err) {
|
|
125
|
+
const errorMessage = `Failed to load theme '${currentTheme}': ${err instanceof Error ? err.message : 'Unknown error'}`;
|
|
126
|
+
setError(errorMessage);
|
|
127
|
+
setCurrentThemeConfig(null);
|
|
128
|
+
console.error(errorMessage, err);
|
|
129
|
+
}
|
|
130
|
+
}, [currentTheme, enhanceThemeColors]);
|
|
131
|
+
|
|
132
|
+
// Theme switching function
|
|
133
|
+
const setTheme = useCallback(async (themeName: string) => {
|
|
134
|
+
if (!themes[themeName]) {
|
|
135
|
+
setError(`Theme '${themeName}' not found`);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
// Get the complete theme configuration
|
|
141
|
+
const themeConfig = themeInheritanceManager.getCompleteTheme(themeName);
|
|
142
|
+
|
|
143
|
+
if (!themeConfig) {
|
|
144
|
+
throw new Error(`Theme configuration not found for '${themeName}'`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Enhance theme colors using ColorManager
|
|
148
|
+
const enhancedThemeConfig = enhanceThemeColors(toCompleteThemeConfig(themeConfig));
|
|
149
|
+
|
|
150
|
+
// Apply enhanced CSS variables to the document
|
|
151
|
+
themeCSSUpdater.applyTheme(enhancedThemeConfig);
|
|
152
|
+
|
|
153
|
+
// Load fonts for the theme
|
|
154
|
+
await fontLoader.loadThemeFonts(enhancedThemeConfig.fonts);
|
|
155
|
+
|
|
156
|
+
// Update state
|
|
157
|
+
setCurrentThemeState(themeName);
|
|
158
|
+
setCurrentThemeConfig(enhancedThemeConfig);
|
|
159
|
+
|
|
160
|
+
// Persist theme preference
|
|
161
|
+
if (persistTheme) {
|
|
162
|
+
const persistence = createThemePersistence({ storageKey });
|
|
163
|
+
persistence.setStoredTheme(themeName);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
setError(null);
|
|
167
|
+
} catch (err) {
|
|
168
|
+
const errorMessage = `Failed to switch to theme '${themeName}': ${err instanceof Error ? err.message : 'Unknown error'}`;
|
|
169
|
+
setError(errorMessage);
|
|
170
|
+
console.error(errorMessage, err);
|
|
171
|
+
}
|
|
172
|
+
}, [themes, persistTheme, storageKey]);
|
|
173
|
+
|
|
174
|
+
// Add new theme
|
|
175
|
+
const addTheme = useCallback((name: string, theme: MultiThemeConfig) => {
|
|
176
|
+
try {
|
|
177
|
+
themeInheritanceManager.registerTheme(name, theme);
|
|
178
|
+
setAvailableThemes(prev => [...prev, name]);
|
|
179
|
+
setError(null);
|
|
180
|
+
} catch (err) {
|
|
181
|
+
setError(`Failed to add theme '${name}': ${err instanceof Error ? err.message : 'Unknown error'}`);
|
|
182
|
+
}
|
|
183
|
+
}, []);
|
|
184
|
+
|
|
185
|
+
// Remove theme
|
|
186
|
+
const removeTheme = useCallback((name: string) => {
|
|
187
|
+
try {
|
|
188
|
+
// Don't allow removing the current theme
|
|
189
|
+
if (name === currentTheme) {
|
|
190
|
+
setError('Cannot remove the currently active theme');
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Remove from inheritance manager (we'll need to add this method)
|
|
195
|
+
// themeInheritanceManager.removeTheme(name);
|
|
196
|
+
|
|
197
|
+
setAvailableThemes(prev => prev.filter(t => t !== name));
|
|
198
|
+
setError(null);
|
|
199
|
+
} catch (err) {
|
|
200
|
+
setError(`Failed to remove theme '${name}': ${err instanceof Error ? err.message : 'Unknown error'}`);
|
|
201
|
+
}
|
|
202
|
+
}, [currentTheme]);
|
|
203
|
+
|
|
204
|
+
// Get theme by name
|
|
205
|
+
const getTheme = useCallback((name: string): CompleteThemeConfig | null => {
|
|
206
|
+
try {
|
|
207
|
+
return themeInheritanceManager.getCompleteTheme(name);
|
|
208
|
+
} catch (err) {
|
|
209
|
+
setError(`Failed to get theme '${name}': ${err instanceof Error ? err.message : 'Unknown error'}`);
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
}, []);
|
|
213
|
+
|
|
214
|
+
// Context value
|
|
215
|
+
const contextValue: ThemeContextType = {
|
|
216
|
+
currentTheme,
|
|
217
|
+
currentThemeConfig,
|
|
218
|
+
availableThemes,
|
|
219
|
+
setTheme,
|
|
220
|
+
addTheme,
|
|
221
|
+
removeTheme,
|
|
222
|
+
getTheme,
|
|
223
|
+
isLoading,
|
|
224
|
+
error
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
return (
|
|
228
|
+
<ThemeContext.Provider value={contextValue}>
|
|
229
|
+
{children}
|
|
230
|
+
</ThemeContext.Provider>
|
|
231
|
+
);
|
|
232
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Accessibility theme system exports
|
|
2
|
+
export * from '../accessibility';
|
|
3
|
+
|
|
4
|
+
// Re-export main managers for easy access
|
|
5
|
+
export { accessibilityManager } from '../accessibility';
|
|
6
|
+
export { keyboardNavigationManager } from '../keyboard-navigation';
|
|
7
|
+
export { screenReaderOptimizer } from '../screen-reader';
|
|
8
|
+
export { highContrastThemeManager } from '../high-contrast';
|
|
9
|
+
export { focusManager } from '../focus-management';
|
|
10
|
+
export { motionReductionManager } from '../motion-reduction';
|
|
11
|
+
|
|
12
|
+
// Re-export specific classes to avoid naming conflicts
|
|
13
|
+
export { ARIAUtils as AriaPatternGenerator } from '../aria-patterns';
|
|
14
|
+
export { FocusManager as FocusManagerClass } from '../focus-management';
|
|
15
|
+
export { FocusTrap } from '../focus-management';
|
|
16
|
+
export { FocusRestoration } from '../focus-management';
|
|
17
|
+
export { FocusNavigation } from '../focus-management';
|
|
18
|
+
|
|
19
|
+
// Re-export specific classes from other modules
|
|
20
|
+
export { KeyboardNavigationManager } from '../keyboard-navigation';
|
|
21
|
+
export { ScreenReaderOptimizer } from '../screen-reader';
|
|
22
|
+
export { HighContrastThemeManager } from '../high-contrast';
|
|
23
|
+
export { MotionReductionManager } from '../motion-reduction';
|
|
24
|
+
|
|
25
|
+
// Re-export specific utilities and constants
|
|
26
|
+
export { ARIA_ROLES, ARIA_STATES, ARIA_LIVE_VALUES } from '../aria-patterns';
|
|
27
|
+
export { KEY_CODES, NAVIGATION_PATTERNS } from '../keyboard-navigation';
|