@shohojdhara/atomix 0.4.0 → 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 (150) hide show
  1. package/dist/atomix.css +0 -14
  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 -359
  7. package/dist/charts.js.map +1 -1
  8. package/dist/core.d.ts +98 -28
  9. package/dist/core.js +1082 -733
  10. package/dist/core.js.map +1 -1
  11. package/dist/forms.d.ts +26 -21
  12. package/dist/forms.js +937 -350
  13. package/dist/forms.js.map +1 -1
  14. package/dist/heavy.d.ts +14 -21
  15. package/dist/heavy.js +409 -256
  16. package/dist/heavy.js.map +1 -1
  17. package/dist/index.d.ts +518 -284
  18. package/dist/index.esm.js +1993 -1237
  19. package/dist/index.esm.js.map +1 -1
  20. package/dist/index.js +1994 -1237
  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 +2 -2
  25. package/scripts/atomix-cli.js +43 -1
  26. package/scripts/cli/__tests__/utils.test.js +6 -2
  27. package/scripts/cli/migration-tools.js +2 -2
  28. package/scripts/cli/theme-bridge.js +7 -9
  29. package/scripts/cli/utils.js +2 -1
  30. package/src/components/Accordion/Accordion.stories.tsx +40 -0
  31. package/src/components/Accordion/Accordion.tsx +174 -56
  32. package/src/components/Accordion/AccordionCompound.test.tsx +70 -0
  33. package/src/components/AtomixGlass/AtomixGlass.tsx +82 -54
  34. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +17 -18
  35. package/src/components/AtomixGlass/README.md +5 -5
  36. package/src/components/AtomixGlass/stories/Customization.stories.tsx +2 -2
  37. package/src/components/AtomixGlass/stories/Examples.stories.tsx +42 -42
  38. package/src/components/AtomixGlass/stories/Modes.stories.tsx +5 -5
  39. package/src/components/AtomixGlass/stories/Overview.stories.tsx +3 -3
  40. package/src/components/AtomixGlass/stories/Performance.stories.tsx +2 -2
  41. package/src/components/AtomixGlass/stories/Playground.stories.tsx +45 -45
  42. package/src/components/AtomixGlass/stories/Shaders.stories.tsx +3 -3
  43. package/src/components/Badge/Badge.stories.tsx +1 -1
  44. package/src/components/Badge/Badge.tsx +1 -1
  45. package/src/components/Breadcrumb/Breadcrumb.tsx +185 -65
  46. package/src/components/Breadcrumb/BreadcrumbCompound.test.tsx +84 -0
  47. package/src/components/Breadcrumb/index.ts +2 -2
  48. package/src/components/Button/Button.stories.tsx +1 -1
  49. package/src/components/Button/README.md +2 -2
  50. package/src/components/Callout/Callout.stories.tsx +166 -1011
  51. package/src/components/Callout/Callout.test.tsx +3 -3
  52. package/src/components/Callout/Callout.tsx +196 -84
  53. package/src/components/Callout/CalloutCompound.test.tsx +72 -0
  54. package/src/components/Callout/README.md +2 -2
  55. package/src/components/Chart/Chart.stories.tsx +1 -1
  56. package/src/components/Chart/Chart.tsx +5 -5
  57. package/src/components/Chart/TreemapChart.tsx +37 -29
  58. package/src/components/DatePicker/readme.md +3 -3
  59. package/src/components/Dropdown/Dropdown.stories.tsx +1 -1
  60. package/src/components/Dropdown/Dropdown.tsx +133 -20
  61. package/src/components/Dropdown/DropdownCompound.test.tsx +64 -0
  62. package/src/components/EdgePanel/EdgePanel.stories.tsx +7 -7
  63. package/src/components/EdgePanel/EdgePanel.tsx +164 -112
  64. package/src/components/EdgePanel/EdgePanelCompound.test.tsx +53 -0
  65. package/src/components/Form/Checkbox.stories.tsx +1 -1
  66. package/src/components/Form/Checkbox.tsx +1 -1
  67. package/src/components/Form/Input.stories.tsx +1 -1
  68. package/src/components/Form/Input.tsx +1 -1
  69. package/src/components/Form/Radio.stories.tsx +1 -1
  70. package/src/components/Form/Radio.tsx +1 -1
  71. package/src/components/Form/Select.stories.tsx +24 -1
  72. package/src/components/Form/Select.test.tsx +99 -0
  73. package/src/components/Form/Select.tsx +145 -94
  74. package/src/components/Form/SelectOption.tsx +88 -0
  75. package/src/components/Form/Textarea.stories.tsx +1 -1
  76. package/src/components/Form/Textarea.tsx +1 -1
  77. package/src/components/Hero/Hero.stories.tsx +39 -2
  78. package/src/components/Hero/Hero.test.tsx +142 -0
  79. package/src/components/Hero/Hero.tsx +143 -4
  80. package/src/components/List/List.test.tsx +62 -0
  81. package/src/components/List/List.tsx +16 -5
  82. package/src/components/List/ListItem.tsx +20 -0
  83. package/src/components/Messages/Messages.stories.tsx +1 -1
  84. package/src/components/Messages/Messages.tsx +2 -2
  85. package/src/components/Modal/Modal.stories.tsx +66 -2
  86. package/src/components/Modal/Modal.tsx +115 -35
  87. package/src/components/Modal/ModalCompound.test.tsx +94 -0
  88. package/src/components/Navigation/Nav/Nav.stories.tsx +2 -2
  89. package/src/components/Navigation/Nav/Nav.tsx +1 -1
  90. package/src/components/Navigation/Navbar/Navbar.stories.tsx +3 -3
  91. package/src/components/Navigation/Navbar/Navbar.tsx +1 -1
  92. package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +2 -2
  93. package/src/components/Navigation/SideMenu/SideMenu.tsx +1 -1
  94. package/src/components/Pagination/Pagination.stories.tsx +1 -1
  95. package/src/components/Pagination/Pagination.tsx +1 -1
  96. package/src/components/Popover/Popover.stories.tsx +1 -1
  97. package/src/components/Popover/Popover.tsx +1 -1
  98. package/src/components/Progress/Progress.tsx +1 -1
  99. package/src/components/Rating/Rating.stories.tsx +1 -1
  100. package/src/components/Rating/Rating.test.tsx +73 -0
  101. package/src/components/Rating/Rating.tsx +25 -37
  102. package/src/components/Spinner/Spinner.tsx +1 -1
  103. package/src/components/Steps/Steps.stories.tsx +1 -1
  104. package/src/components/Steps/Steps.tsx +125 -22
  105. package/src/components/Steps/StepsCompound.test.tsx +81 -0
  106. package/src/components/Tabs/Tabs.stories.tsx +1 -1
  107. package/src/components/Tabs/Tabs.tsx +198 -45
  108. package/src/components/Tabs/TabsCompound.test.tsx +64 -0
  109. package/src/components/Todo/Todo.tsx +0 -1
  110. package/src/components/Toggle/Toggle.stories.tsx +1 -1
  111. package/src/components/Toggle/Toggle.tsx +1 -1
  112. package/src/components/Tooltip/Tooltip.stories.tsx +1 -1
  113. package/src/components/VideoPlayer/VideoPlayer.stories.tsx +2 -2
  114. package/src/lib/composables/__tests__/useAtomixGlassPerf.test.tsx +88 -0
  115. package/src/lib/composables/__tests__/useChart.test.ts +50 -0
  116. package/src/lib/composables/__tests__/useChart.test.tsx +139 -0
  117. package/src/lib/composables/__tests__/useHeroBackgroundSlider.test.tsx +59 -0
  118. package/src/lib/composables/__tests__/useSliderAutoplay.test.tsx +68 -0
  119. package/src/lib/composables/atomix-glass/useGlassBackgroundDetection.ts +329 -0
  120. package/src/lib/composables/atomix-glass/useGlassCornerRadius.ts +82 -0
  121. package/src/lib/composables/atomix-glass/useGlassMouseTracking.ts +153 -0
  122. package/src/lib/composables/atomix-glass/useGlassOverLight.ts +198 -0
  123. package/src/lib/composables/atomix-glass/useGlassSize.ts +117 -0
  124. package/src/lib/composables/atomix-glass/useGlassState.ts +112 -0
  125. package/src/lib/composables/atomix-glass/useGlassTransforms.ts +160 -0
  126. package/src/lib/composables/glass-styles.ts +302 -0
  127. package/src/lib/composables/index.ts +0 -8
  128. package/src/lib/composables/useAtomixGlass.ts +331 -537
  129. package/src/lib/composables/useAtomixGlassStyles.ts +307 -0
  130. package/src/lib/composables/useBarChart.ts +1 -1
  131. package/src/lib/composables/useBreadcrumb.ts +6 -6
  132. package/src/lib/composables/useChart.ts +104 -21
  133. package/src/lib/composables/useHeroBackgroundSlider.ts +16 -7
  134. package/src/lib/composables/useSlider.ts +66 -34
  135. package/src/lib/theme/devtools/CLI.ts +2 -10
  136. package/src/lib/theme/utils/__tests__/themeUtils.test.ts +213 -0
  137. package/src/lib/types/components.ts +21 -23
  138. package/src/lib/utils/__tests__/componentUtils.test.ts +57 -2
  139. package/src/lib/utils/__tests__/dom.test.ts +100 -0
  140. package/src/lib/utils/__tests__/fontPreloader.test.ts +102 -0
  141. package/src/lib/utils/__tests__/themeNaming.test.ts +117 -0
  142. package/src/lib/utils/themeNaming.ts +1 -1
  143. package/src/styles/06-components/_components.accordion.scss +0 -2
  144. package/src/styles/06-components/_components.chart.scss +0 -1
  145. package/src/styles/06-components/_components.dropdown.scss +0 -1
  146. package/src/styles/06-components/_components.edge-panel.scss +0 -2
  147. package/src/styles/06-components/_components.photoviewer.scss +0 -1
  148. package/src/styles/06-components/_components.river.scss +0 -1
  149. package/src/styles/06-components/_components.slider.scss +0 -3
  150. package/src/styles/99-utilities/_utilities.glass-fixes.scss +0 -1
