@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/core.js CHANGED
@@ -727,7 +727,7 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
727
727
  HIGH_CONTRAST: 200
728
728
  }
729
729
  }
730
- }, {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS, calculateDistance = (pos1, pos2) => {
730
+ }, {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateDistance = (pos1, pos2) => {
731
731
  if (!pos1 || !pos2 || "number" != typeof pos1.x || "number" != typeof pos1.y || "number" != typeof pos2.x || "number" != typeof pos2.y) return 0;
732
732
  const deltaX = pos1.x - pos2.x, deltaY = pos1.y - pos2.y;
733
733
  return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
@@ -740,36 +740,36 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
740
740
  }, calculateMouseInfluence = mouseOffset => {
741
741
  if (!mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y) return 0;
742
742
  // Bounded calculation — keeps the glass effect subtle and stable
743
- const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$1.MOUSE_INFLUENCE_DIVISOR;
743
+ const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$2.MOUSE_INFLUENCE_DIVISOR;
744
744
  return Math.min(.8, influence);
745
745
  // Tighter cap to prevent blur/filter blow-out
746
- }, 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 => {
746
+ }, 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 => {
747
747
  if ("number" == typeof value) return Math.max(0, value);
748
- if ("string" != typeof value || !value.trim()) return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
748
+ if ("string" != typeof value || !value.trim()) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
749
749
  const trimmedValue = value.trim();
750
750
  // Handle px values
751
751
  if (trimmedValue.endsWith("px")) {
752
752
  const parsed = parseFloat(trimmedValue);
753
- return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
753
+ return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
754
754
  }
755
755
  // Handle rem values (assume 16px = 1rem)
756
756
  if (trimmedValue.endsWith("rem")) {
757
757
  const parsed = parseFloat(trimmedValue);
758
- return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
758
+ return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
759
759
  }
760
760
  // Handle em values (assume 16px = 1em for simplicity)
761
761
  if (trimmedValue.endsWith("em")) {
762
762
  const parsed = parseFloat(trimmedValue);
763
- return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
763
+ return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
764
764
  }
765
765
  // Handle percentage (convert to approximate px value, assuming 200px container)
766
766
  if (trimmedValue.endsWith("%")) {
767
767
  const parsed = parseFloat(trimmedValue);
768
- return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
768
+ return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
769
769
  }
770
770
  // Handle unitless numbers
771
771
  const numValue = parseFloat(trimmedValue);
772
- return isNaN(numValue) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
772
+ return isNaN(numValue) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
773
773
  }, extractBorderRadiusFromElement = element => {
774
774
  if (!element || !element.props) return null;
775
775
  // Check inline styles first (highest priority)
@@ -785,11 +785,11 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
785
785
  // If element has children, recursively check them
786
786
  if (element.props.children) {
787
787
  const childRadius = extractBorderRadiusFromChildren(element.props.children);
788
- if (childRadius > 0 && childRadius !== CONSTANTS$1.DEFAULT_CORNER_RADIUS) return childRadius;
788
+ if (childRadius > 0 && childRadius !== CONSTANTS$2.DEFAULT_CORNER_RADIUS) return childRadius;
789
789
  }
790
790
  return null;
791
791
  }, extractBorderRadiusFromChildren = children => {
792
- if (!children) return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
792
+ if (!children) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
793
793
  try {
794
794
  const childArray = React.Children.toArray(children);
795
795
  for (let i = 0; i < childArray.length; i++) {
@@ -802,7 +802,7 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
802
802
  } catch (error) {
803
803
  // Silently handle errors
804
804
  }
805
- return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
805
+ return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
806
806
  }, getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
807
807
  switch (mode) {
808
808
  case "standard":
@@ -976,10 +976,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
976
976
  }, globalMousePosition: globalMousePosition = {
977
977
  x: 0,
978
978
  y: 0
979
- }, 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 = {
979
+ }, 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 = {
980
980
  width: 0,
981
981
  height: 0
982
- }, onClick: onClick, mode: mode = "standard", effectiveDisableEffects: effectiveDisableEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", enableLiquidBlur: enableLiquidBlur = !1, elasticity: elasticity = 0, contentRef: contentRef}, ref) => {
982
+ }, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, elasticity: elasticity = 0, contentRef: contentRef}, ref) => {
983
983
  // Generate a stable, deterministic ID for SSR compatibility
984
984
  // Use a module-level counter that's consistent across server and client
985
985
  const filterId = useMemo((() => "atomix-glass-filter-" + ++idCounter), []), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null);
@@ -1089,7 +1089,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
1089
1089
  flowBlur: 1.2 * blurAmount
1090
1090
  };
1091
1091
  // Enhanced validation for liquid blur
1092
- if (!enableLiquidBlur || !rectCache || !mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y || isNaN(mouseOffset.x) || isNaN(mouseOffset.y)) return defaultBlur;
1092
+ if (!withLiquidBlur || !rectCache || !mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y || isNaN(mouseOffset.x) || isNaN(mouseOffset.y)) return defaultBlur;
1093
1093
  try {
1094
1094
  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);
1095
1095
  // NOTE: hover/active multipliers intentionally omitted here —
@@ -1104,14 +1104,14 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
1104
1104
  return console.warn("AtomixGlassContainer: Error calculating liquid blur", error),
1105
1105
  defaultBlur;
1106
1106
  }
