@shohojdhara/atomix 0.3.4 → 0.3.6

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 (237) hide show
  1. package/README.md +101 -199
  2. package/atomix.config.ts +241 -0
  3. package/dist/atomix.css +269 -189
  4. package/dist/atomix.css.map +1 -0
  5. package/dist/atomix.min.css +15179 -11
  6. package/dist/atomix.min.css.map +1 -0
  7. package/dist/charts.d.ts +1929 -0
  8. package/dist/charts.js +6477 -0
  9. package/dist/charts.js.map +1 -0
  10. package/dist/core.d.ts +1289 -0
  11. package/dist/core.js +3373 -0
  12. package/dist/core.js.map +1 -0
  13. package/dist/forms.d.ts +1085 -0
  14. package/dist/forms.js +2466 -0
  15. package/dist/forms.js.map +1 -0
  16. package/dist/heavy.d.ts +636 -0
  17. package/dist/heavy.js +4566 -0
  18. package/dist/heavy.js.map +1 -0
  19. package/dist/index.d.ts +5171 -4792
  20. package/dist/index.esm.js +6098 -4563
  21. package/dist/index.esm.js.map +1 -1
  22. package/dist/index.js +6291 -4747
  23. package/dist/index.js.map +1 -1
  24. package/dist/index.min.js +1 -1
  25. package/dist/index.min.js.map +1 -1
  26. package/dist/layout.d.ts +300 -0
  27. package/dist/layout.js +336 -0
  28. package/dist/layout.js.map +1 -0
  29. package/dist/theme.d.ts +2122 -0
  30. package/dist/theme.js +6084 -0
  31. package/dist/theme.js.map +1 -0
  32. package/package.json +59 -27
  33. package/scripts/atomix-cli.js +544 -16
  34. package/scripts/cli/__tests__/cli-commands.test.js +204 -0
  35. package/scripts/cli/__tests__/utils.test.js +201 -0
  36. package/scripts/cli/__tests__/vitest.config.js +26 -0
  37. package/scripts/cli/interactive-init.js +1 -1
  38. package/scripts/cli/token-manager.js +32 -7
  39. package/scripts/cli/utils.js +347 -0
  40. package/src/components/Accordion/Accordion.stories.tsx +50 -17
  41. package/src/components/Accordion/Accordion.tsx +5 -54
  42. package/src/components/Accordion/index.ts +1 -1
  43. package/src/components/AtomixGlass/AtomixGlass.tsx +65 -31
  44. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +11 -4
  45. package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +1 -32
  46. package/src/components/AtomixGlass/stories/Examples.stories.tsx +2 -2
  47. package/src/components/AtomixGlass/stories/shared-components.tsx +0 -31
  48. package/src/components/Avatar/Avatar.stories.tsx +7 -0
  49. package/src/components/Avatar/Avatar.tsx +3 -3
  50. package/src/components/Badge/Badge.stories.tsx +91 -13
  51. package/src/components/Badge/Badge.tsx +3 -3
  52. package/src/components/Block/Block.stories.tsx +7 -23
  53. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +7 -0
  54. package/src/components/Breadcrumb/Breadcrumb.tsx +3 -3
  55. package/src/components/Button/Button.stories.tsx +141 -22
  56. package/src/components/Button/ButtonGroup.stories.tsx +315 -0
  57. package/src/components/Button/ButtonGroup.tsx +67 -0
  58. package/src/components/Button/index.ts +2 -0
  59. package/src/components/Callout/Callout.stories.tsx +8 -6
  60. package/src/components/Card/Card.stories.tsx +82 -28
  61. package/src/components/Card/ElevationCard.tsx +1 -1
  62. package/src/components/Chart/AnimatedChart.tsx +19 -18
  63. package/src/components/Chart/AreaChart.tsx +5 -2
  64. package/src/components/Chart/BarChart.tsx +1 -1
  65. package/src/components/Chart/BubbleChart.tsx +6 -6
  66. package/src/components/Chart/CandlestickChart.tsx +0 -1
  67. package/src/components/Chart/Chart.stories.tsx +5 -7
  68. package/src/components/Chart/Chart.tsx +0 -16
  69. package/src/components/Chart/ChartRenderer.tsx +1 -1
  70. package/src/components/Chart/ChartToolbar.tsx +1 -0
  71. package/src/components/Chart/DonutChart.tsx +0 -1
  72. package/src/components/Chart/FunnelChart.tsx +1 -2
  73. package/src/components/Chart/GaugeChart.tsx +0 -1
  74. package/src/components/Chart/HeatmapChart.tsx +0 -1
  75. package/src/components/Chart/LineChart.tsx +0 -1
  76. package/src/components/Chart/MultiAxisChart.tsx +0 -1
  77. package/src/components/Chart/PieChart.tsx +0 -1
  78. package/src/components/Chart/RadarChart.tsx +19 -13
  79. package/src/components/Chart/ScatterChart.tsx +3 -4
  80. package/src/components/Chart/TreemapChart.tsx +2 -1
  81. package/src/components/Chart/WaterfallChart.tsx +0 -2
  82. package/src/components/Chart/types.ts +12 -2
  83. package/src/components/Chart/utils.ts +4 -3
  84. package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +7 -0
  85. package/src/components/DataTable/DataTable.stories.tsx +23 -16
  86. package/src/components/DataTable/DataTable.tsx +3 -3
  87. package/src/components/DatePicker/DatePicker.stories.tsx +27 -19
  88. package/src/components/Dropdown/Dropdown.stories.tsx +11 -19
  89. package/src/components/Dropdown/Dropdown.tsx +12 -9
  90. package/src/components/EdgePanel/EdgePanel.stories.tsx +1 -0
  91. package/src/components/Footer/Footer.stories.tsx +8 -6
  92. package/src/components/Footer/FooterLink.tsx +9 -2
  93. package/src/components/Footer/FooterSection.tsx +3 -3
  94. package/src/components/Form/Checkbox.stories.tsx +7 -0
  95. package/src/components/Form/Checkbox.tsx +3 -3
  96. package/src/components/Form/Form.stories.tsx +7 -0
  97. package/src/components/Form/FormGroup.stories.tsx +9 -1
  98. package/src/components/Form/Input.stories.tsx +69 -16
  99. package/src/components/Form/Input.tsx +4 -2
  100. package/src/components/Form/Radio.stories.tsx +9 -1
  101. package/src/components/Form/Radio.tsx +3 -3
  102. package/src/components/Form/Select.stories.tsx +9 -1
  103. package/src/components/Form/Select.tsx +3 -3
  104. package/src/components/Form/Textarea.stories.tsx +10 -2
  105. package/src/components/Form/Textarea.tsx +4 -2
  106. package/src/components/Hero/Hero.stories.tsx +7 -0
  107. package/src/components/List/List.stories.tsx +10 -3
  108. package/src/components/List/List.tsx +3 -3
  109. package/src/components/List/ListGroup.tsx +3 -1
  110. package/src/components/Messages/Messages.stories.tsx +8 -7
  111. package/src/components/Modal/Modal.stories.tsx +17 -6
  112. package/src/components/Modal/Modal.tsx +3 -3
  113. package/src/components/Navigation/Menu/MegaMenu.tsx +9 -3
  114. package/src/components/Navigation/Menu/Menu.stories.tsx +7 -0
  115. package/src/components/Navigation/Menu/Menu.tsx +9 -3
  116. package/src/components/Navigation/Nav/Nav.stories.tsx +7 -0
  117. package/src/components/Navigation/Navbar/Navbar.stories.tsx +1 -0
  118. package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +1 -1
  119. package/src/components/Pagination/Pagination.stories.tsx +188 -111
  120. package/src/components/Pagination/Pagination.tsx +88 -7
  121. package/src/components/PhotoViewer/PhotoViewer.stories.tsx +10 -5
  122. package/src/components/PhotoViewer/PhotoViewerImage.tsx +2 -2
  123. package/src/components/Popover/Popover.stories.tsx +191 -115
  124. package/src/components/Popover/Popover.tsx +4 -4
  125. package/src/components/ProductReview/ProductReview.stories.tsx +80 -58
  126. package/src/components/Progress/Progress.stories.tsx +79 -49
  127. package/src/components/Progress/Progress.tsx +6 -2
  128. package/src/components/Rating/Rating.stories.tsx +109 -84
  129. package/src/components/Rating/Rating.tsx +5 -2
  130. package/src/components/River/River.stories.tsx +194 -114
  131. package/src/components/SectionIntro/SectionIntro.stories.tsx +19 -9
  132. package/src/components/Slider/Slider.stories.tsx +7 -0
  133. package/src/components/Slider/Slider.tsx +10 -9
  134. package/src/components/Spinner/Spinner.stories.tsx +15 -11
  135. package/src/components/Spinner/Spinner.tsx +3 -3
  136. package/src/components/Steps/Steps.stories.tsx +132 -98
  137. package/src/components/Tabs/Tabs.stories.tsx +163 -112
  138. package/src/components/Tabs/Tabs.tsx +3 -3
  139. package/src/components/Testimonial/Testimonial.stories.tsx +114 -68
  140. package/src/components/Todo/Todo.stories.tsx +38 -12
  141. package/src/components/Toggle/Toggle.stories.tsx +61 -28
  142. package/src/components/Tooltip/Tooltip.stories.tsx +318 -200
  143. package/src/components/Tooltip/Tooltip.tsx +3 -3
  144. package/src/components/Upload/Upload.stories.tsx +122 -84
  145. package/src/components/VideoPlayer/VideoPlayer.stories.tsx +7 -24
  146. package/src/components/index.ts +6 -2
  147. package/src/layouts/MasonryGrid/MasonryGrid.tsx +2 -2
  148. package/src/lib/composables/useAtomixGlass.ts +2 -3
  149. package/src/lib/composables/useChartPerformance.ts +102 -78
  150. package/src/lib/composables/useChartScale.ts +10 -0
  151. package/src/lib/composables/useHero.ts +9 -2
  152. package/src/lib/composables/useHeroBackgroundSlider.ts +5 -3
  153. package/src/lib/composables/useNavbar.ts +0 -10
  154. package/src/lib/composables/useSideMenu.ts +1 -0
  155. package/src/lib/composables/useVideoPlayer.ts +3 -2
  156. package/src/lib/config/loader.ts +57 -14
  157. package/src/lib/constants/components.ts +10 -0
  158. package/src/lib/hooks/index.ts +0 -1
  159. package/src/lib/hooks/useComponentCustomization.ts +11 -15
  160. package/src/lib/hooks/usePerformanceMonitor.ts +149 -0
  161. package/src/lib/patterns/index.ts +2 -2
  162. package/src/lib/patterns/slots.tsx +2 -2
  163. package/src/lib/theme/README.md +174 -0
  164. package/src/lib/theme/adapters/index.ts +31 -0
  165. package/src/lib/theme/adapters/themeAdapter.ts +287 -0
  166. package/src/lib/theme/config/__tests__/configLoader.test.ts +207 -0
  167. package/src/lib/theme/config/configLoader.ts +254 -0
  168. package/src/lib/theme/config/loader.ts +37 -48
  169. package/src/lib/theme/config/types.ts +2 -2
  170. package/src/lib/theme/config/validator.ts +15 -91
  171. package/src/lib/theme/{constants.ts → constants/constants.ts} +0 -18
  172. package/src/lib/theme/constants/index.ts +8 -0
  173. package/src/lib/theme/core/ThemeRegistry.ts +19 -6
  174. package/src/lib/theme/core/__tests__/createTheme.test.ts +132 -0
  175. package/src/lib/theme/core/composeTheme.ts +155 -0
  176. package/src/lib/theme/core/createTheme.ts +94 -0
  177. package/src/lib/theme/{createTheme.ts → core/createThemeObject.ts} +10 -6
  178. package/src/lib/theme/core/index.ts +5 -19
  179. package/src/lib/theme/devtools/Comparator.tsx +346 -22
  180. package/src/lib/theme/devtools/IMPROVEMENTS.md +139 -38
  181. package/src/lib/theme/devtools/Inspector.tsx +335 -51
  182. package/src/lib/theme/devtools/LiveEditor.tsx +489 -112
  183. package/src/lib/theme/devtools/Preview.tsx +471 -221
  184. package/src/lib/theme/{core → devtools}/ThemeValidator.ts +6 -3
  185. package/src/lib/theme/devtools/index.ts +14 -4
  186. package/src/lib/theme/devtools/useHistory.ts +130 -0
  187. package/src/lib/theme/errors/index.ts +12 -0
  188. package/src/lib/theme/generators/cssFile.ts +79 -0
  189. package/src/lib/theme/generators/generateCSS.ts +89 -0
  190. package/src/lib/theme/{generateCSSVariables.ts → generators/generateCSSVariables.ts} +4 -14
  191. package/src/lib/theme/generators/index.ts +19 -0
  192. package/src/lib/theme/i18n/rtl.ts +7 -7
  193. package/src/lib/theme/index.ts +120 -15
  194. package/src/lib/theme/runtime/ThemeApplicator.ts +53 -95
  195. package/src/lib/theme/{ThemeContext.tsx → runtime/ThemeContext.tsx} +1 -1
  196. package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +4 -4
  197. package/src/lib/theme/runtime/ThemeProvider.tsx +456 -179
  198. package/src/lib/theme/runtime/index.ts +1 -2
  199. package/src/lib/theme/runtime/useTheme.ts +1 -2
  200. package/src/lib/theme/test/testTheme.ts +385 -0
  201. package/src/lib/theme/tokens/index.ts +12 -0
  202. package/src/lib/theme/tokens/tokens.ts +721 -0
  203. package/src/lib/theme/types.ts +6 -42
  204. package/src/lib/theme/{utils.ts → utils/domUtils.ts} +2 -2
  205. package/src/lib/theme/utils/index.ts +11 -0
  206. package/src/lib/theme/utils/injectCSS.ts +90 -0
  207. package/src/lib/theme/utils/themeHelpers.ts +78 -0
  208. package/src/lib/theme/{themeUtils.ts → utils/themeUtils.ts} +1 -1
  209. package/src/lib/theme-tools.ts +8 -9
  210. package/src/lib/types/components.ts +93 -34
  211. package/src/lib/types/partProps.ts +0 -16
  212. package/src/lib/utils/componentUtils.ts +1 -1
  213. package/src/lib/utils/fontPreloader.ts +148 -0
  214. package/src/lib/utils/index.ts +11 -0
  215. package/src/lib/utils/memoryMonitor.ts +189 -0
  216. package/src/styles/01-settings/_settings.design-tokens.scss +4 -1
  217. package/src/styles/01-settings/_settings.fonts.scss +2 -5
  218. package/src/styles/02-tools/_tools.button.scss +66 -79
  219. package/src/styles/06-components/_components.atomix-glass.scss +13 -3
  220. package/src/styles/06-components/_components.navbar.scss +0 -6
  221. package/src/styles/06-components/_components.pagination.scss +88 -0
  222. package/scripts/build-themes.js +0 -208
  223. package/scripts/sync-theme-config.js +0 -309
  224. package/src/components/AtomixGlass/atomixGLass.old.tsx +0 -1263
  225. package/src/lib/theme/composeTheme.ts +0 -370
  226. package/src/lib/theme/core/ThemeCache.ts +0 -283
  227. package/src/lib/theme/core/ThemeEngine.test.ts +0 -146
  228. package/src/lib/theme/core/ThemeEngine.ts +0 -657
  229. package/src/lib/theme/createThemeFromConfig.ts +0 -132
  230. package/src/lib/theme/devtools/CLI.ts +0 -364
  231. package/src/lib/theme/runtime/ThemeManager.test.ts +0 -192
  232. package/src/lib/theme/runtime/ThemeManager.ts +0 -442
  233. package/src/styles/03-generic/_generated-root.css +0 -5
  234. package/src/themes/README.md +0 -442
  235. package/src/themes/themes.config.js +0 -35
  236. /package/src/lib/theme/{cssVariableMapper.ts → adapters/cssVariableMapper.ts} +0 -0
  237. /package/src/lib/theme/{errors.ts → errors/errors.ts} +0 -0
