@shohojdhara/atomix 0.3.14 → 0.4.0
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 +20 -0
- package/build-tools/EXAMPLES.md +372 -0
- package/build-tools/README.md +242 -0
- package/build-tools/__tests__/error-handler.test.js +230 -0
- package/build-tools/__tests__/index.test.js +141 -0
- package/build-tools/__tests__/rollup-plugin.test.js +194 -0
- package/build-tools/__tests__/utils.test.js +161 -0
- package/build-tools/__tests__/vite-plugin.test.js +129 -0
- package/build-tools/__tests__/webpack-loader.test.js +190 -0
- package/build-tools/error-handler.js +308 -0
- package/build-tools/index.d.ts +44 -0
- package/build-tools/index.js +88 -0
- package/build-tools/package.json +50 -0
- package/build-tools/rollup-plugin.js +236 -0
- package/build-tools/types.d.ts +163 -0
- package/build-tools/utils.js +203 -0
- package/build-tools/vite-plugin.js +161 -0
- package/build-tools/webpack-loader.js +123 -0
- package/dist/atomix.css +21044 -2618
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +77 -3
- package/dist/atomix.min.css.map +1 -1
- package/dist/build-tools/EXAMPLES.md +372 -0
- package/dist/build-tools/README.md +242 -0
- package/dist/build-tools/__tests__/error-handler.test.js +230 -0
- package/dist/build-tools/__tests__/index.test.js +141 -0
- package/dist/build-tools/__tests__/rollup-plugin.test.js +194 -0
- package/dist/build-tools/__tests__/utils.test.js +161 -0
- package/dist/build-tools/__tests__/vite-plugin.test.js +129 -0
- package/dist/build-tools/__tests__/webpack-loader.test.js +190 -0
- package/dist/build-tools/error-handler.js +308 -0
- package/dist/build-tools/index.d.ts +44 -0
- package/dist/build-tools/index.js +88 -0
- package/dist/build-tools/package.json +50 -0
- package/dist/build-tools/rollup-plugin.js +236 -0
- package/dist/build-tools/types.d.ts +163 -0
- package/dist/build-tools/utils.js +203 -0
- package/dist/build-tools/vite-plugin.js +161 -0
- package/dist/build-tools/webpack-loader.js +123 -0
- package/dist/charts.d.ts +1 -1
- package/dist/charts.js +86 -57
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +136 -112
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +2 -5
- package/dist/forms.js +140 -128
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +1 -1
- package/dist/heavy.js +136 -112
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +152 -78
- package/dist/index.esm.js +346 -340
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +359 -353
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/layout.js.map +1 -1
- package/dist/theme.d.ts +9 -9
- package/dist/theme.js.map +1 -1
- package/package.json +23 -8
- package/scripts/atomix-cli.js +170 -73
- package/scripts/cli/__tests__/README.md +81 -0
- package/scripts/cli/__tests__/basic.test.js +115 -0
- package/scripts/cli/__tests__/component-generator.test.js +332 -0
- package/scripts/cli/__tests__/integration.test.js +327 -0
- package/scripts/cli/__tests__/test-setup.js +133 -0
- package/scripts/cli/__tests__/token-manager.test.js +251 -0
- package/scripts/cli/__tests__/utils.test.js +161 -0
- package/scripts/cli/component-generator.js +253 -299
- package/scripts/cli/dependency-checker.js +355 -0
- package/scripts/cli/interactive-init.js +46 -5
- package/scripts/cli/template-manager.js +0 -2
- package/scripts/cli/templates/common-templates.js +636 -0
- package/scripts/cli/templates/composable-templates.js +148 -126
- package/scripts/cli/templates/index.js +23 -16
- package/scripts/cli/templates/project-templates.js +151 -23
- package/scripts/cli/templates/react-templates.js +280 -210
- package/scripts/cli/templates/scss-templates.js +90 -91
- package/scripts/cli/templates/testing-templates.js +206 -27
- package/scripts/cli/templates/testing-utils.js +278 -0
- package/scripts/cli/templates/types-templates.js +70 -56
- package/scripts/cli/theme-bridge.js +8 -2
- package/scripts/cli/token-manager.js +318 -206
- package/scripts/cli/utils.js +0 -1
- package/src/components/Accordion/Accordion.stories.tsx +358 -850
- package/src/components/Accordion/Accordion.test.tsx +70 -50
- package/src/components/Accordion/Accordion.tsx +99 -94
- package/src/components/AtomixGlass/AtomixGlass.test.tsx +1 -1
- package/src/components/AtomixGlass/AtomixGlass.tsx +80 -39
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +103 -81
- package/src/components/AtomixGlass/GlassFilter.tsx +9 -16
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +8 -7
- package/src/components/AtomixGlass/glass-utils.ts +6 -5
- package/src/components/AtomixGlass/shader-utils.ts +133 -52
- package/src/components/AtomixGlass/stories/Customization.stories.tsx +131 -0
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +2957 -2853
- package/src/components/AtomixGlass/stories/Modes.stories.tsx +1 -1
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +348 -0
- package/src/components/AtomixGlass/stories/Performance.stories.tsx +103 -0
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +51 -36
- package/src/components/AtomixGlass/stories/{ShaderVariants.stories.tsx → Shaders.stories.tsx} +2 -2
- package/src/components/AtomixGlass/stories/shared-components.tsx +90 -190
- package/src/components/Avatar/Avatar.stories.tsx +195 -0
- package/src/components/Avatar/Avatar.tsx +58 -56
- package/src/components/Badge/Badge.stories.tsx +122 -352
- package/src/components/Badge/Badge.test.tsx +41 -41
- package/src/components/Badge/Badge.tsx +64 -62
- package/src/components/Block/Block.stories.tsx +30 -11
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +142 -23
- package/src/components/Breadcrumb/Breadcrumb.tsx +62 -60
- package/src/components/Button/Button.stories.tsx +454 -1126
- package/src/components/Button/Button.test.tsx +123 -0
- package/src/components/Button/Button.tsx +88 -60
- package/src/components/Button/ButtonGroup.stories.tsx +376 -215
- package/src/components/Button/ButtonGroup.tsx +4 -15
- package/src/components/Callout/Callout.stories.tsx +316 -568
- package/src/components/Card/Card.stories.tsx +292 -81
- package/src/components/Card/Card.tsx +30 -14
- package/src/components/Chart/AreaChart.tsx +1 -1
- package/src/components/Chart/CandlestickChart.tsx +23 -16
- package/src/components/Chart/Chart.stories.tsx +153 -16
- package/src/components/Chart/Chart.tsx +40 -44
- package/src/components/Chart/ChartRenderer.tsx +39 -12
- package/src/components/Chart/ChartToolbar.tsx +21 -5
- package/src/components/Chart/DonutChart.tsx +1 -1
- package/src/components/Chart/FunnelChart.tsx +4 -1
- package/src/components/Chart/GaugeChart.tsx +3 -1
- package/src/components/Chart/HeatmapChart.tsx +50 -37
- package/src/components/Chart/LineChart.tsx +3 -2
- package/src/components/Chart/MultiAxisChart.tsx +24 -16
- package/src/components/Chart/RadarChart.tsx +19 -17
- package/src/components/Chart/ScatterChart.tsx +29 -21
- package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +152 -66
- package/src/components/ColorModeToggle/ColorModeToggle.tsx +15 -3
- package/src/components/Countdown/Countdown.stories.tsx +114 -7
- package/src/components/DataTable/DataTable.stories.tsx +349 -144
- package/src/components/DataTable/DataTable.test.tsx +26 -148
- package/src/components/DataTable/DataTable.tsx +485 -456
- package/src/components/DatePicker/DatePicker.stories.tsx +310 -1066
- package/src/components/DatePicker/DatePicker.tsx +31 -26
- package/src/components/Dropdown/Dropdown.stories.tsx +153 -36
- package/src/components/Dropdown/Dropdown.tsx +313 -299
- package/src/components/EdgePanel/EdgePanel.stories.tsx +221 -25
- package/src/components/EdgePanel/EdgePanel.tsx +1 -3
- package/src/components/Footer/Footer.stories.tsx +396 -327
- package/src/components/Footer/Footer.tsx +130 -128
- package/src/components/Footer/FooterLink.tsx +2 -2
- package/src/components/Form/Checkbox.stories.tsx +140 -6
- package/src/components/Form/Checkbox.test.tsx +63 -0
- package/src/components/Form/Checkbox.tsx +122 -78
- package/src/components/Form/Form.stories.tsx +110 -19
- package/src/components/Form/FormGroup.stories.tsx +127 -4
- package/src/components/Form/Input.stories.tsx +22 -39
- package/src/components/Form/Input.test.tsx +38 -44
- package/src/components/Form/Radio.stories.tsx +146 -17
- package/src/components/Form/Radio.tsx +68 -66
- package/src/components/Form/Select.stories.tsx +140 -8
- package/src/components/Form/Select.tsx +184 -182
- package/src/components/Form/Textarea.stories.tsx +149 -6
- package/src/components/Form/Textarea.test.tsx +27 -32
- package/src/components/Hero/Hero.stories.tsx +372 -38
- package/src/components/Hero/Hero.tsx +201 -55
- package/src/components/Icon/index.ts +7 -1
- package/src/components/List/List.stories.tsx +141 -3
- package/src/components/List/List.tsx +19 -23
- package/src/components/Modal/Modal.stories.tsx +183 -43
- package/src/components/Modal/Modal.tsx +130 -127
- package/src/components/Navigation/Menu/MegaMenu.tsx +70 -70
- package/src/components/Navigation/Nav/NavDropdown.tsx +1 -5
- package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +128 -28
- package/src/components/Navigation/SideMenu/SideMenu.tsx +5 -7
- package/src/components/Navigation/SideMenu/SideMenuItem.tsx +4 -5
- package/src/components/Pagination/Pagination.stories.tsx +7 -4
- package/src/components/Pagination/Pagination.tsx +199 -202
- package/src/components/PhotoViewer/PhotoViewer.tsx +4 -1
- package/src/components/Popover/Popover.stories.tsx +354 -97
- package/src/components/Popover/Popover.tsx +41 -37
- package/src/components/Progress/Progress.stories.tsx +160 -7
- package/src/components/River/River.stories.tsx +3 -2
- package/src/components/SectionIntro/SectionIntro.stories.tsx +239 -47
- package/src/components/Slider/Slider.stories.tsx +12 -4
- package/src/components/Spinner/Spinner.stories.tsx +104 -8
- package/src/components/Spinner/Spinner.test.tsx +23 -23
- package/src/components/Spinner/Spinner.tsx +43 -46
- package/src/components/Steps/Steps.stories.tsx +173 -42
- package/src/components/Tabs/Tabs.stories.tsx +141 -12
- package/src/components/Tabs/Tabs.tsx +74 -72
- package/src/components/Testimonial/Testimonial.stories.tsx +120 -3
- package/src/components/Todo/Todo.stories.tsx +198 -9
- package/src/components/Toggle/Toggle.stories.tsx +137 -36
- package/src/components/Toggle/Toggle.test.tsx +65 -70
- package/src/components/Toggle/Toggle.tsx +4 -1
- package/src/components/Tooltip/Tooltip.stories.tsx +194 -100
- package/src/components/Tooltip/Tooltip.tsx +104 -106
- package/src/components/Upload/Upload.stories.tsx +241 -150
- package/src/components/Upload/Upload.tsx +287 -283
- package/src/components/VideoPlayer/VideoPlayer.tsx +6 -1
- package/src/components/index.ts +13 -2
- package/src/layouts/Grid/Grid.stories.tsx +9 -3
- package/src/layouts/MasonryGrid/MasonryGrid.tsx +5 -1
- package/src/lib/README.md +2 -2
- package/src/lib/__tests__/theme-tools.test.ts +219 -0
- package/src/lib/composables/index.ts +2 -2
- package/src/lib/composables/shared-mouse-tracker.ts +13 -14
- package/src/lib/composables/useAtomixGlass.ts +126 -97
- package/src/lib/composables/useChartExport.ts +3 -8
- package/src/lib/composables/useDataTable.ts +72 -43
- package/src/lib/composables/useHero.ts +58 -14
- package/src/lib/composables/useHeroBackgroundSlider.ts +2 -9
- package/src/lib/composables/useInput.ts +10 -8
- package/src/lib/composables/useSideMenu.ts +6 -5
- package/src/lib/composables/useTooltip.ts +1 -2
- package/src/lib/composables/useVideoPlayer.ts +44 -35
- package/src/lib/config/index.ts +154 -154
- package/src/lib/constants/components.ts +9 -32
- package/src/lib/constants/cssVariables.ts +29 -29
- package/src/lib/hooks/__tests__/useComponentCustomization.test.ts +2 -6
- package/src/lib/hooks/index.ts +1 -1
- package/src/lib/hooks/useComponentCustomization.ts +11 -17
- package/src/lib/hooks/usePerformanceMonitor.ts +6 -7
- package/src/lib/patterns/__tests__/slots.test.ts +1 -1
- package/src/lib/patterns/index.ts +1 -1
- package/src/lib/patterns/slots.tsx +8 -13
- package/src/lib/storybook/InteractiveDemo.tsx +13 -18
- package/src/lib/storybook/PreviewContainer.tsx +1 -1
- package/src/lib/storybook/VariantsGrid.tsx +3 -7
- package/src/lib/storybook/index.ts +1 -1
- package/src/lib/theme/adapters/cssVariableMapper.ts +47 -74
- package/src/lib/theme/adapters/index.ts +3 -9
- package/src/lib/theme/adapters/themeAdapter.ts +41 -26
- package/src/lib/theme/config/index.ts +1 -1
- package/src/lib/theme/config/types.ts +2 -2
- package/src/lib/theme/config/validator.ts +10 -5
- package/src/lib/theme/constants/constants.ts +2 -2
- package/src/lib/theme/constants/index.ts +1 -2
- package/src/lib/theme/core/__tests__/createTheme.test.ts +20 -22
- package/src/lib/theme/core/composeTheme.ts +32 -26
- package/src/lib/theme/core/createTheme.ts +1 -1
- package/src/lib/theme/core/createThemeObject.ts +308 -301
- package/src/lib/theme/core/index.ts +3 -3
- package/src/lib/theme/devtools/CLI.ts +107 -105
- package/src/lib/theme/devtools/Comparator.tsx +50 -32
- package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +50 -48
- package/src/lib/theme/devtools/DesignTokensCustomizer.tsx +257 -63
- package/src/lib/theme/devtools/Inspector.tsx +75 -60
- package/src/lib/theme/devtools/LiveEditor.tsx +97 -76
- package/src/lib/theme/devtools/Preview.tsx +150 -106
- package/src/lib/theme/devtools/ThemeValidator.ts +29 -21
- package/src/lib/theme/devtools/index.ts +3 -9
- package/src/lib/theme/devtools/useHistory.ts +23 -21
- package/src/lib/theme/errors/errors.ts +12 -11
- package/src/lib/theme/errors/index.ts +2 -7
- package/src/lib/theme/generators/generateCSS.ts +9 -13
- package/src/lib/theme/generators/generateCSSNested.ts +1 -6
- package/src/lib/theme/generators/generateCSSVariables.ts +673 -630
- package/src/lib/theme/generators/index.ts +1 -4
- package/src/lib/theme/i18n/index.ts +1 -1
- package/src/lib/theme/i18n/rtl.ts +13 -13
- package/src/lib/theme/index.ts +7 -16
- package/src/lib/theme/runtime/ThemeApplicator.ts +4 -4
- package/src/lib/theme/runtime/ThemeContext.tsx +1 -1
- package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +19 -23
- package/src/lib/theme/runtime/ThemeProvider.tsx +230 -239
- package/src/lib/theme/runtime/__tests__/ThemeProvider.integration.test.tsx +1 -1
- package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +24 -29
- package/src/lib/theme/runtime/index.ts +2 -5
- package/src/lib/theme/runtime/useTheme.ts +18 -18
- package/src/lib/theme/runtime/useThemeTokens.ts +22 -22
- package/src/lib/theme/test/testTheme.ts +15 -16
- package/src/lib/theme/tokens/index.ts +2 -7
- package/src/lib/theme/tokens/tokens.ts +25 -24
- package/src/lib/theme/types.ts +428 -411
- package/src/lib/theme/utils/__tests__/themeValidation.test.ts +3 -3
- package/src/lib/theme/utils/componentTheming.ts +18 -18
- package/src/lib/theme/utils/domUtils.ts +277 -289
- package/src/lib/theme/utils/index.ts +1 -2
- package/src/lib/theme/utils/injectCSS.ts +10 -14
- package/src/lib/theme/utils/naming.ts +20 -16
- package/src/lib/theme/utils/themeHelpers.ts +10 -12
- package/src/lib/theme/utils/themeUtils.ts +85 -86
- package/src/lib/theme/utils/themeValidation.ts +82 -33
- package/src/lib/theme-tools.ts +8 -6
- package/src/lib/types/components.ts +172 -71
- package/src/lib/types/partProps.ts +1 -1
- package/src/lib/utils/__tests__/csv.test.ts +45 -0
- package/src/lib/utils/componentUtils.ts +8 -12
- package/src/lib/utils/csv.ts +19 -0
- package/src/lib/utils/dataTableExport.ts +2 -15
- package/src/lib/utils/fontPreloader.ts +10 -19
- package/src/lib/utils/icons.ts +4 -1
- package/src/lib/utils/index.ts +2 -6
- package/src/lib/utils/memoryMonitor.ts +10 -8
- package/src/lib/utils/themeNaming.ts +2 -2
- package/src/styles/01-settings/_index.scss +1 -1
- package/src/styles/01-settings/_settings.accordion.scss +28 -7
- package/src/styles/01-settings/_settings.colors.scss +11 -11
- package/src/styles/01-settings/_settings.design-tokens.scss +61 -50
- package/src/styles/01-settings/_settings.navbar.scss +1 -1
- package/src/styles/01-settings/_settings.spacing.scss +3 -4
- package/src/styles/01-settings/_settings.tooltip.scss +1 -1
- package/src/styles/01-settings/_settings.typography.scss +4 -4
- package/src/styles/02-tools/_tools.button.scss +51 -21
- package/src/styles/02-tools/_tools.utility-api.scss +38 -12
- package/src/styles/03-generic/_generic.root.scss +4 -3
- package/src/styles/06-components/_components.accordion.scss +56 -14
- package/src/styles/06-components/_components.atomix-glass.scss +13 -9
- package/src/styles/06-components/_components.button.scss +16 -4
- package/src/styles/06-components/_components.callout.scss +27 -21
- package/src/styles/06-components/_components.card.scss +5 -14
- package/src/styles/06-components/_components.chart.scss +22 -19
- package/src/styles/06-components/_components.checkbox.scss +25 -17
- package/src/styles/06-components/_components.color-mode-toggle.scss +3 -1
- package/src/styles/06-components/_components.edge-panel.scss +9 -2
- package/src/styles/06-components/_components.footer.scss +1 -1
- package/src/styles/06-components/_components.side-menu.scss +5 -5
- package/src/styles/06-components/_components.toggle.scss +18 -0
- package/src/styles/06-components/_index.scss +1 -1
- package/src/styles/06-components/old.chart.styles.scss +0 -2
- package/src/styles/99-utilities/_index.scss +2 -0
- package/src/styles/99-utilities/_utilities.border.scss +69 -27
- package/src/styles/99-utilities/_utilities.display.scss +1 -1
- package/src/styles/99-utilities/_utilities.opacity.scss +10 -0
- package/src/styles/99-utilities/_utilities.position.scss +16 -9
- package/src/styles/99-utilities/_utilities.scss +2 -0
- package/src/styles/99-utilities/_utilities.sizes.scss +47 -18
- package/src/styles/99-utilities/_utilities.spacing.scss +118 -66
- package/src/styles/99-utilities/_utilities.text-gradient.scss +45 -0
- package/src/styles/99-utilities/_utilities.text.scss +67 -46
- package/themes/dark-complementary/README.md +98 -0
- package/themes/dark-complementary/index.scss +158 -0
- package/themes/default-light/README.md +81 -0
- package/themes/default-light/index.scss +154 -0
- package/themes/high-contrast/README.md +105 -0
- package/themes/high-contrast/index.scss +172 -0
- package/themes/test-theme/README.md +38 -0
- package/themes/test-theme/index.scss +47 -0
- package/scripts/cli/templates-original-backup.js +0 -1655
- package/scripts/cli/templates_backup.js +0 -684
- package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +0 -1438
- package/src/lib/composables/useButton.ts +0 -93
- package/src/lib/composables/useCheckbox.ts +0 -70
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Theme Preview Component
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* React component for previewing themes in development
|
|
5
5
|
* Enhanced with interactive components, viewport controls, and dark mode toggle
|
|
6
6
|
*/
|
|
@@ -54,7 +54,7 @@ const VIEWPORT_PRESETS: Record<ViewportPreset, ViewportConfig> = {
|
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* Theme Preview Component
|
|
57
|
-
*
|
|
57
|
+
*
|
|
58
58
|
* Renders a preview of a theme with sample components
|
|
59
59
|
*/
|
|
60
60
|
export const ThemePreview: React.FC<ThemePreviewProps> = ({
|
|
@@ -85,7 +85,7 @@ export const ThemePreview: React.FC<ThemePreviewProps> = ({
|
|
|
85
85
|
// Generate theme with dark mode override if needed
|
|
86
86
|
const previewTheme = useMemo(() => {
|
|
87
87
|
if (!darkMode) return theme;
|
|
88
|
-
|
|
88
|
+
|
|
89
89
|
// Create a dark mode variant (simplified - you might want more sophisticated logic)
|
|
90
90
|
return {
|
|
91
91
|
...theme,
|
|
@@ -138,9 +138,9 @@ export const ThemePreview: React.FC<ThemePreviewProps> = ({
|
|
|
138
138
|
<div className="preview-controls">
|
|
139
139
|
<div className="control-group">
|
|
140
140
|
<label>Viewport:</label>
|
|
141
|
-
<select
|
|
142
|
-
value={viewportPreset}
|
|
143
|
-
onChange={
|
|
141
|
+
<select
|
|
142
|
+
value={viewportPreset}
|
|
143
|
+
onChange={e => setViewportPreset(e.target.value as ViewportPreset)}
|
|
144
144
|
>
|
|
145
145
|
<option value="mobile">Mobile (375px)</option>
|
|
146
146
|
<option value="tablet">Tablet (768px)</option>
|
|
@@ -156,7 +156,7 @@ export const ThemePreview: React.FC<ThemePreviewProps> = ({
|
|
|
156
156
|
<input
|
|
157
157
|
type="number"
|
|
158
158
|
value={customWidth}
|
|
159
|
-
onChange={
|
|
159
|
+
onChange={e => setCustomWidth(parseInt(e.target.value) || 1280)}
|
|
160
160
|
min="320"
|
|
161
161
|
max="3840"
|
|
162
162
|
/>
|
|
@@ -166,7 +166,7 @@ export const ThemePreview: React.FC<ThemePreviewProps> = ({
|
|
|
166
166
|
<input
|
|
167
167
|
type="number"
|
|
168
168
|
value={customHeight}
|
|
169
|
-
onChange={
|
|
169
|
+
onChange={e => setCustomHeight(parseInt(e.target.value) || 720)}
|
|
170
170
|
min="240"
|
|
171
171
|
max="2160"
|
|
172
172
|
/>
|
|
@@ -179,7 +179,7 @@ export const ThemePreview: React.FC<ThemePreviewProps> = ({
|
|
|
179
179
|
<input
|
|
180
180
|
type="checkbox"
|
|
181
181
|
checked={darkMode}
|
|
182
|
-
onChange={
|
|
182
|
+
onChange={e => setDarkMode(e.target.checked)}
|
|
183
183
|
/>
|
|
184
184
|
Dark Mode
|
|
185
185
|
</label>
|
|
@@ -187,7 +187,7 @@ export const ThemePreview: React.FC<ThemePreviewProps> = ({
|
|
|
187
187
|
</div>
|
|
188
188
|
|
|
189
189
|
{/* Viewport Wrapper */}
|
|
190
|
-
<div
|
|
190
|
+
<div
|
|
191
191
|
className="viewport-wrapper"
|
|
192
192
|
style={{
|
|
193
193
|
width: `${viewport.width}px`,
|
|
@@ -197,17 +197,31 @@ export const ThemePreview: React.FC<ThemePreviewProps> = ({
|
|
|
197
197
|
>
|
|
198
198
|
{/* Inject theme CSS variables */}
|
|
199
199
|
<style>{cssVariables}</style>
|
|
200
|
-
|
|
200
|
+
|
|
201
201
|
{/* Theme Details */}
|
|
202
202
|
{showDetails && (
|
|
203
203
|
<div className="theme-details">
|
|
204
204
|
<h2>{previewTheme.name}</h2>
|
|
205
205
|
{previewTheme.description && <p>{previewTheme.description}</p>}
|
|
206
|
-
{previewTheme.author &&
|
|
207
|
-
|
|
208
|
-
|
|
206
|
+
{previewTheme.author && (
|
|
207
|
+
<p>
|
|
208
|
+
<strong>Author:</strong> {previewTheme.author}
|
|
209
|
+
</p>
|
|
210
|
+
)}
|
|
211
|
+
{previewTheme.version && (
|
|
212
|
+
<p>
|
|
213
|
+
<strong>Version:</strong> {previewTheme.version}
|
|
214
|
+
</p>
|
|
215
|
+
)}
|
|
216
|
+
{previewTheme.status && (
|
|
217
|
+
<p>
|
|
218
|
+
<strong>Status:</strong> {previewTheme.status}
|
|
219
|
+
</p>
|
|
220
|
+
)}
|
|
209
221
|
{previewTheme.tags && previewTheme.tags.length > 0 && (
|
|
210
|
-
<p
|
|
222
|
+
<p>
|
|
223
|
+
<strong>Tags:</strong> {previewTheme.tags.join(', ')}
|
|
224
|
+
</p>
|
|
211
225
|
)}
|
|
212
226
|
</div>
|
|
213
227
|
)}
|
|
@@ -217,16 +231,13 @@ export const ThemePreview: React.FC<ThemePreviewProps> = ({
|
|
|
217
231
|
<div className="theme-palette">
|
|
218
232
|
<h3>Color Palette</h3>
|
|
219
233
|
<div className="color-grid">
|
|
220
|
-
{['primary', 'secondary', 'error', 'warning', 'info', 'success'].map(
|
|
234
|
+
{['primary', 'secondary', 'error', 'warning', 'info', 'success'].map(colorName => {
|
|
221
235
|
const color = previewTheme.palette[colorName as keyof typeof previewTheme.palette];
|
|
222
236
|
if (!color || typeof color !== 'object' || !('main' in color)) return null;
|
|
223
|
-
|
|
237
|
+
|
|
224
238
|
return (
|
|
225
239
|
<div key={colorName} className="color-item">
|
|
226
|
-
<div
|
|
227
|
-
className="color-swatch"
|
|
228
|
-
style={{ backgroundColor: color.main }}
|
|
229
|
-
/>
|
|
240
|
+
<div className="color-swatch" style={{ backgroundColor: color.main }} />
|
|
230
241
|
<div className="color-info">
|
|
231
242
|
<strong>{colorName}</strong>
|
|
232
243
|
<code>{color.main}</code>
|
|
@@ -235,16 +246,13 @@ export const ThemePreview: React.FC<ThemePreviewProps> = ({
|
|
|
235
246
|
);
|
|
236
247
|
})}
|
|
237
248
|
</div>
|
|
238
|
-
|
|
249
|
+
|
|
239
250
|
{/* Background Colors */}
|
|
240
251
|
<h4>Background</h4>
|
|
241
252
|
<div className="color-grid">
|
|
242
253
|
{Object.entries(previewTheme.palette.background).map(([name, value]) => (
|
|
243
254
|
<div key={name} className="color-item">
|
|
244
|
-
<div
|
|
245
|
-
className="color-swatch"
|
|
246
|
-
style={{ backgroundColor: value }}
|
|
247
|
-
/>
|
|
255
|
+
<div className="color-swatch" style={{ backgroundColor: value }} />
|
|
248
256
|
<div className="color-info">
|
|
249
257
|
<strong>{name}</strong>
|
|
250
258
|
<code>{value}</code>
|
|
@@ -258,10 +266,7 @@ export const ThemePreview: React.FC<ThemePreviewProps> = ({
|
|
|
258
266
|
<div className="color-grid">
|
|
259
267
|
{Object.entries(previewTheme.palette.text).map(([name, value]) => (
|
|
260
268
|
<div key={name} className="color-item">
|
|
261
|
-
<div
|
|
262
|
-
className="color-swatch"
|
|
263
|
-
style={{ backgroundColor: value }}
|
|
264
|
-
/>
|
|
269
|
+
<div className="color-swatch" style={{ backgroundColor: value }} />
|
|
265
270
|
<div className="color-info">
|
|
266
271
|
<strong>{name}</strong>
|
|
267
272
|
<code>{value}</code>
|
|
@@ -277,44 +282,58 @@ export const ThemePreview: React.FC<ThemePreviewProps> = ({
|
|
|
277
282
|
<div className="theme-typography">
|
|
278
283
|
<h3>Typography</h3>
|
|
279
284
|
<div className="typography-info">
|
|
280
|
-
<p
|
|
281
|
-
|
|
285
|
+
<p>
|
|
286
|
+
<strong>Font Family:</strong> <code>{previewTheme.typography.fontFamily}</code>
|
|
287
|
+
</p>
|
|
288
|
+
<p>
|
|
289
|
+
<strong>Base Font Size:</strong> <code>{previewTheme.typography.fontSize}px</code>
|
|
290
|
+
</p>
|
|
282
291
|
</div>
|
|
283
|
-
|
|
292
|
+
|
|
284
293
|
<div className="typography-samples">
|
|
285
|
-
<h1
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
294
|
+
<h1
|
|
295
|
+
style={{
|
|
296
|
+
fontSize: previewTheme.typography.h1.fontSize,
|
|
297
|
+
fontWeight: previewTheme.typography.h1.fontWeight,
|
|
298
|
+
lineHeight: previewTheme.typography.h1.lineHeight,
|
|
299
|
+
}}
|
|
300
|
+
>
|
|
290
301
|
Heading 1
|
|
291
302
|
</h1>
|
|
292
|
-
<h2
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
303
|
+
<h2
|
|
304
|
+
style={{
|
|
305
|
+
fontSize: previewTheme.typography.h2.fontSize,
|
|
306
|
+
fontWeight: previewTheme.typography.h2.fontWeight,
|
|
307
|
+
lineHeight: previewTheme.typography.h2.lineHeight,
|
|
308
|
+
}}
|
|
309
|
+
>
|
|
297
310
|
Heading 2
|
|
298
311
|
</h2>
|
|
299
|
-
<h3
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
312
|
+
<h3
|
|
313
|
+
style={{
|
|
314
|
+
fontSize: previewTheme.typography.h3.fontSize,
|
|
315
|
+
fontWeight: previewTheme.typography.h3.fontWeight,
|
|
316
|
+
lineHeight: previewTheme.typography.h3.lineHeight,
|
|
317
|
+
}}
|
|
318
|
+
>
|
|
304
319
|
Heading 3
|
|
305
320
|
</h3>
|
|
306
|
-
<p
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
321
|
+
<p
|
|
322
|
+
style={{
|
|
323
|
+
fontSize: previewTheme.typography.body1.fontSize,
|
|
324
|
+
fontWeight: previewTheme.typography.body1.fontWeight,
|
|
325
|
+
lineHeight: previewTheme.typography.body1.lineHeight,
|
|
326
|
+
}}
|
|
327
|
+
>
|
|
311
328
|
Body 1: Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
|
312
329
|
</p>
|
|
313
|
-
<p
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
330
|
+
<p
|
|
331
|
+
style={{
|
|
332
|
+
fontSize: previewTheme.typography.body2.fontSize,
|
|
333
|
+
fontWeight: previewTheme.typography.body2.fontWeight,
|
|
334
|
+
lineHeight: previewTheme.typography.body2.lineHeight,
|
|
335
|
+
}}
|
|
336
|
+
>
|
|
318
337
|
Body 2: Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
|
319
338
|
</p>
|
|
320
339
|
</div>
|
|
@@ -326,17 +345,19 @@ export const ThemePreview: React.FC<ThemePreviewProps> = ({
|
|
|
326
345
|
<div className="theme-spacing">
|
|
327
346
|
<h3>Spacing</h3>
|
|
328
347
|
<div className="spacing-samples">
|
|
329
|
-
{[1, 2, 3, 4, 6, 8, 12].map(
|
|
348
|
+
{[1, 2, 3, 4, 6, 8, 12].map(multiplier => (
|
|
330
349
|
<div key={multiplier} className="spacing-item">
|
|
331
|
-
<div
|
|
350
|
+
<div
|
|
332
351
|
className="spacing-box"
|
|
333
|
-
style={{
|
|
352
|
+
style={{
|
|
334
353
|
width: previewTheme.spacing(multiplier),
|
|
335
354
|
height: previewTheme.spacing(multiplier),
|
|
336
355
|
backgroundColor: previewTheme.palette.primary.main,
|
|
337
356
|
}}
|
|
338
357
|
/>
|
|
339
|
-
<code>
|
|
358
|
+
<code>
|
|
359
|
+
{multiplier} = {previewTheme.spacing(multiplier)}
|
|
360
|
+
</code>
|
|
340
361
|
</div>
|
|
341
362
|
))}
|
|
342
363
|
</div>
|
|
@@ -346,22 +367,26 @@ export const ThemePreview: React.FC<ThemePreviewProps> = ({
|
|
|
346
367
|
{/* Sample Components */}
|
|
347
368
|
<div className="theme-components">
|
|
348
369
|
<h3>Sample Components</h3>
|
|
349
|
-
|
|
370
|
+
|
|
350
371
|
{/* Buttons */}
|
|
351
372
|
<div className="component-group">
|
|
352
373
|
<h4>Buttons</h4>
|
|
353
374
|
<div className="button-group">
|
|
354
|
-
<button
|
|
375
|
+
<button
|
|
355
376
|
className={`interactive-button ${interactiveStates['btn-primary'] ? 'active' : ''}`}
|
|
356
377
|
onClick={() => handleButtonClick('btn-primary')}
|
|
357
|
-
onMouseEnter={() =>
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
378
|
+
onMouseEnter={() =>
|
|
379
|
+
setInteractiveStates(prev => ({ ...prev, 'btn-primary-hover': true }))
|
|
380
|
+
}
|
|
381
|
+
onMouseLeave={() =>
|
|
382
|
+
setInteractiveStates(prev => {
|
|
383
|
+
const next = { ...prev };
|
|
384
|
+
delete next['btn-primary-hover'];
|
|
385
|
+
return next;
|
|
386
|
+
})
|
|
387
|
+
}
|
|
363
388
|
style={{
|
|
364
|
-
backgroundColor: interactiveStates['btn-primary-hover']
|
|
389
|
+
backgroundColor: interactiveStates['btn-primary-hover']
|
|
365
390
|
? previewTheme.palette.primary.dark || previewTheme.palette.primary.main
|
|
366
391
|
: previewTheme.palette.primary.main,
|
|
367
392
|
color: previewTheme.palette.primary.contrastText,
|
|
@@ -375,15 +400,19 @@ export const ThemePreview: React.FC<ThemePreviewProps> = ({
|
|
|
375
400
|
>
|
|
376
401
|
Primary Button
|
|
377
402
|
</button>
|
|
378
|
-
<button
|
|
403
|
+
<button
|
|
379
404
|
className={`interactive-button ${interactiveStates['btn-secondary'] ? 'active' : ''}`}
|
|
380
405
|
onClick={() => handleButtonClick('btn-secondary')}
|
|
381
|
-
onMouseEnter={() =>
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
406
|
+
onMouseEnter={() =>
|
|
407
|
+
setInteractiveStates(prev => ({ ...prev, 'btn-secondary-hover': true }))
|
|
408
|
+
}
|
|
409
|
+
onMouseLeave={() =>
|
|
410
|
+
setInteractiveStates(prev => {
|
|
411
|
+
const next = { ...prev };
|
|
412
|
+
delete next['btn-secondary-hover'];
|
|
413
|
+
return next;
|
|
414
|
+
})
|
|
415
|
+
}
|
|
387
416
|
style={{
|
|
388
417
|
backgroundColor: interactiveStates['btn-secondary-hover']
|
|
389
418
|
? previewTheme.palette.secondary.dark || previewTheme.palette.secondary.main
|
|
@@ -399,21 +428,29 @@ export const ThemePreview: React.FC<ThemePreviewProps> = ({
|
|
|
399
428
|
>
|
|
400
429
|
Secondary Button
|
|
401
430
|
</button>
|
|
402
|
-
<button
|
|
431
|
+
<button
|
|
403
432
|
className={`interactive-button ${interactiveStates['btn-outline'] ? 'active' : ''}`}
|
|
404
433
|
onClick={() => handleButtonClick('btn-outline')}
|
|
405
|
-
onMouseEnter={() =>
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
434
|
+
onMouseEnter={() =>
|
|
435
|
+
setInteractiveStates(prev => ({ ...prev, 'btn-outline-hover': true }))
|
|
436
|
+
}
|
|
437
|
+
onMouseLeave={() =>
|
|
438
|
+
setInteractiveStates(prev => {
|
|
439
|
+
const next = { ...prev };
|
|
440
|
+
delete next['btn-outline-hover'];
|
|
441
|
+
return next;
|
|
442
|
+
})
|
|
443
|
+
}
|
|
444
|
+
onFocus={() =>
|
|
445
|
+
setInteractiveStates(prev => ({ ...prev, 'btn-outline-focus': true }))
|
|
446
|
+
}
|
|
447
|
+
onBlur={() =>
|
|
448
|
+
setInteractiveStates(prev => {
|
|
449
|
+
const next = { ...prev };
|
|
450
|
+
delete next['btn-outline-focus'];
|
|
451
|
+
return next;
|
|
452
|
+
})
|
|
453
|
+
}
|
|
417
454
|
style={{
|
|
418
455
|
backgroundColor: 'transparent',
|
|
419
456
|
color: previewTheme.palette.primary.main,
|
|
@@ -423,7 +460,9 @@ export const ThemePreview: React.FC<ThemePreviewProps> = ({
|
|
|
423
460
|
cursor: 'pointer',
|
|
424
461
|
transform: interactiveStates['btn-outline'] ? 'scale(0.95)' : 'scale(1)',
|
|
425
462
|
transition: 'all 0.2s ease',
|
|
426
|
-
outline: interactiveStates['btn-outline-focus']
|
|
463
|
+
outline: interactiveStates['btn-outline-focus']
|
|
464
|
+
? `2px solid ${previewTheme.palette.primary.main}`
|
|
465
|
+
: 'none',
|
|
427
466
|
outlineOffset: '2px',
|
|
428
467
|
}}
|
|
429
468
|
>
|
|
@@ -435,21 +474,23 @@ export const ThemePreview: React.FC<ThemePreviewProps> = ({
|
|
|
435
474
|
{/* Cards */}
|
|
436
475
|
<div className="component-group">
|
|
437
476
|
<h4>Card</h4>
|
|
438
|
-
<div
|
|
477
|
+
<div
|
|
439
478
|
className="interactive-card"
|
|
440
479
|
onMouseEnter={() => setInteractiveStates(prev => ({ ...prev, 'card-hover': true }))}
|
|
441
|
-
onMouseLeave={() =>
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
480
|
+
onMouseLeave={() =>
|
|
481
|
+
setInteractiveStates(prev => {
|
|
482
|
+
const next = { ...prev };
|
|
483
|
+
delete next['card-hover'];
|
|
484
|
+
return next;
|
|
485
|
+
})
|
|
486
|
+
}
|
|
446
487
|
style={{
|
|
447
488
|
backgroundColor: previewTheme.palette.background.subtle,
|
|
448
489
|
border: `1px solid ${previewTheme.palette.text.disabled}`,
|
|
449
490
|
borderRadius: previewTheme.borderRadius.lg,
|
|
450
491
|
padding: previewTheme.spacing(3),
|
|
451
|
-
boxShadow: interactiveStates['card-hover']
|
|
452
|
-
? previewTheme.shadows.lg
|
|
492
|
+
boxShadow: interactiveStates['card-hover']
|
|
493
|
+
? previewTheme.shadows.lg
|
|
453
494
|
: previewTheme.shadows.md,
|
|
454
495
|
maxWidth: '300px',
|
|
455
496
|
transition: 'all 0.2s ease',
|
|
@@ -457,12 +498,15 @@ export const ThemePreview: React.FC<ThemePreviewProps> = ({
|
|
|
457
498
|
}}
|
|
458
499
|
>
|
|
459
500
|
<h5 style={{ margin: 0, marginBottom: previewTheme.spacing(1) }}>Card Title</h5>
|
|
460
|
-
<p
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
501
|
+
<p
|
|
502
|
+
style={{
|
|
503
|
+
margin: 0,
|
|
504
|
+
color: previewTheme.palette.text.secondary,
|
|
505
|
+
fontSize: previewTheme.typography.body2.fontSize,
|
|
506
|
+
}}
|
|
507
|
+
>
|
|
508
|
+
This is a sample card component showing how the theme colors and spacing work
|
|
509
|
+
together.
|
|
466
510
|
</p>
|
|
467
511
|
</div>
|
|
468
512
|
</div>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Theme Validator
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Runtime theme validation including color contrast and accessibility checks
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -41,7 +41,7 @@ export interface A11yIssue {
|
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
43
|
* Theme Validator
|
|
44
|
-
*
|
|
44
|
+
*
|
|
45
45
|
* Validates themes for correctness and accessibility
|
|
46
46
|
*/
|
|
47
47
|
export class ThemeValidator {
|
|
@@ -105,10 +105,7 @@ export class ThemeValidator {
|
|
|
105
105
|
/**
|
|
106
106
|
* Validate palette
|
|
107
107
|
*/
|
|
108
|
-
private validatePalette(
|
|
109
|
-
palette: Theme['palette'],
|
|
110
|
-
metadata?: ThemeMetadata
|
|
111
|
-
): ValidationResult {
|
|
108
|
+
private validatePalette(palette: Theme['palette'], metadata?: ThemeMetadata): ValidationResult {
|
|
112
109
|
const errors: string[] = [];
|
|
113
110
|
const warnings: string[] = [];
|
|
114
111
|
const a11yIssues: A11yIssue[] = [];
|
|
@@ -142,10 +139,7 @@ export class ThemeValidator {
|
|
|
142
139
|
|
|
143
140
|
// Validate text colors on background
|
|
144
141
|
if (palette.text && palette.background) {
|
|
145
|
-
const textContrast = this.checkContrast(
|
|
146
|
-
palette.background.default,
|
|
147
|
-
palette.text.primary
|
|
148
|
-
);
|
|
142
|
+
const textContrast = this.checkContrast(palette.background.default, palette.text.primary);
|
|
149
143
|
|
|
150
144
|
if (textContrast < contrastTarget) {
|
|
151
145
|
const issue: A11yIssue = {
|
|
@@ -191,7 +185,11 @@ export class ThemeValidator {
|
|
|
191
185
|
errors.push('Typography must have a fontFamily');
|
|
192
186
|
}
|
|
193
187
|
|
|
194
|
-
if (
|
|
188
|
+
if (
|
|
189
|
+
!typography.fontSize ||
|
|
190
|
+
typeof typography.fontSize !== 'number' ||
|
|
191
|
+
typography.fontSize <= 0
|
|
192
|
+
) {
|
|
195
193
|
errors.push('Typography must have a valid fontSize');
|
|
196
194
|
}
|
|
197
195
|
|
|
@@ -221,7 +219,9 @@ export class ThemeValidator {
|
|
|
221
219
|
errors.push('Spacing function must return a string');
|
|
222
220
|
}
|
|
223
221
|
} catch (error) {
|
|
224
|
-
errors.push(
|
|
222
|
+
errors.push(
|
|
223
|
+
`Spacing function error: ${error instanceof Error ? error.message : String(error)}`
|
|
224
|
+
);
|
|
225
225
|
}
|
|
226
226
|
}
|
|
227
227
|
|
|
@@ -328,7 +328,9 @@ export class ThemeValidator {
|
|
|
328
328
|
if (typeof duration !== 'number' || duration < 0) {
|
|
329
329
|
errors.push(`Transition duration ${key} must be a non-negative number`);
|
|
330
330
|
} else if (duration > 10000) {
|
|
331
|
-
warnings.push(
|
|
331
|
+
warnings.push(
|
|
332
|
+
`Transition duration ${key} (${duration}ms) exceeds recommended maximum (10000ms)`
|
|
333
|
+
);
|
|
332
334
|
}
|
|
333
335
|
}
|
|
334
336
|
}
|
|
@@ -343,7 +345,8 @@ export class ThemeValidator {
|
|
|
343
345
|
'sharp',
|
|
344
346
|
];
|
|
345
347
|
|
|
346
|
-
const validEasingPattern =
|
|
348
|
+
const validEasingPattern =
|
|
349
|
+
/^(linear|ease|ease-in|ease-out|ease-in-out|cubic-bezier\([^)]+\)|steps\([^)]+\))$/i;
|
|
347
350
|
|
|
348
351
|
for (const key of easingKeys) {
|
|
349
352
|
const easing = transitions.easing[key];
|
|
@@ -351,7 +354,9 @@ export class ThemeValidator {
|
|
|
351
354
|
if (typeof easing !== 'string') {
|
|
352
355
|
errors.push(`Transition easing ${key} must be a string`);
|
|
353
356
|
} else if (!validEasingPattern.test(easing)) {
|
|
354
|
-
warnings.push(
|
|
357
|
+
warnings.push(
|
|
358
|
+
`Transition easing ${key} may not be a valid CSS easing function: ${easing}`
|
|
359
|
+
);
|
|
355
360
|
}
|
|
356
361
|
}
|
|
357
362
|
}
|
|
@@ -373,10 +378,9 @@ export class ThemeValidator {
|
|
|
373
378
|
return { valid: false, errors, warnings, a11yIssues };
|
|
374
379
|
}
|
|
375
380
|
|
|
376
|
-
const numericEntries = Object.entries(zIndex).filter(
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
]>;
|
|
381
|
+
const numericEntries = Object.entries(zIndex).filter(
|
|
382
|
+
([, value]) => typeof value === 'number'
|
|
383
|
+
) as Array<[string, number]>;
|
|
380
384
|
|
|
381
385
|
for (const [key, value] of Object.entries(zIndex)) {
|
|
382
386
|
if (value !== undefined) {
|
|
@@ -490,7 +494,9 @@ export class ThemeValidator {
|
|
|
490
494
|
|
|
491
495
|
const validateObject = (obj: any, path: string = 'custom'): void => {
|
|
492
496
|
if (currentDepth > maxDepth) {
|
|
493
|
-
warnings.push(
|
|
497
|
+
warnings.push(
|
|
498
|
+
`Custom property path ${path} exceeds maximum depth (${maxDepth}), potential circular reference`
|
|
499
|
+
);
|
|
494
500
|
return;
|
|
495
501
|
}
|
|
496
502
|
|
|
@@ -512,7 +518,9 @@ export class ThemeValidator {
|
|
|
512
518
|
|
|
513
519
|
// Validate property name
|
|
514
520
|
if (!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key)) {
|
|
515
|
-
warnings.push(
|
|
521
|
+
warnings.push(
|
|
522
|
+
`Custom property name "${key}" in ${path} does not follow naming conventions (should be valid identifier)`
|
|
523
|
+
);
|
|
516
524
|
}
|
|
517
525
|
|
|
518
526
|
// Validate value type
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Theme DevTools Module
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Developer tools for theme management and debugging
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -22,14 +22,8 @@ export type { DesignTokensCustomizerProps } from './DesignTokensCustomizer';
|
|
|
22
22
|
|
|
23
23
|
// Validator (devtools only)
|
|
24
24
|
export { ThemeValidator } from './ThemeValidator';
|
|
25
|
-
export type {
|
|
26
|
-
ValidationResult,
|
|
27
|
-
A11yIssue,
|
|
28
|
-
} from './ThemeValidator';
|
|
25
|
+
export type { ValidationResult, A11yIssue } from './ThemeValidator';
|
|
29
26
|
|
|
30
27
|
// Hooks
|
|
31
28
|
export { useHistory } from './useHistory';
|
|
32
|
-
export type {
|
|
33
|
-
UseHistoryOptions,
|
|
34
|
-
UseHistoryReturn,
|
|
35
|
-
} from './useHistory';
|
|
29
|
+
export type { UseHistoryOptions, UseHistoryReturn } from './useHistory';
|