@shohojdhara/atomix 0.3.6 → 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 (51) hide show
  1. package/README.md +3 -3
  2. package/dist/charts.js +50 -142
  3. package/dist/charts.js.map +1 -1
  4. package/dist/core.js +179 -274
  5. package/dist/core.js.map +1 -1
  6. package/dist/forms.js +50 -142
  7. package/dist/forms.js.map +1 -1
  8. package/dist/heavy.js +179 -274
  9. package/dist/heavy.js.map +1 -1
  10. package/dist/index.d.ts +669 -703
  11. package/dist/index.esm.js +966 -1649
  12. package/dist/index.esm.js.map +1 -1
  13. package/dist/index.js +1211 -1890
  14. package/dist/index.js.map +1 -1
  15. package/dist/index.min.js +1 -1
  16. package/dist/index.min.js.map +1 -1
  17. package/dist/theme.d.ts +163 -334
  18. package/dist/theme.js +774 -1473
  19. package/dist/theme.js.map +1 -1
  20. package/package.json +1 -1
  21. package/src/components/AtomixGlass/AtomixGlass.tsx +128 -356
  22. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +1 -1
  23. package/src/components/Button/Button.tsx +85 -167
  24. package/src/lib/composables/useAtomixGlass.ts +7 -7
  25. package/src/lib/config/loader.ts +2 -3
  26. package/src/lib/constants/components.ts +7 -0
  27. package/src/lib/hooks/usePerformanceMonitor.ts +1 -1
  28. package/src/lib/hooks/useThemeTokens.ts +105 -0
  29. package/src/lib/theme/config/configLoader.ts +60 -219
  30. package/src/lib/theme/config/loader.ts +15 -21
  31. package/src/lib/theme/constants/constants.ts +1 -1
  32. package/src/lib/theme/core/ThemeRegistry.ts +75 -279
  33. package/src/lib/theme/core/composeTheme.ts +14 -64
  34. package/src/lib/theme/core/createTheme.ts +54 -40
  35. package/src/lib/theme/core/createThemeObject.ts +2 -2
  36. package/src/lib/theme/core/index.ts +15 -1
  37. package/src/lib/theme/errors/errors.ts +1 -1
  38. package/src/lib/theme/generators/generateCSSNested.ts +130 -0
  39. package/src/lib/theme/generators/index.ts +6 -0
  40. package/src/lib/theme/index.ts +35 -10
  41. package/src/lib/theme/runtime/ThemeApplicator.ts +1 -1
  42. package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +4 -4
  43. package/src/lib/theme/runtime/ThemeProvider.tsx +261 -554
  44. package/src/lib/theme/runtime/index.ts +1 -0
  45. package/src/lib/theme/runtime/useThemeTokens.ts +131 -0
  46. package/src/lib/theme/utils/componentTheming.ts +132 -0
  47. package/src/lib/theme/utils/naming.ts +100 -0
  48. package/src/lib/theme/utils/themeUtils.ts +6 -6
  49. package/src/lib/utils/componentUtils.ts +1 -1
  50. package/src/lib/utils/memoryMonitor.ts +3 -3
  51. package/src/lib/utils/themeNaming.ts +135 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shohojdhara/atomix",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "description": "Atomix Design System - A modern component library for web applications",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -110,20 +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
- // Cache RGB color values from design tokens
122
- const rgbCacheRef = useRef<{
123
- whiteRgb: string;
124
- blackRgb: string;
125
- } | null>(null);
126
-
127
113
  // Use composable hook for all state and logic
