@shohojdhara/atomix 0.3.15 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. package/build-tools/index.d.ts +31 -30
  2. package/build-tools/package.json +4 -21
  3. package/dist/atomix.css +20924 -2611
  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.map +1 -1
  10. package/dist/core.js.map +1 -1
  11. package/dist/forms.js.map +1 -1
  12. package/dist/heavy.js.map +1 -1
  13. package/dist/index.d.ts +144 -18
  14. package/dist/index.esm.js +110 -55
  15. package/dist/index.esm.js.map +1 -1
  16. package/dist/index.js +110 -55
  17. package/dist/index.js.map +1 -1
  18. package/dist/index.min.js +1 -1
  19. package/dist/index.min.js.map +1 -1
  20. package/dist/layout.js.map +1 -1
  21. package/dist/theme.d.ts +9 -9
  22. package/dist/theme.js.map +1 -1
  23. package/package.json +1 -1
  24. package/src/components/Accordion/Accordion.stories.tsx +32 -23
  25. package/src/components/Accordion/Accordion.test.tsx +70 -50
  26. package/src/components/Accordion/Accordion.tsx +99 -94
  27. package/src/components/AtomixGlass/AtomixGlass.test.tsx +1 -1
  28. package/src/components/AtomixGlass/GlassFilter.tsx +9 -16
  29. package/src/components/AtomixGlass/glass-utils.ts +4 -3
  30. package/src/components/AtomixGlass/shader-utils.ts +128 -52
  31. package/src/components/AtomixGlass/stories/Playground.stories.tsx +1 -1
  32. package/src/components/AtomixGlass/stories/Shaders.stories.tsx +1 -1
  33. package/src/components/Avatar/Avatar.stories.tsx +45 -62
  34. package/src/components/Avatar/Avatar.tsx +58 -56
  35. package/src/components/Badge/Badge.stories.tsx +20 -9
  36. package/src/components/Badge/Badge.test.tsx +41 -41
  37. package/src/components/Badge/Badge.tsx +64 -62
  38. package/src/components/Block/Block.stories.tsx +14 -4
  39. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +9 -8
  40. package/src/components/Breadcrumb/Breadcrumb.tsx +62 -60
  41. package/src/components/Button/Button.stories.tsx +13 -22
  42. package/src/components/Button/Button.test.tsx +97 -81
  43. package/src/components/Button/Button.tsx +46 -14
  44. package/src/components/Button/ButtonGroup.stories.tsx +37 -32
  45. package/src/components/Button/ButtonGroup.tsx +4 -15
  46. package/src/components/Callout/Callout.stories.tsx +109 -16
  47. package/src/components/Card/Card.stories.tsx +67 -36
  48. package/src/components/Card/Card.tsx +30 -14
  49. package/src/components/Chart/AreaChart.tsx +1 -1
  50. package/src/components/Chart/CandlestickChart.tsx +23 -16
  51. package/src/components/Chart/Chart.stories.tsx +4 -9
  52. package/src/components/Chart/Chart.tsx +40 -44
  53. package/src/components/Chart/ChartRenderer.tsx +39 -12
  54. package/src/components/Chart/ChartToolbar.tsx +21 -5
  55. package/src/components/Chart/DonutChart.tsx +1 -1
  56. package/src/components/Chart/FunnelChart.tsx +4 -1
  57. package/src/components/Chart/GaugeChart.tsx +3 -1
  58. package/src/components/Chart/HeatmapChart.tsx +50 -37
  59. package/src/components/Chart/LineChart.tsx +3 -2
  60. package/src/components/Chart/MultiAxisChart.tsx +24 -16
  61. package/src/components/Chart/RadarChart.tsx +19 -17
  62. package/src/components/Chart/ScatterChart.tsx +29 -21
  63. package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +6 -2
  64. package/src/components/ColorModeToggle/ColorModeToggle.tsx +15 -3
  65. package/src/components/Countdown/Countdown.stories.tsx +7 -7
  66. package/src/components/DataTable/DataTable.stories.tsx +43 -38
  67. package/src/components/DataTable/DataTable.test.tsx +26 -148
  68. package/src/components/DataTable/DataTable.tsx +485 -456
  69. package/src/components/DatePicker/DatePicker.stories.tsx +32 -47
  70. package/src/components/DatePicker/DatePicker.tsx +31 -26
  71. package/src/components/Dropdown/Dropdown.stories.tsx +2 -5
  72. package/src/components/Dropdown/Dropdown.tsx +313 -299
  73. package/src/components/EdgePanel/EdgePanel.stories.tsx +6 -19
  74. package/src/components/EdgePanel/EdgePanel.tsx +1 -3
  75. package/src/components/Footer/Footer.stories.tsx +21 -16
  76. package/src/components/Footer/Footer.tsx +130 -128
  77. package/src/components/Footer/FooterLink.tsx +2 -2
  78. package/src/components/Form/Checkbox.test.tsx +49 -49
  79. package/src/components/Form/Checkbox.tsx +108 -100
  80. package/src/components/Form/Form.stories.tsx +2 -10
  81. package/src/components/Form/Input.stories.tsx +22 -39
  82. package/src/components/Form/Input.test.tsx +38 -44
  83. package/src/components/Form/Radio.stories.tsx +6 -12
  84. package/src/components/Form/Radio.tsx +68 -66
  85. package/src/components/Form/Select.tsx +184 -182
  86. package/src/components/Form/Textarea.test.tsx +27 -32
  87. package/src/components/Hero/Hero.stories.tsx +56 -23
  88. package/src/components/Hero/Hero.tsx +201 -55
  89. package/src/components/Icon/index.ts +7 -1
  90. package/src/components/List/List.tsx +19 -23
  91. package/src/components/Modal/Modal.stories.tsx +2 -1
  92. package/src/components/Modal/Modal.tsx +130 -127
  93. package/src/components/Navigation/Menu/MegaMenu.tsx +70 -70
  94. package/src/components/Navigation/Nav/NavDropdown.tsx +1 -5
  95. package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +128 -28
  96. package/src/components/Navigation/SideMenu/SideMenu.tsx +5 -7
  97. package/src/components/Navigation/SideMenu/SideMenuItem.tsx +4 -5
  98. package/src/components/Pagination/Pagination.stories.tsx +7 -4
  99. package/src/components/Pagination/Pagination.tsx +199 -202
  100. package/src/components/PhotoViewer/PhotoViewer.tsx +4 -1
  101. package/src/components/Popover/Popover.stories.tsx +99 -192
  102. package/src/components/Popover/Popover.tsx +41 -37
  103. package/src/components/Progress/Progress.stories.tsx +35 -44
  104. package/src/components/River/River.stories.tsx +2 -1
  105. package/src/components/SectionIntro/SectionIntro.stories.tsx +71 -71
  106. package/src/components/Slider/Slider.stories.tsx +12 -4
  107. package/src/components/Spinner/Spinner.stories.tsx +3 -1
  108. package/src/components/Spinner/Spinner.test.tsx +23 -23
  109. package/src/components/Spinner/Spinner.tsx +43 -46
  110. package/src/components/Steps/Steps.stories.tsx +8 -6
  111. package/src/components/Tabs/Tabs.stories.tsx +12 -9
  112. package/src/components/Tabs/Tabs.tsx +74 -72
  113. package/src/components/Toggle/Toggle.stories.tsx +27 -13
  114. package/src/components/Toggle/Toggle.test.tsx +65 -70
  115. package/src/components/Toggle/Toggle.tsx +4 -1
  116. package/src/components/Tooltip/Tooltip.stories.tsx +24 -20
  117. package/src/components/Tooltip/Tooltip.tsx +104 -106
  118. package/src/components/Upload/Upload.stories.tsx +129 -127
  119. package/src/components/Upload/Upload.tsx +287 -283
  120. package/src/components/VideoPlayer/VideoPlayer.tsx +6 -1
  121. package/src/components/index.ts +13 -2
  122. package/src/layouts/Grid/Grid.stories.tsx +9 -3
  123. package/src/layouts/MasonryGrid/MasonryGrid.tsx +5 -1
  124. package/src/lib/__tests__/theme-tools.test.ts +32 -6
  125. package/src/lib/composables/shared-mouse-tracker.ts +13 -14
  126. package/src/lib/composables/useAtomixGlass.ts +106 -49
  127. package/src/lib/composables/useChartExport.ts +1 -1
  128. package/src/lib/composables/useDataTable.ts +29 -17
  129. package/src/lib/composables/useHero.ts +58 -14
  130. package/src/lib/composables/useHeroBackgroundSlider.ts +2 -9
  131. package/src/lib/composables/useInput.ts +10 -8
  132. package/src/lib/composables/useSideMenu.ts +6 -5
  133. package/src/lib/composables/useTooltip.ts +1 -2
  134. package/src/lib/composables/useVideoPlayer.ts +44 -35
  135. package/src/lib/config/index.ts +154 -154
  136. package/src/lib/constants/cssVariables.ts +29 -29
  137. package/src/lib/hooks/__tests__/useComponentCustomization.test.ts +2 -6
  138. package/src/lib/hooks/index.ts +1 -1
  139. package/src/lib/hooks/useComponentCustomization.ts +11 -17
  140. package/src/lib/hooks/usePerformanceMonitor.ts +6 -7
  141. package/src/lib/patterns/__tests__/slots.test.ts +1 -1
  142. package/src/lib/patterns/index.ts +1 -1
  143. package/src/lib/patterns/slots.tsx +8 -13
  144. package/src/lib/storybook/InteractiveDemo.tsx +13 -18
  145. package/src/lib/storybook/PreviewContainer.tsx +1 -1
  146. package/src/lib/storybook/VariantsGrid.tsx +3 -7
  147. package/src/lib/storybook/index.ts +1 -1
  148. package/src/lib/theme/adapters/cssVariableMapper.ts +47 -74
  149. package/src/lib/theme/adapters/index.ts +3 -9
  150. package/src/lib/theme/adapters/themeAdapter.ts +41 -26
  151. package/src/lib/theme/config/index.ts +1 -1
  152. package/src/lib/theme/config/types.ts +2 -2
  153. package/src/lib/theme/config/validator.ts +10 -5
  154. package/src/lib/theme/constants/constants.ts +2 -2
  155. package/src/lib/theme/constants/index.ts +1 -2
  156. package/src/lib/theme/core/__tests__/createTheme.test.ts +20 -22
  157. package/src/lib/theme/core/composeTheme.ts +32 -26
  158. package/src/lib/theme/core/createTheme.ts +1 -1
  159. package/src/lib/theme/core/createThemeObject.ts +308 -301
  160. package/src/lib/theme/core/index.ts +3 -3
  161. package/src/lib/theme/devtools/CLI.ts +106 -104
  162. package/src/lib/theme/devtools/Comparator.tsx +50 -32
  163. package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +50 -48
  164. package/src/lib/theme/devtools/DesignTokensCustomizer.tsx +257 -63
  165. package/src/lib/theme/devtools/Inspector.tsx +75 -60
  166. package/src/lib/theme/devtools/LiveEditor.tsx +97 -76
  167. package/src/lib/theme/devtools/Preview.tsx +150 -106
  168. package/src/lib/theme/devtools/ThemeValidator.ts +29 -21
  169. package/src/lib/theme/devtools/index.ts +3 -9
  170. package/src/lib/theme/devtools/useHistory.ts +23 -21
  171. package/src/lib/theme/errors/errors.ts +12 -11
  172. package/src/lib/theme/errors/index.ts +2 -7
  173. package/src/lib/theme/generators/generateCSS.ts +9 -13
  174. package/src/lib/theme/generators/generateCSSNested.ts +1 -6
  175. package/src/lib/theme/generators/generateCSSVariables.ts +673 -630
  176. package/src/lib/theme/generators/index.ts +1 -4
  177. package/src/lib/theme/i18n/index.ts +1 -1
  178. package/src/lib/theme/i18n/rtl.ts +13 -13
  179. package/src/lib/theme/index.ts +7 -16
  180. package/src/lib/theme/runtime/ThemeApplicator.ts +4 -4
  181. package/src/lib/theme/runtime/ThemeContext.tsx +1 -1
  182. package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +19 -23
  183. package/src/lib/theme/runtime/ThemeProvider.tsx +230 -239
  184. package/src/lib/theme/runtime/__tests__/ThemeProvider.integration.test.tsx +1 -1
  185. package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +24 -29
  186. package/src/lib/theme/runtime/index.ts +2 -5
  187. package/src/lib/theme/runtime/useTheme.ts +18 -18
  188. package/src/lib/theme/runtime/useThemeTokens.ts +22 -22
  189. package/src/lib/theme/test/testTheme.ts +15 -16
  190. package/src/lib/theme/tokens/index.ts +2 -7
  191. package/src/lib/theme/tokens/tokens.ts +25 -24
  192. package/src/lib/theme/types.ts +428 -411
  193. package/src/lib/theme/utils/__tests__/themeValidation.test.ts +3 -3
  194. package/src/lib/theme/utils/componentTheming.ts +18 -18
  195. package/src/lib/theme/utils/domUtils.ts +277 -289
  196. package/src/lib/theme/utils/index.ts +1 -2
  197. package/src/lib/theme/utils/injectCSS.ts +10 -14
  198. package/src/lib/theme/utils/naming.ts +20 -16
  199. package/src/lib/theme/utils/themeHelpers.ts +10 -12
  200. package/src/lib/theme/utils/themeUtils.ts +85 -86
  201. package/src/lib/theme/utils/themeValidation.ts +82 -33
  202. package/src/lib/theme-tools.ts +8 -6
  203. package/src/lib/types/components.ts +172 -71
  204. package/src/lib/types/partProps.ts +1 -1
  205. package/src/lib/utils/__tests__/csv.test.ts +1 -1
  206. package/src/lib/utils/componentUtils.ts +8 -12
  207. package/src/lib/utils/csv.ts +3 -1
  208. package/src/lib/utils/dataTableExport.ts +1 -5
  209. package/src/lib/utils/fontPreloader.ts +10 -19
  210. package/src/lib/utils/icons.ts +4 -1
  211. package/src/lib/utils/index.ts +2 -6
  212. package/src/lib/utils/memoryMonitor.ts +10 -8
  213. package/src/lib/utils/themeNaming.ts +2 -2
  214. package/src/styles/01-settings/_index.scss +0 -1
  215. package/src/styles/01-settings/_settings.colors.scss +8 -8
  216. package/src/styles/01-settings/_settings.design-tokens.scss +61 -50
  217. package/src/styles/01-settings/_settings.navbar.scss +1 -1
  218. package/src/styles/01-settings/_settings.spacing.scss +3 -4
  219. package/src/styles/01-settings/_settings.tooltip.scss +1 -1
  220. package/src/styles/01-settings/_settings.typography.scss +1 -1
  221. package/src/styles/02-tools/_tools.button.scss +51 -21
  222. package/src/styles/02-tools/_tools.utility-api.scss +30 -18
  223. package/src/styles/03-generic/_generic.root.scss +4 -3
  224. package/src/styles/06-components/_components.atomix-glass.scss +13 -9
  225. package/src/styles/06-components/_components.button.scss +16 -4
  226. package/src/styles/06-components/_components.callout.scss +27 -21
  227. package/src/styles/06-components/_components.card.scss +5 -14
  228. package/src/styles/06-components/_components.chart.scss +22 -19
  229. package/src/styles/06-components/_components.checkbox.scss +3 -1
  230. package/src/styles/06-components/_components.color-mode-toggle.scss +3 -1
  231. package/src/styles/06-components/_components.edge-panel.scss +9 -2
  232. package/src/styles/06-components/_components.footer.scss +1 -1
  233. package/src/styles/06-components/_components.side-menu.scss +5 -5
  234. package/src/styles/06-components/_components.toggle.scss +18 -0
  235. package/src/styles/06-components/_index.scss +1 -1
  236. package/src/styles/06-components/old.chart.styles.scss +0 -2
  237. package/src/styles/99-utilities/_utilities.border.scss +69 -27
  238. package/src/styles/99-utilities/_utilities.display.scss +1 -1
  239. package/src/styles/99-utilities/_utilities.opacity.scss +10 -0
  240. package/src/styles/99-utilities/_utilities.position.scss +16 -9
  241. package/src/styles/99-utilities/_utilities.scss +1 -1
  242. package/src/styles/99-utilities/_utilities.sizes.scss +47 -18
  243. package/src/styles/99-utilities/_utilities.spacing.scss +118 -66
  244. package/src/styles/99-utilities/_utilities.text-gradient.scss +30 -30
  245. package/src/styles/99-utilities/_utilities.text.scss +67 -46
