@shohojdhara/atomix 0.3.15 → 0.4.1

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 (276) hide show
  1. package/build-tools/index.d.ts +31 -30
  2. package/build-tools/package.json +4 -21
  3. package/dist/atomix.css +20234 -2027
  4. package/dist/atomix.css.map +1 -1
  5. package/dist/atomix.min.css +76 -2
  6. package/dist/atomix.min.css.map +1 -1
  7. package/dist/build-tools/index.d.ts +31 -30
  8. package/dist/build-tools/package.json +4 -21
  9. package/dist/charts.js +4 -5
  10. package/dist/charts.js.map +1 -1
  11. package/dist/core.d.ts +87 -10
  12. package/dist/core.js +673 -480
  13. package/dist/core.js.map +1 -1
  14. package/dist/forms.d.ts +15 -3
  15. package/dist/forms.js +530 -97
  16. package/dist/forms.js.map +1 -1
  17. package/dist/heavy.js +5 -6
  18. package/dist/heavy.js.map +1 -1
  19. package/dist/index.d.ts +644 -277
  20. package/dist/index.esm.js +1948 -1347
  21. package/dist/index.esm.js.map +1 -1
  22. package/dist/index.js +3333 -2728
  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.js.map +1 -1
  27. package/dist/theme.d.ts +9 -9
  28. package/dist/theme.js.map +1 -1
  29. package/package.json +2 -2
  30. package/scripts/atomix-cli.js +10 -1
  31. package/scripts/cli/__tests__/utils.test.js +6 -2
  32. package/scripts/cli/migration-tools.js +2 -2
  33. package/scripts/cli/theme-bridge.js +7 -9
  34. package/scripts/cli/utils.js +2 -1
  35. package/src/components/Accordion/Accordion.stories.tsx +72 -23
  36. package/src/components/Accordion/Accordion.test.tsx +70 -50
  37. package/src/components/Accordion/Accordion.tsx +219 -96
  38. package/src/components/Accordion/AccordionCompound.test.tsx +70 -0
  39. package/src/components/AtomixGlass/AtomixGlass.test.tsx +1 -1
  40. package/src/components/AtomixGlass/GlassFilter.tsx +9 -16
  41. package/src/components/AtomixGlass/glass-utils.ts +4 -3
  42. package/src/components/AtomixGlass/shader-utils.ts +128 -52
  43. package/src/components/AtomixGlass/stories/Playground.stories.tsx +1 -1
  44. package/src/components/AtomixGlass/stories/Shaders.stories.tsx +1 -1
  45. package/src/components/Avatar/Avatar.stories.tsx +45 -62
  46. package/src/components/Avatar/Avatar.tsx +58 -56
  47. package/src/components/Badge/Badge.stories.tsx +20 -9
  48. package/src/components/Badge/Badge.test.tsx +41 -41
  49. package/src/components/Badge/Badge.tsx +64 -62
  50. package/src/components/Block/Block.stories.tsx +14 -4
  51. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +9 -8
  52. package/src/components/Breadcrumb/Breadcrumb.tsx +173 -65
  53. package/src/components/Breadcrumb/BreadcrumbCompound.test.tsx +84 -0
  54. package/src/components/Button/Button.stories.tsx +13 -22
  55. package/src/components/Button/Button.test.tsx +97 -81
  56. package/src/components/Button/Button.tsx +46 -14
  57. package/src/components/Button/ButtonGroup.stories.tsx +37 -32
  58. package/src/components/Button/ButtonGroup.tsx +4 -15
  59. package/src/components/Callout/Callout.stories.tsx +166 -918
  60. package/src/components/Callout/Callout.tsx +196 -84
  61. package/src/components/Callout/CalloutCompound.test.tsx +72 -0
  62. package/src/components/Card/Card.stories.tsx +67 -36
  63. package/src/components/Card/Card.tsx +30 -14
  64. package/src/components/Chart/AreaChart.tsx +1 -1
  65. package/src/components/Chart/CandlestickChart.tsx +23 -16
  66. package/src/components/Chart/Chart.stories.tsx +4 -9
  67. package/src/components/Chart/Chart.tsx +40 -44
  68. package/src/components/Chart/ChartRenderer.tsx +39 -12
  69. package/src/components/Chart/ChartToolbar.tsx +21 -5
  70. package/src/components/Chart/DonutChart.tsx +1 -1
  71. package/src/components/Chart/FunnelChart.tsx +4 -1
  72. package/src/components/Chart/GaugeChart.tsx +3 -1
  73. package/src/components/Chart/HeatmapChart.tsx +50 -37
  74. package/src/components/Chart/LineChart.tsx +3 -2
  75. package/src/components/Chart/MultiAxisChart.tsx +24 -16
  76. package/src/components/Chart/RadarChart.tsx +19 -17
  77. package/src/components/Chart/ScatterChart.tsx +29 -21
  78. package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +6 -2
  79. package/src/components/ColorModeToggle/ColorModeToggle.tsx +15 -3
  80. package/src/components/Countdown/Countdown.stories.tsx +7 -7
  81. package/src/components/DataTable/DataTable.stories.tsx +43 -38
  82. package/src/components/DataTable/DataTable.test.tsx +26 -148
  83. package/src/components/DataTable/DataTable.tsx +485 -456
  84. package/src/components/DatePicker/DatePicker.stories.tsx +32 -47
  85. package/src/components/DatePicker/DatePicker.tsx +31 -26
  86. package/src/components/Dropdown/Dropdown.stories.tsx +2 -5
  87. package/src/components/Dropdown/Dropdown.tsx +425 -298
  88. package/src/components/Dropdown/DropdownCompound.test.tsx +64 -0
  89. package/src/components/EdgePanel/EdgePanel.stories.tsx +6 -19
  90. package/src/components/EdgePanel/EdgePanel.tsx +163 -113
  91. package/src/components/EdgePanel/EdgePanelCompound.test.tsx +53 -0
  92. package/src/components/Footer/Footer.stories.tsx +21 -16
  93. package/src/components/Footer/Footer.tsx +130 -128
  94. package/src/components/Footer/FooterLink.tsx +2 -2
  95. package/src/components/Form/Checkbox.test.tsx +49 -49
  96. package/src/components/Form/Checkbox.tsx +108 -100
  97. package/src/components/Form/Form.stories.tsx +2 -10
  98. package/src/components/Form/Input.stories.tsx +22 -39
  99. package/src/components/Form/Input.test.tsx +38 -44
  100. package/src/components/Form/Radio.stories.tsx +6 -12
  101. package/src/components/Form/Radio.tsx +68 -66
  102. package/src/components/Form/Select.stories.tsx +23 -0
  103. package/src/components/Form/Select.test.tsx +99 -0
  104. package/src/components/Form/Select.tsx +239 -186
  105. package/src/components/Form/SelectOption.tsx +88 -0
  106. package/src/components/Form/Textarea.test.tsx +27 -32
  107. package/src/components/Hero/Hero.stories.tsx +93 -23
  108. package/src/components/Hero/Hero.test.tsx +142 -0
  109. package/src/components/Hero/Hero.tsx +343 -58
  110. package/src/components/Icon/index.ts +7 -1
  111. package/src/components/List/List.test.tsx +62 -0
  112. package/src/components/List/List.tsx +32 -25
  113. package/src/components/List/ListItem.tsx +20 -0
  114. package/src/components/Modal/Modal.stories.tsx +67 -2
  115. package/src/components/Modal/Modal.tsx +208 -125
  116. package/src/components/Modal/ModalCompound.test.tsx +94 -0
  117. package/src/components/Navigation/Menu/MegaMenu.tsx +70 -70
  118. package/src/components/Navigation/Nav/NavDropdown.tsx +1 -5
  119. package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +128 -28
  120. package/src/components/Navigation/SideMenu/SideMenu.tsx +5 -7
  121. package/src/components/Navigation/SideMenu/SideMenuItem.tsx +4 -5
  122. package/src/components/Pagination/Pagination.stories.tsx +7 -4
  123. package/src/components/Pagination/Pagination.tsx +199 -202
  124. package/src/components/PhotoViewer/PhotoViewer.tsx +4 -1
  125. package/src/components/Popover/Popover.stories.tsx +99 -192
  126. package/src/components/Popover/Popover.tsx +41 -37
  127. package/src/components/Progress/Progress.stories.tsx +35 -44
  128. package/src/components/River/River.stories.tsx +2 -1
  129. package/src/components/SectionIntro/SectionIntro.stories.tsx +71 -71
  130. package/src/components/Slider/Slider.stories.tsx +12 -4
  131. package/src/components/Spinner/Spinner.stories.tsx +3 -1
  132. package/src/components/Spinner/Spinner.test.tsx +23 -23
  133. package/src/components/Spinner/Spinner.tsx +43 -46
  134. package/src/components/Steps/Steps.stories.tsx +8 -6
  135. package/src/components/Steps/Steps.tsx +124 -21
  136. package/src/components/Steps/StepsCompound.test.tsx +81 -0
  137. package/src/components/Tabs/Tabs.stories.tsx +12 -9
  138. package/src/components/Tabs/Tabs.tsx +230 -75
  139. package/src/components/Tabs/TabsCompound.test.tsx +64 -0
  140. package/src/components/Toggle/Toggle.stories.tsx +27 -13
  141. package/src/components/Toggle/Toggle.test.tsx +65 -70
  142. package/src/components/Toggle/Toggle.tsx +4 -1
  143. package/src/components/Tooltip/Tooltip.stories.tsx +24 -20
  144. package/src/components/Tooltip/Tooltip.tsx +104 -106
  145. package/src/components/Upload/Upload.stories.tsx +129 -127
  146. package/src/components/Upload/Upload.tsx +287 -283
  147. package/src/components/VideoPlayer/VideoPlayer.tsx +6 -1
  148. package/src/components/index.ts +13 -2
  149. package/src/layouts/Grid/Grid.stories.tsx +9 -3
  150. package/src/layouts/MasonryGrid/MasonryGrid.tsx +5 -1
  151. package/src/lib/__tests__/theme-tools.test.ts +32 -6
  152. package/src/lib/composables/index.ts +0 -4
  153. package/src/lib/composables/shared-mouse-tracker.ts +13 -14
  154. package/src/lib/composables/useAtomixGlass.ts +102 -60
  155. package/src/lib/composables/useChartExport.ts +1 -1
  156. package/src/lib/composables/useDataTable.ts +29 -17
  157. package/src/lib/composables/useHero.ts +58 -14
  158. package/src/lib/composables/useHeroBackgroundSlider.ts +2 -9
  159. package/src/lib/composables/useInput.ts +10 -8
  160. package/src/lib/composables/useSideMenu.ts +6 -5
  161. package/src/lib/composables/useTooltip.ts +1 -2
  162. package/src/lib/composables/useVideoPlayer.ts +44 -35
  163. package/src/lib/config/index.ts +154 -154
  164. package/src/lib/constants/cssVariables.ts +29 -29
  165. package/src/lib/hooks/__tests__/useComponentCustomization.test.ts +2 -6
  166. package/src/lib/hooks/index.ts +1 -1
  167. package/src/lib/hooks/useComponentCustomization.ts +11 -17
  168. package/src/lib/hooks/usePerformanceMonitor.ts +6 -7
  169. package/src/lib/patterns/__tests__/slots.test.ts +1 -1
  170. package/src/lib/patterns/index.ts +1 -1
  171. package/src/lib/patterns/slots.tsx +8 -13
  172. package/src/lib/storybook/InteractiveDemo.tsx +13 -18
  173. package/src/lib/storybook/PreviewContainer.tsx +1 -1
  174. package/src/lib/storybook/VariantsGrid.tsx +3 -7
  175. package/src/lib/storybook/index.ts +1 -1
  176. package/src/lib/theme/adapters/cssVariableMapper.ts +47 -74
  177. package/src/lib/theme/adapters/index.ts +3 -9
  178. package/src/lib/theme/adapters/themeAdapter.ts +41 -26
  179. package/src/lib/theme/config/index.ts +1 -1
  180. package/src/lib/theme/config/types.ts +2 -2
  181. package/src/lib/theme/config/validator.ts +10 -5
  182. package/src/lib/theme/constants/constants.ts +2 -2
  183. package/src/lib/theme/constants/index.ts +1 -2
  184. package/src/lib/theme/core/__tests__/createTheme.test.ts +20 -22
  185. package/src/lib/theme/core/composeTheme.ts +32 -26
  186. package/src/lib/theme/core/createTheme.ts +1 -1
  187. package/src/lib/theme/core/createThemeObject.ts +308 -301
  188. package/src/lib/theme/core/index.ts +3 -3
  189. package/src/lib/theme/devtools/CLI.ts +105 -111
  190. package/src/lib/theme/devtools/Comparator.tsx +50 -32
  191. package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +50 -48
  192. package/src/lib/theme/devtools/DesignTokensCustomizer.tsx +257 -63
  193. package/src/lib/theme/devtools/Inspector.tsx +75 -60
  194. package/src/lib/theme/devtools/LiveEditor.tsx +97 -76
  195. package/src/lib/theme/devtools/Preview.tsx +150 -106
  196. package/src/lib/theme/devtools/ThemeValidator.ts +29 -21
  197. package/src/lib/theme/devtools/index.ts +3 -9
  198. package/src/lib/theme/devtools/useHistory.ts +23 -21
  199. package/src/lib/theme/errors/errors.ts +12 -11
  200. package/src/lib/theme/errors/index.ts +2 -7
  201. package/src/lib/theme/generators/generateCSS.ts +9 -13
  202. package/src/lib/theme/generators/generateCSSNested.ts +1 -6
  203. package/src/lib/theme/generators/generateCSSVariables.ts +673 -630
  204. package/src/lib/theme/generators/index.ts +1 -4
  205. package/src/lib/theme/i18n/index.ts +1 -1
  206. package/src/lib/theme/i18n/rtl.ts +13 -13
  207. package/src/lib/theme/index.ts +7 -16
  208. package/src/lib/theme/runtime/ThemeApplicator.ts +4 -4
  209. package/src/lib/theme/runtime/ThemeContext.tsx +1 -1
  210. package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +19 -23
  211. package/src/lib/theme/runtime/ThemeProvider.tsx +230 -239
  212. package/src/lib/theme/runtime/__tests__/ThemeProvider.integration.test.tsx +1 -1
  213. package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +24 -29
  214. package/src/lib/theme/runtime/index.ts +2 -5
  215. package/src/lib/theme/runtime/useTheme.ts +18 -18
  216. package/src/lib/theme/runtime/useThemeTokens.ts +22 -22
  217. package/src/lib/theme/test/testTheme.ts +15 -16
  218. package/src/lib/theme/tokens/index.ts +2 -7
  219. package/src/lib/theme/tokens/tokens.ts +25 -24
  220. package/src/lib/theme/types.ts +428 -411
  221. package/src/lib/theme/utils/__tests__/themeValidation.test.ts +3 -3
  222. package/src/lib/theme/utils/componentTheming.ts +18 -18
  223. package/src/lib/theme/utils/domUtils.ts +277 -289
  224. package/src/lib/theme/utils/index.ts +1 -2
  225. package/src/lib/theme/utils/injectCSS.ts +10 -14
  226. package/src/lib/theme/utils/naming.ts +20 -16
  227. package/src/lib/theme/utils/themeHelpers.ts +10 -12
  228. package/src/lib/theme/utils/themeUtils.ts +85 -86
  229. package/src/lib/theme/utils/themeValidation.ts +82 -33
  230. package/src/lib/theme-tools.ts +8 -6
  231. package/src/lib/types/components.ts +180 -73
  232. package/src/lib/types/partProps.ts +1 -1
  233. package/src/lib/utils/__tests__/componentUtils.test.ts +57 -2
  234. package/src/lib/utils/__tests__/csv.test.ts +1 -1
  235. package/src/lib/utils/__tests__/themeNaming.test.ts +117 -0
  236. package/src/lib/utils/componentUtils.ts +8 -12
  237. package/src/lib/utils/csv.ts +3 -1
  238. package/src/lib/utils/dataTableExport.ts +1 -5
  239. package/src/lib/utils/fontPreloader.ts +10 -19
  240. package/src/lib/utils/icons.ts +4 -1
  241. package/src/lib/utils/index.ts +2 -6
  242. package/src/lib/utils/memoryMonitor.ts +10 -8
  243. package/src/lib/utils/themeNaming.ts +3 -3
  244. package/src/styles/01-settings/_index.scss +0 -1
  245. package/src/styles/01-settings/_settings.colors.scss +8 -8
  246. package/src/styles/01-settings/_settings.design-tokens.scss +61 -50
  247. package/src/styles/01-settings/_settings.navbar.scss +1 -1
  248. package/src/styles/01-settings/_settings.spacing.scss +3 -4
  249. package/src/styles/01-settings/_settings.tooltip.scss +1 -1
  250. package/src/styles/01-settings/_settings.typography.scss +1 -1
  251. package/src/styles/02-tools/_tools.breakpoints.scss +1 -1
  252. package/src/styles/02-tools/_tools.button.scss +51 -21
  253. package/src/styles/02-tools/_tools.utility-api.scss +36 -24
  254. package/src/styles/03-generic/_generic.root.scss +4 -3
  255. package/src/styles/06-components/_components.atomix-glass.scss +13 -9
  256. package/src/styles/06-components/_components.button.scss +16 -4
  257. package/src/styles/06-components/_components.callout.scss +27 -21
  258. package/src/styles/06-components/_components.card.scss +5 -14
  259. package/src/styles/06-components/_components.chart.scss +22 -19
  260. package/src/styles/06-components/_components.checkbox.scss +3 -1
  261. package/src/styles/06-components/_components.color-mode-toggle.scss +3 -1
  262. package/src/styles/06-components/_components.edge-panel.scss +9 -2
  263. package/src/styles/06-components/_components.footer.scss +1 -1
  264. package/src/styles/06-components/_components.side-menu.scss +5 -5
  265. package/src/styles/06-components/_components.toggle.scss +18 -0
  266. package/src/styles/06-components/_index.scss +1 -1
  267. package/src/styles/06-components/old.chart.styles.scss +0 -2
  268. package/src/styles/99-utilities/_utilities.border.scss +69 -27
  269. package/src/styles/99-utilities/_utilities.display.scss +1 -1
  270. package/src/styles/99-utilities/_utilities.opacity.scss +10 -0
  271. package/src/styles/99-utilities/_utilities.position.scss +16 -9
  272. package/src/styles/99-utilities/_utilities.scss +1 -1
  273. package/src/styles/99-utilities/_utilities.sizes.scss +47 -18
  274. package/src/styles/99-utilities/_utilities.spacing.scss +118 -66
  275. package/src/styles/99-utilities/_utilities.text-gradient.scss +30 -30
  276. package/src/styles/99-utilities/_utilities.text.scss +67 -47
