@shohojdhara/atomix 0.3.5 → 0.3.7

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 (182) hide show
  1. package/README.md +101 -199
  2. package/atomix.config.ts +241 -0
  3. package/dist/atomix.css +260 -179
  4. package/dist/atomix.css.map +1 -1
  5. package/dist/atomix.min.css +250 -179
  6. package/dist/atomix.min.css.map +1 -1
  7. package/dist/charts.js +69 -166
  8. package/dist/charts.js.map +1 -1
  9. package/dist/core.js +184 -263
  10. package/dist/core.js.map +1 -1
  11. package/dist/forms.js +55 -131
  12. package/dist/forms.js.map +1 -1
  13. package/dist/heavy.js +184 -263
  14. package/dist/heavy.js.map +1 -1
  15. package/dist/index.d.ts +1831 -1657
  16. package/dist/index.esm.js +4497 -4318
  17. package/dist/index.esm.js.map +1 -1
  18. package/dist/index.js +4510 -4328
  19. package/dist/index.js.map +1 -1
  20. package/dist/index.min.js +1 -1
  21. package/dist/index.min.js.map +1 -1
  22. package/dist/theme.d.ts +1431 -1472
  23. package/dist/theme.js +4175 -4138
  24. package/dist/theme.js.map +1 -1
  25. package/package.json +6 -20
  26. package/src/components/Accordion/Accordion.stories.tsx +50 -17
  27. package/src/components/AtomixGlass/AtomixGlass.tsx +128 -322
  28. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +12 -5
  29. package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +1 -32
  30. package/src/components/AtomixGlass/stories/Examples.stories.tsx +2 -2
  31. package/src/components/AtomixGlass/stories/shared-components.tsx +0 -31
  32. package/src/components/Avatar/Avatar.stories.tsx +7 -0
  33. package/src/components/Badge/Badge.stories.tsx +91 -13
  34. package/src/components/Block/Block.stories.tsx +7 -23
  35. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +7 -0
  36. package/src/components/Button/Button.stories.tsx +141 -22
  37. package/src/components/Button/Button.tsx +85 -167
  38. package/src/components/Button/ButtonGroup.stories.tsx +315 -0
  39. package/src/components/Button/ButtonGroup.tsx +67 -0
  40. package/src/components/Button/index.ts +2 -0
  41. package/src/components/Callout/Callout.stories.tsx +8 -6
  42. package/src/components/Card/Card.stories.tsx +82 -28
  43. package/src/components/Chart/AnimatedChart.tsx +0 -1
  44. package/src/components/Chart/AreaChart.tsx +0 -1
  45. package/src/components/Chart/BarChart.tsx +0 -1
  46. package/src/components/Chart/BubbleChart.tsx +0 -1
  47. package/src/components/Chart/CandlestickChart.tsx +0 -1
  48. package/src/components/Chart/Chart.stories.tsx +5 -7
  49. package/src/components/Chart/Chart.tsx +0 -16
  50. package/src/components/Chart/ChartRenderer.tsx +1 -1
  51. package/src/components/Chart/DonutChart.tsx +0 -1
  52. package/src/components/Chart/FunnelChart.tsx +0 -1
  53. package/src/components/Chart/GaugeChart.tsx +0 -1
  54. package/src/components/Chart/HeatmapChart.tsx +0 -1
  55. package/src/components/Chart/LineChart.tsx +0 -1
  56. package/src/components/Chart/MultiAxisChart.tsx +0 -1
  57. package/src/components/Chart/PieChart.tsx +0 -1
  58. package/src/components/Chart/RadarChart.tsx +0 -1
  59. package/src/components/Chart/ScatterChart.tsx +0 -1
  60. package/src/components/Chart/WaterfallChart.tsx +0 -1
  61. package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +7 -0
  62. package/src/components/DataTable/DataTable.stories.tsx +23 -16
  63. package/src/components/DatePicker/DatePicker.stories.tsx +27 -19
  64. package/src/components/Dropdown/Dropdown.stories.tsx +11 -19
  65. package/src/components/EdgePanel/EdgePanel.stories.tsx +1 -0
  66. package/src/components/Footer/Footer.stories.tsx +8 -6
  67. package/src/components/Footer/FooterLink.tsx +9 -2
  68. package/src/components/Form/Checkbox.stories.tsx +7 -0
  69. package/src/components/Form/Form.stories.tsx +7 -0
  70. package/src/components/Form/FormGroup.stories.tsx +9 -1
  71. package/src/components/Form/Input.stories.tsx +69 -16
  72. package/src/components/Form/Radio.stories.tsx +9 -1
  73. package/src/components/Form/Select.stories.tsx +9 -1
  74. package/src/components/Form/Textarea.stories.tsx +10 -2
  75. package/src/components/Hero/Hero.stories.tsx +7 -0
  76. package/src/components/List/List.stories.tsx +7 -0
  77. package/src/components/Messages/Messages.stories.tsx +8 -7
  78. package/src/components/Modal/Modal.stories.tsx +17 -6
  79. package/src/components/Navigation/Menu/Menu.stories.tsx +7 -0
  80. package/src/components/Navigation/Nav/Nav.stories.tsx +7 -0
  81. package/src/components/Navigation/Navbar/Navbar.stories.tsx +1 -0
  82. package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +1 -1
  83. package/src/components/Pagination/Pagination.stories.tsx +188 -111
  84. package/src/components/Pagination/Pagination.tsx +83 -3
  85. package/src/components/PhotoViewer/PhotoViewer.stories.tsx +10 -5
  86. package/src/components/Popover/Popover.stories.tsx +191 -115
  87. package/src/components/ProductReview/ProductReview.stories.tsx +80 -58
  88. package/src/components/Progress/Progress.stories.tsx +79 -49
  89. package/src/components/Rating/Rating.stories.tsx +109 -84
  90. package/src/components/River/River.stories.tsx +194 -114
  91. package/src/components/SectionIntro/SectionIntro.stories.tsx +19 -9
  92. package/src/components/Slider/Slider.stories.tsx +7 -0
  93. package/src/components/Spinner/Spinner.stories.tsx +15 -11
  94. package/src/components/Steps/Steps.stories.tsx +132 -98
  95. package/src/components/Tabs/Tabs.stories.tsx +163 -112
  96. package/src/components/Testimonial/Testimonial.stories.tsx +114 -68
  97. package/src/components/Todo/Todo.stories.tsx +38 -12
  98. package/src/components/Toggle/Toggle.stories.tsx +61 -28
  99. package/src/components/Tooltip/Tooltip.stories.tsx +318 -200
  100. package/src/components/Upload/Upload.stories.tsx +122 -84
  101. package/src/components/VideoPlayer/VideoPlayer.stories.tsx +7 -24
  102. package/src/components/index.ts +1 -0
  103. package/src/lib/composables/useAtomixGlass.ts +9 -10
  104. package/src/lib/composables/useNavbar.ts +0 -10
  105. package/src/lib/config/loader.ts +4 -4
  106. package/src/lib/constants/components.ts +17 -0
  107. package/src/lib/hooks/useComponentCustomization.ts +1 -1
  108. package/src/lib/hooks/usePerformanceMonitor.ts +1 -1
  109. package/src/lib/hooks/useThemeTokens.ts +105 -0
  110. package/src/lib/theme/README.md +174 -0
  111. package/src/lib/theme/adapters/index.ts +31 -0
  112. package/src/lib/theme/adapters/themeAdapter.ts +287 -0
  113. package/src/lib/theme/config/__tests__/configLoader.test.ts +207 -0
  114. package/src/lib/theme/config/configLoader.ts +95 -0
  115. package/src/lib/theme/config/loader.ts +37 -54
  116. package/src/lib/theme/config/types.ts +2 -2
  117. package/src/lib/theme/config/validator.ts +15 -91
  118. package/src/lib/theme/{constants.ts → constants/constants.ts} +1 -19
  119. package/src/lib/theme/constants/index.ts +8 -0
  120. package/src/lib/theme/core/ThemeRegistry.ts +75 -266
  121. package/src/lib/theme/core/__tests__/createTheme.test.ts +132 -0
  122. package/src/lib/theme/core/composeTheme.ts +105 -0
  123. package/src/lib/theme/core/createTheme.ts +108 -0
  124. package/src/lib/theme/{createTheme.ts → core/createThemeObject.ts} +12 -8
  125. package/src/lib/theme/core/index.ts +19 -19
  126. package/src/lib/theme/devtools/Comparator.tsx +346 -22
  127. package/src/lib/theme/devtools/IMPROVEMENTS.md +139 -38
  128. package/src/lib/theme/devtools/Inspector.tsx +335 -51
  129. package/src/lib/theme/devtools/LiveEditor.tsx +478 -107
  130. package/src/lib/theme/devtools/Preview.tsx +471 -221
  131. package/src/lib/theme/{core → devtools}/ThemeValidator.ts +1 -1
  132. package/src/lib/theme/devtools/index.ts +14 -4
  133. package/src/lib/theme/devtools/useHistory.ts +130 -0
  134. package/src/lib/theme/{errors.ts → errors/errors.ts} +1 -1
  135. package/src/lib/theme/errors/index.ts +12 -0
  136. package/src/lib/theme/generators/cssFile.ts +79 -0
  137. package/src/lib/theme/generators/generateCSS.ts +89 -0
  138. package/src/lib/theme/generators/generateCSSNested.ts +130 -0
  139. package/src/lib/theme/{generateCSSVariables.ts → generators/generateCSSVariables.ts} +3 -13
  140. package/src/lib/theme/generators/index.ts +25 -0
  141. package/src/lib/theme/i18n/rtl.ts +5 -6
  142. package/src/lib/theme/index.ts +149 -19
  143. package/src/lib/theme/runtime/ThemeApplicator.ts +53 -112
  144. package/src/lib/theme/{ThemeContext.tsx → runtime/ThemeContext.tsx} +1 -1
  145. package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +5 -5
  146. package/src/lib/theme/runtime/ThemeProvider.tsx +266 -282
  147. package/src/lib/theme/runtime/index.ts +2 -2
  148. package/src/lib/theme/runtime/useTheme.ts +1 -2
  149. package/src/lib/theme/runtime/useThemeTokens.ts +131 -0
  150. package/src/lib/theme/test/testTheme.ts +385 -0
  151. package/src/lib/theme/tokens/index.ts +12 -0
  152. package/src/lib/theme/tokens/tokens.ts +721 -0
  153. package/src/lib/theme/types.ts +6 -42
  154. package/src/lib/theme/utils/componentTheming.ts +132 -0
  155. package/src/lib/theme/{utils.ts → utils/domUtils.ts} +2 -2
  156. package/src/lib/theme/utils/index.ts +11 -0
  157. package/src/lib/theme/utils/injectCSS.ts +90 -0
  158. package/src/lib/theme/utils/naming.ts +100 -0
  159. package/src/lib/theme/utils/themeHelpers.ts +78 -0
  160. package/src/lib/theme/{themeUtils.ts → utils/themeUtils.ts} +7 -7
  161. package/src/lib/theme-tools.ts +7 -8
  162. package/src/lib/types/components.ts +40 -130
  163. package/src/lib/utils/componentUtils.ts +2 -2
  164. package/src/lib/utils/memoryMonitor.ts +3 -3
  165. package/src/lib/utils/themeNaming.ts +135 -0
  166. package/src/styles/01-settings/_settings.design-tokens.scss +4 -1
  167. package/src/styles/02-tools/_tools.button.scss +66 -79
  168. package/src/styles/06-components/_components.atomix-glass.scss +13 -3
  169. package/src/styles/06-components/_components.pagination.scss +88 -0
  170. package/scripts/sync-theme-config.js +0 -309
  171. package/src/lib/theme/composeTheme.ts +0 -370
  172. package/src/lib/theme/core/ThemeCache.ts +0 -283
  173. package/src/lib/theme/core/ThemeEngine.test.ts +0 -146
  174. package/src/lib/theme/core/ThemeEngine.ts +0 -665
  175. package/src/lib/theme/createThemeFromConfig.ts +0 -132
  176. package/src/lib/theme/devtools/CLI.ts +0 -364
  177. package/src/lib/theme/runtime/ThemeManager.test.ts +0 -192
  178. package/src/lib/theme/runtime/ThemeManager.ts +0 -446
  179. package/src/styles/03-generic/_generated-root.css +0 -26
  180. package/src/themes/README.md +0 -442
  181. package/src/themes/themes.config.js +0 -68
  182. /package/src/lib/theme/{cssVariableMapper.ts → adapters/cssVariableMapper.ts} +0 -0