@@ -39,7 +39,7 @@ const smoothStep = (a: number, b: number, t: number): number => {
39
39
  if (typeof a !== 'number' || typeof b !== 'number' || typeof t !== 'number') {
40
40
  return 0;
41
41
  }
42
-
42
+
43
43
  const clamped = Math.max(0, Math.min(1, (t - a) / (b - a)));
44
44
  return clamped * clamped * (3 - 2 * clamped);
45
45
  };
@@ -49,11 +49,11 @@ const calculateLength = (x: number, y: number): number => {
49
49
  if (typeof x !== 'number' || typeof y !== 'number' || isNaN(x) || isNaN(y)) {
50
50
  return 0;
51
51
  }
52
-
52
+
53
53
  // Prevent potential overflow
54
54
  const maxX = Math.max(Math.abs(x), Math.abs(y));
55
55
  if (maxX === 0) return 0;
56
-
56
+
57
57
  const scaledX = x / maxX;
58
58
  const scaledY = y / maxX;
59
59
  return maxX * Math.sqrt(scaledX * scaledX + scaledY * scaledY);
@@ -67,12 +67,16 @@ const roundedRectSDF = (
67
67
  radius: number
68
68
  ): number => {
69
69
  // Add input validation
70
- if (typeof x !== 'number' || typeof y !== 'number' ||
71
- typeof width !== 'number' || typeof height !== 'number' ||
72
- typeof radius !== 'number') {
70
+ if (
71
+ typeof x !== 'number' ||
72
+ typeof y !== 'number' ||
73
+ typeof width !== 'number' ||
74
+ typeof height !== 'number' ||
75
+ typeof radius !== 'number'
76
+ ) {
73
77
  return 0;
74
78
  }
75
-
79
+
76
80
  const qx = Math.abs(x) - width + radius;
77
81
  const qy = Math.abs(y) - height + radius;
78
82
  return Math.min(Math.max(qx, qy), 0) + calculateLength(Math.max(qx, 0), Math.max(qy, 0)) - radius;
@@ -97,11 +101,11 @@ const clampValue = (value: number, min: number, max: number): number => {
97
101
  if (typeof value !== 'number' || typeof min !== 'number' || typeof max !== 'number') {
98
102
  return min;
99
103
  }
100
-
104
+
101
105
  if (isNaN(value)) return min;
102
106
  if (isNaN(min)) return 0;
103
107
  if (isNaN(max)) return 1;
104
-
108
+
105
109
  return Math.max(min, Math.min(max, value));
106
110
  };
107
111
 
@@ -111,9 +115,11 @@ const easeInOutCubic = (t: number): number => {
111
115
  if (typeof t !== 'number' || isNaN(t)) {
112
116
  return 0;
113
117
  }
114
-
118
+
115
119
  const clampedT = Math.max(0, Math.min(1, t));
116
- return clampedT < 0.5 ? 4 * clampedT * clampedT * clampedT : 1 - Math.pow(-2 * clampedT + 2, 3) / 2;
120
+ return clampedT < 0.5
121
+ ? 4 * clampedT * clampedT * clampedT
122
+ : 1 - Math.pow(-2 * clampedT + 2, 3) / 2;
117
123
  };
118
124
 
119
125
  const easeOutQuart = (t: number): number => {
@@ -121,7 +127,7 @@ const easeOutQuart = (t: number): number => {
121
127
  if (typeof t !== 'number' || isNaN(t)) {
122
128
  return 0;
123
129
  }
124
-
130
+
125
131
  const clampedT = Math.max(0, Math.min(1, t));
126
132
  return 1 - Math.pow(1 - clampedT, 4);
127
133
  };
@@ -132,7 +138,7 @@ const noise2D = (x: number, y: number): number => {
132
138
  if (typeof x !== 'number' || typeof y !== 'number' || isNaN(x) || isNaN(y)) {
133
139
  return 0;
134
140
  }
135
-
141
+
136
142
  const X = Math.floor(x) & 255;
137
143
  const Y = Math.floor(y) & 255;
138
144
 
@@ -148,7 +154,7 @@ const noise2D = (x: number, y: number): number => {
148
154
  if (typeof i !== 'number' || typeof j !== 'number') {
149
155
  return 0;
150
156
  }
151
-
157
+
152
158
  const n = i + j * 57;
153
159
  // Use a more stable hash function
154
160
  const hashed = Math.sin(n * 12.9898 + 78.233) * 43758.5453;
@@ -172,10 +178,10 @@ const fbm = (x: number, y: number, octaves: number = 4): number => {
172
178
  if (typeof x !== 'number' || typeof y !== 'number' || isNaN(x) || isNaN(y)) {
173
179
  return 0;
174
180
  }
175
-
181
+
176
182
  // Clamp octaves to prevent performance issues
177
183
  const clampedOctaves = Math.max(1, Math.min(8, Math.floor(octaves)));
178
-
184
+
179
185
  let value = 0;
180
186
  let amplitude = 0.5;
181
187
  let frequency = 1;
@@ -192,11 +198,17 @@ const fbm = (x: number, y: number, octaves: number = 4): number => {
192
198
  // Radial distortion for glass-like refraction
193
199
  const calculateRadialDistortion = (x: number, y: number, strength: number): Vec2 => {
194
200
  // Add input validation
195
- if (typeof x !== 'number' || typeof y !== 'number' || typeof strength !== 'number' ||
196
- isNaN(x) || isNaN(y) || isNaN(strength)) {
201
+ if (
202
+ typeof x !== 'number' ||
203
+ typeof y !== 'number' ||
204
+ typeof strength !== 'number' ||
205
+ isNaN(x) ||
206
+ isNaN(y) ||
207
+ isNaN(strength)
208
+ ) {
197
209
  return { x: 0, y: 0 };
198
210
  }
199
-
211
+
200
212
  const distance = calculateLength(x, y);
201
213
  const distortion = Math.pow(Math.min(distance, 10), 2) * strength; // Limit distance to prevent extreme values
202
214
 
@@ -209,17 +221,23 @@ const calculateRadialDistortion = (x: number, y: number, strength: number): Vec2
209
221
  // Chromatic aberration calculation
210
222
  const calculateChromaticOffset = (x: number, y: number, intensity: number): Vec2 => {
211
223
  // Add input validation
212
- if (typeof x !== 'number' || typeof y !== 'number' || typeof intensity !== 'number' ||
213
- isNaN(x) || isNaN(y) || isNaN(intensity)) {
224
+ if (
225
+ typeof x !== 'number' ||
226
+ typeof y !== 'number' ||
227
+ typeof intensity !== 'number' ||
228
+ isNaN(x) ||
229
+ isNaN(y) ||
230
+ isNaN(intensity)
231
+ ) {
214
232
  return { x: 0, y: 0 };
215
233
  }
216
-
234
+
217
235
  const distance = calculateLength(x, y);
218
236
  // Prevent division by zero and extreme values
219
237
  if (distance === 0) {
220
238
  return { x: 0, y: 0 };
221
239
  }
222
-
240
+
223
241
  const angle = Math.atan2(y, x);
224
242
 
225
243
  return {
@@ -231,11 +249,19 @@ const calculateChromaticOffset = (x: number, y: number, intensity: number): Vec2
231
249
  // Advanced caustic pattern generator for glass refraction
232
250
  const calculateCaustics = (x: number, y: number, time: number, intensity: number = 1): number => {
233
251
  // Add input validation
234
- if (typeof x !== 'number' || typeof y !== 'number' || typeof time !== 'number' ||
235
- typeof intensity !== 'number' || isNaN(x) || isNaN(y) || isNaN(time) || isNaN(intensity)) {
252
+ if (
253
+ typeof x !== 'number' ||
254
+ typeof y !== 'number' ||
255
+ typeof time !== 'number' ||
256
+ typeof intensity !== 'number' ||
257
+ isNaN(x) ||
258
+ isNaN(y) ||
259
+ isNaN(time) ||
260
+ isNaN(intensity)
261
+ ) {
236
262
  return 0.5; // Return middle value on error
237
263
  }
238
-
264
+
239
265
  const scale = 8;
240
266
  const speed = 2;
241
267
 
@@ -263,15 +289,23 @@ const calculateSpectralDispersion = (
263
289
  intensity: number
264
290
  ): { r: Vec2; g: Vec2; b: Vec2 } => {
265
291
  // Add input validation
266
- if (typeof x !== 'number' || typeof y !== 'number' || typeof angle !== 'number' ||
267
- typeof intensity !== 'number' || isNaN(x) || isNaN(y) || isNaN(angle) || isNaN(intensity)) {
292
+ if (
293
+ typeof x !== 'number' ||
294
+ typeof y !== 'number' ||
295
+ typeof angle !== 'number' ||
296
+ typeof intensity !== 'number' ||
297
+ isNaN(x) ||
298
+ isNaN(y) ||
299
+ isNaN(angle) ||
300
+ isNaN(intensity)
301
+ ) {
268
302
  return {
269
303
  r: { x: 0, y: 0 },
270
304
  g: { x: 0, y: 0 },
271
- b: { x: 0, y: 0 }
305
+ b: { x: 0, y: 0 },
272
306
  };
273
307
  }
274
-
308
+
275
309
  const distance = calculateLength(x, y);
276
310
  const dispersionStrength = Math.min(distance * intensity, 1); // Limit strength to prevent extreme values
277
311
 
@@ -305,12 +339,21 @@ const calculateParallaxOffset = (
305
339
  mouseY: number = 0
306
340
  ): Vec2 => {
307
341
  // Add input validation
308
- if (typeof x !== 'number' || typeof y !== 'number' || typeof depth !== 'number' ||
309
- typeof mouseX !== 'number' || typeof mouseY !== 'number' ||
310
- isNaN(x) || isNaN(y) || isNaN(depth) || isNaN(mouseX) || isNaN(mouseY)) {
342
+ if (
343
+ typeof x !== 'number' ||
344
+ typeof y !== 'number' ||
345
+ typeof depth !== 'number' ||
346
+ typeof mouseX !== 'number' ||
347
+ typeof mouseY !== 'number' ||
348
+ isNaN(x) ||
349
+ isNaN(y) ||
350
+ isNaN(depth) ||
351
+ isNaN(mouseX) ||
352
+ isNaN(mouseY)
353
+ ) {
311
354
  return { x: 0, y: 0 };
312
355
  }
313
-
356
+
314
357
  const parallaxStrength = Math.min(0.02 * depth, 0.1); // Limit strength to prevent extreme values
315
358
 
316
359
  // Calculate offset based on view angle (simulated by mouse position)
@@ -323,11 +366,19 @@ const calculateParallaxOffset = (
323
366
  // Volumetric density for depth perception and scattering
324
367
  const calculateVolumetricDensity = (x: number, y: number, depth: number, time: number): number => {
325
368
  // Add input validation
326
- if (typeof x !== 'number' || typeof y !== 'number' || typeof depth !== 'number' ||
327
- typeof time !== 'number' || isNaN(x) || isNaN(y) || isNaN(depth) || isNaN(time)) {
369
+ if (
370
+ typeof x !== 'number' ||
371
+ typeof y !== 'number' ||
372
+ typeof depth !== 'number' ||
373
+ typeof time !== 'number' ||
374
+ isNaN(x) ||
375
+ isNaN(y) ||
376
+ isNaN(depth) ||
377
+ isNaN(time)
378
+ ) {
328
379
  return 0.5; // Return middle value on error
329
380
  }
330
-
381
+
331
382
  const noiseValue = fbm(x * 5 + time * 0.5, y * 5 - time * 0.5, 3);
332
383
  const depthFalloff = Math.exp(-Math.max(0, depth) * 2); // Ensure depth is not negative
333
384
 
@@ -337,14 +388,22 @@ const calculateVolumetricDensity = (x: number, y: number, depth: number, time: n
337
388
  // Advanced turbulence for organic glass distortion
338
389
  const calculateTurbulence = (x: number, y: number, time: number, octaves: number = 5): number => {
339
390
  // Add input validation
340
- if (typeof x !== 'number' || typeof y !== 'number' || typeof time !== 'number' ||
341
- typeof octaves !== 'number' || isNaN(x) || isNaN(y) || isNaN(time) || isNaN(octaves)) {
391
+ if (
392
+ typeof x !== 'number' ||
393
+ typeof y !== 'number' ||
394
+ typeof time !== 'number' ||
395
+ typeof octaves !== 'number' ||
396
+ isNaN(x) ||
397
+ isNaN(y) ||
398
+ isNaN(time) ||
399
+ isNaN(octaves)
400
+ ) {
342
401
  return 0;
343
402
  }
344
-
403
+
345
404
  // Clamp octaves to prevent performance issues
346
405
  const clampedOctaves = Math.max(1, Math.min(8, Math.floor(octaves)));
347
-
406
+
348
407
  let turbulence = 0;
349
408
  let amplitude = 1;
350
409
  let frequency = 1;
@@ -362,11 +421,17 @@ const calculateTurbulence = (x: number, y: number, time: number, octaves: number
362
421
  // Micro-surface detail for high-quality glass texture
363
422
  const calculateMicroSurface = (x: number, y: number, time: number): number => {
364
423
  // Add input validation
365
- if (typeof x !== 'number' || typeof y !== 'number' || typeof time !== 'number' ||
366
- isNaN(x) || isNaN(y) || isNaN(time)) {
424
+ if (
425
+ typeof x !== 'number' ||
426
+ typeof y !== 'number' ||
427
+ typeof time !== 'number' ||
428
+ isNaN(x) ||
429
+ isNaN(y) ||
430
+ isNaN(time)
431
+ ) {
367
432
  return 0.5; // Return middle value on error
368
433
  }
369
-
434
+
370
435
  const highFreqNoise = fbm(x * 40 + time * 0.3, y * 40 - time * 0.3, 6);
371
436
  const microDetail = fbm(x * 80, y * 80, 4);
372
437
 
@@ -742,12 +807,20 @@ export class ShaderDisplacementGenerator {
742
807
 
743
808
  this.canvas = document.createElement('canvas');
744
809
  // Enhanced validation for canvas dimensions
745
- this.canvas.width = Math.max(MIN_CANVAS_DIMENSION,
746
- Math.min(MAX_CANVAS_DIMENSION,
747
- Math.round(options.width * this.canvasDPI || DEFAULT_CANVAS_WIDTH)));
748
- this.canvas.height = Math.max(MIN_CANVAS_DIMENSION,
749
- Math.min(MAX_CANVAS_DIMENSION,
750
- Math.round(options.height * this.canvasDPI || DEFAULT_CANVAS_HEIGHT)));
810
+ this.canvas.width = Math.max(
811
+ MIN_CANVAS_DIMENSION,
812
+ Math.min(
813
+ MAX_CANVAS_DIMENSION,
814
+ Math.round(options.width * this.canvasDPI || DEFAULT_CANVAS_WIDTH)
815
+ )
816
+ );
817
+ this.canvas.height = Math.max(
818
+ MIN_CANVAS_DIMENSION,
819
+ Math.min(
820
+ MAX_CANVAS_DIMENSION,
821
+ Math.round(options.height * this.canvasDPI || DEFAULT_CANVAS_HEIGHT)
822
+ )
823
+ );
751
824
  this.canvas.style.display = 'none';
752
825
 
753
826
  const context = this.canvas.getContext('2d');
@@ -849,7 +922,10 @@ export class ShaderDisplacementGenerator {
849
922
  return this.canvas.toDataURL();
850
923
  } catch (error) {
851
924
  // Graceful fallback on error
852
- console.warn('ShaderDisplacementGenerator: Error generating shader map, using fallback', error);
925
+ console.warn(
926
+ 'ShaderDisplacementGenerator: Error generating shader map, using fallback',
927
+ error
928
+ );
853
929
  return ''; // Return empty string as fallback
854
930
  }
855
931
  }
@@ -874,4 +950,4 @@ export class ShaderDisplacementGenerator {
874
950
  getScale(): number {
875
951
  return this.canvasDPI;
876
952
  }
877
- }
953
+ }
@@ -494,7 +494,7 @@ export const Playground: Story = {
494
494
  };
495
495
 
496
496
  const backgrounds = [
497
- 'https://images.unsplash.com/photo-1651483554034-8defec113cf2?ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&q=80&w=2074',
497
+ 'https://images.unsplash.com/photo-1579546929518-9e396f3cc809',
498
498
  'https://images.unsplash.com/photo-1734760858517-ff3e30c4a420?ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&q=80&w=987',
499
499
  'https://images.unsplash.com/photo-1590634875052-89c137f8df21?ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&q=80&w=2072',
500
500
  'https://images.unsplash.com/photo-1592880476174-2932b3061c30?ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&q=80&w=2070',
@@ -73,7 +73,7 @@ export const LiquidGlass: Story = {
73
73
  margin: '0 0 16px 0',
74
74
  fontSize: '38px',
75
75
  fontWeight: 700,
76
- background: 'linear-gradient(135deg, #fff 0%, rgba(255,255,255,0.8) 100%)',
76
+ background: 'url(https://images.unsplash.com/photo-1579546929518-9e396f3cc809)',
77
77
  WebkitBackgroundClip: 'text',
78
78
  WebkitTextFillColor: 'transparent',
79
79
  backgroundClip: 'text',
@@ -109,10 +109,10 @@ export const Basic: Story = {
109
109
  parameters: {
110
110
  docs: {
111
111
  description: {
112
- story: 'Basic avatar with an image source'
113
- }
114
- }
115
- }
112
+ story: 'Basic avatar with an image source',
113
+ },
114
+ },
115
+ },
116
116
  };
117
117
 
118
118
  // Avatar with Initials
@@ -125,10 +125,10 @@ export const WithInitials: Story = {
125
125
  parameters: {
126
126
  docs: {
127
127
  description: {
128
- story: 'Avatar displaying user initials when no image is available'
129
- }
130
- }
131
- }
128
+ story: 'Avatar displaying user initials when no image is available',
129
+ },
130
+ },
131
+ },
132
132
  };
133
133
 
134
134
  // Avatar with Icon
@@ -141,10 +141,10 @@ export const WithIcon: Story = {
141
141
  parameters: {
142
142
  docs: {
143
143
  description: {
144
- story: 'Avatar displaying an icon when no image or initials are available'
145
- }
146
- }
147
- }
144
+ story: 'Avatar displaying an icon when no image or initials are available',
145
+ },
146
+ },
147
+ },
148
148
  };
149
149
 
150
150
  // Avatar Sizes
@@ -156,10 +156,10 @@ export const Sizes: Story = {
156
156
  <div className="u-flex u-gap-4 u-flex-wrap u-items-center">
157
157
  {sizes.map(size => (
158
158
  <div key={size} className="u-flex u-flex-col u-items-center u-gap-2">
159
- <Avatar
160
- src={`https://i.pravatar.cc/150?img=${size === 'xs' ? 1 : size === 'sm' ? 2 : size === 'md' ? 3 : size === 'lg' ? 4 : 5}`}
161
- size={size}
162
- circle
159
+ <Avatar
160
+ src={`https://i.pravatar.cc/150?img=${size === 'xs' ? 1 : size === 'sm' ? 2 : size === 'md' ? 3 : size === 'lg' ? 4 : 5}`}
161
+ size={size}
162
+ circle
163
163
  />
164
164
  <span className="u-text-xs u-capitalize">{size}</span>
165
165
  </div>
@@ -170,10 +170,10 @@ export const Sizes: Story = {
170
170
  parameters: {
171
171
  docs: {
172
172
  description: {
173
- story: 'Different avatar sizes from extra-small to extra-large'
174
- }
175
- }
176
- }
173
+ story: 'Different avatar sizes from extra-small to extra-large',
174
+ },
175
+ },
176
+ },
177
177
  };
178
178
 
179
179
  // Avatar Shapes
@@ -182,19 +182,11 @@ export const Shapes: Story = {
182
182
  return (
183
183
  <div className="u-flex u-gap-6 u-items-center">
184
184
  <div className="u-flex u-flex-col u-items-center u-gap-2">
185
- <Avatar
186
- src="https://i.pravatar.cc/150?img=6"
187
- size="md"
188
- circle={false}
189
- />
185
+ <Avatar src="https://i.pravatar.cc/150?img=6" size="md" circle={false} />
190
186
  <span className="u-text-xs">Square</span>
191
187
  </div>
192
188
  <div className="u-flex u-flex-col u-items-center u-gap-2">
193
- <Avatar
194
- src="https://i.pravatar.cc/150?img=7"
195
- size="md"
196
- circle={true}
197
- />
189
+ <Avatar src="https://i.pravatar.cc/150?img=7" size="md" circle={true} />
198
190
  <span className="u-text-xs">Circle</span>
199
191
  </div>
200
192
  </div>
@@ -203,10 +195,10 @@ export const Shapes: Story = {
203
195
  parameters: {
204
196
  docs: {
205
197
  description: {
206
- story: 'Avatar shapes: square and circle'
207
- }
208
- }
209
- }
198
+ story: 'Avatar shapes: square and circle',
199
+ },
200
+ },
201
+ },
210
202
  };
211
203
 
212
204
  // Avatar States
@@ -215,20 +207,11 @@ export const States: Story = {
215
207
  return (
216
208
  <div className="u-flex u-gap-6 u-items-center">
217
209
  <div className="u-flex u-flex-col u-items-center u-gap-2">
218
- <Avatar
219
- src="https://i.pravatar.cc/150?img=8"
220
- size="md"
221
- circle
222
- />
210
+ <Avatar src="https://i.pravatar.cc/150?img=8" size="md" circle />
223
211
  <span className="u-text-xs">Default</span>
224
212
  </div>
225
213
  <div className="u-flex u-flex-col u-items-center u-gap-2">
226
- <Avatar
227
- src="https://i.pravatar.cc/150?img=9"
228
- size="md"
229
- circle
230
- disabled
231
- />
214
+ <Avatar src="https://i.pravatar.cc/150?img=9" size="md" circle disabled />
232
215
  <span className="u-text-xs">Disabled</span>
233
216
  </div>
234
217
  </div>
@@ -237,10 +220,10 @@ export const States: Story = {
237
220
  parameters: {
238
221
  docs: {
239
222
  description: {
240
- story: 'Avatar states: default and disabled'
241
- }
242
- }
243
- }
223
+ story: 'Avatar states: default and disabled',
224
+ },
225
+ },
226
+ },
244
227
  };
245
228
 
246
229
  // Avatar with Glass Effect
@@ -254,10 +237,10 @@ export const WithGlassEffect: Story = {
254
237
  parameters: {
255
238
  docs: {
256
239
  description: {
257
- story: 'Avatar with glassmorphism effect'
258
- }
259
- }
260
- }
240
+ story: 'Avatar with glassmorphism effect',
241
+ },
242
+ },
243
+ },
261
244
  };
262
245
 
263
246
  // Avatar Variants Showcase
@@ -357,10 +340,10 @@ export const VariantsShowcase: Story = {
357
340
  parameters: {
358
341
  docs: {
359
342
  description: {
360
- story: 'Comprehensive showcase of avatar variants across all sizes'
361
- }
362
- }
363
- }
343
+ story: 'Comprehensive showcase of avatar variants across all sizes',
344
+ },
345
+ },
346
+ },
364
347
  };
365
348
 
366
349
  // Avatar Group Showcase
@@ -469,8 +452,8 @@ export const AvatarGroupShowcase: Story = {
469
452
  parameters: {
470
453
  docs: {
471
454
  description: {
472
- story: 'Various configurations of AvatarGroup component'
473
- }
474
- }
475
- }
476
- };
455
+ story: 'Various configurations of AvatarGroup component',
456
+ },
457
+ },
458
+ },
459
+ };
@@ -3,66 +3,68 @@ import { AvatarProps } from '../../lib/types/components';
3
3
  import { AVATAR } from '../../lib/constants/components';
4
4
  import { Icon } from '../Icon/Icon';
5
5
 
6
- export const Avatar: React.FC<AvatarProps> = memo(({
7
- src,
8
- alt = 'Avatar',
9
- initials,
10
- icon,
11
- size = 'md',
12
- circle = false,
13
- className = '',
14
- disabled = false,
15
- onClick,
16
- style,
17
- glass,
18
- }) => {
19
- const [imageError, setImageError] = useState(false);
6
+ export const Avatar: React.FC<AvatarProps> = memo(
7
+ ({
8
+ src,
9
+ alt = 'Avatar',
10
+ initials,
11
+ icon,
12
+ size = 'md',
13
+ circle = false,
14
+ className = '',
15
+ disabled = false,
16
+ onClick,
17
+ style,
18
+ glass,
19
+ }) => {
20
+ const [imageError, setImageError] = useState(false);
20
21
 
21
- const handleImageError = () => {
22
- setImageError(true);
23
- };
22
+ const handleImageError = () => {
23
+ setImageError(true);
24
+ };
24
25
 
25
- // Generate CSS classes
26
- const avatarClasses = [
27
- AVATAR.CLASSES.BASE,
28
- size !== 'md' && `c-avatar--${size}`,
29
- circle && AVATAR.CLASSES.CIRCLE,
30
- disabled && 'is-disabled',
31
- className,
32
- ]
33
- .filter(Boolean)
34
- .join(' ');
26
+ // Generate CSS classes
27
+ const avatarClasses = [
28
+ AVATAR.CLASSES.BASE,
29
+ size !== 'md' && `c-avatar--${size}`,
30
+ circle && AVATAR.CLASSES.CIRCLE,
31
+ disabled && 'is-disabled',
32
+ className,
33
+ ]
34
+ .filter(Boolean)
35
+ .join(' ');
35
36
 
36
- // Handle click event
37
- const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {
38
- if (!disabled && onClick) {
39
- onClick(e);
40
- }
41
- };
37
+ // Handle click event
38
+ const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {
39
+ if (!disabled && onClick) {
40
+ onClick(e);
41
+ }
42
+ };
42
43
 
43
- return (
44
- <div
45
- className={avatarClasses}
46
- onClick={onClick ? handleClick : undefined}
47
- role={onClick ? 'button' : undefined}
48
- tabIndex={onClick && !disabled ? 0 : undefined}
49
- aria-disabled={disabled || undefined}
50
- style={style}
51
- >
52
- {src && !imageError ? (
53
- <img src={src} alt={alt} className="c-avatar__image" onError={handleImageError} />
54
- ) : initials ? (
55
- <span className="c-avatar__initials">{initials}</span>
56
- ) : icon ? (
57
- <span className="c-avatar__icon">{icon}</span>
58
- ) : (
59
- <span className="c-avatar__icon">
60
- <Icon name="User" size={size === 'xs' ? 'xs' : size === 'sm' ? 'sm' : 'md'} />
61
- </span>
62
- )}
63
- </div>
64
- );
65
- });
44
+ return (
45
+ <div
46
+ className={avatarClasses}
47
+ onClick={onClick ? handleClick : undefined}
48
+ role={onClick ? 'button' : undefined}
49
+ tabIndex={onClick && !disabled ? 0 : undefined}
50
+ aria-disabled={disabled || undefined}
51
+ style={style}
52
+ >
53
+ {src && !imageError ? (
54
+ <img src={src} alt={alt} className="c-avatar__image" onError={handleImageError} />
55
+ ) : initials ? (
56
+ <span className="c-avatar__initials">{initials}</span>
57
+ ) : icon ? (
58
+ <span className="c-avatar__icon">{icon}</span>
59
+ ) : (
60
+ <span className="c-avatar__icon">
61
+ <Icon name="User" size={size === 'xs' ? 'xs' : size === 'sm' ? 'sm' : 'md'} />
62
+ </span>
63
+ )}
64
+ </div>
65
+ );
66
+ }
67
+ );
66
68
 
67
69
  Avatar.displayName = 'Avatar';
68
70