@rakeyshgidwani/roger-ui-bank-theme-stan-design 0.2.8 → 0.2.10
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/components/ui/accessibility-demo.esm.js +30 -24
- package/dist/components/ui/accessibility-demo.js +30 -24
- package/dist/components/ui/advanced-component-architecture-demo.esm.js +235 -179
- package/dist/components/ui/advanced-component-architecture-demo.js +235 -179
- package/dist/components/ui/advanced-transition-system-demo.esm.js +110 -64
- package/dist/components/ui/advanced-transition-system-demo.js +110 -64
- package/dist/components/ui/advanced-transition-system.esm.js +166 -122
- package/dist/components/ui/advanced-transition-system.js +166 -122
- package/dist/components/ui/animation/animated-container.esm.js +52 -29
- package/dist/components/ui/animation/animated-container.js +52 -29
- package/dist/components/ui/animation/staggered-container.esm.js +18 -9
- package/dist/components/ui/animation/staggered-container.js +18 -9
- package/dist/components/ui/animation-demo.esm.js +67 -35
- package/dist/components/ui/animation-demo.js +67 -35
- package/dist/components/ui/badge.esm.js +9 -6
- package/dist/components/ui/badge.js +9 -6
- package/dist/components/ui/battery-conscious-animation-demo.esm.js +122 -87
- package/dist/components/ui/battery-conscious-animation-demo.js +122 -87
- package/dist/components/ui/border-radius-shadow-demo.esm.js +23 -12
- package/dist/components/ui/border-radius-shadow-demo.js +23 -12
- package/dist/components/ui/button.esm.js +8 -2
- package/dist/components/ui/button.js +8 -2
- package/dist/components/ui/card.esm.js +33 -8
- package/dist/components/ui/card.js +33 -8
- package/dist/components/ui/checkbox.esm.js +3 -3
- package/dist/components/ui/checkbox.js +3 -3
- package/dist/components/ui/color-preview.esm.js +68 -45
- package/dist/components/ui/color-preview.js +68 -45
- package/dist/components/ui/data-display/chart.esm.js +112 -84
- package/dist/components/ui/data-display/chart.js +112 -84
- package/dist/components/ui/data-display/data-grid-simple.esm.js +1 -1
- package/dist/components/ui/data-display/data-grid-simple.js +1 -1
- package/dist/components/ui/data-display/data-grid.esm.js +80 -67
- package/dist/components/ui/data-display/data-grid.js +80 -67
- package/dist/components/ui/data-display/list.esm.js +53 -45
- package/dist/components/ui/data-display/list.js +53 -45
- package/dist/components/ui/data-display/table.esm.js +62 -54
- package/dist/components/ui/data-display/table.js +62 -54
- package/dist/components/ui/data-display/timeline.esm.js +39 -34
- package/dist/components/ui/data-display/timeline.js +39 -34
- package/dist/components/ui/data-display/tree.esm.js +116 -84
- package/dist/components/ui/data-display/tree.js +116 -84
- package/dist/components/ui/data-display/types.esm.js +389 -364
- package/dist/components/ui/data-display/types.js +389 -364
- package/dist/components/ui/enterprise-mobile-experience-demo.esm.js +120 -70
- package/dist/components/ui/enterprise-mobile-experience-demo.js +120 -70
- package/dist/components/ui/enterprise-mobile-experience.esm.js +124 -73
- package/dist/components/ui/enterprise-mobile-experience.js +124 -73
- package/dist/components/ui/feedback/alert.esm.js +22 -15
- package/dist/components/ui/feedback/alert.js +22 -15
- package/dist/components/ui/feedback/progress.esm.js +47 -24
- package/dist/components/ui/feedback/progress.js +47 -24
- package/dist/components/ui/feedback/skeleton.esm.js +39 -29
- package/dist/components/ui/feedback/skeleton.js +39 -29
- package/dist/components/ui/feedback/toast.esm.js +62 -38
- package/dist/components/ui/feedback/toast.js +62 -38
- package/dist/components/ui/feedback/types.esm.js +83 -83
- package/dist/components/ui/feedback/types.js +83 -83
- package/dist/components/ui/font-preview.esm.js +41 -39
- package/dist/components/ui/font-preview.js +41 -39
- package/dist/components/ui/form-demo.esm.js +150 -113
- package/dist/components/ui/form-demo.js +150 -113
- package/dist/components/ui/hardware-acceleration-demo.esm.js +137 -87
- package/dist/components/ui/hardware-acceleration-demo.js +137 -87
- package/dist/components/ui/input.esm.js +4 -1
- package/dist/components/ui/input.js +4 -1
- package/dist/components/ui/layout-demo.esm.js +81 -56
- package/dist/components/ui/layout-demo.js +81 -56
- package/dist/components/ui/layouts/adaptive-layout.esm.js +27 -8
- package/dist/components/ui/layouts/adaptive-layout.js +27 -8
- package/dist/components/ui/layouts/desktop-layout.esm.js +39 -19
- package/dist/components/ui/layouts/desktop-layout.js +39 -19
- package/dist/components/ui/layouts/mobile-layout.esm.js +19 -9
- package/dist/components/ui/layouts/mobile-layout.js +19 -9
- package/dist/components/ui/layouts/tablet-layout.esm.js +28 -14
- package/dist/components/ui/layouts/tablet-layout.js +28 -14
- package/dist/components/ui/mobile-form-validation.esm.js +120 -87
- package/dist/components/ui/mobile-form-validation.js +120 -87
- package/dist/components/ui/mobile-input-demo.esm.js +19 -13
- package/dist/components/ui/mobile-input-demo.js +19 -13
- package/dist/components/ui/mobile-input.esm.js +185 -120
- package/dist/components/ui/mobile-input.js +185 -120
- package/dist/components/ui/mobile-skeleton-loading-demo.esm.js +128 -111
- package/dist/components/ui/mobile-skeleton-loading-demo.js +128 -111
- package/dist/components/ui/navigation/breadcrumb.esm.js +17 -14
- package/dist/components/ui/navigation/breadcrumb.js +17 -14
- package/dist/components/ui/navigation/index.esm.js +23 -1
- package/dist/components/ui/navigation/index.js +23 -1
- package/dist/components/ui/navigation/menu.esm.js +49 -35
- package/dist/components/ui/navigation/menu.js +49 -35
- package/dist/components/ui/navigation/navigation-demo.esm.js +81 -74
- package/dist/components/ui/navigation/navigation-demo.js +81 -74
- package/dist/components/ui/navigation/pagination.esm.js +62 -50
- package/dist/components/ui/navigation/pagination.js +62 -50
- package/dist/components/ui/navigation/sidebar.esm.js +56 -42
- package/dist/components/ui/navigation/sidebar.js +56 -42
- package/dist/components/ui/navigation/stepper.esm.js +34 -23
- package/dist/components/ui/navigation/stepper.js +34 -23
- package/dist/components/ui/navigation/tabs.esm.js +32 -21
- package/dist/components/ui/navigation/tabs.js +32 -21
- package/dist/components/ui/navigation/types.esm.js +196 -195
- package/dist/components/ui/navigation/types.js +196 -195
- package/dist/components/ui/overlay/backdrop.esm.js +17 -16
- package/dist/components/ui/overlay/backdrop.js +17 -16
- package/dist/components/ui/overlay/focus-manager.esm.js +21 -19
- package/dist/components/ui/overlay/focus-manager.js +21 -19
- package/dist/components/ui/overlay/index.esm.js +22 -2
- package/dist/components/ui/overlay/index.js +22 -2
- package/dist/components/ui/overlay/modal.esm.js +38 -34
- package/dist/components/ui/overlay/modal.js +38 -34
- package/dist/components/ui/overlay/overlay-manager.esm.js +25 -20
- package/dist/components/ui/overlay/overlay-manager.js +25 -20
- package/dist/components/ui/overlay/popover.esm.js +74 -58
- package/dist/components/ui/overlay/popover.js +74 -58
- package/dist/components/ui/overlay/portal.esm.js +7 -7
- package/dist/components/ui/overlay/portal.js +7 -7
- package/dist/components/ui/overlay/tooltip.esm.js +54 -39
- package/dist/components/ui/overlay/tooltip.js +54 -39
- package/dist/components/ui/overlay/types.esm.js +132 -131
- package/dist/components/ui/overlay/types.js +132 -131
- package/dist/components/ui/performance-demo.esm.js +135 -88
- package/dist/components/ui/performance-demo.js +135 -88
- package/dist/components/ui/semantic-input-system-demo.esm.js +117 -80
- package/dist/components/ui/semantic-input-system-demo.js +117 -80
- package/dist/components/ui/theme-customizer.esm.js +84 -52
- package/dist/components/ui/theme-customizer.js +84 -52
- package/dist/components/ui/theme-preview.esm.js +95 -43
- package/dist/components/ui/theme-preview.js +95 -43
- package/dist/components/ui/theme-switcher.esm.js +70 -44
- package/dist/components/ui/theme-switcher.js +70 -44
- package/dist/components/ui/theme-toggle.esm.js +3 -3
- package/dist/components/ui/theme-toggle.js +3 -3
- package/dist/components/ui/token-demo.esm.js +33 -21
- package/dist/components/ui/token-demo.js +33 -21
- package/dist/components/ui/touch-demo.esm.js +102 -73
- package/dist/components/ui/touch-demo.js +102 -73
- package/dist/components/ui/touch-friendly-interface-demo.esm.js +102 -64
- package/dist/components/ui/touch-friendly-interface-demo.js +102 -64
- package/dist/components/ui/touch-friendly-interface.esm.js +85 -61
- package/dist/components/ui/touch-friendly-interface.js +85 -61
- package/dist/hooks/use-accessibility-support.esm.js +115 -85
- package/dist/hooks/use-accessibility-support.js +115 -85
- package/dist/hooks/use-adaptive-layout.esm.js +56 -33
- package/dist/hooks/use-adaptive-layout.js +56 -33
- package/dist/hooks/use-advanced-patterns.esm.js +57 -42
- package/dist/hooks/use-advanced-patterns.js +57 -42
- package/dist/hooks/use-advanced-transition-system.esm.js +112 -71
- package/dist/hooks/use-advanced-transition-system.js +112 -71
- package/dist/hooks/use-animation-profile.esm.js +63 -34
- package/dist/hooks/use-animation-profile.js +63 -34
- package/dist/hooks/use-battery-animations.esm.js +80 -55
- package/dist/hooks/use-battery-animations.js +80 -55
- package/dist/hooks/use-battery-conscious-loading.esm.js +166 -123
- package/dist/hooks/use-battery-conscious-loading.js +166 -123
- package/dist/hooks/use-battery-optimization.esm.js +78 -55
- package/dist/hooks/use-battery-optimization.js +78 -55
- package/dist/hooks/use-battery-status.esm.js +73 -51
- package/dist/hooks/use-battery-status.js +73 -51
- package/dist/hooks/use-component-performance.esm.js +62 -47
- package/dist/hooks/use-component-performance.js +62 -47
- package/dist/hooks/use-device-loading-states.esm.js +152 -109
- package/dist/hooks/use-device-loading-states.js +152 -109
- package/dist/hooks/use-device.esm.js +25 -14
- package/dist/hooks/use-device.js +25 -14
- package/dist/hooks/use-enterprise-mobile-experience.esm.js +137 -88
- package/dist/hooks/use-enterprise-mobile-experience.js +137 -88
- package/dist/hooks/use-form-feedback.esm.js +124 -81
- package/dist/hooks/use-form-feedback.js +124 -81
- package/dist/hooks/use-form-performance.esm.js +127 -92
- package/dist/hooks/use-form-performance.js +127 -92
- package/dist/hooks/use-frame-rate.esm.js +56 -37
- package/dist/hooks/use-frame-rate.js +56 -37
- package/dist/hooks/use-gestures.esm.js +96 -72
- package/dist/hooks/use-gestures.js +96 -72
- package/dist/hooks/use-hardware-acceleration.esm.js +65 -37
- package/dist/hooks/use-hardware-acceleration.js +65 -37
- package/dist/hooks/use-input-accessibility.esm.js +157 -119
- package/dist/hooks/use-input-accessibility.js +157 -119
- package/dist/hooks/use-input-performance.esm.js +139 -104
- package/dist/hooks/use-input-performance.js +139 -104
- package/dist/hooks/use-layout-performance.esm.js +50 -29
- package/dist/hooks/use-layout-performance.js +50 -29
- package/dist/hooks/use-loading-accessibility.esm.js +209 -169
- package/dist/hooks/use-loading-accessibility.js +209 -169
- package/dist/hooks/use-loading-performance.esm.js +117 -93
- package/dist/hooks/use-loading-performance.js +117 -93
- package/dist/hooks/use-memory-usage.esm.js +57 -38
- package/dist/hooks/use-memory-usage.js +57 -38
- package/dist/hooks/use-mobile-form-layout.esm.js +111 -74
- package/dist/hooks/use-mobile-form-layout.js +111 -74
- package/dist/hooks/use-mobile-form-validation.esm.js +211 -144
- package/dist/hooks/use-mobile-form-validation.js +211 -144
- package/dist/hooks/use-mobile-keyboard-optimization.esm.js +154 -113
- package/dist/hooks/use-mobile-keyboard-optimization.js +154 -113
- package/dist/hooks/use-mobile-layout.esm.js +73 -51
- package/dist/hooks/use-mobile-layout.js +73 -51
- package/dist/hooks/use-mobile-optimization.esm.js +72 -44
- package/dist/hooks/use-mobile-optimization.js +72 -44
- package/dist/hooks/use-mobile-skeleton.esm.js +97 -64
- package/dist/hooks/use-mobile-skeleton.js +97 -64
- package/dist/hooks/use-mobile-touch.esm.js +128 -93
- package/dist/hooks/use-mobile-touch.js +128 -93
- package/dist/hooks/use-performance-throttling.esm.js +72 -48
- package/dist/hooks/use-performance-throttling.js +72 -48
- package/dist/hooks/use-performance.esm.js +90 -52
- package/dist/hooks/use-performance.js +90 -52
- package/dist/hooks/use-reusable-architecture.esm.js +94 -65
- package/dist/hooks/use-reusable-architecture.js +94 -65
- package/dist/hooks/use-semantic-input-types.esm.js +166 -124
- package/dist/hooks/use-semantic-input-types.js +166 -124
- package/dist/hooks/use-semantic-input.esm.js +178 -126
- package/dist/hooks/use-semantic-input.js +178 -126
- package/dist/hooks/use-tablet-layout.esm.js +67 -38
- package/dist/hooks/use-tablet-layout.js +67 -38
- package/dist/hooks/use-touch-friendly-input.esm.js +193 -149
- package/dist/hooks/use-touch-friendly-input.js +193 -149
- package/dist/hooks/use-touch-friendly-interface.esm.js +99 -67
- package/dist/hooks/use-touch-friendly-interface.js +99 -67
- package/dist/hooks/use-touch-optimization.esm.js +99 -72
- package/dist/hooks/use-touch-optimization.js +99 -72
- package/dist/index.esm.js +289 -280
- package/dist/index.js +289 -280
- package/dist/lib/utils.esm.js +1 -1
- package/dist/lib/utils.js +1 -1
- package/dist/plugins/theme-css-generator.esm.js +104 -55
- package/dist/plugins/theme-css-generator.js +104 -55
- package/dist/provider.esm.js +4 -4
- package/dist/provider.js +4 -4
- package/dist/styles.css +1 -1
- package/dist/theme.esm.js +633 -468
- package/dist/theme.js +633 -468
- package/dist/themes/ThemeContext.esm.js +15 -15
- package/dist/themes/ThemeContext.js +15 -15
- package/dist/themes/ThemeProvider.esm.js +25 -22
- package/dist/themes/ThemeProvider.js +25 -22
- package/dist/themes/accessibility.esm.js +147 -108
- package/dist/themes/accessibility.js +147 -108
- package/dist/themes/aria-patterns.esm.js +198 -162
- package/dist/themes/aria-patterns.js +198 -162
- package/dist/themes/base-themes.esm.js +14 -11
- package/dist/themes/base-themes.js +14 -11
- package/dist/themes/colorManager.esm.js +101 -83
- package/dist/themes/colorManager.js +101 -83
- package/dist/themes/examples/dark-theme.esm.js +133 -103
- package/dist/themes/examples/dark-theme.js +133 -103
- package/dist/themes/examples/minimal-theme.esm.js +83 -61
- package/dist/themes/examples/minimal-theme.js +83 -61
- package/dist/themes/focus-management.esm.js +202 -143
- package/dist/themes/focus-management.js +202 -143
- package/dist/themes/fontLoader.esm.js +28 -19
- package/dist/themes/fontLoader.js +28 -19
- package/dist/themes/high-contrast.esm.js +152 -104
- package/dist/themes/high-contrast.js +152 -104
- package/dist/themes/inheritance.esm.js +35 -27
- package/dist/themes/inheritance.js +35 -27
- package/dist/themes/keyboard-navigation.esm.js +152 -123
- package/dist/themes/keyboard-navigation.js +152 -123
- package/dist/themes/motion-reduction.esm.js +193 -133
- package/dist/themes/motion-reduction.js +193 -133
- package/dist/themes/navigation.esm.js +146 -146
- package/dist/themes/navigation.js +146 -146
- package/dist/themes/screen-reader.esm.js +159 -94
- package/dist/themes/screen-reader.js +159 -94
- package/dist/themes/systemThemeDetector.esm.js +42 -34
- package/dist/themes/systemThemeDetector.js +42 -34
- package/dist/themes/themeCSSUpdater.esm.js +21 -9
- package/dist/themes/themeCSSUpdater.js +21 -9
- package/dist/themes/themePersistence.esm.js +68 -47
- package/dist/themes/themePersistence.js +68 -47
- package/dist/themes/themes/stan-design.esm.js +633 -468
- package/dist/themes/themes/stan-design.js +633 -468
- package/dist/themes/types.esm.js +301 -287
- package/dist/themes/types.js +301 -287
- package/dist/themes/useSystemTheme.esm.js +4 -4
- package/dist/themes/useSystemTheme.js +4 -4
- package/dist/themes/useTheme.esm.js +4 -4
- package/dist/themes/useTheme.js +4 -4
- package/dist/themes/validation.esm.js +128 -77
- package/dist/themes/validation.js +128 -77
- package/dist/tokens/index.esm.js +15 -4
- package/dist/tokens/index.js +15 -4
- package/dist/tokens/tokenExporter.esm.js +87 -61
- package/dist/tokens/tokenExporter.js +87 -61
- package/dist/tokens/tokenGenerator.esm.js +86 -77
- package/dist/tokens/tokenGenerator.js +86 -77
- package/dist/tokens/tokenManager.esm.js +64 -51
- package/dist/tokens/tokenManager.js +64 -51
- package/dist/tokens/tokenValidator.esm.js +193 -147
- package/dist/tokens/tokenValidator.js +193 -147
- package/dist/tokens/types.esm.js +49 -35
- package/dist/tokens/types.js +49 -35
- package/dist/utils/bundle-analyzer.esm.js +83 -65
- package/dist/utils/bundle-analyzer.js +83 -65
- package/dist/utils/bundle-splitting.esm.js +142 -117
- package/dist/utils/bundle-splitting.js +142 -117
- package/dist/utils/lazy-loading.esm.js +132 -106
- package/dist/utils/lazy-loading.js +132 -106
- package/dist/utils/performance-monitor.esm.js +170 -129
- package/dist/utils/performance-monitor.js +170 -129
- package/dist/utils/tree-shaking.esm.js +69 -61
- package/dist/utils/tree-shaking.js +69 -61
- package/package.json +1 -1
- package/src/index.ts +146 -146
|
@@ -4,7 +4,7 @@ import { SystemThemeDetector, SystemTheme, SystemThemeOptions } from './systemTh
|
|
|
4
4
|
/**
|
|
5
5
|
* React hook for using system theme detection
|
|
6
6
|
*/
|
|
7
|
-
export const useSystemTheme = (options= {}) => {
|
|
7
|
+
export const useSystemTheme = (options: SystemThemeOptions = {}) => {
|
|
8
8
|
const [systemTheme, setSystemTheme] = useState<SystemTheme>('light');
|
|
9
9
|
const detectorRef = useRef<SystemThemeDetector | null>(null);
|
|
10
10
|
|
|
@@ -26,14 +26,14 @@ export const useSystemTheme = (options= {}) => {
|
|
|
26
26
|
};
|
|
27
27
|
}, [options.storageKey, options.enablePersistence]);
|
|
28
28
|
|
|
29
|
-
const setSystemThemePreference = useCallback((theme) => {
|
|
29
|
+
const setSystemThemePreference = useCallback((theme: SystemTheme) => {
|
|
30
30
|
if (detectorRef.current) {
|
|
31
31
|
detectorRef.current.setStoredPreference(theme);
|
|
32
32
|
setSystemTheme(theme);
|
|
33
33
|
}
|
|
34
34
|
}, []);
|
|
35
35
|
|
|
36
|
-
const applySystemThemeCSS = useCallback((theme) => {
|
|
36
|
+
const applySystemThemeCSS = useCallback((theme: SystemTheme) => {
|
|
37
37
|
if (detectorRef.current) {
|
|
38
38
|
detectorRef.current.applySystemThemeCSS(theme);
|
|
39
39
|
}
|
|
@@ -43,6 +43,6 @@ export const useSystemTheme = (options= {}) => {
|
|
|
43
43
|
systemTheme,
|
|
44
44
|
setSystemThemePreference,
|
|
45
45
|
applySystemThemeCSS,
|
|
46
|
-
isSupported) ?? false,
|
|
46
|
+
isSupported: detectorRef.current?.isSupported() ?? false,
|
|
47
47
|
};
|
|
48
48
|
};
|
|
@@ -4,7 +4,7 @@ import { SystemThemeDetector, SystemTheme, SystemThemeOptions } from './systemTh
|
|
|
4
4
|
/**
|
|
5
5
|
* React hook for using system theme detection
|
|
6
6
|
*/
|
|
7
|
-
export const useSystemTheme = (options= {}) => {
|
|
7
|
+
export const useSystemTheme = (options: SystemThemeOptions = {}) => {
|
|
8
8
|
const [systemTheme, setSystemTheme] = useState<SystemTheme>('light');
|
|
9
9
|
const detectorRef = useRef<SystemThemeDetector | null>(null);
|
|
10
10
|
|
|
@@ -26,14 +26,14 @@ export const useSystemTheme = (options= {}) => {
|
|
|
26
26
|
};
|
|
27
27
|
}, [options.storageKey, options.enablePersistence]);
|
|
28
28
|
|
|
29
|
-
const setSystemThemePreference = useCallback((theme) => {
|
|
29
|
+
const setSystemThemePreference = useCallback((theme: SystemTheme) => {
|
|
30
30
|
if (detectorRef.current) {
|
|
31
31
|
detectorRef.current.setStoredPreference(theme);
|
|
32
32
|
setSystemTheme(theme);
|
|
33
33
|
}
|
|
34
34
|
}, []);
|
|
35
35
|
|
|
36
|
-
const applySystemThemeCSS = useCallback((theme) => {
|
|
36
|
+
const applySystemThemeCSS = useCallback((theme: SystemTheme) => {
|
|
37
37
|
if (detectorRef.current) {
|
|
38
38
|
detectorRef.current.applySystemThemeCSS(theme);
|
|
39
39
|
}
|
|
@@ -43,6 +43,6 @@ export const useSystemTheme = (options= {}) => {
|
|
|
43
43
|
systemTheme,
|
|
44
44
|
setSystemThemePreference,
|
|
45
45
|
applySystemThemeCSS,
|
|
46
|
-
isSupported) ?? false,
|
|
46
|
+
isSupported: detectorRef.current?.isSupported() ?? false,
|
|
47
47
|
};
|
|
48
48
|
};
|
|
@@ -21,7 +21,7 @@ import { ThemeContext, ThemeContextType } from './ThemeContext';
|
|
|
21
21
|
* }
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
|
-
export const useTheme = ()=> {
|
|
24
|
+
export const useTheme = (): ThemeContextType => {
|
|
25
25
|
const context = useContext(ThemeContext);
|
|
26
26
|
|
|
27
27
|
if (!context) {
|
|
@@ -46,14 +46,14 @@ export const useTheme = ()=> {
|
|
|
46
46
|
* if (!harveyTheme) return <div>Theme not found</div>;
|
|
47
47
|
*
|
|
48
48
|
* return (
|
|
49
|
-
* <div style={{ color] }}>
|
|
49
|
+
* <div style={{ color: harveyTheme.colors.primary[500] }}>
|
|
50
50
|
* Harvey Theme Preview
|
|
51
51
|
* </div>
|
|
52
52
|
* );
|
|
53
53
|
* }
|
|
54
54
|
* ```
|
|
55
55
|
*/
|
|
56
|
-
export const useThemeByName = (themeName) => {
|
|
56
|
+
export const useThemeByName = (themeName: string) => {
|
|
57
57
|
const { getTheme } = useTheme();
|
|
58
58
|
return getTheme(themeName);
|
|
59
59
|
};
|
|
@@ -81,7 +81,7 @@ export const useThemeByName = (themeName) => {
|
|
|
81
81
|
* }
|
|
82
82
|
* ```
|
|
83
83
|
*/
|
|
84
|
-
export const useThemeAvailable = (themeName)=> {
|
|
84
|
+
export const useThemeAvailable = (themeName: string): boolean => {
|
|
85
85
|
const { availableThemes } = useTheme();
|
|
86
86
|
return availableThemes.includes(themeName);
|
|
87
87
|
};
|
package/dist/themes/useTheme.js
CHANGED
|
@@ -21,7 +21,7 @@ import { ThemeContext, ThemeContextType } from './ThemeContext';
|
|
|
21
21
|
* }
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
|
-
export const useTheme = ()=> {
|
|
24
|
+
export const useTheme = (): ThemeContextType => {
|
|
25
25
|
const context = useContext(ThemeContext);
|
|
26
26
|
|
|
27
27
|
if (!context) {
|
|
@@ -46,14 +46,14 @@ export const useTheme = ()=> {
|
|
|
46
46
|
* if (!harveyTheme) return <div>Theme not found</div>;
|
|
47
47
|
*
|
|
48
48
|
* return (
|
|
49
|
-
* <div style={{ color] }}>
|
|
49
|
+
* <div style={{ color: harveyTheme.colors.primary[500] }}>
|
|
50
50
|
* Harvey Theme Preview
|
|
51
51
|
* </div>
|
|
52
52
|
* );
|
|
53
53
|
* }
|
|
54
54
|
* ```
|
|
55
55
|
*/
|
|
56
|
-
export const useThemeByName = (themeName) => {
|
|
56
|
+
export const useThemeByName = (themeName: string) => {
|
|
57
57
|
const { getTheme } = useTheme();
|
|
58
58
|
return getTheme(themeName);
|
|
59
59
|
};
|
|
@@ -81,7 +81,7 @@ export const useThemeByName = (themeName) => {
|
|
|
81
81
|
* }
|
|
82
82
|
* ```
|
|
83
83
|
*/
|
|
84
|
-
export const useThemeAvailable = (themeName)=> {
|
|
84
|
+
export const useThemeAvailable = (themeName: string): boolean => {
|
|
85
85
|
const { availableThemes } = useTheme();
|
|
86
86
|
return availableThemes.includes(themeName);
|
|
87
87
|
};
|
|
@@ -30,11 +30,11 @@ export class ThemeValidator {
|
|
|
30
30
|
];
|
|
31
31
|
|
|
32
32
|
private static readonly COLOR_FORMATS = {
|
|
33
|
-
hex]{6}|[A-Fa-f0-9]{3})$/,
|
|
34
|
-
rgb
|
|
35
|
-
rgba
|
|
36
|
-
hsl
|
|
37
|
-
hsla
|
|
33
|
+
hex: /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,
|
|
34
|
+
rgb: /^rgb\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*\)$/,
|
|
35
|
+
rgba: /^rgba\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*,\s*[\d.]+\s*\)$/,
|
|
36
|
+
hsl: /^hsl\(\s*\d+\s*,\s*\d+%\s*,\s*\d+%\s*\)$/,
|
|
37
|
+
hsla: /^hsla\(\s*\d+\s*,\s*\d+%\s*,\s*\d+%\s*,\s*[\d.]+\s*\)$/
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
private static readonly FONT_WEIGHTS = [100, 200, 300, 400, 500, 600, 700, 800, 900];
|
|
@@ -42,8 +42,9 @@ export class ThemeValidator {
|
|
|
42
42
|
/**
|
|
43
43
|
* Validate a complete theme configuration
|
|
44
44
|
*/
|
|
45
|
-
static validateTheme(theme)
|
|
46
|
-
const
|
|
45
|
+
static validateTheme(theme: MultiThemeConfig): ThemeValidationResult {
|
|
46
|
+
const errors: ThemeValidationError[] = [];
|
|
47
|
+
const warnings: ThemeValidationWarning[] = [];
|
|
47
48
|
|
|
48
49
|
// Validate required fields
|
|
49
50
|
this.validateRequiredFields(theme, errors);
|
|
@@ -70,7 +71,7 @@ export class ThemeValidator {
|
|
|
70
71
|
this.validateSemanticConsistency(theme, warnings);
|
|
71
72
|
|
|
72
73
|
return {
|
|
73
|
-
isValid=== 0,
|
|
74
|
+
isValid: errors.length === 0,
|
|
74
75
|
errors,
|
|
75
76
|
warnings
|
|
76
77
|
};
|
|
@@ -79,13 +80,15 @@ export class ThemeValidator {
|
|
|
79
80
|
/**
|
|
80
81
|
* Validate that all required fields are present
|
|
81
82
|
*/
|
|
82
|
-
private static validateRequiredFields(theme, errors])
|
|
83
|
+
private static validateRequiredFields(theme: MultiThemeConfig, errors: ThemeValidationError[]): void {
|
|
84
|
+
for (const fieldPath of this.REQUIRED_FIELDS) {
|
|
83
85
|
const value = this.getNestedValue(theme, fieldPath);
|
|
84
86
|
if (value === undefined || value === null || value === '') {
|
|
85
87
|
errors.push({
|
|
86
|
-
path,
|
|
87
|
-
message}' is missing or empty`,
|
|
88
|
-
severity
|
|
88
|
+
path: fieldPath,
|
|
89
|
+
message: `Required field '${fieldPath}' is missing or empty`,
|
|
90
|
+
severity: 'error'
|
|
91
|
+
});
|
|
89
92
|
}
|
|
90
93
|
}
|
|
91
94
|
}
|
|
@@ -93,7 +96,8 @@ export class ThemeValidator {
|
|
|
93
96
|
/**
|
|
94
97
|
* Validate color format consistency
|
|
95
98
|
*/
|
|
96
|
-
private static validateColorFormats(theme, errors], warnings])
|
|
99
|
+
private static validateColorFormats(theme: MultiThemeConfig, errors: ThemeValidationError[], warnings: ThemeValidationWarning[]): void {
|
|
100
|
+
const colorFields = this.getAllColorFields(theme);
|
|
97
101
|
const formats = new Set<string>();
|
|
98
102
|
|
|
99
103
|
for (const { path, value } of colorFields) {
|
|
@@ -102,8 +106,9 @@ export class ThemeValidator {
|
|
|
102
106
|
if (!ColorManager.isValidColor(value)) {
|
|
103
107
|
errors.push({
|
|
104
108
|
path,
|
|
105
|
-
message}'. Expected hex, rgb, hsl, or named color format`,
|
|
106
|
-
severity
|
|
109
|
+
message: `Invalid color format: '${value}'. Expected hex, rgb, hsl, or named color format`,
|
|
110
|
+
severity: 'error'
|
|
111
|
+
});
|
|
107
112
|
} else {
|
|
108
113
|
const format = this.detectColorFormat(value);
|
|
109
114
|
if (format) {
|
|
@@ -116,16 +121,18 @@ export class ThemeValidator {
|
|
|
116
121
|
// Warn if multiple color formats are used
|
|
117
122
|
if (formats.size > 1) {
|
|
118
123
|
warnings.push({
|
|
119
|
-
path,
|
|
120
|
-
message).join(', ')}. Consider using a consistent format for better maintainability`,
|
|
121
|
-
severity
|
|
124
|
+
path: 'colors',
|
|
125
|
+
message: `Multiple color formats detected: ${Array.from(formats).join(', ')}. Consider using a consistent format for better maintainability`,
|
|
126
|
+
severity: 'warning'
|
|
127
|
+
});
|
|
122
128
|
}
|
|
123
129
|
}
|
|
124
130
|
|
|
125
131
|
/**
|
|
126
132
|
* Validate color contrast ratios
|
|
127
133
|
*/
|
|
128
|
-
private static validateColorContrast(theme, warnings])
|
|
134
|
+
private static validateColorContrast(theme: MultiThemeConfig, warnings: ThemeValidationWarning[]): void {
|
|
135
|
+
const textColors = [
|
|
129
136
|
theme.colors?.text?.primary,
|
|
130
137
|
theme.colors?.text?.secondary,
|
|
131
138
|
theme.colors?.text?.muted
|
|
@@ -144,22 +151,25 @@ export class ThemeValidator {
|
|
|
144
151
|
|
|
145
152
|
if (!accessibility.aa) {
|
|
146
153
|
warnings.push({
|
|
147
|
-
path,
|
|
148
|
-
message)}}' and '${bgColor}' is below WCAG AA standard (4.5)`,
|
|
149
|
-
severity
|
|
154
|
+
path: 'colors',
|
|
155
|
+
message: `Color contrast ratio ${accessibility.contrastRatio.toFixed(2)}:1 between '${textColor}' and '${bgColor}' is below WCAG AA standard (4.5:1)`,
|
|
156
|
+
severity: 'warning'
|
|
157
|
+
});
|
|
150
158
|
} else if (!accessibility.aaa) {
|
|
151
159
|
warnings.push({
|
|
152
|
-
path,
|
|
153
|
-
message)}}' and '${bgColor}' is below WCAG AAA standard (7)`,
|
|
154
|
-
severity
|
|
160
|
+
path: 'colors',
|
|
161
|
+
message: `Color contrast ratio ${accessibility.contrastRatio.toFixed(2)}:1 between '${textColor}' and '${bgColor}' is below WCAG AAA standard (7:1)`,
|
|
162
|
+
severity: 'info'
|
|
163
|
+
});
|
|
155
164
|
}
|
|
156
165
|
|
|
157
166
|
// Add accessibility recommendations
|
|
158
167
|
if (accessibility.recommended.length > 0) {
|
|
159
168
|
warnings.push({
|
|
160
|
-
path,
|
|
161
|
-
message; ')}`,
|
|
162
|
-
severity
|
|
169
|
+
path: 'colors',
|
|
170
|
+
message: `Accessibility recommendations: ${accessibility.recommended.join('; ')}`,
|
|
171
|
+
severity: 'info'
|
|
172
|
+
});
|
|
163
173
|
}
|
|
164
174
|
}
|
|
165
175
|
}
|
|
@@ -169,13 +179,16 @@ export class ThemeValidator {
|
|
|
169
179
|
/**
|
|
170
180
|
* Validate font configurations
|
|
171
181
|
*/
|
|
172
|
-
private static validateFontConfigurations(theme, warnings])
|
|
182
|
+
private static validateFontConfigurations(theme: MultiThemeConfig, warnings: ThemeValidationWarning[]): void {
|
|
183
|
+
// Validate font weights
|
|
184
|
+
if (theme.fonts?.primary?.weights) {
|
|
173
185
|
for (const weight of theme.fonts.primary.weights) {
|
|
174
186
|
if (!this.FONT_WEIGHTS.includes(weight)) {
|
|
175
187
|
warnings.push({
|
|
176
|
-
path,
|
|
177
|
-
message} is not a standard CSS font weight. Consider using, ')}`,
|
|
178
|
-
severity
|
|
188
|
+
path: 'fonts.primary.weights',
|
|
189
|
+
message: `Font weight ${weight} is not a standard CSS font weight. Consider using: ${this.FONT_WEIGHTS.join(', ')}`,
|
|
190
|
+
severity: 'warning'
|
|
191
|
+
});
|
|
179
192
|
}
|
|
180
193
|
}
|
|
181
194
|
}
|
|
@@ -189,9 +202,10 @@ export class ThemeValidator {
|
|
|
189
202
|
for (let i = 1; i < numericSizes.length; i++) {
|
|
190
203
|
if (numericSizes[i] <= numericSizes[i - 1]) {
|
|
191
204
|
warnings.push({
|
|
192
|
-
path,
|
|
193
|
-
message]} followed by ${numericSizes[i]}`,
|
|
194
|
-
severity
|
|
205
|
+
path: 'fonts.primary.sizes',
|
|
206
|
+
message: `Font sizes should be in ascending order. Found: ${numericSizes[i - 1]} followed by ${numericSizes[i]}`,
|
|
207
|
+
severity: 'warning'
|
|
208
|
+
});
|
|
195
209
|
}
|
|
196
210
|
}
|
|
197
211
|
}
|
|
@@ -202,9 +216,10 @@ export class ThemeValidator {
|
|
|
202
216
|
const family = theme.fonts.primary.family;
|
|
203
217
|
if (!family.includes(',') && !family.includes('"') && !family.includes("'")) {
|
|
204
218
|
warnings.push({
|
|
205
|
-
path,
|
|
206
|
-
message}' should include fallback fonts for better cross-platform compatibility`,
|
|
207
|
-
severity
|
|
219
|
+
path: 'fonts.primary.family',
|
|
220
|
+
message: `Font family '${family}' should include fallback fonts for better cross-platform compatibility`,
|
|
221
|
+
severity: 'warning'
|
|
222
|
+
});
|
|
208
223
|
}
|
|
209
224
|
}
|
|
210
225
|
}
|
|
@@ -212,7 +227,8 @@ export class ThemeValidator {
|
|
|
212
227
|
/**
|
|
213
228
|
* Validate spacing scales
|
|
214
229
|
*/
|
|
215
|
-
private static validateSpacingScales(theme, warnings])
|
|
230
|
+
private static validateSpacingScales(theme: MultiThemeConfig, warnings: ThemeValidationWarning[]): void {
|
|
231
|
+
if (theme.spacing?.scale) {
|
|
216
232
|
const scales = Object.values(theme.spacing.scale);
|
|
217
233
|
const numericScales = scales.map(scale => parseFloat(scale)).filter(scale => !isNaN(scale));
|
|
218
234
|
|
|
@@ -228,9 +244,10 @@ export class ThemeValidator {
|
|
|
228
244
|
|
|
229
245
|
if (variance > 0.1) { // High variance indicates inconsistent spacing
|
|
230
246
|
warnings.push({
|
|
231
|
-
path,
|
|
232
|
-
message
|
|
233
|
-
severity
|
|
247
|
+
path: 'spacing.scale',
|
|
248
|
+
message: `Spacing scale appears inconsistent. Consider using a mathematical scale (e.g., 1.5x or 2x multiplier) for better visual harmony`,
|
|
249
|
+
severity: 'warning'
|
|
250
|
+
});
|
|
234
251
|
}
|
|
235
252
|
}
|
|
236
253
|
}
|
|
@@ -239,30 +256,34 @@ export class ThemeValidator {
|
|
|
239
256
|
/**
|
|
240
257
|
* Validate navigation configurations
|
|
241
258
|
*/
|
|
242
|
-
private static validateNavigationConfigurations(theme, _errors], warnings])
|
|
259
|
+
private static validateNavigationConfigurations(theme: MultiThemeConfig, _errors: ThemeValidationError[], warnings: ThemeValidationWarning[]): void {
|
|
260
|
+
if (theme.navigation) {
|
|
243
261
|
// Validate layout and behavior combinations
|
|
244
262
|
const { layout, behavior } = theme.navigation;
|
|
245
263
|
|
|
246
264
|
if (layout === 'sidebar' && behavior === 'floating') {
|
|
247
265
|
warnings.push({
|
|
248
|
-
path,
|
|
249
|
-
message,
|
|
250
|
-
severity
|
|
266
|
+
path: 'navigation',
|
|
267
|
+
message: 'Sidebar layout with floating behavior may cause usability issues. Consider using static or sticky behavior',
|
|
268
|
+
severity: 'warning'
|
|
269
|
+
});
|
|
251
270
|
}
|
|
252
271
|
|
|
253
272
|
if (layout === 'tabs' && behavior === 'overlay') {
|
|
254
273
|
warnings.push({
|
|
255
|
-
path,
|
|
256
|
-
message,
|
|
257
|
-
severity
|
|
274
|
+
path: 'navigation',
|
|
275
|
+
message: 'Tab layout with overlay behavior is unusual. Consider using static or sticky behavior',
|
|
276
|
+
severity: 'warning'
|
|
277
|
+
});
|
|
258
278
|
}
|
|
259
279
|
|
|
260
280
|
// Validate responsive behavior
|
|
261
281
|
if (theme.navigation.responsive === 'desktop-first' && layout === 'horizontal') {
|
|
262
282
|
warnings.push({
|
|
263
|
-
path,
|
|
264
|
-
message,
|
|
265
|
-
severity
|
|
283
|
+
path: 'navigation',
|
|
284
|
+
message: 'Desktop-first responsive approach with horizontal layout may cause mobile usability issues',
|
|
285
|
+
severity: 'warning'
|
|
286
|
+
});
|
|
266
287
|
}
|
|
267
288
|
}
|
|
268
289
|
}
|
|
@@ -270,29 +291,33 @@ export class ThemeValidator {
|
|
|
270
291
|
/**
|
|
271
292
|
* Validate metadata
|
|
272
293
|
*/
|
|
273
|
-
private static validateMetadata(theme, errors], warnings])
|
|
294
|
+
private static validateMetadata(theme: MultiThemeConfig, errors: ThemeValidationError[], warnings: ThemeValidationWarning[]): void {
|
|
295
|
+
if (theme.meta) {
|
|
274
296
|
// Validate version format
|
|
275
297
|
if (theme.meta.version && !/^\d+\.\d+\.\d+/.test(theme.meta.version)) {
|
|
276
298
|
warnings.push({
|
|
277
|
-
path,
|
|
278
|
-
message}' should follow semantic versioning (e.g., 1.0.0)`,
|
|
279
|
-
severity
|
|
299
|
+
path: 'meta.version',
|
|
300
|
+
message: `Version '${theme.meta.version}' should follow semantic versioning (e.g., 1.0.0)`,
|
|
301
|
+
severity: 'warning'
|
|
302
|
+
});
|
|
280
303
|
}
|
|
281
304
|
|
|
282
305
|
// Validate category
|
|
283
306
|
if (theme.meta.category && !['brand', 'enterprise', 'custom', 'accessibility'].includes(theme.meta.category)) {
|
|
284
307
|
errors.push({
|
|
285
|
-
path,
|
|
286
|
-
message}'. Must be one of, enterprise, custom, accessibility`,
|
|
287
|
-
severity
|
|
308
|
+
path: 'meta.category',
|
|
309
|
+
message: `Invalid category '${theme.meta.category}'. Must be one of: brand, enterprise, custom, accessibility`,
|
|
310
|
+
severity: 'error'
|
|
311
|
+
});
|
|
288
312
|
}
|
|
289
313
|
|
|
290
314
|
// Validate tags
|
|
291
315
|
if (theme.meta.tags && theme.meta.tags.length > 10) {
|
|
292
316
|
warnings.push({
|
|
293
|
-
path,
|
|
294
|
-
message} tags. Consider limiting to 10 tags for better organization`,
|
|
295
|
-
severity
|
|
317
|
+
path: 'meta.tags',
|
|
318
|
+
message: `Theme has ${theme.meta.tags.length} tags. Consider limiting to 10 tags for better organization`,
|
|
319
|
+
severity: 'warning'
|
|
320
|
+
});
|
|
296
321
|
}
|
|
297
322
|
}
|
|
298
323
|
}
|
|
@@ -300,7 +325,9 @@ export class ThemeValidator {
|
|
|
300
325
|
/**
|
|
301
326
|
* Validate semantic consistency
|
|
302
327
|
*/
|
|
303
|
-
private static validateSemanticConsistency(theme, warnings])
|
|
328
|
+
private static validateSemanticConsistency(theme: MultiThemeConfig, warnings: ThemeValidationWarning[]): void {
|
|
329
|
+
// Check if semantic colors are distinct from primary colors
|
|
330
|
+
if (theme.colors?.semantic && theme.colors?.primary) {
|
|
304
331
|
const semanticColors = Object.values(theme.colors.semantic);
|
|
305
332
|
const primaryColors = Object.values(theme.colors.primary);
|
|
306
333
|
|
|
@@ -308,9 +335,10 @@ export class ThemeValidator {
|
|
|
308
335
|
for (const primaryColor of primaryColors) {
|
|
309
336
|
if (this.colorsAreSimilar(semanticColor, primaryColor)) {
|
|
310
337
|
warnings.push({
|
|
311
|
-
path,
|
|
312
|
-
message}' is too similar to primary color '${primaryColor}'. Consider using more distinct colors for better semantic clarity`,
|
|
313
|
-
severity
|
|
338
|
+
path: 'colors.semantic',
|
|
339
|
+
message: `Semantic color '${semanticColor}' is too similar to primary color '${primaryColor}'. Consider using more distinct colors for better semantic clarity`,
|
|
340
|
+
severity: 'warning'
|
|
341
|
+
});
|
|
314
342
|
}
|
|
315
343
|
}
|
|
316
344
|
}
|
|
@@ -318,19 +346,24 @@ export class ThemeValidator {
|
|
|
318
346
|
}
|
|
319
347
|
|
|
320
348
|
/**
|
|
321
|
-
* Helper
|
|
349
|
+
* Helper: Get nested value from object using dot notation
|
|
350
|
+
*/
|
|
351
|
+
private static getNestedValue(obj: any, path: string): any {
|
|
352
|
+
return path.split('.').reduce((current, key) => current?.[key], obj);
|
|
322
353
|
}
|
|
323
354
|
|
|
324
355
|
/**
|
|
325
|
-
* Helper
|
|
326
|
-
|
|
356
|
+
* Helper: Get all color fields from theme
|
|
357
|
+
*/
|
|
358
|
+
private static getAllColorFields(theme: MultiThemeConfig): Array<{ path: string; value: any }> {
|
|
359
|
+
const fields: Array<{ path: string; value: any }> = [];
|
|
327
360
|
|
|
328
|
-
const traverseColors = (obj, path) => {
|
|
361
|
+
const traverseColors = (obj: any, path: string) => {
|
|
329
362
|
if (obj && typeof obj === 'object') {
|
|
330
363
|
for (const [key, value] of Object.entries(obj)) {
|
|
331
|
-
const currentPath = path ? `${path}.${key}` ;
|
|
364
|
+
const currentPath = path ? `${path}.${key}` : key;
|
|
332
365
|
if (typeof value === 'string' && this.isColorValue(value)) {
|
|
333
|
-
fields.push({ path, value });
|
|
366
|
+
fields.push({ path: currentPath, value });
|
|
334
367
|
} else if (typeof value === 'object') {
|
|
335
368
|
traverseColors(value, currentPath);
|
|
336
369
|
}
|
|
@@ -343,7 +376,10 @@ export class ThemeValidator {
|
|
|
343
376
|
}
|
|
344
377
|
|
|
345
378
|
/**
|
|
346
|
-
* Helper
|
|
379
|
+
* Helper: Detect color format
|
|
380
|
+
*/
|
|
381
|
+
private static detectColorFormat(color: string): string | null {
|
|
382
|
+
for (const [format, regex] of Object.entries(this.COLOR_FORMATS)) {
|
|
347
383
|
if (regex.test(color)) {
|
|
348
384
|
return format;
|
|
349
385
|
}
|
|
@@ -352,7 +388,10 @@ export class ThemeValidator {
|
|
|
352
388
|
}
|
|
353
389
|
|
|
354
390
|
/**
|
|
355
|
-
* Helper
|
|
391
|
+
* Helper: Check if value looks like a color
|
|
392
|
+
*/
|
|
393
|
+
private static isColorValue(value: string): boolean {
|
|
394
|
+
// Accept any string that might be a color, let detectColorFormat validate it
|
|
356
395
|
return value.startsWith('#') ||
|
|
357
396
|
value.startsWith('rgb') ||
|
|
358
397
|
value.startsWith('hsl') ||
|
|
@@ -366,7 +405,11 @@ export class ThemeValidator {
|
|
|
366
405
|
}
|
|
367
406
|
|
|
368
407
|
/**
|
|
369
|
-
* Helper
|
|
408
|
+
* Helper: Calculate color contrast ratio
|
|
409
|
+
*/
|
|
410
|
+
private static calculateColorContrast(color1: string, color2: string): number {
|
|
411
|
+
try {
|
|
412
|
+
const luminance1 = this.getLuminance(color1);
|
|
370
413
|
const luminance2 = this.getLuminance(color2);
|
|
371
414
|
|
|
372
415
|
const lighter = Math.max(luminance1, luminance2);
|
|
@@ -379,7 +422,11 @@ export class ThemeValidator {
|
|
|
379
422
|
}
|
|
380
423
|
|
|
381
424
|
/**
|
|
382
|
-
* Helper
|
|
425
|
+
* Helper: Get luminance of a color
|
|
426
|
+
*/
|
|
427
|
+
private static getLuminance(color: string): number {
|
|
428
|
+
// Handle CSS variables and other formats
|
|
429
|
+
if (color.startsWith('var(--') || color === 'transparent' || color === 'currentColor' || color === 'inherit') {
|
|
383
430
|
return 0.5; // Default fallback
|
|
384
431
|
}
|
|
385
432
|
|
|
@@ -402,7 +449,11 @@ export class ThemeValidator {
|
|
|
402
449
|
}
|
|
403
450
|
|
|
404
451
|
/**
|
|
405
|
-
* Helper
|
|
452
|
+
* Helper: Check if two colors are similar
|
|
453
|
+
*/
|
|
454
|
+
private static colorsAreSimilar(color1: string, color2: string): boolean {
|
|
455
|
+
try {
|
|
456
|
+
const contrast = this.calculateColorContrast(color1, color2);
|
|
406
457
|
return contrast < 2.0; // Very low contrast indicates similar colors
|
|
407
458
|
} catch {
|
|
408
459
|
return false;
|