@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.
Files changed (343) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/build-tools/EXAMPLES.md +372 -0
  3. package/build-tools/README.md +242 -0
  4. package/build-tools/__tests__/error-handler.test.js +230 -0
  5. package/build-tools/__tests__/index.test.js +141 -0
  6. package/build-tools/__tests__/rollup-plugin.test.js +194 -0
  7. package/build-tools/__tests__/utils.test.js +161 -0
  8. package/build-tools/__tests__/vite-plugin.test.js +129 -0
  9. package/build-tools/__tests__/webpack-loader.test.js +190 -0
  10. package/build-tools/error-handler.js +308 -0
  11. package/build-tools/index.d.ts +44 -0
  12. package/build-tools/index.js +88 -0
  13. package/build-tools/package.json +50 -0
  14. package/build-tools/rollup-plugin.js +236 -0
  15. package/build-tools/types.d.ts +163 -0
  16. package/build-tools/utils.js +203 -0
  17. package/build-tools/vite-plugin.js +161 -0
  18. package/build-tools/webpack-loader.js +123 -0
  19. package/dist/atomix.css +21044 -2618
  20. package/dist/atomix.css.map +1 -1
  21. package/dist/atomix.min.css +77 -3
  22. package/dist/atomix.min.css.map +1 -1
  23. package/dist/build-tools/EXAMPLES.md +372 -0
  24. package/dist/build-tools/README.md +242 -0
  25. package/dist/build-tools/__tests__/error-handler.test.js +230 -0
  26. package/dist/build-tools/__tests__/index.test.js +141 -0
  27. package/dist/build-tools/__tests__/rollup-plugin.test.js +194 -0
  28. package/dist/build-tools/__tests__/utils.test.js +161 -0
  29. package/dist/build-tools/__tests__/vite-plugin.test.js +129 -0
  30. package/dist/build-tools/__tests__/webpack-loader.test.js +190 -0
  31. package/dist/build-tools/error-handler.js +308 -0
  32. package/dist/build-tools/index.d.ts +44 -0
  33. package/dist/build-tools/index.js +88 -0
  34. package/dist/build-tools/package.json +50 -0
  35. package/dist/build-tools/rollup-plugin.js +236 -0
  36. package/dist/build-tools/types.d.ts +163 -0
  37. package/dist/build-tools/utils.js +203 -0
  38. package/dist/build-tools/vite-plugin.js +161 -0
  39. package/dist/build-tools/webpack-loader.js +123 -0
  40. package/dist/charts.d.ts +1 -1
  41. package/dist/charts.js +86 -57
  42. package/dist/charts.js.map +1 -1
  43. package/dist/core.d.ts +1 -1
  44. package/dist/core.js +136 -112
  45. package/dist/core.js.map +1 -1
  46. package/dist/forms.d.ts +2 -5
  47. package/dist/forms.js +140 -128
  48. package/dist/forms.js.map +1 -1
  49. package/dist/heavy.d.ts +1 -1
  50. package/dist/heavy.js +136 -112
  51. package/dist/heavy.js.map +1 -1
  52. package/dist/index.d.ts +152 -78
  53. package/dist/index.esm.js +346 -340
  54. package/dist/index.esm.js.map +1 -1
  55. package/dist/index.js +359 -353
  56. package/dist/index.js.map +1 -1
  57. package/dist/index.min.js +1 -1
  58. package/dist/index.min.js.map +1 -1
  59. package/dist/layout.js.map +1 -1
  60. package/dist/theme.d.ts +9 -9
  61. package/dist/theme.js.map +1 -1
  62. package/package.json +23 -8
  63. package/scripts/atomix-cli.js +170 -73
  64. package/scripts/cli/__tests__/README.md +81 -0
  65. package/scripts/cli/__tests__/basic.test.js +115 -0
  66. package/scripts/cli/__tests__/component-generator.test.js +332 -0
  67. package/scripts/cli/__tests__/integration.test.js +327 -0
  68. package/scripts/cli/__tests__/test-setup.js +133 -0
  69. package/scripts/cli/__tests__/token-manager.test.js +251 -0
  70. package/scripts/cli/__tests__/utils.test.js +161 -0
  71. package/scripts/cli/component-generator.js +253 -299
  72. package/scripts/cli/dependency-checker.js +355 -0
  73. package/scripts/cli/interactive-init.js +46 -5
  74. package/scripts/cli/template-manager.js +0 -2
  75. package/scripts/cli/templates/common-templates.js +636 -0
  76. package/scripts/cli/templates/composable-templates.js +148 -126
  77. package/scripts/cli/templates/index.js +23 -16
  78. package/scripts/cli/templates/project-templates.js +151 -23
  79. package/scripts/cli/templates/react-templates.js +280 -210
  80. package/scripts/cli/templates/scss-templates.js +90 -91
  81. package/scripts/cli/templates/testing-templates.js +206 -27
  82. package/scripts/cli/templates/testing-utils.js +278 -0
  83. package/scripts/cli/templates/types-templates.js +70 -56
  84. package/scripts/cli/theme-bridge.js +8 -2
  85. package/scripts/cli/token-manager.js +318 -206
  86. package/scripts/cli/utils.js +0 -1
  87. package/src/components/Accordion/Accordion.stories.tsx +358 -850
  88. package/src/components/Accordion/Accordion.test.tsx +70 -50
  89. package/src/components/Accordion/Accordion.tsx +99 -94
  90. package/src/components/AtomixGlass/AtomixGlass.test.tsx +1 -1
  91. package/src/components/AtomixGlass/AtomixGlass.tsx +80 -39
  92. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +103 -81
  93. package/src/components/AtomixGlass/GlassFilter.tsx +9 -16
  94. package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +8 -7
  95. package/src/components/AtomixGlass/glass-utils.ts +6 -5
  96. package/src/components/AtomixGlass/shader-utils.ts +133 -52
  97. package/src/components/AtomixGlass/stories/Customization.stories.tsx +131 -0
  98. package/src/components/AtomixGlass/stories/Examples.stories.tsx +2957 -2853
  99. package/src/components/AtomixGlass/stories/Modes.stories.tsx +1 -1
  100. package/src/components/AtomixGlass/stories/Overview.stories.tsx +348 -0
  101. package/src/components/AtomixGlass/stories/Performance.stories.tsx +103 -0
  102. package/src/components/AtomixGlass/stories/Playground.stories.tsx +51 -36
  103. package/src/components/AtomixGlass/stories/{ShaderVariants.stories.tsx → Shaders.stories.tsx} +2 -2
  104. package/src/components/AtomixGlass/stories/shared-components.tsx +90 -190
  105. package/src/components/Avatar/Avatar.stories.tsx +195 -0
  106. package/src/components/Avatar/Avatar.tsx +58 -56
  107. package/src/components/Badge/Badge.stories.tsx +122 -352
  108. package/src/components/Badge/Badge.test.tsx +41 -41
  109. package/src/components/Badge/Badge.tsx +64 -62
  110. package/src/components/Block/Block.stories.tsx +30 -11
  111. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +142 -23
  112. package/src/components/Breadcrumb/Breadcrumb.tsx +62 -60
  113. package/src/components/Button/Button.stories.tsx +454 -1126
  114. package/src/components/Button/Button.test.tsx +123 -0
  115. package/src/components/Button/Button.tsx +88 -60
  116. package/src/components/Button/ButtonGroup.stories.tsx +376 -215
  117. package/src/components/Button/ButtonGroup.tsx +4 -15
  118. package/src/components/Callout/Callout.stories.tsx +316 -568
  119. package/src/components/Card/Card.stories.tsx +292 -81
  120. package/src/components/Card/Card.tsx +30 -14
  121. package/src/components/Chart/AreaChart.tsx +1 -1
  122. package/src/components/Chart/CandlestickChart.tsx +23 -16
  123. package/src/components/Chart/Chart.stories.tsx +153 -16
  124. package/src/components/Chart/Chart.tsx +40 -44
  125. package/src/components/Chart/ChartRenderer.tsx +39 -12
  126. package/src/components/Chart/ChartToolbar.tsx +21 -5
  127. package/src/components/Chart/DonutChart.tsx +1 -1
  128. package/src/components/Chart/FunnelChart.tsx +4 -1
  129. package/src/components/Chart/GaugeChart.tsx +3 -1
  130. package/src/components/Chart/HeatmapChart.tsx +50 -37
  131. package/src/components/Chart/LineChart.tsx +3 -2
  132. package/src/components/Chart/MultiAxisChart.tsx +24 -16
  133. package/src/components/Chart/RadarChart.tsx +19 -17
  134. package/src/components/Chart/ScatterChart.tsx +29 -21
  135. package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +152 -66
  136. package/src/components/ColorModeToggle/ColorModeToggle.tsx +15 -3
  137. package/src/components/Countdown/Countdown.stories.tsx +114 -7
  138. package/src/components/DataTable/DataTable.stories.tsx +349 -144
  139. package/src/components/DataTable/DataTable.test.tsx +26 -148
  140. package/src/components/DataTable/DataTable.tsx +485 -456
  141. package/src/components/DatePicker/DatePicker.stories.tsx +310 -1066
  142. package/src/components/DatePicker/DatePicker.tsx +31 -26
  143. package/src/components/Dropdown/Dropdown.stories.tsx +153 -36
  144. package/src/components/Dropdown/Dropdown.tsx +313 -299
  145. package/src/components/EdgePanel/EdgePanel.stories.tsx +221 -25
  146. package/src/components/EdgePanel/EdgePanel.tsx +1 -3
  147. package/src/components/Footer/Footer.stories.tsx +396 -327
  148. package/src/components/Footer/Footer.tsx +130 -128
  149. package/src/components/Footer/FooterLink.tsx +2 -2
  150. package/src/components/Form/Checkbox.stories.tsx +140 -6
  151. package/src/components/Form/Checkbox.test.tsx +63 -0
  152. package/src/components/Form/Checkbox.tsx +122 -78
  153. package/src/components/Form/Form.stories.tsx +110 -19
  154. package/src/components/Form/FormGroup.stories.tsx +127 -4
  155. package/src/components/Form/Input.stories.tsx +22 -39
  156. package/src/components/Form/Input.test.tsx +38 -44
  157. package/src/components/Form/Radio.stories.tsx +146 -17
  158. package/src/components/Form/Radio.tsx +68 -66
  159. package/src/components/Form/Select.stories.tsx +140 -8
  160. package/src/components/Form/Select.tsx +184 -182
  161. package/src/components/Form/Textarea.stories.tsx +149 -6
  162. package/src/components/Form/Textarea.test.tsx +27 -32
  163. package/src/components/Hero/Hero.stories.tsx +372 -38
  164. package/src/components/Hero/Hero.tsx +201 -55
  165. package/src/components/Icon/index.ts +7 -1
  166. package/src/components/List/List.stories.tsx +141 -3
  167. package/src/components/List/List.tsx +19 -23
  168. package/src/components/Modal/Modal.stories.tsx +183 -43
  169. package/src/components/Modal/Modal.tsx +130 -127
  170. package/src/components/Navigation/Menu/MegaMenu.tsx +70 -70
  171. package/src/components/Navigation/Nav/NavDropdown.tsx +1 -5
  172. package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +128 -28
  173. package/src/components/Navigation/SideMenu/SideMenu.tsx +5 -7
  174. package/src/components/Navigation/SideMenu/SideMenuItem.tsx +4 -5
  175. package/src/components/Pagination/Pagination.stories.tsx +7 -4
  176. package/src/components/Pagination/Pagination.tsx +199 -202
  177. package/src/components/PhotoViewer/PhotoViewer.tsx +4 -1
  178. package/src/components/Popover/Popover.stories.tsx +354 -97
  179. package/src/components/Popover/Popover.tsx +41 -37
  180. package/src/components/Progress/Progress.stories.tsx +160 -7
  181. package/src/components/River/River.stories.tsx +3 -2
  182. package/src/components/SectionIntro/SectionIntro.stories.tsx +239 -47
  183. package/src/components/Slider/Slider.stories.tsx +12 -4
  184. package/src/components/Spinner/Spinner.stories.tsx +104 -8
  185. package/src/components/Spinner/Spinner.test.tsx +23 -23
  186. package/src/components/Spinner/Spinner.tsx +43 -46
  187. package/src/components/Steps/Steps.stories.tsx +173 -42
  188. package/src/components/Tabs/Tabs.stories.tsx +141 -12
  189. package/src/components/Tabs/Tabs.tsx +74 -72
  190. package/src/components/Testimonial/Testimonial.stories.tsx +120 -3
  191. package/src/components/Todo/Todo.stories.tsx +198 -9
  192. package/src/components/Toggle/Toggle.stories.tsx +137 -36
  193. package/src/components/Toggle/Toggle.test.tsx +65 -70
  194. package/src/components/Toggle/Toggle.tsx +4 -1
  195. package/src/components/Tooltip/Tooltip.stories.tsx +194 -100
  196. package/src/components/Tooltip/Tooltip.tsx +104 -106
  197. package/src/components/Upload/Upload.stories.tsx +241 -150
  198. package/src/components/Upload/Upload.tsx +287 -283
  199. package/src/components/VideoPlayer/VideoPlayer.tsx +6 -1
  200. package/src/components/index.ts +13 -2
  201. package/src/layouts/Grid/Grid.stories.tsx +9 -3
  202. package/src/layouts/MasonryGrid/MasonryGrid.tsx +5 -1
  203. package/src/lib/README.md +2 -2
  204. package/src/lib/__tests__/theme-tools.test.ts +219 -0
  205. package/src/lib/composables/index.ts +2 -2
  206. package/src/lib/composables/shared-mouse-tracker.ts +13 -14
  207. package/src/lib/composables/useAtomixGlass.ts +126 -97
  208. package/src/lib/composables/useChartExport.ts +3 -8
  209. package/src/lib/composables/useDataTable.ts +72 -43
  210. package/src/lib/composables/useHero.ts +58 -14
  211. package/src/lib/composables/useHeroBackgroundSlider.ts +2 -9
  212. package/src/lib/composables/useInput.ts +10 -8
  213. package/src/lib/composables/useSideMenu.ts +6 -5
  214. package/src/lib/composables/useTooltip.ts +1 -2
  215. package/src/lib/composables/useVideoPlayer.ts +44 -35
  216. package/src/lib/config/index.ts +154 -154
  217. package/src/lib/constants/components.ts +9 -32
  218. package/src/lib/constants/cssVariables.ts +29 -29
  219. package/src/lib/hooks/__tests__/useComponentCustomization.test.ts +2 -6
  220. package/src/lib/hooks/index.ts +1 -1
  221. package/src/lib/hooks/useComponentCustomization.ts +11 -17
  222. package/src/lib/hooks/usePerformanceMonitor.ts +6 -7
  223. package/src/lib/patterns/__tests__/slots.test.ts +1 -1
  224. package/src/lib/patterns/index.ts +1 -1
  225. package/src/lib/patterns/slots.tsx +8 -13
  226. package/src/lib/storybook/InteractiveDemo.tsx +13 -18
  227. package/src/lib/storybook/PreviewContainer.tsx +1 -1
  228. package/src/lib/storybook/VariantsGrid.tsx +3 -7
  229. package/src/lib/storybook/index.ts +1 -1
  230. package/src/lib/theme/adapters/cssVariableMapper.ts +47 -74
  231. package/src/lib/theme/adapters/index.ts +3 -9
  232. package/src/lib/theme/adapters/themeAdapter.ts +41 -26
  233. package/src/lib/theme/config/index.ts +1 -1
  234. package/src/lib/theme/config/types.ts +2 -2
  235. package/src/lib/theme/config/validator.ts +10 -5
  236. package/src/lib/theme/constants/constants.ts +2 -2
  237. package/src/lib/theme/constants/index.ts +1 -2
  238. package/src/lib/theme/core/__tests__/createTheme.test.ts +20 -22
  239. package/src/lib/theme/core/composeTheme.ts +32 -26
  240. package/src/lib/theme/core/createTheme.ts +1 -1
  241. package/src/lib/theme/core/createThemeObject.ts +308 -301
  242. package/src/lib/theme/core/index.ts +3 -3
  243. package/src/lib/theme/devtools/CLI.ts +107 -105
  244. package/src/lib/theme/devtools/Comparator.tsx +50 -32
  245. package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +50 -48
  246. package/src/lib/theme/devtools/DesignTokensCustomizer.tsx +257 -63
  247. package/src/lib/theme/devtools/Inspector.tsx +75 -60
  248. package/src/lib/theme/devtools/LiveEditor.tsx +97 -76
  249. package/src/lib/theme/devtools/Preview.tsx +150 -106
  250. package/src/lib/theme/devtools/ThemeValidator.ts +29 -21
  251. package/src/lib/theme/devtools/index.ts +3 -9
  252. package/src/lib/theme/devtools/useHistory.ts +23 -21
  253. package/src/lib/theme/errors/errors.ts +12 -11
  254. package/src/lib/theme/errors/index.ts +2 -7
  255. package/src/lib/theme/generators/generateCSS.ts +9 -13
  256. package/src/lib/theme/generators/generateCSSNested.ts +1 -6
  257. package/src/lib/theme/generators/generateCSSVariables.ts +673 -630
  258. package/src/lib/theme/generators/index.ts +1 -4
  259. package/src/lib/theme/i18n/index.ts +1 -1
  260. package/src/lib/theme/i18n/rtl.ts +13 -13
  261. package/src/lib/theme/index.ts +7 -16
  262. package/src/lib/theme/runtime/ThemeApplicator.ts +4 -4
  263. package/src/lib/theme/runtime/ThemeContext.tsx +1 -1
  264. package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +19 -23
  265. package/src/lib/theme/runtime/ThemeProvider.tsx +230 -239
  266. package/src/lib/theme/runtime/__tests__/ThemeProvider.integration.test.tsx +1 -1
  267. package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +24 -29
  268. package/src/lib/theme/runtime/index.ts +2 -5
  269. package/src/lib/theme/runtime/useTheme.ts +18 -18
  270. package/src/lib/theme/runtime/useThemeTokens.ts +22 -22
  271. package/src/lib/theme/test/testTheme.ts +15 -16
  272. package/src/lib/theme/tokens/index.ts +2 -7
  273. package/src/lib/theme/tokens/tokens.ts +25 -24
  274. package/src/lib/theme/types.ts +428 -411
  275. package/src/lib/theme/utils/__tests__/themeValidation.test.ts +3 -3
  276. package/src/lib/theme/utils/componentTheming.ts +18 -18
  277. package/src/lib/theme/utils/domUtils.ts +277 -289
  278. package/src/lib/theme/utils/index.ts +1 -2
  279. package/src/lib/theme/utils/injectCSS.ts +10 -14
  280. package/src/lib/theme/utils/naming.ts +20 -16
  281. package/src/lib/theme/utils/themeHelpers.ts +10 -12
  282. package/src/lib/theme/utils/themeUtils.ts +85 -86
  283. package/src/lib/theme/utils/themeValidation.ts +82 -33
  284. package/src/lib/theme-tools.ts +8 -6
  285. package/src/lib/types/components.ts +172 -71
  286. package/src/lib/types/partProps.ts +1 -1
  287. package/src/lib/utils/__tests__/csv.test.ts +45 -0
  288. package/src/lib/utils/componentUtils.ts +8 -12
  289. package/src/lib/utils/csv.ts +19 -0
  290. package/src/lib/utils/dataTableExport.ts +2 -15
  291. package/src/lib/utils/fontPreloader.ts +10 -19
  292. package/src/lib/utils/icons.ts +4 -1
  293. package/src/lib/utils/index.ts +2 -6
  294. package/src/lib/utils/memoryMonitor.ts +10 -8
  295. package/src/lib/utils/themeNaming.ts +2 -2
  296. package/src/styles/01-settings/_index.scss +1 -1
  297. package/src/styles/01-settings/_settings.accordion.scss +28 -7
  298. package/src/styles/01-settings/_settings.colors.scss +11 -11
  299. package/src/styles/01-settings/_settings.design-tokens.scss +61 -50
  300. package/src/styles/01-settings/_settings.navbar.scss +1 -1
  301. package/src/styles/01-settings/_settings.spacing.scss +3 -4
  302. package/src/styles/01-settings/_settings.tooltip.scss +1 -1
  303. package/src/styles/01-settings/_settings.typography.scss +4 -4
  304. package/src/styles/02-tools/_tools.button.scss +51 -21
  305. package/src/styles/02-tools/_tools.utility-api.scss +38 -12
  306. package/src/styles/03-generic/_generic.root.scss +4 -3
  307. package/src/styles/06-components/_components.accordion.scss +56 -14
  308. package/src/styles/06-components/_components.atomix-glass.scss +13 -9
  309. package/src/styles/06-components/_components.button.scss +16 -4
  310. package/src/styles/06-components/_components.callout.scss +27 -21
  311. package/src/styles/06-components/_components.card.scss +5 -14
  312. package/src/styles/06-components/_components.chart.scss +22 -19
  313. package/src/styles/06-components/_components.checkbox.scss +25 -17
  314. package/src/styles/06-components/_components.color-mode-toggle.scss +3 -1
  315. package/src/styles/06-components/_components.edge-panel.scss +9 -2
  316. package/src/styles/06-components/_components.footer.scss +1 -1
  317. package/src/styles/06-components/_components.side-menu.scss +5 -5
  318. package/src/styles/06-components/_components.toggle.scss +18 -0
  319. package/src/styles/06-components/_index.scss +1 -1
  320. package/src/styles/06-components/old.chart.styles.scss +0 -2
  321. package/src/styles/99-utilities/_index.scss +2 -0
  322. package/src/styles/99-utilities/_utilities.border.scss +69 -27
  323. package/src/styles/99-utilities/_utilities.display.scss +1 -1
  324. package/src/styles/99-utilities/_utilities.opacity.scss +10 -0
  325. package/src/styles/99-utilities/_utilities.position.scss +16 -9
  326. package/src/styles/99-utilities/_utilities.scss +2 -0
  327. package/src/styles/99-utilities/_utilities.sizes.scss +47 -18
  328. package/src/styles/99-utilities/_utilities.spacing.scss +118 -66
  329. package/src/styles/99-utilities/_utilities.text-gradient.scss +45 -0
  330. package/src/styles/99-utilities/_utilities.text.scss +67 -46
  331. package/themes/dark-complementary/README.md +98 -0
  332. package/themes/dark-complementary/index.scss +158 -0
  333. package/themes/default-light/README.md +81 -0
  334. package/themes/default-light/index.scss +154 -0
  335. package/themes/high-contrast/README.md +105 -0
  336. package/themes/high-contrast/index.scss +172 -0
  337. package/themes/test-theme/README.md +38 -0
  338. package/themes/test-theme/index.scss +47 -0
  339. package/scripts/cli/templates-original-backup.js +0 -1655
  340. package/scripts/cli/templates_backup.js +0 -684
  341. package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +0 -1438
  342. package/src/lib/composables/useButton.ts +0 -93
  343. package/src/lib/composables/useCheckbox.ts +0 -70
