@shohojdhara/atomix 0.4.1 → 0.4.2

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 (126) hide show
  1. package/dist/atomix.css +9341 -9249
  2. package/dist/atomix.css.map +1 -1
  3. package/dist/atomix.min.css +4 -4
  4. package/dist/atomix.min.css.map +1 -1
  5. package/dist/charts.d.ts +12 -19
  6. package/dist/charts.js +555 -358
  7. package/dist/charts.js.map +1 -1
  8. package/dist/core.d.ts +16 -23
  9. package/dist/core.js +418 -262
  10. package/dist/core.js.map +1 -1
  11. package/dist/forms.d.ts +11 -18
  12. package/dist/forms.js +411 -257
  13. package/dist/forms.js.map +1 -1
  14. package/dist/heavy.d.ts +14 -21
  15. package/dist/heavy.js +408 -254
  16. package/dist/heavy.js.map +1 -1
  17. package/dist/index.d.ts +33 -40
  18. package/dist/index.esm.js +663 -453
  19. package/dist/index.esm.js.map +1 -1
  20. package/dist/index.js +667 -460
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.min.js +1 -1
  23. package/dist/index.min.js.map +1 -1
  24. package/package.json +1 -1
  25. package/scripts/atomix-cli.js +34 -1
  26. package/src/components/AtomixGlass/AtomixGlass.tsx +82 -54
  27. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +17 -18
  28. package/src/components/AtomixGlass/README.md +5 -5
  29. package/src/components/AtomixGlass/stories/Customization.stories.tsx +2 -2
  30. package/src/components/AtomixGlass/stories/Examples.stories.tsx +42 -42
  31. package/src/components/AtomixGlass/stories/Modes.stories.tsx +5 -5
  32. package/src/components/AtomixGlass/stories/Overview.stories.tsx +3 -3
  33. package/src/components/AtomixGlass/stories/Performance.stories.tsx +2 -2
  34. package/src/components/AtomixGlass/stories/Playground.stories.tsx +45 -45
  35. package/src/components/AtomixGlass/stories/Shaders.stories.tsx +3 -3
  36. package/src/components/Badge/Badge.stories.tsx +1 -1
  37. package/src/components/Badge/Badge.tsx +1 -1
  38. package/src/components/Breadcrumb/Breadcrumb.tsx +90 -76
  39. package/src/components/Breadcrumb/index.ts +2 -2
  40. package/src/components/Button/Button.stories.tsx +1 -1
  41. package/src/components/Button/README.md +2 -2
  42. package/src/components/Callout/Callout.test.tsx +3 -3
  43. package/src/components/Callout/Callout.tsx +2 -2
  44. package/src/components/Callout/README.md +2 -2
  45. package/src/components/Chart/Chart.stories.tsx +1 -1
  46. package/src/components/Chart/Chart.tsx +5 -5
  47. package/src/components/Chart/TreemapChart.tsx +37 -29
  48. package/src/components/DatePicker/readme.md +3 -3
  49. package/src/components/Dropdown/Dropdown.stories.tsx +1 -1
  50. package/src/components/EdgePanel/EdgePanel.stories.tsx +7 -7
  51. package/src/components/Form/Checkbox.stories.tsx +1 -1
  52. package/src/components/Form/Checkbox.tsx +1 -1
  53. package/src/components/Form/Input.stories.tsx +1 -1
  54. package/src/components/Form/Input.tsx +1 -1
  55. package/src/components/Form/Radio.stories.tsx +1 -1
  56. package/src/components/Form/Radio.tsx +1 -1
  57. package/src/components/Form/Select.stories.tsx +1 -1
  58. package/src/components/Form/Select.tsx +1 -1
  59. package/src/components/Form/Textarea.stories.tsx +1 -1
  60. package/src/components/Form/Textarea.tsx +1 -1
  61. package/src/components/Hero/Hero.stories.tsx +2 -2
  62. package/src/components/Hero/Hero.tsx +2 -2
  63. package/src/components/Messages/Messages.stories.tsx +1 -1
  64. package/src/components/Messages/Messages.tsx +2 -2
  65. package/src/components/Modal/Modal.stories.tsx +1 -1
  66. package/src/components/Navigation/Nav/Nav.stories.tsx +2 -2
  67. package/src/components/Navigation/Nav/Nav.tsx +1 -1
  68. package/src/components/Navigation/Navbar/Navbar.stories.tsx +3 -3
  69. package/src/components/Navigation/Navbar/Navbar.tsx +1 -1
  70. package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +2 -2
  71. package/src/components/Navigation/SideMenu/SideMenu.tsx +1 -1
  72. package/src/components/Pagination/Pagination.stories.tsx +1 -1
  73. package/src/components/Pagination/Pagination.tsx +1 -1
  74. package/src/components/Popover/Popover.stories.tsx +1 -1
  75. package/src/components/Popover/Popover.tsx +1 -1
  76. package/src/components/Progress/Progress.tsx +1 -1
  77. package/src/components/Rating/Rating.stories.tsx +1 -1
  78. package/src/components/Rating/Rating.test.tsx +73 -0
  79. package/src/components/Rating/Rating.tsx +25 -37
  80. package/src/components/Spinner/Spinner.tsx +1 -1
  81. package/src/components/Steps/Steps.stories.tsx +1 -1
  82. package/src/components/Steps/Steps.tsx +2 -2
  83. package/src/components/Tabs/Tabs.stories.tsx +1 -1
  84. package/src/components/Tabs/Tabs.tsx +1 -1
  85. package/src/components/Todo/Todo.tsx +0 -1
  86. package/src/components/Toggle/Toggle.stories.tsx +1 -1
  87. package/src/components/Toggle/Toggle.tsx +1 -1
  88. package/src/components/Tooltip/Tooltip.stories.tsx +1 -1
  89. package/src/components/VideoPlayer/VideoPlayer.stories.tsx +2 -2
  90. package/src/lib/composables/__tests__/useAtomixGlassPerf.test.tsx +88 -0
  91. package/src/lib/composables/__tests__/useChart.test.ts +50 -0
  92. package/src/lib/composables/__tests__/useChart.test.tsx +139 -0
  93. package/src/lib/composables/__tests__/useHeroBackgroundSlider.test.tsx +59 -0
  94. package/src/lib/composables/__tests__/useSliderAutoplay.test.tsx +68 -0
  95. package/src/lib/composables/atomix-glass/useGlassBackgroundDetection.ts +329 -0
  96. package/src/lib/composables/atomix-glass/useGlassCornerRadius.ts +82 -0
  97. package/src/lib/composables/atomix-glass/useGlassMouseTracking.ts +153 -0
  98. package/src/lib/composables/atomix-glass/useGlassOverLight.ts +198 -0
  99. package/src/lib/composables/atomix-glass/useGlassSize.ts +117 -0
  100. package/src/lib/composables/atomix-glass/useGlassState.ts +112 -0
  101. package/src/lib/composables/atomix-glass/useGlassTransforms.ts +160 -0
  102. package/src/lib/composables/glass-styles.ts +302 -0
  103. package/src/lib/composables/index.ts +0 -4
  104. package/src/lib/composables/useAtomixGlass.ts +331 -522
  105. package/src/lib/composables/useAtomixGlassStyles.ts +307 -0
  106. package/src/lib/composables/useBarChart.ts +1 -1
  107. package/src/lib/composables/useBreadcrumb.ts +6 -6
  108. package/src/lib/composables/useChart.ts +104 -21
  109. package/src/lib/composables/useHeroBackgroundSlider.ts +16 -7
  110. package/src/lib/composables/useSlider.ts +66 -34
  111. package/src/lib/theme/devtools/CLI.ts +1 -1
  112. package/src/lib/theme/utils/__tests__/themeUtils.test.ts +213 -0
  113. package/src/lib/types/components.ts +13 -21
  114. package/src/lib/utils/__tests__/dom.test.ts +100 -0
  115. package/src/lib/utils/__tests__/fontPreloader.test.ts +102 -0
  116. package/src/styles/02-tools/_tools.breakpoints.scss +1 -1
  117. package/src/styles/02-tools/_tools.utility-api.scss +6 -6
  118. package/src/styles/06-components/_components.accordion.scss +0 -2
  119. package/src/styles/06-components/_components.chart.scss +0 -1
  120. package/src/styles/06-components/_components.dropdown.scss +0 -1
  121. package/src/styles/06-components/_components.edge-panel.scss +0 -2
  122. package/src/styles/06-components/_components.photoviewer.scss +0 -1
  123. package/src/styles/06-components/_components.river.scss +0 -1
  124. package/src/styles/06-components/_components.slider.scss +0 -3
  125. package/src/styles/99-utilities/_utilities.glass-fixes.scss +0 -1
  126. package/src/styles/99-utilities/_utilities.text.scss +1 -0
package/dist/forms.js CHANGED
@@ -218,7 +218,7 @@ import React, { memo, forwardRef, useMemo, useState, useRef, useEffect, useCallb
218
218
  HIGH_CONTRAST: 200
219
219
  }
220
220
  }