package/dist/heavy.js CHANGED
@@ -236,7 +236,7 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
236
236
  HIGH_CONTRAST: 200
237
237
  }
238
238
  }
239
- }, {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS, calculateDistance = (pos1, pos2) => {
239
+ }, {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateDistance = (pos1, pos2) => {
240
240
  if (!pos1 || !pos2 || "number" != typeof pos1.x || "number" != typeof pos1.y || "number" != typeof pos2.x || "number" != typeof pos2.y) return 0;
241
241
  const deltaX = pos1.x - pos2.x, deltaY = pos1.y - pos2.y;
242
242
  return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
@@ -249,36 +249,36 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
249
249
  }, calculateMouseInfluence = mouseOffset => {
250
250
  if (!mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y) return 0;
251
251
  // Bounded calculation — keeps the glass effect subtle and stable
252
- const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$1.MOUSE_INFLUENCE_DIVISOR;
252
+ const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$2.MOUSE_INFLUENCE_DIVISOR;
253
253
  return Math.min(.8, influence);
254
254
  // Tighter cap to prevent blur/filter blow-out
255
- }, 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 => {
255
+ }, 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 => {
256
256
  if ("number" == typeof value) return Math.max(0, value);
257
- if ("string" != typeof value || !value.trim()) return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
257
+ if ("string" != typeof value || !value.trim()) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
258
258
  const trimmedValue = value.trim();
259
259
  // Handle px values
260
260
  if (trimmedValue.endsWith("px")) {
261
261
  const parsed = parseFloat(trimmedValue);
262
- return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
262
+ return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
263
263
  }
264
264
  // Handle rem values (assume 16px = 1rem)
265
265
  if (trimmedValue.endsWith("rem")) {
266
266
  const parsed = parseFloat(trimmedValue);
267
- return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
267
+ return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
268
268
  }
269
269
  // Handle em values (assume 16px = 1em for simplicity)
270
270
  if (trimmedValue.endsWith("em")) {
271
271
  const parsed = parseFloat(trimmedValue);
272
- return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
272
+ return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
273
273
  }
274
274
  // Handle percentage (convert to approximate px value, assuming 200px container)
275
275
  if (trimmedValue.endsWith("%")) {
276
276
  const parsed = parseFloat(trimmedValue);
277
- return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
277
+ return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
278
278
  }
279
279
  // Handle unitless numbers
280
280
  const numValue = parseFloat(trimmedValue);
281
- return isNaN(numValue) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
281
+ return isNaN(numValue) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
282
282
  }, extractBorderRadiusFromElement = element => {
283
283
  if (!element || !element.props) return null;
284
284
  // Check inline styles first (highest priority)
@@ -294,11 +294,11 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
294
294
  // If element has children, recursively check them
295
295
  if (element.props.children) {
296
296
  const childRadius = extractBorderRadiusFromChildren(element.props.children);
297
- if (childRadius > 0 && childRadius !== CONSTANTS$1.DEFAULT_CORNER_RADIUS) return childRadius;
297
+ if (childRadius > 0 && childRadius !== CONSTANTS$2.DEFAULT_CORNER_RADIUS) return childRadius;
298
298
  }
299
299
  return null;
300
300
  }, extractBorderRadiusFromChildren = children => {
301
- if (!children) return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
301
+ if (!children) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
302
302
  try {
303
303
  const childArray = React.Children.toArray(children);
304
304
  for (let i = 0; i < childArray.length; i++) {
@@ -311,7 +311,7 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
311
311
  } catch (error) {
312
312
  // Silently handle errors
313
313
  }
314
- return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
314
+ return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
315
315
  }, getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
316
316
  switch (mode) {
317
317
  case "standard":
@@ -480,10 +480,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
480
480
  }, globalMousePosition: globalMousePosition = {
481
481
  x: 0,
482
482
  y: 0
483
- }, 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 = {
483
+ }, 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 = {
484
484
  width: 0,
485
485
  height: 0
486
- }, onClick: onClick, mode: mode = "standard", effectiveDisableEffects: effectiveDisableEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", enableLiquidBlur: enableLiquidBlur = !1, elasticity: elasticity = 0, contentRef: contentRef}, ref) => {
486
+ }, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, elasticity: elasticity = 0, contentRef: contentRef}, ref) => {
487
487
  // Generate a stable, deterministic ID for SSR compatibility
488
488
  // Use a module-level counter that's consistent across server and client
489
489
  const filterId = useMemo((() => "atomix-glass-filter-" + ++idCounter), []), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null);
@@ -593,7 +593,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
593
593
  flowBlur: 1.2 * blurAmount
594
594
  };
595
595
  // Enhanced validation for liquid blur
596
- if (!enableLiquidBlur || !rectCache || !mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y || isNaN(mouseOffset.x) || isNaN(mouseOffset.y)) return defaultBlur;
596
+ if (!withLiquidBlur || !rectCache || !mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y || isNaN(mouseOffset.x) || isNaN(mouseOffset.y)) return defaultBlur;
597
597
  try {
598
598
  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);
599
599
  // NOTE: hover/active multipliers intentionally omitted here —
@@ -608,14 +608,14 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
608
608
  return console.warn("AtomixGlassContainer: Error calculating liquid blur", error),
609
609
  defaultBlur;
610
610
  }