@@ -2,49 +2,208 @@
2
2
  * Design Token Manager for Atomix Design System
3
3
  */
4
4
 
5
- import { readFile, writeFile, readdir } from 'fs/promises';
6
- import { join, basename } from 'path';
5
+ import { readFile, writeFile } from 'fs/promises';
6
+ import { resolve, basename } from 'path';
7
7
  import { existsSync } from 'fs';
8
8
  import chalk from 'chalk';
9
9
  import ora from 'ora';
10
10
  import boxen from 'boxen';
11
11
 
12
+ /**
13
+ * Utility function to safely call spinner methods
14
+ */
15
+ function safeSpinnerCall(spinner, method, ...args) {
16
+ if (typeof spinner[method] === 'function') {
17
+ return spinner[method](...args);
18
+ }
19
+ }
20
+
21
+ /**
22
+ * Utility function to safely call chalk methods
23
+ */
24
+ function safeChalkCall(chalkObj, methodChain, text) {
25
+ try {
26
+ // Split method chain like 'bold.cyan' into ['bold', 'cyan']
27
+ const methods = methodChain.split('.');
28
+ let result = chalkObj;
29
+
30
+ for (const method of methods) {
31
+ if (typeof result[method] === 'function') {
32
+ result = result[method];
33
+ } else {
34
+ // If any method in the chain doesn't exist, return the text as-is
35
+ return text;
36
+ }
37
+ }
38
+
39
+ return result(text);
40
+ } catch (e) {
41
+ // If anything goes wrong, return the text as-is
42
+ return text;
43
+ }
44
+ }
45
+
12
46
  /**
13
47
  * Token categories in the design system
14
48
  */