@@ -18,6 +18,11 @@ export function useChartScale(
18
18
  return {
19
19
  xScale: () => padding.left,
20
20
  yScale: () => padding.top + innerHeight,
21
+ minValue: 0,
22
+ maxValue: 0,
23
+ valueRange: 0,
24
+ innerWidth,
25
+ innerHeight,
21
26
  width,
22
27
  height,
23
28
  padding,
@@ -40,6 +45,11 @@ export function useChartScale(
40
45
  return {
41
46
  xScale,
42
47
  yScale,
48
+ minValue,
49
+ maxValue,
50
+ valueRange,
51
+ innerWidth,
52
+ innerHeight,
43
53
  width,
44
54
  height,
45
55
  padding,
@@ -97,10 +97,17 @@ export function useHero(initialProps?: Partial<HeroProps>): UseHeroResult {
97
97
  const hasBackgroundSlider = !!defaultProps.backgroundSlider;
98
98
 
99
99
  /**
100
- * Initialize background slider hook if enabled
100
+ * Initialize background slider hook - always call hook, conditionally use result
101
101
  */
102
+ const backgroundSliderResult = useHeroBackgroundSlider(
103
+ defaultProps.backgroundSlider || {
104
+ slides: [],
105
+ autoplay: { delay: 5000, pauseOnHover: true }
106
+ }
107
+ );
108
+
102
109
  const backgroundSlider = hasBackgroundSlider && defaultProps.backgroundSlider
103
- ? useHeroBackgroundSlider(defaultProps.backgroundSlider)
110
+ ? backgroundSliderResult
104
111
  : undefined;
105
112
 
106
113
  /**
@@ -89,8 +89,9 @@ export function useHeroBackgroundSlider(
89
89
 
90
90
  // Play video if it's a video slide
91
91
  const currentVideo = videoRefs[nextIndex]?.current;
92
- if (currentVideo && slides[nextIndex].type === 'video') {
93
- const videoOptions = slides[nextIndex].videoOptions || {};
92
+ const nextSlide = slides[nextIndex];
93
+ if (currentVideo && nextSlide && nextSlide.type === 'video') {
94
+ const videoOptions = nextSlide.videoOptions || {};
94
95
  if (videoOptions.autoplay !== false) {
95
96
  currentVideo.play().catch(() => {
96
97
  // Ignore autoplay errors
@@ -100,7 +101,8 @@ export function useHeroBackgroundSlider(
100
101
 
101
102
  // Pause previous video if it exists
102
103
  const prevVideo = videoRefs[currentIndex]?.current;
103
- if (prevVideo && slides[currentIndex].type === 'video') {
104
+ const currentSlide = slides[currentIndex];
105
+ if (prevVideo && currentSlide && currentSlide.type === 'video') {
104
106
  prevVideo.pause();
105
107
  }
106
108
 
@@ -269,20 +269,10 @@ export function useNavDropdown(initialProps?: Partial<NavDropdownProps>) {
269
269
  return isFixedBottom ? 'CaretUp' : 'CaretDown';
270
270
  };
271
271
 
272
- // Keeping this for backward compatibility
273
- const getIconClass = (isMegaMenu: boolean = false): string => {
274
- console.warn(
275
- 'getIconClass is deprecated. Please use the Icon component directly with the getIconName function.'
276
- );
277
- const isFixedBottom = isInFixedBottomNavbar();
278
- return `c-nav__icon ${isFixedBottom ? 'icon-lux-caret-up' : 'icon-lux-caret-down'}`;
279
- };
280
-
281
272
  return {
282
273
  defaultProps,
283
274
  generateDropdownMenuClass,
284
275
  isInFixedBottomNavbar,
285
- getIconClass,
286
276
  getIconName,
287
277
  };
288
278
  }
@@ -60,6 +60,7 @@ export function useSideMenu(initialProps?: Partial<SideMenuProps>) {
60
60
  } else if (!shouldCollapse && wrapperRef.current) {
61
61
  wrapperRef.current.style.height = 'auto';
62
62
  }
63
+ return undefined;
63
64
  }, []); // Only run on mount
64
65
 
65
66
  // Handle responsive behavior - vertical collapse for both mobile and desktop
@@ -41,18 +41,19 @@ export function useVideoPlayer({
41
41
  const [currentQuality, setCurrentQuality] = useState<VideoQuality | null>(quality?.[0] || null);
42
42
  const [showControls, setShowControls] = useState(true);
43
43
 
44
- const controlsTimeoutRef = useRef<NodeJS.Timeout>(null);
44
+ const controlsTimeoutRef = useRef<NodeJS.Timeout | null>(null);
45
45
 
46
46
  const resetControlsTimeout = useCallback(() => {
47
47
  if (controlsTimeoutRef.current) {
48
48
  clearTimeout(controlsTimeoutRef.current);
49
49
  }
50
50
  setShowControls(true);
51
- controlsTimeoutRef.current = setTimeout(() => {
51
+ const timeout = setTimeout(() => {
52
52
  if (isPlaying) {
53
53
  setShowControls(false);
54
54
  }
55
55
  }, 3000);
56
+ controlsTimeoutRef.current = timeout;
56
57
  }, [isPlaying]);
57
58
 
58
59
  const play = useCallback(async () => {
@@ -19,9 +19,10 @@ import type { AtomixConfig } from './index';
19
19
  * @example
20
20
  * ```typescript
21
21
  * import { loadAtomixConfig } from '@shohojdhara/atomix/config';
22
+ * import { createTheme } from '@shohojdhara/atomix/theme';
22
23
  *
23
24
  * const config = loadAtomixConfig();
24
- * const theme = createThemeFromConfig(config);
25
+ * const theme = createTheme(config.theme?.tokens || {});
25
26
  * ```
26
27
  */
27
28
  export function loadAtomixConfig(
@@ -76,26 +77,68 @@ export function loadAtomixConfig(
76
77
  * Resolve config path
77
78
  *
78
79
  * Finds atomix.config.ts in the project, checking common locations.
80
+ * Returns null in browser environments where file system access is not available.
81
+ *
82
+ * This function is designed to work in Node.js environments only.
83
+ * In browser builds, it will always return null without attempting to access Node.js modules.
84
+ *
85
+ * @internal This function uses Node.js modules and should not be called in browser environments.
79
86
  */
80
87
  export function resolveConfigPath(): string | null {
81
- if (typeof process === 'undefined' || !process.cwd) {
88
+ // Early return for browser environments - prevents any Node.js module access
89
+ // This check happens before any require() calls, preventing bundlers from analyzing them
90
+ if (typeof window !== 'undefined' || typeof process === 'undefined' || !process.cwd) {
82
91
  return null;
83
92
  }
84
93
 
85
- const fs = require('fs');
86
- const path = require('path');
87
-
88
- const cwd = process.cwd();
89
- const possiblePaths = [
90
- path.join(cwd, 'atomix.config.ts'),
91
- path.join(cwd, 'atomix.config.js'),
92
- path.join(cwd, 'atomix.config.mjs'),
93
- ];
94
+ // Only attempt to load Node.js modules in Node.js runtime
95
+ // Use a lazy-loading pattern that prevents static analysis by bundlers
96
+ try {
97
+ // Create a function that only executes in Node.js runtime
98
+ // Use string-based module names to prevent static analysis by bundlers
99
+ const loadNodeModules = () => {
100
+ // These requires are only executed at runtime in Node.js environments
101
+ // They are marked as external in Rollup config and should not be bundled
102
+ // Using string concatenation and computed property access to prevent static analysis
103
+ if (typeof require === 'undefined') {
104
+ return null;
105
+ }
106
+
107
+ // Use a try-catch wrapper to safely access require
108
+ try {
109
+ // Build module names dynamically to prevent static analysis
110
+ const moduleNames: [string, string] = ['f' + 's', 'p' + 'a' + 't' + 'h'];
111
+ // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
112
+ const fs = require(moduleNames[0]);
113
+ // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
114
+ const path = require(moduleNames[1]);
115
+ return { fs, path };
116
+ } catch {
117
+ return null;
118
+ }
119
+ };
94
120
 
95
- for (const configPath of possiblePaths) {
96
- if (fs.existsSync(configPath)) {
97
- return configPath;
121
+ const modules = loadNodeModules();
122
+ if (!modules) {
123
+ return null;
98
124
  }
125
+
126
+ const { fs, path } = modules;
127
+ const cwd = process.cwd();
128
+ const possiblePaths = [
129
+ path.join(cwd, 'atomix.config.ts'),
130
+ path.join(cwd, 'atomix.config.js'),
131
+ path.join(cwd, 'atomix.config.mjs'),
132
+ ];
133
+
134
+ for (const configPath of possiblePaths) {
135
+ if (fs.existsSync(configPath)) {
136
+ return configPath;
137
+ }
138
+ }
139
+ } catch (error) {
140
+ // Silently fail in browser environments or when modules are unavailable
141
+ return null;
99
142
  }
100
143
 
101
144
  return null;
@@ -48,6 +48,16 @@ export const BUTTON = {
48
48
  },
49
49
  };
50
50
 
51
+ /**
52
+ * ButtonGroup-specific constants
53
+ */
54
+ export const BUTTON_GROUP = {
55
+ BASE_CLASS: 'c-btn-group',
56
+ CLASSES: {
57
+ BASE: 'c-btn-group',
58
+ },
59
+ };
60
+
51
61
  /**
52
62
  * Callout-specific constants
53
63
  */
@@ -8,7 +8,6 @@ export {
8
8
  useComponentCustomization,
9
9
  useComponentDefaultProps,
10
10
  useMergedProps,
11
- mergeClassNames,
12
11
  applyCSSVarsToStyle,
13
12
  } from './useComponentCustomization';
14
13
 
@@ -9,8 +9,9 @@ import { useMemo } from 'react';
9
9
  import { useTheme } from '../theme/runtime/useTheme';
10
10
  import type { ComponentPartsMap } from '../types/partProps';
11
11
  import type { ComponentCSSVariables } from '../constants/cssVariables';
12
- import { mergeCSSVars } from '../theme/cssVariableMapper';
12
+ import { mergeCSSVars } from '../theme/adapters/cssVariableMapper';
13
13
  import { mergePartStyles } from '../types/partProps';
14
+ import { mergeClassNames } from '../utils/componentUtils';
14
15
 
15
16
  /**
16
17
  * Component names that support customization
@@ -22,7 +23,9 @@ export type ComponentName = keyof ComponentPartsMap;
22
23
  */
23
24
  export interface CustomizableComponentProps<T extends ComponentName> {
24
25
  /** CSS variable overrides */
25
- cssVars?: Partial<Record<ComponentCSSVariables[T], string | number>>;
26
+ cssVars?: T extends keyof ComponentCSSVariables
27
+ ? Partial<Record<ComponentCSSVariables[T], string | number>>
28
+ : Record<string, string | number>;
26
29
  /** Part-based styling */
27
30
  parts?: ComponentPartsMap[T];
28
31
  /** Additional className */
@@ -72,17 +75,17 @@ export function useComponentCustomization<T extends ComponentName>(
72
75
 
73
76
  // Merge CSS variables
74
77
  const cssVars = useMemo(() => {
75
- const themeVars = theme?.components?.[component]?.cssVars || {};
78
+ const themeVars = (theme as any)?.components?.[component]?.cssVars || {};
76
79
  const propVars = props.cssVars || {};
77
80
  return mergeCSSVars(themeVars, propVars as any);
78
81
  }, [theme, component, props.cssVars]);
79
82
 
80
83
  // Merge parts
81
84
  const parts = useMemo(() => {
82
- const themeParts = theme?.components?.[component]?.parts || {};
83
- const propParts = props.parts || {};
85
+ const themeParts = (theme as any)?.components?.[component]?.parts || {};
86
+ const propParts = (props.parts || {}) as Record<string, any>;
84
87
 
85
- const merged: any = {};
88
+ const merged: Record<string, any> = {};
86
89
  const allPartNames = new Set([
87
90
  ...Object.keys(themeParts),
88
91
  ...Object.keys(propParts),
@@ -100,7 +103,7 @@ export function useComponentCustomization<T extends ComponentName>(
100
103
 
101
104
  // Merge className
102
105
  const className = useMemo(() => {
103
- const themeClassName = theme?.components?.[component]?.className || '';
106
+ const themeClassName = (theme as any)?.components?.[component]?.className || '';
104
107
  const propClassName = props.className || '';
105
108
  return [themeClassName, propClassName].filter(Boolean).join(' ');
106
109
  }, [theme, component, props.className]);
@@ -136,7 +139,7 @@ export function useComponentDefaultProps<T extends ComponentName>(
136
139
  const { theme } = useTheme();
137
140
 
138
141
  return useMemo(() => {
139
- return theme?.components?.[component]?.defaultProps || {};
142
+ return (theme as any)?.components?.[component]?.defaultProps || {};
140
143
  }, [theme, component]);
141
144
  }
142
145
 
@@ -152,13 +155,6 @@ export function useMergedProps<T extends Record<string, any>>(
152
155
  }, [defaultProps, props]);
153
156
  }
154
157
 
155
- /**
156
- * Utility to create className from parts
157
- */
158
- export function mergeClassNames(...classNames: Array<string | undefined | null | false>): string {
159
- return classNames.filter(Boolean).join(' ');
160
- }
161
-
162
158
  /**
163
159
  * Utility to apply CSS variables to style object
164
160
  */
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Performance Monitoring Hook
3
+ *
4
+ * Tracks component render times and re-render counts
5
+ * for performance analysis and optimization
6
+ */
7
+
8
+ import { useEffect, useRef } from 'react';
9
+
10
+ export interface PerformanceMetrics {
11
+ /**
12
+ * Component name
13
+ */
14
+ componentName: string;
15
+ /**
16
+ * Number of renders
17
+ */
18
+ renderCount: number;
19
+ /**
20
+ * Average render time in milliseconds
21
+ */
22
+ averageRenderTime: number;
23
+ /**
24
+ * Total render time in milliseconds
25
+ */
26
+ totalRenderTime: number;
27
+ /**
28
+ * Maximum render time in milliseconds
29
+ */
30
+ maxRenderTime: number;
31
+ /**
32
+ * Minimum render time in milliseconds
33
+ */
34
+ minRenderTime: number;
35
+ }
36
+
37
+ /**
38
+ * Options for performance monitoring
39
+ */
40
+ export interface UsePerformanceMonitorOptions {
41
+ /**
42
+ * Component name to track
43
+ */
44
+ componentName: string;
45
+ /**
46
+ * Whether to log metrics to console (development only)
47
+ */
48
+ logToConsole?: boolean;
49
+ /**
50
+ * Threshold in milliseconds to warn about slow renders
51
+ */
52
+ warnThreshold?: number;
53
+ /**
54
+ * Callback to report metrics (e.g., to analytics)
55
+ */
56
+ onMetrics?: (metrics: PerformanceMetrics) => void;
57
+ }
58
+
59
+ /**
60
+ * Hook to monitor component performance
61
+ *
62
+ * @param options - Performance monitoring options
63
+ * @returns Performance metrics
64
+ *
65
+ * @example
66
+ * ```tsx
67
+ * function MyComponent() {
68
+ * usePerformanceMonitor({
69
+ * componentName: 'MyComponent',
70
+ * warnThreshold: 16, // Warn if render takes > 16ms (1 frame)
71
+ * });
72
+ *
73
+ * return <div>Content</div>;
74
+ * }
75
+ * ```
76
+ */
77
+ export function usePerformanceMonitor(options: UsePerformanceMonitorOptions) {
78
+ const {
79
+ componentName,
80
+ logToConsole = process.env.NODE_ENV === 'development',
81
+ warnThreshold = 16,
82
+ onMetrics,
83
+ } = options;
84
+
85
+ const metricsRef = useRef<PerformanceMetrics>({
86
+ componentName,
87
+ renderCount: 0,
88
+ averageRenderTime: 0,
89
+ totalRenderTime: 0,
90
+ maxRenderTime: 0,
91
+ minRenderTime: Infinity,
92
+ });
93
+
94
+ const renderStartRef = useRef<number>(0);
95
+
96
+ useEffect(() => {
97
+ // Start timing the render
98
+ renderStartRef.current = performance.now();
99
+ });
100
+
101
+ useEffect(() => {
102
+ // Calculate render time
103
+ const renderTime = performance.now() - renderStartRef.current;
104
+ const metrics = metricsRef.current;
105
+
106
+ // Update metrics
107
+ metrics.renderCount += 1;
108
+ metrics.totalRenderTime += renderTime;
109
+ metrics.averageRenderTime = metrics.totalRenderTime / metrics.renderCount;
110
+ metrics.maxRenderTime = Math.max(metrics.maxRenderTime, renderTime);
111
+ metrics.minRenderTime = Math.min(metrics.minRenderTime, renderTime);
112
+
113
+ // Warn if render is slow
114
+ if (renderTime > warnThreshold && logToConsole) {
115
+ console.warn(
116
+ `[Performance] ${componentName} render took ${renderTime.toFixed(2)}ms ` +
117
+ `(threshold: ${warnThreshold}ms)`
118
+ );
119
+ }
120
+
121
+ // Log metrics in development
122
+ if (logToConsole && metrics.renderCount % 10 === 0) {
123
+ console.log(`[Performance] ${componentName} metrics:`, {
124
+ renderCount: metrics.renderCount,
125
+ averageRenderTime: metrics.averageRenderTime.toFixed(2) + 'ms',
126
+ maxRenderTime: metrics.maxRenderTime.toFixed(2) + 'ms',
127
+ minRenderTime: metrics.minRenderTime.toFixed(2) + 'ms',
128
+ });
129
+ }
130
+
131
+ // Report metrics via callback
132
+ if (onMetrics) {
133
+ onMetrics({ ...metrics });
134
+ }
135
+ });
136
+
137
+ return metricsRef.current;
138
+ }
139
+
140
+ /**
141
+ * Get all performance metrics for all monitored components
142
+ * (useful for debugging and analytics)
143
+ */
144
+ export function getPerformanceMetrics(): PerformanceMetrics[] {
145
+ // This would need to be implemented with a global store
146
+ // For now, this is a placeholder
147
+ return [];
148
+ }
149
+
@@ -11,7 +11,7 @@ export {
11
11
  createSlotComponent,
12
12
  useSlot,
13
13
  createSlotProps,
14
- } from './slots.tsx';
14
+ } from './slots';
15
15
 
16
16
  export type {
17
17
  SlotProps,
@@ -32,4 +32,4 @@ export type {
32
32
  DropdownRootSlotProps,
33
33
  DropdownToggleSlotProps,
34
34
  DropdownMenuSlotProps,
35
- } from './slots.tsx';
35
+ } from './slots';
@@ -59,7 +59,7 @@ export function renderSlot<T>(
59
59
  // Priority 2: component
60
60
  if (slotObj.component) {
61
61
  const Component = slotObj.component;
62
- return <Component {...props} />;
62
+ return <Component {...(props as any)} />;
63
63
  }
64
64
 
65
65
  // Priority 3: children
@@ -133,7 +133,7 @@ export function createSlotComponent<T>(
133
133
  return <Element {...(props as any)}>{children}</Element>;
134
134
  }
135
135
 
136
- const Component = defaultElement;
136
+ const Component = defaultElement as React.ComponentType<any>;
137
137
  return <Component {...slotProps}>{children}</Component>;
138
138
  };
139
139
  }
@@ -0,0 +1,174 @@
1
+ # Theme System File Organization
2
+
3
+ ## Directory Structure
4
+
5
+ The theme system is organized following senior developer best practices with clear separation of concerns and logical grouping:
6
+
7
+ ```
8
+ theme/
9
+ ├── index.ts # Main public API exports
10
+ ├── README.md # This file
11
+
12
+ ├── core/ # Core theme engine
13
+ │ ├── index.ts
14
+ │ ├── createTheme.ts # Main createTheme function (unified)
15
+ │ ├── createThemeObject.ts # Theme object creation
16
+ │ ├── composeTheme.ts # Theme composition and merging
17
+ │ └── ThemeRegistry.ts # Theme registration and discovery
18
+
19
+ ├── adapters/ # Adapters and converters
20
+ │ ├── index.ts
21
+ │ ├── themeAdapter.ts # Theme ↔ DesignTokens conversion
22
+ │ └── cssVariableMapper.ts # CSS variable mapping utilities
23
+
24
+ ├── generators/ # Code generation
25
+ │ ├── index.ts
26
+ │ ├── generateCSS.ts # CSS variable generation (simple)
27
+ │ ├── generateCSSVariables.ts # CSS variable generation (advanced)
28
+ │ └── cssFile.ts # File operations (save CSS to disk)
29
+
30
+ ├── runtime/ # React runtime components
31
+ │ ├── index.ts
32
+ │ ├── ThemeProvider.tsx # Main theme provider component
33
+ │ ├── ThemeApplicator.ts # Theme application logic
34
+ │ ├── ThemeErrorBoundary.tsx # Error boundary for themes
35
+ │ ├── ThemeContext.tsx # React context for theme management
36
+ │ └── useTheme.ts # React hook for theme access
37
+
38
+ ├── config/ # Configuration
39
+ │ ├── index.ts
40
+ │ ├── loader.ts # Config file loader
41
+ │ ├── configLoader.ts # Config loading from atomix.config.ts
42
+ │ ├── types.ts # Config type definitions
43
+ │ └── validator.ts # Config validation
44
+
45
+ ├── utils/ # Utilities
46
+ │ ├── index.ts
47
+ │ ├── themeHelpers.ts # Type guards and DesignTokens utilities
48
+ │ ├── themeUtils.ts # Theme value manipulation (colors, spacing)
49
+ │ ├── domUtils.ts # DOM/browser utilities
50
+ │ └── injectCSS.ts # CSS injection utilities
51
+
52
+ ├── tokens/ # Design tokens
53
+ │ ├── index.ts
54
+ │ └── tokens.ts # Design tokens definitions
55
+
56
+ ├── constants/ # Constants
57
+ │ ├── index.ts
58
+ │ └── constants.ts # System constants and default values
59
+
60
+ ├── errors/ # Error handling
61
+ │ ├── index.ts
62
+ │ └── errors.ts # Error classes and error handling
63
+
64
+ ├── devtools/ # Development tools
65
+ │ ├── index.ts
66
+ │ ├── CLI.ts # Command-line interface
67
+ │ ├── Comparator.tsx # Theme comparison
68
+ │ ├── Inspector.tsx # Theme inspector
69
+ │ ├── LiveEditor.tsx # Live theme editor
70
+ │ ├── Preview.tsx # Theme preview
71
+ │ ├── ThemeValidator.tsx # Theme validation component
72
+ │ └── README.md # DevTools documentation
73
+
74
+ ├── i18n/ # Internationalization
75
+ │ ├── index.ts
76
+ │ └── rtl.ts # Right-to-left language support
77
+
78
+ └── types.ts # TypeScript type definitions (root level)
79
+ ```
80
+
81
+ ## Naming Conventions
82
+
83
+ ### Files and Directories
84
+
85
+ 1. **React Components**: Always use PascalCase (e.g., `ThemeProvider.tsx`)
86
+ 2. **Feature Modules**: Use camelCase with descriptive names (e.g., `themeAdapter.ts`)
87
+ 3. **Base Utilities**: Use lowercase for foundational utilities (e.g., `domUtils.ts`, `types.ts`)
88
+ 4. **Directories**: Use lowercase, plural for collections (e.g., `utils/`, `adapters/`)
89
+ 5. **Index Files**: Each subdirectory has an `index.ts` for clean exports
90
+
91
+ ### Import Patterns
92
+
93
+ ```typescript
94
+ // ✅ CORRECT - Import from organized directories
95
+ import { createTheme } from './core';
96
+ import { themeToDesignTokens } from './adapters';
97
+ import { generateCSSVariables } from './generators';
98
+ import { isDesignTokens } from './utils/themeHelpers';
99
+
100
+ // ❌ INCORRECT - Direct imports from root (old structure)
101
+ import { createTheme } from './core';
102
+ import { themeToDesignTokens } from './themeAdapter';
103
+ ```
104
+
105
+ ## File Organization Principles
106
+
107
+ 1. **Separation of Concerns**: Each directory has a single, well-defined responsibility
108
+ 2. **Logical Grouping**: Related functionality is grouped together
109
+ 3. **Clear Entry Points**: Each directory has an `index.ts` for clean exports
110
+ 4. **Consistent Naming**: Follow established naming conventions throughout
111
+ 5. **Maintainability**: Structure makes it easy to find and modify code
112
+
113
+ ## Directory Responsibilities
114
+
115
+ ### `/core` - Core Theme Engine
116
+ - Theme creation and composition
117
+ - Theme registry and discovery
118
+ - Core theme logic
119
+
120
+ ### `/adapters` - Adapters and Converters
121
+ - Convert between Theme objects and DesignTokens
122
+ - CSS variable mapping utilities
123
+ - Format transformations
124
+
125
+ ### `/generators` - Code Generation
126
+ - CSS variable generation
127
+ - File operations (save CSS to disk)
128
+ - Code generation utilities
129
+
130
+ ### `/runtime` - React Runtime
131
+ - React components (ThemeProvider, ThemeErrorBoundary)
132
+ - React hooks (useTheme)
133
+ - Theme application logic
134
+ - React context
135
+
136
+ ### `/config` - Configuration
137
+ - Config file loading
138
+ - Config validation
139
+ - Configuration types
140
+
141
+ ### `/utils` - Utilities
142
+ - Theme helpers and type guards
143
+ - Theme value manipulation
144
+ - DOM/browser utilities
145
+ - CSS injection
146
+
147
+ ### `/tokens` - Design Tokens
148
+ - Design token definitions
149
+ - Token creation utilities
150
+
151
+ ### `/constants` - Constants
152
+ - System constants
153
+ - Default values
154
+
155
+ ### `/errors` - Error Handling
156
+ - Error classes
157
+ - Error handling utilities
158
+
159
+ ### `/devtools` - Development Tools
160
+ - Development and debugging tools
161
+ - Theme inspection and validation
162
+ - Live editing capabilities
163
+
164
+ ### `/i18n` - Internationalization
165
+ - RTL (Right-to-Left) support
166
+ - Internationalization utilities
167
+
168
+ ## Best Practices
169
+
170
+ 1. **Always use index files**: Import from directory index files when possible
171
+ 2. **Group related functionality**: Keep related code together
172
+ 3. **Maintain clear boundaries**: Don't mix concerns between directories
173
+ 4. **Follow naming conventions**: Consistency is key
174
+ 5. **Document changes**: Update this README when structure changes