@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
@@ -1,10 +1,139 @@
1
- import React, { CSSProperties, useEffect } from 'react';
2
- import { HeroProps, HeroAlignment } from '../../lib/types/components';
1
+ import React, { CSSProperties, useEffect, ReactNode } from 'react';
2
+ import { HeroProps, HeroAlignment, AtomixGlassProps } from '../../lib/types/components';
3
3
  import { useHero } from '../../lib/composables/useHero';
4
4
  import { HERO } from '../../lib/constants/components';
5
5
  import { AtomixGlass } from '../AtomixGlass/AtomixGlass';
6
6
 
7
- export const Hero: React.FC<HeroProps> = ({
7
+ // Subcomponents
8
+ export interface HeroTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {
9
+ level?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'div';
10
+ }
11
+
12
+ const HeroTitle = ({ children, className, level = 'h1', ...props }: HeroTitleProps) => {
13
+ const Tag = level as any;
14
+ return (
15
+ <Tag className={`${HERO.SELECTORS.TITLE.replace('.', '')} ${className || ''}`.trim()} {...props}>
16
+ {children}
17
+ </Tag>
18
+ );
19
+ };
20
+
21
+ const HeroSubtitle = ({ children, className, ...props }: React.HTMLAttributes<HTMLParagraphElement>) => {
22
+ return (
23
+ <p className={`${HERO.SELECTORS.SUBTITLE.replace('.', '')} ${className || ''}`.trim()} {...props}>
24
+ {children}
25
+ </p>
26
+ );
27
+ };
28
+
29
+ const HeroText = ({ children, className, ...props }: React.HTMLAttributes<HTMLParagraphElement>) => {
30
+ return (
31
+ <p className={`${HERO.SELECTORS.TEXT.replace('.', '')} ${className || ''}`.trim()} {...props}>
32
+ {children}
33
+ </p>
34
+ );
35
+ };
36
+
37
+ const HeroActions = ({ children, className, ...props }: React.HTMLAttributes<HTMLDivElement>) => {
38
+ return (
39
+ <div className={`${HERO.SELECTORS.ACTIONS.replace('.', '')} ${className || ''}`.trim()} {...props}>
40
+ {children}
41
+ </div>
42
+ );
43
+ };
44
+
45
+ export interface HeroContentProps extends React.HTMLAttributes<HTMLDivElement> {
46
+ glass?: AtomixGlassProps | boolean;
47
+ }
48
+
49
+ const HeroContent = ({ children, className, style, glass, ...props }: HeroContentProps) => {
50
+ const contentClass = `${HERO.SELECTORS.CONTENT.replace('.', '')} ${className || ''}`.trim();
51
+
52
+ if (glass) {
53
+ const glassProps = typeof glass === 'boolean' ? {
54
+ displacementScale: 60,
55
+ blurAmount: 3,
56
+ saturation: 180,
57
+ aberrationIntensity: 0,
58
+ cornerRadius: 8,
59
+ overLight: false,
60
+ mode: 'standard' as const,
61
+ } : glass;
62
+
63
+ return (
64
+ <div className={contentClass} style={style} {...props}>
65
+ <AtomixGlass {...glassProps}>
66
+ <div className="u-p-4">
67
+ {children}
68
+ </div>
69
+ </AtomixGlass>
70
+ </div>
71
+ );
72
+ }
73
+
74
+ return (
75
+ <div className={contentClass} style={style} {...props}>
76
+ {children}
77
+ </div>
78
+ );
79
+ };
80
+
81
+ export interface HeroImageProps extends React.ImgHTMLAttributes<HTMLImageElement> {
82
+ wrapperClassName?: string;
83
+ wrapperStyle?: React.CSSProperties;
84
+ }
85
+
86
+ const HeroImage = ({
87
+ src,
88
+ alt = '',
89
+ className,
90
+ wrapperClassName,
91
+ wrapperStyle,
92
+ ...props
93
+ }: HeroImageProps) => {
94
+ return (
95
+ <div
96
+ className={`${HERO.SELECTORS.IMAGE_WRAPPER.replace('.', '')} ${wrapperClassName || ''}`.trim()}
97
+ style={wrapperStyle}
98
+ >
99
+ <img
100
+ src={src}
101
+ alt={alt}
102
+ className={`${HERO.SELECTORS.IMAGE.replace('.', '')} ${className || ''}`.trim()}
103
+ {...props}
104
+ />
105
+ </div>
106
+ );
107
+ };
108
+
109
+ const HeroBackground = ({ className, style, src, children, ...props }: React.HTMLAttributes<HTMLDivElement> & { src?: string }) => {
110
+ return (
111
+ <div
112
+ className={`${HERO.SELECTORS.BG.replace('.', '')} ${className || ''}`.trim()}
113
+ style={style}
114
+ {...props}
115
+ >
116
+ {src && (
117
+ <img
118
+ src={src}
119
+ alt="Background"
120
+ className={HERO.SELECTORS.BG_IMAGE.replace('.', '')}
121
+ />
122
+ )}
123
+ {children}
124
+ </div>
125
+ );
126
+ };
127
+
128
+ export const Hero: React.FC<HeroProps> & {
129
+ Title: typeof HeroTitle;
130
+ Subtitle: typeof HeroSubtitle;
131
+ Text: typeof HeroText;
132
+ Actions: typeof HeroActions;
133
+ Content: typeof HeroContent;
134
+ Image: typeof HeroImage;
135
+ Background: typeof HeroBackground;
136
+ } = ({
8
137
  title,
9
138
  subtitle,
10
139
  text,
@@ -16,7 +145,11 @@ export const Hero: React.FC<HeroProps> = ({
16
145
  fullViewportHeight = false,
17
146
  actions,
18
147
  imageColSize = 7,
148
+ imageColClassName,
149
+ imageColStyle,
19
150
  contentColSize = 5,
151
+ contentColClassName,
152
+ contentColStyle,
20
153
  contentWidth,
21
154
  className = '',
22
155
  style,
@@ -31,7 +164,14 @@ export const Hero: React.FC<HeroProps> = ({
31
164
  muted: true,
32
165
  },
33
166
  backgroundSlider,
34
- }) => {
167
+ headingLevel = 'h1',
168
+ reverseOnMobile = false,
169
+ parts,
170
+ backgroundElement,
171
+ ...rest
172
+ }: HeroProps) => {
173
+ // Define dynamic heading tag
174
+ const HeadingTag = headingLevel;
35
175
  const {
36
176
  generateHeroClassNames,
37
177
  generateImageColClass,
@@ -44,6 +184,7 @@ export const Hero: React.FC<HeroProps> = ({
44
184
  backgroundSlider: sliderHook,
45
185
  hasBackgroundSlider,
46
186
  } = useHero({
187
+ title,
47
188
  alignment,
48
189
  imageColSize,
49
190
  contentColSize,
@@ -56,6 +197,7 @@ export const Hero: React.FC<HeroProps> = ({
56
197
  parallaxIntensity,
57
198
  videoBackground,
58
199
  backgroundSlider,
200
+ reverseOnMobile,
59
201
  });
60
202
 
61
203
  // Create custom style for hero element with content width if provided
@@ -95,16 +237,16 @@ export const Hero: React.FC<HeroProps> = ({
95
237
  let transitionClass = HERO.CLASSES.SLIDER_FADE;
96
238
  if (transition === 'slide') {
97
239
  transitionClass = HERO.CLASSES.SLIDER_SLIDE;
98
- } else if (transition === 'custom') {
99
- transitionClass = HERO.CLASSES.SLIDER_CUSTOM;
100
240
  }
101
241
 
102
242
  return (
103
243
  <div
104
244
  className={`${HERO.SELECTORS.SLIDER.replace('.', '')} ${transitionClass}`}
105
- style={{
106
- '--slider-transition-duration': `${transitionDuration}ms`,
107
- } as React.CSSProperties}
245
+ style={
246
+ {
247
+ '--slider-transition-duration': `${transitionDuration}ms`,
248
+ } as React.CSSProperties
249
+ }
108
250
  onMouseEnter={() => {
109
251
  if (backgroundSlider.autoplay?.pauseOnHover) {
110
252
  sliderHook.pauseAutoplay();
@@ -116,7 +258,7 @@ export const Hero: React.FC<HeroProps> = ({
116
258
  }
117
259
  }}
118
260
  >
119
- {slides.map((slide, index) => {
261
+ {slides.map((slide, index: number) => {
120
262
  const isActive = index === currentIndex;
121
263
  const slideRef = slideRefs[index];
122
264
  const videoRef = videoRefs[index];
@@ -125,37 +267,40 @@ export const Hero: React.FC<HeroProps> = ({
125
267
  <div
126
268
  key={index}
127
269
  ref={slideRef}
128
- className={`${HERO.SELECTORS.SLIDER_ITEM.replace('.', '')} ${
129
- isActive ? HERO.CLASSES.SLIDER_ITEM_ACTIVE : ''
130
- }`}
270
+ className={`${HERO.SELECTORS.SLIDER_ITEM.replace('.', '')} ${isActive ? HERO.CLASSES.SLIDER_ITEM_ACTIVE : ''}`}
271
+ aria-hidden={!isActive}
131
272
  >
132
- {slide.type === 'image' ? (
133
- <img
134
- src={slide.src}
135
- alt={slide.alt || 'Background slide'}
136
- className={HERO.SELECTORS.BG_IMAGE.replace('.', '')}
137
- />
138
- ) : (
273
+ {slide.type === 'video' ? (
139
274
  <video
140
275
  ref={videoRef as React.LegacyRef<HTMLVideoElement>}
141
- className="c-hero__video"
142
- autoPlay={slide.videoOptions?.autoplay !== false}
143
- loop={slide.videoOptions?.loop !== false}
144
- muted={slide.videoOptions?.muted !== false}
276
+ className={'c-hero__bg-video'}
277
+ src={slide.src}
278
+ poster={slide.videoOptions?.posterUrl || slide.alt}
279
+ muted={slide.videoOptions?.muted ?? true}
280
+ loop={slide.videoOptions?.loop ?? true}
145
281
  playsInline
146
- poster={slide.videoOptions?.posterUrl}
282
+ aria-hidden="true"
283
+ autoPlay={slide.videoOptions?.autoplay !== false}
147
284
  >
148
- <source
149
- src={slide.src}
150
- type={`video/${slide.src.split('.').pop() || 'mp4'}`}
151
- />
285
+ <source src={slide.src} type={`video/${slide.src.split('.').pop() || 'mp4'}`} />
152
286
  Your browser does not support the video tag.
153
287
  </video>
288
+ ) : (
289
+ <img
290
+ src={slide.src}
291
+ alt={slide.alt || 'Background slide'}
292
+ className={HERO.SELECTORS.BG_IMAGE.replace('.', '')}
293
+ />
154
294
  )}
155
295
  </div>
156
296
  );
157
297
  })}
158
- {showOverlay && <div className={HERO.SELECTORS.OVERLAY.replace('.', '')}></div>}
298
+ {showOverlay && (
299
+ <div
300
+ className={`${HERO.SELECTORS.OVERLAY.replace('.', '')} ${parts?.overlay?.className || ''}`.trim()}
301
+ style={parts?.overlay?.style}
302
+ ></div>
303
+ )}
159
304
  </div>
160
305
  );
161
306
  }
@@ -164,7 +309,10 @@ export const Hero: React.FC<HeroProps> = ({
164
309
  if (!hasBackgroundImage && !videoBackground) return null;
165
310
 
166
311
  return (
167
- <div className={HERO.SELECTORS.BG.replace('.', '')}>
312
+ <div
313
+ className={`${HERO.SELECTORS.BG.replace('.', '')} ${parts?.background?.className || ''}`.trim()}
314
+ style={parts?.background?.style}
315
+ >
168
316
  {backgroundImageSrc && (
169
317
  <img
170
318
  src={backgroundImageSrc}
@@ -173,18 +321,52 @@ export const Hero: React.FC<HeroProps> = ({
173
321
  />
174
322
  )}
175
323
  {renderVideoBackground()}
176
- {showOverlay && <div className={HERO.SELECTORS.OVERLAY.replace('.', '')}></div>}
324
+ {showOverlay && (
325
+ <div
326
+ className={`${HERO.SELECTORS.OVERLAY.replace('.', '')} ${parts?.overlay?.className || ''}`.trim()}
327
+ style={parts?.overlay?.style}
328
+ ></div>
329
+ )}
177
330
  </div>
178
331
  );
179
332
  };
180
333
 
181
334
  const renderContent = () => {
182
335
  const content = (
183
- <div className={HERO.SELECTORS.CONTENT.replace('.', '')}>
184
- {subtitle && <p className={HERO.SELECTORS.SUBTITLE.replace('.', '')}>{subtitle}</p>}
185
- <h1 className={HERO.SELECTORS.TITLE.replace('.', '')}>{title}</h1>
186
- {text && <p className={HERO.SELECTORS.TEXT.replace('.', '')}>{text}</p>}
187
- {actions && <div className={HERO.SELECTORS.ACTIONS.replace('.', '')}>{actions}</div>}
336
+ <div
337
+ className={`${HERO.SELECTORS.CONTENT.replace('.', '')} ${parts?.content?.className || ''}`.trim()}
338
+ style={parts?.content?.style}
339
+ >
340
+ {subtitle && (
341
+ <p
342
+ className={`${HERO.SELECTORS.SUBTITLE.replace('.', '')} ${parts?.subtitle?.className || ''}`.trim()}
343
+ style={parts?.subtitle?.style}
344
+ >
345
+ {subtitle}
346
+ </p>
347
+ )}
348
+ <HeadingTag
349
+ className={`${HERO.SELECTORS.TITLE.replace('.', '')} ${parts?.title?.className || ''}`.trim()}
350
+ style={parts?.title?.style}
351
+ >
352
+ {title}
353
+ </HeadingTag>
354
+ {text && (
355
+ <p
356
+ className={`${HERO.SELECTORS.TEXT.replace('.', '')} ${parts?.text?.className || ''}`.trim()}
357
+ style={parts?.text?.style}
358
+ >
359
+ {text}
360
+ </p>
361
+ )}
362
+ {actions && (
363
+ <div
364
+ className={`${HERO.SELECTORS.ACTIONS.replace('.', '')} ${parts?.actions?.className || ''}`.trim()}
365
+ style={parts?.actions?.style}
366
+ >
367
+ {actions}
368
+ </div>
369
+ )}
188
370
  </div>
189
371
  );
190
372
 
@@ -198,7 +380,10 @@ export const Hero: React.FC<HeroProps> = ({
198
380
  // If glass is true, use default glass props
199
381
  if (glass === true) {
200
382
  return (
201
- <div className={HERO.SELECTORS.CONTENT.replace('.', '')}>
383
+ <div
384
+ className={`${HERO.SELECTORS.CONTENT.replace('.', '')} ${parts?.content?.className || ''}`.trim()}
385
+ style={parts?.content?.style}
386
+ >
202
387
  <AtomixGlass
203
388
  displacementScale={60}
204
389
  blurAmount={3}
@@ -209,11 +394,35 @@ export const Hero: React.FC<HeroProps> = ({
209
394
  mode="standard"
210
395
  >
211
396
  <div className="u-p-4">
212
- {subtitle && <p className={HERO.SELECTORS.SUBTITLE.replace('.', '')}>{subtitle}</p>}
213
- <h1 className={HERO.SELECTORS.TITLE.replace('.', '')}>{title}</h1>
214
- {text && <p className={HERO.SELECTORS.TEXT.replace('.', '')}>{text}</p>}
397
+ {subtitle && (
398
+ <p
399
+ className={`${HERO.SELECTORS.SUBTITLE.replace('.', '')} ${parts?.subtitle?.className || ''}`.trim()}
400
+ style={parts?.subtitle?.style}
401
+ >
402
+ {subtitle}
403
+ </p>
404
+ )}
405
+ <HeadingTag
406
+ className={`${HERO.SELECTORS.TITLE.replace('.', '')} ${parts?.title?.className || ''}`.trim()}
407
+ style={parts?.title?.style}
408
+ >
409
+ {title}
410
+ </HeadingTag>
411
+ {text && (
412
+ <p
413
+ className={`${HERO.SELECTORS.TEXT.replace('.', '')} ${parts?.text?.className || ''}`.trim()}
414
+ style={parts?.text?.style}
415
+ >
416
+ {text}
417
+ </p>
418
+ )}
215
419
  {actions && (
216
- <div className={HERO.SELECTORS.ACTIONS.replace('.', '')}>{actions}</div>
420
+ <div
421
+ className={`${HERO.SELECTORS.ACTIONS.replace('.', '')} ${parts?.actions?.className || ''}`.trim()}
422
+ style={parts?.actions?.style}
423
+ >
424
+ {actions}
425
+ </div>
217
426
  )}
218
427
  </div>
219
428
  </AtomixGlass>
@@ -223,13 +432,42 @@ export const Hero: React.FC<HeroProps> = ({
223
432
 
224
433
  // If glass is an object, use provided glass props
225
434
  return (
226
- <div className={HERO.SELECTORS.CONTENT.replace('.', '')}>
435
+ <div
436
+ className={`${HERO.SELECTORS.CONTENT.replace('.', '')} ${parts?.content?.className || ''}`.trim()}
437
+ style={parts?.content?.style}
438
+ >
227
439
  <AtomixGlass {...glass}>
228
440
  <div className="u-p-4">
229
- {subtitle && <p className={HERO.SELECTORS.SUBTITLE.replace('.', '')}>{subtitle}</p>}
230
- <h1 className={HERO.SELECTORS.TITLE.replace('.', '')}>{title}</h1>
231
- {text && <p className={HERO.SELECTORS.TEXT.replace('.', '')}>{text}</p>}
232
- {actions && <div className={HERO.SELECTORS.ACTIONS.replace('.', '')}>{actions}</div>}
441
+ {subtitle && (
442
+ <p
443
+ className={`${HERO.SELECTORS.SUBTITLE.replace('.', '')} ${parts?.subtitle?.className || ''}`.trim()}
444
+ style={parts?.subtitle?.style}
445
+ >
446
+ {subtitle}
447
+ </p>
448
+ )}
449
+ <HeadingTag
450
+ className={`${HERO.SELECTORS.TITLE.replace('.', '')} ${parts?.title?.className || ''}`.trim()}
451
+ style={parts?.title?.style}
452
+ >
453
+ {title}
454
+ </HeadingTag>
455
+ {text && (
456
+ <p
457
+ className={`${HERO.SELECTORS.TEXT.replace('.', '')} ${parts?.text?.className || ''}`.trim()}
458
+ style={parts?.text?.style}
459
+ >
460
+ {text}
461
+ </p>
462
+ )}
463
+ {actions && (
464
+ <div
465
+ className={`${HERO.SELECTORS.ACTIONS.replace('.', '')} ${parts?.actions?.className || ''}`.trim()}
466
+ style={parts?.actions?.style}
467
+ >
468
+ {actions}
469
+ </div>
470
+ )}
233
471
  </div>
234
472
  </AtomixGlass>
235
473
  </div>
@@ -245,15 +483,31 @@ export const Hero: React.FC<HeroProps> = ({
245
483
 
246
484
  if (alignment === 'center') {
247
485
  return (
248
- <div className={HERO.SELECTORS.IMAGE_WRAPPER.replace('.', '')}>
249
- <img src={imageSrc} alt={imageAlt} className={HERO.SELECTORS.IMAGE.replace('.', '')} />
486
+ <div
487
+ className={`${HERO.SELECTORS.IMAGE_WRAPPER.replace('.', '')} ${imageColClassName || ''} ${parts?.imageWrapper?.className || ''}`.trim()}
488
+ style={{ ...imageColStyle, ...parts?.imageWrapper?.style }}
489
+ >
490
+ <img
491
+ src={imageSrc}
492
+ alt={imageAlt}
493
+ className={`${HERO.SELECTORS.IMAGE.replace('.', '')} ${parts?.image?.className || ''}`.trim()}
494
+ style={parts?.image?.style}
495
+ />
250
496
  </div>
251
497
  );
252
498
  }
253
499
 
254
500
  return (
255
- <div className={generateImageColClass()}>
256
- <img src={imageSrc} alt={imageAlt} className={HERO.SELECTORS.IMAGE.replace('.', '')} />
501
+ <div
502
+ className={`${generateImageColClass(imageColSize, imageColClassName)} ${parts?.imageWrapper?.className || ''}`.trim()}
503
+ style={{ ...imageColStyle, ...parts?.imageWrapper?.style }}
504
+ >
505
+ <img
506
+ src={imageSrc}
507
+ alt={imageAlt}
508
+ className={`${HERO.SELECTORS.IMAGE.replace('.', '')} ${parts?.image?.className || ''}`.trim()}
509
+ style={parts?.image?.style}
510
+ />
257
511
  </div>
258
512
  );
259
513
  };
@@ -263,7 +517,12 @@ export const Hero: React.FC<HeroProps> = ({
263
517
  if (alignment === 'left') {
264
518
  return (
265
519
  <>
266
- <div className={generateContentColClass()}>{renderContent()}</div>
520
+ <div
521
+ className={generateContentColClass(contentColSize, contentColClassName)}
522
+ style={contentColStyle}
523
+ >
524
+ {renderContent()}
525
+ </div>
267
526
  {renderForegroundImage()}
268
527
  </>
269
528
  );
@@ -273,7 +532,12 @@ export const Hero: React.FC<HeroProps> = ({
273
532
  return (
274
533
  <>
275
534
  {renderForegroundImage()}
276
- <div className={generateContentColClass()}>{renderContent()}</div>
535
+ <div
536
+ className={generateContentColClass(contentColSize, contentColClassName)}
537
+ style={contentColStyle}
538
+ >
539
+ {renderContent()}
540
+ </div>
277
541
  </>
278
542
  );
279
543
  };
@@ -281,17 +545,30 @@ export const Hero: React.FC<HeroProps> = ({
281
545
  return (
282
546
  <div
283
547
  ref={heroRef as React.LegacyRef<HTMLDivElement>}
284
- className={generateHeroClassNames(className)}
285
- style={heroStyle}
548
+ className={`${generateHeroClassNames(className)} ${parts?.root?.className || ''}`.trim()}
549
+ style={{ ...heroStyle, ...parts?.root?.style }}
286
550
  data-parallax={parallax ? 'true' : undefined}
287
551
  data-parallax-intensity={parallax ? parallaxIntensity : undefined}
552
+ {...rest}
288
553
  >
554
+ {backgroundElement}
289
555
  {renderBackground()}
290
- <div className={`${HERO.SELECTORS.CONTAINER.replace('.', '')} o-container`}>
556
+ <div
557
+ className={`${HERO.SELECTORS.CONTAINER.replace('.', '')} o-container ${parts?.container?.className || ''}`.trim()}
558
+ style={parts?.container?.style}
559
+ >
291
560
  {children ? (
292
- <div className={HERO.SELECTORS.GRID.replace('.', '')}>{children}</div>
561
+ <div
562
+ className={`${HERO.SELECTORS.GRID.replace('.', '')} ${parts?.grid?.className || ''}`.trim()}
563
+ style={parts?.grid?.style}
564
+ >
565
+ {children}
566
+ </div>
293
567
  ) : useGridLayout ? (
294
- <div className={`${HERO.SELECTORS.GRID.replace('.', '')} o-grid`}>
568
+ <div
569
+ className={`${HERO.SELECTORS.GRID.replace('.', '')} o-grid ${parts?.grid?.className || ''}`.trim()}
570
+ style={parts?.grid?.style}
571
+ >
295
572
  {renderGridContent()}
296
573
  </div>
297
574
  ) : (
@@ -305,6 +582,14 @@ export const Hero: React.FC<HeroProps> = ({
305
582
  );
306
583
  };
307
584
 
585
+ Hero.Title = HeroTitle;
586
+ Hero.Subtitle = HeroSubtitle;
587
+ Hero.Text = HeroText;
588
+ Hero.Actions = HeroActions;
589
+ Hero.Content = HeroContent;
590
+ Hero.Image = HeroImage;
591
+ Hero.Background = HeroBackground;
592
+
308
593
  export type { HeroProps };
309
594
 
310
595
  Hero.displayName = 'Hero';
@@ -1,2 +1,8 @@
1
- export { Icon, type IconProps, type IconSize, type IconWeight, type PhosphorIconsType } from './Icon';
1
+ export {
2
+ Icon,
3
+ type IconProps,
4
+ type IconSize,
5
+ type IconWeight,
6
+ type PhosphorIconsType,
7
+ } from './Icon';
2
8
  export { default } from './Icon';
@@ -0,0 +1,62 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { describe, it, expect } from 'vitest';
4
+ import { List } from './List';
5
+
6
+ describe('List Component', () => {
7
+ it('renders legacy items wrapped in li', () => {
8
+ render(
9
+ <List>
10
+ <span>Item 1</span>
11
+ <span>Item 2</span>
12
+ </List>
13
+ );
14
+
15
+ const listItems = screen.getAllByRole('listitem');
16
+ expect(listItems).toHaveLength(2);
17
+ expect(listItems[0]).toHaveTextContent('Item 1');
18
+ expect(listItems[0]).toHaveClass('c-list__item');
19
+ });
20
+
21
+ it('renders List.Item components directly', () => {
22
+ render(
23
+ <List>
24
+ <List.Item>Item 1</List.Item>
25
+ <List.Item className="custom-class">Item 2</List.Item>
26
+ </List>
27
+ );
28
+
29
+ const listItems = screen.getAllByRole('listitem');
30
+ expect(listItems).toHaveLength(2);
31
+ expect(listItems[0]).toHaveTextContent('Item 1');
32
+ expect(listItems[0]).toHaveClass('c-list__item');
33
+ expect(listItems[1]).toHaveTextContent('Item 2');
34
+ expect(listItems[1]).toHaveClass('c-list__item');
35
+ expect(listItems[1]).toHaveClass('custom-class');
36
+ });
37
+
38
+ it('renders mixed content correctly', () => {
39
+ render(
40
+ <List>
41
+ <List.Item>Compound Item</List.Item>
42
+ <span>Legacy Item</span>
43
+ </List>
44
+ );
45
+
46
+ const listItems = screen.getAllByRole('listitem');
47
+ expect(listItems).toHaveLength(2);
48
+ expect(listItems[0]).toHaveTextContent('Compound Item');
49
+ expect(listItems[1]).toHaveTextContent('Legacy Item');
50
+ });
51
+
52
+ it('renders ordered list when variant is number', () => {
53
+ render(
54
+ <List variant="number">
55
+ <List.Item>Item 1</List.Item>
56
+ </List>
57
+ );
58
+
59
+ const list = screen.getByRole('list');
60
+ expect(list.tagName).toBe('OL');
61
+ });
62
+ });