128
114
  const {
129
115
  isHovered,
@@ -165,354 +151,142 @@ export function AtomixGlass({
165
151
  const isOverLight = overLightConfig.isOverLight;
166
152
  const shouldRenderOverLightLayers = enableOverLightLayers && isOverLight;
167
153
 
168
- // Read CSS custom properties once on mount and cache them
169
- useEffect(() => {
170
- if (typeof window !== 'undefined' && glassRef.current) {
171
- try {
172
- const computedStyle = window.getComputedStyle(glassRef.current);
173
-
174
- // Cache opacity values
175
- if (!opacityCacheRef.current) {
176
- const opacity50Value = computedStyle.getPropertyValue('--atomix-opacity-50').trim();
177
- const opacity40Value = computedStyle.getPropertyValue('--atomix-opacity-40').trim();
178
- const opacity80Value = computedStyle.getPropertyValue('--atomix-opacity-80').trim();
179
- const opacity0Value = computedStyle.getPropertyValue('--atomix-opacity-0').trim();
180
-
181
- // Parse opacity values, handling 0 correctly (use NaN check instead of falsy check)
182
- const parseOpacity = (value: string, defaultValue: number): number => {
183
- if (!value) return defaultValue;
184
- const parsed = parseFloat(value);
185
- return isNaN(parsed) ? defaultValue : parsed;
186
- };
187
-
188
- opacityCacheRef.current = {
189
- opacity50: parseOpacity(opacity50Value, 0.5),
190
- opacity40: parseOpacity(opacity40Value, 0.4),
191
- opacity80: parseOpacity(opacity80Value, 0.8),
192
- opacity0: parseOpacity(opacity0Value, 0),
193
- };
194
- }
195
-
196
- // Cache RGB color values from design tokens
197
- if (!rgbCacheRef.current) {
198
- // Try to read from design tokens, fallback to defaults
199
- const whiteRgbValue = computedStyle.getPropertyValue('--atomix-light-rgb').trim() ||
200
- computedStyle.getPropertyValue('--atomix-white-rgb').trim() ||
201
- '';
202
- const blackRgbValue = computedStyle.getPropertyValue('--atomix-dark-rgb').trim() ||
203
- computedStyle.getPropertyValue('--atomix-black-rgb').trim() ||
204
- '';
205
-
206
- rgbCacheRef.current = {
207
- whiteRgb: whiteRgbValue || '255, 255, 255', // Fallback to white RGB
208
- blackRgb: blackRgbValue || '0, 0, 0', // Fallback to black RGB
209
- };
210
- }
211
- } catch (error) {
212
- // Fallback to defaults if reading fails
213
- if (!opacityCacheRef.current) {
214
- opacityCacheRef.current = {
215
- opacity50: 0.5,
216
- opacity40: 0.4,
217
- opacity80: 0.8,
218
- opacity0: 0,
219
- };
220
- }
221
- if (!rgbCacheRef.current) {
222
- rgbCacheRef.current = {
223
- whiteRgb: '255, 255, 255',
224
- blackRgb: '0, 0, 0',
225
- };
226
- }
227
- }
228
- }
229
- }, []);
230
-
231
-
232
- // Calculate base style with transforms (only dynamic values)
233
- const baseStyle = useMemo(
234
- () => ({
235
- ...style,
236
- ...(elasticity !== 0 && !effectiveDisableEffects && {
237
- transform: transformStyle,
238
- }),
154
+ // Calculate base style with transforms
155
+ const baseStyle = {
156
+ ...style,
157
+ ...(elasticity !== 0 && !effectiveDisableEffects && {
158
+ transform: transformStyle,
239
159
  }),
240
- [style, transformStyle, effectiveDisableEffects, elasticity]
241
- );
160
+ };
242
161
 
243
162
  // Build className with state modifiers
244
- const componentClassName = useMemo(
245
- () =>
246
- [
247
- ATOMIX_GLASS.BASE_CLASS,
248
- effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`,
249
- effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`,
250
- effectiveDisableEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`,
251
- className,
252
- ]
253
- .filter(Boolean)
254
- .join(' '),
255
- [effectiveReducedMotion, effectiveHighContrast, effectiveDisableEffects, className]
256
- );
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(' ');
257
172
 
258
173
  // Calculate position and size styles
259
- // Optimize: only depend on specific baseStyle properties used
260
- const baseStylePosition = baseStyle.position;
261
- const baseStyleTop = baseStyle.top;
262
- const baseStyleLeft = baseStyle.left;
263
-
264
- const positionStyles = useMemo(
265
- () => ({
266
- position: (baseStylePosition || 'absolute') as React.CSSProperties['position'],
267
- top: baseStyleTop || 0,
268
- left: baseStyleLeft || 0,
269
- }),
270
- [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
271
205
  );
272
-
273
- // Optimize: only depend on specific baseStyle properties used
274
- const baseStyleWidth = baseStyle.width;
275
- const baseStyleHeight = baseStyle.height;
276
- const glassSizeWidth = glassSize.width;
277
- const glassSizeHeight = glassSize.height;
278
-
279
- const adjustedSize = useMemo(
280
- () => ({
281
- width:
282
- baseStylePosition !== 'fixed'
283
- ? '100%'
284
- : baseStyleWidth
285
- ? baseStyleWidth
286
- : Math.max(glassSizeWidth, 0),
287
- height:
288
- baseStylePosition !== 'fixed'
289
- ? '100%'
290
- : baseStyleHeight
291
- ? baseStyleHeight
292
- : Math.max(glassSizeHeight, 0),
293
- }),
294
- [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
295
209
  );
296
-
297
-
298
-
299
- // Memoize gradient calculations separately for better performance
300
- // Extract mouse position values for dependency optimization
301
- const mouseOffsetX = mouseOffset.x;
302
- const mouseOffsetY = mouseOffset.y;
303
-
304
- // Extract constants outside useMemo to avoid recreating on every render
305
- const GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT;
306
-
307
- const gradientCalculations = useMemo(() => {
308
- const mx = mouseOffsetX;
309
- const my = mouseOffsetY;
310
-
311
- // Calculate gradient angles and stops (optimized)
312
- const borderGradientAngle =
313
- GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER;
314
- const borderStop1 = Math.max(
315
- GRADIENT.BORDER_STOP_1.MIN,
316
- GRADIENT.BORDER_STOP_1.BASE + my * GRADIENT.BORDER_STOP_1.MULTIPLIER
317
- );
318
- const borderStop2 = Math.min(
319
- GRADIENT.BORDER_STOP_2.MAX,
320
- GRADIENT.BORDER_STOP_2.BASE + my * GRADIENT.BORDER_STOP_2.MULTIPLIER
321
- );
322
- const borderOpacity1 =
323
- GRADIENT.BORDER_OPACITY.BASE_1 +
324
- Math.abs(mx) * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW;
325
- const borderOpacity2 =
326
- GRADIENT.BORDER_OPACITY.BASE_2 +
327
- Math.abs(mx) * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH;
328
- const borderOpacity3 =
329
- GRADIENT.BORDER_OPACITY.BASE_3 +
330
- Math.abs(mx) * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW;
331
- const borderOpacity4 =
332
- GRADIENT.BORDER_OPACITY.BASE_4 +
333
- Math.abs(mx) * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH;
334
-
335
- // Hover gradient positions
336
- const hover1X = GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1;
337
- const hover1Y = GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1;
338
- const hover2X = GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_2;
339
- const hover2Y = GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_2;
340
- const hover3X = GRADIENT.CENTER_POSITION + mx * GRADIENT.HOVER_POSITION.MULTIPLIER_3;
341
- const hover3Y = GRADIENT.CENTER_POSITION + my * GRADIENT.HOVER_POSITION.MULTIPLIER_3;
342
-
343
- // Base layer positions
344
- const baseX = GRADIENT.CENTER_POSITION + mx * GRADIENT.BASE_LAYER_MULTIPLIER;
345
- const baseY = GRADIENT.CENTER_POSITION + my * GRADIENT.BASE_LAYER_MULTIPLIER;
346
-
347
- return {
348
- isOverLight,
349
- mx,
350
- my,
351
- borderGradientAngle,
352
- borderStop1,
353
- borderStop2,
354
- borderOpacity1,
355
- borderOpacity2,
356
- borderOpacity3,
357
- borderOpacity4,
358
- hover1X,
359
- hover1Y,
360
- hover2X,
361
- hover2Y,
362
- hover3X,
363
- hover3Y,
364
- baseX,
365
- baseY,
366
- };
367
- }, [mouseOffsetX, mouseOffsetY, isOverLight]); // GRADIENT is constant, no need to include
368
-
369
- // Memoize opacity values separately - using design token values where applicable
370
- // 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
371
236
  const overLightOpacity = overLightConfig.opacity;
372
-
373
- // Use cached opacity values from CSS custom properties (read once on mount)
374
- const opacityValues = useMemo(() => {
375
- // Use cached values if available, otherwise fallback to defaults
376
- const opacity50 = opacityCacheRef.current?.opacity50 ?? 0.5;
377
- const opacity40 = opacityCacheRef.current?.opacity40 ?? 0.4;
378
- const opacity80 = opacityCacheRef.current?.opacity80 ?? 0.8;
379
- const opacity0 = opacityCacheRef.current?.opacity0 ?? 0;
380
-
381
- const BASE_OVER_LIGHT_OPACITY = opacity40; // Uses design token
382
- const OVER_OPACITY_MULTIPLIER = 1.1; // Dynamic multiplier for overlay
383
-
384
- return {
385
- hover1: isHovered || isActive ? opacity50 : opacity0,
386
- hover2: isActive ? opacity50 : opacity0,
387
- hover3: isHovered ? opacity40 : isActive ? opacity80 : opacity0,
388
- base: isOverLight ? overLightOpacity || BASE_OVER_LIGHT_OPACITY : opacity0,
389
- over: isOverLight ? (overLightOpacity || BASE_OVER_LIGHT_OPACITY) * OVER_OPACITY_MULTIPLIER : opacity0,
390
- };
391
- }, [isHovered, isActive, isOverLight, overLightOpacity]);
392
-
393
- // Generate CSS variables for layers (only dynamic values)
394
- // Optimize: extract specific properties from objects to minimize dependencies
395
- const gradientIsOverLight = gradientCalculations.isOverLight;
396
- const gradientMx = gradientCalculations.mx;
397
- const gradientMy = gradientCalculations.my;
398
- const gradientBorderGradientAngle = gradientCalculations.borderGradientAngle;
399
- const gradientBorderStop1 = gradientCalculations.borderStop1;
400
- const gradientBorderStop2 = gradientCalculations.borderStop2;
401
- const gradientBorderOpacity1 = gradientCalculations.borderOpacity1;
402
- const gradientBorderOpacity2 = gradientCalculations.borderOpacity2;
403
- const gradientBorderOpacity3 = gradientCalculations.borderOpacity3;
404
- const gradientBorderOpacity4 = gradientCalculations.borderOpacity4;
405
- const gradientHover1X = gradientCalculations.hover1X;
406
- const gradientHover1Y = gradientCalculations.hover1Y;
407
- const gradientHover2X = gradientCalculations.hover2X;
408
- const gradientHover2Y = gradientCalculations.hover2Y;
409
- const gradientHover3X = gradientCalculations.hover3X;
410
- const gradientHover3Y = gradientCalculations.hover3Y;
411
- const gradientBaseX = gradientCalculations.baseX;
412
- const gradientBaseY = gradientCalculations.baseY;
413
-
414
- const positionStylesPosition = positionStyles.position;
415
- const positionStylesTop = positionStyles.top;
416
- const positionStylesLeft = positionStyles.left;
417
-
418
- const adjustedSizeWidth = adjustedSize.width;
419
- const adjustedSizeHeight = adjustedSize.height;
420
-
421
- const baseStyleTransform = baseStyle.transform;
422
- const opacityValuesHover1 = opacityValues.hover1;
423
- const opacityValuesHover2 = opacityValues.hover2;
424
- const opacityValuesHover3 = opacityValues.hover3;
425
- const opacityValuesBase = opacityValues.base;
426
- const opacityValuesOver = opacityValues.over;
427
-
428
- const glassVars = useMemo(() => {
429
- // RGB color values for rgba() functions
430
- // Note: CSS doesn't support rgba(var(--rgb), opacity) syntax - this is a CSS specification
431
- // limitation, not a browser support issue. We read RGB values from design tokens at mount
432
- // and cache them for performance. Falls back to defaults if tokens are not available.
433
- // Uses design tokens: --atomix-light-rgb / --atomix-white-rgb and --atomix-dark-rgb / --atomix-black-rgb
434
- const whiteColor = rgbCacheRef.current?.whiteRgb || '255, 255, 255';
435
- const blackColor = rgbCacheRef.current?.blackRgb || '0, 0, 0';
436
-
437
- return {
438
- // Standard CSS custom properties for dynamic values
439
- '--atomix-glass-radius': `${effectiveCornerRadius}px`,
440
- '--atomix-glass-transform': baseStyleTransform || 'none',
441
- '--atomix-glass-position': positionStylesPosition,
442
- '--atomix-glass-top': positionStylesTop !== 'fixed' ? `${positionStylesTop}px` : '0',
443
- '--atomix-glass-left': positionStylesLeft !== 'fixed' ? `${positionStylesLeft}px` : '0',
444
- '--atomix-glass-width':
445
- baseStylePosition !== 'fixed' ? adjustedSizeWidth : `${adjustedSizeWidth}px`,
446
- '--atomix-glass-height':
447
- baseStylePosition !== 'fixed' ? adjustedSizeHeight : `${adjustedSizeHeight}px`,
448
- // Border width: Use spacing token for consistency
449
- '--atomix-glass-border-width': 'var(--atomix-spacing-0-5, 0.09375rem)',
450
- '--atomix-glass-blend-mode': gradientIsOverLight ? 'multiply' : 'overlay',
451
- // Dynamic gradients and backgrounds
452
- // Note: RGB values use design token-aligned constants (white: 255,255,255; black: 0,0,0)
453
- '--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%)`,
454
- '--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%)`,
455
- '--atomix-glass-hover-1-opacity': opacityValuesHover1,
456
- '--atomix-glass-hover-1-gradient': gradientIsOverLight
457
- ? `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}%)`
458
- : `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}%)`,
459
- '--atomix-glass-hover-2-opacity': opacityValuesHover2,
460
- '--atomix-glass-hover-2-gradient': gradientIsOverLight
461
- ? `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}%)`
462
- : `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}%)`,
463
- '--atomix-glass-hover-3-opacity': opacityValuesHover3,
464
- '--atomix-glass-hover-3-gradient': gradientIsOverLight
465
- ? `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}%)`
466
- : `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}%)`,
467
- '--atomix-glass-base-opacity': opacityValuesBase,
468
- '--atomix-glass-base-gradient': gradientIsOverLight
469
- ? `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%)`
470
- : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.WHITE_OPACITY})`,
471
- '--atomix-glass-overlay-opacity': opacityValuesOver,
472
- '--atomix-glass-overlay-gradient': gradientIsOverLight
473
- ? `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%)`
474
- : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.WHITE_OPACITY})`,
475
- } as React.CSSProperties;
476
- }, [
477
- // Position styles - only specific properties
478
- positionStylesPosition,
479
- positionStylesTop,
480
- positionStylesLeft,
481
- // Adjusted size - only specific properties
482
- adjustedSizeWidth,
483
- adjustedSizeHeight,
484
- // Base style - only transform property
485
- baseStyleTransform,
486
- baseStylePosition,
487
- // Other values
488
- effectiveCornerRadius,
489
- effectiveReducedMotion,
490
- // Gradient calculations - extracted properties
491
- gradientIsOverLight,
492
- gradientMx,
493
- gradientMy,
494
- gradientBorderGradientAngle,
495
- gradientBorderStop1,
496
- gradientBorderStop2,
497
- gradientBorderOpacity1,
498
- gradientBorderOpacity2,
499
- gradientBorderOpacity3,
500
- gradientBorderOpacity4,
501
- gradientHover1X,
502
- gradientHover1Y,
503
- gradientHover2X,
504
- gradientHover2Y,
505
- gradientHover3X,
506
- gradientHover3Y,
507
- gradientBaseX,
508
- gradientBaseY,
509
- // Opacity values - extracted properties
510
- opacityValuesHover1,
511
- opacityValuesHover2,
512
- opacityValuesHover3,
513
- opacityValuesBase,
514
- opacityValuesOver,
515
- ]);
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;
516
290
 
517
291
  return (
518
292
  <div
@@ -526,8 +300,6 @@ export function AtomixGlass({
526
300
  aria-pressed={onClick && isActive ? true : onClick ? false : undefined}
527
301
  onKeyDown={onClick ? handleKeyDown : undefined}
528
302
  >
529
-
530
-
531
303
  <AtomixGlassContainer
532
304
  ref={glassRef}
533
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
  }