1107
- }), [ enableLiquidBlur, blurAmount, mouseOffset, rectCache ]), backdropStyle = useMemo((() => {
1107
+ }), [ withLiquidBlur, blurAmount, mouseOffset, rectCache ]), backdropStyle = useMemo((() => {
1108
1108
  try {
1109
1109
  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;
1110
1110
  // Validate blur values before using them
1111
- return !enableLiquidBlur || effectiveReducedMotion || effectiveDisableEffects || area > 18e4 ? {
1111
+ return !withLiquidBlur || effectiveReducedMotion || effectiveWithoutEffects || area > 18e4 ? {
1112
1112
  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})`
1113
1113
  } : {
1114
- 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})`
1114
+ 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})`
1115
1115
  };
1116
1116
  // Single-pass fallback: stronger radius to match perceived blur of multi-pass
1117
1117
  } catch (error) {
@@ -1120,7 +1120,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
1120
1120
  backdropFilter: `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`
1121
1121
  };
1122
1122
  }
1123
- }), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveDisableEffects, enableLiquidBlur ]), containerVars = useMemo((() => {
1123
+ }), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveWithoutEffects, withLiquidBlur ]), containerVars = useMemo((() => {
1124
1124
  try {
1125
1125
  // Safe extraction of mouse offset values
1126
1126
  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;
@@ -1128,10 +1128,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
1128
1128
  "--atomix-glass-container-width": `${glassSize?.width}`,
1129
1129
  "--atomix-glass-container-height": `${glassSize?.height}`,
1130
1130
  "--atomix-glass-container-padding": padding || "0 0",
1131
- "--atomix-glass-container-radius": `${"number" != typeof cornerRadius || isNaN(cornerRadius) ? 0 : cornerRadius}px`,
1131
+ "--atomix-glass-container-radius": `${"number" != typeof borderRadius || isNaN(borderRadius) ? 0 : borderRadius}px`,
1132
1132
  "--atomix-glass-container-backdrop": backdropStyle?.backdropFilter || "none",
1133
1133
  "--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",
1134
- "--atomix-glass-container-shadow-opacity": effectiveDisableEffects ? 0 : 1,
1134
+ "--atomix-glass-container-shadow-opacity": effectiveWithoutEffects ? 0 : 1,
1135
1135
  // Background and shadow values use design token-aligned RGB values
1136
1136
  "--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",
1137
1137
  "--atomix-glass-container-text-shadow": overLight ? "0px 2px 12px rgba(0, 0, 0, 0)" : "0px 2px 12px rgba(0, 0, 0, 0.4)",
@@ -1149,14 +1149,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
1149
1149
  "--atomix-glass-container-text-shadow": "none"
1150
1150
  };
1151
1151
  }
1152
- }), [ glassSize, padding, cornerRadius, backdropStyle, mouseOffset, overLight, effectiveDisableEffects ]), setForceNoTransition = el => {
1153
- el && (el.style.setProperty("transition-duration", "0s", "important"), el.style.setProperty("animation-duration", "0s", "important"),
1154
- el.style.setProperty("transition-delay", "0s", "important"));
1155
- };
1152
+ }), [ glassSize, padding, borderRadius, backdropStyle, mouseOffset, overLight, effectiveWithoutEffects ]);
1156
1153
  return jsx("div", {
1157
1154
  ref: el => {
1158
1155
  // Apply force no-transition
1159
- setForceNoTransition(el),
1160
1156
  // Handle forwarded ref
1161
1157
  "function" == typeof ref ? ref(el) : ref && (ref.current = el);
1162
1158
  },
@@ -1191,7 +1187,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
1191
1187
  aberrationIntensity: "number" != typeof aberrationIntensity || isNaN(aberrationIntensity) ? 0 : aberrationIntensity,
1192
1188
  shaderMapUrl: shaderMapUrl
1193
1189
  }), jsx("div", {
1194
- ref: setForceNoTransition,
1190
+ ref: el => {
1191
+ el && (el.style.setProperty("transition-duration", "0s", "important"), el.style.setProperty("animation-duration", "0s", "important"),
1192
+ el.style.setProperty("transition-delay", "0s", "important"));
1193
+ },
1195
1194
  className: ATOMIX_GLASS.FILTER_OVERLAY_CLASS,
1196
1195
  style: {
1197
1196
  filter: `url(#${filterId})`,
@@ -1308,7 +1307,128 @@ class {
1308
1307
  */ getSubscriberCount() {
1309
1308
  return this.listeners.size;
1310
1309
  }
1311
- }, {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
1310
+ }, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
1311
+ if (!wrapperElement && !containerElement) return;
1312
+ 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 = {
1313
+ opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
1314
+ contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
1315
+ brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
1316
+ shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
1317
+ borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence)),
1318
+ saturationBoost: baseOverLightConfig.saturationBoost
1319
+ };
1320
+ // Calculate mouse influence
1321
+ // Calculate elastic translation
1322
+ let elasticTranslation = {
1323
+ x: 0,
1324
+ y: 0
1325
+ };
1326
+ if (!effectiveWithoutEffects && wrapperElement) {
1327
+ const rect = wrapperElement.getBoundingClientRect(), center = calculateElementCenter(rect);
1328
+ // Calculate fade in factor
1329
+ let fadeInFactor = 0;
1330
+ if (globalMousePosition.x && globalMousePosition.y && validateGlassSize(glassSize)) {
1331
+ 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({
1332
+ x: edgeDistanceX,
1333
+ y: edgeDistanceY
1334
+ }, {
1335
+ x: 0,
1336
+ y: 0
1337
+ });
1338
+ fadeInFactor = edgeDistance > ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE ? 0 : 1 - edgeDistance / ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE;
1339
+ }
1340
+ elasticTranslation = {
1341
+ x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
1342
+ y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
1343
+ };
1344
+ }
1345
+ 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}`;
1346
+ // Update Wrapper Styles (glassVars)
1347
+ if (wrapperElement) {
1348
+ 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 = {
1349
+ hover1: {
1350
+ x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1,
1351
+ y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1
1352
+ },
1353
+ hover2: {
1354
+ x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_2,
1355
+ y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_2
1356
+ },
1357
+ hover3: {
1358
+ x: GRADIENT.CENTER_POSITION + mx * GRADIENT.HOVER_POSITION.MULTIPLIER_3,
1359
+ y: GRADIENT.CENTER_POSITION + my * GRADIENT.HOVER_POSITION.MULTIPLIER_3
1360
+ }
1361
+ }, basePosition = {
1362
+ x: GRADIENT.CENTER_POSITION + mx * GRADIENT.BASE_LAYER_MULTIPLIER,
1363
+ y: GRADIENT.CENTER_POSITION + my * GRADIENT.BASE_LAYER_MULTIPLIER
1364
+ }, opacityValues = {
1365
+ hover1: isHovered || isActive ? .5 : 0,
1366
+ hover2: isActive ? .5 : 0,
1367
+ hover3: isHovered ? .4 : isActive ? .8 : 0,
1368
+ base: isOverLight ? overLightConfig.opacity : 0,
1369
+ over: isOverLight ? 1.1 * overLightConfig.opacity : 0
1370
+ }, style = wrapperElement.style;
1371
+ style.setProperty("--atomix-glass-transform", transformStyle || "none"),
1372
+ // Gradients
1373
+ 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%)`),
1374
+ 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%)`),
1375
+ // Hover gradients
1376
+ 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}%)`),
1377
+ 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}%)`),
1378
+ 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}%)`),
1379
+ 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})`),
1380
+ 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})`),
1381
+ // Opacities
1382
+ style.setProperty("--atomix-glass-hover-1-opacity", opacityValues.hover1.toString()),
1383
+ style.setProperty("--atomix-glass-hover-2-opacity", opacityValues.hover2.toString()),
1384
+ style.setProperty("--atomix-glass-hover-3-opacity", opacityValues.hover3.toString()),
1385
+ style.setProperty("--atomix-glass-base-opacity", opacityValues.base.toString()),
1386
+ style.setProperty("--atomix-glass-overlay-opacity", opacityValues.over.toString()),
1387
+ style.setProperty("--atomix-glass-overlay-highlight-opacity", (opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER).toString()),
1388
+ // Other
1389
+ style.setProperty("--atomix-glass-blend-mode", isOverLight ? "multiply" : "overlay"),
1390
+ style.setProperty("--atomix-glass-radius", `${effectiveBorderRadius}px`);
1391
+ }
1392
+ // Update Container Styles (containerVars)
1393
+ if (containerElement) {
1394
+ 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();
1395
+ let liquidBlur = {
1396
+ baseBlur: blurAmount,
1397
+ edgeBlur: blurAmount * EDGE_BLUR_MULTIPLIER,
1398
+ centerBlur: blurAmount * CENTER_BLUR_MULTIPLIER,
1399
+ flowBlur: blurAmount * FLOW_BLUR_MULTIPLIER
1400
+ };
1401
+ if (withLiquidBlur && rect) {
1402
+ 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);
1403
+ liquidBlur = {
1404
+ baseBlur: clampBlur(baseBlur),
1405
+ edgeBlur: clampBlur(edgeBlur),
1406
+ centerBlur: clampBlur(centerBlur),
1407
+ flowBlur: clampBlur(flowBlur)
1408
+ };
1409
+ }
1410
+ // Backdrop filter
1411
+ let backdropFilterString = `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`;
1412
+ const dynamicSaturation = saturation + 20 * (liquidBlur.baseBlur || 0), area = rect ? rect.width * rect.height : 0;
1413
+ 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})`;
1414
+ // Container variables
1415
+ const style = containerElement.style;
1416
+ style.setProperty("--atomix-glass-container-width", `${glassSize.width}`), style.setProperty("--atomix-glass-container-height", `${glassSize.height}`),
1417
+ style.setProperty("--atomix-glass-container-padding", padding), style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
1418
+ style.setProperty("--atomix-glass-container-backdrop", backdropFilterString),
1419
+ // Shadows
1420
+ 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"),
1421
+ style.setProperty("--atomix-glass-container-shadow-opacity", effectiveWithoutEffects ? "0" : "1"),
1422
+ 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"),
1423
+ 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)"),
1424
+ 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)");
1425
+ }
1426
+ }, {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS;
1427
+
1428
+ /**
1429
+ * Updates the styles of the AtomixGlass wrapper and container elements imperatively
1430
+ * to avoid React re-renders on mouse movement.
1431
+ */ const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
1312
1432
  parentElement && backgroundDetectionCache.set(parentElement, {
1313
1433
  result: result,
1314
1434
  timestamp: Date.now(),
@@ -1321,18 +1441,74 @@ class {
1321
1441
  * Composable hook for AtomixGlass component logic
1322
1442
  * Manages all state, calculations, and event handlers
1323
1443
  */
1324
- 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}) {
1444
+ 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}) {
1325
1445
  // State
1326
- const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), [glassSize, setGlassSize] = useState({
1327
- width: 270,
1328
- height: 69
1329
- }), [internalGlobalMousePosition, setInternalGlobalMousePosition] = useState({
1446
+ const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), cachedRectRef = useRef(null), internalGlobalMousePositionRef = useRef({
1330
1447
  x: 0,
1331
1448
  y: 0
1332
- }), [internalMouseOffset, setInternalMouseOffset] = useState({
1449
+ }), internalMouseOffsetRef = useRef({
1333
1450
  x: 0,
1334
1451
  y: 0
1335
- }), [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 ]);
1452
+ }), [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}) {
1453
+ const [glassSize, setGlassSize] = useState({
1454
+ width: 270,
1455
+ height: 69
1456
+ });
1457
+ return useEffect((() => {
1458
+ const isValidElement = element => null !== element && element instanceof HTMLElement && element.isConnected;
1459
+ let rafId = null, lastSize = {
1460
+ width: 0,
1461
+ height: 0
1462
+ }, lastCornerRadius = effectiveBorderRadius;
1463
+ const updateGlassSize = (forceUpdate = !1) => {
1464
+ null !== rafId && cancelAnimationFrame(rafId), rafId = requestAnimationFrame((() => {
1465
+ if (!isValidElement(glassRef.current)) return void (rafId = null);
1466
+ const rect = glassRef.current.getBoundingClientRect();
1467
+ if (rect.width <= 0 || rect.height <= 0) return void (rafId = null);
1468
+ // Measure actual rendered size without artificial offsets to avoid feedback loops
1469
+ const newSize = {
1470
+ width: Math.round(rect.width),
1471
+ height: Math.round(rect.height)
1472
+ }, cornerRadiusChanged = lastCornerRadius !== effectiveBorderRadius, dimensionsChanged = Math.abs(newSize.width - lastSize.width) > 1 || Math.abs(newSize.height - lastSize.height) > 1;
1473
+ var size;
1474
+ (forceUpdate || cornerRadiusChanged || dimensionsChanged) && validateGlassSize(size = newSize) && size.width <= CONSTANTS$1.MAX_SIZE && size.height <= CONSTANTS$1.MAX_SIZE && (lastSize = newSize,
1475
+ lastCornerRadius = effectiveBorderRadius, setGlassSize(newSize)), rafId = null;
1476
+ }));
1477
+ };
1478
+ let resizeTimeoutId = null;
1479
+ const debouncedResizeHandler = () => {
1480
+ resizeTimeoutId && clearTimeout(resizeTimeoutId), resizeTimeoutId = setTimeout((() => updateGlassSize(!1)), 16);
1481
+ }, initialTimeoutId = setTimeout((() => updateGlassSize(!0)), 0);
1482
+ let resizeObserver = null, resizeDebounceTimeout = null;
1483
+ // ResizeObserver has 98%+ browser support, no need for fallback
1484
+ if ("undefined" != typeof ResizeObserver && isValidElement(glassRef.current)) try {
1485
+ resizeObserver = new ResizeObserver((entries => {
1486
+ for (const entry of entries) if (entry.target === glassRef.current) {
1487
+ // Update cached rect when size changes
1488
+ glassRef.current && cachedRectRef && (cachedRectRef.current = glassRef.current.getBoundingClientRect()),
1489
+ // Debounce resize updates to match RAF timing (16ms)
1490
+ resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), resizeDebounceTimeout = setTimeout((() => updateGlassSize(!1)), 16);
1491
+ break;
1492
+ }
1493
+ })), resizeObserver.observe(glassRef.current);
1494
+ } catch (error) {
1495
+ console.warn("AtomixGlass: ResizeObserver not available, using window resize only", error);
1496
+ }
1497
+ return window.addEventListener("resize", debouncedResizeHandler, {
1498
+ passive: !0
1499
+ }), () => {
1500
+ clearTimeout(initialTimeoutId), null !== rafId && cancelAnimationFrame(rafId), resizeTimeoutId && clearTimeout(resizeTimeoutId),
1501
+ resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), window.removeEventListener("resize", debouncedResizeHandler),
1502
+ resizeObserver?.disconnect();
1503
+ };
1504
+ }), [ effectiveBorderRadius, glassRef, cachedRectRef ]), {
1505
+ glassSize: glassSize
1506
+ };
1507
+ }({
1508
+ glassRef: glassRef,
1509
+ effectiveBorderRadius: effectiveBorderRadius,
1510
+ cachedRectRef: cachedRectRef
1511
+ }), 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;
1336
1512
  // Extract border-radius from children
1337
1513
  useEffect((() => {
1338
1514
  const extractRadius = () => {
@@ -1363,13 +1539,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1363
1539
  }
1364
1540
  null !== extractedRadius && extractedRadius > 0 && setDynamicCornerRadius(extractedRadius);
1365
1541
  } catch (error) {
1366
- "undefined" != typeof process && "production" === process.env?.NODE_ENV || !debugCornerRadius || console.error("[AtomixGlass] Error extracting corner radius:", error);
1542
+ "undefined" != typeof process && "production" === process.env?.NODE_ENV || !debugBorderRadius || console.error("[AtomixGlass] Error extracting corner radius:", error);
1367
1543
  }
1368
1544
  };
1369
1545
  extractRadius();
1370
1546
  const timeoutId = setTimeout(extractRadius, 100);
1371
1547
  return () => clearTimeout(timeoutId);
1372
- }), [ children, debugCornerRadius, contentRef ]),
1548
+ }), [ children, debugBorderRadius, contentRef ]),
1373
1549
  // Media query handlers and background detection
1374
1550
  useEffect((() => {
1375
1551
  if (("auto" === overLight || "object" == typeof overLight && null !== overLight) && glassRef.current) {
@@ -1425,72 +1601,52 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1425
1601
  const rgb = bgColor.match(/\d+/g);
1426
1602
  if (rgb && rgb.length >= 3) {
1427
1603
  const r = Number(rgb[0]), g = Number(rgb[1]), b = Number(rgb[2]);
1428
- // Validate RGB values are valid numbers
1429
- 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)) {
1604
+ if (!isNaN(r) && !isNaN(g) && !isNaN(b) && (r > 10 || g > 10 || b > 10)) {
1430
1605
  const luminance = (.299 * r + .587 * g + .114 * b) / 255;
1431
1606
  !isNaN(luminance) && isFinite(luminance) && (totalLuminance += luminance, validSamples++,
1432
1607
  hasValidBackground = !0);
1433
1608
  }
1434
1609
  }
1435
1610
  }
1436
- // Check for image backgrounds
1437
- bgImage && "none" !== bgImage && "initial" !== bgImage && (
1438
- // For image backgrounds, assume medium luminance
1439
- totalLuminance += .5, validSamples++, hasValidBackground = !0);
1611
+ bgImage && "none" !== bgImage && "initial" !== bgImage && (totalLuminance += .5,
1612
+ validSamples++, hasValidBackground = !0);
1440
1613
  } catch (styleError) {
1441
- "undefined" == typeof process || process.env;
1614
+ // Silently continue
1442
1615
  }
1443
- // Move to parent element for next iteration
1444
- if (!currentElement) break;
1445
- // Exit loop if currentElement becomes null
1446
- currentElement = currentElement.parentElement, depth++;
1616
+ if (!currentElement) break;
1617
+ currentElement = currentElement.parentElement, depth++;
1447
1618
  }
1448
- // More conservative detection with better error handling
1449
- if (hasValidBackground && validSamples > 0) {
1619
+ if (hasValidBackground && validSamples > 0) {
1450
1620
  const avgLuminance = totalLuminance / validSamples;
1451
1621
  if (!isNaN(avgLuminance) && isFinite(avgLuminance)) {
1452
1622
  let threshold = .7;
1453
- // Conservative threshold for overlight
1454
- // If overLight is an object, use its threshold property with validation
1455
- if ("object" == typeof overLight && null !== overLight) {
1623
+ if ("object" == typeof overLight && null !== overLight) {
1456
1624
  const objConfig = overLight;
1457
1625
  if (void 0 !== objConfig.threshold) {
1458
- const configThreshold = "number" == typeof objConfig.threshold && !isNaN(objConfig.threshold) && isFinite(objConfig.threshold) ? objConfig.threshold : .7;
1626
+ const configThreshold = "number" != typeof objConfig.threshold || isNaN(objConfig.threshold) ? .7 : objConfig.threshold;
1459
1627
  threshold = Math.min(.9, Math.max(.1, configThreshold));
1460
1628
  }
1461
1629
  }
1462
1630
  const isOverLightDetected = avgLuminance > threshold;
1463
- // Cache the result in shared cache
1464
- setCachedBackgroundDetection(element.parentElement, overLight, isOverLightDetected, threshold),
1631
+ setCachedBackgroundDetection(element.parentElement, overLight, isOverLightDetected, threshold),
1465
1632
  setDetectedOverLight(isOverLightDetected);
1466
1633
  } else {
1467
- // Invalid luminance calculation, default to false
1468
1634
  const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
1469
1635
  setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
1470
1636
  setDetectedOverLight(result);
1471
1637
  }
1472
1638
  } else {
1473
- // Default to false if no valid background found
1474
1639
  const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
1475
1640
  setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
1476
1641
  setDetectedOverLight(result);
1477
1642
  }
1478
1643
  } catch (error) {
1479
- // Enhanced error logging with context
1480
- "undefined" != typeof process && "development" !== process.env?.NODE_ENV || console.warn("AtomixGlass: Error detecting background brightness:", error);
1481
- const result = !1;
1482
- if (element && element.parentElement) {
1483
- const threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
1484
- setCachedBackgroundDetection(element.parentElement, overLight, result, threshold);
1485
- }
1486
- setDetectedOverLight(result);
1644
+ setDetectedOverLight(!1);
1487
1645
  }
1488
1646
  }), 150);
1489
1647
  return () => clearTimeout(timeoutId);
1490
1648
  }
1491
- if ("boolean" == typeof overLight &&
1492
- // For boolean values, disable auto-detection
1493
- setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
1649
+ if ("boolean" == typeof overLight && setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
1494
1650
  const mediaQueryReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)"), mediaQueryHighContrast = window.matchMedia("(prefers-contrast: high)");
1495
1651
  setUserPrefersReducedMotion(mediaQueryReducedMotion.matches), setUserPrefersHighContrast(mediaQueryHighContrast.matches);
1496
1652
  const handleReducedMotionChange = e => {
@@ -1501,64 +1657,54 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1501
1657
  return mediaQueryReducedMotion.addEventListener ? (mediaQueryReducedMotion.addEventListener("change", handleReducedMotionChange),
1502
1658
  mediaQueryHighContrast.addEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.addListener && (mediaQueryReducedMotion.addListener(handleReducedMotionChange),
1503
1659
  mediaQueryHighContrast.addListener(handleHighContrastChange)), () => {
1504
- try {
1505
- mediaQueryReducedMotion.removeEventListener ? (mediaQueryReducedMotion.removeEventListener("change", handleReducedMotionChange),
1506
- mediaQueryHighContrast.removeEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.removeListener && (mediaQueryReducedMotion.removeListener(handleReducedMotionChange),
1507
- mediaQueryHighContrast.removeListener(handleHighContrastChange));
1508
- } catch (cleanupError) {
1509
- console.error("AtomixGlass: Error cleaning up media query listeners:", cleanupError);
1510
- }
1660
+ // ignore
1511
1661
  };
1512
1662
  } catch (error) {
1513
- return void console.error("AtomixGlass: Error setting up media queries:", error);
1663
+ return;
1514
1664
  }
1515
1665
  }), [ overLight, glassRef, debugOverLight ]);
1516
- // Mouse tracking using shared global tracker
1517
- // Cache bounding rect to avoid repeated getBoundingClientRect calls
1518
- const cachedRectRef = useRef(null), updateRectRef = useRef(null), handleGlobalMousePosition = useCallback((globalPos => {
1519
- if (externalGlobalMousePosition && externalMouseOffset)
1520
- // External mouse position provided, skip internal tracking
1521
- return;
1522
- if (effectiveDisableEffects) return;
1523
- const container = mouseContainer?.current || glassRef.current;
1524
- if (!container) return;
1525
- // Use cached rect if available, otherwise get new one
1526
- let rect = cachedRectRef.current;
1527
- if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
1528
- cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
1529
- const center = calculateElementCenter(rect), newOffset = {
1530
- x: (globalPos.x - center.x) / rect.width * 100,
1531
- y: (globalPos.y - center.y) / rect.height * 100
1666
+ /**
1667
+ * Get effective overLight value based on configuration
1668
+ */
1669
+ 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((() => {
1670
+ const isOverLight = getEffectiveOverLight(), baseConfig = {
1671
+ isOverLight: isOverLight,
1672
+ threshold: .7,
1673
+ opacity: isOverLight ? Math.min(.6, Math.max(.2, .5)) : 0,
1674
+ contrast: 1,
1675
+ // Base contrast
1676
+ brightness: 1,
1677
+ // Base brightness
1678
+ saturationBoost: 1.3,
1679
+ shadowIntensity: .9,
1680
+ borderOpacity: .7
1532
1681
  };
1533
- // Calculate offset relative to this container
1534
- // React 18 automatically batches these updates
1535
- setInternalMouseOffset(newOffset), setInternalGlobalMousePosition(globalPos);
1536
- }), [ mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveDisableEffects ]);
1537
- // Subscribe to shared mouse tracker
1538
- useEffect((() => {
1539
- if (externalGlobalMousePosition && externalMouseOffset)
1540
- // External mouse position provided, don't subscribe
1541
- return;
1542
- if (effectiveDisableEffects)
1543
- // Effects disabled, don't subscribe
1544
- return;
1545
- // Subscribe to shared tracker
1546
- const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition), container = mouseContainer?.current || glassRef.current;
1547
- // Update cached rect when container size changes
1548
- let resizeObserver = null;
1549
- return container && "undefined" != typeof ResizeObserver && (resizeObserver = new ResizeObserver((() => {
1550
- null !== updateRectRef.current && cancelAnimationFrame(updateRectRef.current), updateRectRef.current = requestAnimationFrame((() => {
1551
- const container = mouseContainer?.current || glassRef.current;
1552
- container && (cachedRectRef.current = container.getBoundingClientRect()), updateRectRef.current = null;
1553
- }));
1554
- })), resizeObserver.observe(container)), () => {
1555
- unsubscribe(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
1556
- updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
1682
+ if ("object" == typeof overLight && null !== overLight) {
1683
+ 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);
1684
+ return {
1685
+ ...baseConfig,
1686
+ threshold: validatedThreshold,
1687
+ opacity: validatedOpacity,
1688
+ contrast: validatedContrast,
1689
+ brightness: validatedBrightness,
1690
+ saturationBoost: validatedSaturationBoost
1691
+ };
1692
+ }
1693
+ return baseConfig;
1694
+ }), [ overLight, getEffectiveOverLight, validateConfigValue ]), overLightConfig = useMemo((() => {
1695
+ const mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1;
1696
+ return {
1697
+ isOverLight: baseOverLightConfig.isOverLight,
1698
+ threshold: baseOverLightConfig.threshold,
1699
+ opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
1700
+ contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
1701
+ brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
1702
+ saturationBoost: baseOverLightConfig.saturationBoost,
1703
+ shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
1704
+ borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence))
1557
1705
  };
1558
- }), [ handleGlobalMousePosition, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveDisableEffects ]);
1559
- // Transform calculations
1560
- const calculateDirectionalScale = useCallback((() => {
1561
- if (!0 === overLight || "auto" === overLight && detectedOverLight || "object" == typeof overLight && null !== overLight && detectedOverLight) return "scale(1)";
1706
+ }), [ baseOverLightConfig, mouseOffset, isHovered, isActive ]), updateRectRef = useRef(null), calculateDirectionalScale = useCallback((() => {
1707
+ if (baseOverLightConfig.isOverLight) return "scale(1)";
1562
1708
  if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return "scale(1)";
1563
1709
  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({
1564
1710
  x: edgeDistanceX,
@@ -1572,7 +1718,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1572
1718
  if (0 === centerDistance) return "scale(1)";
1573
1719
  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;
1574
1720
  return `scaleX(${Math.max(.8, scaleX)}) scaleY(${Math.max(.8, scaleY)})`;
1575
- }), [ globalMousePosition, elasticity, glassSize, glassRef, overLight, detectedOverLight ]), calculateFadeInFactor = useCallback((() => {
1721
+ }), [ globalMousePosition, elasticity, glassSize, glassRef, baseOverLightConfig ]), calculateFadeInFactor = useCallback((() => {
1576
1722
  if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return 0;
1577
1723
  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({
1578
1724
  x: edgeDistanceX,
@@ -1592,122 +1738,110 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1592
1738
  x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
1593
1739
  y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
1594
1740
  };
1595
- }), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = useMemo((() => effectiveDisableEffects ? {
1741
+ }), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = useMemo((() => effectiveWithoutEffects ? {
1596
1742
  x: 0,
1597
1743
  y: 0
1598
- } : 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 ]);
1599
- // Size management
1600
- useEffect((() => {
1601
- const isValidElement = element => null !== element && element instanceof HTMLElement && element.isConnected;
1602
- let rafId = null, lastSize = {
1603
- width: 0,
1604
- height: 0
1605
- }, lastCornerRadius = effectiveCornerRadius;
1606
- const updateGlassSize = (forceUpdate = !1) => {
1607
- null !== rafId && cancelAnimationFrame(rafId), rafId = requestAnimationFrame((() => {
1608
- if (!isValidElement(glassRef.current)) return void (rafId = null);
1609
- const rect = glassRef.current.getBoundingClientRect();
1610
- if (rect.width <= 0 || rect.height <= 0) return void (rafId = null);
1611
- // Measure actual rendered size without artificial offsets to avoid feedback loops
1612
- const newSize = {
1613
- width: Math.round(rect.width),
1614
- height: Math.round(rect.height)
1615
- }, cornerRadiusChanged = lastCornerRadius !== effectiveCornerRadius, dimensionsChanged = Math.abs(newSize.width - lastSize.width) > 1 || Math.abs(newSize.height - lastSize.height) > 1;
1616
- var size;
1617
- (forceUpdate || cornerRadiusChanged || dimensionsChanged) && validateGlassSize(size = newSize) && size.width <= CONSTANTS.MAX_SIZE && size.height <= CONSTANTS.MAX_SIZE && (lastSize = newSize,
1618
- lastCornerRadius = effectiveCornerRadius, setGlassSize(newSize)), rafId = null;
1619
- }));
1620
- };
1621
- let resizeTimeoutId = null;
1622
- const debouncedResizeHandler = () => {
1623
- resizeTimeoutId && clearTimeout(resizeTimeoutId), resizeTimeoutId = setTimeout((() => updateGlassSize(!1)), 16);
1624
- }, initialTimeoutId = setTimeout((() => updateGlassSize(!0)), 0);
1625
- let resizeObserver = null, resizeDebounceTimeout = null;
1626
- // ResizeObserver has 98%+ browser support, no need for fallback
1627
- if ("undefined" != typeof ResizeObserver && isValidElement(glassRef.current)) try {
1628
- resizeObserver = new ResizeObserver((entries => {
1629
- for (const entry of entries) if (entry.target === glassRef.current) {
1630
- // Update cached rect when size changes
1631
- glassRef.current && (cachedRectRef.current = glassRef.current.getBoundingClientRect()),
1632
- // Debounce resize updates to match RAF timing (16ms)
1633
- resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), resizeDebounceTimeout = setTimeout((() => updateGlassSize(!1)), 16);
1634
- break;
1635
- }
1636
- })), resizeObserver.observe(glassRef.current);
1637
- } catch (error) {
1638
- console.warn("AtomixGlass: ResizeObserver not available, using window resize only", error);
1639
- }
1640
- return window.addEventListener("resize", debouncedResizeHandler, {
1641
- passive: !0
1642
- }), () => {
1643
- clearTimeout(initialTimeoutId), null !== rafId && cancelAnimationFrame(rafId), resizeTimeoutId && clearTimeout(resizeTimeoutId),
1644
- resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), window.removeEventListener("resize", debouncedResizeHandler),
1645
- resizeObserver?.disconnect();
1744
+ } : 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 => {
1745
+ if (externalGlobalMousePosition && externalMouseOffset) return;
1746
+ if (effectiveWithoutEffects) return;
1747
+ const container = mouseContainer?.current || glassRef.current;
1748
+ if (!container) return;
1749
+ // Use cached rect if available, otherwise get new one
1750
+ let rect = cachedRectRef.current;
1751
+ if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
1752
+ cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
1753
+ const center = calculateElementCenter(rect), newOffset = {
1754
+ x: (globalPos.x - center.x) / rect.width * 100,
1755
+ y: (globalPos.y - center.y) / rect.height * 100
1646
1756
  };
1647
- }), [ effectiveCornerRadius, glassRef ]);
1648
- // OverLight config
1757
+ // Calculate offset relative to this container
1758
+ // Store in refs instead of state
1759
+ internalMouseOffsetRef.current = newOffset, internalGlobalMousePositionRef.current = globalPos,
1760
+ // Imperative style update
1761
+ updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
1762
+ mouseOffset: newOffset,
1763
+ globalMousePosition: globalPos,
1764
+ glassSize: glassSize,
1765
+ isHovered: isHovered,
1766
+ isActive: isActive,
1767
+ isOverLight: baseOverLightConfig.isOverLight,
1768
+ baseOverLightConfig: baseOverLightConfig,
1769
+ effectiveBorderRadius: effectiveBorderRadius,
1770
+ effectiveWithoutEffects: effectiveWithoutEffects,
1771
+ effectiveReducedMotion: effectiveReducedMotion,
1772
+ elasticity: elasticity,
1773
+ directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
1774
+ // Simplified directional scale for fast path
1775
+ onClick: onClick,
1776
+ withLiquidBlur: withLiquidBlur,
1777
+ blurAmount: blurAmount,
1778
+ saturation: saturation,
1779
+ padding: padding
1780
+ });
1781
+ }), [ mouseContainer, glassRef, wrapperRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects, glassSize, isHovered, isActive, baseOverLightConfig, effectiveBorderRadius, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding ]);
1649
1782
  /**
1650
- * Get effective overLight value based on configuration
1651
- * - boolean: returns the boolean value directly
1652
- * - 'auto': returns detectedOverLight (auto-detected from background)
1653
- * - object: returns detectedOverLight (auto-detected, but config object provides customization)
1654
- */
1655
- 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((() => {
1656
- const isOverLight = getEffectiveOverLight(), mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1, baseConfig = {
1657
- isOverLight: isOverLight,
1658
- threshold: .7,
1659
- opacity: isOverLight ? Math.min(.6, Math.max(.2, .5 * hoverIntensity * activeIntensity)) : 0,
1660
- contrast: Math.min(1.6, Math.max(1, 1.4 + .1 * mouseInfluence)),
1661
- brightness: Math.min(1.1, Math.max(.8, .9 + .05 * mouseInfluence)),
1662
- saturationBoost: 1.3,
1663
- // Fixed value dynamic saturation amplifies perceived displacement
1664
- shadowIntensity: Math.min(1.2, Math.max(.5, .9 + .2 * mouseInfluence)),
1665
- borderOpacity: Math.min(1, Math.max(.3, .7 + .1 * mouseInfluence))
1783
+ * Validate and clamp a numeric config value
1784
+ */
1785
+ // Subscribe to shared mouse tracker
1786
+ useEffect((() => {
1787
+ if (externalGlobalMousePosition && externalMouseOffset) return;
1788
+ if (effectiveWithoutEffects) return;
1789
+ const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition), container = mouseContainer?.current || glassRef.current;
1790
+ let resizeObserver = null;
1791
+ return container && "undefined" != typeof ResizeObserver && (resizeObserver = new ResizeObserver((() => {
1792
+ null !== updateRectRef.current && cancelAnimationFrame(updateRectRef.current), updateRectRef.current = requestAnimationFrame((() => {
1793
+ const container = mouseContainer?.current || glassRef.current;
1794
+ container && (cachedRectRef.current = container.getBoundingClientRect()), updateRectRef.current = null;
1795
+ }));
1796
+ })), resizeObserver.observe(container)), () => {
1797
+ unsubscribe(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
1798
+ updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
1666
1799
  };
1667
- if ("object" == typeof overLight && null !== overLight) {
1668
- 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 = {
1669
- ...baseConfig,
1670
- threshold: validatedThreshold,
1671
- opacity: validatedOpacity * hoverIntensity * activeIntensity,
1672
- contrast: Math.min(1.6, validatedContrast + .1 * mouseInfluence),
1673
- brightness: Math.min(1.1, validatedBrightness + .05 * mouseInfluence),
1674
- saturationBoost: validatedSaturationBoost
1675
- };
1676
- // Validate and apply object config values with proper clamping
1677
- return "undefined" == typeof process || process.env, finalConfig;
1678
- }
1679
- // Debug logging for non-object configs
1680
- return "undefined" == typeof process || process.env, baseConfig;
1681
- }), [ 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 => {
1800
+ }), [ handleGlobalMousePosition, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects ]),
1801
+ // Also call updateStyles on other state changes (hover, active, etc)
1802
+ useEffect((() => {
1803
+ updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
1804
+ mouseOffset: externalMouseOffset || internalMouseOffsetRef.current,
1805
+ globalMousePosition: externalGlobalMousePosition || internalGlobalMousePositionRef.current,
1806
+ glassSize: glassSize,
1807
+ isHovered: isHovered,
1808
+ isActive: isActive,
1809
+ isOverLight: baseOverLightConfig.isOverLight,
1810
+ baseOverLightConfig: baseOverLightConfig,
1811
+ effectiveBorderRadius: effectiveBorderRadius,
1812
+ effectiveWithoutEffects: effectiveWithoutEffects,
1813
+ effectiveReducedMotion: effectiveReducedMotion,
1814
+ elasticity: elasticity,
1815
+ directionalScale: directionalScale,
1816
+ onClick: onClick,
1817
+ withLiquidBlur: withLiquidBlur,
1818
+ blurAmount: blurAmount,
1819
+ saturation: saturation,
1820
+ padding: padding
1821
+ });
1822
+ }), [ isHovered, isActive, glassSize, baseOverLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, directionalScale, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation, padding, onClick ]);
1823
+ // Event handlers
1824
+ const handleMouseEnter = useCallback((() => setIsHovered(!0)), []), handleMouseLeave = useCallback((() => setIsHovered(!1)), []), handleMouseDown = useCallback((() => setIsActive(!0)), []), handleMouseUp = useCallback((() => setIsActive(!1)), []), handleMouseMove = useCallback((_e => {}), []), handleKeyDown = useCallback((e => {
1682
1825
  !onClick || "Enter" !== e.key && " " !== e.key || (e.preventDefault(), onClick());
1683
- }), [ onClick ]), handleMouseMove = useCallback((_e => {}), []);
1684
- /**
1685
- * Validate and clamp a numeric config value
1686
- * @param value - The value to validate
1687
- * @param min - Minimum allowed value
1688
- * @param max - Maximum allowed value
1689
- * @param defaultValue - Default value if validation fails
1690
- * @returns Validated and clamped value
1691
- */ return {
1692
- // State
1826
+ }), [ onClick ]);
1827
+ return {
1693
1828
  isHovered: isHovered,
1694
1829
  isActive: isActive,
1695
1830
  glassSize: glassSize,
1696
- dynamicCornerRadius: dynamicCornerRadius,
1697
- effectiveCornerRadius: effectiveCornerRadius,
1831
+ dynamicBorderRadius: dynamicBorderRadius,
1832
+ effectiveBorderRadius: effectiveBorderRadius,
1698
1833
  effectiveReducedMotion: effectiveReducedMotion,
1699
1834
  effectiveHighContrast: effectiveHighContrast,
1700
- effectiveDisableEffects: effectiveDisableEffects,
1835
+ effectiveWithoutEffects: effectiveWithoutEffects,
1701
1836
  detectedOverLight: detectedOverLight,
1702
1837
  globalMousePosition: globalMousePosition,
1838
+ // This is now static (refs or props) unless prop changes
1703
1839
  mouseOffset: mouseOffset,
1704
- // OverLight config
1840
+ // This is now static (refs or props) unless prop changes
1705
1841
  overLightConfig: overLightConfig,
1706
- // Transform calculations
1707
1842
  elasticTranslation: elasticTranslation,
1708
1843
  directionalScale: directionalScale,
1709
1844
  transformStyle: transformStyle,
1710
- // Event handlers
1711
1845
  handleMouseEnter: handleMouseEnter,
1712
1846
  handleMouseLeave: handleMouseLeave,
1713
1847
  handleMouseDown: handleMouseDown,
@@ -1746,7 +1880,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1746
1880
  *
1747
1881
  * @example
1748
1882
  * // Manual border-radius override
1749
- * <AtomixGlass cornerRadius={20}>
1883
+ * <AtomixGlass borderRadius={20}>
1750
1884
  * <div>Content with 20px glass radius</div>
1751
1885
  * </AtomixGlass>
1752
1886
  *
@@ -1787,37 +1921,48 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1787
1921
  * <AtomixGlass overLight="auto" debugOverLight={true}>
1788
1922
  * <div>Content with debug logging enabled</div>
1789
1923
  * </AtomixGlass>
1790
- */ 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}) {
1791
- 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({
1924
+ */ 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}) {
1925
+ 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({
1792
1926
  glassRef: glassRef,
1793
1927
  contentRef: contentRef,
1794
- cornerRadius: cornerRadius,
1928
+ borderRadius: borderRadius,
1795
1929
  globalMousePosition: externalGlobalMousePosition,
1796
1930
  mouseOffset: externalMouseOffset,
1797
1931
  mouseContainer: mouseContainer,
1798
1932
  overLight: overLight,
1799
1933
  reducedMotion: reducedMotion,
1800
1934
  highContrast: highContrast,
1801
- disableEffects: disableEffects,
1935
+ withoutEffects: withoutEffects,
1802
1936
  elasticity: elasticity,
1803
1937
  onClick: onClick,
1804
- debugCornerRadius: debugCornerRadius,
1938
+ debugBorderRadius: debugBorderRadius,
1805
1939
  debugOverLight: debugOverLight,
1806
- enablePerformanceMonitoring: enablePerformanceMonitoring,
1807
- children: children
1808
- }), isOverLight = useMemo((() => overLightConfig?.isOverLight), [ overLight ]), shouldRenderOverLightLayers = enableOverLightLayers && isOverLight, baseStyle = {
1940
+ debugPerformance: debugPerformance,
1941
+ children: children,
1942
+ blurAmount: blurAmount,
1943
+ saturation: saturation,
1944
+ withLiquidBlur: withLiquidBlur,
1945
+ padding: padding,
1946
+ style: style
1947
+ }), isOverLight = useMemo((() => overLightConfig?.isOverLight), [ overLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, baseStyle = {
1809
1948
  ...style,
1810
- ...!effectiveDisableEffects && {
1949
+ ...!effectiveWithoutEffects && {
1811
1950
  transform: transformStyle
1812
1951
  }
1813
- }, 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((() => ({
1952
+ }, 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((() => ({
1814
1953
  position: style.position || "absolute",
1815
1954
  top: style.top || 0,
1816
1955
  left: style.left || 0
1817
- })), [ style.position, style.top, style.left ]), adjustedSize = useMemo((() => ({
1818
- width: "fixed" !== style.position ? "100%" : style.width ? style.width : Math.max(glassSize.width, 0),
1819
- height: "fixed" !== style.position ? "100%" : style.height ? style.height : Math.max(glassSize.height, 0)
1820
- })), [ style.position, style.width, style.height, glassSize.width, glassSize.height ]), gradientValues = useMemo((() => {
1956
+ })), [ style.position, style.top, style.left ]), adjustedSize = useMemo((() => {
1957
+ const resolveSize = (propValue, styleValue, measuredSize) => {
1958
+ const explicitSize = propValue ?? styleValue;
1959
+ return void 0 !== explicitSize ? "number" == typeof explicitSize ? `${explicitSize}px` : explicitSize : "fixed" === positionStyles.position ? `${Math.max(measuredSize, 0)}px` : "100%";
1960
+ };
1961
+ return {
1962
+ width: resolveSize(width, style.width, glassSize.width),
1963
+ height: resolveSize(height, style.height, glassSize.height)
1964
+ };
1965
+ }), [ width, height, style.width, style.height, positionStyles.position, glassSize.width, glassSize.height ]), gradientValues = useMemo((() => {
1821
1966
  const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT;
1822
1967
  return {
1823
1968
  borderGradientAngle: GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER,
@@ -1859,13 +2004,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1859
2004
  }), [ isHovered, isActive, isOverLight, overLightConfig.opacity ]), glassVars = useMemo((() => {
1860
2005
  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;
1861
2006
  return {
1862
- "--atomix-glass-radius": `${effectiveCornerRadius}px`,
2007
+ "--atomix-glass-radius": `${effectiveBorderRadius}px`,
1863
2008
  "--atomix-glass-transform": transformStyle || "none",
1864
2009
  "--atomix-glass-position": positionStyles.position,
1865
2010
  "--atomix-glass-top": "fixed" !== positionStyles.top ? `${positionStyles.top}px` : "0",
1866
2011
  "--atomix-glass-left": "fixed" !== positionStyles.left ? `${positionStyles.left}px` : "0",
1867
- "--atomix-glass-width": "fixed" !== style.position ? adjustedSize.width : `${adjustedSize.width}px`,
1868
- "--atomix-glass-height": "fixed" !== style.position ? adjustedSize.height : `${adjustedSize.height}px`,
2012
+ "--atomix-glass-width": adjustedSize.width,
2013
+ "--atomix-glass-height": adjustedSize.height,
1869
2014
  "--atomix-glass-border-width": "var(--atomix-spacing-0-5, 0.09375rem)",
1870
2015
  "--atomix-glass-blend-mode": isOverLight ? "multiply" : "overlay",
1871
2016
  "--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%)`,