49
+ let projectRoot = '';
50
+
51
+ export function setProjectRoot(path) {
52
+ projectRoot = path;
53
+ }
54
+
15
55
  const tokenCategories = {
16
56
  colors: {
17
- path: 'src/styles/01-settings/_settings.colors.scss',
57
+ get path() { return resolve(projectRoot, 'src/styles/01-settings/_settings.colors.scss'); },
18
58
  prefix: '--atomix-color',
19
59
  description: 'Color palette tokens'
20
60
  },
21
61
  typography: {
22
- path: 'src/styles/01-settings/_settings.typography.scss',
62
+ get path() { return resolve(projectRoot, 'src/styles/01-settings/_settings.typography.scss'); },
23
63
  prefix: '--atomix-font',
24
64
  description: 'Typography scale tokens'
25
65
  },
26
66
  spacing: {
27
- path: 'src/styles/01-settings/_settings.spacing.scss',
67
+ get path() { return resolve(projectRoot, 'src/styles/01-settings/_settings.spacing.scss'); },
28
68
  prefix: '--atomix-space',
29
69
  description: 'Spacing scale tokens'
30
70
  },
31
71
  radius: {
32
- path: 'src/styles/01-settings/_settings.radius.scss',
72
+ get path() { return resolve(projectRoot, 'src/styles/01-settings/_settings.border-radius.scss'); },
33
73
  prefix: '--atomix-radius',
34
74
  description: 'Border radius tokens'
35
75
  },
36
76
  shadows: {
37
- path: 'src/styles/01-settings/_settings.shadows.scss',
77
+ get path() { return resolve(projectRoot, 'src/styles/01-settings/_settings.box-shadow.scss'); },
38
78
  prefix: '--atomix-shadow',
39
79
  description: 'Box shadow tokens'
40
80
  },
41
81
  breakpoints: {
42
- path: 'src/styles/01-settings/_settings.breakpoints.scss',
82
+ get path() { return resolve(projectRoot, 'src/styles/01-settings/_settings.breakpoints.scss'); },
43
83
  prefix: '--atomix-breakpoint',
44
84
  description: 'Responsive breakpoint tokens'
45
85
  }
46
86
  };
