@shohojdhara/atomix 0.3.1 → 0.3.3
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 +0 -1
- package/README.md +41 -24
- package/dist/atomix.css +540 -666
- package/dist/atomix.min.css +3 -3
- package/dist/index.d.ts +7559 -5717
- package/dist/index.esm.js +5013 -2301
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +5084 -2356
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/themes/applemix.css +1683 -722
- package/dist/themes/applemix.css.map +1 -0
- package/dist/themes/applemix.min.css +13 -10
- package/dist/themes/boomdevs.css +1358 -544
- package/dist/themes/boomdevs.css.map +1 -0
- package/dist/themes/boomdevs.min.css +13 -10
- package/dist/themes/esrar.css +1743 -718
- package/dist/themes/esrar.css.map +1 -0
- package/dist/themes/esrar.min.css +41 -7
- package/dist/themes/flashtrade.css +1735 -752
- package/dist/themes/flashtrade.css.map +1 -0
- package/dist/themes/flashtrade.min.css +19 -13
- package/dist/themes/mashroom.css +1765 -787
- package/dist/themes/mashroom.css.map +1 -0
- package/dist/themes/mashroom.min.css +87 -38
- package/dist/themes/shaj-default.css +1685 -713
- package/dist/themes/shaj-default.css.map +1 -0
- package/dist/themes/shaj-default.min.css +11 -7
- package/package.json +95 -26
- package/scripts/atomix-cli.js +1428 -0
- package/scripts/build-themes.js +208 -0
- package/scripts/cli/interactive-init.js +528 -0
- package/scripts/cli/migration-tools.js +603 -0
- package/scripts/cli/token-manager.js +519 -0
- package/scripts/sync-theme-config.js +309 -0
- package/src/components/List/ListGroup.tsx +1 -2
- package/src/components/Popover/Popover.tsx +2 -2
- package/src/components/Tooltip/Tooltip.stories.tsx +49 -12
- package/src/components/Tooltip/Tooltip.tsx +32 -58
- package/src/lib/composables/useAtomixGlass.ts +46 -46
- package/src/lib/composables/useTooltip.ts +285 -0
- package/src/lib/constants/cssVariables.ts +390 -0
- package/src/lib/hooks/__tests__/useComponentCustomization.test.ts +151 -0
- package/src/lib/hooks/index.ts +19 -0
- package/src/lib/hooks/useComponentCustomization.ts +175 -0
- package/src/lib/index.ts +10 -1
- package/src/lib/patterns/__tests__/slots.test.ts +108 -0
- package/src/lib/patterns/index.ts +35 -0
- package/src/lib/patterns/slots.tsx +421 -0
- package/src/lib/theme/__tests__/ThemeBuilder.test.ts +223 -0
- package/src/lib/theme/builders/ThemeBuilder.ts +372 -0
- package/src/lib/theme/config/index.ts +21 -0
- package/src/lib/theme/config/loader.ts +276 -0
- package/src/lib/theme/config/types.ts +98 -0
- package/src/lib/theme/config/validator.ts +326 -0
- package/src/lib/theme/constants.ts +183 -0
- package/src/lib/theme/core/ThemeCache.ts +283 -0
- package/src/lib/theme/core/ThemeEngine.test.ts +146 -0
- package/src/lib/theme/core/ThemeEngine.ts +657 -0
- package/src/lib/theme/core/ThemeRegistry.ts +284 -0
- package/src/lib/theme/core/ThemeValidator.ts +530 -0
- package/src/lib/theme/core/index.ts +24 -0
- package/src/lib/theme/createTheme.ts +83 -204
- package/src/lib/theme/cssVariableMapper.ts +261 -0
- package/src/lib/theme/devtools/CLI.ts +279 -0
- package/src/lib/theme/devtools/Inspector.tsx +594 -0
- package/src/lib/theme/devtools/Preview.tsx +392 -0
- package/src/lib/theme/devtools/index.ts +21 -0
- package/src/lib/theme/errors.test.ts +207 -0
- package/src/lib/theme/errors.ts +233 -0
- package/src/lib/theme/generateCSSVariables.ts +93 -9
- package/src/lib/theme/generators/CSSGenerator.ts +311 -0
- package/src/lib/theme/generators/ConfigGenerator.ts +287 -0
- package/src/lib/theme/generators/TypeGenerator.ts +228 -0
- package/src/lib/theme/generators/index.ts +21 -0
- package/src/lib/theme/i18n/index.ts +9 -0
- package/src/lib/theme/i18n/rtl.ts +325 -0
- package/src/lib/theme/index.ts +36 -109
- package/src/lib/theme/monitoring/ThemeAnalytics.ts +409 -0
- package/src/lib/theme/monitoring/index.ts +17 -0
- package/src/lib/theme/overrides/ComponentOverrides.ts +243 -0
- package/src/lib/theme/overrides/index.ts +15 -0
- package/src/lib/theme/runtime/ThemeApplicator.ts +252 -0
- package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +233 -0
- package/src/lib/theme/runtime/ThemeManager.test.ts +176 -0
- package/src/lib/theme/runtime/ThemeManager.ts +442 -0
- package/src/lib/theme/runtime/ThemeProvider.tsx +318 -0
- package/src/lib/theme/runtime/index.ts +17 -0
- package/src/lib/theme/runtime/useTheme.ts +52 -0
- package/src/lib/theme/themeUtils.ts +27 -5
- package/src/lib/theme/types.ts +62 -1
- package/src/lib/theme/utils.ts +23 -22
- package/src/lib/theme/whitelabel/WhiteLabelManager.ts +364 -0
- package/src/lib/theme/whitelabel/index.ts +13 -0
- package/src/lib/theme-tools.ts +185 -0
- package/src/lib/types/components.ts +194 -0
- package/src/lib/types/partProps.ts +426 -0
- package/src/lib/utils/__tests__/componentUtils.test.ts +144 -0
- package/src/lib/utils/componentUtils.ts +163 -0
- package/src/lib/utils/index.ts +17 -57
- package/src/styles/01-settings/_settings.badge.scss +1 -1
- package/src/styles/01-settings/_settings.callout.scss +1 -1
- package/src/styles/01-settings/_settings.card.scss +1 -1
- package/src/styles/01-settings/_settings.colors.scss +10 -10
- package/src/styles/01-settings/_settings.input.scss +1 -1
- package/src/styles/01-settings/_settings.navbar.scss +1 -1
- package/src/styles/01-settings/_settings.tooltip.scss +1 -1
- package/src/styles/01-settings/_settings.upload.scss +1 -1
- package/src/styles/06-components/_components.chart.scss +2 -2
- package/src/styles/06-components/_components.tooltip.scss +31 -81
- package/src/styles/99-utilities/_utilities.border.scss +27 -58
- package/src/styles/99-utilities/_utilities.gradient.scss +12 -0
- package/src/styles/99-utilities/_utilities.position.scss +8 -15
- package/src/styles/99-utilities/_utilities.scss +2 -0
- package/src/styles/99-utilities/_utilities.spacing.scss +76 -121
- package/src/styles/99-utilities/_utilities.text.scss +30 -49
- package/src/themes/README.md +443 -0
- package/src/themes/THEME_CHECKLIST.md +74 -0
- package/src/themes/applemix/01-settings/_index.scss +24 -0
- package/src/themes/applemix/01-settings/_settings.animations.scss +0 -0
- package/src/themes/applemix/01-settings/_settings.background.scss +6 -0
- package/src/themes/applemix/01-settings/_settings.colors.scss +75 -0
- package/src/themes/applemix/01-settings/_settings.config.scss +15 -0
- package/src/themes/applemix/01-settings/_settings.typography.scss +30 -0
- package/src/themes/applemix/02-tools/_index.scss +4 -0
- package/src/themes/applemix/03-generic/_index.scss +7 -0
- package/src/themes/applemix/04-elements/_index.scss +7 -0
- package/src/themes/applemix/05-objects/_index.scss +7 -0
- package/src/themes/applemix/06-components/_index.scss +15 -0
- package/src/themes/applemix/99-utilities/_index.scss +7 -0
- package/src/themes/applemix/README.md +378 -0
- package/src/themes/applemix/index.scss +33 -0
- package/src/themes/boomdevs/01-settings/_index.scss +38 -0
- package/src/themes/boomdevs/01-settings/_settings.accordion.scss +12 -0
- package/src/themes/boomdevs/01-settings/_settings.animations.scss +11 -0
- package/src/themes/boomdevs/01-settings/_settings.avatar.scss +9 -0
- package/src/themes/boomdevs/01-settings/_settings.badge.scss +11 -0
- package/src/themes/boomdevs/01-settings/_settings.border-radius.scss +16 -0
- package/src/themes/boomdevs/01-settings/_settings.border.scss +10 -0
- package/src/themes/boomdevs/01-settings/_settings.box-shadow.scss +14 -0
- package/src/themes/boomdevs/01-settings/_settings.breadcrumb.scss +13 -0
- package/src/themes/boomdevs/01-settings/_settings.breakpoints.scss +15 -0
- package/src/themes/boomdevs/01-settings/_settings.button.scss +9 -0
- package/src/themes/boomdevs/01-settings/_settings.callout.scss +9 -0
- package/src/themes/boomdevs/01-settings/_settings.card.scss +11 -0
- package/src/themes/boomdevs/01-settings/_settings.checkbox.scss +9 -0
- package/src/themes/boomdevs/01-settings/_settings.colors.scss +145 -0
- package/src/themes/boomdevs/01-settings/_settings.dropdown.scss +11 -0
- package/src/themes/boomdevs/01-settings/_settings.grid.scss +16 -0
- package/src/themes/boomdevs/01-settings/_settings.input.scss +14 -0
- package/src/themes/boomdevs/01-settings/_settings.link.scss +11 -0
- package/src/themes/boomdevs/01-settings/_settings.list.scss +10 -0
- package/src/themes/boomdevs/01-settings/_settings.modal.scss +16 -0
- package/src/themes/boomdevs/01-settings/_settings.navbar.scss +16 -0
- package/src/themes/boomdevs/01-settings/_settings.pagination.scss +13 -0
- package/src/themes/boomdevs/01-settings/_settings.progress.scss +11 -0
- package/src/themes/boomdevs/01-settings/_settings.rating.scss +10 -0
- package/src/themes/boomdevs/01-settings/_settings.spacing.scss +33 -0
- package/src/themes/boomdevs/01-settings/_settings.spinner.scss +11 -0
- package/src/themes/boomdevs/01-settings/_settings.steps.scss +12 -0
- package/src/themes/boomdevs/01-settings/_settings.tabs.scss +12 -0
- package/src/themes/boomdevs/01-settings/_settings.todo.scss +15 -0
- package/src/themes/boomdevs/01-settings/_settings.toggle.scss +14 -0
- package/src/themes/boomdevs/01-settings/_settings.tooltip.scss +13 -0
- package/src/themes/boomdevs/01-settings/_settings.typography.scss +58 -0
- package/src/themes/boomdevs/01-settings/_settings.video-player.scss +12 -0
- package/src/themes/boomdevs/02-tools/_index.scss +7 -0
- package/src/themes/boomdevs/03-generic/_index.scss +7 -0
- package/src/themes/boomdevs/04-elements/_index.scss +7 -0
- package/src/themes/boomdevs/05-objects/_index.scss +7 -0
- package/src/themes/boomdevs/06-components/_components.button.scss +11 -0
- package/src/themes/boomdevs/06-components/_index.scss +11 -0
- package/src/themes/boomdevs/99-utilities/_index.scss +7 -0
- package/src/themes/boomdevs/index.scss +26 -0
- package/src/themes/esrar/01-settings/_index.scss +15 -0
- package/src/themes/esrar/01-settings/_settings.colors.scss +91 -0
- package/src/themes/esrar/02-tools/_index.scss +8 -0
- package/src/themes/esrar/02-tools/_tools.animations.scss +342 -0
- package/src/themes/esrar/06-components/_components.accordion.scss +49 -0
- package/src/themes/esrar/06-components/_components.avatar-group.scss +14 -0
- package/src/themes/esrar/06-components/_components.avatar.scss +61 -0
- package/src/themes/esrar/06-components/_components.badge.scss +117 -0
- package/src/themes/esrar/06-components/_components.breadcrumb.scss +65 -0
- package/src/themes/esrar/06-components/_components.btn-group.scss +19 -0
- package/src/themes/esrar/06-components/_components.button.scss +224 -0
- package/src/themes/esrar/06-components/_components.callout.scss +51 -0
- package/src/themes/esrar/06-components/_components.card.scss +134 -0
- package/src/themes/esrar/06-components/_components.chart.scss +24 -0
- package/src/themes/esrar/06-components/_components.checkbox-group.scss +26 -0
- package/src/themes/esrar/06-components/_components.checkbox.scss +71 -0
- package/src/themes/esrar/06-components/_components.color-mode-toggle.scss +29 -0
- package/src/themes/esrar/06-components/_components.countdown.scss +67 -0
- package/src/themes/esrar/06-components/_components.data-table.scss +22 -0
- package/src/themes/esrar/06-components/_components.datepicker.scss +20 -0
- package/src/themes/esrar/06-components/_components.dropdown.scss +272 -0
- package/src/themes/esrar/06-components/_components.edge-panel.scss +10 -0
- package/src/themes/esrar/06-components/_components.form-group.scss +15 -0
- package/src/themes/esrar/06-components/_components.form.scss +66 -0
- package/src/themes/esrar/06-components/_components.hero.scss +251 -0
- package/src/themes/esrar/06-components/_components.icon.scss +33 -0
- package/src/themes/esrar/06-components/_components.image-gallery.scss +29 -0
- package/src/themes/esrar/06-components/_components.input.scss +91 -0
- package/src/themes/esrar/06-components/_components.list-group.scss +26 -0
- package/src/themes/esrar/06-components/_components.modal.scss +148 -0
- package/src/themes/esrar/06-components/_components.notification.scss +80 -0
- package/src/themes/esrar/06-components/_components.pagination.scss +84 -0
- package/src/themes/esrar/06-components/_components.popover.scss +10 -0
- package/src/themes/esrar/06-components/_components.progress.scss +64 -0
- package/src/themes/esrar/06-components/_components.rating.scss +26 -0
- package/src/themes/esrar/06-components/_components.skeleton.scss +15 -0
- package/src/themes/esrar/06-components/_components.slider.scss +90 -0
- package/src/themes/esrar/06-components/_components.spinner.scss +71 -0
- package/src/themes/esrar/06-components/_components.steps.scss +76 -0
- package/src/themes/esrar/06-components/_components.tab.scss +58 -0
- package/src/themes/esrar/06-components/_components.tag.scss +21 -0
- package/src/themes/esrar/06-components/_components.timeline.scss +19 -0
- package/src/themes/esrar/06-components/_components.toast.scss +91 -0
- package/src/themes/esrar/06-components/_components.toggle.scss +74 -0
- package/src/themes/esrar/06-components/_components.tooltip.scss +45 -0
- package/src/themes/esrar/06-components/_components.upload.scss +102 -0
- package/src/themes/esrar/06-components/_index.scss +42 -0
- package/src/themes/esrar/index.scss +30 -0
- package/src/themes/flashtrade/01-settings/_index.scss +19 -0
- package/src/themes/flashtrade/01-settings/_settings.animations.scss +11 -0
- package/src/themes/flashtrade/01-settings/_settings.background.scss +9 -0
- package/src/themes/flashtrade/01-settings/_settings.colors.scss +79 -0
- package/src/themes/flashtrade/01-settings/_settings.config.scss +16 -0
- package/src/themes/flashtrade/01-settings/_settings.typography.scss +35 -0
- package/src/themes/flashtrade/02-tools/_index.scss +8 -0
- package/src/themes/flashtrade/03-generic/_index.scss +8 -0
- package/src/themes/flashtrade/04-elements/_index.scss +12 -0
- package/src/themes/flashtrade/05-objects/_index.scss +8 -0
- package/src/themes/flashtrade/06-components/_components.badge.scss +156 -0
- package/src/themes/flashtrade/06-components/_components.button.scss +135 -0
- package/src/themes/flashtrade/06-components/_components.card.scss +214 -0
- package/src/themes/flashtrade/06-components/_components.navbar.scss +227 -0
- package/src/themes/flashtrade/06-components/_index.scss +13 -0
- package/src/themes/flashtrade/99-utilities/_index.scss +9 -0
- package/src/themes/flashtrade/99-utilities/_utilities.trading.scss +187 -0
- package/src/themes/flashtrade/README.md +386 -0
- package/src/themes/flashtrade/demo.html +272 -0
- package/src/themes/flashtrade/index.scss +36 -0
- package/src/themes/mashroom/01-settings/_index.scss +69 -0
- package/src/themes/mashroom/01-settings/_settings.accordion.scss +32 -0
- package/src/themes/mashroom/01-settings/_settings.animations.scss +26 -0
- package/src/themes/mashroom/01-settings/_settings.avatar-group.scss +22 -0
- package/src/themes/mashroom/01-settings/_settings.avatar.scss +57 -0
- package/src/themes/mashroom/01-settings/_settings.badge.scss +19 -0
- package/src/themes/mashroom/01-settings/_settings.border-radius.scss +24 -0
- package/src/themes/mashroom/01-settings/_settings.border.scss +14 -0
- package/src/themes/mashroom/01-settings/_settings.box-shadow.scss +40 -0
- package/src/themes/mashroom/01-settings/_settings.breadcrumb.scss +0 -0
- package/src/themes/mashroom/01-settings/_settings.breakpoints.scss +17 -0
- package/src/themes/mashroom/01-settings/_settings.btn-group.scss +5 -0
- package/src/themes/mashroom/01-settings/_settings.button.scss +50 -0
- package/src/themes/mashroom/01-settings/_settings.callout.scss +81 -0
- package/src/themes/mashroom/01-settings/_settings.card.scss +52 -0
- package/src/themes/mashroom/01-settings/_settings.checkbox-group.scss +5 -0
- package/src/themes/mashroom/01-settings/_settings.checkbox.scss +23 -0
- package/src/themes/mashroom/01-settings/_settings.color-mode.scss +7 -0
- package/src/themes/mashroom/01-settings/_settings.colors.scss +180 -0
- package/src/themes/mashroom/01-settings/_settings.config.scss +4 -0
- package/src/themes/mashroom/01-settings/_settings.countdown.scss +20 -0
- package/src/themes/mashroom/01-settings/_settings.data-table.scss +56 -0
- package/src/themes/mashroom/01-settings/_settings.datepicker.scss +45 -0
- package/src/themes/mashroom/01-settings/_settings.design-tokens.scss +3 -0
- package/src/themes/mashroom/01-settings/_settings.dropdown.scss +45 -0
- package/src/themes/mashroom/01-settings/_settings.edge-panel.scss +24 -0
- package/src/themes/mashroom/01-settings/_settings.fonts.scss +8 -0
- package/src/themes/mashroom/01-settings/_settings.form-group.scss +14 -0
- package/src/themes/mashroom/01-settings/_settings.form.scss +6 -0
- package/src/themes/mashroom/01-settings/_settings.grid.scss +23 -0
- package/src/themes/mashroom/01-settings/_settings.hero.scss +41 -0
- package/src/themes/mashroom/01-settings/_settings.input.scss +51 -0
- package/src/themes/mashroom/01-settings/_settings.link.scss +13 -0
- package/src/themes/mashroom/01-settings/_settings.list-group.scss +16 -0
- package/src/themes/mashroom/01-settings/_settings.list.scss +13 -0
- package/src/themes/mashroom/01-settings/_settings.masonry-grid.scss +23 -0
- package/src/themes/mashroom/01-settings/_settings.menu.scss +50 -0
- package/src/themes/mashroom/01-settings/_settings.messages.scss +98 -0
- package/src/themes/mashroom/01-settings/_settings.modal.scss +41 -0
- package/src/themes/mashroom/01-settings/_settings.nav.scss +20 -0
- package/src/themes/mashroom/01-settings/_settings.navbar.scss +54 -0
- package/src/themes/mashroom/01-settings/_settings.pagination.scss +30 -0
- package/src/themes/mashroom/01-settings/_settings.photoviewer.scss +45 -0
- package/src/themes/mashroom/01-settings/_settings.popover.scss +20 -0
- package/src/themes/mashroom/01-settings/_settings.position.scss +9 -0
- package/src/themes/mashroom/01-settings/_settings.progress.scss +17 -0
- package/src/themes/mashroom/01-settings/_settings.rating.scss +11 -0
- package/src/themes/mashroom/01-settings/_settings.river.scss +50 -0
- package/src/themes/mashroom/01-settings/_settings.sectionintro.scss +31 -0
- package/src/themes/mashroom/01-settings/_settings.select.scss +47 -0
- package/src/themes/mashroom/01-settings/_settings.side-menu.scss +79 -0
- package/src/themes/mashroom/01-settings/_settings.skeleton.scss +24 -0
- package/src/themes/mashroom/01-settings/_settings.spacing.scss +66 -0
- package/src/themes/mashroom/01-settings/_settings.spinner.scss +34 -0
- package/src/themes/mashroom/01-settings/_settings.steps.scss +33 -0
- package/src/themes/mashroom/01-settings/_settings.tabs.scss +33 -0
- package/src/themes/mashroom/01-settings/_settings.testimonials.scss +24 -0
- package/src/themes/mashroom/01-settings/_settings.todo.scss +52 -0
- package/src/themes/mashroom/01-settings/_settings.toggle.scss +49 -0
- package/src/themes/mashroom/01-settings/_settings.tooltip.scss +20 -0
- package/src/themes/mashroom/01-settings/_settings.typography.scss +95 -0
- package/src/themes/mashroom/01-settings/_settings.upload.scss +96 -0
- package/src/themes/mashroom/01-settings/_settings.z-layers.scss +19 -0
- package/src/themes/mashroom/02-tools/_index.scss +8 -0
- package/src/themes/mashroom/02-tools/_tools.psychedelic-gradients.scss +78 -0
- package/src/themes/mashroom/02-tools/_tools.trippy-effects.scss +114 -0
- package/src/themes/mashroom/03-generic/_index.scss +6 -0
- package/src/themes/mashroom/04-elements/_index.scss +6 -0
- package/src/themes/mashroom/05-objects/_index.scss +6 -0
- package/src/themes/mashroom/06-components/_components.accordion.scss +187 -0
- package/src/themes/mashroom/06-components/_components.avatar-group.scss +276 -0
- package/src/themes/mashroom/06-components/_components.avatar.scss +114 -0
- package/src/themes/mashroom/06-components/_components.badge.scss +152 -0
- package/src/themes/mashroom/06-components/_components.breadcrumb.scss +162 -0
- package/src/themes/mashroom/06-components/_components.btn-group.scss +404 -0
- package/src/themes/mashroom/06-components/_components.button.scss +160 -0
- package/src/themes/mashroom/06-components/_components.callout.scss +140 -0
- package/src/themes/mashroom/06-components/_components.card.scss +225 -0
- package/src/themes/mashroom/06-components/_components.checkbox.scss +186 -0
- package/src/themes/mashroom/06-components/_components.color-mode-toggle.scss +308 -0
- package/src/themes/mashroom/06-components/_components.countdown.scss +402 -0
- package/src/themes/mashroom/06-components/_components.data-table.scss +354 -0
- package/src/themes/mashroom/06-components/_components.datepicker.scss +349 -0
- package/src/themes/mashroom/06-components/_components.dropdown.scss +334 -0
- package/src/themes/mashroom/06-components/_components.edge-panel.scss +413 -0
- package/src/themes/mashroom/06-components/_components.form-group.scss +433 -0
- package/src/themes/mashroom/06-components/_components.form.scss +358 -0
- package/src/themes/mashroom/06-components/_components.hero.scss +151 -0
- package/src/themes/mashroom/06-components/_components.input.scss +147 -0
- package/src/themes/mashroom/06-components/_components.list-group.scss +456 -0
- package/src/themes/mashroom/06-components/_components.list.scss +145 -0
- package/src/themes/mashroom/06-components/_components.menu.scss +497 -0
- package/src/themes/mashroom/06-components/_components.messages.scss +277 -0
- package/src/themes/mashroom/06-components/_components.modal.scss +264 -0
- package/src/themes/mashroom/06-components/_components.nav.scss +181 -0
- package/src/themes/mashroom/06-components/_components.navbar.scss +538 -0
- package/src/themes/mashroom/06-components/_components.pagination.scss +400 -0
- package/src/themes/mashroom/06-components/_components.photoviewer.scss +498 -0
- package/src/themes/mashroom/06-components/_components.popover.scss +383 -0
- package/src/themes/mashroom/06-components/_components.product-review.scss +408 -0
- package/src/themes/mashroom/06-components/_components.progress.scss +249 -0
- package/src/themes/mashroom/06-components/_components.rating.scss +300 -0
- package/src/themes/mashroom/06-components/_components.river.scss +570 -0
- package/src/themes/mashroom/06-components/_components.sectionintro.scss +546 -0
- package/src/themes/mashroom/06-components/_components.select.scss +455 -0
- package/src/themes/mashroom/06-components/_components.side-menu.scss +635 -0
- package/src/themes/mashroom/06-components/_components.skeleton.scss +447 -0
- package/src/themes/mashroom/06-components/_components.slider.scss +414 -0
- package/src/themes/mashroom/06-components/_components.spinner.scss +198 -0
- package/src/themes/mashroom/06-components/_components.steps.scss +350 -0
- package/src/themes/mashroom/06-components/_components.tabs.scss +269 -0
- package/src/themes/mashroom/06-components/_components.testimonials.scss +561 -0
- package/src/themes/mashroom/06-components/_components.toggle.scss +231 -0
- package/src/themes/mashroom/06-components/_components.tooltip.scss +167 -0
- package/src/themes/mashroom/06-components/_components.upload.scss +537 -0
- package/src/themes/mashroom/06-components/_components.video-player.scss +560 -0
- package/src/themes/mashroom/06-components/_index.scss +55 -0
- package/src/themes/mashroom/99-utilities/_index.scss +6 -0
- package/src/themes/mashroom/index.scss +26 -0
- package/src/themes/shaj-default/01-settings/_index.scss +69 -0
- package/src/themes/shaj-default/01-settings/_settings.accordion.scss +38 -0
- package/src/themes/shaj-default/01-settings/_settings.animations.scss +32 -0
- package/src/themes/shaj-default/01-settings/_settings.avatar-group.scss +28 -0
- package/src/themes/shaj-default/01-settings/_settings.avatar.scss +63 -0
- package/src/themes/shaj-default/01-settings/_settings.badge.scss +25 -0
- package/src/themes/shaj-default/01-settings/_settings.border-radius.scss +24 -0
- package/src/themes/shaj-default/01-settings/_settings.border.scss +20 -0
- package/src/themes/shaj-default/01-settings/_settings.box-shadow.scss +46 -0
- package/src/themes/shaj-default/01-settings/_settings.breadcrumb.scss +0 -0
- package/src/themes/shaj-default/01-settings/_settings.breakpoints.scss +23 -0
- package/src/themes/shaj-default/01-settings/_settings.btn-group.scss +11 -0
- package/src/themes/shaj-default/01-settings/_settings.button.scss +56 -0
- package/src/themes/shaj-default/01-settings/_settings.callout.scss +87 -0
- package/src/themes/shaj-default/01-settings/_settings.card.scss +52 -0
- package/src/themes/shaj-default/01-settings/_settings.checkbox-group.scss +11 -0
- package/src/themes/shaj-default/01-settings/_settings.checkbox.scss +29 -0
- package/src/themes/shaj-default/01-settings/_settings.color-mode.scss +13 -0
- package/src/themes/shaj-default/01-settings/_settings.colors.scss +91 -0
- package/src/themes/shaj-default/01-settings/_settings.config.scss +4 -0
- package/src/themes/shaj-default/01-settings/_settings.countdown.scss +26 -0
- package/src/themes/shaj-default/01-settings/_settings.data-table.scss +62 -0
- package/src/themes/shaj-default/01-settings/_settings.datepicker.scss +51 -0
- package/src/themes/shaj-default/01-settings/_settings.design-tokens.scss +9 -0
- package/src/themes/shaj-default/01-settings/_settings.dropdown.scss +51 -0
- package/src/themes/shaj-default/01-settings/_settings.edge-panel.scss +30 -0
- package/src/themes/shaj-default/01-settings/_settings.fonts.scss +13 -0
- package/src/themes/shaj-default/01-settings/_settings.form-group.scss +20 -0
- package/src/themes/shaj-default/01-settings/_settings.form.scss +12 -0
- package/src/themes/shaj-default/01-settings/_settings.grid.scss +29 -0
- package/src/themes/shaj-default/01-settings/_settings.hero.scss +47 -0
- package/src/themes/shaj-default/01-settings/_settings.input.scss +57 -0
- package/src/themes/shaj-default/01-settings/_settings.link.scss +19 -0
- package/src/themes/shaj-default/01-settings/_settings.list-group.scss +22 -0
- package/src/themes/shaj-default/01-settings/_settings.list.scss +19 -0
- package/src/themes/shaj-default/01-settings/_settings.masonry-grid.scss +29 -0
- package/src/themes/shaj-default/01-settings/_settings.menu.scss +56 -0
- package/src/themes/shaj-default/01-settings/_settings.messages.scss +104 -0
- package/src/themes/shaj-default/01-settings/_settings.modal.scss +47 -0
- package/src/themes/shaj-default/01-settings/_settings.nav.scss +26 -0
- package/src/themes/shaj-default/01-settings/_settings.navbar.scss +60 -0
- package/src/themes/shaj-default/01-settings/_settings.pagination.scss +36 -0
- package/src/themes/shaj-default/01-settings/_settings.photoviewer.scss +51 -0
- package/src/themes/shaj-default/01-settings/_settings.popover.scss +26 -0
- package/src/themes/shaj-default/01-settings/_settings.position.scss +15 -0
- package/src/themes/shaj-default/01-settings/_settings.progress.scss +23 -0
- package/src/themes/shaj-default/01-settings/_settings.rating.scss +17 -0
- package/src/themes/shaj-default/01-settings/_settings.river.scss +56 -0
- package/src/themes/shaj-default/01-settings/_settings.sectionintro.scss +37 -0
- package/src/themes/shaj-default/01-settings/_settings.select.scss +53 -0
- package/src/themes/shaj-default/01-settings/_settings.side-menu.scss +85 -0
- package/src/themes/shaj-default/01-settings/_settings.skeleton.scss +30 -0
- package/src/themes/shaj-default/01-settings/_settings.spacing.scss +72 -0
- package/src/themes/shaj-default/01-settings/_settings.spinner.scss +24 -0
- package/src/themes/shaj-default/01-settings/_settings.steps.scss +39 -0
- package/src/themes/shaj-default/01-settings/_settings.tabs.scss +39 -0
- package/src/themes/shaj-default/01-settings/_settings.testimonials.scss +30 -0
- package/src/themes/shaj-default/01-settings/_settings.todo.scss +58 -0
- package/src/themes/shaj-default/01-settings/_settings.toggle.scss +55 -0
- package/src/themes/shaj-default/01-settings/_settings.tooltip.scss +26 -0
- package/src/themes/shaj-default/01-settings/_settings.typography.scss +101 -0
- package/src/themes/shaj-default/01-settings/_settings.upload.scss +102 -0
- package/src/themes/shaj-default/01-settings/_settings.z-layers.scss +25 -0
- package/src/themes/shaj-default/02-tools/_index.scss +0 -0
- package/src/themes/shaj-default/03-generic/_generic.root.scss +0 -0
- package/src/themes/shaj-default/03-generic/_index.scss +2 -0
- package/src/themes/shaj-default/04-elements/_index.scss +0 -0
- package/src/themes/shaj-default/05-objects/_index.scss +0 -0
- package/src/themes/shaj-default/06-components/_components.button.scss +55 -0
- package/src/themes/shaj-default/06-components/_components.card.scss +57 -0
- package/src/themes/shaj-default/06-components/_components.input.scss +58 -0
- package/src/themes/shaj-default/06-components/_components.navbar.scss +99 -0
- package/src/themes/shaj-default/06-components/_components.tooltip.scss +0 -0
- package/src/themes/shaj-default/06-components/_index.scss +13 -0
- package/src/themes/shaj-default/99-utilities/_index.scss +0 -0
- package/src/themes/shaj-default/index.scss +25 -0
- package/src/themes/themes.config.js +219 -0
- package/theme.config.ts +360 -0
- package/src/lib/theme/ThemeManager.integration.test.ts +0 -124
- package/src/lib/theme/ThemeManager.stories.tsx +0 -472
- package/src/lib/theme/ThemeManager.test.ts +0 -190
- package/src/lib/theme/ThemeManager.ts +0 -645
- package/src/lib/theme/ThemeProvider.tsx +0 -377
- package/src/lib/theme/createTheme.test.ts +0 -475
- package/src/lib/theme/useTheme.test.tsx +0 -67
- package/src/lib/theme/useTheme.ts +0 -64
- package/src/lib/theme/utils.test.ts +0 -140
|
@@ -0,0 +1,1428 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Atomix CLI - Enhanced Version
|
|
5
|
+
* Design System Development Tools
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { program } from 'commander';
|
|
9
|
+
import { readFile, writeFile, mkdir, access, stat, rm } from 'fs/promises';
|
|
10
|
+
import { join, dirname, basename, relative, resolve } from 'path';
|
|
11
|
+
import { fileURLToPath } from 'url';
|
|
12
|
+
import { existsSync } from 'fs';
|
|
13
|
+
import * as sass from 'sass';
|
|
14
|
+
import postcss from 'postcss';
|
|
15
|
+
import autoprefixer from 'autoprefixer';
|
|
16
|
+
import cssnano from 'cssnano';
|
|
17
|
+
import chalk from 'chalk';
|
|
18
|
+
import ora from 'ora';
|
|
19
|
+
import chokidar from 'chokidar';
|
|
20
|
+
import inquirer from 'inquirer';
|
|
21
|
+
import boxen from 'boxen';
|
|
22
|
+
import { runInitWizard } from './cli/interactive-init.js';
|
|
23
|
+
import {
|
|
24
|
+
migrateTailwind,
|
|
25
|
+
migrateBootstrap,
|
|
26
|
+
migrateSCSSVariables,
|
|
27
|
+
displayMigrationReport
|
|
28
|
+
} from './cli/migration-tools.js';
|
|
29
|
+
import {
|
|
30
|
+
listTokens,
|
|
31
|
+
validateTokens,
|
|
32
|
+
exportTokens,
|
|
33
|
+
importTokens
|
|
34
|
+
} from './cli/token-manager.js';
|
|
35
|
+
|
|
36
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
37
|
+
const __dirname = dirname(__filename);
|
|
38
|
+
|
|
39
|
+
// Package info
|
|
40
|
+
const packageJson = JSON.parse(
|
|
41
|
+
await readFile(join(__dirname, '../package.json'), 'utf8')
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
// CLI Configuration
|
|
45
|
+
const DEBUG = process.env.ATOMIX_DEBUG === 'true' || process.argv.includes('--debug');
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Enhanced Error Class
|
|
49
|
+
*/
|
|
50
|
+
class AtomixCLIError extends Error {
|
|
51
|
+
constructor(message, code, suggestions = []) {
|
|
52
|
+
super(message);
|
|
53
|
+
this.name = 'AtomixCLIError';
|
|
54
|
+
this.code = code;
|
|
55
|
+
this.suggestions = suggestions;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Debug logger
|
|
61
|
+
*/
|
|
62
|
+
function debug(message, data = null) {
|
|
63
|
+
if (DEBUG) {
|
|
64
|
+
console.log(chalk.gray(`[DEBUG] ${message}`));
|
|
65
|
+
if (data) {
|
|
66
|
+
console.log(chalk.gray(JSON.stringify(data, null, 2)));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Error handler with suggestions
|
|
73
|
+
*/
|
|
74
|
+
function handleError(error, spinner = null) {
|
|
75
|
+
if (spinner) spinner.fail(chalk.red('Operation failed'));
|
|
76
|
+
|
|
77
|
+
console.error(chalk.bold.red(`\n❌ ${error.message}`));
|
|
78
|
+
|
|
79
|
+
if (error instanceof AtomixCLIError && error.suggestions.length > 0) {
|
|
80
|
+
console.log(chalk.yellow('\n💡 Suggestions:'));
|
|
81
|
+
error.suggestions.forEach((suggestion, index) => {
|
|
82
|
+
console.log(chalk.gray(` ${index + 1}. ${suggestion}`));
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (DEBUG && error.stack) {
|
|
87
|
+
console.error(chalk.gray('\nStack trace:'));
|
|
88
|
+
console.error(chalk.gray(error.stack));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Component templates for design system
|
|
96
|
+
*/
|
|
97
|
+
const componentTemplates = {
|
|
98
|
+
react: {
|
|
99
|
+
component: (name, options = {}) => `import React, { forwardRef, memo } from 'react';
|
|
100
|
+
${options.scssModule ? `import styles from './${name}.module.scss';` : ''}
|
|
101
|
+
${options.types ? `import type { ${name}Props } from '../../lib/types/components';` : ''}
|
|
102
|
+
|
|
103
|
+
${options.types ? '' : `export interface ${name}Props {
|
|
104
|
+
/**
|
|
105
|
+
* Content to be rendered
|
|
106
|
+
*/
|
|
107
|
+
children?: React.ReactNode;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Additional CSS classes
|
|
111
|
+
*/
|
|
112
|
+
className?: string;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Size variant
|
|
116
|
+
*/
|
|
117
|
+
size?: 'sm' | 'md' | 'lg';
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Color variant
|
|
121
|
+
*/
|
|
122
|
+
variant?: 'primary' | 'secondary' | 'success' | 'error';
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Disabled state
|
|
126
|
+
*/
|
|
127
|
+
disabled?: boolean;
|
|
128
|
+
}`}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* ${name} component
|
|
132
|
+
*
|
|
133
|
+
* @component
|
|
134
|
+
* @example
|
|
135
|
+
* <${name} variant="primary" size="md">
|
|
136
|
+
* Content
|
|
137
|
+
* </${name}>
|
|
138
|
+
*/
|
|
139
|
+
export const ${name} = memo(
|
|
140
|
+
forwardRef<HTMLDivElement, ${name}Props>(
|
|
141
|
+
({ children, className = '', size = 'md', variant = 'primary', disabled = false, ...props }, ref) => {
|
|
142
|
+
${options.scssModule ? `const componentClasses = [
|
|
143
|
+
styles.${name.toLowerCase()},
|
|
144
|
+
styles[\`${name.toLowerCase()}--\${size}\`],
|
|
145
|
+
styles[\`${name.toLowerCase()}--\${variant}\`],
|
|
146
|
+
disabled && styles['${name.toLowerCase()}--disabled'],
|
|
147
|
+
className
|
|
148
|
+
].filter(Boolean).join(' ');` : `const componentClasses = \`c-${name.toLowerCase()} c-${name.toLowerCase()}--\${size} c-${name.toLowerCase()}--\${variant} \${disabled ? 'c-${name.toLowerCase()}--disabled' : ''} \${className}\`.trim();`}
|
|
149
|
+
|
|
150
|
+
return (
|
|
151
|
+
<div
|
|
152
|
+
ref={ref}
|
|
153
|
+
className={componentClasses}
|
|
154
|
+
aria-disabled={disabled}
|
|
155
|
+
{...props}
|
|
156
|
+
>
|
|
157
|
+
{children}
|
|
158
|
+
</div>
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
)
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
${name}.displayName = '${name}';
|
|
165
|
+
|
|
166
|
+
export default ${name};`,
|
|
167
|
+
|
|
168
|
+
index: (name) => `export { default as ${name} } from './${name}';
|
|
169
|
+
export type { ${name}Props } from './${name}';`,
|
|
170
|
+
|
|
171
|
+
story: (name) => `import type { Meta, StoryObj } from '@storybook/react';
|
|
172
|
+
import { ${name} } from './${name}';
|
|
173
|
+
|
|
174
|
+
const meta: Meta<typeof ${name}> = {
|
|
175
|
+
title: 'Components/${name}',
|
|
176
|
+
component: ${name},
|
|
177
|
+
parameters: {
|
|
178
|
+
layout: 'centered',
|
|
179
|
+
},
|
|
180
|
+
tags: ['autodocs'],
|
|
181
|
+
argTypes: {
|
|
182
|
+
size: {
|
|
183
|
+
control: 'select',
|
|
184
|
+
options: ['sm', 'md', 'lg'],
|
|
185
|
+
},
|
|
186
|
+
variant: {
|
|
187
|
+
control: 'select',
|
|
188
|
+
options: ['primary', 'secondary', 'success', 'error'],
|
|
189
|
+
},
|
|
190
|
+
disabled: {
|
|
191
|
+
control: 'boolean',
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
export default meta;
|
|
197
|
+
type Story = StoryObj<typeof meta>;
|
|
198
|
+
|
|
199
|
+
export const Default: Story = {
|
|
200
|
+
args: {
|
|
201
|
+
children: '${name} Component',
|
|
202
|
+
size: 'md',
|
|
203
|
+
variant: 'primary',
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
export const Small: Story = {
|
|
208
|
+
args: {
|
|
209
|
+
...Default.args,
|
|
210
|
+
size: 'sm',
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
export const Large: Story = {
|
|
215
|
+
args: {
|
|
216
|
+
...Default.args,
|
|
217
|
+
size: 'lg',
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
export const Secondary: Story = {
|
|
222
|
+
args: {
|
|
223
|
+
...Default.args,
|
|
224
|
+
variant: 'secondary',
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
export const Success: Story = {
|
|
229
|
+
args: {
|
|
230
|
+
...Default.args,
|
|
231
|
+
variant: 'success',
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
export const Error: Story = {
|
|
236
|
+
args: {
|
|
237
|
+
...Default.args,
|
|
238
|
+
variant: 'error',
|
|
239
|
+
},
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
export const Disabled: Story = {
|
|
243
|
+
args: {
|
|
244
|
+
...Default.args,
|
|
245
|
+
disabled: true,
|
|
246
|
+
},
|
|
247
|
+
};`,
|
|
248
|
+
|
|
249
|
+
test: (name) => `import { describe, it, expect } from 'vitest';
|
|
250
|
+
import { render, screen } from '@testing-library/react';
|
|
251
|
+
import { ${name} } from './${name}';
|
|
252
|
+
|
|
253
|
+
describe('${name}', () => {
|
|
254
|
+
it('renders children correctly', () => {
|
|
255
|
+
render(<${name}>Test Content</${name}>);
|
|
256
|
+
expect(screen.getByText('Test Content')).toBeInTheDocument();
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('applies size variant classes', () => {
|
|
260
|
+
const { container } = render(<${name} size="lg">Content</${name}>);
|
|
261
|
+
const element = container.firstChild;
|
|
262
|
+
expect(element).toHaveClass('c-${name.toLowerCase()}--lg');
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it('applies variant classes', () => {
|
|
266
|
+
const { container } = render(<${name} variant="success">Content</${name}>);
|
|
267
|
+
const element = container.firstChild;
|
|
268
|
+
expect(element).toHaveClass('c-${name.toLowerCase()}--success');
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
it('handles disabled state', () => {
|
|
272
|
+
const { container } = render(<${name} disabled>Content</${name}>);
|
|
273
|
+
const element = container.firstChild;
|
|
274
|
+
expect(element).toHaveAttribute('aria-disabled', 'true');
|
|
275
|
+
expect(element).toHaveClass('c-${name.toLowerCase()}--disabled');
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
it('forwards ref correctly', () => {
|
|
279
|
+
const ref = React.createRef<HTMLDivElement>();
|
|
280
|
+
render(<${name} ref={ref}>Content</${name}>);
|
|
281
|
+
expect(ref.current).toBeInstanceOf(HTMLDivElement);
|
|
282
|
+
});
|
|
283
|
+
});`,
|
|
284
|
+
|
|
285
|
+
scss: (name) => `// Component: ${name}
|
|
286
|
+
// =============================================================================
|
|
287
|
+
// Design system component following ITCSS architecture
|
|
288
|
+
|
|
289
|
+
@import '../../styles/01-settings';
|
|
290
|
+
@import '../../styles/02-tools';
|
|
291
|
+
|
|
292
|
+
// Block: Base component
|
|
293
|
+
// =============================================================================
|
|
294
|
+
.c-${name.toLowerCase()} {
|
|
295
|
+
// Layout
|
|
296
|
+
display: flex;
|
|
297
|
+
align-items: center;
|
|
298
|
+
justify-content: center;
|
|
299
|
+
|
|
300
|
+
// Spacing
|
|
301
|
+
padding: var(--atomix-space-3) var(--atomix-space-4);
|
|
302
|
+
gap: var(--atomix-space-2);
|
|
303
|
+
|
|
304
|
+
// Typography
|
|
305
|
+
font-family: var(--atomix-font-family-base);
|
|
306
|
+
font-size: var(--atomix-font-size-base);
|
|
307
|
+
font-weight: var(--atomix-font-weight-normal);
|
|
308
|
+
line-height: var(--atomix-line-height-base);
|
|
309
|
+
|
|
310
|
+
// Appearance
|
|
311
|
+
background-color: var(--atomix-color-background);
|
|
312
|
+
color: var(--atomix-color-text);
|
|
313
|
+
border: 1px solid var(--atomix-color-border);
|
|
314
|
+
border-radius: var(--atomix-radius-md);
|
|
315
|
+
|
|
316
|
+
// Interaction
|
|
317
|
+
cursor: default;
|
|
318
|
+
user-select: none;
|
|
319
|
+
transition: all 0.2s ease-in-out;
|
|
320
|
+
|
|
321
|
+
// Focus
|
|
322
|
+
&:focus-visible {
|
|
323
|
+
@include focus-ring;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Size Modifiers
|
|
328
|
+
// =============================================================================
|
|
329
|
+
.c-${name.toLowerCase()}--sm {
|
|
330
|
+
padding: var(--atomix-space-2) var(--atomix-space-3);
|
|
331
|
+
font-size: var(--atomix-font-size-sm);
|
|
332
|
+
gap: var(--atomix-space-1);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.c-${name.toLowerCase()}--md {
|
|
336
|
+
// Default size - explicitly defined for clarity
|
|
337
|
+
padding: var(--atomix-space-3) var(--atomix-space-4);
|
|
338
|
+
font-size: var(--atomix-font-size-base);
|
|
339
|
+
gap: var(--atomix-space-2);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
.c-${name.toLowerCase()}--lg {
|
|
343
|
+
padding: var(--atomix-space-4) var(--atomix-space-5);
|
|
344
|
+
font-size: var(--atomix-font-size-lg);
|
|
345
|
+
gap: var(--atomix-space-3);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Color/Variant Modifiers
|
|
349
|
+
// =============================================================================
|
|
350
|
+
.c-${name.toLowerCase()}--primary {
|
|
351
|
+
background-color: var(--atomix-color-primary);
|
|
352
|
+
color: var(--atomix-color-primary-text);
|
|
353
|
+
border-color: var(--atomix-color-primary-dark);
|
|
354
|
+
|
|
355
|
+
&:hover:not(:disabled) {
|
|
356
|
+
background-color: var(--atomix-color-primary-dark);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.c-${name.toLowerCase()}--secondary {
|
|
361
|
+
background-color: var(--atomix-color-secondary);
|
|
362
|
+
color: var(--atomix-color-secondary-text);
|
|
363
|
+
border-color: var(--atomix-color-secondary-dark);
|
|
364
|
+
|
|
365
|
+
&:hover:not(:disabled) {
|
|
366
|
+
background-color: var(--atomix-color-secondary-dark);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
.c-${name.toLowerCase()}--success {
|
|
371
|
+
background-color: var(--atomix-color-success);
|
|
372
|
+
color: var(--atomix-color-success-text);
|
|
373
|
+
border-color: var(--atomix-color-success-dark);
|
|
374
|
+
|
|
375
|
+
&:hover:not(:disabled) {
|
|
376
|
+
background-color: var(--atomix-color-success-dark);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
.c-${name.toLowerCase()}--error {
|
|
381
|
+
background-color: var(--atomix-color-error);
|
|
382
|
+
color: var(--atomix-color-error-text);
|
|
383
|
+
border-color: var(--atomix-color-error-dark);
|
|
384
|
+
|
|
385
|
+
&:hover:not(:disabled) {
|
|
386
|
+
background-color: var(--atomix-color-error-dark);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// State Modifiers
|
|
391
|
+
// =============================================================================
|
|
392
|
+
.c-${name.toLowerCase()}--disabled {
|
|
393
|
+
@include disabled;
|
|
394
|
+
cursor: not-allowed;
|
|
395
|
+
|
|
396
|
+
&:hover {
|
|
397
|
+
transform: none;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Elements (if component has child elements)
|
|
402
|
+
// =============================================================================
|
|
403
|
+
.c-${name.toLowerCase()}__icon {
|
|
404
|
+
display: flex;
|
|
405
|
+
align-items: center;
|
|
406
|
+
justify-content: center;
|
|
407
|
+
flex-shrink: 0;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
.c-${name.toLowerCase()}__content {
|
|
411
|
+
flex: 1;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// Responsive Design
|
|
415
|
+
// =============================================================================
|
|
416
|
+
@include respond-to('tablet') {
|
|
417
|
+
.c-${name.toLowerCase()} {
|
|
418
|
+
// Tablet adjustments
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
@include respond-to('mobile') {
|
|
423
|
+
.c-${name.toLowerCase()} {
|
|
424
|
+
// Mobile adjustments
|
|
425
|
+
padding: var(--atomix-space-2) var(--atomix-space-3);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// Accessibility
|
|
430
|
+
// =============================================================================
|
|
431
|
+
@media (prefers-reduced-motion: reduce) {
|
|
432
|
+
.c-${name.toLowerCase()} {
|
|
433
|
+
transition: none;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
@media (prefers-contrast: high) {
|
|
438
|
+
.c-${name.toLowerCase()} {
|
|
439
|
+
border-width: 2px;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// Dark Mode Support
|
|
444
|
+
// =============================================================================
|
|
445
|
+
[data-theme="dark"] {
|
|
446
|
+
.c-${name.toLowerCase()} {
|
|
447
|
+
background-color: var(--atomix-color-background-dark);
|
|
448
|
+
color: var(--atomix-color-text-dark);
|
|
449
|
+
border-color: var(--atomix-color-border-dark);
|
|
450
|
+
}
|
|
451
|
+
}`,
|
|
452
|
+
|
|
453
|
+
scssModule: (name) => `// Component: ${name}
|
|
454
|
+
// =============================================================================
|
|
455
|
+
// Design system component using CSS Modules
|
|
456
|
+
|
|
457
|
+
@import '../../styles/01-settings';
|
|
458
|
+
@import '../../styles/02-tools';
|
|
459
|
+
|
|
460
|
+
// Block: Base component
|
|
461
|
+
// =============================================================================
|
|
462
|
+
.${name.toLowerCase()} {
|
|
463
|
+
// Layout
|
|
464
|
+
display: flex;
|
|
465
|
+
align-items: center;
|
|
466
|
+
justify-content: center;
|
|
467
|
+
|
|
468
|
+
// Spacing
|
|
469
|
+
padding: var(--atomix-space-3) var(--atomix-space-4);
|
|
470
|
+
gap: var(--atomix-space-2);
|
|
471
|
+
|
|
472
|
+
// Typography
|
|
473
|
+
font-family: var(--atomix-font-family-base);
|
|
474
|
+
font-size: var(--atomix-font-size-base);
|
|
475
|
+
font-weight: var(--atomix-font-weight-normal);
|
|
476
|
+
line-height: var(--atomix-line-height-base);
|
|
477
|
+
|
|
478
|
+
// Appearance
|
|
479
|
+
background-color: var(--atomix-color-background);
|
|
480
|
+
color: var(--atomix-color-text);
|
|
481
|
+
border: 1px solid var(--atomix-color-border);
|
|
482
|
+
border-radius: var(--atomix-radius-md);
|
|
483
|
+
|
|
484
|
+
// Interaction
|
|
485
|
+
cursor: default;
|
|
486
|
+
user-select: none;
|
|
487
|
+
transition: all 0.2s ease-in-out;
|
|
488
|
+
|
|
489
|
+
// Focus
|
|
490
|
+
&:focus-visible {
|
|
491
|
+
outline: 2px solid var(--atomix-color-focus);
|
|
492
|
+
outline-offset: 2px;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
// Size Modifiers
|
|
497
|
+
// =============================================================================
|
|
498
|
+
.${name.toLowerCase()}--sm {
|
|
499
|
+
composes: ${name.toLowerCase()};
|
|
500
|
+
padding: var(--atomix-space-2) var(--atomix-space-3);
|
|
501
|
+
font-size: var(--atomix-font-size-sm);
|
|
502
|
+
gap: var(--atomix-space-1);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
.${name.toLowerCase()}--md {
|
|
506
|
+
composes: ${name.toLowerCase()};
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
.${name.toLowerCase()}--lg {
|
|
510
|
+
composes: ${name.toLowerCase()};
|
|
511
|
+
padding: var(--atomix-space-4) var(--atomix-space-5);
|
|
512
|
+
font-size: var(--atomix-font-size-lg);
|
|
513
|
+
gap: var(--atomix-space-3);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// Color/Variant Modifiers
|
|
517
|
+
// =============================================================================
|
|
518
|
+
.${name.toLowerCase()}--primary {
|
|
519
|
+
background-color: var(--atomix-color-primary);
|
|
520
|
+
color: var(--atomix-color-primary-text);
|
|
521
|
+
border-color: var(--atomix-color-primary-dark);
|
|
522
|
+
|
|
523
|
+
&:hover:not([aria-disabled="true"]) {
|
|
524
|
+
background-color: var(--atomix-color-primary-dark);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
.${name.toLowerCase()}--secondary {
|
|
529
|
+
background-color: var(--atomix-color-secondary);
|
|
530
|
+
color: var(--atomix-color-secondary-text);
|
|
531
|
+
border-color: var(--atomix-color-secondary-dark);
|
|
532
|
+
|
|
533
|
+
&:hover:not([aria-disabled="true"]) {
|
|
534
|
+
background-color: var(--atomix-color-secondary-dark);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
.${name.toLowerCase()}--success {
|
|
539
|
+
background-color: var(--atomix-color-success);
|
|
540
|
+
color: var(--atomix-color-success-text);
|
|
541
|
+
border-color: var(--atomix-color-success-dark);
|
|
542
|
+
|
|
543
|
+
&:hover:not([aria-disabled="true"]) {
|
|
544
|
+
background-color: var(--atomix-color-success-dark);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
.${name.toLowerCase()}--error {
|
|
549
|
+
background-color: var(--atomix-color-error);
|
|
550
|
+
color: var(--atomix-color-error-text);
|
|
551
|
+
border-color: var(--atomix-color-error-dark);
|
|
552
|
+
|
|
553
|
+
&:hover:not([aria-disabled="true"]) {
|
|
554
|
+
background-color: var(--atomix-color-error-dark);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// State Modifiers
|
|
559
|
+
// =============================================================================
|
|
560
|
+
.${name.toLowerCase()}--disabled {
|
|
561
|
+
opacity: 0.5;
|
|
562
|
+
cursor: not-allowed;
|
|
563
|
+
pointer-events: none;
|
|
564
|
+
}`
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
// Initialize program
|
|
569
|
+
program
|
|
570
|
+
.name('atomix')
|
|
571
|
+
.description('Atomix Design System CLI - Enhanced Edition')
|
|
572
|
+
.version(packageJson.version)
|
|
573
|
+
.option('-d, --debug', 'Enable debug mode', false)
|
|
574
|
+
.hook('preAction', (thisCommand) => {
|
|
575
|
+
if (thisCommand.opts().debug) {
|
|
576
|
+
process.env.ATOMIX_DEBUG = 'true';
|
|
577
|
+
}
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Enhanced Build Theme Command with Watch Mode
|
|
582
|
+
*/
|
|
583
|
+
program
|
|
584
|
+
.command('build-theme <path>')
|
|
585
|
+
.description('Build a custom theme from SCSS')
|
|
586
|
+
.option('-o, --output <path>', 'Output directory', './dist')
|
|
587
|
+
.option('-m, --minify', 'Generate minified version', true)
|
|
588
|
+
.option('-s, --sourcemap', 'Generate source maps', false)
|
|
589
|
+
.option('-w, --watch', 'Watch for changes and rebuild', false)
|
|
590
|
+
.option('--analyze', 'Analyze bundle size', false)
|
|
591
|
+
.action(async (themePath, options) => {
|
|
592
|
+
let spinner = ora('Initializing theme build...').start();
|
|
593
|
+
|
|
594
|
+
try {
|
|
595
|
+
// Resolve paths
|
|
596
|
+
const indexPath = themePath.endsWith('.scss')
|
|
597
|
+
? resolve(themePath)
|
|
598
|
+
: resolve(themePath, 'index.scss');
|
|
599
|
+
|
|
600
|
+
debug(`Building theme from: ${indexPath}`);
|
|
601
|
+
|
|
602
|
+
// Check if path exists
|
|
603
|
+
try {
|
|
604
|
+
await access(indexPath);
|
|
605
|
+
} catch (error) {
|
|
606
|
+
throw new AtomixCLIError(
|
|
607
|
+
`Theme file not found: ${indexPath}`,
|
|
608
|
+
'THEME_NOT_FOUND',
|
|
609
|
+
[
|
|
610
|
+
'Check if the file path is correct',
|
|
611
|
+
'Ensure the file has a .scss extension',
|
|
612
|
+
'Create a new theme with: atomix create-theme <name>'
|
|
613
|
+
]
|
|
614
|
+
);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// Build function
|
|
618
|
+
const buildTheme = async () => {
|
|
619
|
+
const startTime = Date.now();
|
|
620
|
+
|
|
621
|
+
try {
|
|
622
|
+
// Compile SCSS
|
|
623
|
+
spinner.text = 'Compiling SCSS...';
|
|
624
|
+
debug('Starting SCSS compilation');
|
|
625
|
+
|
|
626
|
+
const result = sass.compile(indexPath, {
|
|
627
|
+
loadPaths: [
|
|
628
|
+
process.cwd(),
|
|
629
|
+
join(process.cwd(), 'node_modules'),
|
|
630
|
+
join(__dirname, '../src'),
|
|
631
|
+
join(__dirname, '../src/styles'),
|
|
632
|
+
dirname(indexPath)
|
|
633
|
+
],
|
|
634
|
+
sourceMap: options.sourcemap,
|
|
635
|
+
style: 'expanded',
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
// Process with PostCSS
|
|
639
|
+
spinner.text = 'Processing with PostCSS...';
|
|
640
|
+
const processed = await postcss([
|
|
641
|
+
autoprefixer({
|
|
642
|
+
overrideBrowserslist: ['> 1%', 'last 2 versions', 'not dead'],
|
|
643
|
+
}),
|
|
644
|
+
]).process(result.css, {
|
|
645
|
+
from: indexPath,
|
|
646
|
+
map: options.sourcemap,
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
// Ensure output directory exists
|
|
650
|
+
await mkdir(options.output, { recursive: true });
|
|
651
|
+
|
|
652
|
+
// Get theme name
|
|
653
|
+
const themeName = basename(dirname(indexPath));
|
|
654
|
+
|
|
655
|
+
// Write expanded CSS
|
|
656
|
+
const outputPath = join(options.output, `${themeName}.css`);
|
|
657
|
+
await writeFile(outputPath, processed.css, 'utf8');
|
|
658
|
+
|
|
659
|
+
// Get file size
|
|
660
|
+
const stats = await stat(outputPath);
|
|
661
|
+
const sizeKB = (stats.size / 1024).toFixed(2);
|
|
662
|
+
|
|
663
|
+
spinner.succeed(chalk.green(`✓ Built ${outputPath} (${sizeKB} KB)`));
|
|
664
|
+
|
|
665
|
+
// Write minified if requested
|
|
666
|
+
if (options.minify) {
|
|
667
|
+
const minifySpinner = ora('Minifying CSS...').start();
|
|
668
|
+
const minified = await postcss([
|
|
669
|
+
autoprefixer(),
|
|
670
|
+
cssnano({ preset: 'default' }),
|
|
671
|
+
]).process(result.css, {
|
|
672
|
+
from: indexPath,
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
const minPath = join(options.output, `${themeName}.min.css`);
|
|
676
|
+
await writeFile(minPath, minified.css, 'utf8');
|
|
677
|
+
|
|
678
|
+
const minStats = await stat(minPath);
|
|
679
|
+
const minSizeKB = (minStats.size / 1024).toFixed(2);
|
|
680
|
+
|
|
681
|
+
minifySpinner.succeed(chalk.green(`✓ Built ${minPath} (${minSizeKB} KB)`));
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// Analyze if requested
|
|
685
|
+
if (options.analyze) {
|
|
686
|
+
console.log(chalk.cyan('\n📊 Theme Analysis:'));
|
|
687
|
+
console.log(chalk.gray(` Original size: ${sizeKB} KB`));
|
|
688
|
+
if (options.minify) {
|
|
689
|
+
const minPath = join(options.output, `${themeName}.min.css`);
|
|
690
|
+
const minStats = await stat(minPath);
|
|
691
|
+
const minSizeKB = (minStats.size / 1024).toFixed(2);
|
|
692
|
+
const reduction = ((1 - minStats.size / stats.size) * 100).toFixed(1);
|
|
693
|
+
console.log(chalk.gray(` Minified size: ${minSizeKB} KB (${reduction}% reduction)`));
|
|
694
|
+
}
|
|
695
|
+
console.log(chalk.gray(` Build time: ${Date.now() - startTime}ms`));
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
if (!options.watch) {
|
|
699
|
+
console.log(chalk.bold.green('\n✨ Theme build complete!'));
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
} catch (error) {
|
|
703
|
+
if (options.watch) {
|
|
704
|
+
console.error(chalk.red(`Build error: ${error.message}`));
|
|
705
|
+
console.log(chalk.yellow('Waiting for changes...'));
|
|
706
|
+
} else {
|
|
707
|
+
throw error;
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
};
|
|
711
|
+
|
|
712
|
+
// Initial build
|
|
713
|
+
await buildTheme();
|
|
714
|
+
spinner.stop();
|
|
715
|
+
|
|
716
|
+
// Watch mode
|
|
717
|
+
if (options.watch) {
|
|
718
|
+
console.log(chalk.cyan('\n👁️ Watch mode enabled. Press Ctrl+C to exit.\n'));
|
|
719
|
+
|
|
720
|
+
const watcher = chokidar.watch([themePath], {
|
|
721
|
+
ignored: /node_modules/,
|
|
722
|
+
persistent: true,
|
|
723
|
+
ignoreInitial: true
|
|
724
|
+
});
|
|
725
|
+
|
|
726
|
+
watcher.on('change', async (path) => {
|
|
727
|
+
console.log(chalk.gray(`\n[${new Date().toLocaleTimeString()}] File changed: ${relative(process.cwd(), path)}`));
|
|
728
|
+
spinner = ora('Rebuilding theme...').start();
|
|
729
|
+
await buildTheme();
|
|
730
|
+
spinner.stop();
|
|
731
|
+
});
|
|
732
|
+
|
|
733
|
+
watcher.on('add', async (path) => {
|
|
734
|
+
console.log(chalk.gray(`\n[${new Date().toLocaleTimeString()}] File added: ${relative(process.cwd(), path)}`));
|
|
735
|
+
spinner = ora('Rebuilding theme...').start();
|
|
736
|
+
await buildTheme();
|
|
737
|
+
spinner.stop();
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
// Handle graceful shutdown
|
|
741
|
+
process.on('SIGINT', () => {
|
|
742
|
+
console.log(chalk.yellow('\n\nShutting down watch mode...'));
|
|
743
|
+
watcher.close();
|
|
744
|
+
process.exit(0);
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
} catch (error) {
|
|
749
|
+
handleError(error, spinner);
|
|
750
|
+
}
|
|
751
|
+
});
|
|
752
|
+
|
|
753
|
+
/**
|
|
754
|
+
* Generate Component Command - NEW
|
|
755
|
+
*/
|
|
756
|
+
program
|
|
757
|
+
.command('generate <type> <name>')
|
|
758
|
+
.alias('g')
|
|
759
|
+
.description('Generate design system components, tokens, or themes')
|
|
760
|
+
.option('-t, --typescript', 'Use TypeScript (default)', true)
|
|
761
|
+
.option('-s, --story', 'Include Storybook story', true)
|
|
762
|
+
.option('--test', 'Include test file', false)
|
|
763
|
+
.option('--scss-module', 'Use SCSS modules', false)
|
|
764
|
+
.option('--path <path>', 'Custom output path', './src/components')
|
|
765
|
+
.option('-f, --force', 'Overwrite existing files', false)
|
|
766
|
+
.action(async (type, name, options) => {
|
|
767
|
+
const spinner = ora(`Generating ${type}: ${name}...`).start();
|
|
768
|
+
|
|
769
|
+
try {
|
|
770
|
+
debug(`Generating ${type} with name: ${name}`, options);
|
|
771
|
+
|
|
772
|
+
// Validate name
|
|
773
|
+
if (!/^[A-Z][a-zA-Z0-9]*$/.test(name)) {
|
|
774
|
+
throw new AtomixCLIError(
|
|
775
|
+
'Component name must be in PascalCase (e.g., Button, CardHeader)',
|
|
776
|
+
'INVALID_NAME',
|
|
777
|
+
[
|
|
778
|
+
'Use PascalCase naming (e.g., MyComponent)',
|
|
779
|
+
'Start with an uppercase letter',
|
|
780
|
+
'Use only letters and numbers'
|
|
781
|
+
]
|
|
782
|
+
);
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
if (type === 'component' || type === 'c') {
|
|
786
|
+
const componentPath = join(options.path, name);
|
|
787
|
+
|
|
788
|
+
// Check if component already exists
|
|
789
|
+
if (existsSync(componentPath) && !options.force) {
|
|
790
|
+
throw new AtomixCLIError(
|
|
791
|
+
`Component ${name} already exists`,
|
|
792
|
+
'COMPONENT_EXISTS',
|
|
793
|
+
[
|
|
794
|
+
`Delete the existing component at ${componentPath}`,
|
|
795
|
+
'Use --force flag to overwrite',
|
|
796
|
+
'Choose a different component name'
|
|
797
|
+
]
|
|
798
|
+
);
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
// Create component directory
|
|
802
|
+
await mkdir(componentPath, { recursive: true });
|
|
803
|
+
|
|
804
|
+
// Generate component file
|
|
805
|
+
const componentContent = componentTemplates.react.component(name, {
|
|
806
|
+
scssModule: options.scssModule,
|
|
807
|
+
types: false // We'll generate inline types for now
|
|
808
|
+
});
|
|
809
|
+
|
|
810
|
+
await writeFile(
|
|
811
|
+
join(componentPath, `${name}.tsx`),
|
|
812
|
+
componentContent,
|
|
813
|
+
'utf8'
|
|
814
|
+
);
|
|
815
|
+
spinner.succeed(chalk.green(`✓ Created ${name}.tsx`));
|
|
816
|
+
|
|
817
|
+
// Generate index file
|
|
818
|
+
const indexContent = componentTemplates.react.index(name);
|
|
819
|
+
await writeFile(
|
|
820
|
+
join(componentPath, 'index.ts'),
|
|
821
|
+
indexContent,
|
|
822
|
+
'utf8'
|
|
823
|
+
);
|
|
824
|
+
console.log(chalk.green(` ✓ Created index.ts`));
|
|
825
|
+
|
|
826
|
+
// Generate SCSS file
|
|
827
|
+
const scssContent = options.scssModule
|
|
828
|
+
? componentTemplates.react.scssModule(name)
|
|
829
|
+
: componentTemplates.react.scss(name);
|
|
830
|
+
|
|
831
|
+
const scssFilename = options.scssModule ? `${name}.module.scss` : `_${name.toLowerCase()}.scss`;
|
|
832
|
+
await writeFile(
|
|
833
|
+
join(componentPath, scssFilename),
|
|
834
|
+
scssContent,
|
|
835
|
+
'utf8'
|
|
836
|
+
);
|
|
837
|
+
console.log(chalk.green(` ✓ Created ${scssFilename}`));
|
|
838
|
+
|
|
839
|
+
// Generate Storybook story
|
|
840
|
+
if (options.story) {
|
|
841
|
+
const storyContent = componentTemplates.react.story(name);
|
|
842
|
+
await writeFile(
|
|
843
|
+
join(componentPath, `${name}.stories.tsx`),
|
|
844
|
+
storyContent,
|
|
845
|
+
'utf8'
|
|
846
|
+
);
|
|
847
|
+
console.log(chalk.green(` ✓ Created ${name}.stories.tsx`));
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
// Generate test file
|
|
851
|
+
if (options.test) {
|
|
852
|
+
const testContent = componentTemplates.react.test(name);
|
|
853
|
+
await writeFile(
|
|
854
|
+
join(componentPath, `${name}.test.tsx`),
|
|
855
|
+
testContent,
|
|
856
|
+
'utf8'
|
|
857
|
+
);
|
|
858
|
+
console.log(chalk.green(` ✓ Created ${name}.test.tsx`));
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
// Success message with next steps
|
|
862
|
+
console.log(boxen(
|
|
863
|
+
chalk.bold.green(`🎉 Component ${name} created successfully!\n\n`) +
|
|
864
|
+
chalk.cyan('Next steps:\n') +
|
|
865
|
+
chalk.gray(`1. Import in your app:\n`) +
|
|
866
|
+
chalk.white(` import { ${name} } from '${options.path}/${name}';\n\n`) +
|
|
867
|
+
chalk.gray(`2. Add to design system exports:\n`) +
|
|
868
|
+
chalk.white(` export { ${name} } from './${name}';\n\n`) +
|
|
869
|
+
chalk.gray(`3. Run Storybook to see your component:\n`) +
|
|
870
|
+
chalk.white(` npm run storybook`),
|
|
871
|
+
{
|
|
872
|
+
padding: 1,
|
|
873
|
+
margin: 1,
|
|
874
|
+
borderStyle: 'round',
|
|
875
|
+
borderColor: 'green'
|
|
876
|
+
}
|
|
877
|
+
));
|
|
878
|
+
|
|
879
|
+
} else if (type === 'token' || type === 't') {
|
|
880
|
+
// Token generation logic (to be implemented)
|
|
881
|
+
throw new AtomixCLIError(
|
|
882
|
+
'Token generation not yet implemented',
|
|
883
|
+
'NOT_IMPLEMENTED',
|
|
884
|
+
[
|
|
885
|
+
'This feature is coming soon',
|
|
886
|
+
'For now, manually edit token files in src/styles/01-settings'
|
|
887
|
+
]
|
|
888
|
+
);
|
|
889
|
+
} else {
|
|
890
|
+
throw new AtomixCLIError(
|
|
891
|
+
`Unknown generation type: ${type}`,
|
|
892
|
+
'UNKNOWN_TYPE',
|
|
893
|
+
[
|
|
894
|
+
'Valid types are: component (or c), token (or t)',
|
|
895
|
+
'Example: atomix generate component Button',
|
|
896
|
+
'Example: atomix g c Button'
|
|
897
|
+
]
|
|
898
|
+
);
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
} catch (error) {
|
|
902
|
+
handleError(error, spinner);
|
|
903
|
+
}
|
|
904
|
+
});
|
|
905
|
+
|
|
906
|
+
/**
|
|
907
|
+
* Validate Command - NEW
|
|
908
|
+
*/
|
|
909
|
+
program
|
|
910
|
+
.command('validate [target]')
|
|
911
|
+
.description('Validate themes, design tokens, or accessibility')
|
|
912
|
+
.option('--tokens', 'Validate design tokens', false)
|
|
913
|
+
.option('--theme <path>', 'Validate specific theme', '')
|
|
914
|
+
.option('--a11y, --accessibility', 'Check accessibility compliance', false)
|
|
915
|
+
.option('--fix', 'Attempt to fix issues automatically', false)
|
|
916
|
+
.action(async (target, options) => {
|
|
917
|
+
const spinner = ora('Running validation...').start();
|
|
918
|
+
|
|
919
|
+
try {
|
|
920
|
+
debug('Validation options:', options);
|
|
921
|
+
|
|
922
|
+
const issues = [];
|
|
923
|
+
const warnings = [];
|
|
924
|
+
|
|
925
|
+
// Token validation
|
|
926
|
+
if (options.tokens || target === 'tokens') {
|
|
927
|
+
spinner.text = 'Validating design tokens...';
|
|
928
|
+
|
|
929
|
+
const tokenFiles = [
|
|
930
|
+
'src/styles/01-settings/_settings.colors.scss',
|
|
931
|
+
'src/styles/01-settings/_settings.typography.scss',
|
|
932
|
+
'src/styles/01-settings/_settings.spacing.scss',
|
|
933
|
+
'src/styles/01-settings/_settings.radius.scss'
|
|
934
|
+
];
|
|
935
|
+
|
|
936
|
+
for (const file of tokenFiles) {
|
|
937
|
+
const filePath = join(process.cwd(), file);
|
|
938
|
+
if (existsSync(filePath)) {
|
|
939
|
+
const content = await readFile(filePath, 'utf8');
|
|
940
|
+
|
|
941
|
+
// Check for hardcoded values
|
|
942
|
+
const hardcodedColors = content.match(/#[0-9a-fA-F]{3,8}(?![0-9a-fA-F])/g);
|
|
943
|
+
if (hardcodedColors && hardcodedColors.length > 0) {
|
|
944
|
+
warnings.push({
|
|
945
|
+
file: file,
|
|
946
|
+
issue: `Found ${hardcodedColors.length} hardcoded color values`,
|
|
947
|
+
suggestion: 'Use CSS custom properties or SCSS variables'
|
|
948
|
+
});
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
// Check for missing default flags
|
|
952
|
+
const variables = content.match(/\$[a-z-]+:/gi);
|
|
953
|
+
const defaultFlags = content.match(/!default/g);
|
|
954
|
+
if (variables && (!defaultFlags || defaultFlags.length < variables.length)) {
|
|
955
|
+
warnings.push({
|
|
956
|
+
file: file,
|
|
957
|
+
issue: 'Some variables missing !default flag',
|
|
958
|
+
suggestion: 'Add !default to all token variables for better theming'
|
|
959
|
+
});
|
|
960
|
+
}
|
|
961
|
+
} else {
|
|
962
|
+
issues.push({
|
|
963
|
+
file: file,
|
|
964
|
+
issue: 'Token file not found',
|
|
965
|
+
suggestion: 'Ensure all token files are present in src/styles/01-settings/'
|
|
966
|
+
});
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
// Theme validation
|
|
972
|
+
if (options.theme) {
|
|
973
|
+
spinner.text = `Validating theme: ${options.theme}...`;
|
|
974
|
+
|
|
975
|
+
const themePath = resolve(options.theme);
|
|
976
|
+
if (!existsSync(themePath)) {
|
|
977
|
+
issues.push({
|
|
978
|
+
file: options.theme,
|
|
979
|
+
issue: 'Theme file not found',
|
|
980
|
+
suggestion: 'Check the theme path is correct'
|
|
981
|
+
});
|
|
982
|
+
} else {
|
|
983
|
+
const content = await readFile(themePath, 'utf8');
|
|
984
|
+
|
|
985
|
+
// Check for required imports
|
|
986
|
+
const requiredImports = [
|
|
987
|
+
'@import.*settings',
|
|
988
|
+
'@use.*settings',
|
|
989
|
+
'@import.*tools',
|
|
990
|
+
'@use.*tools'
|
|
991
|
+
];
|
|
992
|
+
|
|
993
|
+
let hasSettings = false;
|
|
994
|
+
for (const pattern of requiredImports) {
|
|
995
|
+
if (new RegExp(pattern).test(content)) {
|
|
996
|
+
hasSettings = true;
|
|
997
|
+
break;
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
if (!hasSettings) {
|
|
1002
|
+
issues.push({
|
|
1003
|
+
file: options.theme,
|
|
1004
|
+
issue: 'Missing design system imports',
|
|
1005
|
+
suggestion: 'Import settings and tools from the design system'
|
|
1006
|
+
});
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
// Accessibility validation
|
|
1012
|
+
if (options.a11y || options.accessibility) {
|
|
1013
|
+
spinner.text = 'Checking accessibility compliance...';
|
|
1014
|
+
|
|
1015
|
+
// Check for focus styles
|
|
1016
|
+
const componentFiles = [
|
|
1017
|
+
'src/styles/06-components'
|
|
1018
|
+
];
|
|
1019
|
+
|
|
1020
|
+
for (const dir of componentFiles) {
|
|
1021
|
+
const dirPath = join(process.cwd(), dir);
|
|
1022
|
+
if (existsSync(dirPath)) {
|
|
1023
|
+
// This is a simplified check - in reality, we'd parse the CSS
|
|
1024
|
+
warnings.push({
|
|
1025
|
+
file: dir,
|
|
1026
|
+
issue: 'Manual accessibility review recommended',
|
|
1027
|
+
suggestion: 'Ensure all interactive components have :focus-visible styles'
|
|
1028
|
+
});
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
spinner.stop();
|
|
1034
|
+
|
|
1035
|
+
// Display results
|
|
1036
|
+
if (issues.length === 0 && warnings.length === 0) {
|
|
1037
|
+
console.log(boxen(
|
|
1038
|
+
chalk.bold.green('✅ All validations passed!\n\n') +
|
|
1039
|
+
chalk.gray('Your design system is following best practices.'),
|
|
1040
|
+
{
|
|
1041
|
+
padding: 1,
|
|
1042
|
+
margin: 1,
|
|
1043
|
+
borderStyle: 'round',
|
|
1044
|
+
borderColor: 'green'
|
|
1045
|
+
}
|
|
1046
|
+
));
|
|
1047
|
+
} else {
|
|
1048
|
+
if (issues.length > 0) {
|
|
1049
|
+
console.log(chalk.bold.red(`\n❌ Found ${issues.length} issue(s):\n`));
|
|
1050
|
+
issues.forEach((issue, index) => {
|
|
1051
|
+
console.log(chalk.red(` ${index + 1}. ${issue.file}`));
|
|
1052
|
+
console.log(chalk.gray(` Issue: ${issue.issue}`));
|
|
1053
|
+
console.log(chalk.yellow(` Fix: ${issue.suggestion}\n`));
|
|
1054
|
+
});
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
if (warnings.length > 0) {
|
|
1058
|
+
console.log(chalk.bold.yellow(`\n⚠️ Found ${warnings.length} warning(s):\n`));
|
|
1059
|
+
warnings.forEach((warning, index) => {
|
|
1060
|
+
console.log(chalk.yellow(` ${index + 1}. ${warning.file}`));
|
|
1061
|
+
console.log(chalk.gray(` Warning: ${warning.issue}`));
|
|
1062
|
+
console.log(chalk.cyan(` Suggestion: ${warning.suggestion}\n`));
|
|
1063
|
+
});
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
if (options.fix && issues.length > 0) {
|
|
1067
|
+
console.log(chalk.cyan('\n🔧 Auto-fix is not yet implemented. Please fix issues manually.'));
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
} catch (error) {
|
|
1072
|
+
handleError(error, spinner);
|
|
1073
|
+
}
|
|
1074
|
+
});
|
|
1075
|
+
|
|
1076
|
+
/**
|
|
1077
|
+
* Dev Command - NEW (Alias for build --watch)
|
|
1078
|
+
*/
|
|
1079
|
+
program
|
|
1080
|
+
.command('dev <theme>')
|
|
1081
|
+
.description('Start development mode with hot reload')
|
|
1082
|
+
.option('-o, --output <path>', 'Output directory', './dist')
|
|
1083
|
+
.option('--open', 'Open in browser after build', false)
|
|
1084
|
+
.action(async (theme, options) => {
|
|
1085
|
+
console.log(boxen(
|
|
1086
|
+
chalk.bold.cyan('🚀 Starting Atomix Dev Mode\n\n') +
|
|
1087
|
+
chalk.gray('Watching for changes...\n') +
|
|
1088
|
+
chalk.gray('Press Ctrl+C to exit'),
|
|
1089
|
+
{
|
|
1090
|
+
padding: 1,
|
|
1091
|
+
margin: 1,
|
|
1092
|
+
borderStyle: 'round',
|
|
1093
|
+
borderColor: 'cyan'
|
|
1094
|
+
}
|
|
1095
|
+
));
|
|
1096
|
+
|
|
1097
|
+
// Reuse build command with watch flag
|
|
1098
|
+
await program.parseAsync([
|
|
1099
|
+
...process.argv.slice(0, 2),
|
|
1100
|
+
'build-theme',
|
|
1101
|
+
theme,
|
|
1102
|
+
'--watch',
|
|
1103
|
+
'--output', options.output
|
|
1104
|
+
]);
|
|
1105
|
+
});
|
|
1106
|
+
|
|
1107
|
+
// Keep existing commands (create-theme, list-themes, info)
|
|
1108
|
+
// ... [Previous create-theme, list-themes, and info commands remain the same]
|
|
1109
|
+
|
|
1110
|
+
/**
|
|
1111
|
+
* Migrate Command - NEW (Migration from other frameworks)
|
|
1112
|
+
*/
|
|
1113
|
+
program
|
|
1114
|
+
.command('migrate <from>')
|
|
1115
|
+
.description('Migrate from other CSS frameworks to Atomix design system')
|
|
1116
|
+
.option('-s, --source <path>', 'Source directory to migrate', './src')
|
|
1117
|
+
.option('--dry-run', 'Preview changes without modifying files', false)
|
|
1118
|
+
.option('--create-backup', 'Create backup before migration', true)
|
|
1119
|
+
.action(async (from, options) => {
|
|
1120
|
+
const spinner = ora('Preparing migration...').start();
|
|
1121
|
+
|
|
1122
|
+
try {
|
|
1123
|
+
debug(`Migrating from ${from}`, options);
|
|
1124
|
+
|
|
1125
|
+
// Validate migration type
|
|
1126
|
+
const validMigrations = ['tailwind', 'bootstrap', 'scss-variables'];
|
|
1127
|
+
if (!validMigrations.includes(from.toLowerCase())) {
|
|
1128
|
+
throw new AtomixCLIError(
|
|
1129
|
+
`Unknown migration source: ${from}`,
|
|
1130
|
+
'INVALID_MIGRATION',
|
|
1131
|
+
[
|
|
1132
|
+
'Valid migration sources: tailwind, bootstrap, scss-variables',
|
|
1133
|
+
'Example: atomix migrate tailwind',
|
|
1134
|
+
'Example: atomix migrate bootstrap --source ./src'
|
|
1135
|
+
]
|
|
1136
|
+
);
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
// Check source directory
|
|
1140
|
+
const sourcePath = resolve(options.source);
|
|
1141
|
+
if (!existsSync(sourcePath)) {
|
|
1142
|
+
throw new AtomixCLIError(
|
|
1143
|
+
`Source directory not found: ${sourcePath}`,
|
|
1144
|
+
'SOURCE_NOT_FOUND',
|
|
1145
|
+
[
|
|
1146
|
+
'Check the source path is correct',
|
|
1147
|
+
'Use --source flag to specify a different directory',
|
|
1148
|
+
'Example: atomix migrate tailwind --source ./app'
|
|
1149
|
+
]
|
|
1150
|
+
);
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
spinner.stop();
|
|
1154
|
+
|
|
1155
|
+
// Show migration preview
|
|
1156
|
+
console.log(boxen(
|
|
1157
|
+
chalk.bold.cyan(`🔄 Migration Preview\n\n`) +
|
|
1158
|
+
chalk.gray(`From: ${chalk.white(from)}\n`) +
|
|
1159
|
+
chalk.gray(`Source: ${chalk.white(sourcePath)}\n`) +
|
|
1160
|
+
chalk.gray(`Mode: ${options.dryRun ? chalk.yellow('Dry Run') : chalk.green('Live')}\n`) +
|
|
1161
|
+
chalk.gray(`Backup: ${options.createBackup ? chalk.green('Yes') : chalk.red('No')}`),
|
|
1162
|
+
{
|
|
1163
|
+
padding: 1,
|
|
1164
|
+
margin: 1,
|
|
1165
|
+
borderStyle: 'round',
|
|
1166
|
+
borderColor: 'cyan'
|
|
1167
|
+
}
|
|
1168
|
+
));
|
|
1169
|
+
|
|
1170
|
+
// Confirm migration
|
|
1171
|
+
if (!options.dryRun) {
|
|
1172
|
+
const { confirmMigration } = await inquirer.prompt([
|
|
1173
|
+
{
|
|
1174
|
+
type: 'confirm',
|
|
1175
|
+
name: 'confirmMigration',
|
|
1176
|
+
message: chalk.yellow('This will modify your files. Continue?'),
|
|
1177
|
+
default: false
|
|
1178
|
+
}
|
|
1179
|
+
]);
|
|
1180
|
+
|
|
1181
|
+
if (!confirmMigration) {
|
|
1182
|
+
console.log(chalk.yellow('\n Migration cancelled.'));
|
|
1183
|
+
return;
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
// Create backup if requested
|
|
1188
|
+
if (options.createBackup && !options.dryRun) {
|
|
1189
|
+
const backupSpinner = ora('Creating backup...').start();
|
|
1190
|
+
const backupDir = `${sourcePath}.backup.${Date.now()}`;
|
|
1191
|
+
|
|
1192
|
+
try {
|
|
1193
|
+
const { execSync } = await import('child_process');
|
|
1194
|
+
execSync(`cp -r "${sourcePath}" "${backupDir}"`, { stdio: 'ignore' });
|
|
1195
|
+
backupSpinner.succeed(chalk.green(`✓ Backup created: ${backupDir}`));
|
|
1196
|
+
} catch (error) {
|
|
1197
|
+
backupSpinner.warn(chalk.yellow('Could not create backup, continuing anyway...'));
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
// Run migration
|
|
1202
|
+
let report;
|
|
1203
|
+
|
|
1204
|
+
switch (from.toLowerCase()) {
|
|
1205
|
+
case 'tailwind':
|
|
1206
|
+
report = await migrateTailwind(sourcePath, options);
|
|
1207
|
+
break;
|
|
1208
|
+
|
|
1209
|
+
case 'bootstrap':
|
|
1210
|
+
report = await migrateBootstrap(sourcePath, options);
|
|
1211
|
+
break;
|
|
1212
|
+
|
|
1213
|
+
case 'scss-variables':
|
|
1214
|
+
report = await migrateSCSSVariables(sourcePath, options);
|
|
1215
|
+
break;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
// Display report
|
|
1219
|
+
displayMigrationReport(report);
|
|
1220
|
+
|
|
1221
|
+
// Next steps
|
|
1222
|
+
if (!options.dryRun && report.filesProcessed > 0) {
|
|
1223
|
+
console.log(chalk.cyan('\n📝 Next Steps:'));
|
|
1224
|
+
console.log(chalk.gray(' 1. Review the changes in your code'));
|
|
1225
|
+
console.log(chalk.gray(' 2. Install Atomix: npm install @shohojdhara/atomix'));
|
|
1226
|
+
console.log(chalk.gray(' 3. Import Atomix styles: import "@shohojdhara/atomix/css"'));
|
|
1227
|
+
console.log(chalk.gray(' 4. Test your application thoroughly'));
|
|
1228
|
+
console.log(chalk.gray(' 5. Customize with your theme: atomix create-theme custom'));
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
} catch (error) {
|
|
1232
|
+
handleError(error, spinner);
|
|
1233
|
+
}
|
|
1234
|
+
});
|
|
1235
|
+
|
|
1236
|
+
/**
|
|
1237
|
+
* Init Command - NEW (Interactive Setup Wizard)
|
|
1238
|
+
*/
|
|
1239
|
+
program
|
|
1240
|
+
.command('init')
|
|
1241
|
+
.description('Interactive setup wizard for Atomix design system')
|
|
1242
|
+
.option('--skip-install', 'Skip dependency installation', false)
|
|
1243
|
+
.action(async (options) => {
|
|
1244
|
+
try {
|
|
1245
|
+
// Set environment variable for skip install if needed
|
|
1246
|
+
if (options.skipInstall) {
|
|
1247
|
+
process.env.ATOMIX_SKIP_INSTALL = 'true';
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
// Run the interactive wizard
|
|
1251
|
+
await runInitWizard();
|
|
1252
|
+
} catch (error) {
|
|
1253
|
+
handleError(error);
|
|
1254
|
+
}
|
|
1255
|
+
});
|
|
1256
|
+
|
|
1257
|
+
/**
|
|
1258
|
+
* Tokens Command - NEW (Design Token Management)
|
|
1259
|
+
*/
|
|
1260
|
+
program
|
|
1261
|
+
.command('tokens <action>')
|
|
1262
|
+
.description('Manage design tokens (list, validate, export, import)')
|
|
1263
|
+
.option('-c, --category <category>', 'Token category (colors, typography, spacing, etc.)')
|
|
1264
|
+
.option('-f, --format <format>', 'Export format (json, css, scss, js, ts)', 'json')
|
|
1265
|
+
.option('-o, --output <path>', 'Output file path')
|
|
1266
|
+
.option('--dry-run', 'Preview changes without modifying files', false)
|
|
1267
|
+
.action(async (action, options) => {
|
|
1268
|
+
try {
|
|
1269
|
+
debug(`Token action: ${action}`, options);
|
|
1270
|
+
|
|
1271
|
+
switch (action.toLowerCase()) {
|
|
1272
|
+
case 'list':
|
|
1273
|
+
case 'ls':
|
|
1274
|
+
await listTokens(options.category);
|
|
1275
|
+
break;
|
|
1276
|
+
|
|
1277
|
+
case 'validate':
|
|
1278
|
+
case 'check':
|
|
1279
|
+
const validationResult = await validateTokens(options);
|
|
1280
|
+
if (validationResult.issues.length > 0) {
|
|
1281
|
+
process.exit(1); // Exit with error if issues found
|
|
1282
|
+
}
|
|
1283
|
+
break;
|
|
1284
|
+
|
|
1285
|
+
case 'export':
|
|
1286
|
+
if (!options.format) {
|
|
1287
|
+
throw new AtomixCLIError(
|
|
1288
|
+
'Export format is required',
|
|
1289
|
+
'MISSING_FORMAT',
|
|
1290
|
+
[
|
|
1291
|
+
'Specify format with --format flag',
|
|
1292
|
+
'Valid formats: json, css, scss, js, ts',
|
|
1293
|
+
'Example: atomix tokens export --format json'
|
|
1294
|
+
]
|
|
1295
|
+
);
|
|
1296
|
+
}
|
|
1297
|
+
await exportTokens(options.format, options.output);
|
|
1298
|
+
break;
|
|
1299
|
+
|
|
1300
|
+
case 'import':
|
|
1301
|
+
if (!options.output) {
|
|
1302
|
+
throw new AtomixCLIError(
|
|
1303
|
+
'Import file path is required',
|
|
1304
|
+
'MISSING_PATH',
|
|
1305
|
+
[
|
|
1306
|
+
'Specify file with --output flag',
|
|
1307
|
+
'Example: atomix tokens import --output tokens.json'
|
|
1308
|
+
]
|
|
1309
|
+
);
|
|
1310
|
+
}
|
|
1311
|
+
await importTokens(options.output, { dryRun: options.dryRun });
|
|
1312
|
+
break;
|
|
1313
|
+
|
|
1314
|
+
default:
|
|
1315
|
+
throw new AtomixCLIError(
|
|
1316
|
+
`Unknown token action: ${action}`,
|
|
1317
|
+
'UNKNOWN_ACTION',
|
|
1318
|
+
[
|
|
1319
|
+
'Valid actions: list, validate, export, import',
|
|
1320
|
+
'Example: atomix tokens list',
|
|
1321
|
+
'Example: atomix tokens export --format json'
|
|
1322
|
+
]
|
|
1323
|
+
);
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
} catch (error) {
|
|
1327
|
+
handleError(error);
|
|
1328
|
+
}
|
|
1329
|
+
});
|
|
1330
|
+
|
|
1331
|
+
/**
|
|
1332
|
+
* Doctor Command - NEW
|
|
1333
|
+
*/
|
|
1334
|
+
program
|
|
1335
|
+
.command('doctor')
|
|
1336
|
+
.description('Diagnose common issues with your Atomix setup')
|
|
1337
|
+
.action(async () => {
|
|
1338
|
+
const spinner = ora('Running diagnostics...').start();
|
|
1339
|
+
|
|
1340
|
+
try {
|
|
1341
|
+
const checks = [];
|
|
1342
|
+
|
|
1343
|
+
// Check Node version
|
|
1344
|
+
const nodeVersion = process.version;
|
|
1345
|
+
const majorVersion = parseInt(nodeVersion.slice(1).split('.')[0]);
|
|
1346
|
+
checks.push({
|
|
1347
|
+
name: 'Node.js Version',
|
|
1348
|
+
status: majorVersion >= 16 ? '✅' : '❌',
|
|
1349
|
+
message: majorVersion >= 16
|
|
1350
|
+
? `${nodeVersion} (supported)`
|
|
1351
|
+
: `${nodeVersion} (requires Node 16+)`,
|
|
1352
|
+
});
|
|
1353
|
+
|
|
1354
|
+
// Check Atomix installation
|
|
1355
|
+
const atomixPath = join(process.cwd(), 'node_modules', '@shohojdhara', 'atomix');
|
|
1356
|
+
checks.push({
|
|
1357
|
+
name: 'Atomix Installation',
|
|
1358
|
+
status: existsSync(atomixPath) ? '✅' : '❌',
|
|
1359
|
+
message: existsSync(atomixPath)
|
|
1360
|
+
? 'Installed correctly'
|
|
1361
|
+
: 'Not found - run: npm install @shohojdhara/atomix',
|
|
1362
|
+
});
|
|
1363
|
+
|
|
1364
|
+
// Check for required dependencies
|
|
1365
|
+
const requiredDeps = ['react', 'react-dom', 'sass'];
|
|
1366
|
+
for (const dep of requiredDeps) {
|
|
1367
|
+
const depPath = join(process.cwd(), 'node_modules', dep);
|
|
1368
|
+
checks.push({
|
|
1369
|
+
name: `Dependency: ${dep}`,
|
|
1370
|
+
status: existsSync(depPath) ? '✅' : '⚠️',
|
|
1371
|
+
message: existsSync(depPath)
|
|
1372
|
+
? 'Installed'
|
|
1373
|
+
: 'Missing (may be required for some features)',
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
// Check for configuration files
|
|
1378
|
+
const configFiles = ['.atomixrc', 'atomix.config.js', 'atomix.config.json'];
|
|
1379
|
+
let hasConfig = false;
|
|
1380
|
+
for (const file of configFiles) {
|
|
1381
|
+
if (existsSync(join(process.cwd(), file))) {
|
|
1382
|
+
hasConfig = true;
|
|
1383
|
+
break;
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
checks.push({
|
|
1388
|
+
name: 'Configuration File',
|
|
1389
|
+
status: hasConfig ? '✅' : '💡',
|
|
1390
|
+
message: hasConfig
|
|
1391
|
+
? 'Configuration found'
|
|
1392
|
+
: 'No config file (using defaults)',
|
|
1393
|
+
});
|
|
1394
|
+
|
|
1395
|
+
spinner.stop();
|
|
1396
|
+
|
|
1397
|
+
// Display results
|
|
1398
|
+
console.log(chalk.bold('\n🏥 Atomix Doctor Report\n'));
|
|
1399
|
+
console.log(chalk.gray('=' .repeat(50)));
|
|
1400
|
+
|
|
1401
|
+
checks.forEach(check => {
|
|
1402
|
+
console.log(`${check.status} ${chalk.bold(check.name)}`);
|
|
1403
|
+
console.log(` ${chalk.gray(check.message)}\n`);
|
|
1404
|
+
});
|
|
1405
|
+
|
|
1406
|
+
const hasIssues = checks.some(c => c.status === '❌');
|
|
1407
|
+
const hasWarnings = checks.some(c => c.status === '⚠️');
|
|
1408
|
+
|
|
1409
|
+
if (hasIssues) {
|
|
1410
|
+
console.log(chalk.red('\n❌ Some issues need attention'));
|
|
1411
|
+
} else if (hasWarnings) {
|
|
1412
|
+
console.log(chalk.yellow('\n⚠️ Some optional improvements available'));
|
|
1413
|
+
} else {
|
|
1414
|
+
console.log(chalk.green('\n✅ Everything looks good!'));
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
} catch (error) {
|
|
1418
|
+
handleError(error, spinner);
|
|
1419
|
+
}
|
|
1420
|
+
});
|
|
1421
|
+
|
|
1422
|
+
// Parse arguments
|
|
1423
|
+
program.parse(process.argv);
|
|
1424
|
+
|
|
1425
|
+
// Show help if no command provided
|
|
1426
|
+
if (!process.argv.slice(2).length) {
|
|
1427
|
+
program.outputHelp();
|
|
1428
|
+
}
|