221
- }, {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS, calculateDistance = (pos1, pos2) => {
221
+ }, {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateDistance = (pos1, pos2) => {
222
222
  if (!pos1 || !pos2 || "number" != typeof pos1.x || "number" != typeof pos1.y || "number" != typeof pos2.x || "number" != typeof pos2.y) return 0;
223
223
  const deltaX = pos1.x - pos2.x, deltaY = pos1.y - pos2.y;
224
224
  return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
@@ -231,36 +231,36 @@ import React, { memo, forwardRef, useMemo, useState, useRef, useEffect, useCallb
231
231
  }, calculateMouseInfluence = mouseOffset => {
232
232
  if (!mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y) return 0;
233
233
  // Bounded calculation — keeps the glass effect subtle and stable
234
- const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$1.MOUSE_INFLUENCE_DIVISOR;
234
+ const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$2.MOUSE_INFLUENCE_DIVISOR;
235
235
  return Math.min(.8, influence);
236
236
  // Tighter cap to prevent blur/filter blow-out
237
- }, clampBlur = value => "number" != typeof value || isNaN(value) ? CONSTANTS$1.MIN_BLUR : Math.max(CONSTANTS$1.MIN_BLUR, Math.min(50, value)), validateGlassSize = size => size && "number" == typeof size.width && "number" == typeof size.height && size.width > 0 && size.height > 0 && size.width <= CONSTANTS$1.MAX_SIZE && size.height <= CONSTANTS$1.MAX_SIZE, parseBorderRadiusValue = value => {
237
+ }, clampBlur = value => "number" != typeof value || isNaN(value) ? CONSTANTS$2.MIN_BLUR : Math.max(CONSTANTS$2.MIN_BLUR, Math.min(50, value)), validateGlassSize = size => size && "number" == typeof size.width && "number" == typeof size.height && size.width > 0 && size.height > 0 && size.width <= CONSTANTS$2.MAX_SIZE && size.height <= CONSTANTS$2.MAX_SIZE, parseBorderRadiusValue = value => {
238
238
  if ("number" == typeof value) return Math.max(0, value);
239
- if ("string" != typeof value || !value.trim()) return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
239
+ if ("string" != typeof value || !value.trim()) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
240
240
  const trimmedValue = value.trim();
241
241
  // Handle px values
242
242
  if (trimmedValue.endsWith("px")) {
243
243
  const parsed = parseFloat(trimmedValue);
244
- return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
244
+ return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
245
245
  }
246
246
  // Handle rem values (assume 16px = 1rem)
247
247
  if (trimmedValue.endsWith("rem")) {
248
248
  const parsed = parseFloat(trimmedValue);
249
- return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
249
+ return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
250
250
  }
251
251
  // Handle em values (assume 16px = 1em for simplicity)
252
252
  if (trimmedValue.endsWith("em")) {
253
253
  const parsed = parseFloat(trimmedValue);
254
- return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
254
+ return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
255
255
  }
256
256
  // Handle percentage (convert to approximate px value, assuming 200px container)
257
257
  if (trimmedValue.endsWith("%")) {
258
258
  const parsed = parseFloat(trimmedValue);
259
- return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
259
+ return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
260
260
  }
261
261
  // Handle unitless numbers
262
262
  const numValue = parseFloat(trimmedValue);
263
- return isNaN(numValue) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
263
+ return isNaN(numValue) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
264
264
  }, extractBorderRadiusFromElement = element => {
265
265
  if (!element || !element.props) return null;
266
266
  // Check inline styles first (highest priority)
@@ -276,11 +276,11 @@ import React, { memo, forwardRef, useMemo, useState, useRef, useEffect, useCallb
276
276
  // If element has children, recursively check them
277
277
  if (element.props.children) {
278
278
  const childRadius = extractBorderRadiusFromChildren(element.props.children);
279
- if (childRadius > 0 && childRadius !== CONSTANTS$1.DEFAULT_CORNER_RADIUS) return childRadius;
279
+ if (childRadius > 0 && childRadius !== CONSTANTS$2.DEFAULT_CORNER_RADIUS) return childRadius;
280
280
  }
281
281
  return null;
282
282
  }, extractBorderRadiusFromChildren = children => {
283
- if (!children) return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
283
+ if (!children) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
284
284
  try {
285
285
  const childArray = React.Children.toArray(children);
286
286
  for (let i = 0; i < childArray.length; i++) {
@@ -293,7 +293,7 @@ import React, { memo, forwardRef, useMemo, useState, useRef, useEffect, useCallb
293
293
  } catch (error) {
294
294
  // Silently handle errors
295
295
  }
296
- return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
296
+ return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
297
297
  }, getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
298
298
  switch (mode) {
299
299
  case "standard":
@@ -464,10 +464,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
464
464
  }, globalMousePosition: globalMousePosition = {
465
465
  x: 0,
466
466
  y: 0
467
- }, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isHovered: isHovered = !1, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {}, cornerRadius: cornerRadius = 0, padding: padding = "0 0", glassSize: glassSize = {
467
+ }, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isHovered: isHovered = !1, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {}, borderRadius: borderRadius = 0, padding: padding = "0 0", glassSize: glassSize = {
468
468
  width: 0,
469
469
  height: 0
470
- }, onClick: onClick, mode: mode = "standard", effectiveDisableEffects: effectiveDisableEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", enableLiquidBlur: enableLiquidBlur = !1, elasticity: elasticity = 0, contentRef: contentRef}, ref) => {
470
+ }, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, elasticity: elasticity = 0, contentRef: contentRef}, ref) => {
471
471
  // Generate a stable, deterministic ID for SSR compatibility
472
472
  // Use a module-level counter that's consistent across server and client
473
473
  const filterId = useMemo((() => "atomix-glass-filter-" + ++idCounter), []), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null);
@@ -577,7 +577,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
577
577
  flowBlur: 1.2 * blurAmount
578
578
  };
579
579
  // Enhanced validation for liquid blur
580
- if (!enableLiquidBlur || !rectCache || !mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y || isNaN(mouseOffset.x) || isNaN(mouseOffset.y)) return defaultBlur;
580
+ if (!withLiquidBlur || !rectCache || !mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y || isNaN(mouseOffset.x) || isNaN(mouseOffset.y)) return defaultBlur;
581
581
  try {
582
582
  const mouseInfluence = calculateMouseInfluence(mouseOffset), maxBlur = 2 * blurAmount, baseBlur = Math.min(maxBlur, blurAmount + mouseInfluence * blurAmount * .15), edgeIntensity = .15 * mouseInfluence, edgeBlur = Math.min(maxBlur, baseBlur * (.8 + .4 * edgeIntensity)), centerIntensity = .1 * mouseInfluence, centerBlur = Math.min(maxBlur, baseBlur * (.3 + .3 * centerIntensity)), flowBlur = Math.min(maxBlur, 1.2 * baseBlur);
583
583
  // NOTE: hover/active multipliers intentionally omitted here —
@@ -592,14 +592,14 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
592
592
  return console.warn("AtomixGlassContainer: Error calculating liquid blur", error),
593
593
  defaultBlur;
594
594
  }
595
- }), [ enableLiquidBlur, blurAmount, mouseOffset, rectCache ]), backdropStyle = useMemo((() => {
595
+ }), [ withLiquidBlur, blurAmount, mouseOffset, rectCache ]), backdropStyle = useMemo((() => {
596
596
  try {
597
597
  const dynamicSaturation = saturation + 20 * (liquidBlur.baseBlur || 0), validatedBaseBlur = "number" != typeof liquidBlur.baseBlur || isNaN(liquidBlur.baseBlur) ? 0 : liquidBlur.baseBlur, validatedEdgeBlur = "number" != typeof liquidBlur.edgeBlur || isNaN(liquidBlur.edgeBlur) ? 0 : liquidBlur.edgeBlur, validatedCenterBlur = "number" != typeof liquidBlur.centerBlur || isNaN(liquidBlur.centerBlur) ? 0 : liquidBlur.centerBlur, validatedFlowBlur = "number" != typeof liquidBlur.flowBlur || isNaN(liquidBlur.flowBlur) ? 0 : liquidBlur.flowBlur, area = rectCache ? rectCache.width * rectCache.height : 0;
598
598
  // Validate blur values before using them
599
- return !enableLiquidBlur || effectiveReducedMotion || effectiveDisableEffects || area > 18e4 ? {
599
+ return !withLiquidBlur || effectiveReducedMotion || effectiveWithoutEffects || area > 18e4 ? {
600
600
  backdropFilter: `blur(${clampBlur(Math.max(validatedBaseBlur, .8 * validatedEdgeBlur, 1.1 * validatedCenterBlur, .9 * validatedFlowBlur))}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1.05}) brightness(${overLightConfig?.brightness || 1.05})`
601
601
  } : {
602
- backdropFilter: `blur(${clampBlur(.4 * validatedBaseBlur + .25 * validatedEdgeBlur + .15 * validatedCenterBlur + .2 * validatedFlowBlur)}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1.05}) brightness(${overLightConfig?.brightness || 1.05})`
602
+ backdropFilter: `blur(${clampBlur(.4 * validatedBaseBlur + .25 * validatedEdgeBlur + .15 * validatedCenterBlur + .2 * validatedFlowBlur)}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1}) brightness(${overLightConfig?.brightness || 1})`
603
603
  };
604
604
  // Single-pass fallback: stronger radius to match perceived blur of multi-pass
605
605
  } catch (error) {
@@ -608,7 +608,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
608
608
  backdropFilter: `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`
609
609
  };
610
610
  }
611
- }), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveDisableEffects, enableLiquidBlur ]), containerVars = useMemo((() => {
611
+ }), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveWithoutEffects, withLiquidBlur ]), containerVars = useMemo((() => {
612
612
  try {
613
613
  // Safe extraction of mouse offset values
614
614
  const mx = mouseOffset && "number" == typeof mouseOffset.x && !isNaN(mouseOffset.x) ? mouseOffset.x : 0, my = mouseOffset && "number" == typeof mouseOffset.y && !isNaN(mouseOffset.y) ? mouseOffset.y : 0;
@@ -616,10 +616,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
616
616
  "--atomix-glass-container-width": `${glassSize?.width}`,
617
617
  "--atomix-glass-container-height": `${glassSize?.height}`,
618
618
  "--atomix-glass-container-padding": padding || "0 0",
619
- "--atomix-glass-container-radius": `${"number" != typeof cornerRadius || isNaN(cornerRadius) ? 0 : cornerRadius}px`,
619
+ "--atomix-glass-container-radius": `${"number" != typeof borderRadius || isNaN(borderRadius) ? 0 : borderRadius}px`,
620
620
  "--atomix-glass-container-backdrop": backdropStyle?.backdropFilter || "none",
621
621
  "--atomix-glass-container-shadow": overLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${(.4 + .002 * mx) * (overLightConfig?.shadowIntensity || 1)})`, `inset 0 -1px 0 rgba(0, 0, 0, ${(.2 + .001 * Math.abs(my)) * (overLightConfig?.shadowIntensity || 1)})`, `inset 0 0 20px rgba(0, 0, 0, ${(.08 + .001 * Math.abs(mx + my)) * (overLightConfig?.shadowIntensity || 1)})`, `0 2px 12px rgba(0, 0, 0, ${(.12 + .002 * Math.abs(my)) * (overLightConfig?.shadowIntensity || 1)})` ].join(", ") : "0 0 20px rgba(0, 0, 0, 0.15) inset, 0 4px 8px rgba(0, 0, 0, 0.08) inset",
622
- "--atomix-glass-container-shadow-opacity": effectiveDisableEffects ? 0 : 1,
622
+ "--atomix-glass-container-shadow-opacity": effectiveWithoutEffects ? 0 : 1,
623
623
  // Background and shadow values use design token-aligned RGB values
624
624
  "--atomix-glass-container-bg": overLight ? `linear-gradient(${180 + .5 * mx}deg, rgba(255, 255, 255, 0.1) 0%, transparent 20%, transparent 80%, rgba(0, 0, 0, 0.05) 100%)` : "none",
625
625
  "--atomix-glass-container-text-shadow": overLight ? "0px 2px 12px rgba(0, 0, 0, 0)" : "0px 2px 12px rgba(0, 0, 0, 0.4)",
@@ -637,14 +637,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
637
637
  "--atomix-glass-container-text-shadow": "none"
638
638
  };
639
639
  }
640
- }), [ glassSize, padding, cornerRadius, backdropStyle, mouseOffset, overLight, effectiveDisableEffects ]), setForceNoTransition = el => {
641
- el && (el.style.setProperty("transition-duration", "0s", "important"), el.style.setProperty("animation-duration", "0s", "important"),
642
- el.style.setProperty("transition-delay", "0s", "important"));
643
- };
640
+ }), [ glassSize, padding, borderRadius, backdropStyle, mouseOffset, overLight, effectiveWithoutEffects ]);
644
641
  return jsx("div", {
645
642
  ref: el => {
646
643
  // Apply force no-transition
647
- setForceNoTransition(el),
648
644
  // Handle forwarded ref
649
645
  "function" == typeof ref ? ref(el) : ref && (ref.current = el);
650
646
  },
@@ -679,7 +675,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
679
675
  aberrationIntensity: "number" != typeof aberrationIntensity || isNaN(aberrationIntensity) ? 0 : aberrationIntensity,
680
676
  shaderMapUrl: shaderMapUrl
681
677
  }), jsx("div", {
682
- ref: setForceNoTransition,
678
+ ref: el => {
679
+ el && (el.style.setProperty("transition-duration", "0s", "important"), el.style.setProperty("animation-duration", "0s", "important"),
680
+ el.style.setProperty("transition-delay", "0s", "important"));
681
+ },
683
682
  className: ATOMIX_GLASS.FILTER_OVERLAY_CLASS,
684
683
  style: {
685
684
  filter: `url(#${filterId})`,
@@ -796,7 +795,128 @@ class {
796
795
  */ getSubscriberCount() {
797
796
  return this.listeners.size;
798
797
  }
799
- }, {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
798
+ }, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
799
+ if (!wrapperElement && !containerElement) return;
800
+ const {mouseOffset: mouseOffset, globalMousePosition: globalMousePosition, glassSize: glassSize, isHovered: isHovered, isActive: isActive, isOverLight: isOverLight, baseOverLightConfig: baseOverLightConfig, effectiveBorderRadius: effectiveBorderRadius, effectiveWithoutEffects: effectiveWithoutEffects, effectiveReducedMotion: effectiveReducedMotion, elasticity: elasticity, directionalScale: directionalScale, onClick: onClick, withLiquidBlur: withLiquidBlur, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, padding: padding = ATOMIX_GLASS.DEFAULTS.PADDING} = params, mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1, overLightConfig = {
801
+ opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
802
+ contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
803
+ brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
804
+ shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
805
+ borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence)),
806
+ saturationBoost: baseOverLightConfig.saturationBoost
807
+ };
808
+ // Calculate mouse influence
809
+ // Calculate elastic translation
810
+ let elasticTranslation = {
811
+ x: 0,
812
+ y: 0
813
+ };
814
+ if (!effectiveWithoutEffects && wrapperElement) {
815
+ const rect = wrapperElement.getBoundingClientRect(), center = calculateElementCenter(rect);
816
+ // Calculate fade in factor
817
+ let fadeInFactor = 0;
818
+ if (globalMousePosition.x && globalMousePosition.y && validateGlassSize(glassSize)) {
819
+ const edgeDistanceX = Math.max(0, Math.abs(globalMousePosition.x - center.x) - glassSize.width / 2), edgeDistanceY = Math.max(0, Math.abs(globalMousePosition.y - center.y) - glassSize.height / 2), edgeDistance = calculateDistance({
820
+ x: edgeDistanceX,
821
+ y: edgeDistanceY
822
+ }, {
823
+ x: 0,
824
+ y: 0
825
+ });
826
+ fadeInFactor = edgeDistance > ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE ? 0 : 1 - edgeDistance / ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE;
827
+ }
828
+ elasticTranslation = {
829
+ x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
830
+ y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
831
+ };
832
+ }
833
+ const transformStyle = effectiveWithoutEffects ? isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)" : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) ${isActive && Boolean(onClick) ? "scale(0.96)" : directionalScale}`;
834
+ // Update Wrapper Styles (glassVars)
835
+ if (wrapperElement) {
836
+ const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT, borderGradientAngle = GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER, borderStop1 = Math.max(GRADIENT.BORDER_STOP_1.MIN, GRADIENT.BORDER_STOP_1.BASE + my * GRADIENT.BORDER_STOP_1.MULTIPLIER), borderStop2 = Math.min(GRADIENT.BORDER_STOP_2.MAX, GRADIENT.BORDER_STOP_2.BASE + my * GRADIENT.BORDER_STOP_2.MULTIPLIER), borderOpacities = [ GRADIENT.BORDER_OPACITY.BASE_1 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW, GRADIENT.BORDER_OPACITY.BASE_2 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH, GRADIENT.BORDER_OPACITY.BASE_3 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW, GRADIENT.BORDER_OPACITY.BASE_4 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH ], configBorderOpacity = overLightConfig.borderOpacity, whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE, blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK, hoverPositions = {
837
+ hover1: {
838
+ x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1,
839
+ y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1
840
+ },
841
+ hover2: {
842
+ x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_2,
843
+ y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_2
844
+ },
845
+ hover3: {
846
+ x: GRADIENT.CENTER_POSITION + mx * GRADIENT.HOVER_POSITION.MULTIPLIER_3,
847
+ y: GRADIENT.CENTER_POSITION + my * GRADIENT.HOVER_POSITION.MULTIPLIER_3
848
+ }
849
+ }, basePosition = {
850
+ x: GRADIENT.CENTER_POSITION + mx * GRADIENT.BASE_LAYER_MULTIPLIER,
851
+ y: GRADIENT.CENTER_POSITION + my * GRADIENT.BASE_LAYER_MULTIPLIER
852
+ }, opacityValues = {
853
+ hover1: isHovered || isActive ? .5 : 0,
854
+ hover2: isActive ? .5 : 0,
855
+ hover3: isHovered ? .4 : isActive ? .8 : 0,
856
+ base: isOverLight ? overLightConfig.opacity : 0,
857
+ over: isOverLight ? 1.1 * overLightConfig.opacity : 0
858
+ }, style = wrapperElement.style;
859
+ style.setProperty("--atomix-glass-transform", transformStyle || "none"),
860
+ // Gradients
861
+ style.setProperty("--atomix-glass-border-gradient-1", `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[0] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[1] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`),
862
+ style.setProperty("--atomix-glass-border-gradient-2", `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[2] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[3] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`),
863
+ // Hover gradients
864
+ style.setProperty("--atomix-glass-hover-1-gradient", isOverLight ? `radial-gradient(circle at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, 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}%)` : `radial-gradient(circle at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_STOP}%)`),
865
+ style.setProperty("--atomix-glass-hover-2-gradient", isOverLight ? `radial-gradient(circle at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, 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}%)` : `radial-gradient(circle at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_STOP}%)`),
866
+ style.setProperty("--atomix-glass-hover-3-gradient", isOverLight ? `radial-gradient(circle at ${hoverPositions.hover3.x}% ${hoverPositions.hover3.y}%, 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}%)` : `radial-gradient(circle at ${hoverPositions.hover3.x}% ${hoverPositions.hover3.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_STOP}%)`),
867
+ style.setProperty("--atomix-glass-base-gradient", isOverLight ? `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 + absMx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.WHITE_OPACITY})`),
868
+ style.setProperty("--atomix-glass-overlay-gradient", isOverLight ? `radial-gradient(circle at ${basePosition.x}% ${basePosition.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_BASE + absMx * 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 + absMy * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.WHITE_OPACITY})`),
869
+ // Opacities
870
+ style.setProperty("--atomix-glass-hover-1-opacity", opacityValues.hover1.toString()),
871
+ style.setProperty("--atomix-glass-hover-2-opacity", opacityValues.hover2.toString()),
872
+ style.setProperty("--atomix-glass-hover-3-opacity", opacityValues.hover3.toString()),
873
+ style.setProperty("--atomix-glass-base-opacity", opacityValues.base.toString()),
874
+ style.setProperty("--atomix-glass-overlay-opacity", opacityValues.over.toString()),
875
+ style.setProperty("--atomix-glass-overlay-highlight-opacity", (opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER).toString()),
876
+ // Other
877
+ style.setProperty("--atomix-glass-blend-mode", isOverLight ? "multiply" : "overlay"),
878
+ style.setProperty("--atomix-glass-radius", `${effectiveBorderRadius}px`);
879
+ }
880
+ // Update Container Styles (containerVars)
881
+ if (containerElement) {
882
+ const mx = mouseOffset.x, my = mouseOffset.y, EDGE_BLUR_MULTIPLIER = 1.25, CENTER_BLUR_MULTIPLIER = 1.1, FLOW_BLUR_MULTIPLIER = 1.2, MOUSE_INFLUENCE_BLUR_FACTOR = .15, EDGE_INTENSITY_MOUSE_FACTOR = .15, CENTER_INTENSITY_MOUSE_FACTOR = .1, MAX_BLUR_RELATIVE = 2, rect = containerElement.getBoundingClientRect();
883
+ let liquidBlur = {
884
+ baseBlur: blurAmount,
885
+ edgeBlur: blurAmount * EDGE_BLUR_MULTIPLIER,
886
+ centerBlur: blurAmount * CENTER_BLUR_MULTIPLIER,
887
+ flowBlur: blurAmount * FLOW_BLUR_MULTIPLIER
888
+ };
889
+ if (withLiquidBlur && rect) {
890
+ const mouseInfluence = calculateMouseInfluence(mouseOffset), maxBlur = blurAmount * MAX_BLUR_RELATIVE, baseBlur = Math.min(maxBlur, blurAmount + mouseInfluence * blurAmount * MOUSE_INFLUENCE_BLUR_FACTOR), edgeIntensity = mouseInfluence * EDGE_INTENSITY_MOUSE_FACTOR, edgeBlur = Math.min(maxBlur, baseBlur * (.8 + .4 * edgeIntensity)), centerIntensity = mouseInfluence * CENTER_INTENSITY_MOUSE_FACTOR, centerBlur = Math.min(maxBlur, baseBlur * (.3 + .3 * centerIntensity)), flowBlur = Math.min(maxBlur, baseBlur * FLOW_BLUR_MULTIPLIER);
891
+ liquidBlur = {
892
+ baseBlur: clampBlur(baseBlur),
893
+ edgeBlur: clampBlur(edgeBlur),
894
+ centerBlur: clampBlur(centerBlur),
895
+ flowBlur: clampBlur(flowBlur)
896
+ };
897
+ }
898
+ // Backdrop filter
899
+ let backdropFilterString = `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`;
900
+ const dynamicSaturation = saturation + 20 * (liquidBlur.baseBlur || 0), area = rect ? rect.width * rect.height : 0;
901
+ backdropFilterString = !withLiquidBlur || effectiveReducedMotion || effectiveWithoutEffects || area > 18e4 ? `blur(${clampBlur(Math.max(liquidBlur.baseBlur, .8 * liquidBlur.edgeBlur, 1.1 * liquidBlur.centerBlur, .9 * liquidBlur.flowBlur))}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig.contrast}) brightness(${overLightConfig.brightness})` : `blur(${clampBlur(.4 * liquidBlur.baseBlur + .25 * liquidBlur.edgeBlur + .15 * liquidBlur.centerBlur + .2 * liquidBlur.flowBlur)}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig.contrast}) brightness(${overLightConfig.brightness})`;
902
+ // Container variables
903
+ const style = containerElement.style;
904
+ style.setProperty("--atomix-glass-container-width", `${glassSize.width}`), style.setProperty("--atomix-glass-container-height", `${glassSize.height}`),
905
+ style.setProperty("--atomix-glass-container-padding", padding), style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
906
+ style.setProperty("--atomix-glass-container-backdrop", backdropFilterString),
907
+ // Shadows
908
+ style.setProperty("--atomix-glass-container-shadow", isOverLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${(.4 + .002 * mx) * (overLightConfig.shadowIntensity || 1)})`, `inset 0 -1px 0 rgba(0, 0, 0, ${(.2 + .001 * Math.abs(my)) * (overLightConfig.shadowIntensity || 1)})`, `inset 0 0 20px rgba(0, 0, 0, ${(.08 + .001 * Math.abs(mx + my)) * (overLightConfig.shadowIntensity || 1)})`, `0 2px 12px rgba(0, 0, 0, ${(.12 + .002 * Math.abs(my)) * (overLightConfig.shadowIntensity || 1)})` ].join(", ") : "0 0 20px rgba(0, 0, 0, 0.15) inset, 0 4px 8px rgba(0, 0, 0, 0.08) inset"),
909
+ style.setProperty("--atomix-glass-container-shadow-opacity", effectiveWithoutEffects ? "0" : "1"),
910
+ style.setProperty("--atomix-glass-container-bg", isOverLight ? `linear-gradient(${180 + .5 * mx}deg, rgba(255, 255, 255, 0.1) 0%, transparent 20%, transparent 80%, rgba(0, 0, 0, 0.05) 100%)` : "none"),
911
+ style.setProperty("--atomix-glass-container-text-shadow", isOverLight ? "0px 2px 12px rgba(0, 0, 0, 0)" : "0px 2px 12px rgba(0, 0, 0, 0.4)"),
912
+ style.setProperty("--atomix-glass-container-box-shadow", isOverLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "0px 12px 40px rgba(0, 0, 0, 0.25)");
913
+ }
914
+ }, {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS;
915
+
916
+ /**
917
+ * Updates the styles of the AtomixGlass wrapper and container elements imperatively
918
+ * to avoid React re-renders on mouse movement.
919
+ */ const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
800
920
  parentElement && backgroundDetectionCache.set(parentElement, {
801
921
  result: result,
802
922
  timestamp: Date.now(),
@@ -809,18 +929,74 @@ class {
809
929
  * Composable hook for AtomixGlass component logic
810
930
  * Manages all state, calculations, and event handlers
811
931
  */
812
- function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadius: cornerRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, disableEffects: disableEffects = !1, elasticity: elasticity = .05, onClick: onClick, debugCornerRadius: debugCornerRadius = !1, debugOverLight: debugOverLight = !1, children: children}) {
932
+ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef: wrapperRef, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, elasticity: elasticity = .05, onClick: onClick, debugBorderRadius: debugBorderRadius = !1, debugOverLight: debugOverLight = !1, debugPerformance: debugPerformance = !1, children: children, blurAmount: blurAmount, saturation: saturation, padding: padding, withLiquidBlur: withLiquidBlur}) {
813
933
  // State
814
- const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), [glassSize, setGlassSize] = useState({
815
- width: 270,
816
- height: 69
817
- }), [internalGlobalMousePosition, setInternalGlobalMousePosition] = useState({
934
+ const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), cachedRectRef = useRef(null), internalGlobalMousePositionRef = useRef({
818
935
  x: 0,
819
936
  y: 0
820
- }), [internalMouseOffset, setInternalMouseOffset] = useState({
937
+ }), internalMouseOffsetRef = useRef({
821
938
  x: 0,
822
939
  y: 0
823
- }), [dynamicCornerRadius, setDynamicCornerRadius] = useState(CONSTANTS.DEFAULT_CORNER_RADIUS), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1), effectiveCornerRadius = useMemo((() => void 0 !== cornerRadius ? Math.max(0, cornerRadius) : Math.max(0, dynamicCornerRadius)), [ cornerRadius, dynamicCornerRadius ]), effectiveReducedMotion = useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveHighContrast = useMemo((() => highContrast || userPrefersHighContrast), [ highContrast, userPrefersHighContrast ]), effectiveDisableEffects = useMemo((() => disableEffects || effectiveReducedMotion), [ disableEffects, effectiveReducedMotion ]), globalMousePosition = useMemo((() => externalGlobalMousePosition || internalGlobalMousePosition), [ externalGlobalMousePosition, internalGlobalMousePosition ]), mouseOffset = useMemo((() => externalMouseOffset || internalMouseOffset), [ externalMouseOffset, internalMouseOffset ]);
940
+ }), [dynamicBorderRadius, setDynamicCornerRadius] = useState(CONSTANTS.DEFAULT_CORNER_RADIUS), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1), effectiveBorderRadius = useMemo((() => void 0 !== borderRadius ? Math.max(0, borderRadius) : Math.max(0, dynamicBorderRadius)), [ borderRadius, dynamicBorderRadius ]), {glassSize: glassSize} = function({glassRef: glassRef, effectiveBorderRadius: effectiveBorderRadius, cachedRectRef: cachedRectRef}) {
941
+ const [glassSize, setGlassSize] = useState({
942
+ width: 270,
943
+ height: 69
944
+ });
945
+ return useEffect((() => {
946
+ const isValidElement = element => null !== element && element instanceof HTMLElement && element.isConnected;
947
+ let rafId = null, lastSize = {
948
+ width: 0,
949
+ height: 0
950
+ }, lastCornerRadius = effectiveBorderRadius;
951
+ const updateGlassSize = (forceUpdate = !1) => {
952
+ null !== rafId && cancelAnimationFrame(rafId), rafId = requestAnimationFrame((() => {
953
+ if (!isValidElement(glassRef.current)) return void (rafId = null);
954
+ const rect = glassRef.current.getBoundingClientRect();
955
+ if (rect.width <= 0 || rect.height <= 0) return void (rafId = null);
956
+ // Measure actual rendered size without artificial offsets to avoid feedback loops
957
+ const newSize = {
958
+ width: Math.round(rect.width),
959
+ height: Math.round(rect.height)
960
+ }, cornerRadiusChanged = lastCornerRadius !== effectiveBorderRadius, dimensionsChanged = Math.abs(newSize.width - lastSize.width) > 1 || Math.abs(newSize.height - lastSize.height) > 1;
961
+ var size;
962
+ (forceUpdate || cornerRadiusChanged || dimensionsChanged) && validateGlassSize(size = newSize) && size.width <= CONSTANTS$1.MAX_SIZE && size.height <= CONSTANTS$1.MAX_SIZE && (lastSize = newSize,
963
+ lastCornerRadius = effectiveBorderRadius, setGlassSize(newSize)), rafId = null;
964
+ }));
965
+ };
966
+ let resizeTimeoutId = null;
967
+ const debouncedResizeHandler = () => {
968
+ resizeTimeoutId && clearTimeout(resizeTimeoutId), resizeTimeoutId = setTimeout((() => updateGlassSize(!1)), 16);
969
+ }, initialTimeoutId = setTimeout((() => updateGlassSize(!0)), 0);
970
+ let resizeObserver = null, resizeDebounceTimeout = null;
971
+ // ResizeObserver has 98%+ browser support, no need for fallback
972
+ if ("undefined" != typeof ResizeObserver && isValidElement(glassRef.current)) try {
973
+ resizeObserver = new ResizeObserver((entries => {
974
+ for (const entry of entries) if (entry.target === glassRef.current) {
975
+ // Update cached rect when size changes
976
+ glassRef.current && cachedRectRef && (cachedRectRef.current = glassRef.current.getBoundingClientRect()),
977
+ // Debounce resize updates to match RAF timing (16ms)
978
+ resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), resizeDebounceTimeout = setTimeout((() => updateGlassSize(!1)), 16);
979
+ break;
980
+ }
981
+ })), resizeObserver.observe(glassRef.current);
982
+ } catch (error) {
983
+ console.warn("AtomixGlass: ResizeObserver not available, using window resize only", error);
984
+ }
985
+ return window.addEventListener("resize", debouncedResizeHandler, {
986
+ passive: !0
987
+ }), () => {
988
+ clearTimeout(initialTimeoutId), null !== rafId && cancelAnimationFrame(rafId), resizeTimeoutId && clearTimeout(resizeTimeoutId),
989
+ resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), window.removeEventListener("resize", debouncedResizeHandler),
990
+ resizeObserver?.disconnect();
991
+ };
992
+ }), [ effectiveBorderRadius, glassRef, cachedRectRef ]), {
993
+ glassSize: glassSize
994
+ };
995
+ }({
996
+ glassRef: glassRef,
997
+ effectiveBorderRadius: effectiveBorderRadius,
998
+ cachedRectRef: cachedRectRef
999
+ }), effectiveReducedMotion = useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveHighContrast = useMemo((() => highContrast || userPrefersHighContrast), [ highContrast, userPrefersHighContrast ]), effectiveWithoutEffects = useMemo((() => withoutEffects || effectiveReducedMotion), [ withoutEffects, effectiveReducedMotion ]), globalMousePosition = externalGlobalMousePosition || internalGlobalMousePositionRef.current, mouseOffset = externalMouseOffset || internalMouseOffsetRef.current;
824
1000
  // Extract border-radius from children
825
1001
  useEffect((() => {
826
1002
  const extractRadius = () => {
@@ -851,13 +1027,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
851
1027
  }
852
1028
  null !== extractedRadius && extractedRadius > 0 && setDynamicCornerRadius(extractedRadius);
853
1029
  } catch (error) {
854
- "undefined" != typeof process && "production" === process.env?.NODE_ENV || !debugCornerRadius || console.error("[AtomixGlass] Error extracting corner radius:", error);
1030
+ "undefined" != typeof process && "production" === process.env?.NODE_ENV || !debugBorderRadius || console.error("[AtomixGlass] Error extracting corner radius:", error);
855
1031
  }
856
1032
  };
857
1033
  extractRadius();
858
1034
  const timeoutId = setTimeout(extractRadius, 100);
859
1035
  return () => clearTimeout(timeoutId);
860
- }), [ children, debugCornerRadius, contentRef ]),
1036
+ }), [ children, debugBorderRadius, contentRef ]),
861
1037
  // Media query handlers and background detection
862
1038
  useEffect((() => {
863
1039
  if (("auto" === overLight || "object" == typeof overLight && null !== overLight) && glassRef.current) {
@@ -913,72 +1089,52 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
913
1089
  const rgb = bgColor.match(/\d+/g);
914
1090
  if (rgb && rgb.length >= 3) {
915
1091
  const r = Number(rgb[0]), g = Number(rgb[1]), b = Number(rgb[2]);
916
- // Validate RGB values are valid numbers
917
- if (!isNaN(r) && !isNaN(g) && !isNaN(b) && isFinite(r) && isFinite(g) && isFinite(b) && r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255 && (r > 10 || g > 10 || b > 10)) {
1092
+ if (!isNaN(r) && !isNaN(g) && !isNaN(b) && (r > 10 || g > 10 || b > 10)) {
918
1093
  const luminance = (.299 * r + .587 * g + .114 * b) / 255;
919
1094
  !isNaN(luminance) && isFinite(luminance) && (totalLuminance += luminance, validSamples++,
920
1095
  hasValidBackground = !0);
921
1096
  }
922
1097
  }
923
1098
  }
924
- // Check for image backgrounds
925
- bgImage && "none" !== bgImage && "initial" !== bgImage && (
926
- // For image backgrounds, assume medium luminance
927
- totalLuminance += .5, validSamples++, hasValidBackground = !0);
1099
+ bgImage && "none" !== bgImage && "initial" !== bgImage && (totalLuminance += .5,
1100
+ validSamples++, hasValidBackground = !0);
928
1101
  } catch (styleError) {
929
- "undefined" == typeof process || process.env;
1102
+ // Silently continue
930
1103
  }
931
- // Move to parent element for next iteration
932
- if (!currentElement) break;
933
- // Exit loop if currentElement becomes null
934
- currentElement = currentElement.parentElement, depth++;
1104
+ if (!currentElement) break;
1105
+ currentElement = currentElement.parentElement, depth++;
935
1106
  }
936
- // More conservative detection with better error handling
937
- if (hasValidBackground && validSamples > 0) {
1107
+ if (hasValidBackground && validSamples > 0) {
938
1108
  const avgLuminance = totalLuminance / validSamples;
939
1109
  if (!isNaN(avgLuminance) && isFinite(avgLuminance)) {
940
1110
  let threshold = .7;
941
- // Conservative threshold for overlight
942
- // If overLight is an object, use its threshold property with validation
943
- if ("object" == typeof overLight && null !== overLight) {
1111
+ if ("object" == typeof overLight && null !== overLight) {
944
1112
  const objConfig = overLight;
945
1113
  if (void 0 !== objConfig.threshold) {
946
- const configThreshold = "number" == typeof objConfig.threshold && !isNaN(objConfig.threshold) && isFinite(objConfig.threshold) ? objConfig.threshold : .7;
1114
+ const configThreshold = "number" != typeof objConfig.threshold || isNaN(objConfig.threshold) ? .7 : objConfig.threshold;
947
1115
  threshold = Math.min(.9, Math.max(.1, configThreshold));
948
1116
  }
949
1117
  }
950
1118
  const isOverLightDetected = avgLuminance > threshold;
951
- // Cache the result in shared cache
952
- setCachedBackgroundDetection(element.parentElement, overLight, isOverLightDetected, threshold),
1119
+ setCachedBackgroundDetection(element.parentElement, overLight, isOverLightDetected, threshold),
953
1120
  setDetectedOverLight(isOverLightDetected);
954
1121
  } else {
955
- // Invalid luminance calculation, default to false
956
1122
  const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
957
1123
  setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
958
1124
  setDetectedOverLight(result);
959
1125
  }
960
1126
  } else {
961
- // Default to false if no valid background found
962
1127
  const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
963
1128
  setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
964
1129
  setDetectedOverLight(result);
965
1130
  }
966
1131
  } catch (error) {
967
- // Enhanced error logging with context
968
- "undefined" != typeof process && "development" !== process.env?.NODE_ENV || console.warn("AtomixGlass: Error detecting background brightness:", error);
969
- const result = !1;
970
- if (element && element.parentElement) {
971
- const threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
972
- setCachedBackgroundDetection(element.parentElement, overLight, result, threshold);
973
- }
974
- setDetectedOverLight(result);
1132
+ setDetectedOverLight(!1);
975
1133
  }
976
1134
  }), 150);
977
1135
  return () => clearTimeout(timeoutId);
978
1136
  }
979
- if ("boolean" == typeof overLight &&
980
- // For boolean values, disable auto-detection
981
- setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
1137
+ if ("boolean" == typeof overLight && setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
982
1138
  const mediaQueryReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)"), mediaQueryHighContrast = window.matchMedia("(prefers-contrast: high)");
983
1139
  setUserPrefersReducedMotion(mediaQueryReducedMotion.matches), setUserPrefersHighContrast(mediaQueryHighContrast.matches);
984
1140
  const handleReducedMotionChange = e => {
@@ -989,64 +1145,54 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
989
1145
  return mediaQueryReducedMotion.addEventListener ? (mediaQueryReducedMotion.addEventListener("change", handleReducedMotionChange),
990
1146
  mediaQueryHighContrast.addEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.addListener && (mediaQueryReducedMotion.addListener(handleReducedMotionChange),
991
1147
  mediaQueryHighContrast.addListener(handleHighContrastChange)), () => {
992
- try {
993
- mediaQueryReducedMotion.removeEventListener ? (mediaQueryReducedMotion.removeEventListener("change", handleReducedMotionChange),
994
- mediaQueryHighContrast.removeEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.removeListener && (mediaQueryReducedMotion.removeListener(handleReducedMotionChange),
995
- mediaQueryHighContrast.removeListener(handleHighContrastChange));
996
- } catch (cleanupError) {
997
- console.error("AtomixGlass: Error cleaning up media query listeners:", cleanupError);
998
- }
1148
+ // ignore
999
1149
  };
1000
1150
  } catch (error) {
1001
- return void console.error("AtomixGlass: Error setting up media queries:", error);
1151
+ return;
1002
1152
  }
1003
1153
  }), [ overLight, glassRef, debugOverLight ]);
1004
- // Mouse tracking using shared global tracker
1005
- // Cache bounding rect to avoid repeated getBoundingClientRect calls
1006
- const cachedRectRef = useRef(null), updateRectRef = useRef(null), handleGlobalMousePosition = useCallback((globalPos => {
1007
- if (externalGlobalMousePosition && externalMouseOffset)
1008
- // External mouse position provided, skip internal tracking
1009
- return;
1010
- if (effectiveDisableEffects) return;
1011
- const container = mouseContainer?.current || glassRef.current;
1012
- if (!container) return;
1013
- // Use cached rect if available, otherwise get new one
1014
- let rect = cachedRectRef.current;
1015
- if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
1016
- cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
1017
- const center = calculateElementCenter(rect), newOffset = {
1018
- x: (globalPos.x - center.x) / rect.width * 100,
1019
- y: (globalPos.y - center.y) / rect.height * 100
1154
+ /**
1155
+ * Get effective overLight value based on configuration
1156
+ */
1157
+ const getEffectiveOverLight = useCallback((() => "boolean" == typeof overLight ? overLight : ("auto" === overLight || "object" == typeof overLight && null !== overLight) && detectedOverLight), [ overLight, detectedOverLight ]), validateConfigValue = useCallback(((value, min, max, defaultValue) => "number" != typeof value || isNaN(value) || !isFinite(value) ? defaultValue : Math.min(max, Math.max(min, value))), []), baseOverLightConfig = useMemo((() => {
1158
+ const isOverLight = getEffectiveOverLight(), baseConfig = {
1159
+ isOverLight: isOverLight,
1160
+ threshold: .7,
1161
+ opacity: isOverLight ? Math.min(.6, Math.max(.2, .5)) : 0,
1162
+ contrast: 1,
1163
+ // Base contrast
1164
+ brightness: 1,
1165
+ // Base brightness
1166
+ saturationBoost: 1.3,
1167
+ shadowIntensity: .9,
1168
+ borderOpacity: .7
1020
1169
  };
1021
- // Calculate offset relative to this container
1022
- // React 18 automatically batches these updates
1023
- setInternalMouseOffset(newOffset), setInternalGlobalMousePosition(globalPos);
1024
- }), [ mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveDisableEffects ]);
1025
- // Subscribe to shared mouse tracker
1026
- useEffect((() => {
1027
- if (externalGlobalMousePosition && externalMouseOffset)
1028
- // External mouse position provided, don't subscribe
1029
- return;
1030
- if (effectiveDisableEffects)
1031
- // Effects disabled, don't subscribe
1032
- return;
1033
- // Subscribe to shared tracker
1034
- const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition), container = mouseContainer?.current || glassRef.current;
1035
- // Update cached rect when container size changes
1036
- let resizeObserver = null;
1037
- return container && "undefined" != typeof ResizeObserver && (resizeObserver = new ResizeObserver((() => {
1038
- null !== updateRectRef.current && cancelAnimationFrame(updateRectRef.current), updateRectRef.current = requestAnimationFrame((() => {
1039
- const container = mouseContainer?.current || glassRef.current;
1040
- container && (cachedRectRef.current = container.getBoundingClientRect()), updateRectRef.current = null;
1041
- }));
1042
- })), resizeObserver.observe(container)), () => {
1043
- unsubscribe(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
1044
- updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
1170
+ if ("object" == typeof overLight && null !== overLight) {
1171
+ const objConfig = overLight, validatedThreshold = validateConfigValue(objConfig.threshold, .1, 1, baseConfig.threshold), validatedOpacity = validateConfigValue(objConfig.opacity, .1, 1, baseConfig.opacity), validatedContrast = validateConfigValue(objConfig.contrast, .5, 2.5, baseConfig.contrast), validatedBrightness = validateConfigValue(objConfig.brightness, .5, 2, baseConfig.brightness), validatedSaturationBoost = validateConfigValue(objConfig.saturationBoost, .5, 3, baseConfig.saturationBoost);
1172
+ return {
1173
+ ...baseConfig,
1174
+ threshold: validatedThreshold,
1175
+ opacity: validatedOpacity,
1176
+ contrast: validatedContrast,
1177
+ brightness: validatedBrightness,
1178
+ saturationBoost: validatedSaturationBoost
1179
+ };
1180
+ }
1181
+ return baseConfig;
1182
+ }), [ overLight, getEffectiveOverLight, validateConfigValue ]), overLightConfig = useMemo((() => {
1183
+ const mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1;
1184
+ return {
1185
+ isOverLight: baseOverLightConfig.isOverLight,
1186
+ threshold: baseOverLightConfig.threshold,
1187
+ opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
1188
+ contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
1189
+ brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
1190
+ saturationBoost: baseOverLightConfig.saturationBoost,
1191
+ shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
1192
+ borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence))
1045
1193
  };
1046
- }), [ handleGlobalMousePosition, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveDisableEffects ]);
1047
- // Transform calculations
1048
- const calculateDirectionalScale = useCallback((() => {
1049
- if (!0 === overLight || "auto" === overLight && detectedOverLight || "object" == typeof overLight && null !== overLight && detectedOverLight) return "scale(1)";
1194
+ }), [ baseOverLightConfig, mouseOffset, isHovered, isActive ]), updateRectRef = useRef(null), calculateDirectionalScale = useCallback((() => {
1195
+ if (baseOverLightConfig.isOverLight) return "scale(1)";
1050
1196
  if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return "scale(1)";
1051
1197
  const rect = glassRef.current.getBoundingClientRect(), center = calculateElementCenter(rect), deltaX = globalMousePosition.x - center.x, deltaY = globalMousePosition.y - center.y, edgeDistanceX = Math.max(0, Math.abs(deltaX) - glassSize.width / 2), edgeDistanceY = Math.max(0, Math.abs(deltaY) - glassSize.height / 2), edgeDistance = calculateDistance({
1052
1198
  x: edgeDistanceX,
@@ -1060,7 +1206,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1060
1206
  if (0 === centerDistance) return "scale(1)";
1061
1207
  const normalizedX = deltaX / centerDistance, normalizedY = deltaY / centerDistance, stretchIntensity = Math.min(centerDistance / 300, 1) * elasticity * fadeInFactor, scaleX = 1 + Math.abs(normalizedX) * stretchIntensity * .3 - Math.abs(normalizedY) * stretchIntensity * .15, scaleY = 1 + Math.abs(normalizedY) * stretchIntensity * .3 - Math.abs(normalizedX) * stretchIntensity * .15;
1062
1208
  return `scaleX(${Math.max(.8, scaleX)}) scaleY(${Math.max(.8, scaleY)})`;
1063
- }), [ globalMousePosition, elasticity, glassSize, glassRef, overLight, detectedOverLight ]), calculateFadeInFactor = useCallback((() => {
1209
+ }), [ globalMousePosition, elasticity, glassSize, glassRef, baseOverLightConfig ]), calculateFadeInFactor = useCallback((() => {
1064
1210
  if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return 0;
1065
1211
  const rect = glassRef.current.getBoundingClientRect(), center = calculateElementCenter(rect), edgeDistanceX = Math.max(0, Math.abs(globalMousePosition.x - center.x) - glassSize.width / 2), edgeDistanceY = Math.max(0, Math.abs(globalMousePosition.y - center.y) - glassSize.height / 2), edgeDistance = calculateDistance({
1066
1212
  x: edgeDistanceX,
@@ -1080,122 +1226,110 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1080
1226
  x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
1081
1227
  y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
1082
1228
  };
1083
- }), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = useMemo((() => effectiveDisableEffects ? {
1229
+ }), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = useMemo((() => effectiveWithoutEffects ? {
1084
1230
  x: 0,
1085
1231
  y: 0
1086
- } : calculateElasticTranslation()), [ calculateElasticTranslation, effectiveDisableEffects ]), directionalScale = useMemo((() => effectiveDisableEffects ? "scale(1)" : calculateDirectionalScale()), [ calculateDirectionalScale, effectiveDisableEffects ]), transformStyle = useMemo((() => effectiveDisableEffects ? isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)" : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) ${isActive && Boolean(onClick) ? "scale(0.96)" : directionalScale}`), [ elasticTranslation, isActive, onClick, directionalScale, effectiveDisableEffects ]);
1087
- // Size management
1088
- useEffect((() => {
1089
- const isValidElement = element => null !== element && element instanceof HTMLElement && element.isConnected;
1090
- let rafId = null, lastSize = {
1091
- width: 0,
1092
- height: 0
1093
- }, lastCornerRadius = effectiveCornerRadius;
1094
- const updateGlassSize = (forceUpdate = !1) => {
1095
- null !== rafId && cancelAnimationFrame(rafId), rafId = requestAnimationFrame((() => {
1096
- if (!isValidElement(glassRef.current)) return void (rafId = null);
1097
- const rect = glassRef.current.getBoundingClientRect();
1098
- if (rect.width <= 0 || rect.height <= 0) return void (rafId = null);
1099
- // Measure actual rendered size without artificial offsets to avoid feedback loops
1100
- const newSize = {
1101
- width: Math.round(rect.width),
1102
- height: Math.round(rect.height)
1103
- }, cornerRadiusChanged = lastCornerRadius !== effectiveCornerRadius, dimensionsChanged = Math.abs(newSize.width - lastSize.width) > 1 || Math.abs(newSize.height - lastSize.height) > 1;
1104
- var size;
1105
- (forceUpdate || cornerRadiusChanged || dimensionsChanged) && validateGlassSize(size = newSize) && size.width <= CONSTANTS.MAX_SIZE && size.height <= CONSTANTS.MAX_SIZE && (lastSize = newSize,
1106
- lastCornerRadius = effectiveCornerRadius, setGlassSize(newSize)), rafId = null;
1107
- }));
1108
- };
1109
- let resizeTimeoutId = null;
1110
- const debouncedResizeHandler = () => {
1111
- resizeTimeoutId && clearTimeout(resizeTimeoutId), resizeTimeoutId = setTimeout((() => updateGlassSize(!1)), 16);
1112
- }, initialTimeoutId = setTimeout((() => updateGlassSize(!0)), 0);
1113
- let resizeObserver = null, resizeDebounceTimeout = null;
1114
- // ResizeObserver has 98%+ browser support, no need for fallback
1115
- if ("undefined" != typeof ResizeObserver && isValidElement(glassRef.current)) try {
1116
- resizeObserver = new ResizeObserver((entries => {
1117
- for (const entry of entries) if (entry.target === glassRef.current) {
1118
- // Update cached rect when size changes
1119
- glassRef.current && (cachedRectRef.current = glassRef.current.getBoundingClientRect()),
1120
- // Debounce resize updates to match RAF timing (16ms)
1121
- resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), resizeDebounceTimeout = setTimeout((() => updateGlassSize(!1)), 16);
1122
- break;
1123
- }
1124
- })), resizeObserver.observe(glassRef.current);
1125
- } catch (error) {
1126
- console.warn("AtomixGlass: ResizeObserver not available, using window resize only", error);
1127
- }
1128
- return window.addEventListener("resize", debouncedResizeHandler, {
1129
- passive: !0
1130
- }), () => {
1131
- clearTimeout(initialTimeoutId), null !== rafId && cancelAnimationFrame(rafId), resizeTimeoutId && clearTimeout(resizeTimeoutId),
1132
- resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), window.removeEventListener("resize", debouncedResizeHandler),
1133
- resizeObserver?.disconnect();
1232
+ } : calculateElasticTranslation()), [ calculateElasticTranslation, effectiveWithoutEffects ]), directionalScale = useMemo((() => effectiveWithoutEffects ? "scale(1)" : calculateDirectionalScale()), [ calculateDirectionalScale, effectiveWithoutEffects ]), transformStyle = useMemo((() => effectiveWithoutEffects ? isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)" : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) ${isActive && Boolean(onClick) ? "scale(0.96)" : directionalScale}`), [ elasticTranslation, isActive, onClick, directionalScale, effectiveWithoutEffects ]), handleGlobalMousePosition = useCallback((globalPos => {
1233
+ if (externalGlobalMousePosition && externalMouseOffset) return;
1234
+ if (effectiveWithoutEffects) return;
1235
+ const container = mouseContainer?.current || glassRef.current;
1236
+ if (!container) return;
1237
+ // Use cached rect if available, otherwise get new one
1238
+ let rect = cachedRectRef.current;
1239
+ if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
1240
+ cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
1241
+ const center = calculateElementCenter(rect), newOffset = {
1242
+ x: (globalPos.x - center.x) / rect.width * 100,
1243
+ y: (globalPos.y - center.y) / rect.height * 100
1134
1244
  };
1135
- }), [ effectiveCornerRadius, glassRef ]);
1136
- // OverLight config
1245
+ // Calculate offset relative to this container
1246
+ // Store in refs instead of state
1247
+ internalMouseOffsetRef.current = newOffset, internalGlobalMousePositionRef.current = globalPos,
1248
+ // Imperative style update
1249
+ updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
1250
+ mouseOffset: newOffset,
1251
+ globalMousePosition: globalPos,
1252
+ glassSize: glassSize,
1253
+ isHovered: isHovered,
1254
+ isActive: isActive,
1255
+ isOverLight: baseOverLightConfig.isOverLight,
1256
+ baseOverLightConfig: baseOverLightConfig,
1257
+ effectiveBorderRadius: effectiveBorderRadius,
1258
+ effectiveWithoutEffects: effectiveWithoutEffects,
1259
+ effectiveReducedMotion: effectiveReducedMotion,
1260
+ elasticity: elasticity,
1261
+ directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
1262
+ // Simplified directional scale for fast path
1263
+ onClick: onClick,
1264
+ withLiquidBlur: withLiquidBlur,
1265
+ blurAmount: blurAmount,
1266
+ saturation: saturation,
1267
+ padding: padding
1268
+ });
1269
+ }), [ mouseContainer, glassRef, wrapperRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects, glassSize, isHovered, isActive, baseOverLightConfig, effectiveBorderRadius, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding ]);
1137
1270
  /**
1138
- * Get effective overLight value based on configuration
1139
- * - boolean: returns the boolean value directly
1140
- * - 'auto': returns detectedOverLight (auto-detected from background)
1141
- * - object: returns detectedOverLight (auto-detected, but config object provides customization)
1142
- */
1143
- const getEffectiveOverLight = useCallback((() => "boolean" == typeof overLight ? overLight : ("auto" === overLight || "object" == typeof overLight && null !== overLight) && detectedOverLight), [ overLight, detectedOverLight ]), validateConfigValue = useCallback(((value, min, max, defaultValue) => "number" != typeof value || isNaN(value) || !isFinite(value) ? defaultValue : Math.min(max, Math.max(min, value))), []), overLightConfig = useMemo((() => {
1144
- const isOverLight = getEffectiveOverLight(), mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1, baseConfig = {
1145
- isOverLight: isOverLight,
1146
- threshold: .7,
1147
- opacity: isOverLight ? Math.min(.6, Math.max(.2, .5 * hoverIntensity * activeIntensity)) : 0,
1148
- contrast: Math.min(1.6, Math.max(1, 1.4 + .1 * mouseInfluence)),
1149
- brightness: Math.min(1.1, Math.max(.8, .9 + .05 * mouseInfluence)),
1150
- saturationBoost: 1.3,
1151
- // Fixed value dynamic saturation amplifies perceived displacement
1152
- shadowIntensity: Math.min(1.2, Math.max(.5, .9 + .2 * mouseInfluence)),
1153
- borderOpacity: Math.min(1, Math.max(.3, .7 + .1 * mouseInfluence))
1271
+ * Validate and clamp a numeric config value
1272
+ */
1273
+ // Subscribe to shared mouse tracker
1274
+ useEffect((() => {
1275
+ if (externalGlobalMousePosition && externalMouseOffset) return;
1276
+ if (effectiveWithoutEffects) return;
1277
+ const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition), container = mouseContainer?.current || glassRef.current;
1278
+ let resizeObserver = null;
1279
+ return container && "undefined" != typeof ResizeObserver && (resizeObserver = new ResizeObserver((() => {
1280
+ null !== updateRectRef.current && cancelAnimationFrame(updateRectRef.current), updateRectRef.current = requestAnimationFrame((() => {
1281
+ const container = mouseContainer?.current || glassRef.current;
1282
+ container && (cachedRectRef.current = container.getBoundingClientRect()), updateRectRef.current = null;
1283
+ }));
1284
+ })), resizeObserver.observe(container)), () => {
1285
+ unsubscribe(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
1286
+ updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
1154
1287
  };
1155
- if ("object" == typeof overLight && null !== overLight) {
1156
- const objConfig = overLight, validatedThreshold = validateConfigValue(objConfig.threshold, .1, 1, baseConfig.threshold), validatedOpacity = validateConfigValue(objConfig.opacity, .1, 1, baseConfig.opacity), validatedContrast = validateConfigValue(objConfig.contrast, .5, 2.5, baseConfig.contrast), validatedBrightness = validateConfigValue(objConfig.brightness, .5, 2, baseConfig.brightness), validatedSaturationBoost = validateConfigValue(objConfig.saturationBoost, .5, 3, baseConfig.saturationBoost), finalConfig = {
1157
- ...baseConfig,
1158
- threshold: validatedThreshold,
1159
- opacity: validatedOpacity * hoverIntensity * activeIntensity,
1160
- contrast: Math.min(1.6, validatedContrast + .1 * mouseInfluence),
1161
- brightness: Math.min(1.1, validatedBrightness + .05 * mouseInfluence),
1162
- saturationBoost: validatedSaturationBoost
1163
- };
1164
- // Validate and apply object config values with proper clamping
1165
- return "undefined" == typeof process || process.env, finalConfig;
1166
- }
1167
- // Debug logging for non-object configs
1168
- return "undefined" == typeof process || process.env, baseConfig;
1169
- }), [ overLight, getEffectiveOverLight, mouseOffset, isHovered, isActive, validateConfigValue, debugOverLight ]), handleMouseEnter = useCallback((() => setIsHovered(!0)), []), handleMouseLeave = useCallback((() => setIsHovered(!1)), []), handleMouseDown = useCallback((() => setIsActive(!0)), []), handleMouseUp = useCallback((() => setIsActive(!1)), []), handleKeyDown = useCallback((e => {
1288
+ }), [ handleGlobalMousePosition, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects ]),
1289
+ // Also call updateStyles on other state changes (hover, active, etc)
1290
+ useEffect((() => {
1291
+ updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
1292
+ mouseOffset: externalMouseOffset || internalMouseOffsetRef.current,
1293
+ globalMousePosition: externalGlobalMousePosition || internalGlobalMousePositionRef.current,
1294
+ glassSize: glassSize,
1295
+ isHovered: isHovered,
1296
+ isActive: isActive,
1297
+ isOverLight: baseOverLightConfig.isOverLight,
1298
+ baseOverLightConfig: baseOverLightConfig,
1299
+ effectiveBorderRadius: effectiveBorderRadius,
1300
+ effectiveWithoutEffects: effectiveWithoutEffects,
1301
+ effectiveReducedMotion: effectiveReducedMotion,
1302
+ elasticity: elasticity,
1303
+ directionalScale: directionalScale,
1304
+ onClick: onClick,
1305
+ withLiquidBlur: withLiquidBlur,
1306
+ blurAmount: blurAmount,
1307
+ saturation: saturation,
1308
+ padding: padding
1309
+ });
1310
+ }), [ isHovered, isActive, glassSize, baseOverLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, directionalScale, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation, padding, onClick ]);
1311
+ // Event handlers
1312
+ const handleMouseEnter = useCallback((() => setIsHovered(!0)), []), handleMouseLeave = useCallback((() => setIsHovered(!1)), []), handleMouseDown = useCallback((() => setIsActive(!0)), []), handleMouseUp = useCallback((() => setIsActive(!1)), []), handleMouseMove = useCallback((_e => {}), []), handleKeyDown = useCallback((e => {
1170
1313
  !onClick || "Enter" !== e.key && " " !== e.key || (e.preventDefault(), onClick());
1171
- }), [ onClick ]), handleMouseMove = useCallback((_e => {}), []);
1172
- /**
1173
- * Validate and clamp a numeric config value
1174
- * @param value - The value to validate
1175
- * @param min - Minimum allowed value
1176
- * @param max - Maximum allowed value
1177
- * @param defaultValue - Default value if validation fails
1178
- * @returns Validated and clamped value
1179
- */ return {
1180
- // State
1314
+ }), [ onClick ]);
1315
+ return {
1181
1316
  isHovered: isHovered,
1182
1317
  isActive: isActive,
1183
1318
  glassSize: glassSize,
1184
- dynamicCornerRadius: dynamicCornerRadius,
1185
- effectiveCornerRadius: effectiveCornerRadius,
1319
+ dynamicBorderRadius: dynamicBorderRadius,
1320
+ effectiveBorderRadius: effectiveBorderRadius,
1186
1321
  effectiveReducedMotion: effectiveReducedMotion,
1187
1322
  effectiveHighContrast: effectiveHighContrast,
1188
- effectiveDisableEffects: effectiveDisableEffects,
1323
+ effectiveWithoutEffects: effectiveWithoutEffects,
1189
1324
  detectedOverLight: detectedOverLight,
1190
1325
  globalMousePosition: globalMousePosition,
1326
+ // This is now static (refs or props) unless prop changes
1191
1327
  mouseOffset: mouseOffset,
1192
- // OverLight config
1328
+ // This is now static (refs or props) unless prop changes
1193
1329
  overLightConfig: overLightConfig,
1194
- // Transform calculations
1195
1330
  elasticTranslation: elasticTranslation,
1196
1331
  directionalScale: directionalScale,
1197
1332
  transformStyle: transformStyle,
1198
- // Event handlers
1199
1333
  handleMouseEnter: handleMouseEnter,
1200
1334
  handleMouseLeave: handleMouseLeave,
1201
1335
  handleMouseDown: handleMouseDown,
@@ -1234,7 +1368,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1234
1368
  *
1235
1369
  * @example
1236
1370
  * // Manual border-radius override
1237
- * <AtomixGlass cornerRadius={20}>
1371
+ * <AtomixGlass borderRadius={20}>
1238
1372
  * <div>Content with 20px glass radius</div>
1239
1373
  * </AtomixGlass>
1240
1374
  *
@@ -1275,37 +1409,48 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1275
1409
  * <AtomixGlass overLight="auto" debugOverLight={true}>
1276
1410
  * <div>Content with debug logging enabled</div>
1277
1411
  * </AtomixGlass>
1278
- */ function AtomixGlass({children: children, displacementScale: displacementScale = ATOMIX_GLASS.DEFAULTS.DISPLACEMENT_SCALE, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, aberrationIntensity: aberrationIntensity = ATOMIX_GLASS.DEFAULTS.ABERRATION_INTENSITY, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, cornerRadius: cornerRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer = null, className: className = "", padding: padding = ATOMIX_GLASS.DEFAULTS.PADDING, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, style: style = {}, mode: mode = ATOMIX_GLASS.DEFAULTS.MODE, onClick: onClick, shaderVariant: shaderVariant = "liquidGlass", "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, role: role, tabIndex: tabIndex, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, disableEffects: disableEffects = !1, enableLiquidBlur: enableLiquidBlur = !1, enableBorderEffect: enableBorderEffect = !0, enableOverLightLayers: enableOverLightLayers = ATOMIX_GLASS.DEFAULTS.ENABLE_OVER_LIGHT_LAYERS, enablePerformanceMonitoring: enablePerformanceMonitoring = !1, debugCornerRadius: debugCornerRadius = !1, debugOverLight: debugOverLight = !1}) {
1279
- const glassRef = useRef(null), contentRef = useRef(null), {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveCornerRadius: effectiveCornerRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveDisableEffects: effectiveDisableEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown} = useAtomixGlass({
1412
+ */ function AtomixGlass({children: children, displacementScale: displacementScale = ATOMIX_GLASS.DEFAULTS.DISPLACEMENT_SCALE, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, aberrationIntensity: aberrationIntensity = ATOMIX_GLASS.DEFAULTS.ABERRATION_INTENSITY, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer = null, className: className = "", padding: padding = ATOMIX_GLASS.DEFAULTS.PADDING, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, style: style = {}, mode: mode = ATOMIX_GLASS.DEFAULTS.MODE, onClick: onClick, shaderVariant: shaderVariant = "liquidGlass", "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, role: role, tabIndex: tabIndex, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, withLiquidBlur: withLiquidBlur = !1, withBorder: withBorder = !0, withOverLightLayers: withOverLightLayers = ATOMIX_GLASS.DEFAULTS.ENABLE_OVER_LIGHT_LAYERS, debugPerformance: debugPerformance = !1, debugBorderRadius: debugBorderRadius = !1, debugOverLight: debugOverLight = !1, height: height, width: width, ...rest}) {
1413
+ const glassRef = useRef(null), contentRef = useRef(null), {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveBorderRadius: effectiveBorderRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveWithoutEffects: effectiveWithoutEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown} = useAtomixGlass({
1280
1414
  glassRef: glassRef,
1281
1415
  contentRef: contentRef,
1282
- cornerRadius: cornerRadius,
1416
+ borderRadius: borderRadius,
1283
1417
  globalMousePosition: externalGlobalMousePosition,
1284
1418
  mouseOffset: externalMouseOffset,
1285
1419
  mouseContainer: mouseContainer,
1286
1420
  overLight: overLight,
1287
1421
  reducedMotion: reducedMotion,
1288
1422
  highContrast: highContrast,
1289
- disableEffects: disableEffects,
1423
+ withoutEffects: withoutEffects,
1290
1424
  elasticity: elasticity,
1291
1425
  onClick: onClick,
1292
- debugCornerRadius: debugCornerRadius,
1426
+ debugBorderRadius: debugBorderRadius,
1293
1427
  debugOverLight: debugOverLight,
1294
- enablePerformanceMonitoring: enablePerformanceMonitoring,
1295
- children: children
1296
- }), isOverLight = useMemo((() => overLightConfig?.isOverLight), [ overLight ]), shouldRenderOverLightLayers = enableOverLightLayers && isOverLight, baseStyle = {
1428
+ debugPerformance: debugPerformance,
1429
+ children: children,
1430
+ blurAmount: blurAmount,
1431
+ saturation: saturation,
1432
+ withLiquidBlur: withLiquidBlur,
1433
+ padding: padding,
1434
+ style: style
1435
+ }), isOverLight = useMemo((() => overLightConfig?.isOverLight), [ overLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, baseStyle = {
1297
1436
  ...style,
1298
- ...!effectiveDisableEffects && {
1437
+ ...!effectiveWithoutEffects && {
1299
1438
  transform: transformStyle
1300
1439
  }
1301
- }, componentClassName = [ ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`, effectiveDisableEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`, className ].filter(Boolean).join(" "), positionStyles = useMemo((() => ({
1440
+ }, componentClassName = [ ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`, effectiveWithoutEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`, className ].filter(Boolean).join(" "), positionStyles = useMemo((() => ({
1302
1441
  position: style.position || "absolute",
1303
1442
  top: style.top || 0,
1304
1443
  left: style.left || 0
1305
- })), [ style.position, style.top, style.left ]), adjustedSize = useMemo((() => ({
1306
- width: "fixed" !== style.position ? "100%" : style.width ? style.width : Math.max(glassSize.width, 0),
1307
- height: "fixed" !== style.position ? "100%" : style.height ? style.height : Math.max(glassSize.height, 0)
1308
- })), [ style.position, style.width, style.height, glassSize.width, glassSize.height ]), gradientValues = useMemo((() => {
1444
+ })), [ style.position, style.top, style.left ]), adjustedSize = useMemo((() => {
1445
+ const resolveSize = (propValue, styleValue, measuredSize) => {
1446
+ const explicitSize = propValue ?? styleValue;
1447
+ return void 0 !== explicitSize ? "number" == typeof explicitSize ? `${explicitSize}px` : explicitSize : "fixed" === positionStyles.position ? `${Math.max(measuredSize, 0)}px` : "100%";
1448
+ };
1449
+ return {
1450
+ width: resolveSize(width, style.width, glassSize.width),
1451
+ height: resolveSize(height, style.height, glassSize.height)
1452
+ };
1453
+ }), [ width, height, style.width, style.height, positionStyles.position, glassSize.width, glassSize.height ]), gradientValues = useMemo((() => {
1309
1454
  const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT;
1310
1455
  return {
1311
1456
  borderGradientAngle: GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER,
@@ -1347,13 +1492,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1347
1492
  }), [ isHovered, isActive, isOverLight, overLightConfig.opacity ]), glassVars = useMemo((() => {
1348
1493
  const whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE, blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK, {borderGradientAngle: borderGradientAngle, borderStop1: borderStop1, borderStop2: borderStop2, borderOpacities: borderOpacities, hoverPositions: hoverPositions, basePosition: basePosition, mx: mx, my: my, absMx: absMx, absMy: absMy} = gradientValues, configBorderOpacity = overLightConfig?.borderOpacity ?? 1;
1349
1494
  return {
1350
- "--atomix-glass-radius": `${effectiveCornerRadius}px`,
1495
+ "--atomix-glass-radius": `${effectiveBorderRadius}px`,
1351
1496
  "--atomix-glass-transform": transformStyle || "none",
1352
1497
  "--atomix-glass-position": positionStyles.position,
1353
1498
  "--atomix-glass-top": "fixed" !== positionStyles.top ? `${positionStyles.top}px` : "0",
1354
1499
  "--atomix-glass-left": "fixed" !== positionStyles.left ? `${positionStyles.left}px` : "0",
1355
- "--atomix-glass-width": "fixed" !== style.position ? adjustedSize.width : `${adjustedSize.width}px`,
1356
- "--atomix-glass-height": "fixed" !== style.position ? adjustedSize.height : `${adjustedSize.height}px`,
1500
+ "--atomix-glass-width": adjustedSize.width,
1501
+ "--atomix-glass-height": adjustedSize.height,
1357
1502
  "--atomix-glass-border-width": "var(--atomix-spacing-0-5, 0.09375rem)",
1358
1503
  "--atomix-glass-blend-mode": isOverLight ? "multiply" : "overlay",
1359
1504
  "--atomix-glass-border-gradient-1": `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[0] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[1] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
@@ -1369,24 +1514,25 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1369
1514
  "--atomix-glass-overlay-opacity": opacityValues.over,
1370
1515
  "--atomix-glass-overlay-gradient": isOverLight ? `radial-gradient(circle at ${basePosition.x}% ${basePosition.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_BASE + absMx * 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 + absMy * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.WHITE_OPACITY})`
1371
1516
  };
1372
- }), [ gradientValues, opacityValues, effectiveCornerRadius, transformStyle, positionStyles, adjustedSize, style.position, isOverLight, overLightConfig.borderOpacity ]), renderBackgroundLayer = layerType => jsx("div", {
1517
+ }), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle, positionStyles, adjustedSize, isOverLight, overLightConfig.borderOpacity ]), renderBackgroundLayer = layerType => jsx("div", {
1373
1518
  className: [ ATOMIX_GLASS.BACKGROUND_LAYER_CLASS, "dark" === layerType ? ATOMIX_GLASS.BACKGROUND_LAYER_DARK_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_BLACK_CLASS, isOverLight ? ATOMIX_GLASS.BACKGROUND_LAYER_OVER_LIGHT_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_HIDDEN_CLASS ].filter(Boolean).join(" "),
1374
1519
  style: {
1375
1520
  ...positionStyles,
1376
1521
  height: adjustedSize.height,
1377
1522
  width: adjustedSize.width,
1378
- borderRadius: `${effectiveCornerRadius}px`,
1523
+ borderRadius: `${effectiveBorderRadius}px`,
1379
1524
  transform: baseStyle.transform
1380
1525
  }
1381
1526
  });
1382
1527
  return jsxs("div", {
1528
+ ...rest,
1383
1529
  className: componentClassName,
1384
1530
  style: glassVars,
1385
1531
  role: role || (onClick ? "button" : void 0),
1386
1532
  tabIndex: onClick ? tabIndex ?? 0 : tabIndex,
1387
1533
  "aria-label": ariaLabel,
1388
1534
  "aria-describedby": ariaDescribedBy,
1389
- "aria-disabled": !(!onClick || !effectiveDisableEffects) || !onClick && void 0,
1535
+ "aria-disabled": !(!onClick || !effectiveWithoutEffects) || !onClick && void 0,
1390
1536
  "aria-pressed": !(!onClick || !isActive) || !onClick && void 0,
1391
1537
  onKeyDown: onClick ? handleKeyDown : void 0,
1392
1538
  children: [ jsx(AtomixGlassContainer, {
@@ -1394,18 +1540,18 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1394
1540
  contentRef: contentRef,
1395
1541
  className: className,
1396
1542
  style: baseStyle,
1397
- cornerRadius: effectiveCornerRadius,
1398
- displacementScale: effectiveDisableEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
1399
- blurAmount: effectiveDisableEffects ? 0 : blurAmount,
1543
+ borderRadius: effectiveBorderRadius,
1544
+ displacementScale: effectiveWithoutEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
1545
+ blurAmount: effectiveWithoutEffects ? 0 : blurAmount,
1400
1546
  saturation: effectiveHighContrast ? ATOMIX_GLASS.CONSTANTS.SATURATION.HIGH_CONTRAST : isOverLight ? saturation * overLightConfig.saturationBoost : saturation,
1401
- aberrationIntensity: effectiveDisableEffects ? 0 : "shader" === mode ? aberrationIntensity * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_ABERRATION : aberrationIntensity,
1547
+ aberrationIntensity: effectiveWithoutEffects ? 0 : "shader" === mode ? aberrationIntensity * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_ABERRATION : aberrationIntensity,
1402
1548
  glassSize: glassSize,
1403
1549
  padding: padding,
1404
- mouseOffset: effectiveDisableEffects ? {
1550
+ mouseOffset: effectiveWithoutEffects ? {
1405
1551
  x: 0,
1406
1552
  y: 0
1407
1553
  } : mouseOffset,
1408
- globalMousePosition: effectiveDisableEffects ? {
1554
+ globalMousePosition: effectiveWithoutEffects ? {
1409
1555
  x: 0,
1410
1556
  y: 0
1411
1557
  } : globalMousePosition,
@@ -1425,11 +1571,11 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1425
1571
  onClick: onClick,
1426
1572
  mode: mode,
1427
1573
  transform: baseStyle.transform,
1428
- effectiveDisableEffects: effectiveDisableEffects,
1574
+ effectiveWithoutEffects: effectiveWithoutEffects,
1429
1575
  effectiveReducedMotion: effectiveReducedMotion,
1430
1576
  shaderVariant: shaderVariant,
1431
1577
  elasticity: elasticity,
1432
- enableLiquidBlur: enableLiquidBlur,
1578
+ withLiquidBlur: withLiquidBlur,
1433
1579
  children: children
1434
1580
  }), Boolean(onClick) && jsxs(Fragment, {
1435
1581
  children: [ jsx("div", {
@@ -1451,11 +1597,19 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1451
1597
  background: `radial-gradient(circle at ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_X}% ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_Y}%, rgba(255, 255, 255, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.WHITE_OPACITY}) 0%, transparent ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.STOP}%)`
1452
1598
  }
1453
1599
  }) ]
1454
- }), enableBorderEffect && jsxs(Fragment, {
1600
+ }), withBorder && jsxs(Fragment, {
1455
1601
  children: [ jsx("span", {
1456
- className: ATOMIX_GLASS.BORDER_1_CLASS
1602
+ className: ATOMIX_GLASS.BORDER_1_CLASS,
1603
+ style: {
1604
+ width: glassSize.width,
1605
+ height: glassSize.height
1606
+ }
1457
1607
  }), jsx("span", {
1458
- className: ATOMIX_GLASS.BORDER_2_CLASS
1608
+ className: ATOMIX_GLASS.BORDER_2_CLASS,
1609
+ style: {
1610
+ width: glassSize.width,
1611
+ height: glassSize.height
1612
+ }
1459
1613
  }) ]
1460
1614
  }) ]
1461
1615
  });
@@ -1516,7 +1670,7 @@ const Checkbox = React.memo( forwardRef((({label: label, checked: checked, onCh
1516
1670
  blurAmount: 1,
1517
1671
  saturation: 160,
1518
1672
  aberrationIntensity: .3,
1519
- cornerRadius: 6,
1673
+ borderRadius: 6,
1520
1674
  mode: "shader"
1521
1675
  }, glassProps = !0 === glass ? defaultGlassProps : {
1522
1676
  ...defaultGlassProps,
@@ -1741,7 +1895,7 @@ const Input = memo( forwardRef((({type: type = "text", value: value, defaultVal
1741
1895
  blurAmount: 1,
1742
1896
  saturation: 180,
1743
1897
  aberrationIntensity: .2,
1744
- cornerRadius: 12,
1898
+ borderRadius: 12,
1745
1899
  mode: "shader"
1746
1900
  }, glassProps = !0 === glass ? defaultGlassProps : {
1747
1901
  ...defaultGlassProps,
@@ -1826,7 +1980,7 @@ const Radio = memo((({label: label, checked: checked = !1, onChange: onChange,
1826
1980
  blurAmount: 1,
1827
1981
  saturation: 160,
1828
1982
  aberrationIntensity: .3,
1829
- cornerRadius: 6,
1983
+ borderRadius: 6,
1830
1984
  mode: "shader"
1831
1985
  }, glassProps = !0 === glass ? defaultGlassProps : {
1832
1986
  ...defaultGlassProps,
@@ -2439,7 +2593,7 @@ const Select = memo((({options: options, value: value, onChange: onChange, onBl
2439
2593
  blurAmount: 1,
2440
2594
  saturation: 180,
2441
2595
  aberrationIntensity: .2,
2442
- cornerRadius: 12,
2596
+ borderRadius: 12,
2443
2597
  mode: "shader"
2444
2598
  }, glassProps = !0 === glass ? defaultGlassProps : {
2445
2599
  ...defaultGlassProps,
@@ -2527,7 +2681,7 @@ const Textarea = memo( forwardRef((({value: value, defaultValue: defaultValue,
2527
2681
  blurAmount: 1,
2528
2682
  saturation: 180,
2529
2683
  aberrationIntensity: 1,
2530
- cornerRadius: 8,
2684
+ borderRadius: 8,
2531
2685
  mode: "shader"
2532
2686
  }, glassProps = !0 === glass ? defaultGlassProps : {
2533
2687
  ...defaultGlassProps,