@@ -110,14 +110,6 @@ export function AtomixGlass({
110
110
  const glassRef = useRef<HTMLDivElement>(null);
111
111
  const contentRef = useRef<HTMLDivElement>(null);
112
112
 
113
- // Cache CSS custom property values to avoid reading on every render
114
- const opacityCacheRef = useRef<{
115
- opacity50: number;
116
- opacity40: number;
117
- opacity80: number;
118
- opacity0: number;
119
- } | null>(null);
120
-
121
113
  // Use composable hook for all state and logic
122
114
  const {
123
115
  isHovered,
@@ -159,326 +151,142 @@ export function AtomixGlass({
159
151
  const isOverLight = overLightConfig.isOverLight;
160
152
  const shouldRenderOverLightLayers = enableOverLightLayers && isOverLight;
161
153
 
162
- // Read CSS custom properties once on mount and cache them
163
- useEffect(() => {
164
- if (typeof window !== 'undefined' && glassRef.current && !opacityCacheRef.current) {
165
- try {
166
- const computedStyle = window.getComputedStyle(glassRef.current);
167
- const opacity50Value = computedStyle.getPropertyValue('--atomix-opacity-50').trim();
168
- const opacity40Value = computedStyle.getPropertyValue('--atomix-opacity-40').trim();
169
- const opacity80Value = computedStyle.getPropertyValue('--atomix-opacity-80').trim();
170
- const opacity0Value = computedStyle.getPropertyValue('--atomix-opacity-0').trim();
171
-
172
- // Parse opacity values, handling 0 correctly (use NaN check instead of falsy check)
173
- const parseOpacity = (value: string, defaultValue: number): number => {
174
- if (!value) return defaultValue;
175
- const parsed = parseFloat(value);
176
- return isNaN(parsed) ? defaultValue : parsed;
177
- };
178
-
179
- opacityCacheRef.current = {
180
- opacity50: parseOpacity(opacity50Value, 0.5),
181
- opacity40: parseOpacity(opacity40Value, 0.4),
182
- opacity80: parseOpacity(opacity80Value, 0.8),
183
- opacity0: parseOpacity(opacity0Value, 0),
184
- };
185
- } catch (error) {
186
- // Fallback to defaults if reading fails
187
- opacityCacheRef.current = {
188
- opacity50: 0.5,
189
- opacity40: 0.4,
190
- opacity80: 0.8,
191
- opacity0: 0,
192
- };
193
- }
194
- }
195
- }, []);
196
-
197
-
198
- // Calculate base style with transforms (only dynamic values)
199
- const baseStyle = useMemo(
200
- () => ({
201
- ...style,
202
- ...(elasticity !== 0 && !effectiveDisableEffects && {
203
- transform: transformStyle,
204
- }),
154
+ // Calculate base style with transforms
155
+ const baseStyle = {
156
+ ...style,
157
+ ...(elasticity !== 0 && !effectiveDisableEffects && {
158
+ transform: transformStyle,
205
159
  }),
206
- [style, transformStyle, effectiveDisableEffects, elasticity]
207
- );
160
+ };
208
161
 
209
162
  // Build className with state modifiers
210
- const componentClassName = useMemo(
211
- () =>
212
- [
213
- ATOMIX_GLASS.BASE_CLASS,
214
- effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`,
215
- effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`,
216
- effectiveDisableEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`,
217
- className,
218
- ]
219
- .filter(Boolean)
220
- .join(' '),
221
- [effectiveReducedMotion, effectiveHighContrast, effectiveDisableEffects, className]
222
- );
163
+ const componentClassName = [
164
+ ATOMIX_GLASS.BASE_CLASS,
165
+ effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`,
166
+ effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`,
167
+ effectiveDisableEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`,
168
+ className,
169
+ ]
170
+ .filter(Boolean)
171
+ .join(' ');
223
172
 
224
173
  // Calculate position and size styles
225
- // Optimize: only depend on specific baseStyle properties used
226
- const baseStylePosition = baseStyle.position;
227
- const baseStyleTop = baseStyle.top;
228
- const baseStyleLeft = baseStyle.left;
229
-
230
- const positionStyles = useMemo(
231
- () => ({
232
- position: (baseStylePosition || 'absolute') as React.CSSProperties['position'],
233
- top: baseStyleTop || 0,
234
- left: baseStyleLeft || 0,
235
- }),
236
- [baseStylePosition, baseStyleTop, baseStyleLeft]
174
+ const positionStyles = {
175
+ position: (style.position || 'absolute') as React.CSSProperties['position'],
176
+ top: style.top || 0,
177
+ left: style.left || 0,
178
+ };
179
+
180
+ const adjustedSize = {
181
+ width:
182
+ style.position !== 'fixed'
183
+ ? '100%'
184
+ : style.width
185
+ ? style.width
186
+ : Math.max(glassSize.width, 0),
187
+ height:
188
+ style.position !== 'fixed'
189
+ ? '100%'
190
+ : style.height
191
+ ? style.height
192
+ : Math.max(glassSize.height, 0),
193
+ };
194
+
195
+ // Calculate gradient values directly without excessive memoization
196
+ const mx = mouseOffset.x;
197
+ const my = mouseOffset.y;
198
+
199
+ // Calculate gradient angles and stops
200
+ const GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT;
201
+ const borderGradientAngle = GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER;
202
+ const borderStop1 = Math.max(
203
+ GRADIENT.BORDER_STOP_1.MIN,
204
+ GRADIENT.BORDER_STOP_1.BASE + my * GRADIENT.BORDER_STOP_1.MULTIPLIER
237
205
  );
238
-
239
- // Optimize: only depend on specific baseStyle properties used
240
- const baseStyleWidth = baseStyle.width;
241
- const baseStyleHeight = baseStyle.height;
242
- const glassSizeWidth = glassSize.width;
243
- const glassSizeHeight = glassSize.height;
244
-
245
- const adjustedSize = useMemo(
246
- () => ({
247
- width:
248
- baseStylePosition !== 'fixed'
249
- ? '100%'
250
- : baseStyleWidth
251
- ? baseStyleWidth
252
- : Math.max(glassSizeWidth, 0),
253
- height:
254
- baseStylePosition !== 'fixed'
255
- ? '100%'
256
- : baseStyleHeight
257
- ? baseStyleHeight
258
- : Math.max(glassSizeHeight, 0),
259
- }),
260
- [baseStylePosition, baseStyleWidth, baseStyleHeight, glassSizeWidth, glassSizeHeight]
206
+ const borderStop2 = Math.min(
207
+ GRADIENT.BORDER_STOP_2.MAX,
208
+ GRADIENT.BORDER_STOP_2.BASE + my * GRADIENT.BORDER_STOP_2.MULTIPLIER
261
209
  );
262
-
263
-
264
-
265
- // Memoize gradient calculations separately for better performance
266
- // Extract mouse position values for dependency optimization
267
- const mouseOffsetX = mouseOffset.x;
268
- const mouseOffsetY = mouseOffset.y;
269
-
270
- // Extract constants outside useMemo to avoid recreating on every render
271
- const GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT;
272
-
273
- const gradientCalculations = useMemo(() => {
274
- const mx = mouseOffsetX;
275
- const my = mouseOffsetY;
276
-
277
- // Calculate gradient angles and stops (optimized)
278
- const borderGradientAngle =
279
- GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER;
280
- const borderStop1 = Math.max(
281
- GRADIENT.BORDER_STOP_1.MIN,
282
- GRADIENT.BORDER_STOP_1.BASE + my * GRADIENT.BORDER_STOP_1.MULTIPLIER
283
- );
284
- const borderStop2 = Math.min(
285
- GRADIENT.BORDER_STOP_2.MAX,
286
- GRADIENT.BORDER_STOP_2.BASE + my * GRADIENT.BORDER_STOP_2.MULTIPLIER
287
- );
288
- const borderOpacity1 =
289
- GRADIENT.BORDER_OPACITY.BASE_1 +
290
- Math.abs(mx) * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW;
291
- const borderOpacity2 =
292
- GRADIENT.BORDER_OPACITY.BASE_2 +
293
- Math.abs(mx) * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH;
294
- const borderOpacity3 =
295
- GRADIENT.BORDER_OPACITY.BASE_3 +
296
- Math.abs(mx) * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW;
297
- const borderOpacity4 =
298
- GRADIENT.BORDER_OPACITY.BASE_4 +
299
- Math.abs(mx) * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH;
300
-
301
- // Hover gradient positions
302
- const hover1X = GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1;
303
- const hover1Y = GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1;
304
- const hover2X = GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_2;
305
- const hover2Y = GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_2;
306
- const hover3X = GRADIENT.CENTER_POSITION + mx * GRADIENT.HOVER_POSITION.MULTIPLIER_3;
307
- const hover3Y = GRADIENT.CENTER_POSITION + my * GRADIENT.HOVER_POSITION.MULTIPLIER_3;
308
-
309
- // Base layer positions
310
- const baseX = GRADIENT.CENTER_POSITION + mx * GRADIENT.BASE_LAYER_MULTIPLIER;
311
- const baseY = GRADIENT.CENTER_POSITION + my * GRADIENT.BASE_LAYER_MULTIPLIER;
312
-
313
- return {
314
- isOverLight,
315
- mx,
316
- my,
317
- borderGradientAngle,
318
- borderStop1,
319
- borderStop2,
320
- borderOpacity1,
321
- borderOpacity2,
322
- borderOpacity3,
323
- borderOpacity4,
324
- hover1X,
325
- hover1Y,
326
- hover2X,
327
- hover2Y,
328
- hover3X,
329
- hover3Y,
330
- baseX,
331
- baseY,
332
- };
333
- }, [mouseOffsetX, mouseOffsetY, isOverLight]); // GRADIENT is constant, no need to include
334
-
335
- // Memoize opacity values separately - using design token values where applicable
336
- // Optimize: extract overLightConfig.opacity to avoid depending on whole object
210
+ const borderOpacity1 =
211
+ GRADIENT.BORDER_OPACITY.BASE_1 +
212
+ Math.abs(mx) * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW;
213
+ const borderOpacity2 =
214
+ GRADIENT.BORDER_OPACITY.BASE_2 +
215
+ Math.abs(mx) * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH;
216
+ const borderOpacity3 =
217
+ GRADIENT.BORDER_OPACITY.BASE_3 +
218
+ Math.abs(mx) * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW;
219
+ const borderOpacity4 =
220
+ GRADIENT.BORDER_OPACITY.BASE_4 +
221
+ Math.abs(mx) * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH;
222
+
223
+ // Hover gradient positions
224
+ const hover1X = GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1;
225
+ const hover1Y = GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1;
226
+ const hover2X = GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_2;
227
+ const hover2Y = GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_2;
228
+ const hover3X = GRADIENT.CENTER_POSITION + mx * GRADIENT.HOVER_POSITION.MULTIPLIER_3;
229
+ const hover3Y = GRADIENT.CENTER_POSITION + my * GRADIENT.HOVER_POSITION.MULTIPLIER_3;
230
+
231
+ // Base layer positions
232
+ const baseX = GRADIENT.CENTER_POSITION + mx * GRADIENT.BASE_LAYER_MULTIPLIER;
233
+ const baseY = GRADIENT.CENTER_POSITION + my * GRADIENT.BASE_LAYER_MULTIPLIER;
234
+
235
+ // Calculate opacity values
337
236
  const overLightOpacity = overLightConfig.opacity;
338
-
339
- // Use cached opacity values from CSS custom properties (read once on mount)
340
- const opacityValues = useMemo(() => {
341
- // Use cached values if available, otherwise fallback to defaults
342
- const opacity50 = opacityCacheRef.current?.opacity50 ?? 0.5;
343
- const opacity40 = opacityCacheRef.current?.opacity40 ?? 0.4;
344
- const opacity80 = opacityCacheRef.current?.opacity80 ?? 0.8;
345
- const opacity0 = opacityCacheRef.current?.opacity0 ?? 0;
346
-
347
- const BASE_OVER_LIGHT_OPACITY = opacity40; // Uses design token
348
- const OVER_OPACITY_MULTIPLIER = 1.1; // Dynamic multiplier for overlay
349
-
350
- return {
351
- hover1: isHovered || isActive ? opacity50 : opacity0,
352
- hover2: isActive ? opacity50 : opacity0,
353
- hover3: isHovered ? opacity40 : isActive ? opacity80 : opacity0,
354
- base: isOverLight ? overLightOpacity || BASE_OVER_LIGHT_OPACITY : opacity0,
355
- over: isOverLight ? (overLightOpacity || BASE_OVER_LIGHT_OPACITY) * OVER_OPACITY_MULTIPLIER : opacity0,
356
- };
357
- }, [isHovered, isActive, isOverLight, overLightOpacity]);
358
-
359
- // Generate CSS variables for layers (only dynamic values)
360
- // Optimize: extract specific properties from objects to minimize dependencies
361
- const gradientIsOverLight = gradientCalculations.isOverLight;
362
- const gradientMx = gradientCalculations.mx;
363
- const gradientMy = gradientCalculations.my;
364
- const gradientBorderGradientAngle = gradientCalculations.borderGradientAngle;
365
- const gradientBorderStop1 = gradientCalculations.borderStop1;
366
- const gradientBorderStop2 = gradientCalculations.borderStop2;
367
- const gradientBorderOpacity1 = gradientCalculations.borderOpacity1;
368
- const gradientBorderOpacity2 = gradientCalculations.borderOpacity2;
369
- const gradientBorderOpacity3 = gradientCalculations.borderOpacity3;
370
- const gradientBorderOpacity4 = gradientCalculations.borderOpacity4;
371
- const gradientHover1X = gradientCalculations.hover1X;
372
- const gradientHover1Y = gradientCalculations.hover1Y;
373
- const gradientHover2X = gradientCalculations.hover2X;
374
- const gradientHover2Y = gradientCalculations.hover2Y;
375
- const gradientHover3X = gradientCalculations.hover3X;
376
- const gradientHover3Y = gradientCalculations.hover3Y;
377
- const gradientBaseX = gradientCalculations.baseX;
378
- const gradientBaseY = gradientCalculations.baseY;
379
-
380
- const positionStylesPosition = positionStyles.position;
381
- const positionStylesTop = positionStyles.top;
382
- const positionStylesLeft = positionStyles.left;
383
-
384
- const adjustedSizeWidth = adjustedSize.width;
385
- const adjustedSizeHeight = adjustedSize.height;
386
-
387
- const baseStyleTransform = baseStyle.transform;
388
- const opacityValuesHover1 = opacityValues.hover1;
389
- const opacityValuesHover2 = opacityValues.hover2;
390
- const opacityValuesHover3 = opacityValues.hover3;
391
- const opacityValuesBase = opacityValues.base;
392
- const opacityValuesOver = opacityValues.over;
393
-
394
- const glassVars = useMemo(() => {
395
- // RGB color values for rgba() functions
396
- // Note: CSS doesn't support rgba(var(--rgb), opacity) syntax, so we use direct values
397
- // These values align with design tokens: --atomix-white-rgb and --atomix-black-rgb
398
- // The actual RGB values are defined in SCSS and should match these fallbacks
399
- // TODO: Consider reading from CSS custom properties if browser support improves
400
- const whiteColor = '255, 255, 255'; // Matches --atomix-white-rgb design token
401
- const blackColor = '0, 0, 0'; // Matches --atomix-black-rgb design token
402
-
403
- return {
404
- // Standard CSS custom properties for dynamic values
405
- '--atomix-glass-radius': `${effectiveCornerRadius}px`,
406
- '--atomix-glass-transform': baseStyleTransform || 'none',
407
- '--atomix-glass-position': positionStylesPosition,
408
- '--atomix-glass-top': positionStylesTop !== 'fixed' ? `${positionStylesTop}px` : '0',
409
- '--atomix-glass-left': positionStylesLeft !== 'fixed' ? `${positionStylesLeft}px` : '0',
410
- '--atomix-glass-width':
411
- baseStylePosition !== 'fixed' ? adjustedSizeWidth : `${adjustedSizeWidth}px`,
412
- '--atomix-glass-height':
413
- baseStylePosition !== 'fixed' ? adjustedSizeHeight : `${adjustedSizeHeight}px`,
414
- // Border width: Use spacing token for consistency
415
- '--atomix-glass-border-width': 'var(--atomix-spacing-0-5, 0.09375rem)',
416
- '--atomix-glass-blend-mode': gradientIsOverLight ? 'multiply' : 'overlay',
417
- // Dynamic gradients and backgrounds
418
- // Note: RGB values use design token-aligned constants (white: 255,255,255; black: 0,0,0)
419
- '--atomix-glass-border-gradient-1': `linear-gradient(${gradientBorderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${gradientBorderOpacity1}) ${gradientBorderStop1}%, rgba(${whiteColor}, ${gradientBorderOpacity2}) ${gradientBorderStop2}%, rgba(${whiteColor}, 0) 100%)`,
420
- '--atomix-glass-border-gradient-2': `linear-gradient(${gradientBorderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${gradientBorderOpacity3}) ${gradientBorderStop1}%, rgba(${whiteColor}, ${gradientBorderOpacity4}) ${gradientBorderStop2}%, rgba(${whiteColor}, 0) 100%)`,
421
- '--atomix-glass-hover-1-opacity': opacityValuesHover1,
422
- '--atomix-glass-hover-1-gradient': gradientIsOverLight
423
- ? `radial-gradient(circle at ${gradientHover1X}% ${gradientHover1Y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_END}%)`
424
- : `radial-gradient(circle at ${gradientHover1X}% ${gradientHover1Y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_STOP}%)`,
425
- '--atomix-glass-hover-2-opacity': opacityValuesHover2,
426
- '--atomix-glass-hover-2-gradient': gradientIsOverLight
427
- ? `radial-gradient(circle at ${gradientHover2X}% ${gradientHover2Y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_END}%)`
428
- : `radial-gradient(circle at ${gradientHover2X}% ${gradientHover2Y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_STOP}%)`,
429
- '--atomix-glass-hover-3-opacity': opacityValuesHover3,
430
- '--atomix-glass-hover-3-gradient': gradientIsOverLight
431
- ? `radial-gradient(circle at ${gradientHover3X}% ${gradientHover3Y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_END}%)`
432
- : `radial-gradient(circle at ${gradientHover3X}% ${gradientHover3Y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_STOP}%)`,
433
- '--atomix-glass-base-opacity': opacityValuesBase,
434
- '--atomix-glass-base-gradient': gradientIsOverLight
435
- ? `linear-gradient(${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.ANGLE}deg, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_BASE + gradientMx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_BASE + gradientMy * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_MULTIPLIER}) ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_BASE + Math.abs(gradientMx) * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_MULTIPLIER}) 100%)`
436
- : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.WHITE_OPACITY})`,
437
- '--atomix-glass-overlay-opacity': opacityValuesOver,
438
- '--atomix-glass-overlay-gradient': gradientIsOverLight
439
- ? `radial-gradient(circle at ${gradientBaseX}% ${gradientBaseY}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_BASE + Math.abs(gradientMx) * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_BASE + Math.abs(gradientMy) * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_MULTIPLIER}) 100%)`
440
- : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.WHITE_OPACITY})`,
441
- } as React.CSSProperties;
442
- }, [
443
- // Position styles - only specific properties
444
- positionStylesPosition,
445
- positionStylesTop,
446
- positionStylesLeft,
447
- // Adjusted size - only specific properties
448
- adjustedSizeWidth,
449
- adjustedSizeHeight,
450
- // Base style - only transform property
451
- baseStyleTransform,
452
- baseStylePosition,
453
- // Other values
454
- effectiveCornerRadius,
455
- effectiveReducedMotion,
456
- // Gradient calculations - extracted properties
457
- gradientIsOverLight,
458
- gradientMx,
459
- gradientMy,
460
- gradientBorderGradientAngle,
461
- gradientBorderStop1,
462
- gradientBorderStop2,
463
- gradientBorderOpacity1,
464
- gradientBorderOpacity2,
465
- gradientBorderOpacity3,
466
- gradientBorderOpacity4,
467
- gradientHover1X,
468
- gradientHover1Y,
469
- gradientHover2X,
470
- gradientHover2Y,
471
- gradientHover3X,
472
- gradientHover3Y,
473
- gradientBaseX,
474
- gradientBaseY,
475
- // Opacity values - extracted properties
476
- opacityValuesHover1,
477
- opacityValuesHover2,
478
- opacityValuesHover3,
479
- opacityValuesBase,
480
- opacityValuesOver,
481
- ]);
237
+ const BASE_OVER_LIGHT_OPACITY = 0.4; // Default opacity value
238
+ const OVER_OPACITY_MULTIPLIER = 1.1; // Dynamic multiplier for overlay
239
+
240
+ const opacityValues = {
241
+ hover1: isHovered || isActive ? 0.5 : 0,
242
+ hover2: isActive ? 0.5 : 0,
243
+ hover3: isHovered ? 0.4 : isActive ? 0.8 : 0,
244
+ base: isOverLight ? overLightOpacity || BASE_OVER_LIGHT_OPACITY : 0,
245
+ over: isOverLight ? (overLightOpacity || BASE_OVER_LIGHT_OPACITY) * OVER_OPACITY_MULTIPLIER : 0,
246
+ };
247
+
248
+ // Generate CSS variables for layers
249
+ const whiteColor = '255, 255, 255'; // Default white RGB
250
+ const blackColor = '0, 0, 0'; // Default black RGB
251
+
252
+ const glassVars = {
253
+ // Standard CSS custom properties for dynamic values
254
+ '--atomix-glass-radius': `${effectiveCornerRadius}px`,
255
+ '--atomix-glass-transform': transformStyle || 'none',
256
+ '--atomix-glass-position': positionStyles.position,
257
+ '--atomix-glass-top': positionStyles.top !== 'fixed' ? `${positionStyles.top}px` : '0',
258
+ '--atomix-glass-left': positionStyles.left !== 'fixed' ? `${positionStyles.left}px` : '0',
259
+ '--atomix-glass-width':
260
+ style.position !== 'fixed' ? adjustedSize.width : `${adjustedSize.width}px`,
261
+ '--atomix-glass-height':
262
+ style.position !== 'fixed' ? adjustedSize.height : `${adjustedSize.height}px`,
263
+ // Border width: Use spacing token for consistency
264
+ '--atomix-glass-border-width': 'var(--atomix-spacing-0-5, 0.09375rem)',
265
+ '--atomix-glass-blend-mode': isOverLight ? 'multiply' : 'overlay',
266
+ // Dynamic gradients and backgrounds
267
+ '--atomix-glass-border-gradient-1': `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${borderOpacity1}) ${borderStop1}%, rgba(${whiteColor}, ${borderOpacity2}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
268
+ '--atomix-glass-border-gradient-2': `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${borderOpacity3}) ${borderStop1}%, rgba(${whiteColor}, ${borderOpacity4}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
269
+ '--atomix-glass-hover-1-opacity': opacityValues.hover1,
270
+ '--atomix-glass-hover-1-gradient': isOverLight
271
+ ? `radial-gradient(circle at ${hover1X}% ${hover1Y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_END}%)`
272
+ : `radial-gradient(circle at ${hover1X}% ${hover1Y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_STOP}%)`,
273
+ '--atomix-glass-hover-2-opacity': opacityValues.hover2,
274
+ '--atomix-glass-hover-2-gradient': isOverLight
275
+ ? `radial-gradient(circle at ${hover2X}% ${hover2Y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_END}%)`
276
+ : `radial-gradient(circle at ${hover2X}% ${hover2Y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_STOP}%)`,
277
+ '--atomix-glass-hover-3-opacity': opacityValues.hover3,
278
+ '--atomix-glass-hover-3-gradient': isOverLight
279
+ ? `radial-gradient(circle at ${hover3X}% ${hover3Y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_END}%)`
280
+ : `radial-gradient(circle at ${hover3X}% ${hover3Y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_STOP}%)`,
281
+ '--atomix-glass-base-opacity': opacityValues.base,
282
+ '--atomix-glass-base-gradient': isOverLight
283
+ ? `linear-gradient(${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.ANGLE}deg, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_BASE + mx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_BASE + my * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_MULTIPLIER}) ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_BASE + Math.abs(mx) * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_MULTIPLIER}) 100%)`
284
+ : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.WHITE_OPACITY})`,
285
+ '--atomix-glass-overlay-opacity': opacityValues.over,
286
+ '--atomix-glass-overlay-gradient': isOverLight
287
+ ? `radial-gradient(circle at ${baseX}% ${baseY}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_BASE + Math.abs(mx) * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_BASE + Math.abs(my) * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_MULTIPLIER}) 100%)`
288
+ : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.WHITE_OPACITY})`,
289
+ } as React.CSSProperties;
482
290
 
483
291
  return (
484
292
  <div
@@ -492,8 +300,6 @@ export function AtomixGlass({
492
300
  aria-pressed={onClick && isActive ? true : onClick ? false : undefined}
493
301
  onKeyDown={onClick ? handleKeyDown : undefined}
494
302
  >
495
-
496
-
497
303
  <AtomixGlassContainer
498
304
  ref={glassRef}
499
305
  contentRef={contentRef}
@@ -53,7 +53,7 @@ const setCachedShader = (key: string, url: string): void => {
53
53
  sharedShaderCache.set(key, { url, timestamp: Date.now() });
54
54
 
55
55
  // Development mode: log cache size
56
- if (process.env.NODE_ENV !== 'production') {
56
+ if (typeof process === 'undefined' || process.env?.NODE_ENV !== 'production') {
57
57
  if (sharedShaderCache.size >= MAX_CACHE_SIZE * 0.8) {
58
58
  console.log(`AtomixGlass: Shader cache size: ${sharedShaderCache.size}/${MAX_CACHE_SIZE}`);
59
59
  }
@@ -130,10 +130,17 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
130
130
  },
131
131
  ref
132
132
  ) => {
133
- // Use React's useId() for SSR compatibility
134
- // Note: In Next.js, IDs may differ between server and client
135
- // We'll suppress hydration warnings on elements that use this ID
136
- const filterId = useId();
133
+ // Generate a stable, deterministic ID for SSR compatibility
134
+ // React's useId() should produce the same ID on server and client for the same
135
+ // component position in the tree. We use useState to ensure the ID is only
136
+ // generated once and remains stable across renders.
137
+ const baseId = useId();
138
+ const [filterId] = useState(() => {
139
+ // Normalize the ID to ensure it's valid and consistent
140
+ // Remove colons (which useId() uses) and ensure it starts with a letter
141
+ const normalizedId = baseId.replace(/:/g, '-').replace(/^[^a-z]/i, 'atomix-');
142
+ return `atomix-glass-filter-${normalizedId}`;
143
+ });
137
144
 
138
145
  const [shaderMapUrl, setShaderMapUrl] = useState<string>('');
139
146
  const shaderGeneratorRef = useRef<any>(null);
@@ -124,7 +124,7 @@ See documentation for detailed examples of each mode.`,
124
124
  },
125
125
  },
126
126
  mode: {
127
- control: 'select',
127
+ control: { type: 'select' },
128
128
  options: ['standard', 'polar', 'prominent', 'shader'],
129
129
  description: 'Glass effect mode (default: "standard")',
130
130
  table: { defaultValue: { summary: '"standard"' } },
@@ -446,37 +446,6 @@ const backgroundImages = [
446
446
  'https://images.unsplash.com/photo-1521587760476-6c12a4b040da?q=80&w=2940&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
447
447
  ];
448
448
 
449
- /**
450
- * Legacy backgrounds object for backward compatibility
451
- * @deprecated Use backgroundImages array instead
452
- */
453
- const backgrounds = {
454
- // Office and workspace environments
455
- blueGradient: backgroundImages[0], // Modern office interior
456
- purpleGradient: backgroundImages[1], // Mountain landscape
457
- greenGradient: backgroundImages[3], // Forest path
458
-
459
- // Apple-inspired natural scenes
460
- macosWallpaper: backgroundImages[1], // Mountain landscape
461
- iosWallpaper: backgroundImages[4], // Ocean waves
462
-
463
- // Nature scenes
464
- mountains: backgroundImages[1], // Mountain landscape
465
- ocean: backgroundImages[4], // Ocean waves
466
-
467
- // Urban environments
468
- cityNight: backgroundImages[2], // Urban cityscape
469
- cityDay: backgroundImages[5], // Modern architecture
470
-
471
- // Interior spaces
472
- abstract1: backgroundImages[6], // Cozy café interior
473
- abstract2: backgroundImages[9], // Modern library
474
-
475
- // Video backgrounds
476
- videoBackground:
477
- 'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
478
- };
479
-
480
449
  /**
481
450
  * Default showcase of the AtomixGlass component
482
451
  *
@@ -11,7 +11,7 @@ import React from 'react';
11
11
  import { useState, useEffect } from 'react';
12
12
  import { Meta, StoryObj } from '@storybook/react';
13
13
  import AtomixGlass from '../AtomixGlass';
14
- import { BackgroundWrapper, backgrounds, backgroundImages } from './shared-components';
14
+ import { BackgroundWrapper, backgroundImages } from './shared-components';
15
15
 
16
16
  import { Button } from '../../Button';
17
17
  import { Badge } from '../../Badge';
@@ -181,7 +181,7 @@ export const VideoBackground: Story = {
181
181
  zIndex: -1,
182
182
  }}
183
183
  >
184
- <source src={backgrounds.videoBackground} type="video/mp4" />
184
+ <source src="https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" type="video/mp4" />
185
185
  </video>
186
186
 
187
187
  <div
@@ -106,37 +106,6 @@ export const backgroundImages = [
106
106
  'https://images.unsplash.com/photo-1521587760476-6c12a4b040da?q=80&w=2940&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
107
107
  ];
108
108
 
109
- /**
110
- * Legacy backgrounds object for backward compatibility
111
- * @deprecated Use backgroundImages array instead
112
- */
113
- export const backgrounds = {
114
- // Office and workspace environments
115
- blueGradient: backgroundImages[0], // Modern office interior
116
- purpleGradient: backgroundImages[1], // Mountain landscape
117
- greenGradient: backgroundImages[3], // Forest path
118
-
119
- // Apple-inspired natural scenes
120
- macosWallpaper: backgroundImages[1], // Mountain landscape
121
- iosWallpaper: backgroundImages[4], // Ocean waves
122
-
123
- // Nature scenes
124
- mountains: backgroundImages[1], // Mountain landscape
125
- ocean: backgroundImages[4], // Ocean waves
126
-
127
- // Urban environments
128
- cityNight: backgroundImages[2], // Urban cityscape
129
- cityDay: backgroundImages[5], // Modern architecture
130
-
131
- // Interior spaces
132
- abstract1: backgroundImages[6], // Cozy café interior
133
- abstract2: backgroundImages[9], // Modern library
134
-
135
- // Video backgrounds
136
- videoBackground:
137
- 'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
138
- };
139
-
140
109
  /**
141
110
  * BackgroundWrapper Component Implementation
142
111
  *
@@ -8,7 +8,14 @@ const meta = {
8
8
  component: Avatar,
9
9
  parameters: {
10
10
  layout: 'centered',
11
+ docs: {
12
+ description: {
13
+ component:
14
+ 'The Avatar component displays user profile images, initials, or icons. It provides a consistent way to represent users throughout the application. Avatars support various sizes, can be circular or square, and gracefully handle missing images by showing initials or icons.',
15
+ },
16
+ },
11
17
  },
18
+ tags: ['autodocs'],
12
19
  argTypes: {
13
20
  src: {
14
21
  control: 'text',