47
87
 
88
+ /**
89
+ * Parse tokens from content based on category
90
+ */
91
+ function parseTokens(content, category) {
92
+ const tokens = {};
93
+ let count = 0;
94
+
95
+ // Extract SCSS variables
96
+ const scssVarPattern = /\$([a-z0-9-]+):\s*(.+?);/gi;
97
+ let match;
98
+ while ((match = scssVarPattern.exec(content)) !== null) {
99
+ const name = `$${match[1]}`;
100
+ let value = match[2].trim();
101
+
102
+ // Check for !default flag in value
103
+ if (value.endsWith('!default')) {
104
+ value = value.replace(/\s*!default$/i, '').trim();
105
+ }
106
+
107
+ tokens[name] = value;
108
+ count++;
109
+ }
110
+
111
+ // Extract CSS custom properties
112
+ const cssVarPattern = /(--[a-z0-9-]+):\s*(.+?);/gi;
113
+ while ((match = cssVarPattern.exec(content)) !== null) {
114
+ const name = match[1];
115
+ const value = match[2].trim();
116
+ tokens[name] = value;
117
+ count++;
118
+ }
119
+
120
+ return {
121
+ tokens,
122
+ count,
123
+ description: tokenCategories[category]?.description || 'Unknown category',
124
+ path: tokenCategories[category]?.path || 'Unknown path'
125
+ };
126
+ }
127
+
128
+ /**
129
+ * Validate a token file for common issues
130
+ */
131
+ function validateTokenFile(content, category, filePath) {
132
+ const issues = [];
133
+ const warnings = [];
134
+ let count = 0;
135
+
136
+ // Special handling for breakpoints which uses a map structure
137
+ if (category === 'breakpoints') {
138
+ // Count map entries in breakpoints
139
+ const mapPattern = /\$[a-z0-9_-]+:\s*\(([\s\S]*?)\)/gi;
140
+ let match;
141
+ while ((match = mapPattern.exec(content)) !== null) {
142
+ // Count entries inside the map
143
+ const mapContent = match[1];
144
+ const entryMatches = mapContent.match(/[\w-]+:\s*[^,}]+/g);
145
+ count += entryMatches ? entryMatches.length : 0;
146
+ }
147
+
148
+ return { issues, warnings, count };
149
+ }
150
+
151
+ // Count tokens for non-breakpoint categories
152
+ const scssVarPattern = /\$([a-z0-9-]+):\s*(.+?);/gi;
153
+ let match;
154
+ while ((match = scssVarPattern.exec(content)) !== null) {
155
+ count++;
156
+
157
+ let value = match[2].trim();
158
+ let hasDefault = false;
159
+
160
+ // Check for !default flag in value
161
+ if (value.toLowerCase().endsWith('!default')) {
162
+ hasDefault = true;
163
+ value = value.replace(/\s*!default$/i, '').trim();
164
+ }
165
+
166
+ // Check for missing !default flag
167
+ if (!hasDefault) { // !default is not present
168
+ issues.push({
169
+ category: 'missing-default',
170
+ issue: `Missing !default flag for variable $${match[1]}`,
171
+ file: filePath,
172
+ fix: `Add !default to the variable: $${match[1]}: ${value} !default;`
173
+ });
174
+ }
175
+
176
+ // Check for hardcoded values that should be tokens
177
+ if (/#[0-9a-fA-F]{3,6}|rgb\(|rgba\(|hsl\(|hsla\(/.test(value)) {
178
+ warnings.push({
179
+ category: 'hardcoded-value',
180
+ issue: `Hardcoded color value detected in $${match[1]}`,
181
+ file: filePath,
182
+ values: [value],
183
+ fix: `Consider using a token instead of hardcoded value`
184
+ });
185
+ }
186
+ }
187
+
188
+ // Check for naming conventions
189
+ const namingPattern = /\$([a-z0-9-]+)/gi;
190
+ while ((match = namingPattern.exec(content)) !== null) {
191
+ const varName = match[1];
192
+
193
+ // Check if name contains uppercase letters
194
+ if (/[A-Z]/.test(varName)) {
195
+ issues.push({
196
+ category: 'naming-convention',
197
+ issue: `Variable name $${varName} contains uppercase letters`,
198
+ file: filePath,
199
+ fix: `Use lowercase and hyphens: $${varName.toLowerCase()}`
200
+ });
201
+ }
202
+ }
203
+
204
+ return { issues, warnings, count };
205
+ }
206
+
48
207
  /**
49
208
  * Extract tokens from SCSS file
50
209
  */