@@ -1881,24 +2026,25 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1881
2026
  "--atomix-glass-overlay-opacity": opacityValues.over,
1882
2027
  "--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})`
1883
2028
  };
1884
- }), [ gradientValues, opacityValues, effectiveCornerRadius, transformStyle, positionStyles, adjustedSize, style.position, isOverLight, overLightConfig.borderOpacity ]), renderBackgroundLayer = layerType => jsx("div", {
2029
+ }), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle, positionStyles, adjustedSize, isOverLight, overLightConfig.borderOpacity ]), renderBackgroundLayer = layerType => jsx("div", {
1885
2030
  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(" "),
1886
2031
  style: {
1887
2032
  ...positionStyles,
1888
2033
  height: adjustedSize.height,
1889
2034
  width: adjustedSize.width,
1890
- borderRadius: `${effectiveCornerRadius}px`,
2035
+ borderRadius: `${effectiveBorderRadius}px`,
1891
2036
  transform: baseStyle.transform
1892
2037
  }
1893
2038
  });
1894
2039
  return jsxs("div", {
2040
+ ...rest,
1895
2041
  className: componentClassName,
1896
2042
  style: glassVars,
1897
2043
  role: role || (onClick ? "button" : void 0),
1898
2044
  tabIndex: onClick ? tabIndex ?? 0 : tabIndex,
1899
2045
  "aria-label": ariaLabel,
1900
2046
  "aria-describedby": ariaDescribedBy,
1901
- "aria-disabled": !(!onClick || !effectiveDisableEffects) || !onClick && void 0,
2047
+ "aria-disabled": !(!onClick || !effectiveWithoutEffects) || !onClick && void 0,
1902
2048
  "aria-pressed": !(!onClick || !isActive) || !onClick && void 0,
1903
2049
  onKeyDown: onClick ? handleKeyDown : void 0,
1904
2050
  children: [ jsx(AtomixGlassContainer, {
@@ -1906,18 +2052,18 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1906
2052
  contentRef: contentRef,
1907
2053
  className: className,
1908
2054
  style: baseStyle,
1909
- cornerRadius: effectiveCornerRadius,
1910
- displacementScale: effectiveDisableEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
1911
- blurAmount: effectiveDisableEffects ? 0 : blurAmount,
2055
+ borderRadius: effectiveBorderRadius,
2056
+ displacementScale: effectiveWithoutEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
2057
+ blurAmount: effectiveWithoutEffects ? 0 : blurAmount,
1912
2058
  saturation: effectiveHighContrast ? ATOMIX_GLASS.CONSTANTS.SATURATION.HIGH_CONTRAST : isOverLight ? saturation * overLightConfig.saturationBoost : saturation,
1913
- aberrationIntensity: effectiveDisableEffects ? 0 : "shader" === mode ? aberrationIntensity * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_ABERRATION : aberrationIntensity,
2059
+ aberrationIntensity: effectiveWithoutEffects ? 0 : "shader" === mode ? aberrationIntensity * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_ABERRATION : aberrationIntensity,
1914
2060
  glassSize: glassSize,
1915
2061
  padding: padding,
1916
- mouseOffset: effectiveDisableEffects ? {
2062
+ mouseOffset: effectiveWithoutEffects ? {
1917
2063
  x: 0,
1918
2064
  y: 0
1919
2065
  } : mouseOffset,
1920
- globalMousePosition: effectiveDisableEffects ? {
2066
+ globalMousePosition: effectiveWithoutEffects ? {
1921
2067
  x: 0,
1922
2068
  y: 0
1923
2069
  } : globalMousePosition,
@@ -1937,11 +2083,11 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1937
2083
  onClick: onClick,
1938
2084
  mode: mode,
1939
2085
  transform: baseStyle.transform,
1940
- effectiveDisableEffects: effectiveDisableEffects,
2086
+ effectiveWithoutEffects: effectiveWithoutEffects,
1941
2087
  effectiveReducedMotion: effectiveReducedMotion,
1942
2088
  shaderVariant: shaderVariant,
1943
2089
  elasticity: elasticity,
1944
- enableLiquidBlur: enableLiquidBlur,
2090
+ withLiquidBlur: withLiquidBlur,
1945
2091
  children: children
1946
2092
  }), Boolean(onClick) && jsxs(Fragment, {
1947
2093
  children: [ jsx("div", {
@@ -1963,11 +2109,19 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1963
2109
  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}%)`
1964
2110
  }
1965
2111
  }) ]
1966
- }), enableBorderEffect && jsxs(Fragment, {
2112
+ }), withBorder && jsxs(Fragment, {
1967
2113
  children: [ jsx("span", {
1968
- className: ATOMIX_GLASS.BORDER_1_CLASS
2114
+ className: ATOMIX_GLASS.BORDER_1_CLASS,
2115
+ style: {
2116
+ width: glassSize.width,
2117
+ height: glassSize.height
2118
+ }
1969
2119
  }), jsx("span", {
1970
- className: ATOMIX_GLASS.BORDER_2_CLASS
2120
+ className: ATOMIX_GLASS.BORDER_2_CLASS,
2121
+ style: {
2122
+ width: glassSize.width,
2123
+ height: glassSize.height
2124
+ }
1971
2125
  }) ]
1972
2126
  }) ]
1973
2127
  });
@@ -2235,7 +2389,7 @@ const Accordion = AccordionWithSubcomponents, Badge = memo((({label: label, var
2235
2389
  // Default glass settings for badges
2236
2390
  const defaultGlassProps = {
2237
2391
  displacementScale: 20,
2238
- cornerRadius: ref.current?.getBoundingClientRect().width ? ref.current?.getBoundingClientRect().width / 2 : 16,
2392
+ borderRadius: ref.current?.getBoundingClientRect().width ? ref.current?.getBoundingClientRect().width / 2 : 16,
2239
2393
  className: "c-badge--glass",
2240
2394
  elasticity: 0
2241
2395
  }, glassProps = !0 === glass ? defaultGlassProps : {
@@ -2356,7 +2510,7 @@ const Block = forwardRef((({children: children, as: Component = "section", spac
2356
2510
  * ```
2357
2511
  */ Block.displayName = "Block";
2358
2512
 
2359
- const BreadcrumbItem = forwardRef((({children: children, href: href, active: active, icon: icon, onClick: onClick, className: className = "", style: style, linkAs: LinkComponent, linkProps: linkProps = {}, ...props}, ref) => {
2513
+ const BreadcrumbItem = forwardRef((({children: children, href: href, active: active, icon: icon, onClick: onClick, className: className = "", style: style, linkAs: linkAs, linkProps: linkProps = {}, ...props}, ref) => {
2360
2514
  const itemClasses = [ BREADCRUMB.CLASSES.ITEM, active ? BREADCRUMB.CLASSES.ACTIVE : "", className ].filter(Boolean).join(" "), linkContent = jsxs(Fragment, {
2361
2515
  children: [ icon && jsx("span", {
2362
2516
  className: "c-breadcrumb__icon",
@@ -2374,7 +2528,9 @@ const BreadcrumbItem = forwardRef((({children: children, href: href, active: ac
2374
2528
  className: itemClasses,
2375
2529
  style: style,
2376
2530
  ...props,
2377
- children: href && !active ? jsx(LinkComponent || "a", {
2531
+ children: href && !active ?
2532
+ // @ts-ignore - Dynamic components are tricky in TS without stricter types
2533
+ jsx(linkAs || "a", {
2378
2534
  href: href,
2379
2535
  ...commonLinkProps,
2380
2536
  children: linkContent
@@ -2387,7 +2543,7 @@ const BreadcrumbItem = forwardRef((({children: children, href: href, active: ac
2387
2543
 
2388
2544
  BreadcrumbItem.displayName = "BreadcrumbItem";
2389
2545
 
2390
- const Breadcrumb = memo((({items: items, divider: divider, className: className = "", "aria-label": ariaLabel = "Breadcrumb", LinkComponent: LinkComponent, style: style, children: children}) => {
2546
+ const Breadcrumb = memo((function({items: items, divider: divider, className: className = "", "aria-label": ariaLabel = "Breadcrumb", LinkComponent: LinkComponent, style: style, children: children}) {
2391
2547
  const breadcrumbClasses = [ BREADCRUMB.CLASSES.BASE, className ].filter(Boolean).join(" ");
2392
2548
  let content;
2393
2549
  if (items && items.length > 0)
@@ -2409,11 +2565,11 @@ const Breadcrumb = memo((({items: items, divider: divider, className: className
2409
2565
  const childrenCount = Children.count(children);
2410
2566
  content = Children.map(children, ((child, index) => {
2411
2567
  if ( isValidElement(child)) {
2412
- const isLast = index === childrenCount - 1, childProps = child.props;
2568
+ const isLast = index === childrenCount - 1, childProps = child.props, {active: active, linkAs: linkAs, ...otherProps} = childProps;
2413
2569
 
2414
2570
  return cloneElement(child, {
2415
- active: childProps.active ?? (!!isLast || void 0),
2416
- linkAs: childProps.linkAs ?? LinkComponent
2571
+ active: active ?? (!!isLast || void 0),
2572
+ linkAs: linkAs ?? LinkComponent
2417
2573
  });
2418
2574
  }
2419
2575
  return child;
@@ -2480,7 +2636,7 @@ const Spinner = memo((({size: size = "md", variant: variant = "primary", fullsc
2480
2636
  const defaultGlassProps = {
2481
2637
  displacementScale: 20,
2482
2638
  blurAmount: 1,
2483
- cornerRadius: 999,
2639
+ borderRadius: 999,
2484
2640
  mode: "shader"
2485
2641
  }, glassProps = !0 === glass ? defaultGlassProps : {
2486
2642
  ...defaultGlassProps,
@@ -3135,7 +3291,7 @@ const Callout = memo((({title: title, children: children, icon: icon, variant:
3135
3291
  // Default glass settings for callouts
3136
3292
  const defaultGlassProps = {
3137
3293
  displacementScale: 30,
3138
- cornerRadius: 8,
3294
+ borderRadius: 8,
3139
3295
  elasticity: 0
3140
3296
  }, glassProps = !0 === glass ? defaultGlassProps : {
3141
3297
  ...defaultGlassProps,
@@ -3157,7 +3313,7 @@ const Callout = memo((({title: title, children: children, icon: icon, variant:
3157
3313
  children: jsx("div", {
3158
3314
  className: "c-callout__glass-content",
3159
3315
  style: {
3160
- borderRadius: glassProps.cornerRadius
3316
+ borderRadius: glassProps.borderRadius
3161
3317
  },
3162
3318
  children: calloutContent
3163
3319
  })