611
- }), [ enableLiquidBlur, blurAmount, mouseOffset, rectCache ]), backdropStyle = useMemo((() => {
611
+ }), [ withLiquidBlur, blurAmount, mouseOffset, rectCache ]), backdropStyle = useMemo((() => {
612
612
  try {
613
613
  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;
614
614
  // Validate blur values before using them
615
- return !enableLiquidBlur || effectiveReducedMotion || effectiveDisableEffects || area > 18e4 ? {
615
+ return !withLiquidBlur || effectiveReducedMotion || effectiveWithoutEffects || area > 18e4 ? {
616
616
  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})`
617
617
  } : {
618
- 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})`
618
+ 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})`
619
619
  };
620
620
  // Single-pass fallback: stronger radius to match perceived blur of multi-pass
621
621
  } catch (error) {
@@ -624,7 +624,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
624
624
  backdropFilter: `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`
625
625
  };
626
626
  }
627
- }), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveDisableEffects, enableLiquidBlur ]), containerVars = useMemo((() => {
627
+ }), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveWithoutEffects, withLiquidBlur ]), containerVars = useMemo((() => {
628
628
  try {
629
629
  // Safe extraction of mouse offset values
630
630
  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;
@@ -632,10 +632,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
632
632
  "--atomix-glass-container-width": `${glassSize?.width}`,
633
633
  "--atomix-glass-container-height": `${glassSize?.height}`,
634
634
  "--atomix-glass-container-padding": padding || "0 0",
635
- "--atomix-glass-container-radius": `${"number" != typeof cornerRadius || isNaN(cornerRadius) ? 0 : cornerRadius}px`,
635
+ "--atomix-glass-container-radius": `${"number" != typeof borderRadius || isNaN(borderRadius) ? 0 : borderRadius}px`,
636
636
  "--atomix-glass-container-backdrop": backdropStyle?.backdropFilter || "none",
637
637
  "--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",
638
- "--atomix-glass-container-shadow-opacity": effectiveDisableEffects ? 0 : 1,
638
+ "--atomix-glass-container-shadow-opacity": effectiveWithoutEffects ? 0 : 1,
639
639
  // Background and shadow values use design token-aligned RGB values
640
640
  "--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",
641
641
  "--atomix-glass-container-text-shadow": overLight ? "0px 2px 12px rgba(0, 0, 0, 0)" : "0px 2px 12px rgba(0, 0, 0, 0.4)",
@@ -653,14 +653,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
653
653
  "--atomix-glass-container-text-shadow": "none"
654
654
  };
655
655
  }
656
- }), [ glassSize, padding, cornerRadius, backdropStyle, mouseOffset, overLight, effectiveDisableEffects ]), setForceNoTransition = el => {
657
- el && (el.style.setProperty("transition-duration", "0s", "important"), el.style.setProperty("animation-duration", "0s", "important"),
658
- el.style.setProperty("transition-delay", "0s", "important"));
659
- };
656
+ }), [ glassSize, padding, borderRadius, backdropStyle, mouseOffset, overLight, effectiveWithoutEffects ]);
660
657
  return jsx("div", {
661
658
  ref: el => {
662
659
  // Apply force no-transition
663
- setForceNoTransition(el),
664
660
  // Handle forwarded ref
665
661
  "function" == typeof ref ? ref(el) : ref && (ref.current = el);
666
662
  },
@@ -695,7 +691,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
695
691
  aberrationIntensity: "number" != typeof aberrationIntensity || isNaN(aberrationIntensity) ? 0 : aberrationIntensity,
696
692
  shaderMapUrl: shaderMapUrl
697
693
  }), jsx("div", {
698
- ref: setForceNoTransition,
694
+ ref: el => {
695
+ el && (el.style.setProperty("transition-duration", "0s", "important"), el.style.setProperty("animation-duration", "0s", "important"),
696
+ el.style.setProperty("transition-delay", "0s", "important"));
697
+ },
699
698
  className: ATOMIX_GLASS.FILTER_OVERLAY_CLASS,
700
699
  style: {
701
700
  filter: `url(#${filterId})`,
@@ -812,7 +811,128 @@ class {
812
811
  */ getSubscriberCount() {
813
812
  return this.listeners.size;
814
813
  }
815
- }, {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
814
+ }, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
815
+ if (!wrapperElement && !containerElement) return;
816
+ 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 = {
817
+ opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
818
+ contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
819
+ brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
820
+ shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
821
+ borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence)),
822
+ saturationBoost: baseOverLightConfig.saturationBoost
823
+ };
824
+ // Calculate mouse influence
825
+ // Calculate elastic translation
826
+ let elasticTranslation = {
827
+ x: 0,
828
+ y: 0
829
+ };
830
+ if (!effectiveWithoutEffects && wrapperElement) {
831
+ const rect = wrapperElement.getBoundingClientRect(), center = calculateElementCenter(rect);
832
+ // Calculate fade in factor
833
+ let fadeInFactor = 0;
834
+ if (globalMousePosition.x && globalMousePosition.y && validateGlassSize(glassSize)) {
835
+ 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({
836
+ x: edgeDistanceX,
837
+ y: edgeDistanceY
838
+ }, {
839
+ x: 0,
840
+ y: 0
841
+ });
842
+ fadeInFactor = edgeDistance > ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE ? 0 : 1 - edgeDistance / ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE;
843
+ }
844
+ elasticTranslation = {
845
+ x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
846
+ y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
847
+ };
848
+ }
849
+ 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}`;
850
+ // Update Wrapper Styles (glassVars)
851
+ if (wrapperElement) {
852
+ 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 = {
853
+ hover1: {
854
+ x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1,
855
+ y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1
856
+ },
857
+ hover2: {
858
+ x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_2,
859
+ y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_2
860
+ },
861
+ hover3: {
862
+ x: GRADIENT.CENTER_POSITION + mx * GRADIENT.HOVER_POSITION.MULTIPLIER_3,
863
+ y: GRADIENT.CENTER_POSITION + my * GRADIENT.HOVER_POSITION.MULTIPLIER_3
864
+ }
865
+ }, basePosition = {
866
+ x: GRADIENT.CENTER_POSITION + mx * GRADIENT.BASE_LAYER_MULTIPLIER,
867
+ y: GRADIENT.CENTER_POSITION + my * GRADIENT.BASE_LAYER_MULTIPLIER
868
+ }, opacityValues = {
869
+ hover1: isHovered || isActive ? .5 : 0,
870
+ hover2: isActive ? .5 : 0,
871
+ hover3: isHovered ? .4 : isActive ? .8 : 0,
872
+ base: isOverLight ? overLightConfig.opacity : 0,
873
+ over: isOverLight ? 1.1 * overLightConfig.opacity : 0
874
+ }, style = wrapperElement.style;
875
+ style.setProperty("--atomix-glass-transform", transformStyle || "none"),
876
+ // Gradients
877
+ 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%)`),
878
+ 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%)`),
879
+ // Hover gradients
880
+ 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}%)`),
881
+ 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}%)`),
882
+ 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}%)`),
883
+ 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})`),
884
+ 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})`),
885
+ // Opacities
886
+ style.setProperty("--atomix-glass-hover-1-opacity", opacityValues.hover1.toString()),
887
+ style.setProperty("--atomix-glass-hover-2-opacity", opacityValues.hover2.toString()),
888
+ style.setProperty("--atomix-glass-hover-3-opacity", opacityValues.hover3.toString()),
889
+ style.setProperty("--atomix-glass-base-opacity", opacityValues.base.toString()),
890
+ style.setProperty("--atomix-glass-overlay-opacity", opacityValues.over.toString()),
891
+ style.setProperty("--atomix-glass-overlay-highlight-opacity", (opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER).toString()),
892
+ // Other
893
+ style.setProperty("--atomix-glass-blend-mode", isOverLight ? "multiply" : "overlay"),
894
+ style.setProperty("--atomix-glass-radius", `${effectiveBorderRadius}px`);
895
+ }
896
+ // Update Container Styles (containerVars)
897
+ if (containerElement) {
898
+ 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();
899
+ let liquidBlur = {
900
+ baseBlur: blurAmount,
901
+ edgeBlur: blurAmount * EDGE_BLUR_MULTIPLIER,
902
+ centerBlur: blurAmount * CENTER_BLUR_MULTIPLIER,
903
+ flowBlur: blurAmount * FLOW_BLUR_MULTIPLIER
904
+ };
905
+ if (withLiquidBlur && rect) {
906
+ 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);
907
+ liquidBlur = {
908
+ baseBlur: clampBlur(baseBlur),
909
+ edgeBlur: clampBlur(edgeBlur),
910
+ centerBlur: clampBlur(centerBlur),
911
+ flowBlur: clampBlur(flowBlur)
912
+ };
913
+ }
914
+ // Backdrop filter
915
+ let backdropFilterString = `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`;
916
+ const dynamicSaturation = saturation + 20 * (liquidBlur.baseBlur || 0), area = rect ? rect.width * rect.height : 0;
917
+ 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})`;
918
+ // Container variables
919
+ const style = containerElement.style;
920
+ style.setProperty("--atomix-glass-container-width", `${glassSize.width}`), style.setProperty("--atomix-glass-container-height", `${glassSize.height}`),
921
+ style.setProperty("--atomix-glass-container-padding", padding), style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
922
+ style.setProperty("--atomix-glass-container-backdrop", backdropFilterString),
923
+ // Shadows
924
+ 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"),
925
+ style.setProperty("--atomix-glass-container-shadow-opacity", effectiveWithoutEffects ? "0" : "1"),
926
+ 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"),
927
+ 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)"),
928
+ 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)");
929
+ }
930
+ }, {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS;
931
+
932
+ /**
933
+ * Updates the styles of the AtomixGlass wrapper and container elements imperatively
934
+ * to avoid React re-renders on mouse movement.
935
+ */ const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
816
936
  parentElement && backgroundDetectionCache.set(parentElement, {
817
937
  result: result,
818
938
  timestamp: Date.now(),
@@ -825,18 +945,74 @@ class {
825
945
  * Composable hook for AtomixGlass component logic
826
946
  * Manages all state, calculations, and event handlers
827
947
  */
828
- 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, enablePerformanceMonitoring: enablePerformanceMonitoring = !1, children: children}) {
948
+ 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}) {
829
949
  // State
830
- const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), [glassSize, setGlassSize] = useState({
831
- width: 270,
832
- height: 69
833
- }), [internalGlobalMousePosition, setInternalGlobalMousePosition] = useState({
950
+ const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), cachedRectRef = useRef(null), internalGlobalMousePositionRef = useRef({
834
951
  x: 0,
835
952
  y: 0
836
- }), [internalMouseOffset, setInternalMouseOffset] = useState({
953
+ }), internalMouseOffsetRef = useRef({
837
954
  x: 0,
838
955
  y: 0
839
- }), [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 ]);
956
+ }), [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}) {
957
+ const [glassSize, setGlassSize] = useState({
958
+ width: 270,
959
+ height: 69
960
+ });
961
+ return useEffect((() => {
962
+ const isValidElement = element => null !== element && element instanceof HTMLElement && element.isConnected;
963
+ let rafId = null, lastSize = {
964
+ width: 0,
965
+ height: 0
966
+ }, lastCornerRadius = effectiveBorderRadius;
967
+ const updateGlassSize = (forceUpdate = !1) => {
968
+ null !== rafId && cancelAnimationFrame(rafId), rafId = requestAnimationFrame((() => {
969
+ if (!isValidElement(glassRef.current)) return void (rafId = null);
970
+ const rect = glassRef.current.getBoundingClientRect();
971
+ if (rect.width <= 0 || rect.height <= 0) return void (rafId = null);
972
+ // Measure actual rendered size without artificial offsets to avoid feedback loops
973
+ const newSize = {
974
+ width: Math.round(rect.width),
975
+ height: Math.round(rect.height)
976
+ }, cornerRadiusChanged = lastCornerRadius !== effectiveBorderRadius, dimensionsChanged = Math.abs(newSize.width - lastSize.width) > 1 || Math.abs(newSize.height - lastSize.height) > 1;
977
+ var size;
978
+ (forceUpdate || cornerRadiusChanged || dimensionsChanged) && validateGlassSize(size = newSize) && size.width <= CONSTANTS$1.MAX_SIZE && size.height <= CONSTANTS$1.MAX_SIZE && (lastSize = newSize,
979
+ lastCornerRadius = effectiveBorderRadius, setGlassSize(newSize)), rafId = null;
980
+ }));
981
+ };
982
+ let resizeTimeoutId = null;
983
+ const debouncedResizeHandler = () => {
984
+ resizeTimeoutId && clearTimeout(resizeTimeoutId), resizeTimeoutId = setTimeout((() => updateGlassSize(!1)), 16);
985
+ }, initialTimeoutId = setTimeout((() => updateGlassSize(!0)), 0);
986
+ let resizeObserver = null, resizeDebounceTimeout = null;
987
+ // ResizeObserver has 98%+ browser support, no need for fallback
988
+ if ("undefined" != typeof ResizeObserver && isValidElement(glassRef.current)) try {
989
+ resizeObserver = new ResizeObserver((entries => {
990
+ for (const entry of entries) if (entry.target === glassRef.current) {
991
+ // Update cached rect when size changes
992
+ glassRef.current && cachedRectRef && (cachedRectRef.current = glassRef.current.getBoundingClientRect()),
993
+ // Debounce resize updates to match RAF timing (16ms)
994
+ resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), resizeDebounceTimeout = setTimeout((() => updateGlassSize(!1)), 16);
995
+ break;
996
+ }
997
+ })), resizeObserver.observe(glassRef.current);
998
+ } catch (error) {
999
+ console.warn("AtomixGlass: ResizeObserver not available, using window resize only", error);
1000
+ }
1001
+ return window.addEventListener("resize", debouncedResizeHandler, {
1002
+ passive: !0
1003
+ }), () => {
1004
+ clearTimeout(initialTimeoutId), null !== rafId && cancelAnimationFrame(rafId), resizeTimeoutId && clearTimeout(resizeTimeoutId),
1005
+ resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), window.removeEventListener("resize", debouncedResizeHandler),
1006
+ resizeObserver?.disconnect();
1007
+ };
1008
+ }), [ effectiveBorderRadius, glassRef, cachedRectRef ]), {
1009
+ glassSize: glassSize
1010
+ };
1011
+ }({
1012
+ glassRef: glassRef,
1013
+ effectiveBorderRadius: effectiveBorderRadius,
1014
+ cachedRectRef: cachedRectRef
1015
+ }), 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;
840
1016
  // Extract border-radius from children
841
1017
  useEffect((() => {
842
1018
  const extractRadius = () => {
@@ -867,13 +1043,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
867
1043
  }
868
1044
  null !== extractedRadius && extractedRadius > 0 && setDynamicCornerRadius(extractedRadius);
869
1045
  } catch (error) {
870
- "undefined" != typeof process && "production" === process.env?.NODE_ENV || !debugCornerRadius || console.error("[AtomixGlass] Error extracting corner radius:", error);
1046
+ "undefined" != typeof process && "production" === process.env?.NODE_ENV || !debugBorderRadius || console.error("[AtomixGlass] Error extracting corner radius:", error);
871
1047
  }
872
1048
  };
873
1049
  extractRadius();
874
1050
  const timeoutId = setTimeout(extractRadius, 100);
875
1051
  return () => clearTimeout(timeoutId);
876
- }), [ children, debugCornerRadius, contentRef ]),
1052
+ }), [ children, debugBorderRadius, contentRef ]),
877
1053
  // Media query handlers and background detection
878
1054
  useEffect((() => {
879
1055
  if (("auto" === overLight || "object" == typeof overLight && null !== overLight) && glassRef.current) {
@@ -929,72 +1105,52 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
929
1105
  const rgb = bgColor.match(/\d+/g);
930
1106
  if (rgb && rgb.length >= 3) {
931
1107
  const r = Number(rgb[0]), g = Number(rgb[1]), b = Number(rgb[2]);
932
- // Validate RGB values are valid numbers
933
- 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)) {
1108
+ if (!isNaN(r) && !isNaN(g) && !isNaN(b) && (r > 10 || g > 10 || b > 10)) {
934
1109
  const luminance = (.299 * r + .587 * g + .114 * b) / 255;
935
1110
  !isNaN(luminance) && isFinite(luminance) && (totalLuminance += luminance, validSamples++,
936
1111
  hasValidBackground = !0);
937
1112
  }
938
1113
  }
939
1114
  }
940
- // Check for image backgrounds
941
- bgImage && "none" !== bgImage && "initial" !== bgImage && (
942
- // For image backgrounds, assume medium luminance
943
- totalLuminance += .5, validSamples++, hasValidBackground = !0);
1115
+ bgImage && "none" !== bgImage && "initial" !== bgImage && (totalLuminance += .5,
1116
+ validSamples++, hasValidBackground = !0);
944
1117
  } catch (styleError) {
945
- "undefined" == typeof process || process.env;
1118
+ // Silently continue
946
1119
  }
947
- // Move to parent element for next iteration
948
- if (!currentElement) break;
949
- // Exit loop if currentElement becomes null
950
- currentElement = currentElement.parentElement, depth++;
1120
+ if (!currentElement) break;
1121
+ currentElement = currentElement.parentElement, depth++;
951
1122
  }
952
- // More conservative detection with better error handling
953
- if (hasValidBackground && validSamples > 0) {
1123
+ if (hasValidBackground && validSamples > 0) {
954
1124
  const avgLuminance = totalLuminance / validSamples;
955
1125
  if (!isNaN(avgLuminance) && isFinite(avgLuminance)) {
956
1126
  let threshold = .7;
957
- // Conservative threshold for overlight
958
- // If overLight is an object, use its threshold property with validation
959
- if ("object" == typeof overLight && null !== overLight) {
1127
+ if ("object" == typeof overLight && null !== overLight) {
960
1128
  const objConfig = overLight;
961
1129
  if (void 0 !== objConfig.threshold) {
962
- const configThreshold = "number" == typeof objConfig.threshold && !isNaN(objConfig.threshold) && isFinite(objConfig.threshold) ? objConfig.threshold : .7;
1130
+ const configThreshold = "number" != typeof objConfig.threshold || isNaN(objConfig.threshold) ? .7 : objConfig.threshold;
963
1131
  threshold = Math.min(.9, Math.max(.1, configThreshold));
964
1132
  }
965
1133
  }
966
1134
  const isOverLightDetected = avgLuminance > threshold;
967
- // Cache the result in shared cache
968
- setCachedBackgroundDetection(element.parentElement, overLight, isOverLightDetected, threshold),
1135
+ setCachedBackgroundDetection(element.parentElement, overLight, isOverLightDetected, threshold),
969
1136
  setDetectedOverLight(isOverLightDetected);
970
1137
  } else {
971
- // Invalid luminance calculation, default to false
972
1138
  const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
973
1139
  setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
974
1140
  setDetectedOverLight(result);
975
1141
  }
976
1142
  } else {
977
- // Default to false if no valid background found
978
1143
  const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
979
1144
  setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
980
1145
  setDetectedOverLight(result);
981
1146
  }
982
1147
  } catch (error) {
983
- // Enhanced error logging with context
984
- "undefined" != typeof process && "development" !== process.env?.NODE_ENV || console.warn("AtomixGlass: Error detecting background brightness:", error);
985
- const result = !1;
986
- if (element && element.parentElement) {
987
- const threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
988
- setCachedBackgroundDetection(element.parentElement, overLight, result, threshold);
989
- }
990
- setDetectedOverLight(result);
1148
+ setDetectedOverLight(!1);
991
1149
  }
992
1150
  }), 150);
993
1151
  return () => clearTimeout(timeoutId);
994
1152
  }
995
- if ("boolean" == typeof overLight &&
996
- // For boolean values, disable auto-detection
997
- setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
1153
+ if ("boolean" == typeof overLight && setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
998
1154
  const mediaQueryReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)"), mediaQueryHighContrast = window.matchMedia("(prefers-contrast: high)");
999
1155
  setUserPrefersReducedMotion(mediaQueryReducedMotion.matches), setUserPrefersHighContrast(mediaQueryHighContrast.matches);
1000
1156
  const handleReducedMotionChange = e => {
@@ -1005,65 +1161,54 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1005
1161
  return mediaQueryReducedMotion.addEventListener ? (mediaQueryReducedMotion.addEventListener("change", handleReducedMotionChange),
1006
1162
  mediaQueryHighContrast.addEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.addListener && (mediaQueryReducedMotion.addListener(handleReducedMotionChange),
1007
1163
  mediaQueryHighContrast.addListener(handleHighContrastChange)), () => {
1008
- try {
1009
- mediaQueryReducedMotion.removeEventListener ? (mediaQueryReducedMotion.removeEventListener("change", handleReducedMotionChange),
1010
- mediaQueryHighContrast.removeEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.removeListener && (mediaQueryReducedMotion.removeListener(handleReducedMotionChange),
1011
- mediaQueryHighContrast.removeListener(handleHighContrastChange));
1012
- } catch (cleanupError) {
1013
- console.error("AtomixGlass: Error cleaning up media query listeners:", cleanupError);
1014
- }
1164
+ // ignore
1015
1165
  };
1016
1166
  } catch (error) {
1017
- return void console.error("AtomixGlass: Error setting up media queries:", error);
1167
+ return;
1018
1168
  }
1019
1169
  }), [ overLight, glassRef, debugOverLight ]);
1020
- // Mouse tracking using shared global tracker
1021
- // Cache bounding rect to avoid repeated getBoundingClientRect calls
1022
- const cachedRectRef = useRef(null), updateRectRef = useRef(null), handleGlobalMousePosition = useCallback((globalPos => {
1023
- if (externalGlobalMousePosition && externalMouseOffset)
1024
- // External mouse position provided, skip internal tracking
1025
- return;
1026
- if (effectiveDisableEffects) return;
1027
- const container = mouseContainer?.current || glassRef.current;
1028
- if (!container) return;
1029
- enablePerformanceMonitoring && performance.now();
1030
- // Use cached rect if available, otherwise get new one
1031
- let rect = cachedRectRef.current;
1032
- if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
1033
- cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
1034
- const center = calculateElementCenter(rect), newOffset = {
1035
- x: (globalPos.x - center.x) / rect.width * 100,
1036
- y: (globalPos.y - center.y) / rect.height * 100
1170
+ /**
1171
+ * Get effective overLight value based on configuration
1172
+ */
1173
+ 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((() => {
1174
+ const isOverLight = getEffectiveOverLight(), baseConfig = {
1175
+ isOverLight: isOverLight,
1176
+ threshold: .7,
1177
+ opacity: isOverLight ? Math.min(.6, Math.max(.2, .5)) : 0,
1178
+ contrast: 1,
1179
+ // Base contrast
1180
+ brightness: 1,
1181
+ // Base brightness
1182
+ saturationBoost: 1.3,
1183
+ shadowIntensity: .9,
1184
+ borderOpacity: .7
1037
1185
  };
1038
- // Calculate offset relative to this container
1039
- // React 18 automatically batches these updates
1040
- setInternalMouseOffset(newOffset), setInternalGlobalMousePosition(globalPos), "undefined" != typeof process && "production" === process.env?.NODE_ENV || !enablePerformanceMonitoring || performance.now();
1041
- }), [ mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveDisableEffects, enablePerformanceMonitoring ]);
1042
- // Subscribe to shared mouse tracker
1043
- useEffect((() => {
1044
- if (externalGlobalMousePosition && externalMouseOffset)
1045
- // External mouse position provided, don't subscribe
1046
- return;
1047
- if (effectiveDisableEffects)
1048
- // Effects disabled, don't subscribe
1049
- return;
1050
- // Subscribe to shared tracker
1051
- const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition), container = mouseContainer?.current || glassRef.current;
1052
- // Update cached rect when container size changes
1053
- let resizeObserver = null;
1054
- return container && "undefined" != typeof ResizeObserver && (resizeObserver = new ResizeObserver((() => {
1055
- null !== updateRectRef.current && cancelAnimationFrame(updateRectRef.current), updateRectRef.current = requestAnimationFrame((() => {
1056
- const container = mouseContainer?.current || glassRef.current;
1057
- container && (cachedRectRef.current = container.getBoundingClientRect()), updateRectRef.current = null;
1058
- }));
1059
- })), resizeObserver.observe(container)), () => {
1060
- unsubscribe(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
1061
- updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
1186
+ if ("object" == typeof overLight && null !== overLight) {
1187
+ 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);
1188
+ return {
1189
+ ...baseConfig,
1190
+ threshold: validatedThreshold,
1191
+ opacity: validatedOpacity,
1192
+ contrast: validatedContrast,
1193
+ brightness: validatedBrightness,
1194
+ saturationBoost: validatedSaturationBoost
1195
+ };
1196
+ }
1197
+ return baseConfig;
1198
+ }), [ overLight, getEffectiveOverLight, validateConfigValue ]), overLightConfig = useMemo((() => {
1199
+ const mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1;
1200
+ return {
1201
+ isOverLight: baseOverLightConfig.isOverLight,
1202
+ threshold: baseOverLightConfig.threshold,
1203
+ opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
1204
+ contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
1205
+ brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
1206
+ saturationBoost: baseOverLightConfig.saturationBoost,
1207
+ shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
1208
+ borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence))
1062
1209
  };
1063
- }), [ handleGlobalMousePosition, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveDisableEffects ]);
1064
- // Transform calculations
1065
- const calculateDirectionalScale = useCallback((() => {
1066
- if (!0 === overLight || "auto" === overLight && detectedOverLight || "object" == typeof overLight && null !== overLight && detectedOverLight) return "scale(1)";
1210
+ }), [ baseOverLightConfig, mouseOffset, isHovered, isActive ]), updateRectRef = useRef(null), calculateDirectionalScale = useCallback((() => {
1211
+ if (baseOverLightConfig.isOverLight) return "scale(1)";
1067
1212
  if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return "scale(1)";
1068
1213
  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({
1069
1214
  x: edgeDistanceX,
@@ -1077,7 +1222,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1077
1222
  if (0 === centerDistance) return "scale(1)";
1078
1223
  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;
1079
1224
  return `scaleX(${Math.max(.8, scaleX)}) scaleY(${Math.max(.8, scaleY)})`;
1080
- }), [ globalMousePosition, elasticity, glassSize, glassRef, overLight, detectedOverLight ]), calculateFadeInFactor = useCallback((() => {
1225
+ }), [ globalMousePosition, elasticity, glassSize, glassRef, baseOverLightConfig ]), calculateFadeInFactor = useCallback((() => {
1081
1226
  if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return 0;
1082
1227
  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({
1083
1228
  x: edgeDistanceX,
@@ -1097,122 +1242,110 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1097
1242
  x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
1098
1243
  y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
1099
1244
  };
1100
- }), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = useMemo((() => effectiveDisableEffects ? {
1245
+ }), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = useMemo((() => effectiveWithoutEffects ? {
1101
1246
  x: 0,
1102
1247
  y: 0
1103
- } : 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 ]);
1104
- // Size management
1105
- useEffect((() => {
1106
- const isValidElement = element => null !== element && element instanceof HTMLElement && element.isConnected;
1107
- let rafId = null, lastSize = {
1108
- width: 0,
1109
- height: 0
1110
- }, lastCornerRadius = effectiveCornerRadius;
1111
- const updateGlassSize = (forceUpdate = !1) => {
1112
- null !== rafId && cancelAnimationFrame(rafId), rafId = requestAnimationFrame((() => {
1113
- if (!isValidElement(glassRef.current)) return void (rafId = null);
1114
- const rect = glassRef.current.getBoundingClientRect();
1115
- if (rect.width <= 0 || rect.height <= 0) return void (rafId = null);
1116
- // Measure actual rendered size without artificial offsets to avoid feedback loops
1117
- const newSize = {
1118
- width: Math.round(rect.width),
1119
- height: Math.round(rect.height)
1120
- }, cornerRadiusChanged = lastCornerRadius !== effectiveCornerRadius, dimensionsChanged = Math.abs(newSize.width - lastSize.width) > 1 || Math.abs(newSize.height - lastSize.height) > 1;
1121
- var size;
1122
- (forceUpdate || cornerRadiusChanged || dimensionsChanged) && validateGlassSize(size = newSize) && size.width <= CONSTANTS.MAX_SIZE && size.height <= CONSTANTS.MAX_SIZE && (lastSize = newSize,
1123
- lastCornerRadius = effectiveCornerRadius, setGlassSize(newSize)), rafId = null;
1124
- }));
1125
- };
1126
- let resizeTimeoutId = null;
1127
- const debouncedResizeHandler = () => {
1128
- resizeTimeoutId && clearTimeout(resizeTimeoutId), resizeTimeoutId = setTimeout((() => updateGlassSize(!1)), 16);
1129
- }, initialTimeoutId = setTimeout((() => updateGlassSize(!0)), 0);
1130
- let resizeObserver = null, resizeDebounceTimeout = null;
1131
- // ResizeObserver has 98%+ browser support, no need for fallback
1132
- if ("undefined" != typeof ResizeObserver && isValidElement(glassRef.current)) try {
1133
- resizeObserver = new ResizeObserver((entries => {
1134
- for (const entry of entries) if (entry.target === glassRef.current) {
1135
- // Update cached rect when size changes
1136
- glassRef.current && (cachedRectRef.current = glassRef.current.getBoundingClientRect()),
1137
- // Debounce resize updates to match RAF timing (16ms)
1138
- resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), resizeDebounceTimeout = setTimeout((() => updateGlassSize(!1)), 16);
1139
- break;
1140
- }
1141
- })), resizeObserver.observe(glassRef.current);
1142
- } catch (error) {
1143
- console.warn("AtomixGlass: ResizeObserver not available, using window resize only", error);
1144
- }
1145
- return window.addEventListener("resize", debouncedResizeHandler, {
1146
- passive: !0
1147
- }), () => {
1148
- clearTimeout(initialTimeoutId), null !== rafId && cancelAnimationFrame(rafId), resizeTimeoutId && clearTimeout(resizeTimeoutId),
1149
- resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), window.removeEventListener("resize", debouncedResizeHandler),
1150
- resizeObserver?.disconnect();
1248
+ } : 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 => {
1249
+ if (externalGlobalMousePosition && externalMouseOffset) return;
1250
+ if (effectiveWithoutEffects) return;
1251
+ const container = mouseContainer?.current || glassRef.current;
1252
+ if (!container) return;
1253
+ // Use cached rect if available, otherwise get new one
1254
+ let rect = cachedRectRef.current;
1255
+ if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
1256
+ cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
1257
+ const center = calculateElementCenter(rect), newOffset = {
1258
+ x: (globalPos.x - center.x) / rect.width * 100,
1259
+ y: (globalPos.y - center.y) / rect.height * 100
1151
1260
  };
1152
- }), [ effectiveCornerRadius, glassRef ]);
1153
- // OverLight config
1261
+ // Calculate offset relative to this container
1262
+ // Store in refs instead of state
1263
+ internalMouseOffsetRef.current = newOffset, internalGlobalMousePositionRef.current = globalPos,
1264
+ // Imperative style update
1265
+ updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
1266
+ mouseOffset: newOffset,
1267
+ globalMousePosition: globalPos,
1268
+ glassSize: glassSize,
1269
+ isHovered: isHovered,
1270
+ isActive: isActive,
1271
+ isOverLight: baseOverLightConfig.isOverLight,
1272
+ baseOverLightConfig: baseOverLightConfig,
1273
+ effectiveBorderRadius: effectiveBorderRadius,
1274
+ effectiveWithoutEffects: effectiveWithoutEffects,
1275
+ effectiveReducedMotion: effectiveReducedMotion,
1276
+ elasticity: elasticity,
1277
+ directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
1278
+ // Simplified directional scale for fast path
1279
+ onClick: onClick,
1280
+ withLiquidBlur: withLiquidBlur,
1281
+ blurAmount: blurAmount,
1282
+ saturation: saturation,
1283
+ padding: padding
1284
+ });
1285
+ }), [ mouseContainer, glassRef, wrapperRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects, glassSize, isHovered, isActive, baseOverLightConfig, effectiveBorderRadius, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding ]);
1154
1286
  /**
1155
- * Get effective overLight value based on configuration
1156
- * - boolean: returns the boolean value directly
1157
- * - 'auto': returns detectedOverLight (auto-detected from background)
1158
- * - object: returns detectedOverLight (auto-detected, but config object provides customization)
1159
- */
1160
- 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((() => {
1161
- const isOverLight = getEffectiveOverLight(), mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1, baseConfig = {
1162
- isOverLight: isOverLight,
1163
- threshold: .7,
1164
- opacity: isOverLight ? Math.min(.6, Math.max(.2, .5 * hoverIntensity * activeIntensity)) : 0,
1165
- contrast: Math.min(1.6, Math.max(1, 1.4 + .1 * mouseInfluence)),
1166
- brightness: Math.min(1.1, Math.max(.8, .9 + .05 * mouseInfluence)),
1167
- saturationBoost: 1.3,
1168
- // Fixed value dynamic saturation amplifies perceived displacement
1169
- shadowIntensity: Math.min(1.2, Math.max(.5, .9 + .2 * mouseInfluence)),
1170
- borderOpacity: Math.min(1, Math.max(.3, .7 + .1 * mouseInfluence))
1287
+ * Validate and clamp a numeric config value
1288
+ */
1289
+ // Subscribe to shared mouse tracker
1290
+ useEffect((() => {
1291
+ if (externalGlobalMousePosition && externalMouseOffset) return;
1292
+ if (effectiveWithoutEffects) return;
1293
+ const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition), container = mouseContainer?.current || glassRef.current;
1294
+ let resizeObserver = null;
1295
+ return container && "undefined" != typeof ResizeObserver && (resizeObserver = new ResizeObserver((() => {
1296
+ null !== updateRectRef.current && cancelAnimationFrame(updateRectRef.current), updateRectRef.current = requestAnimationFrame((() => {
1297
+ const container = mouseContainer?.current || glassRef.current;
1298
+ container && (cachedRectRef.current = container.getBoundingClientRect()), updateRectRef.current = null;
1299
+ }));
1300
+ })), resizeObserver.observe(container)), () => {
1301
+ unsubscribe(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
1302
+ updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
1171
1303
  };
1172
- if ("object" == typeof overLight && null !== overLight) {
1173
- 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 = {
1174
- ...baseConfig,
1175
- threshold: validatedThreshold,
1176
- opacity: validatedOpacity * hoverIntensity * activeIntensity,
1177
- contrast: Math.min(1.6, validatedContrast + .1 * mouseInfluence),
1178
- brightness: Math.min(1.1, validatedBrightness + .05 * mouseInfluence),
1179
- saturationBoost: validatedSaturationBoost
1180
- };
1181
- // Validate and apply object config values with proper clamping
1182
- return "undefined" == typeof process || process.env, finalConfig;
1183
- }
1184
- // Debug logging for non-object configs
1185
- return "undefined" == typeof process || process.env, baseConfig;
1186
- }), [ 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 => {
1304
+ }), [ handleGlobalMousePosition, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects ]),
1305
+ // Also call updateStyles on other state changes (hover, active, etc)
1306
+ useEffect((() => {
1307
+ updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
1308
+ mouseOffset: externalMouseOffset || internalMouseOffsetRef.current,
1309
+ globalMousePosition: externalGlobalMousePosition || internalGlobalMousePositionRef.current,
1310
+ glassSize: glassSize,
1311
+ isHovered: isHovered,
1312
+ isActive: isActive,
1313
+ isOverLight: baseOverLightConfig.isOverLight,
1314
+ baseOverLightConfig: baseOverLightConfig,
1315
+ effectiveBorderRadius: effectiveBorderRadius,
1316
+ effectiveWithoutEffects: effectiveWithoutEffects,
1317
+ effectiveReducedMotion: effectiveReducedMotion,
1318
+ elasticity: elasticity,
1319
+ directionalScale: directionalScale,
1320
+ onClick: onClick,
1321
+ withLiquidBlur: withLiquidBlur,
1322
+ blurAmount: blurAmount,
1323
+ saturation: saturation,
1324
+ padding: padding
1325
+ });
1326
+ }), [ isHovered, isActive, glassSize, baseOverLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, directionalScale, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation, padding, onClick ]);
1327
+ // Event handlers
1328
+ const handleMouseEnter = useCallback((() => setIsHovered(!0)), []), handleMouseLeave = useCallback((() => setIsHovered(!1)), []), handleMouseDown = useCallback((() => setIsActive(!0)), []), handleMouseUp = useCallback((() => setIsActive(!1)), []), handleMouseMove = useCallback((_e => {}), []), handleKeyDown = useCallback((e => {
1187
1329
  !onClick || "Enter" !== e.key && " " !== e.key || (e.preventDefault(), onClick());
1188
- }), [ onClick ]), handleMouseMove = useCallback((_e => {}), []);
1189
- /**
1190
- * Validate and clamp a numeric config value
1191
- * @param value - The value to validate
1192
- * @param min - Minimum allowed value
1193
- * @param max - Maximum allowed value
1194
- * @param defaultValue - Default value if validation fails
1195
- * @returns Validated and clamped value
1196
- */ return {
1197
- // State
1330
+ }), [ onClick ]);
1331
+ return {
1198
1332
  isHovered: isHovered,
1199
1333
  isActive: isActive,
1200
1334
  glassSize: glassSize,
1201
- dynamicCornerRadius: dynamicCornerRadius,
1202
- effectiveCornerRadius: effectiveCornerRadius,
1335
+ dynamicBorderRadius: dynamicBorderRadius,
1336
+ effectiveBorderRadius: effectiveBorderRadius,
1203
1337
  effectiveReducedMotion: effectiveReducedMotion,
1204
1338
  effectiveHighContrast: effectiveHighContrast,
1205
- effectiveDisableEffects: effectiveDisableEffects,
1339
+ effectiveWithoutEffects: effectiveWithoutEffects,
1206
1340
  detectedOverLight: detectedOverLight,
1207
1341
  globalMousePosition: globalMousePosition,
1342
+ // This is now static (refs or props) unless prop changes
1208
1343
  mouseOffset: mouseOffset,
1209
- // OverLight config
1344
+ // This is now static (refs or props) unless prop changes
1210
1345
  overLightConfig: overLightConfig,
1211
- // Transform calculations
1212
1346
  elasticTranslation: elasticTranslation,
1213
1347
  directionalScale: directionalScale,
1214
1348
  transformStyle: transformStyle,
1215
- // Event handlers
1216
1349
  handleMouseEnter: handleMouseEnter,
1217
1350
  handleMouseLeave: handleMouseLeave,
1218
1351
  handleMouseDown: handleMouseDown,
@@ -1251,7 +1384,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1251
1384
  *
1252
1385
  * @example
1253
1386
  * // Manual border-radius override
1254
- * <AtomixGlass cornerRadius={20}>
1387
+ * <AtomixGlass borderRadius={20}>
1255
1388
  * <div>Content with 20px glass radius</div>
1256
1389
  * </AtomixGlass>
1257
1390
  *
@@ -1292,37 +1425,48 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1292
1425
  * <AtomixGlass overLight="auto" debugOverLight={true}>
1293
1426
  * <div>Content with debug logging enabled</div>
1294
1427
  * </AtomixGlass>
1295
- */ 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}) {
1296
- 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({
1428
+ */ 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}) {
1429
+ 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({
1297
1430
  glassRef: glassRef,
1298
1431
  contentRef: contentRef,
1299
- cornerRadius: cornerRadius,
1432
+ borderRadius: borderRadius,
1300
1433
  globalMousePosition: externalGlobalMousePosition,
1301
1434
  mouseOffset: externalMouseOffset,
1302
1435
  mouseContainer: mouseContainer,
1303
1436
  overLight: overLight,
1304
1437
  reducedMotion: reducedMotion,
1305
1438
  highContrast: highContrast,
1306
- disableEffects: disableEffects,
1439
+ withoutEffects: withoutEffects,
1307
1440
  elasticity: elasticity,
1308
1441
  onClick: onClick,
1309
- debugCornerRadius: debugCornerRadius,
1442
+ debugBorderRadius: debugBorderRadius,
1310
1443
  debugOverLight: debugOverLight,
1311
- enablePerformanceMonitoring: enablePerformanceMonitoring,
1312
- children: children
1313
- }), isOverLight = useMemo((() => overLightConfig?.isOverLight), [ overLight ]), shouldRenderOverLightLayers = enableOverLightLayers && isOverLight, baseStyle = {
1444
+ debugPerformance: debugPerformance,
1445
+ children: children,
1446
+ blurAmount: blurAmount,
1447
+ saturation: saturation,
1448
+ withLiquidBlur: withLiquidBlur,
1449
+ padding: padding,
1450
+ style: style
1451
+ }), isOverLight = useMemo((() => overLightConfig?.isOverLight), [ overLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, baseStyle = {
1314
1452
  ...style,
1315
- ...!effectiveDisableEffects && {
1453
+ ...!effectiveWithoutEffects && {
1316
1454
  transform: transformStyle
1317
1455
  }
1318
- }, 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((() => ({
1456
+ }, 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((() => ({
1319
1457
  position: style.position || "absolute",
1320
1458
  top: style.top || 0,
1321
1459
  left: style.left || 0
1322
- })), [ style.position, style.top, style.left ]), adjustedSize = useMemo((() => ({
1323
- width: "fixed" !== style.position ? "100%" : style.width ? style.width : Math.max(glassSize.width, 0),
1324
- height: "fixed" !== style.position ? "100%" : style.height ? style.height : Math.max(glassSize.height, 0)
1325
- })), [ style.position, style.width, style.height, glassSize.width, glassSize.height ]), gradientValues = useMemo((() => {
1460
+ })), [ style.position, style.top, style.left ]), adjustedSize = useMemo((() => {
1461
+ const resolveSize = (propValue, styleValue, measuredSize) => {
1462
+ const explicitSize = propValue ?? styleValue;
1463
+ return void 0 !== explicitSize ? "number" == typeof explicitSize ? `${explicitSize}px` : explicitSize : "fixed" === positionStyles.position ? `${Math.max(measuredSize, 0)}px` : "100%";
1464
+ };
1465
+ return {
1466
+ width: resolveSize(width, style.width, glassSize.width),
1467
+ height: resolveSize(height, style.height, glassSize.height)
1468
+ };
1469
+ }), [ width, height, style.width, style.height, positionStyles.position, glassSize.width, glassSize.height ]), gradientValues = useMemo((() => {
1326
1470
  const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT;
1327
1471
  return {
1328
1472
  borderGradientAngle: GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER,
@@ -1364,13 +1508,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1364
1508
  }), [ isHovered, isActive, isOverLight, overLightConfig.opacity ]), glassVars = useMemo((() => {
1365
1509
  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;
1366
1510
  return {
1367
- "--atomix-glass-radius": `${effectiveCornerRadius}px`,
1511
+ "--atomix-glass-radius": `${effectiveBorderRadius}px`,
1368
1512
  "--atomix-glass-transform": transformStyle || "none",
1369
1513
  "--atomix-glass-position": positionStyles.position,
1370
1514
  "--atomix-glass-top": "fixed" !== positionStyles.top ? `${positionStyles.top}px` : "0",
1371
1515
  "--atomix-glass-left": "fixed" !== positionStyles.left ? `${positionStyles.left}px` : "0",
1372
- "--atomix-glass-width": "fixed" !== style.position ? adjustedSize.width : `${adjustedSize.width}px`,
1373
- "--atomix-glass-height": "fixed" !== style.position ? adjustedSize.height : `${adjustedSize.height}px`,
1516
+ "--atomix-glass-width": adjustedSize.width,
1517
+ "--atomix-glass-height": adjustedSize.height,
1374
1518
  "--atomix-glass-border-width": "var(--atomix-spacing-0-5, 0.09375rem)",
1375
1519
  "--atomix-glass-blend-mode": isOverLight ? "multiply" : "overlay",
1376
1520
  "--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%)`,