@@ -57,7 +216,7 @@ async function extractTokensFromFile(filePath) {
57
216
  const tokens = {};
58
217
 
59
218
  // Extract SCSS variables
60
- const scssVarPattern = /\$([a-z-]+):\s*([^;!]+)(?:\s*!default)?;/gi;
219
+ const scssVarPattern = /\$([a-z0-9-]+):\s*([^;!]+)(?:\s*!default)?;/gi;
61
220
  let match;
62
221
  while ((match = scssVarPattern.exec(content)) !== null) {
63
222
  tokens[`$${match[1]}`] = {
@@ -83,217 +242,167 @@ async function extractTokensFromFile(filePath) {
83
242
  }
84
243
 
85
244
  /**
86
- * List all design tokens
245
+ * Load all design tokens from SCSS files
87
246
  */
88
- export async function listTokens(category = null) {
89
- const spinner = ora('Loading design tokens...').start();
247
+ export async function listTokens(categories = Object.keys(tokenCategories)) {
248
+ const spinner = ora('Loading design tokens...');
249
+ safeSpinnerCall(spinner, 'start');
90
250
 
91
251
  try {
92
- const results = {};
93
-
94
- // Get tokens from specified category or all categories
95
- const categories = category
96
- ? [category]
97
- : Object.keys(tokenCategories);
252
+ const tokens = {};
253
+ let categoryCount = 0;
254
+ let tokenCount = 0;
98
255
 
99
256
  for (const cat of categories) {
100
257
  if (!tokenCategories[cat]) {
101
- spinner.warn(chalk.yellow(`Unknown category: ${cat}`));
258
+ safeSpinnerCall(spinner, 'warn', safeChalkCall(chalk, 'yellow', `Unknown category: ${cat}`));
102
259
  continue;
103
260
  }
104
261
 
105
- const { path, description } = tokenCategories[cat];
106
- const fullPath = join(process.cwd(), path);
107
- const tokens = await extractTokensFromFile(fullPath);
108
-
109
- if (tokens) {
110
- results[cat] = {
111
- description,
112
- path: path,
113
- tokens: tokens,
114
- count: Object.keys(tokens).length
115
- };
262
+ const fullPath = tokenCategories[cat].path;
263
+
264
+ if (!existsSync(fullPath)) {
265
+ continue;
116
266
  }
117
- }
118
-
119
- spinner.stop();
120
267
 
121
- // Display results
122
- if (Object.keys(results).length === 0) {
123
- console.log(chalk.yellow('\n⚠️ No design tokens found'));
124
- console.log(chalk.gray('Make sure you are in an Atomix project directory'));
125
- return;
268
+ const content = await readFile(fullPath, 'utf8');
269
+ const categoryTokens = parseTokens(content, cat);
270
+
271
+ if (Object.keys(categoryTokens).length > 0) {
272
+ tokens[cat] = categoryTokens;
273
+ categoryCount++;
274
+ tokenCount += Object.keys(categoryTokens).length;
275
+ }
126
276
  }
127
277
 
128
- console.log(chalk.bold.cyan('\n📐 Design Tokens\n'));
129
-
130
- for (const [category, data] of Object.entries(results)) {
131
- console.log(boxen(
132
- chalk.bold(category.toUpperCase()) + '\n' +
133
- chalk.gray(data.description) + '\n\n' +
134
- chalk.cyan(`Tokens: ${data.count}\n`) +
135
- chalk.gray(`File: ${data.path}`),
136
- {
137
- padding: 1,
138
- margin: { top: 0, bottom: 1, left: 0, right: 0 },
139
- borderStyle: 'round',
140
- borderColor: 'gray'
278
+ safeSpinnerCall(spinner, 'succeed', safeChalkCall(chalk, 'green', 'Tokens loaded successfully'));
279
+
280
+ // Show summary
281
+ if (categoryCount === 0) {
282
+ console.log(safeChalkCall(chalk, 'yellow', '\n⚠️ No design tokens found'));
283
+ console.log(safeChalkCall(chalk, 'gray', 'Make sure you are in an Atomix project directory'));
284
+ } else {
285
+ console.log(safeChalkCall(chalk, 'bold.cyan', '\n📐 Design Tokens\n'));
286
+
287
+ for (const [category, data] of Object.entries(tokens)) {
288
+ console.log(boxen(
289
+ safeChalkCall(chalk, 'bold', category.toUpperCase()) + '\n' +
290
+ safeChalkCall(chalk, 'gray', data.description) + '\n\n' +
291
+ safeChalkCall(chalk, 'cyan', `Tokens: ${data.count}\n`) +
292
+ safeChalkCall(chalk, 'gray', `File: ${data.path}`),
293
+ { padding: 1, borderColor: 'blue', borderStyle: 'round' }
294
+ ));
295
+
296
+ // Log first 5 tokens as examples
297
+ const tokenEntries = Object.entries(data.tokens).slice(0, 5);
298
+ for (const [name, value] of tokenEntries) {
299
+ console.log(` ${safeChalkCall(chalk, 'green', name)}: ${safeChalkCall(chalk, 'white', value)}`);
300
+ }
301
+
302
+ if (Object.keys(data.tokens).length > 5) {
303
+ console.log(safeChalkCall(chalk, 'gray', ` ... and ${Object.keys(data.tokens).length - 5} more\n`));
141
304
  }
142
- ));
143
-
144
- // Show first 5 tokens as examples
145
- const tokenEntries = Object.entries(data.tokens).slice(0, 5);
146
- tokenEntries.forEach(([name, info]) => {
147
- const value = info.value.length > 30
148
- ? info.value.substring(0, 30) + '...'
149
- : info.value;
150
- console.log(` ${chalk.green(name)}: ${chalk.white(value)}`);
151
- });
152
-
153
- if (Object.keys(data.tokens).length > 5) {
154
- console.log(chalk.gray(` ... and ${Object.keys(data.tokens).length - 5} more\n`));
155
- } else {
156
- console.log();
157
305
  }
158
306
  }
159
307
 
160
- return results;
308
+ return { tokens, categoryCount, tokenCount };
161
309
 
162
310
  } catch (error) {
163
- spinner.fail(chalk.red('Failed to load tokens'));
311
+ safeSpinnerCall(spinner, 'fail', safeChalkCall(chalk, 'red', 'Failed to load tokens'));
164
312
  throw error;
165
313
  }
166
314
  }
167
315
 
168
316
  /**
169
- * Validate design tokens
317
+ * Validate tokens according to design system standards
170
318
  */
171
- export async function validateTokens(options = {}) {
172
- const spinner = ora('Validating design tokens...').start();
319
+ export async function validateTokens(categories = Object.keys(tokenCategories), options = {}) {
320
+ const spinner = ora('Validating design tokens...');
321
+ safeSpinnerCall(spinner, 'start');
173
322
 
174
323
  try {
175
- const issues = [];
176
- const warnings = [];
324
+ let issues = [];
325
+ let warnings = [];
177
326
  let totalTokens = 0;
178
327
 
179
- for (const [category, config] of Object.entries(tokenCategories)) {
180
- const fullPath = join(process.cwd(), config.path);
181
-
182
- if (!existsSync(fullPath)) {
183
- issues.push({
184
- category,
185
- issue: 'Token file missing',
186
- file: config.path,
187
- fix: `Create file: ${config.path}`
188
- });
189
- continue;
190
- }
191
-
192
- const tokens = await extractTokensFromFile(fullPath);
193
- if (tokens) {
194
- totalTokens += Object.keys(tokens).length;
195
-
196
- // Check for hardcoded values
197
- const content = await readFile(fullPath, 'utf8');
198
-
199
- // Check for hardcoded colors
200
- if (category === 'colors') {
201
- const hardcodedColors = content.match(/#[0-9a-fA-F]{3,8}(?![0-9a-fA-F])/g);
202
- if (hardcodedColors) {
203
- const uniqueColors = [...new Set(hardcodedColors)];
204
- warnings.push({
205
- category,
206
- issue: `Found ${uniqueColors.length} hardcoded color values`,
207
- values: uniqueColors.slice(0, 3),
208
- fix: 'Use color tokens or CSS custom properties'
209
- });
210
- }
211
- }
212
-
213
- // Check for hardcoded pixel values
214
- if (category === 'spacing' || category === 'typography') {
215
- const hardcodedPixels = content.match(/\d+px/g);
216
- if (hardcodedPixels) {
217
- const uniquePixels = [...new Set(hardcodedPixels)];
218
- warnings.push({
219
- category,
220
- issue: `Found ${uniquePixels.length} hardcoded pixel values`,
221
- values: uniquePixels.slice(0, 3),
222
- fix: 'Use spacing tokens or rem units'
223
- });
224
- }
225
- }
328
+ for (const cat of categories) {
329
+ if (!tokenCategories[cat]) continue;
226
330
 
227
- // Check for missing !default flags
228
- const scssVars = content.match(/\$[a-z-]+:\s*[^;]+;/gi);
229
- const defaultFlags = content.match(/!default/g);
230
- if (scssVars && (!defaultFlags || defaultFlags.length < scssVars.length)) {
231
- warnings.push({
232
- category,
233
- issue: 'Some SCSS variables missing !default flag',
234
- fix: 'Add !default to allow theme overrides'
235
- });
236
- }
331
+ const fullPath = tokenCategories[cat].path;
332
+
333
+ if (!existsSync(fullPath)) continue;
237
334
 
238
- // Check naming conventions
239
- for (const [name, info] of Object.entries(tokens)) {
240
- if (info.type === 'css' && !name.startsWith(config.prefix)) {
241
- warnings.push({
242
- category,
243
- issue: `Token "${name}" doesn't follow naming convention`,
244
- fix: `Should start with "${config.prefix}"`
245
- });
246
- }
247
- }
248
- }
335
+ const content = await readFile(fullPath, 'utf8');
336
+ const { issues: catIssues, warnings: catWarnings, count: catCount } = validateTokenFile(content, cat, fullPath);
337
+
338
+ issues = [...issues, ...catIssues];
339
+ warnings = [...warnings, ...catWarnings];
340
+ totalTokens += catCount;
249
341
  }
250
342
 
251
- spinner.stop();
252
-
253
- // Display validation results
254
- console.log(chalk.bold.cyan('\n🔍 Token Validation Report\n'));
255
-
256
343
  if (issues.length === 0 && warnings.length === 0) {
257
- console.log(boxen(
258
- chalk.bold.green('✅ All tokens valid!\n\n') +
259
- chalk.gray(`Total tokens: ${totalTokens}\n`) +
260
- chalk.gray('All naming conventions followed\n') +
261
- chalk.gray('No hardcoded values found'),
262
- {
263
- padding: 1,
264
- borderStyle: 'round',
265
- borderColor: 'green'
266
- }
267
- ));
344
+ safeSpinnerCall(spinner, 'succeed', safeChalkCall(chalk, 'green', 'All tokens are valid!'));
345
+
346
+ console.log(safeChalkCall(chalk, 'bold.cyan', '\n🔍 Token Validation Report\n'));
347
+ console.log(
348
+ safeChalkCall(chalk, 'bold.green', '✅ All tokens valid!\n\n') +
349
+ safeChalkCall(chalk, 'gray', `Total tokens: ${totalTokens}\n`) +
350
+ safeChalkCall(chalk, 'gray', 'All naming conventions followed\n') +
351
+ safeChalkCall(chalk, 'gray', 'No hardcoded values found')
352
+ );
353
+
354
+ console.log(safeChalkCall(chalk, 'gray', '─'.repeat(50)));
355
+
356
+ return { isValid: true, issues: [], warnings: [] };
268
357
  } else {
358
+ const status = issues.length > 0 ? 'fail' : 'warn';
359
+ safeSpinnerCall(spinner, status, safeChalkCall(chalk, 'red', `Found ${issues.length} issues and ${warnings.length} warnings`));
360
+
361
+ console.log(safeChalkCall(chalk, 'bold.cyan', '\n🔍 Token Validation Report\n'));
362
+
269
363
  if (issues.length > 0) {
270
- console.log(chalk.bold.red(`❌ Issues (${issues.length}):\n`));
271
- issues.forEach((issue, i) => {
272
- console.log(chalk.red(` ${i + 1}. [${issue.category}] ${issue.issue}`));
273
- console.log(chalk.gray(` File: ${issue.file}`));
274
- console.log(chalk.yellow(` Fix: ${issue.fix}\n`));
275
- });
364
+ console.log(safeChalkCall(chalk, 'bold.red', `❌ Issues (${issues.length}):\n`));
365
+
366
+ for (let i = 0; i < Math.min(issues.length, 5); i++) {
367
+ const issue = issues[i];
368
+ console.log(safeChalkCall(chalk, 'red', ` ${i + 1}. [${issue.category}] ${issue.issue}`));
369
+ console.log(safeChalkCall(chalk, 'gray', ` File: ${issue.file}`));
370
+ console.log(safeChalkCall(chalk, 'yellow', ` Fix: ${issue.fix}\n`));
371
+ }
372
+
373
+ if (issues.length > 5) {
374
+ console.log(safeChalkCall(chalk, 'gray', `... and ${issues.length - 5} more\n`));
375
+ }
276
376
  }
277
-
377
+
278
378
  if (warnings.length > 0) {
279
- console.log(chalk.bold.yellow(`⚠️ Warnings (${warnings.length}):\n`));
280
- warnings.forEach((warning, i) => {
281
- console.log(chalk.yellow(` ${i + 1}. [${warning.category}] ${warning.issue}`));
282
- if (warning.values) {
283
- console.log(chalk.gray(` Examples: ${warning.values.join(', ')}`));
379
+ console.log(safeChalkCall(chalk, 'bold.yellow', `⚠️ Warnings (${warnings.length}):\n`));
380
+
381
+ for (let i = 0; i < Math.min(warnings.length, 5); i++) {
382
+ const warning = warnings[i];
383
+ console.log(safeChalkCall(chalk, 'yellow', ` ${i + 1}. [${warning.category}] ${warning.issue}`));
384
+ console.log(safeChalkCall(chalk, 'gray', ` File: ${warning.file}`));
385
+ if (warning.values && warning.values.length > 0) {
386
+ console.log(safeChalkCall(chalk, 'gray', ` Examples: ${warning.values.join(', ')}`));
284
387
  }
285
- console.log(chalk.cyan(` Fix: ${warning.fix}\n`));
286
- });
388
+ console.log(safeChalkCall(chalk, 'cyan', ` Fix: ${warning.fix}\n`));
389
+ }
390
+
391
+ if (warnings.length > 5) {
392
+ console.log(safeChalkCall(chalk, 'gray', `... and ${warnings.length - 5} more\n`));
393
+ }
287
394
  }
288
-
289
- console.log(chalk.gray('─'.repeat(50)));
290
- console.log(chalk.cyan('\n💡 Run with --fix to attempt automatic fixes'));
395
+
396
+ console.log(safeChalkCall(chalk, 'gray', '─'.repeat(50)));
397
+
398
+ if (options.fix) {
399
+ console.log(safeChalkCall(chalk, 'yellow', '\n💡 Run with --fix to automatically fix some issues'));
400
+ }
401
+
402
+ return { isValid: false, issues, warnings };
291
403
  }
292
-
293
- return { issues, warnings, totalTokens };
294
-
295
404
  } catch (error) {
296
- spinner.fail(chalk.red('Validation failed'));
405
+ safeSpinnerCall(spinner, 'fail', safeChalkCall(chalk, 'red', 'Validation failed'));
297
406
  throw error;
298
407
  }
299
408
  }
@@ -302,14 +411,15 @@ export async function validateTokens(options = {}) {
302
411
  * Export tokens to different formats
303
412
  */
304
413
  export async function exportTokens(format = 'json', outputPath = null) {
305
- const spinner = ora(`Exporting tokens as ${format.toUpperCase()}...`).start();
414
+ const spinner = ora(`Exporting tokens as ${format.toUpperCase()}...`);
415
+ safeSpinnerCall(spinner, 'start');
306
416
 
307
417
  try {
308
418
  const allTokens = {};
309
419
 
310
420
  // Collect all tokens
311
421
  for (const [category, config] of Object.entries(tokenCategories)) {
312
- const fullPath = join(process.cwd(), config.path);
422
+ const fullPath = config.path;
313
423
  const tokens = await extractTokensFromFile(fullPath);
314
424
 
315
425
  if (tokens) {
@@ -388,7 +498,7 @@ export async function exportTokens(format = 'json', outputPath = null) {
388
498
  const finalPath = outputPath || filename;
389
499
  await writeFile(finalPath, output, 'utf8');
390
500
 
391
- spinner.succeed(chalk.green(`✓ Exported tokens to ${finalPath}`));
501
+ safeSpinnerCall(spinner, 'succeed', safeChalkCall(chalk, 'green', `✓ Exported tokens to ${finalPath}`));
392
502
 
393
503
  // Show summary
394
504
  const categoryCount = Object.keys(allTokens).length;
@@ -397,14 +507,14 @@ export async function exportTokens(format = 'json', outputPath = null) {
397
507
  0
398
508
  );
399
509
 
400
- console.log(chalk.gray(`\n Categories: ${categoryCount}`));
401
- console.log(chalk.gray(` Total tokens: ${tokenCount}`));
402
- console.log(chalk.gray(` Format: ${format.toUpperCase()}`));
510
+ console.log(safeChalkCall(chalk, 'gray', `\n Categories: ${categoryCount}`));
511
+ console.log(safeChalkCall(chalk, 'gray', ` Total tokens: ${tokenCount}`));
512
+ console.log(safeChalkCall(chalk, 'gray', ` Format: ${format.toUpperCase()}`));
403
513
 
404
514
  return { path: finalPath, tokens: allTokens };
405
515
 
406
516
  } catch (error) {
407
- spinner.fail(chalk.red('Export failed'));
517
+ safeSpinnerCall(spinner, 'fail', safeChalkCall(chalk, 'red', 'Export failed'));
408
518
  throw error;
409
519
  }
410
520
  }
@@ -413,7 +523,8 @@ export async function exportTokens(format = 'json', outputPath = null) {
413
523
  * Import tokens from file
414
524
  */
415
525
  export async function importTokens(filePath, options = {}) {
416
- const spinner = ora('Importing design tokens...').start();
526
+ const spinner = ora('Importing design tokens...');
527
+ safeSpinnerCall(spinner, 'start');
417
528
 
418
529
  try {
419
530
  if (!existsSync(filePath)) {
@@ -472,17 +583,17 @@ export async function importTokens(filePath, options = {}) {
472
583
  throw new Error(`Unsupported file type: ${extension}`);
473
584
  }
474
585
 
475
- spinner.text = 'Updating token files...';
586
+ safeSpinnerCall(spinner, 'text', 'Updating token files...');
476
587
 
477
588
  // Update token files
478
589
  for (const [category, categoryTokens] of Object.entries(tokens)) {
479
590
  if (!tokenCategories[category]) {
480
- console.warn(chalk.yellow(`\n⚠️ Unknown category: ${category} (skipped)`));
591
+ console.warn(safeChalkCall(chalk, 'yellow', `\n⚠️ Unknown category: ${category} (skipped)`));
481
592
  continue;
482
593
  }
483
594
 
484
595
  const config = tokenCategories[category];
485
- const fullPath = join(process.cwd(), config.path);
596
+ const fullPath = config.path;
486
597
 
487
598
  // Generate SCSS content
488
599
  let scssContent = `// ${config.description}\n`;
@@ -501,15 +612,15 @@ export async function importTokens(filePath, options = {}) {
501
612
  }
502
613
 
503
614
  if (options.dryRun) {
504
- console.log(chalk.yellow(`\n Would update: ${config.path}`));
505
- console.log(chalk.gray(scssContent.substring(0, 200) + '...'));
615
+ console.log(safeChalkCall(chalk, 'yellow', `\n Would update: ${config.path}`));
616
+ console.log(safeChalkCall(chalk, 'gray', scssContent.substring(0, 200) + '...'));
506
617
  } else {
507
618
  await writeFile(fullPath, scssContent, 'utf8');
508
- console.log(chalk.green(` ✓ Updated ${config.path}`));
619
+ console.log(safeChalkCall(chalk, 'green', ` ✓ Updated ${config.path}`));
509
620
  }
510
621
  }
511
622
 
512
- spinner.succeed(chalk.green('✓ Tokens imported successfully'));
623
+ safeSpinnerCall(spinner, 'succeed', safeChalkCall(chalk, 'green', '✓ Tokens imported successfully'));
513
624
 
514
625
  // Show summary
515
626
  const categoryCount = Object.keys(tokens).length;
@@ -518,20 +629,20 @@ export async function importTokens(filePath, options = {}) {
518
629
  0
519
630
  );
520
631
 
521
- console.log(chalk.gray(`\n Categories imported: ${categoryCount}`));
522
- console.log(chalk.gray(` Total tokens: ${tokenCount}`));
632
+ console.log(safeChalkCall(chalk, 'gray', `\n Categories imported: ${categoryCount}`));
633
+ console.log(safeChalkCall(chalk, 'gray', ` Total tokens: ${tokenCount}`));
523
634
 
524
635
  if (!options.dryRun) {
525
- console.log(chalk.cyan('\n💡 Next steps:'));
526
- console.log(chalk.gray(' 1. Review the updated token files'));
527
- console.log(chalk.gray(' 2. Rebuild your themes: atomix build-theme <theme>'));
528
- console.log(chalk.gray(' 3. Test your components with new tokens'));
636
+ console.log(safeChalkCall(chalk, 'cyan', '\n💡 Next steps:'));
637
+ console.log(safeChalkCall(chalk, 'gray', ' 1. Review the updated token files'));
638
+ console.log(safeChalkCall(chalk, 'gray', ' 2. Rebuild your themes: atomix build-theme <theme>'));
639
+ console.log(safeChalkCall(chalk, 'gray', ' 3. Test your components with new tokens'));
529
640
  }
530
641
 
531
642
  return { tokens, categoryCount, tokenCount };
532
643
 
533
644
  } catch (error) {
534
- spinner.fail(chalk.red('Import failed'));
645
+ safeSpinnerCall(spinner, 'fail', safeChalkCall(chalk, 'red', 'Import failed'));
535
646
  throw error;
536
647
  }
537
648
  }
@@ -540,12 +651,13 @@ export async function importTokens(filePath, options = {}) {
540
651
  * Automatically fix issues in token files
541
652
  */
542
653
  export async function fixTokens(options = {}) {
543
- const spinner = ora('Attempting to fix design tokens...').start();
654
+ const spinner = ora('Attempting to fix design tokens...');
655
+ safeSpinnerCall(spinner, 'start');
544
656
  let totalFixed = 0;
545
657
 
546
658
  try {
547
659
  for (const [category, config] of Object.entries(tokenCategories)) {
548
- const fullPath = join(process.cwd(), config.path);
660
+ const fullPath = config.path;
549
661
 
550
662
  if (!existsSync(fullPath)) continue;
551
663
 
@@ -554,7 +666,7 @@ export async function fixTokens(options = {}) {
554
666
  let fileFixedCount = 0;
555
667
 
556
668
  // 1. Fix missing !default flags
557
- const defaultFixed = content.replace(/(\$[a-z-]+:\s*[^;!]+)(;)/gi, (match, p1, p2) => {
669
+ const defaultFixed = content.replace(/(\$[a-z-]+:\s*[^;!\n]+)(;\s*)(?!\s*!default)/gi, (match, p1, p2) => {
558
670
  fileFixedCount++;
559
671
  return `${p1} !default${p2}`;
560
672
  });
@@ -595,15 +707,15 @@ export async function fixTokens(options = {}) {
595
707
  await writeFile(fullPath, content, 'utf8');
596
708
  }
597
709
  totalFixed += fileFixedCount;
598
- console.log(chalk.green(` ✓ Fixed ${fileFixedCount} issues in ${config.path}`));
710
+ console.log(safeChalkCall(chalk, 'green', ` ✓ Fixed ${fileFixedCount} issues in ${config.path}`));
599
711
  }
600
712
  }
601
713
 
602
- spinner.succeed(chalk.green(`✓ Successfully fixed ${totalFixed} issues!`));
714
+ safeSpinnerCall(spinner, 'succeed', safeChalkCall(chalk, 'green', `✓ Successfully fixed ${totalFixed} issues!`));
603
715
  return { totalFixed };
604
716
 
605
717
  } catch (error) {
606
- spinner.fail(chalk.red('Fix operation failed'));
718
+ safeSpinnerCall(spinner, 'fail', safeChalkCall(chalk, 'red', 'Fix operation failed'));
607
719
  throw error;
608
720
  }
609
721
  }