@@ -167,25 +167,14 @@ export const States: Story = {
167
167
  export const WithIcons: Story = {
168
168
  render: () => (
169
169
  <div className="u-flex u-flex-column u-gap-3" style={{ width: '300px' }}>
170
- <Input
171
- placeholder="Search..."
172
- prefixIcon={<MagnifyingGlass size={18} />}
173
- />
174
- <Input
175
- placeholder="Email address"
176
- type="email"
177
- prefixIcon={<Envelope size={18} />}
178
- />
170
+ <Input placeholder="Search..." prefixIcon={<MagnifyingGlass size={18} />} />
171
+ <Input placeholder="Email address" type="email" prefixIcon={<Envelope size={18} />} />
179
172
  <Input
180
173
  placeholder="Username"
181
174
  prefixIcon={<User size={18} />}
182
175
  suffixIcon={<span style={{ color: 'green' }}>✓</span>}
183
176
  />
184
- <Input
185
- placeholder="Phone number"
186
- type="tel"
187
- prefixIcon={<Phone size={18} />}
188
- />
177
+ <Input placeholder="Phone number" type="tel" prefixIcon={<Phone size={18} />} />
189
178
  </div>
190
179
  ),
191
180
  };
@@ -201,14 +190,14 @@ export const Clearable: Story = {
201
190
  <Input
202
191
  placeholder="Type to see clear button"
203
192
  value={value}
204
- onChange={(e) => setValue(e.target.value)}
193
+ onChange={e => setValue(e.target.value)}
205
194
  clearable
206
195
  />
207
196
  <Input
208
197
  placeholder="With prefix icon"
209
198
  prefixIcon={<MagnifyingGlass size={18} />}
210
199
  value={value}
211
- onChange={(e) => setValue(e.target.value)}
200
+ onChange={e => setValue(e.target.value)}
212
201
  clearable
213
202
  />
214
203
  </div>
@@ -227,14 +216,14 @@ export const WithCounter: Story = {
227
216
  <Input
228
217
  placeholder="Type here (max 50 characters)"
229
218
  value={value}
230
- onChange={(e) => setValue(e.target.value)}
219
+ onChange={e => setValue(e.target.value)}
231
220
  maxLength={50}
232
221
  showCounter
233
222
  />
234
223
  <Input
235
224
  placeholder="With custom max count"
236
225
  value={value}
237
- onChange={(e) => setValue(e.target.value)}
226
+ onChange={e => setValue(e.target.value)}
238
227
  maxCount={100}
239
228
  showCounter
240
229
  />
@@ -255,7 +244,7 @@ export const PasswordToggle: Story = {
255
244
  type="password"
256
245
  placeholder="Enter password"
257
246
  value={password}
258
- onChange={(e) => setPassword(e.target.value)}
247
+ onChange={e => setPassword(e.target.value)}
259
248
  showPasswordToggle
260
249
  />
261
250
  <Input
@@ -263,7 +252,7 @@ export const PasswordToggle: Story = {
263
252
  placeholder="Password with prefix icon"
264
253
  prefixIcon={<Lock size={18} />}
265
254
  value={password}
266
- onChange={(e) => setPassword(e.target.value)}
255
+ onChange={e => setPassword(e.target.value)}
267
256
  showPasswordToggle
268
257
  />
269
258
  </div>
@@ -287,22 +276,18 @@ export const WithMessages: Story = {
287
276
  type="email"
288
277
  placeholder="Email address"
289
278
  value={email}
290
- onChange={(e) => setEmail(e.target.value)}
279
+ onChange={e => setEmail(e.target.value)}
291
280
  invalid={isInvalidEmail}
292
281
  errorMessage={isInvalidEmail ? 'Please enter a valid email address' : undefined}
293
- helperText={!isInvalidEmail ? 'We\'ll never share your email' : undefined}
282
+ helperText={!isInvalidEmail ? "We'll never share your email" : undefined}
294
283
  />
295
284
  <Input
296
285
  placeholder="Username"
297
286
  value={username}
298
- onChange={(e) => setUsername(e.target.value)}
287
+ onChange={e => setUsername(e.target.value)}
299
288
  helperText="Choose a unique username"
300
289
  />
301
- <Input
302
- placeholder="Required field"
303
- required
304
- helperText="This field is required"
305
- />
290
+ <Input placeholder="Required field" required helperText="This field is required" />
306
291
  </div>
307
292
  );
308
293
  },
@@ -331,7 +316,8 @@ export const Comprehensive: Story = {
331
316
  parameters: {
332
317
  docs: {
333
318
  description: {
334
- story: 'A comprehensive example demonstrating multiple input features including icons, clearable functionality, password toggle, character counter, and helper text in a form-like layout.',
319
+ story:
320
+ 'A comprehensive example demonstrating multiple input features including icons, clearable functionality, password toggle, character counter, and helper text in a form-like layout.',
335
321
  },
336
322
  },
337
323
  },
@@ -343,13 +329,11 @@ export const Comprehensive: Story = {
343
329
  return (
344
330
  <div className="u-flex u-flex-column u-gap-4" style={{ width: '400px' }}>
345
331
  <div>
346
- <label style={{ display: 'block', marginBottom: '0.5rem', color: 'white' }}>
347
- Search
348
- </label>
332
+ <label style={{ display: 'block', marginBottom: '0.5rem', color: 'white' }}>Search</label>
349
333
  <Input
350
334
  placeholder="Search products..."
351
335
  value={search}
352
- onChange={(e) => setSearch(e.target.value)}
336
+ onChange={e => setSearch(e.target.value)}
353
337
  prefixIcon={<MagnifyingGlass size={18} />}
354
338
  clearable
355
339
  fullWidth
@@ -364,7 +348,7 @@ export const Comprehensive: Story = {
364
348
  type="password"
365
349
  placeholder="Enter your password"
366
350
  value={password}
367
- onChange={(e) => setPassword(e.target.value)}
351
+ onChange={e => setPassword(e.target.value)}
368
352
  prefixIcon={<Lock size={18} />}
369
353
  showPasswordToggle
370
354
  fullWidth
@@ -373,13 +357,11 @@ export const Comprehensive: Story = {
373
357
  </div>
374
358
 
375
359
  <div>
376
- <label style={{ display: 'block', marginBottom: '0.5rem', color: 'white' }}>
377
- Bio
378
- </label>
360
+ <label style={{ display: 'block', marginBottom: '0.5rem', color: 'white' }}>Bio</label>
379
361
  <Input
380
362
  placeholder="Tell us about yourself"
381
363
  value={bio}
382
- onChange={(e) => setBio(e.target.value)}
364
+ onChange={e => setBio(e.target.value)}
383
365
  maxLength={200}
384
366
  showCounter
385
367
  fullWidth
@@ -465,7 +447,8 @@ export const GlassShowcase: Story = {
465
447
  parameters: {
466
448
  docs: {
467
449
  description: {
468
- story: 'Demonstrates glass morphism effects on inputs with different modes and configurations, showing how inputs look over colorful backgrounds.',
450
+ story:
451
+ 'Demonstrates glass morphism effects on inputs with different modes and configurations, showing how inputs look over colorful backgrounds.',
469
452
  },
470
453
  },
471
454
  },
@@ -4,56 +4,50 @@ import { Input } from './Input';
4
4
 
5
5
  // Mock AtomixGlass component
6
6
  vi.mock('../AtomixGlass/AtomixGlass', () => ({
7
- AtomixGlass: ({ children, ...props }: any) => (
8
- <div data-testid="atomix-glass" data-glass-props={JSON.stringify(props)}>
9
- {children}
10
- </div>
11
- ),
7
+ AtomixGlass: ({ children, ...props }: any) => (
8
+ <div data-testid="atomix-glass" data-glass-props={JSON.stringify(props)}>
9
+ {children}
10
+ </div>
11
+ ),
12
12
  }));
13
13
 
14
14
  describe('Input Component', () => {
15
- it('renders correctly', () => {
16
- render(<Input placeholder="Test Input" />);
17
- expect(screen.getByPlaceholderText('Test Input')).toBeInTheDocument();
18
- });
15
+ it('renders correctly', () => {
16
+ render(<Input placeholder="Test Input" />);
17
+ expect(screen.getByPlaceholderText('Test Input')).toBeInTheDocument();
18
+ });
19
19
 
20
- it('handles controlled value', () => {
21
- render(<Input value="Controlled Value" onChange={() => { }} />);
22
- const input = screen.getByDisplayValue('Controlled Value');
23
- expect(input).toBeInTheDocument();
24
- expect(input).toHaveValue('Controlled Value');
25
- });
20
+ it('handles controlled value', () => {
21
+ render(<Input value="Controlled Value" onChange={() => {}} />);
22
+ const input = screen.getByDisplayValue('Controlled Value');
23
+ expect(input).toBeInTheDocument();
24
+ expect(input).toHaveValue('Controlled Value');
25
+ });
26
26
 
27
- it('handles uncontrolled defaultValue', () => {
28
- render(<Input defaultValue="Default Value" />);
29
- const input = screen.getByDisplayValue('Default Value');
30
- expect(input).toBeInTheDocument();
31
- expect(input).toHaveValue('Default Value');
32
- });
27
+ it('handles uncontrolled defaultValue', () => {
28
+ render(<Input defaultValue="Default Value" />);
29
+ const input = screen.getByDisplayValue('Default Value');
30
+ expect(input).toBeInTheDocument();
31
+ expect(input).toHaveValue('Default Value');
32
+ });
33
33
 
34
- it('calls onChange when typing', () => {
35
- const handleChange = vi.fn();
36
- render(<Input onChange={handleChange} />);
37
- const input = screen.getByRole('textbox');
38
- fireEvent.change(input, { target: { value: 'New Value' } });
39
- expect(handleChange).toHaveBeenCalledTimes(1);
40
- });
34
+ it('calls onChange when typing', () => {
35
+ const handleChange = vi.fn();
36
+ render(<Input onChange={handleChange} />);
37
+ const input = screen.getByRole('textbox');
38
+ fireEvent.change(input, { target: { value: 'New Value' } });
39
+ expect(handleChange).toHaveBeenCalledTimes(1);
40
+ });
41
41
 
42
- it('applies accessibility attributes', () => {
43
- render(
44
- <Input
45
- aria-label="Accessible Label"
46
- aria-describedby="description-id"
47
- invalid
48
- />
49
- );
50
- const input = screen.getByLabelText('Accessible Label');
51
- expect(input).toHaveAttribute('aria-describedby', 'description-id');
52
- expect(input).toHaveAttribute('aria-invalid', 'true');
53
- });
42
+ it('applies accessibility attributes', () => {
43
+ render(<Input aria-label="Accessible Label" aria-describedby="description-id" invalid />);
44
+ const input = screen.getByLabelText('Accessible Label');
45
+ expect(input).toHaveAttribute('aria-describedby', 'description-id');
46
+ expect(input).toHaveAttribute('aria-invalid', 'true');
47
+ });
54
48
 
55
- it('renders as glass when enabled', () => {
56
- render(<Input glass placeholder="Glass Input" />);
57
- expect(screen.getByTestId('atomix-glass')).toBeInTheDocument();
58
- });
49
+ it('renders as glass when enabled', () => {
50
+ render(<Input glass placeholder="Glass Input" />);
51
+ expect(screen.getByTestId('atomix-glass')).toBeInTheDocument();
52
+ });
59
53
  });
@@ -256,20 +256,14 @@ export const States: Story = {
256
256
  checked={selectedValue === 'checked'}
257
257
  onChange={() => setSelectedValue('checked')}
258
258
  />
259
- <Radio
260
- label="Disabled radio"
261
- name="states"
262
- value="disabled"
263
- disabled
264
- onChange={() => { }}
265
- />
259
+ <Radio label="Disabled radio" name="states" value="disabled" disabled onChange={() => {}} />
266
260
  <Radio
267
261
  label="Disabled and checked radio"
268
262
  name="states"
269
263
  value="disabledChecked"
270
264
  disabled
271
265
  checked
272
- onChange={() => { }}
266
+ onChange={() => {}}
273
267
  />
274
268
  <Radio
275
269
  label="Valid radio"
@@ -298,7 +292,7 @@ export const WithoutLabel: Story = {
298
292
  name: 'noLabel',
299
293
  value: 'noLabel',
300
294
  'aria-label': 'Radio button without visible label',
301
- onChange: () => { },
295
+ onChange: () => {},
302
296
  },
303
297
  };
304
298
 
@@ -309,7 +303,7 @@ export const Glass: Story = {
309
303
  name: 'glass',
310
304
  value: 'glass',
311
305
  glass: true,
312
- onChange: () => { },
306
+ onChange: () => {},
313
307
  },
314
308
  render: (args: any) => (
315
309
  <div
@@ -341,7 +335,7 @@ export const GlassCustom: Story = {
341
335
  aberrationIntensity: 0.8,
342
336
  cornerRadius: 12,
343
337
  } as any,
344
- onChange: () => { },
338
+ onChange: () => {},
345
339
  },
346
340
  render: (args: any) => (
347
341
  <div
@@ -520,4 +514,4 @@ export const GlassStates: Story = {
520
514
  </div>
521
515
  );
522
516
  },
523
- };
517
+ };
@@ -6,78 +6,80 @@ import { AtomixGlass } from '../AtomixGlass/AtomixGlass';
6
6
  /**
7
7
  * Radio - A component for radio button inputs
8
8
  */
9
- export const Radio: React.FC<RadioProps> = memo(({
10
- label,
11
- checked = false,
12
- onChange,
13
- className = '',
14
- style,
15
- disabled = false,
16
- required = false,
17
- id,
18
- name,
19
- value,
20
- invalid = false,
21
- valid = false,
22
- 'aria-label': ariaLabel,
23
- 'aria-describedby': ariaDescribedBy,
24
- glass,
25
- }) => {
26
- const { generateRadioClass } = useRadio({
27
- disabled,
28
- invalid,
29
- valid,
30
- });
9
+ export const Radio: React.FC<RadioProps> = memo(
10
+ ({
11
+ label,
12
+ checked = false,
13
+ onChange,
14
+ className = '',
15
+ style,
16
+ disabled = false,
17
+ required = false,
18
+ id,
19
+ name,
20
+ value,
21
+ invalid = false,
22
+ valid = false,
23
+ 'aria-label': ariaLabel,
24
+ 'aria-describedby': ariaDescribedBy,
25
+ glass,
26
+ }) => {
27
+ const { generateRadioClass } = useRadio({
28
+ disabled,
29
+ invalid,
30
+ valid,
31
+ });
31
32
 
32
- const radioClass = generateRadioClass({
33
- className: `${className} ${glass ? 'c-radio--glass' : ''}`.trim(),
34
- disabled,
35
- invalid,
36
- valid,
37
- });
33
+ const radioClass = generateRadioClass({
34
+ className: `${className} ${glass ? 'c-radio--glass' : ''}`.trim(),
35
+ disabled,
36
+ invalid,
37
+ valid,
38
+ });
38
39
 
39
- const radioContent = (
40
- <div className={radioClass} style={style}>
41
- <input
42
- type="radio"
43
- className="c-radio__input"
44
- checked={checked}
45
- onChange={onChange}
46
- disabled={disabled}
47
- required={required}
48
- id={id}
49
- name={name}
50
- value={value}
51
- aria-label={!label ? ariaLabel : undefined}
52
- aria-describedby={ariaDescribedBy}
53
- aria-invalid={invalid}
54
- />
55
- {label && (
56
- <label className="c-radio__label" htmlFor={id}>
57
- {label}
58
- </label>
59
- )}
60
- </div>
61
- );
40
+ const radioContent = (
41
+ <div className={radioClass} style={style}>
42
+ <input
43
+ type="radio"
44
+ className="c-radio__input"
45
+ checked={checked}
46
+ onChange={onChange}
47
+ disabled={disabled}
48
+ required={required}
49
+ id={id}
50
+ name={name}
51
+ value={value}
52
+ aria-label={!label ? ariaLabel : undefined}
53
+ aria-describedby={ariaDescribedBy}
54
+ aria-invalid={invalid}
55
+ />
56
+ {label && (
57
+ <label className="c-radio__label" htmlFor={id}>
58
+ {label}
59
+ </label>
60
+ )}
61
+ </div>
62
+ );
62
63
 
63
- if (glass) {
64
- // Default glass settings for radio buttons
65
- const defaultGlassProps = {
66
- displacementScale: 40,
67
- blurAmount: 1,
68
- saturation: 160,
69
- aberrationIntensity: 0.3,
70
- cornerRadius: 6,
71
- mode: 'shader' as const,
72
- };
64
+ if (glass) {
65
+ // Default glass settings for radio buttons
66
+ const defaultGlassProps = {
67
+ displacementScale: 40,
68
+ blurAmount: 1,
69
+ saturation: 160,
70
+ aberrationIntensity: 0.3,
71
+ cornerRadius: 6,
72
+ mode: 'shader' as const,
73
+ };
73
74
 
74
- const glassProps = glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
75
+ const glassProps = glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
75
76
 
76
- return <AtomixGlass {...glassProps}>{radioContent}</AtomixGlass>;
77
- }
77
+ return <AtomixGlass {...glassProps}>{radioContent}</AtomixGlass>;
78
+ }
78
79
 
79
- return radioContent;
80
- });
80
+ return radioContent;
81
+ }
82
+ );
81
83
 
82
84
  export type { RadioProps };
83
85
 
@@ -256,6 +256,29 @@ export const Sizes: Story = {
256
256
  ),
257
257
  };
258
258
 
259
+ // Compound usage
260
+ export const Compound: Story = {
261
+ render: () => (
262
+ <div style={{ width: '300px' }}>
263
+ <Select placeholder="Select a framework">
264
+ <Select.Option value="react">React</Select.Option>
265
+ <Select.Option value="vue">Vue</Select.Option>
266
+ <Select.Option value="angular">Angular</Select.Option>
267
+ <Select.Option value="svelte" disabled>
268
+ Svelte (Disabled)
269
+ </Select.Option>
270
+ </Select>
271
+ </div>
272
+ ),
273
+ parameters: {
274
+ docs: {
275
+ description: {
276
+ story: 'Select component using Compound Component Pattern.',
277
+ },
278
+ },
279
+ },
280
+ };
281
+
259
282
  // Select states
260
283
  export const States: Story = {
261
284
  args: {
@@ -0,0 +1,99 @@
1
+ import React from 'react';
2
+ import { render, screen, fireEvent, waitFor } from '@testing-library/react';
3
+ import { describe, it, expect, vi } from 'vitest';
4
+ import { Select } from './Select';
5
+
6
+ describe('Select Component', () => {
7
+ it('renders legacy options correctly', () => {
8
+ const options = [
9
+ { value: '1', label: 'Option 1' },
10
+ { value: '2', label: 'Option 2' },
11
+ ];
12
+ render(<Select options={options} value="" onChange={() => {}} />);
13
+
14
+ // Check custom UI items
15
+ const items = document.querySelectorAll('.c-select__item');
16
+ expect(items).toHaveLength(2);
17
+ expect(items[0]).toHaveTextContent('Option 1');
18
+ expect(items[1]).toHaveTextContent('Option 2');
19
+
20
+ // Check native select options
21
+ const select = document.querySelector('select');
22
+ expect(select).not.toBeNull();
23
+ expect(select?.options).toHaveLength(3); // Placeholder + 2
24
+ expect(select?.options[1].value).toBe('1');
25
+ expect(select?.options[2].value).toBe('2');
26
+ });
27
+
28
+ it('renders compound options correctly', async () => {
29
+ render(
30
+ <Select value="" onChange={() => {}}>
31
+ <Select.Option value="1">Compound Option 1</Select.Option>
32
+ <Select.Option value="2">Compound Option 2</Select.Option>
33
+ </Select>
34
+ );
35
+
36
+ // Check custom UI items
37
+ const items = document.querySelectorAll('.c-select__item');
38
+ expect(items).toHaveLength(2);
39
+ expect(items[0]).toHaveTextContent('Compound Option 1');
40
+ expect(items[1]).toHaveTextContent('Compound Option 2');
41
+
42
+ // Check native select options
43
+ await waitFor(() => {
44
+ const select = document.querySelector('select');
45
+ expect(select).not.toBeNull();
46
+ expect(select?.options).toHaveLength(3); // Placeholder + 2
47
+ expect(select?.options[1].value).toBe('1');
48
+ expect(select?.options[2].value).toBe('2');
49
+ });
50
+ });
51
+
52
+ it('handles selection in legacy mode', () => {
53
+ const handleChange = vi.fn();
54
+ const options = [
55
+ { value: '1', label: 'Option 1' },
56
+ { value: '2', label: 'Option 2' },
57
+ ];
58
+ render(<Select options={options} value="" onChange={handleChange} />);
59
+
60
+ // Open dropdown
61
+ const trigger = document.querySelector('.c-select__selected');
62
+ fireEvent.click(trigger!);
63
+
64
+ // Click item
65
+ const item = document.querySelector('.c-select__item[data-value="1"]');
66
+ fireEvent.click(item!);
67
+
68
+ expect(handleChange).toHaveBeenCalled();
69
+ // Check event value
70
+ expect(handleChange.mock.calls[0][0].target.value).toBe('1');
71
+ });
72
+
73
+ it('handles selection in compound mode', async () => {
74
+ const handleChange = vi.fn();
75
+ render(
76
+ <Select value="" onChange={handleChange}>
77
+ <Select.Option value="1">Option 1</Select.Option>
78
+ <Select.Option value="2">Option 2</Select.Option>
79
+ </Select>
80
+ );
81
+
82
+ // Wait for options to be registered
83
+ await waitFor(() => {
84
+ const select = document.querySelector('select');
85
+ expect(select?.options).toHaveLength(3);
86
+ });
87
+
88
+ // Open dropdown
89
+ const trigger = document.querySelector('.c-select__selected');
90
+ fireEvent.click(trigger!);
91
+
92
+ // Click item
93
+ const item = document.querySelector('.c-select__item[data-value="2"]');
94
+ fireEvent.click(item!);
95
+
96
+ expect(handleChange).toHaveBeenCalled();
97
+ expect(handleChange.mock.calls[0][0].target.value).toBe('2');
98
+ });
99
+ });