@@ -1386,24 +1530,25 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1386
1530
  "--atomix-glass-overlay-opacity": opacityValues.over,
1387
1531
  "--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})`
1388
1532
  };
1389
- }), [ gradientValues, opacityValues, effectiveCornerRadius, transformStyle, positionStyles, adjustedSize, style.position, isOverLight, overLightConfig.borderOpacity ]), renderBackgroundLayer = layerType => jsx("div", {
1533
+ }), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle, positionStyles, adjustedSize, isOverLight, overLightConfig.borderOpacity ]), renderBackgroundLayer = layerType => jsx("div", {
1390
1534
  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(" "),
1391
1535
  style: {
1392
1536
  ...positionStyles,
1393
1537
  height: adjustedSize.height,
1394
1538
  width: adjustedSize.width,
1395
- borderRadius: `${effectiveCornerRadius}px`,
1539
+ borderRadius: `${effectiveBorderRadius}px`,
1396
1540
  transform: baseStyle.transform
1397
1541
  }
1398
1542
  });
1399
1543
  return jsxs("div", {
1544
+ ...rest,
1400
1545
  className: componentClassName,
1401
1546
  style: glassVars,
1402
1547
  role: role || (onClick ? "button" : void 0),
1403
1548
  tabIndex: onClick ? tabIndex ?? 0 : tabIndex,
1404
1549
  "aria-label": ariaLabel,
1405
1550
  "aria-describedby": ariaDescribedBy,
1406
- "aria-disabled": !(!onClick || !effectiveDisableEffects) || !onClick && void 0,
1551
+ "aria-disabled": !(!onClick || !effectiveWithoutEffects) || !onClick && void 0,
1407
1552
  "aria-pressed": !(!onClick || !isActive) || !onClick && void 0,
1408
1553
  onKeyDown: onClick ? handleKeyDown : void 0,
1409
1554
  children: [ jsx(AtomixGlassContainer, {
@@ -1411,18 +1556,18 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1411
1556
  contentRef: contentRef,
1412
1557
  className: className,
1413
1558
  style: baseStyle,
1414
- cornerRadius: effectiveCornerRadius,
1415
- displacementScale: effectiveDisableEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
1416
- blurAmount: effectiveDisableEffects ? 0 : blurAmount,
1559
+ borderRadius: effectiveBorderRadius,
1560
+ displacementScale: effectiveWithoutEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
1561
+ blurAmount: effectiveWithoutEffects ? 0 : blurAmount,
1417
1562
  saturation: effectiveHighContrast ? ATOMIX_GLASS.CONSTANTS.SATURATION.HIGH_CONTRAST : isOverLight ? saturation * overLightConfig.saturationBoost : saturation,
1418
- aberrationIntensity: effectiveDisableEffects ? 0 : "shader" === mode ? aberrationIntensity * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_ABERRATION : aberrationIntensity,
1563
+ aberrationIntensity: effectiveWithoutEffects ? 0 : "shader" === mode ? aberrationIntensity * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_ABERRATION : aberrationIntensity,
1419
1564
  glassSize: glassSize,
1420
1565
  padding: padding,
1421
- mouseOffset: effectiveDisableEffects ? {
1566
+ mouseOffset: effectiveWithoutEffects ? {
1422
1567
  x: 0,
1423
1568
  y: 0
1424
1569
  } : mouseOffset,
1425
- globalMousePosition: effectiveDisableEffects ? {
1570
+ globalMousePosition: effectiveWithoutEffects ? {
1426
1571
  x: 0,
1427
1572
  y: 0
1428
1573
  } : globalMousePosition,
@@ -1442,11 +1587,11 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1442
1587
  onClick: onClick,
1443
1588
  mode: mode,
1444
1589
  transform: baseStyle.transform,
1445
- effectiveDisableEffects: effectiveDisableEffects,
1590
+ effectiveWithoutEffects: effectiveWithoutEffects,
1446
1591
  effectiveReducedMotion: effectiveReducedMotion,
1447
1592
  shaderVariant: shaderVariant,
1448
1593
  elasticity: elasticity,
1449
- enableLiquidBlur: enableLiquidBlur,
1594
+ withLiquidBlur: withLiquidBlur,
1450
1595
  children: children
1451
1596
  }), Boolean(onClick) && jsxs(Fragment, {
1452
1597
  children: [ jsx("div", {
@@ -1468,11 +1613,19 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1468
1613
  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}%)`
1469
1614
  }
1470
1615
  }) ]
1471
- }), enableBorderEffect && jsxs(Fragment, {
1616
+ }), withBorder && jsxs(Fragment, {
1472
1617
  children: [ jsx("span", {
1473
- className: ATOMIX_GLASS.BORDER_1_CLASS
1618
+ className: ATOMIX_GLASS.BORDER_1_CLASS,
1619
+ style: {
1620
+ width: glassSize.width,
1621
+ height: glassSize.height
1622
+ }
1474
1623
  }), jsx("span", {
1475
- className: ATOMIX_GLASS.BORDER_2_CLASS
1624
+ className: ATOMIX_GLASS.BORDER_2_CLASS,
1625
+ style: {
1626
+ width: glassSize.width,
1627
+ height: glassSize.height
1628
+ }
1476
1629
  }) ]
1477
1630
  }) ]
1478
1631
  });
@@ -3088,7 +3241,7 @@ const Badge = memo((({label: label, variant: variant = "primary", size: size =
3088
3241
  // Default glass settings for badges
3089
3242
  const defaultGlassProps = {
3090
3243
  displacementScale: 20,
3091
- cornerRadius: ref.current?.getBoundingClientRect().width ? ref.current?.getBoundingClientRect().width / 2 : 16,
3244
+ borderRadius: ref.current?.getBoundingClientRect().width ? ref.current?.getBoundingClientRect().width / 2 : 16,
3092
3245
  className: "c-badge--glass",
3093
3246
  elasticity: 0
3094
3247
  }, glassProps = !0 === glass ? defaultGlassProps : {
@@ -3154,7 +3307,7 @@ const Spinner = memo((({size: size = "md", variant: variant = "primary", fullsc
3154
3307
  const defaultGlassProps = {
3155
3308
  displacementScale: 20,
3156
3309
  blurAmount: 1,
3157
- cornerRadius: 999,
3310
+ borderRadius: 999,
3158
3311
  mode: "shader"
3159
3312
  }, glassProps = !0 === glass ? defaultGlassProps : {
3160
3313
  ...defaultGlassProps,
@@ -3222,7 +3375,7 @@ class ThemeNaming {
3222
3375
  * Convert camelCase to kebab-case for CSS variables
3223
3376
  * @param str - String to convert
3224
3377
  */ static camelToKebab(str) {
3225
- return str.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2").toLowerCase();
3378
+ return str.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
3226
3379
  }
3227
3380
  /**
3228
3381
  * Convert kebab-case to camelCase for JavaScript properties