@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
@@ -0,0 +1,347 @@
1
+ /**
2
+ * CLI Utility Functions
3
+ * Provides common utilities for the Atomix CLI including security, validation, and helpers
4
+ */
5
+
6
+ import { resolve, relative, isAbsolute, normalize } from 'path';
7
+ import { existsSync } from 'fs';
8
+ import { access } from 'fs/promises';
9
+
10
+ /**
11
+ * Validates and sanitizes file paths to prevent directory traversal attacks
12
+ * @param {string} inputPath - The path to validate
13
+ * @param {string} basePath - The base directory (defaults to process.cwd())
14
+ * @returns {Object} { isValid: boolean, safePath: string, error?: string }
15
+ */
16
+ export function validatePath(inputPath, basePath = process.cwd()) {
17
+ try {
18
+ // Normalize the paths to remove any '..' or '.' segments
19
+ const normalizedBase = normalize(resolve(basePath));
20
+ const normalizedInput = normalize(isAbsolute(inputPath)
21
+ ? inputPath
22
+ : resolve(basePath, inputPath));
23
+
24
+ // Check if the resolved path is within the base directory
25
+ const relativePath = relative(normalizedBase, normalizedInput);
26
+
27
+ // If the relative path starts with '..', it's outside the base directory
28
+ if (relativePath.startsWith('..')) {
29
+ return {
30
+ isValid: false,
31
+ safePath: null,
32
+ error: 'Path is outside the project directory'
33
+ };
34
+ }
35
+
36
+ // Additional checks for sensitive paths
37
+ const sensitivePatterns = [
38
+ /^\.git/,
39
+ /node_modules/,
40
+ /^\.env/,
41
+ /\.pem$/,
42
+ /\.key$/,
43
+ /private/i,
44
+ /secret/i
45
+ ];
46
+
47
+ for (const pattern of sensitivePatterns) {
48
+ if (pattern.test(relativePath)) {
49
+ return {
50
+ isValid: false,
51
+ safePath: null,
52
+ error: `Access to sensitive path is restricted: ${pattern}`
53
+ };
54
+ }
55
+ }
56
+
57
+ return {
58
+ isValid: true,
59
+ safePath: normalizedInput,
60
+ error: null
61
+ };
62
+ } catch (error) {
63
+ return {
64
+ isValid: false,
65
+ safePath: null,
66
+ error: `Invalid path: ${error.message}`
67
+ };
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Validates component names according to PascalCase convention
73
+ * @param {string} name - The component name to validate
74
+ * @returns {Object} { isValid: boolean, error?: string }
75
+ */
76
+ export function validateComponentName(name) {
77
+ if (!name || typeof name !== 'string') {
78
+ return {
79
+ isValid: false,
80
+ error: 'Component name must be a non-empty string'
81
+ };
82
+ }
83
+
84
+ // Check PascalCase: starts with uppercase, only contains letters and numbers
85
+ if (!/^[A-Z][a-zA-Z0-9]*$/.test(name)) {
86
+ return {
87
+ isValid: false,
88
+ error: 'Component name must be in PascalCase (e.g., Button, CardHeader)'
89
+ };
90
+ }
91
+
92
+ // Check for reserved words
93
+ const reservedWords = [
94
+ 'Component', 'React', 'Fragment', 'Suspense', 'StrictMode',
95
+ 'Error', 'Loading', 'App', 'Root', 'Document', 'Html'
96
+ ];
97
+
98
+ if (reservedWords.includes(name)) {
99
+ return {
100
+ isValid: false,
101
+ error: `"${name}" is a reserved word. Please choose a different name.`
102
+ };
103
+ }
104
+
105
+ // Check minimum length
106
+ if (name.length < 2) {
107
+ return {
108
+ isValid: false,
109
+ error: 'Component name must be at least 2 characters long'
110
+ };
111
+ }
112
+
113
+ return { isValid: true };
114
+ }
115
+
116
+ /**
117
+ * Validates theme names according to kebab-case convention
118
+ * @param {string} name - The theme name to validate
119
+ * @returns {Object} { isValid: boolean, error?: string }
120
+ */
121
+ export function validateThemeName(name) {
122
+ if (!name || typeof name !== 'string') {
123
+ return {
124
+ isValid: false,
125
+ error: 'Theme name must be a non-empty string'
126
+ };
127
+ }
128
+
129
+ // Check kebab-case: lowercase letters, numbers, and hyphens
130
+ if (!/^[a-z][a-z0-9-]*$/.test(name)) {
131
+ return {
132
+ isValid: false,
133
+ error: 'Theme name must be lowercase and use hyphens (e.g., dark-theme)'
134
+ };
135
+ }
136
+
137
+ // Check for consecutive hyphens
138
+ if (/--/.test(name)) {
139
+ return {
140
+ isValid: false,
141
+ error: 'Theme name cannot contain consecutive hyphens'
142
+ };
143
+ }
144
+
145
+ // Check for trailing hyphen
146
+ if (name.endsWith('-')) {
147
+ return {
148
+ isValid: false,
149
+ error: 'Theme name cannot end with a hyphen'
150
+ };
151
+ }
152
+
153
+ return { isValid: true };
154
+ }
155
+
156
+ /**
157
+ * Sanitizes user input to prevent injection attacks
158
+ * @param {string} input - The user input to sanitize
159
+ * @returns {string} Sanitized input
160
+ */
161
+ export function sanitizeInput(input) {
162
+ if (typeof input !== 'string') {
163
+ return String(input);
164
+ }
165
+
166
+ // Remove any shell metacharacters that could be dangerous
167
+ return input
168
+ .replace(/[;&|`$<>\\]/g, '')
169
+ .replace(/\0/g, '') // Remove null bytes
170
+ .trim();
171
+ }
172
+
173
+ /**
174
+ * Checks if a file exists and is accessible
175
+ * @param {string} filePath - Path to check
176
+ * @returns {Promise<boolean>}
177
+ */
178
+ export async function fileExists(filePath) {
179
+ try {
180
+ await access(filePath);
181
+ return true;
182
+ } catch {
183
+ return false;
184
+ }
185
+ }
186
+
187
+ /**
188
+ * Checks if running in CI environment
189
+ * @returns {boolean}
190
+ */
191
+ export function isCI() {
192
+ return !!(
193
+ process.env.CI ||
194
+ process.env.CONTINUOUS_INTEGRATION ||
195
+ process.env.GITHUB_ACTIONS ||
196
+ process.env.GITLAB_CI ||
197
+ process.env.CIRCLECI ||
198
+ process.env.TRAVIS ||
199
+ process.env.JENKINS_URL
200
+ );
201
+ }
202
+
203
+ /**
204
+ * Checks if running in debug mode
205
+ * @returns {boolean}
206
+ */
207
+ export function isDebug() {
208
+ return process.env.ATOMIX_DEBUG === 'true' ||
209
+ process.argv.includes('--debug') ||
210
+ process.argv.includes('-d');
211
+ }
212
+
213
+ /**
214
+ * Formats file size in human readable format
215
+ * @param {number} bytes - File size in bytes
216
+ * @returns {string} Formatted size
217
+ */
218
+ export function formatFileSize(bytes) {
219
+ const sizes = ['B', 'KB', 'MB', 'GB'];
220
+ if (bytes === 0) return '0 B';
221
+ const i = Math.floor(Math.log(bytes) / Math.log(1024));
222
+ return `${(bytes / Math.pow(1024, i)).toFixed(2)} ${sizes[i]}`;
223
+ }
224
+
225
+ /**
226
+ * Debounce function for watch mode
227
+ * @param {Function} func - Function to debounce
228
+ * @param {number} wait - Wait time in milliseconds
229
+ * @returns {Function} Debounced function
230
+ */
231
+ export function debounce(func, wait) {
232
+ let timeout;
233
+ return function executedFunction(...args) {
234
+ const later = () => {
235
+ clearTimeout(timeout);
236
+ func(...args);
237
+ };
238
+ clearTimeout(timeout);
239
+ timeout = setTimeout(later, wait);
240
+ };
241
+ }
242
+
243
+ /**
244
+ * Creates a safe file path for cross-platform compatibility
245
+ * @param {...string} segments - Path segments
246
+ * @returns {string} Safe file path
247
+ */
248
+ export function safePath(...segments) {
249
+ // Filter out empty segments and join with proper separator
250
+ return segments
251
+ .filter(Boolean)
252
+ .join('/')
253
+ .replace(/\/+/g, '/') // Remove duplicate slashes
254
+ .replace(/\\/g, '/'); // Convert Windows backslashes
255
+ }
256
+
257
+ /**
258
+ * Validates SCSS/CSS color values
259
+ * @param {string} color - Color value to validate
260
+ * @returns {boolean}
261
+ */
262
+ export function isValidColor(color) {
263
+ const patterns = [
264
+ /^#[0-9A-F]{3}$/i, // #RGB
265
+ /^#[0-9A-F]{4}$/i, // #RGBA
266
+ /^#[0-9A-F]{6}$/i, // #RRGGBB
267
+ /^#[0-9A-F]{8}$/i, // #RRGGBBAA
268
+ /^rgb\(/i, // rgb()
269
+ /^rgba\(/i, // rgba()
270
+ /^hsl\(/i, // hsl()
271
+ /^hsla\(/i, // hsla()
272
+ /^var\(--/ // CSS custom property
273
+ ];
274
+
275
+ return patterns.some(pattern => pattern.test(color));
276
+ }
277
+
278
+ /**
279
+ * Extracts and validates npm scripts from package.json
280
+ * @param {Object} packageJson - Parsed package.json content
281
+ * @param {Array<string>} requiredScripts - List of required script names
282
+ * @returns {Object} { valid: boolean, missing: Array<string> }
283
+ */
284
+ export function validateNpmScripts(packageJson, requiredScripts = []) {
285
+ const scripts = packageJson.scripts || {};
286
+ const missing = requiredScripts.filter(script => !scripts[script]);
287
+
288
+ return {
289
+ valid: missing.length === 0,
290
+ missing
291
+ };
292
+ }
293
+
294
+ /**
295
+ * Generates a unique ID for components/themes
296
+ * @param {string} prefix - Prefix for the ID
297
+ * @returns {string} Unique ID
298
+ */
299
+ export function generateId(prefix = 'atomix') {
300
+ const timestamp = Date.now().toString(36);
301
+ const random = Math.random().toString(36).substring(2, 7);
302
+ return `${prefix}-${timestamp}-${random}`;
303
+ }
304
+
305
+ /**
306
+ * Checks Node.js version compatibility
307
+ * @param {string} requiredVersion - Minimum required version (e.g., '18.0.0')
308
+ * @returns {Object} { compatible: boolean, current: string, required: string }
309
+ */
310
+ export function checkNodeVersion(requiredVersion = '18.0.0') {
311
+ const currentVersion = process.version.substring(1); // Remove 'v' prefix
312
+ const current = currentVersion.split('.').map(Number);
313
+ const required = requiredVersion.split('.').map(Number);
314
+
315
+ let compatible = true;
316
+ for (let i = 0; i < required.length; i++) {
317
+ if (current[i] < required[i]) {
318
+ compatible = false;
319
+ break;
320
+ } else if (current[i] > required[i]) {
321
+ break;
322
+ }
323
+ }
324
+
325
+ return {
326
+ compatible,
327
+ current: currentVersion,
328
+ required: requiredVersion
329
+ };
330
+ }
331
+
332
+ export default {
333
+ validatePath,
334
+ validateComponentName,
335
+ validateThemeName,
336
+ sanitizeInput,
337
+ fileExists,
338
+ isCI,
339
+ isDebug,
340
+ formatFileSize,
341
+ debounce,
342
+ safePath,
343
+ isValidColor,
344
+ validateNpmScripts,
345
+ generateId,
346
+ checkNodeVersion
347
+ };
@@ -4,6 +4,9 @@ import { Accordion } from './Accordion';
4
4
  import { ACCORDION } from '../../lib/constants/components';
5
5
  import type { AtomixGlassProps } from '../../lib/types/components';
6
6
 
7
+ // Helper type for glass props in stories (without children requirement)
8
+ type GlassProps = boolean | Omit<AtomixGlassProps, 'children'>;
9
+
7
10
  // Extract class names without the leading dots
8
11
  const ACCORDION_CLASS = ACCORDION.SELECTORS.ACCORDION.replace('.', '');
9
12
  const HEADER_CLASS = ACCORDION.SELECTORS.HEADER.replace('.', '');
@@ -24,15 +27,18 @@ const meta = {
24
27
  },
25
28
  },
26
29
  },
30
+ tags: ['autodocs'],
27
31
  argTypes: {
28
32
  iconPosition: {
29
33
  control: { type: 'radio' },
30
34
  options: ['right', 'left'],
31
35
  description: 'Position of the icon',
36
+ defaultValue: 'right',
32
37
  },
33
38
  defaultOpen: {
34
39
  control: 'boolean',
35
40
  description: 'Whether the accordion is initially open',
41
+ defaultValue: false,
36
42
  },
37
43
  disabled: {
38
44
  control: 'boolean',
@@ -56,7 +62,9 @@ const meta = {
56
62
  export default meta;
57
63
  type Story = StoryObj<typeof meta>;
58
64
 
59
- // Default Accordion (Closed)
65
+ /**
66
+ * Default accordion in closed state.
67
+ */
60
68
  export const Default: Story = {
61
69
  args: {
62
70
  title: 'Accordion Title',
@@ -64,7 +72,9 @@ export const Default: Story = {
64
72
  },
65
73
  };
66
74
 
67
- // Open Accordion
75
+ /**
76
+ * Accordion in open state by default.
77
+ */
68
78
  export const Open: Story = {
69
79
  args: {
70
80
  title: 'Open Accordion',
@@ -73,7 +83,9 @@ export const Open: Story = {
73
83
  },
74
84
  };
75
85
 
76
- // Disabled Accordion
86
+ /**
87
+ * Disabled accordion - non-interactive state.
88
+ */
77
89
  export const Disabled: Story = {
78
90
  args: {
79
91
  title: 'Disabled Accordion',
@@ -82,7 +94,9 @@ export const Disabled: Story = {
82
94
  },
83
95
  };
84
96
 
85
- // Icon on Left
97
+ /**
98
+ * Accordion with icon positioned on the left side.
99
+ */
86
100
  export const IconLeft: Story = {
87
101
  args: {
88
102
  title: 'Icon on Left',
@@ -91,7 +105,9 @@ export const IconLeft: Story = {
91
105
  },
92
106
  };
93
107
 
94
- // Custom Icon
108
+ /**
109
+ * Accordion with custom icon instead of default chevron.
110
+ */
95
111
  export const CustomIcon: Story = {
96
112
  args: {
97
113
  title: 'Custom Icon',
@@ -118,7 +134,9 @@ export const CustomIcon: Story = {
118
134
  },
119
135
  };
120
136
 
121
- // Accordion Group
137
+ /**
138
+ * Multiple accordions grouped together.
139
+ */
122
140
  export const AccordionGroup: Story = {
123
141
  args: {
124
142
  title: 'Accordion Group',
@@ -150,12 +168,21 @@ export const AccordionGroup: Story = {
150
168
  ),
151
169
  };
152
170
 
153
- // All Variants
171
+ /**
172
+ * Showcase of all accordion variants and states.
173
+ */
154
174
  export const AllVariants: Story = {
155
175
  args: {
156
176
  title: 'All Variants',
157
177
  children: <p>See render function for all variants</p>,
158
178
  },
179
+ parameters: {
180
+ docs: {
181
+ description: {
182
+ story: 'Comprehensive showcase of all accordion variants including default, open, disabled, icon positions, and custom icons.',
183
+ },
184
+ },
185
+ },
159
186
  render: () => (
160
187
  <div>
161
188
  <h2>All Accordion Variants</h2>
@@ -246,7 +273,9 @@ export const AllVariants: Story = {
246
273
  ),
247
274
  };
248
275
 
249
- // Controlled Accordion
276
+ /**
277
+ * Controlled accordion using external state management.
278
+ */
250
279
  export const Controlled: Story = {
251
280
  args: {
252
281
  title: 'Controlled Accordion',
@@ -275,7 +304,9 @@ export const Controlled: Story = {
275
304
  },
276
305
  };
277
306
 
278
- // Glass Variant
307
+ /**
308
+ * Accordion with glass morphism effect enabled.
309
+ */
279
310
  export const Glass: Story = {
280
311
  args: {
281
312
  title: 'Glass Accordion',
@@ -312,7 +343,9 @@ export const Glass: Story = {
312
343
  },
313
344
  };
314
345
 
315
- // Glass with Custom Settings
346
+ /**
347
+ * Accordion with custom glass morphism settings.
348
+ */
316
349
  export const GlassCustom: Story = {
317
350
  args: {
318
351
  title: 'Custom Glass Accordion',
@@ -322,7 +355,7 @@ export const GlassCustom: Story = {
322
355
  blurAmount: 3,
323
356
  saturation: 60,
324
357
  mode: 'polar',
325
- } as AtomixGlassProps as any,
358
+ } as GlassProps,
326
359
  },
327
360
  render: args => (
328
361
  <div
@@ -505,7 +538,7 @@ export const GlassModePolar: Story = {
505
538
  blurAmount: 1.5,
506
539
  saturation: 180,
507
540
  aberrationIntensity: 3,
508
- } as any,
541
+ } as GlassProps,
509
542
  },
510
543
  render: args => (
511
544
  <div
@@ -550,7 +583,7 @@ export const GlassModeProminent: Story = {
550
583
  blurAmount: 2.5,
551
584
  saturation: 200,
552
585
  aberrationIntensity: 4,
553
- } as any,
586
+ } as GlassProps,
554
587
  },
555
588
  render: args => (
556
589
  <div
@@ -595,7 +628,7 @@ export const GlassModeShader: Story = {
595
628
  displacementScale: 70,
596
629
  blurAmount: 1.8,
597
630
  saturation: 170,
598
- } as any,
631
+ } as GlassProps,
599
632
  },
600
633
  render: args => (
601
634
  <div
@@ -700,7 +733,7 @@ export const AllGlassModesComparison: Story = {
700
733
  blurAmount: 1.5,
701
734
  saturation: 180,
702
735
  aberrationIntensity: 3,
703
- } as any
736
+ } as GlassProps
704
737
  }
705
738
  >
706
739
  <p>Radial distortion effects emanating from the center point.</p>
@@ -728,7 +761,7 @@ export const AllGlassModesComparison: Story = {
728
761
  blurAmount: 2.5,
729
762
  saturation: 200,
730
763
  aberrationIntensity: 4,
731
- } as any
764
+ } as GlassProps
732
765
  }
733
766
  >
734
767
  <p>Enhanced distortion with maximum depth and visual impact.</p>
@@ -756,7 +789,7 @@ export const AllGlassModesComparison: Story = {
756
789
  displacementScale: 70,
757
790
  blurAmount: 1.8,
758
791
  saturation: 170,
759
- } as any
792
+ } as GlassProps
760
793
  }
761
794
  >
762
795
  <p>GPU-accelerated liquid glass with smooth animations.</p>
@@ -1,61 +1,12 @@
1
- import React, { ReactNode, useId } from 'react';
1
+ import React, { ReactNode, useId, memo } from 'react';
2
2
  import { ACCORDION } from '../../lib/constants/components';
3
3
  import { useAccordion } from '../../lib/composables/useAccordion';
4
- import { BaseComponentProps, IconPosition, AtomixGlassProps } from '../../lib/types/components';
4
+ import type { AccordionProps as AccordionPropsType, AtomixGlassProps } from '../../lib/types/components';
5
5
  import { AtomixGlass } from '../AtomixGlass/AtomixGlass';
6
6
 
7
- /**
8
- * Accordion component for showing/hiding content panels
9
- */
10
- export interface AccordionProps extends BaseComponentProps {
11
- /**
12
- * Title of the accordion
13
- */
14
- title: string;
7
+ export type AccordionProps = AccordionPropsType;
15
8
 
16
- /**
17
- * Content to be shown when accordion is expanded
18
- */
19
- children: ReactNode;
20
-
21
- /**
22
- * Whether the accordion is initially open
23
- */
24
- defaultOpen?: boolean;
25
-
26
- /**
27
- * Position of the icon (right or left)
28
- */
29
- iconPosition?: IconPosition;
30
-
31
- /**
32
- * Custom icon for the accordion
33
- */
34
- icon?: ReactNode;
35
-
36
- /**
37
- * Controlled open state (overrides defaultOpen)
38
- */
39
- isOpen?: boolean;
40
-
41
- /**
42
- * Callback when open state changes (for controlled mode)
43
- */
44
- onOpenChange?: (open: boolean) => void;
45
-
46
- /**
47
- * Glass morphism effect for the accordion
48
- * Can be a boolean to enable with default settings, or an object with AtomixGlassProps to customize the effect
49
- */
50
- glass?: AtomixGlassProps | boolean;
51
-
52
- /**
53
- * Custom style for the accordion
54
- */
55
- style?: React.CSSProperties;
56
- }
57
-
58
- export const Accordion: React.FC<AccordionProps> = ({
9
+ export const Accordion: React.FC<AccordionProps> = memo(({
59
10
  title,
60
11
  children,
61
12
  defaultOpen = false,
@@ -159,7 +110,7 @@ export const Accordion: React.FC<AccordionProps> = ({
159
110
  }
160
111
 
161
112
  return accordionContent;
162
- };
113
+ });
163
114
 
164
115
  // Set display name for debugging
165
116
  Accordion.displayName = 'Accordion';
@@ -1,3 +1,3 @@
1
1
  export { Accordion } from './Accordion';
2
2
  export { default } from './Accordion';
3
- export type { AccordionProps } from './Accordion';
3
+ export type { AccordionProps } from '../../lib/types/components';