@shohojdhara/atomix 0.4.1 → 0.4.3

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 (131) hide show
  1. package/dist/atomix.css +9351 -9259
  2. package/dist/atomix.css.map +1 -1
  3. package/dist/atomix.min.css +4 -4
  4. package/dist/atomix.min.css.map +1 -1
  5. package/dist/charts.d.ts +12 -19
  6. package/dist/charts.js +555 -358
  7. package/dist/charts.js.map +1 -1
  8. package/dist/core.d.ts +21 -24
  9. package/dist/core.js +435 -265
  10. package/dist/core.js.map +1 -1
  11. package/dist/forms.d.ts +11 -18
  12. package/dist/forms.js +411 -257
  13. package/dist/forms.js.map +1 -1
  14. package/dist/heavy.d.ts +14 -21
  15. package/dist/heavy.js +409 -254
  16. package/dist/heavy.js.map +1 -1
  17. package/dist/index.d.ts +38 -41
  18. package/dist/index.esm.js +731 -487
  19. package/dist/index.esm.js.map +1 -1
  20. package/dist/index.js +733 -492
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.min.js +1 -1
  23. package/dist/index.min.js.map +1 -1
  24. package/package.json +1 -1
  25. package/scripts/atomix-cli.js +34 -1
  26. package/src/components/AtomixGlass/AtomixGlass.tsx +82 -54
  27. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +17 -18
  28. package/src/components/AtomixGlass/README.md +5 -5
  29. package/src/components/AtomixGlass/stories/Customization.stories.tsx +2 -2
  30. package/src/components/AtomixGlass/stories/Examples.stories.tsx +42 -42
  31. package/src/components/AtomixGlass/stories/Modes.stories.tsx +5 -5
  32. package/src/components/AtomixGlass/stories/Overview.stories.tsx +3 -3
  33. package/src/components/AtomixGlass/stories/Performance.stories.tsx +2 -2
  34. package/src/components/AtomixGlass/stories/Playground.stories.tsx +45 -45
  35. package/src/components/AtomixGlass/stories/Shaders.stories.tsx +3 -3
  36. package/src/components/Badge/Badge.stories.tsx +1 -1
  37. package/src/components/Badge/Badge.tsx +1 -1
  38. package/src/components/Breadcrumb/Breadcrumb.tsx +90 -77
  39. package/src/components/Breadcrumb/index.ts +2 -2
  40. package/src/components/Button/Button.stories.tsx +1 -1
  41. package/src/components/Button/Button.tsx +2 -1
  42. package/src/components/Button/README.md +2 -2
  43. package/src/components/Callout/Callout.test.tsx +3 -3
  44. package/src/components/Callout/Callout.tsx +2 -2
  45. package/src/components/Callout/README.md +2 -2
  46. package/src/components/Card/Card.tsx +31 -11
  47. package/src/components/Chart/Chart.stories.tsx +1 -1
  48. package/src/components/Chart/Chart.tsx +5 -5
  49. package/src/components/Chart/TreemapChart.tsx +37 -29
  50. package/src/components/DatePicker/readme.md +3 -3
  51. package/src/components/Dropdown/Dropdown.stories.tsx +1 -1
  52. package/src/components/Dropdown/Dropdown.tsx +276 -273
  53. package/src/components/EdgePanel/EdgePanel.stories.tsx +7 -7
  54. package/src/components/Footer/FooterLink.tsx +2 -2
  55. package/src/components/Form/Checkbox.stories.tsx +1 -1
  56. package/src/components/Form/Checkbox.tsx +1 -1
  57. package/src/components/Form/Input.stories.tsx +1 -1
  58. package/src/components/Form/Input.tsx +1 -1
  59. package/src/components/Form/Radio.stories.tsx +1 -1
  60. package/src/components/Form/Radio.tsx +1 -1
  61. package/src/components/Form/Select.stories.tsx +1 -1
  62. package/src/components/Form/Select.tsx +1 -1
  63. package/src/components/Form/Textarea.stories.tsx +1 -1
  64. package/src/components/Form/Textarea.tsx +1 -1
  65. package/src/components/Hero/Hero.stories.tsx +2 -2
  66. package/src/components/Hero/Hero.tsx +2 -2
  67. package/src/components/Messages/Messages.stories.tsx +1 -1
  68. package/src/components/Messages/Messages.tsx +2 -2
  69. package/src/components/Modal/Modal.stories.tsx +1 -1
  70. package/src/components/Navigation/Nav/Nav.stories.tsx +2 -2
  71. package/src/components/Navigation/Nav/Nav.tsx +1 -1
  72. package/src/components/Navigation/Nav/NavItem.tsx +6 -3
  73. package/src/components/Navigation/Navbar/Navbar.stories.tsx +3 -3
  74. package/src/components/Navigation/Navbar/Navbar.tsx +1 -1
  75. package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +2 -2
  76. package/src/components/Navigation/SideMenu/SideMenu.tsx +1 -1
  77. package/src/components/Pagination/Pagination.stories.tsx +1 -1
  78. package/src/components/Pagination/Pagination.tsx +1 -1
  79. package/src/components/Popover/Popover.stories.tsx +1 -1
  80. package/src/components/Popover/Popover.tsx +1 -1
  81. package/src/components/Progress/Progress.tsx +1 -1
  82. package/src/components/Rating/Rating.stories.tsx +1 -1
  83. package/src/components/Rating/Rating.test.tsx +73 -0
  84. package/src/components/Rating/Rating.tsx +25 -37
  85. package/src/components/Spinner/Spinner.tsx +1 -1
  86. package/src/components/Steps/Steps.stories.tsx +1 -1
  87. package/src/components/Steps/Steps.tsx +2 -2
  88. package/src/components/Tabs/Tabs.stories.tsx +1 -1
  89. package/src/components/Tabs/Tabs.tsx +1 -1
  90. package/src/components/Todo/Todo.tsx +0 -1
  91. package/src/components/Toggle/Toggle.stories.tsx +1 -1
  92. package/src/components/Toggle/Toggle.tsx +1 -1
  93. package/src/components/Tooltip/Tooltip.stories.tsx +1 -1
  94. package/src/components/VideoPlayer/VideoPlayer.stories.tsx +2 -2
  95. package/src/lib/composables/__tests__/useAtomixGlassPerf.test.tsx +88 -0
  96. package/src/lib/composables/__tests__/useChart.test.ts +50 -0
  97. package/src/lib/composables/__tests__/useChart.test.tsx +139 -0
  98. package/src/lib/composables/__tests__/useHeroBackgroundSlider.test.tsx +59 -0
  99. package/src/lib/composables/__tests__/useSliderAutoplay.test.tsx +68 -0
  100. package/src/lib/composables/atomix-glass/useGlassBackgroundDetection.ts +329 -0
  101. package/src/lib/composables/atomix-glass/useGlassCornerRadius.ts +82 -0
  102. package/src/lib/composables/atomix-glass/useGlassMouseTracking.ts +153 -0
  103. package/src/lib/composables/atomix-glass/useGlassOverLight.ts +198 -0
  104. package/src/lib/composables/atomix-glass/useGlassSize.ts +117 -0
  105. package/src/lib/composables/atomix-glass/useGlassState.ts +112 -0
  106. package/src/lib/composables/atomix-glass/useGlassTransforms.ts +160 -0
  107. package/src/lib/composables/glass-styles.ts +302 -0
  108. package/src/lib/composables/index.ts +0 -4
  109. package/src/lib/composables/useAtomixGlass.ts +331 -522
  110. package/src/lib/composables/useAtomixGlassStyles.ts +307 -0
  111. package/src/lib/composables/useBarChart.ts +1 -1
  112. package/src/lib/composables/useBreadcrumb.ts +6 -6
  113. package/src/lib/composables/useChart.ts +104 -21
  114. package/src/lib/composables/useHeroBackgroundSlider.ts +16 -7
  115. package/src/lib/composables/useSlider.ts +66 -34
  116. package/src/lib/theme/devtools/CLI.ts +1 -1
  117. package/src/lib/theme/utils/__tests__/themeUtils.test.ts +213 -0
  118. package/src/lib/types/components.ts +18 -21
  119. package/src/lib/utils/__tests__/dom.test.ts +100 -0
  120. package/src/lib/utils/__tests__/fontPreloader.test.ts +102 -0
  121. package/src/styles/02-tools/_tools.breakpoints.scss +1 -1
  122. package/src/styles/02-tools/_tools.utility-api.scss +6 -6
  123. package/src/styles/06-components/_components.accordion.scss +0 -2
  124. package/src/styles/06-components/_components.chart.scss +0 -1
  125. package/src/styles/06-components/_components.dropdown.scss +0 -1
  126. package/src/styles/06-components/_components.edge-panel.scss +0 -2
  127. package/src/styles/06-components/_components.photoviewer.scss +0 -1
  128. package/src/styles/06-components/_components.river.scss +0 -1
  129. package/src/styles/06-components/_components.slider.scss +0 -3
  130. package/src/styles/99-utilities/_utilities.glass-fixes.scss +0 -1
  131. package/src/styles/99-utilities/_utilities.text.scss +1 -0
package/dist/index.js CHANGED
@@ -1972,7 +1972,7 @@ function useAccordion(initialProps) {
1972
1972
  };
1973
1973
  }
1974
1974
 
1975
- const {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS, calculateDistance = (pos1, pos2) => {
1975
+ const {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateDistance = (pos1, pos2) => {
1976
1976
  if (!pos1 || !pos2 || "number" != typeof pos1.x || "number" != typeof pos1.y || "number" != typeof pos2.x || "number" != typeof pos2.y) return 0;
1977
1977
  const deltaX = pos1.x - pos2.x, deltaY = pos1.y - pos2.y;
1978
1978
  return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
@@ -1985,36 +1985,36 @@ const {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS, calculateDistance = (pos1, pos2)
1985
1985
  }, calculateMouseInfluence = mouseOffset => {
1986
1986
  if (!mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y) return 0;
1987
1987
  // Bounded calculation — keeps the glass effect subtle and stable
1988
- const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$1.MOUSE_INFLUENCE_DIVISOR;
1988
+ const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$2.MOUSE_INFLUENCE_DIVISOR;
1989
1989
  return Math.min(.8, influence);
1990
1990
  // Tighter cap to prevent blur/filter blow-out
1991
- }, 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 => {
1991
+ }, 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 => {
1992
1992
  if ("number" == typeof value) return Math.max(0, value);
1993
- if ("string" != typeof value || !value.trim()) return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
1993
+ if ("string" != typeof value || !value.trim()) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
1994
1994
  const trimmedValue = value.trim();
1995
1995
  // Handle px values
1996
1996
  if (trimmedValue.endsWith("px")) {
1997
1997
  const parsed = parseFloat(trimmedValue);
1998
- return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
1998
+ return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
1999
1999
  }
2000
2000
  // Handle rem values (assume 16px = 1rem)
2001
2001
  if (trimmedValue.endsWith("rem")) {
2002
2002
  const parsed = parseFloat(trimmedValue);
2003
- return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
2003
+ return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
2004
2004
  }
2005
2005
  // Handle em values (assume 16px = 1em for simplicity)
2006
2006
  if (trimmedValue.endsWith("em")) {
2007
2007
  const parsed = parseFloat(trimmedValue);
2008
- return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
2008
+ return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
2009
2009
  }
2010
2010
  // Handle percentage (convert to approximate px value, assuming 200px container)
2011
2011
  if (trimmedValue.endsWith("%")) {
2012
2012
  const parsed = parseFloat(trimmedValue);
2013
- return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
2013
+ return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
2014
2014
  }
2015
2015
  // Handle unitless numbers
2016
2016
  const numValue = parseFloat(trimmedValue);
2017
- return isNaN(numValue) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
2017
+ return isNaN(numValue) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
2018
2018
  }, extractBorderRadiusFromElement = element => {
2019
2019
  if (!element || !element.props) return null;
2020
2020
  // Check inline styles first (highest priority)
@@ -2030,11 +2030,11 @@ const {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS, calculateDistance = (pos1, pos2)
2030
2030
  // If element has children, recursively check them
2031
2031
  if (element.props.children) {
2032
2032
  const childRadius = extractBorderRadiusFromChildren(element.props.children);
2033
- if (childRadius > 0 && childRadius !== CONSTANTS$1.DEFAULT_CORNER_RADIUS) return childRadius;
2033
+ if (childRadius > 0 && childRadius !== CONSTANTS$2.DEFAULT_CORNER_RADIUS) return childRadius;
2034
2034
  }
2035
2035
  return null;
2036
2036
  }, extractBorderRadiusFromChildren = children => {
2037
- if (!children) return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
2037
+ if (!children) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
2038
2038
  try {
2039
2039
  const childArray = React__default.default.Children.toArray(children);
2040
2040
  for (let i = 0; i < childArray.length; i++) {
@@ -2047,7 +2047,7 @@ const {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS, calculateDistance = (pos1, pos2)
2047
2047
  } catch (error) {
2048
2048
  // Silently handle errors
2049
2049
  }
2050
- return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
2050
+ return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
2051
2051
  }, getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
2052
2052
  switch (mode) {
2053
2053
  case "standard":
@@ -2218,10 +2218,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
2218
2218
  }, globalMousePosition: globalMousePosition = {
2219
2219
  x: 0,
2220
2220
  y: 0
2221
- }, 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 = {
2221
+ }, 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 = {
2222
2222
  width: 0,
2223
2223
  height: 0
2224
- }, onClick: onClick, mode: mode = "standard", effectiveDisableEffects: effectiveDisableEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", enableLiquidBlur: enableLiquidBlur = !1, elasticity: elasticity = 0, contentRef: contentRef}, ref) => {
2224
+ }, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, elasticity: elasticity = 0, contentRef: contentRef}, ref) => {
2225
2225
  // Generate a stable, deterministic ID for SSR compatibility
2226
2226
  // Use a module-level counter that's consistent across server and client
2227
2227
  const filterId = React.useMemo((() => "atomix-glass-filter-" + ++idCounter), []), [shaderMapUrl, setShaderMapUrl] = React.useState(""), shaderGeneratorRef = React.useRef(null), shaderUtilsRef = React.useRef(null), shaderDebounceTimeoutRef = React.useRef(null);
@@ -2333,7 +2333,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
2333
2333
  flowBlur: 1.2 * blurAmount
2334
2334
  };
2335
2335
  // Enhanced validation for liquid blur
2336
- if (!enableLiquidBlur || !rectCache || !mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y || isNaN(mouseOffset.x) || isNaN(mouseOffset.y)) return defaultBlur;
2336
+ if (!withLiquidBlur || !rectCache || !mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y || isNaN(mouseOffset.x) || isNaN(mouseOffset.y)) return defaultBlur;
2337
2337
  try {
2338
2338
  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);
2339
2339
  // NOTE: hover/active multipliers intentionally omitted here —
@@ -2348,14 +2348,14 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
2348
2348
  return console.warn("AtomixGlassContainer: Error calculating liquid blur", error),
2349
2349
  defaultBlur;
2350
2350
  }
2351
- }), [ enableLiquidBlur, blurAmount, mouseOffset, rectCache ]), backdropStyle = React.useMemo((() => {
2351
+ }), [ withLiquidBlur, blurAmount, mouseOffset, rectCache ]), backdropStyle = React.useMemo((() => {
2352
2352
  try {
2353
2353
  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;
2354
2354
  // Validate blur values before using them
2355
- return !enableLiquidBlur || effectiveReducedMotion || effectiveDisableEffects || area > 18e4 ? {
2355
+ return !withLiquidBlur || effectiveReducedMotion || effectiveWithoutEffects || area > 18e4 ? {
2356
2356
  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})`
2357
2357
  } : {
2358
- 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})`
2358
+ 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})`
2359
2359
  };
2360
2360
  // Single-pass fallback: stronger radius to match perceived blur of multi-pass
2361
2361
  } catch (error) {
@@ -2364,7 +2364,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
2364
2364
  backdropFilter: `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`
2365
2365
  };
2366
2366
  }
2367
- }), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveDisableEffects, enableLiquidBlur ]), containerVars = React.useMemo((() => {
2367
+ }), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveWithoutEffects, withLiquidBlur ]), containerVars = React.useMemo((() => {
2368
2368
  try {
2369
2369
  // Safe extraction of mouse offset values
2370
2370
  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;
@@ -2372,10 +2372,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
2372
2372
  "--atomix-glass-container-width": `${glassSize?.width}`,
2373
2373
  "--atomix-glass-container-height": `${glassSize?.height}`,
2374
2374
  "--atomix-glass-container-padding": padding || "0 0",
2375
- "--atomix-glass-container-radius": `${"number" != typeof cornerRadius || isNaN(cornerRadius) ? 0 : cornerRadius}px`,
2375
+ "--atomix-glass-container-radius": `${"number" != typeof borderRadius || isNaN(borderRadius) ? 0 : borderRadius}px`,
2376
2376
  "--atomix-glass-container-backdrop": backdropStyle?.backdropFilter || "none",
2377
2377
  "--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",
2378
- "--atomix-glass-container-shadow-opacity": effectiveDisableEffects ? 0 : 1,
2378
+ "--atomix-glass-container-shadow-opacity": effectiveWithoutEffects ? 0 : 1,
2379
2379
  // Background and shadow values use design token-aligned RGB values
2380
2380
  "--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",
2381
2381
  "--atomix-glass-container-text-shadow": overLight ? "0px 2px 12px rgba(0, 0, 0, 0)" : "0px 2px 12px rgba(0, 0, 0, 0.4)",
@@ -2393,14 +2393,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
2393
2393
  "--atomix-glass-container-text-shadow": "none"
2394
2394
  };
2395
2395
  }
2396
- }), [ glassSize, padding, cornerRadius, backdropStyle, mouseOffset, overLight, effectiveDisableEffects ]), setForceNoTransition = el => {
2397
- el && (el.style.setProperty("transition-duration", "0s", "important"), el.style.setProperty("animation-duration", "0s", "important"),
2398
- el.style.setProperty("transition-delay", "0s", "important"));
2399
- };
2396
+ }), [ glassSize, padding, borderRadius, backdropStyle, mouseOffset, overLight, effectiveWithoutEffects ]);
2400
2397
  return jsxRuntime.jsx("div", {
2401
2398
  ref: el => {
2402
2399
  // Apply force no-transition
2403
- setForceNoTransition(el),
2404
2400
  // Handle forwarded ref
2405
2401
  "function" == typeof ref ? ref(el) : ref && (ref.current = el);
2406
2402
  },
@@ -2435,7 +2431,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
2435
2431
  aberrationIntensity: "number" != typeof aberrationIntensity || isNaN(aberrationIntensity) ? 0 : aberrationIntensity,
2436
2432
  shaderMapUrl: shaderMapUrl
2437
2433
  }), jsxRuntime.jsx("div", {
2438
- ref: setForceNoTransition,
2434
+ ref: el => {
2435
+ el && (el.style.setProperty("transition-duration", "0s", "important"), el.style.setProperty("animation-duration", "0s", "important"),
2436
+ el.style.setProperty("transition-delay", "0s", "important"));
2437
+ },
2439
2438
  className: ATOMIX_GLASS.FILTER_OVERLAY_CLASS,
2440
2439
  style: {
2441
2440
  filter: `url(#${filterId})`,
@@ -2552,7 +2551,128 @@ class {
2552
2551
  */ getSubscriberCount() {
2553
2552
  return this.listeners.size;
2554
2553
  }
2555
- }, {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
2554
+ }, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
2555
+ if (!wrapperElement && !containerElement) return;
2556
+ 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 = {
2557
+ opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
2558
+ contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
2559
+ brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
2560
+ shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
2561
+ borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence)),
2562
+ saturationBoost: baseOverLightConfig.saturationBoost
2563
+ };
2564
+ // Calculate mouse influence
2565
+ // Calculate elastic translation
2566
+ let elasticTranslation = {
2567
+ x: 0,
2568
+ y: 0
2569
+ };
2570
+ if (!effectiveWithoutEffects && wrapperElement) {
2571
+ const rect = wrapperElement.getBoundingClientRect(), center = calculateElementCenter(rect);
2572
+ // Calculate fade in factor
2573
+ let fadeInFactor = 0;
2574
+ if (globalMousePosition.x && globalMousePosition.y && validateGlassSize(glassSize)) {
2575
+ 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({
2576
+ x: edgeDistanceX,
2577
+ y: edgeDistanceY
2578
+ }, {
2579
+ x: 0,
2580
+ y: 0
2581
+ });
2582
+ fadeInFactor = edgeDistance > ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE ? 0 : 1 - edgeDistance / ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE;
2583
+ }
2584
+ elasticTranslation = {
2585
+ x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
2586
+ y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
2587
+ };
2588
+ }
2589
+ 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}`;
2590
+ // Update Wrapper Styles (glassVars)
2591
+ if (wrapperElement) {
2592
+ 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 = {
2593
+ hover1: {
2594
+ x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1,
2595
+ y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1
2596
+ },
2597
+ hover2: {
2598
+ x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_2,
2599
+ y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_2
2600
+ },
2601
+ hover3: {
2602
+ x: GRADIENT.CENTER_POSITION + mx * GRADIENT.HOVER_POSITION.MULTIPLIER_3,
2603
+ y: GRADIENT.CENTER_POSITION + my * GRADIENT.HOVER_POSITION.MULTIPLIER_3
2604
+ }
2605
+ }, basePosition = {
2606
+ x: GRADIENT.CENTER_POSITION + mx * GRADIENT.BASE_LAYER_MULTIPLIER,
2607
+ y: GRADIENT.CENTER_POSITION + my * GRADIENT.BASE_LAYER_MULTIPLIER
2608
+ }, opacityValues = {
2609
+ hover1: isHovered || isActive ? .5 : 0,
2610
+ hover2: isActive ? .5 : 0,
2611
+ hover3: isHovered ? .4 : isActive ? .8 : 0,
2612
+ base: isOverLight ? overLightConfig.opacity : 0,
2613
+ over: isOverLight ? 1.1 * overLightConfig.opacity : 0
2614
+ }, style = wrapperElement.style;
2615
+ style.setProperty("--atomix-glass-transform", transformStyle || "none"),
2616
+ // Gradients
2617
+ 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%)`),
2618
+ 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%)`),
2619
+ // Hover gradients
2620
+ 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}%)`),
2621
+ 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}%)`),
2622
+ 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}%)`),
2623
+ 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})`),
2624
+ 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})`),
2625
+ // Opacities
2626
+ style.setProperty("--atomix-glass-hover-1-opacity", opacityValues.hover1.toString()),
2627
+ style.setProperty("--atomix-glass-hover-2-opacity", opacityValues.hover2.toString()),
2628
+ style.setProperty("--atomix-glass-hover-3-opacity", opacityValues.hover3.toString()),
2629
+ style.setProperty("--atomix-glass-base-opacity", opacityValues.base.toString()),
2630
+ style.setProperty("--atomix-glass-overlay-opacity", opacityValues.over.toString()),
2631
+ style.setProperty("--atomix-glass-overlay-highlight-opacity", (opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER).toString()),
2632
+ // Other
2633
+ style.setProperty("--atomix-glass-blend-mode", isOverLight ? "multiply" : "overlay"),
2634
+ style.setProperty("--atomix-glass-radius", `${effectiveBorderRadius}px`);
2635
+ }
2636
+ // Update Container Styles (containerVars)
2637
+ if (containerElement) {
2638
+ 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();
2639
+ let liquidBlur = {
2640
+ baseBlur: blurAmount,
2641
+ edgeBlur: blurAmount * EDGE_BLUR_MULTIPLIER,
2642
+ centerBlur: blurAmount * CENTER_BLUR_MULTIPLIER,
2643
+ flowBlur: blurAmount * FLOW_BLUR_MULTIPLIER
2644
+ };
2645
+ if (withLiquidBlur && rect) {
2646
+ 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);
2647
+ liquidBlur = {
2648
+ baseBlur: clampBlur(baseBlur),
2649
+ edgeBlur: clampBlur(edgeBlur),
2650
+ centerBlur: clampBlur(centerBlur),
2651
+ flowBlur: clampBlur(flowBlur)
2652
+ };
2653
+ }
2654
+ // Backdrop filter
2655
+ let backdropFilterString = `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`;
2656
+ const dynamicSaturation = saturation + 20 * (liquidBlur.baseBlur || 0), area = rect ? rect.width * rect.height : 0;
2657
+ 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})`;
2658
+ // Container variables
2659
+ const style = containerElement.style;
2660
+ style.setProperty("--atomix-glass-container-width", `${glassSize.width}`), style.setProperty("--atomix-glass-container-height", `${glassSize.height}`),
2661
+ style.setProperty("--atomix-glass-container-padding", padding), style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
2662
+ style.setProperty("--atomix-glass-container-backdrop", backdropFilterString),
2663
+ // Shadows
2664
+ 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"),
2665
+ style.setProperty("--atomix-glass-container-shadow-opacity", effectiveWithoutEffects ? "0" : "1"),
2666
+ 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"),
2667
+ 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)"),
2668
+ 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)");
2669
+ }
2670
+ }, {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS;
2671
+
2672
+ /**
2673
+ * Updates the styles of the AtomixGlass wrapper and container elements imperatively
2674
+ * to avoid React re-renders on mouse movement.
2675
+ */ const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
2556
2676
  parentElement && backgroundDetectionCache.set(parentElement, {
2557
2677
  result: result,
2558
2678
  timestamp: Date.now(),
@@ -2565,18 +2685,74 @@ class {
2565
2685
  * Composable hook for AtomixGlass component logic
2566
2686
  * Manages all state, calculations, and event handlers
2567
2687
  */
2568
- function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadius: cornerRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, disableEffects: disableEffects = !1, elasticity: elasticity = .05, onClick: onClick, debugCornerRadius: debugCornerRadius = !1, debugOverLight: debugOverLight = !1, children: children}) {
2688
+ 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}) {
2569
2689
  // State
2570
- const [isHovered, setIsHovered] = React.useState(!1), [isActive, setIsActive] = React.useState(!1), [glassSize, setGlassSize] = React.useState({
2571
- width: 270,
2572
- height: 69
2573
- }), [internalGlobalMousePosition, setInternalGlobalMousePosition] = React.useState({
2690
+ const [isHovered, setIsHovered] = React.useState(!1), [isActive, setIsActive] = React.useState(!1), cachedRectRef = React.useRef(null), internalGlobalMousePositionRef = React.useRef({
2574
2691
  x: 0,
2575
2692
  y: 0
2576
- }), [internalMouseOffset, setInternalMouseOffset] = React.useState({
2693
+ }), internalMouseOffsetRef = React.useRef({
2577
2694
  x: 0,
2578
2695
  y: 0
2579
- }), [dynamicCornerRadius, setDynamicCornerRadius] = React.useState(CONSTANTS.DEFAULT_CORNER_RADIUS), [userPrefersReducedMotion, setUserPrefersReducedMotion] = React.useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = React.useState(!1), [detectedOverLight, setDetectedOverLight] = React.useState(!1), effectiveCornerRadius = React.useMemo((() => void 0 !== cornerRadius ? Math.max(0, cornerRadius) : Math.max(0, dynamicCornerRadius)), [ cornerRadius, dynamicCornerRadius ]), effectiveReducedMotion = React.useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveHighContrast = React.useMemo((() => highContrast || userPrefersHighContrast), [ highContrast, userPrefersHighContrast ]), effectiveDisableEffects = React.useMemo((() => disableEffects || effectiveReducedMotion), [ disableEffects, effectiveReducedMotion ]), globalMousePosition = React.useMemo((() => externalGlobalMousePosition || internalGlobalMousePosition), [ externalGlobalMousePosition, internalGlobalMousePosition ]), mouseOffset = React.useMemo((() => externalMouseOffset || internalMouseOffset), [ externalMouseOffset, internalMouseOffset ]);
2696
+ }), [dynamicBorderRadius, setDynamicCornerRadius] = React.useState(CONSTANTS.DEFAULT_CORNER_RADIUS), [userPrefersReducedMotion, setUserPrefersReducedMotion] = React.useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = React.useState(!1), [detectedOverLight, setDetectedOverLight] = React.useState(!1), effectiveBorderRadius = React.useMemo((() => void 0 !== borderRadius ? Math.max(0, borderRadius) : Math.max(0, dynamicBorderRadius)), [ borderRadius, dynamicBorderRadius ]), {glassSize: glassSize} = function({glassRef: glassRef, effectiveBorderRadius: effectiveBorderRadius, cachedRectRef: cachedRectRef}) {
2697
+ const [glassSize, setGlassSize] = React.useState({
2698
+ width: 270,
2699
+ height: 69
2700
+ });
2701
+ return React.useEffect((() => {
2702
+ const isValidElement = element => null !== element && element instanceof HTMLElement && element.isConnected;
2703
+ let rafId = null, lastSize = {
2704
+ width: 0,
2705
+ height: 0
2706
+ }, lastCornerRadius = effectiveBorderRadius;
2707
+ const updateGlassSize = (forceUpdate = !1) => {
2708
+ null !== rafId && cancelAnimationFrame(rafId), rafId = requestAnimationFrame((() => {
2709
+ if (!isValidElement(glassRef.current)) return void (rafId = null);
2710
+ const rect = glassRef.current.getBoundingClientRect();
2711
+ if (rect.width <= 0 || rect.height <= 0) return void (rafId = null);
2712
+ // Measure actual rendered size without artificial offsets to avoid feedback loops
2713
+ const newSize = {
2714
+ width: Math.round(rect.width),
2715
+ height: Math.round(rect.height)
2716
+ }, cornerRadiusChanged = lastCornerRadius !== effectiveBorderRadius, dimensionsChanged = Math.abs(newSize.width - lastSize.width) > 1 || Math.abs(newSize.height - lastSize.height) > 1;
2717
+ var size;
2718
+ (forceUpdate || cornerRadiusChanged || dimensionsChanged) && validateGlassSize(size = newSize) && size.width <= CONSTANTS$1.MAX_SIZE && size.height <= CONSTANTS$1.MAX_SIZE && (lastSize = newSize,
2719
+ lastCornerRadius = effectiveBorderRadius, setGlassSize(newSize)), rafId = null;
2720
+ }));
2721
+ };
2722
+ let resizeTimeoutId = null;
2723
+ const debouncedResizeHandler = () => {
2724
+ resizeTimeoutId && clearTimeout(resizeTimeoutId), resizeTimeoutId = setTimeout((() => updateGlassSize(!1)), 16);
2725
+ }, initialTimeoutId = setTimeout((() => updateGlassSize(!0)), 0);
2726
+ let resizeObserver = null, resizeDebounceTimeout = null;
2727
+ // ResizeObserver has 98%+ browser support, no need for fallback
2728
+ if ("undefined" != typeof ResizeObserver && isValidElement(glassRef.current)) try {
2729
+ resizeObserver = new ResizeObserver((entries => {
2730
+ for (const entry of entries) if (entry.target === glassRef.current) {
2731
+ // Update cached rect when size changes
2732
+ glassRef.current && cachedRectRef && (cachedRectRef.current = glassRef.current.getBoundingClientRect()),
2733
+ // Debounce resize updates to match RAF timing (16ms)
2734
+ resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), resizeDebounceTimeout = setTimeout((() => updateGlassSize(!1)), 16);
2735
+ break;
2736
+ }
2737
+ })), resizeObserver.observe(glassRef.current);
2738
+ } catch (error) {
2739
+ console.warn("AtomixGlass: ResizeObserver not available, using window resize only", error);
2740
+ }
2741
+ return window.addEventListener("resize", debouncedResizeHandler, {
2742
+ passive: !0
2743
+ }), () => {
2744
+ clearTimeout(initialTimeoutId), null !== rafId && cancelAnimationFrame(rafId), resizeTimeoutId && clearTimeout(resizeTimeoutId),
2745
+ resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), window.removeEventListener("resize", debouncedResizeHandler),
2746
+ resizeObserver?.disconnect();
2747
+ };
2748
+ }), [ effectiveBorderRadius, glassRef, cachedRectRef ]), {
2749
+ glassSize: glassSize
2750
+ };
2751
+ }({
2752
+ glassRef: glassRef,
2753
+ effectiveBorderRadius: effectiveBorderRadius,
2754
+ cachedRectRef: cachedRectRef
2755
+ }), effectiveReducedMotion = React.useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveHighContrast = React.useMemo((() => highContrast || userPrefersHighContrast), [ highContrast, userPrefersHighContrast ]), effectiveWithoutEffects = React.useMemo((() => withoutEffects || effectiveReducedMotion), [ withoutEffects, effectiveReducedMotion ]), globalMousePosition = externalGlobalMousePosition || internalGlobalMousePositionRef.current, mouseOffset = externalMouseOffset || internalMouseOffsetRef.current;
2580
2756
  // Extract border-radius from children
2581
2757
  React.useEffect((() => {
2582
2758
  const extractRadius = () => {
@@ -2607,13 +2783,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2607
2783
  }
2608
2784
  null !== extractedRadius && extractedRadius > 0 && setDynamicCornerRadius(extractedRadius);
2609
2785
  } catch (error) {
2610
- "undefined" != typeof process && "production" === process.env?.NODE_ENV || !debugCornerRadius || console.error("[AtomixGlass] Error extracting corner radius:", error);
2786
+ "undefined" != typeof process && "production" === process.env?.NODE_ENV || !debugBorderRadius || console.error("[AtomixGlass] Error extracting corner radius:", error);
2611
2787
  }
2612
2788
  };
2613
2789
  extractRadius();
2614
2790
  const timeoutId = setTimeout(extractRadius, 100);
2615
2791
  return () => clearTimeout(timeoutId);
2616
- }), [ children, debugCornerRadius, contentRef ]),
2792
+ }), [ children, debugBorderRadius, contentRef ]),
2617
2793
  // Media query handlers and background detection
2618
2794
  React.useEffect((() => {
2619
2795
  if (("auto" === overLight || "object" == typeof overLight && null !== overLight) && glassRef.current) {
@@ -2669,72 +2845,52 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2669
2845
  const rgb = bgColor.match(/\d+/g);
2670
2846
  if (rgb && rgb.length >= 3) {
2671
2847
  const r = Number(rgb[0]), g = Number(rgb[1]), b = Number(rgb[2]);
2672
- // Validate RGB values are valid numbers
2673
- 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)) {
2848
+ if (!isNaN(r) && !isNaN(g) && !isNaN(b) && (r > 10 || g > 10 || b > 10)) {
2674
2849
  const luminance = (.299 * r + .587 * g + .114 * b) / 255;
2675
2850
  !isNaN(luminance) && isFinite(luminance) && (totalLuminance += luminance, validSamples++,
2676
2851
  hasValidBackground = !0);
2677
2852
  }
2678
2853
  }
2679
2854
  }
2680
- // Check for image backgrounds
2681
- bgImage && "none" !== bgImage && "initial" !== bgImage && (
2682
- // For image backgrounds, assume medium luminance
2683
- totalLuminance += .5, validSamples++, hasValidBackground = !0);
2855
+ bgImage && "none" !== bgImage && "initial" !== bgImage && (totalLuminance += .5,
2856
+ validSamples++, hasValidBackground = !0);
2684
2857
  } catch (styleError) {
2685
- "undefined" == typeof process || process.env;
2858
+ // Silently continue
2686
2859
  }
2687
- // Move to parent element for next iteration
2688
- if (!currentElement) break;
2689
- // Exit loop if currentElement becomes null
2690
- currentElement = currentElement.parentElement, depth++;
2860
+ if (!currentElement) break;
2861
+ currentElement = currentElement.parentElement, depth++;
2691
2862
  }
2692
- // More conservative detection with better error handling
2693
- if (hasValidBackground && validSamples > 0) {
2863
+ if (hasValidBackground && validSamples > 0) {
2694
2864
  const avgLuminance = totalLuminance / validSamples;
2695
2865
  if (!isNaN(avgLuminance) && isFinite(avgLuminance)) {
2696
2866
  let threshold = .7;
2697
- // Conservative threshold for overlight
2698
- // If overLight is an object, use its threshold property with validation
2699
- if ("object" == typeof overLight && null !== overLight) {
2867
+ if ("object" == typeof overLight && null !== overLight) {
2700
2868
  const objConfig = overLight;
2701
2869
  if (void 0 !== objConfig.threshold) {
2702
- const configThreshold = "number" == typeof objConfig.threshold && !isNaN(objConfig.threshold) && isFinite(objConfig.threshold) ? objConfig.threshold : .7;
2870
+ const configThreshold = "number" != typeof objConfig.threshold || isNaN(objConfig.threshold) ? .7 : objConfig.threshold;
2703
2871
  threshold = Math.min(.9, Math.max(.1, configThreshold));
2704
2872
  }
2705
2873
  }
2706
2874
  const isOverLightDetected = avgLuminance > threshold;
2707
- // Cache the result in shared cache
2708
- setCachedBackgroundDetection(element.parentElement, overLight, isOverLightDetected, threshold),
2875
+ setCachedBackgroundDetection(element.parentElement, overLight, isOverLightDetected, threshold),
2709
2876
  setDetectedOverLight(isOverLightDetected);
2710
2877
  } else {
2711
- // Invalid luminance calculation, default to false
2712
2878
  const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
2713
2879
  setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
2714
2880
  setDetectedOverLight(result);
2715
2881
  }
2716
2882
  } else {
2717
- // Default to false if no valid background found
2718
2883
  const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
2719
2884
  setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
2720
2885
  setDetectedOverLight(result);
2721
2886
  }
2722
2887
  } catch (error) {
2723
- // Enhanced error logging with context
2724
- "undefined" != typeof process && "development" !== process.env?.NODE_ENV || console.warn("AtomixGlass: Error detecting background brightness:", error);
2725
- const result = !1;
2726
- if (element && element.parentElement) {
2727
- const threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
2728
- setCachedBackgroundDetection(element.parentElement, overLight, result, threshold);
2729
- }
2730
- setDetectedOverLight(result);
2888
+ setDetectedOverLight(!1);
2731
2889
  }
2732
2890
  }), 150);
2733
2891
  return () => clearTimeout(timeoutId);
2734
2892
  }
2735
- if ("boolean" == typeof overLight &&
2736
- // For boolean values, disable auto-detection
2737
- setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
2893
+ if ("boolean" == typeof overLight && setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
2738
2894
  const mediaQueryReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)"), mediaQueryHighContrast = window.matchMedia("(prefers-contrast: high)");
2739
2895
  setUserPrefersReducedMotion(mediaQueryReducedMotion.matches), setUserPrefersHighContrast(mediaQueryHighContrast.matches);
2740
2896
  const handleReducedMotionChange = e => {
@@ -2745,64 +2901,54 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2745
2901
  return mediaQueryReducedMotion.addEventListener ? (mediaQueryReducedMotion.addEventListener("change", handleReducedMotionChange),
2746
2902
  mediaQueryHighContrast.addEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.addListener && (mediaQueryReducedMotion.addListener(handleReducedMotionChange),
2747
2903
  mediaQueryHighContrast.addListener(handleHighContrastChange)), () => {
2748
- try {
2749
- mediaQueryReducedMotion.removeEventListener ? (mediaQueryReducedMotion.removeEventListener("change", handleReducedMotionChange),
2750
- mediaQueryHighContrast.removeEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.removeListener && (mediaQueryReducedMotion.removeListener(handleReducedMotionChange),
2751
- mediaQueryHighContrast.removeListener(handleHighContrastChange));
2752
- } catch (cleanupError) {
2753
- console.error("AtomixGlass: Error cleaning up media query listeners:", cleanupError);
2754
- }
2904
+ // ignore
2755
2905
  };
2756
2906
  } catch (error) {
2757
- return void console.error("AtomixGlass: Error setting up media queries:", error);
2907
+ return;
2758
2908
  }
2759
2909
  }), [ overLight, glassRef, debugOverLight ]);
2760
- // Mouse tracking using shared global tracker
2761
- // Cache bounding rect to avoid repeated getBoundingClientRect calls
2762
- const cachedRectRef = React.useRef(null), updateRectRef = React.useRef(null), handleGlobalMousePosition = React.useCallback((globalPos => {
2763
- if (externalGlobalMousePosition && externalMouseOffset)
2764
- // External mouse position provided, skip internal tracking
2765
- return;
2766
- if (effectiveDisableEffects) return;
2767
- const container = mouseContainer?.current || glassRef.current;
2768
- if (!container) return;
2769
- // Use cached rect if available, otherwise get new one
2770
- let rect = cachedRectRef.current;
2771
- if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
2772
- cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
2773
- const center = calculateElementCenter(rect), newOffset = {
2774
- x: (globalPos.x - center.x) / rect.width * 100,
2775
- y: (globalPos.y - center.y) / rect.height * 100
2910
+ /**
2911
+ * Get effective overLight value based on configuration
2912
+ */
2913
+ const getEffectiveOverLight = React.useCallback((() => "boolean" == typeof overLight ? overLight : ("auto" === overLight || "object" == typeof overLight && null !== overLight) && detectedOverLight), [ overLight, detectedOverLight ]), validateConfigValue = React.useCallback(((value, min, max, defaultValue) => "number" != typeof value || isNaN(value) || !isFinite(value) ? defaultValue : Math.min(max, Math.max(min, value))), []), baseOverLightConfig = React.useMemo((() => {
2914
+ const isOverLight = getEffectiveOverLight(), baseConfig = {
2915
+ isOverLight: isOverLight,
2916
+ threshold: .7,
2917
+ opacity: isOverLight ? Math.min(.6, Math.max(.2, .5)) : 0,
2918
+ contrast: 1,
2919
+ // Base contrast
2920
+ brightness: 1,
2921
+ // Base brightness
2922
+ saturationBoost: 1.3,
2923
+ shadowIntensity: .9,
2924
+ borderOpacity: .7
2776
2925
  };
2777
- // Calculate offset relative to this container
2778
- // React 18 automatically batches these updates
2779
- setInternalMouseOffset(newOffset), setInternalGlobalMousePosition(globalPos);
2780
- }), [ mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveDisableEffects ]);
2781
- // Subscribe to shared mouse tracker
2782
- React.useEffect((() => {
2783
- if (externalGlobalMousePosition && externalMouseOffset)
2784
- // External mouse position provided, don't subscribe
2785
- return;
2786
- if (effectiveDisableEffects)
2787
- // Effects disabled, don't subscribe
2788
- return;
2789
- // Subscribe to shared tracker
2790
- const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition), container = mouseContainer?.current || glassRef.current;
2791
- // Update cached rect when container size changes
2792
- let resizeObserver = null;
2793
- return container && "undefined" != typeof ResizeObserver && (resizeObserver = new ResizeObserver((() => {
2794
- null !== updateRectRef.current && cancelAnimationFrame(updateRectRef.current), updateRectRef.current = requestAnimationFrame((() => {
2795
- const container = mouseContainer?.current || glassRef.current;
2796
- container && (cachedRectRef.current = container.getBoundingClientRect()), updateRectRef.current = null;
2797
- }));
2798
- })), resizeObserver.observe(container)), () => {
2799
- unsubscribe(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
2800
- updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
2926
+ if ("object" == typeof overLight && null !== overLight) {
2927
+ 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);
2928
+ return {
2929
+ ...baseConfig,
2930
+ threshold: validatedThreshold,
2931
+ opacity: validatedOpacity,
2932
+ contrast: validatedContrast,
2933
+ brightness: validatedBrightness,
2934
+ saturationBoost: validatedSaturationBoost
2935
+ };
2936
+ }
2937
+ return baseConfig;
2938
+ }), [ overLight, getEffectiveOverLight, validateConfigValue ]), overLightConfig = React.useMemo((() => {
2939
+ const mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1;
2940
+ return {
2941
+ isOverLight: baseOverLightConfig.isOverLight,
2942
+ threshold: baseOverLightConfig.threshold,
2943
+ opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
2944
+ contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
2945
+ brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
2946
+ saturationBoost: baseOverLightConfig.saturationBoost,
2947
+ shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
2948
+ borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence))
2801
2949
  };
2802
- }), [ handleGlobalMousePosition, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveDisableEffects ]);
2803
- // Transform calculations
2804
- const calculateDirectionalScale = React.useCallback((() => {
2805
- if (!0 === overLight || "auto" === overLight && detectedOverLight || "object" == typeof overLight && null !== overLight && detectedOverLight) return "scale(1)";
2950
+ }), [ baseOverLightConfig, mouseOffset, isHovered, isActive ]), updateRectRef = React.useRef(null), calculateDirectionalScale = React.useCallback((() => {
2951
+ if (baseOverLightConfig.isOverLight) return "scale(1)";
2806
2952
  if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return "scale(1)";
2807
2953
  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({
2808
2954
  x: edgeDistanceX,
@@ -2816,7 +2962,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2816
2962
  if (0 === centerDistance) return "scale(1)";
2817
2963
  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;
2818
2964
  return `scaleX(${Math.max(.8, scaleX)}) scaleY(${Math.max(.8, scaleY)})`;
2819
- }), [ globalMousePosition, elasticity, glassSize, glassRef, overLight, detectedOverLight ]), calculateFadeInFactor = React.useCallback((() => {
2965
+ }), [ globalMousePosition, elasticity, glassSize, glassRef, baseOverLightConfig ]), calculateFadeInFactor = React.useCallback((() => {
2820
2966
  if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return 0;
2821
2967
  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({
2822
2968
  x: edgeDistanceX,
@@ -2836,122 +2982,110 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2836
2982
  x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
2837
2983
  y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
2838
2984
  };
2839
- }), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = React.useMemo((() => effectiveDisableEffects ? {
2985
+ }), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = React.useMemo((() => effectiveWithoutEffects ? {
2840
2986
  x: 0,
2841
2987
  y: 0
2842
- } : calculateElasticTranslation()), [ calculateElasticTranslation, effectiveDisableEffects ]), directionalScale = React.useMemo((() => effectiveDisableEffects ? "scale(1)" : calculateDirectionalScale()), [ calculateDirectionalScale, effectiveDisableEffects ]), transformStyle = React.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 ]);
2843
- // Size management
2844
- React.useEffect((() => {
2845
- const isValidElement = element => null !== element && element instanceof HTMLElement && element.isConnected;
2846
- let rafId = null, lastSize = {
2847
- width: 0,
2848
- height: 0
2849
- }, lastCornerRadius = effectiveCornerRadius;
2850
- const updateGlassSize = (forceUpdate = !1) => {
2851
- null !== rafId && cancelAnimationFrame(rafId), rafId = requestAnimationFrame((() => {
2852
- if (!isValidElement(glassRef.current)) return void (rafId = null);
2853
- const rect = glassRef.current.getBoundingClientRect();
2854
- if (rect.width <= 0 || rect.height <= 0) return void (rafId = null);
2855
- // Measure actual rendered size without artificial offsets to avoid feedback loops
2856
- const newSize = {
2857
- width: Math.round(rect.width),
2858
- height: Math.round(rect.height)
2859
- }, cornerRadiusChanged = lastCornerRadius !== effectiveCornerRadius, dimensionsChanged = Math.abs(newSize.width - lastSize.width) > 1 || Math.abs(newSize.height - lastSize.height) > 1;
2860
- var size;
2861
- (forceUpdate || cornerRadiusChanged || dimensionsChanged) && validateGlassSize(size = newSize) && size.width <= CONSTANTS.MAX_SIZE && size.height <= CONSTANTS.MAX_SIZE && (lastSize = newSize,
2862
- lastCornerRadius = effectiveCornerRadius, setGlassSize(newSize)), rafId = null;
2863
- }));
2864
- };
2865
- let resizeTimeoutId = null;
2866
- const debouncedResizeHandler = () => {
2867
- resizeTimeoutId && clearTimeout(resizeTimeoutId), resizeTimeoutId = setTimeout((() => updateGlassSize(!1)), 16);
2868
- }, initialTimeoutId = setTimeout((() => updateGlassSize(!0)), 0);
2869
- let resizeObserver = null, resizeDebounceTimeout = null;
2870
- // ResizeObserver has 98%+ browser support, no need for fallback
2871
- if ("undefined" != typeof ResizeObserver && isValidElement(glassRef.current)) try {
2872
- resizeObserver = new ResizeObserver((entries => {
2873
- for (const entry of entries) if (entry.target === glassRef.current) {
2874
- // Update cached rect when size changes
2875
- glassRef.current && (cachedRectRef.current = glassRef.current.getBoundingClientRect()),
2876
- // Debounce resize updates to match RAF timing (16ms)
2877
- resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), resizeDebounceTimeout = setTimeout((() => updateGlassSize(!1)), 16);
2878
- break;
2879
- }
2880
- })), resizeObserver.observe(glassRef.current);
2881
- } catch (error) {
2882
- console.warn("AtomixGlass: ResizeObserver not available, using window resize only", error);
2883
- }
2884
- return window.addEventListener("resize", debouncedResizeHandler, {
2885
- passive: !0
2886
- }), () => {
2887
- clearTimeout(initialTimeoutId), null !== rafId && cancelAnimationFrame(rafId), resizeTimeoutId && clearTimeout(resizeTimeoutId),
2888
- resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), window.removeEventListener("resize", debouncedResizeHandler),
2889
- resizeObserver?.disconnect();
2988
+ } : calculateElasticTranslation()), [ calculateElasticTranslation, effectiveWithoutEffects ]), directionalScale = React.useMemo((() => effectiveWithoutEffects ? "scale(1)" : calculateDirectionalScale()), [ calculateDirectionalScale, effectiveWithoutEffects ]), transformStyle = React.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 = React.useCallback((globalPos => {
2989
+ if (externalGlobalMousePosition && externalMouseOffset) return;
2990
+ if (effectiveWithoutEffects) return;
2991
+ const container = mouseContainer?.current || glassRef.current;
2992
+ if (!container) return;
2993
+ // Use cached rect if available, otherwise get new one
2994
+ let rect = cachedRectRef.current;
2995
+ if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
2996
+ cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
2997
+ const center = calculateElementCenter(rect), newOffset = {
2998
+ x: (globalPos.x - center.x) / rect.width * 100,
2999
+ y: (globalPos.y - center.y) / rect.height * 100
2890
3000
  };
2891
- }), [ effectiveCornerRadius, glassRef ]);
2892
- // OverLight config
3001
+ // Calculate offset relative to this container
3002
+ // Store in refs instead of state
3003
+ internalMouseOffsetRef.current = newOffset, internalGlobalMousePositionRef.current = globalPos,
3004
+ // Imperative style update
3005
+ updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
3006
+ mouseOffset: newOffset,
3007
+ globalMousePosition: globalPos,
3008
+ glassSize: glassSize,
3009
+ isHovered: isHovered,
3010
+ isActive: isActive,
3011
+ isOverLight: baseOverLightConfig.isOverLight,
3012
+ baseOverLightConfig: baseOverLightConfig,
3013
+ effectiveBorderRadius: effectiveBorderRadius,
3014
+ effectiveWithoutEffects: effectiveWithoutEffects,
3015
+ effectiveReducedMotion: effectiveReducedMotion,
3016
+ elasticity: elasticity,
3017
+ directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
3018
+ // Simplified directional scale for fast path
3019
+ onClick: onClick,
3020
+ withLiquidBlur: withLiquidBlur,
3021
+ blurAmount: blurAmount,
3022
+ saturation: saturation,
3023
+ padding: padding
3024
+ });
3025
+ }), [ mouseContainer, glassRef, wrapperRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects, glassSize, isHovered, isActive, baseOverLightConfig, effectiveBorderRadius, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding ]);
2893
3026
  /**
2894
- * Get effective overLight value based on configuration
2895
- * - boolean: returns the boolean value directly
2896
- * - 'auto': returns detectedOverLight (auto-detected from background)
2897
- * - object: returns detectedOverLight (auto-detected, but config object provides customization)
2898
- */
2899
- const getEffectiveOverLight = React.useCallback((() => "boolean" == typeof overLight ? overLight : ("auto" === overLight || "object" == typeof overLight && null !== overLight) && detectedOverLight), [ overLight, detectedOverLight ]), validateConfigValue = React.useCallback(((value, min, max, defaultValue) => "number" != typeof value || isNaN(value) || !isFinite(value) ? defaultValue : Math.min(max, Math.max(min, value))), []), overLightConfig = React.useMemo((() => {
2900
- const isOverLight = getEffectiveOverLight(), mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1, baseConfig = {
2901
- isOverLight: isOverLight,
2902
- threshold: .7,
2903
- opacity: isOverLight ? Math.min(.6, Math.max(.2, .5 * hoverIntensity * activeIntensity)) : 0,
2904
- contrast: Math.min(1.6, Math.max(1, 1.4 + .1 * mouseInfluence)),
2905
- brightness: Math.min(1.1, Math.max(.8, .9 + .05 * mouseInfluence)),
2906
- saturationBoost: 1.3,
2907
- // Fixed value dynamic saturation amplifies perceived displacement
2908
- shadowIntensity: Math.min(1.2, Math.max(.5, .9 + .2 * mouseInfluence)),
2909
- borderOpacity: Math.min(1, Math.max(.3, .7 + .1 * mouseInfluence))
3027
+ * Validate and clamp a numeric config value
3028
+ */
3029
+ // Subscribe to shared mouse tracker
3030
+ React.useEffect((() => {
3031
+ if (externalGlobalMousePosition && externalMouseOffset) return;
3032
+ if (effectiveWithoutEffects) return;
3033
+ const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition), container = mouseContainer?.current || glassRef.current;
3034
+ let resizeObserver = null;
3035
+ return container && "undefined" != typeof ResizeObserver && (resizeObserver = new ResizeObserver((() => {
3036
+ null !== updateRectRef.current && cancelAnimationFrame(updateRectRef.current), updateRectRef.current = requestAnimationFrame((() => {
3037
+ const container = mouseContainer?.current || glassRef.current;
3038
+ container && (cachedRectRef.current = container.getBoundingClientRect()), updateRectRef.current = null;
3039
+ }));
3040
+ })), resizeObserver.observe(container)), () => {
3041
+ unsubscribe(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
3042
+ updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
2910
3043
  };
2911
- if ("object" == typeof overLight && null !== overLight) {
2912
- 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 = {
2913
- ...baseConfig,
2914
- threshold: validatedThreshold,
2915
- opacity: validatedOpacity * hoverIntensity * activeIntensity,
2916
- contrast: Math.min(1.6, validatedContrast + .1 * mouseInfluence),
2917
- brightness: Math.min(1.1, validatedBrightness + .05 * mouseInfluence),
2918
- saturationBoost: validatedSaturationBoost
2919
- };
2920
- // Validate and apply object config values with proper clamping
2921
- return "undefined" == typeof process || process.env, finalConfig;
2922
- }
2923
- // Debug logging for non-object configs
2924
- return "undefined" == typeof process || process.env, baseConfig;
2925
- }), [ overLight, getEffectiveOverLight, mouseOffset, isHovered, isActive, validateConfigValue, debugOverLight ]), handleMouseEnter = React.useCallback((() => setIsHovered(!0)), []), handleMouseLeave = React.useCallback((() => setIsHovered(!1)), []), handleMouseDown = React.useCallback((() => setIsActive(!0)), []), handleMouseUp = React.useCallback((() => setIsActive(!1)), []), handleKeyDown = React.useCallback((e => {
3044
+ }), [ handleGlobalMousePosition, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects ]),
3045
+ // Also call updateStyles on other state changes (hover, active, etc)
3046
+ React.useEffect((() => {
3047
+ updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
3048
+ mouseOffset: externalMouseOffset || internalMouseOffsetRef.current,
3049
+ globalMousePosition: externalGlobalMousePosition || internalGlobalMousePositionRef.current,
3050
+ glassSize: glassSize,
3051
+ isHovered: isHovered,
3052
+ isActive: isActive,
3053
+ isOverLight: baseOverLightConfig.isOverLight,
3054
+ baseOverLightConfig: baseOverLightConfig,
3055
+ effectiveBorderRadius: effectiveBorderRadius,
3056
+ effectiveWithoutEffects: effectiveWithoutEffects,
3057
+ effectiveReducedMotion: effectiveReducedMotion,
3058
+ elasticity: elasticity,
3059
+ directionalScale: directionalScale,
3060
+ onClick: onClick,
3061
+ withLiquidBlur: withLiquidBlur,
3062
+ blurAmount: blurAmount,
3063
+ saturation: saturation,
3064
+ padding: padding
3065
+ });
3066
+ }), [ isHovered, isActive, glassSize, baseOverLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, directionalScale, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation, padding, onClick ]);
3067
+ // Event handlers
3068
+ const handleMouseEnter = React.useCallback((() => setIsHovered(!0)), []), handleMouseLeave = React.useCallback((() => setIsHovered(!1)), []), handleMouseDown = React.useCallback((() => setIsActive(!0)), []), handleMouseUp = React.useCallback((() => setIsActive(!1)), []), handleMouseMove = React.useCallback((_e => {}), []), handleKeyDown = React.useCallback((e => {
2926
3069
  !onClick || "Enter" !== e.key && " " !== e.key || (e.preventDefault(), onClick());
2927
- }), [ onClick ]), handleMouseMove = React.useCallback((_e => {}), []);
2928
- /**
2929
- * Validate and clamp a numeric config value
2930
- * @param value - The value to validate
2931
- * @param min - Minimum allowed value
2932
- * @param max - Maximum allowed value
2933
- * @param defaultValue - Default value if validation fails
2934
- * @returns Validated and clamped value
2935
- */ return {
2936
- // State
3070
+ }), [ onClick ]);
3071
+ return {
2937
3072
  isHovered: isHovered,
2938
3073
  isActive: isActive,
2939
3074
  glassSize: glassSize,
2940
- dynamicCornerRadius: dynamicCornerRadius,
2941
- effectiveCornerRadius: effectiveCornerRadius,
3075
+ dynamicBorderRadius: dynamicBorderRadius,
3076
+ effectiveBorderRadius: effectiveBorderRadius,
2942
3077
  effectiveReducedMotion: effectiveReducedMotion,
2943
3078
  effectiveHighContrast: effectiveHighContrast,
2944
- effectiveDisableEffects: effectiveDisableEffects,
3079
+ effectiveWithoutEffects: effectiveWithoutEffects,
2945
3080
  detectedOverLight: detectedOverLight,
2946
3081
  globalMousePosition: globalMousePosition,
3082
+ // This is now static (refs or props) unless prop changes
2947
3083
  mouseOffset: mouseOffset,
2948
- // OverLight config
3084
+ // This is now static (refs or props) unless prop changes
2949
3085
  overLightConfig: overLightConfig,
2950
- // Transform calculations
2951
3086
  elasticTranslation: elasticTranslation,
2952
3087
  directionalScale: directionalScale,
2953
3088
  transformStyle: transformStyle,
2954
- // Event handlers
2955
3089
  handleMouseEnter: handleMouseEnter,
2956
3090
  handleMouseLeave: handleMouseLeave,
2957
3091
  handleMouseDown: handleMouseDown,
@@ -2990,7 +3124,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2990
3124
  *
2991
3125
  * @example
2992
3126
  * // Manual border-radius override
2993
- * <AtomixGlass cornerRadius={20}>
3127
+ * <AtomixGlass borderRadius={20}>
2994
3128
  * <div>Content with 20px glass radius</div>
2995
3129
  * </AtomixGlass>
2996
3130
  *
@@ -3031,37 +3165,48 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
3031
3165
  * <AtomixGlass overLight="auto" debugOverLight={true}>
3032
3166
  * <div>Content with debug logging enabled</div>
3033
3167
  * </AtomixGlass>
3034
- */ 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}) {
3035
- const glassRef = React.useRef(null), contentRef = React.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({
3168
+ */ 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}) {
3169
+ const glassRef = React.useRef(null), contentRef = React.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({
3036
3170
  glassRef: glassRef,
3037
3171
  contentRef: contentRef,
3038
- cornerRadius: cornerRadius,
3172
+ borderRadius: borderRadius,
3039
3173
  globalMousePosition: externalGlobalMousePosition,
3040
3174
  mouseOffset: externalMouseOffset,
3041
3175
  mouseContainer: mouseContainer,
3042
3176
  overLight: overLight,
3043
3177
  reducedMotion: reducedMotion,
3044
3178
  highContrast: highContrast,
3045
- disableEffects: disableEffects,
3179
+ withoutEffects: withoutEffects,
3046
3180
  elasticity: elasticity,
3047
3181
  onClick: onClick,
3048
- debugCornerRadius: debugCornerRadius,
3182
+ debugBorderRadius: debugBorderRadius,
3049
3183
  debugOverLight: debugOverLight,
3050
- enablePerformanceMonitoring: enablePerformanceMonitoring,
3051
- children: children
3052
- }), isOverLight = React.useMemo((() => overLightConfig?.isOverLight), [ overLight ]), shouldRenderOverLightLayers = enableOverLightLayers && isOverLight, baseStyle = {
3184
+ debugPerformance: debugPerformance,
3185
+ children: children,
3186
+ blurAmount: blurAmount,
3187
+ saturation: saturation,
3188
+ withLiquidBlur: withLiquidBlur,
3189
+ padding: padding,
3190
+ style: style
3191
+ }), isOverLight = React.useMemo((() => overLightConfig?.isOverLight), [ overLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, baseStyle = {
3053
3192
  ...style,
3054
- ...!effectiveDisableEffects && {
3193
+ ...!effectiveWithoutEffects && {
3055
3194
  transform: transformStyle
3056
3195
  }
3057
- }, 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 = React.useMemo((() => ({
3196
+ }, 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 = React.useMemo((() => ({
3058
3197
  position: style.position || "absolute",
3059
3198
  top: style.top || 0,
3060
3199
  left: style.left || 0
3061
- })), [ style.position, style.top, style.left ]), adjustedSize = React.useMemo((() => ({
3062
- width: "fixed" !== style.position ? "100%" : style.width ? style.width : Math.max(glassSize.width, 0),
3063
- height: "fixed" !== style.position ? "100%" : style.height ? style.height : Math.max(glassSize.height, 0)
3064
- })), [ style.position, style.width, style.height, glassSize.width, glassSize.height ]), gradientValues = React.useMemo((() => {
3200
+ })), [ style.position, style.top, style.left ]), adjustedSize = React.useMemo((() => {
3201
+ const resolveSize = (propValue, styleValue, measuredSize) => {
3202
+ const explicitSize = propValue ?? styleValue;
3203
+ return void 0 !== explicitSize ? "number" == typeof explicitSize ? `${explicitSize}px` : explicitSize : "fixed" === positionStyles.position ? `${Math.max(measuredSize, 0)}px` : "100%";
3204
+ };
3205
+ return {
3206
+ width: resolveSize(width, style.width, glassSize.width),
3207
+ height: resolveSize(height, style.height, glassSize.height)
3208
+ };
3209
+ }), [ width, height, style.width, style.height, positionStyles.position, glassSize.width, glassSize.height ]), gradientValues = React.useMemo((() => {
3065
3210
  const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT;
3066
3211
  return {
3067
3212
  borderGradientAngle: GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER,
@@ -3103,13 +3248,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
3103
3248
  }), [ isHovered, isActive, isOverLight, overLightConfig.opacity ]), glassVars = React.useMemo((() => {
3104
3249
  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;
3105
3250
  return {
3106
- "--atomix-glass-radius": `${effectiveCornerRadius}px`,
3251
+ "--atomix-glass-radius": `${effectiveBorderRadius}px`,
3107
3252
  "--atomix-glass-transform": transformStyle || "none",
3108
3253
  "--atomix-glass-position": positionStyles.position,
3109
3254
  "--atomix-glass-top": "fixed" !== positionStyles.top ? `${positionStyles.top}px` : "0",
3110
3255
  "--atomix-glass-left": "fixed" !== positionStyles.left ? `${positionStyles.left}px` : "0",
3111
- "--atomix-glass-width": "fixed" !== style.position ? adjustedSize.width : `${adjustedSize.width}px`,
3112
- "--atomix-glass-height": "fixed" !== style.position ? adjustedSize.height : `${adjustedSize.height}px`,
3256
+ "--atomix-glass-width": adjustedSize.width,
3257
+ "--atomix-glass-height": adjustedSize.height,
3113
3258
  "--atomix-glass-border-width": "var(--atomix-spacing-0-5, 0.09375rem)",
3114
3259
  "--atomix-glass-blend-mode": isOverLight ? "multiply" : "overlay",
3115
3260
  "--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%)`,
@@ -3125,24 +3270,25 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
3125
3270
  "--atomix-glass-overlay-opacity": opacityValues.over,
3126
3271
  "--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})`
3127
3272
  };
3128
- }), [ gradientValues, opacityValues, effectiveCornerRadius, transformStyle, positionStyles, adjustedSize, style.position, isOverLight, overLightConfig.borderOpacity ]), renderBackgroundLayer = layerType => jsxRuntime.jsx("div", {
3273
+ }), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle, positionStyles, adjustedSize, isOverLight, overLightConfig.borderOpacity ]), renderBackgroundLayer = layerType => jsxRuntime.jsx("div", {
3129
3274
  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(" "),
3130
3275
  style: {
3131
3276
  ...positionStyles,
3132
3277
  height: adjustedSize.height,
3133
3278
  width: adjustedSize.width,
3134
- borderRadius: `${effectiveCornerRadius}px`,
3279
+ borderRadius: `${effectiveBorderRadius}px`,
3135
3280
  transform: baseStyle.transform
3136
3281
  }
3137
3282
  });
3138
3283
  return jsxRuntime.jsxs("div", {
3284
+ ...rest,
3139
3285
  className: componentClassName,
3140
3286
  style: glassVars,
3141
3287
  role: role || (onClick ? "button" : void 0),
3142
3288
  tabIndex: onClick ? tabIndex ?? 0 : tabIndex,
3143
3289
  "aria-label": ariaLabel,
3144
3290
  "aria-describedby": ariaDescribedBy,
3145
- "aria-disabled": !(!onClick || !effectiveDisableEffects) || !onClick && void 0,
3291
+ "aria-disabled": !(!onClick || !effectiveWithoutEffects) || !onClick && void 0,
3146
3292
  "aria-pressed": !(!onClick || !isActive) || !onClick && void 0,
3147
3293
  onKeyDown: onClick ? handleKeyDown : void 0,
3148
3294
  children: [ jsxRuntime.jsx(AtomixGlassContainer, {
@@ -3150,18 +3296,18 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
3150
3296
  contentRef: contentRef,
3151
3297
  className: className,
3152
3298
  style: baseStyle,
3153
- cornerRadius: effectiveCornerRadius,
3154
- displacementScale: effectiveDisableEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
3155
- blurAmount: effectiveDisableEffects ? 0 : blurAmount,
3299
+ borderRadius: effectiveBorderRadius,
3300
+ displacementScale: effectiveWithoutEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
3301
+ blurAmount: effectiveWithoutEffects ? 0 : blurAmount,
3156
3302
  saturation: effectiveHighContrast ? ATOMIX_GLASS.CONSTANTS.SATURATION.HIGH_CONTRAST : isOverLight ? saturation * overLightConfig.saturationBoost : saturation,
3157
- aberrationIntensity: effectiveDisableEffects ? 0 : "shader" === mode ? aberrationIntensity * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_ABERRATION : aberrationIntensity,
3303
+ aberrationIntensity: effectiveWithoutEffects ? 0 : "shader" === mode ? aberrationIntensity * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_ABERRATION : aberrationIntensity,
3158
3304
  glassSize: glassSize,
3159
3305
  padding: padding,
3160
- mouseOffset: effectiveDisableEffects ? {
3306
+ mouseOffset: effectiveWithoutEffects ? {
3161
3307
  x: 0,
3162
3308
  y: 0
3163
3309
  } : mouseOffset,
3164
- globalMousePosition: effectiveDisableEffects ? {
3310
+ globalMousePosition: effectiveWithoutEffects ? {
3165
3311
  x: 0,
3166
3312
  y: 0
3167
3313
  } : globalMousePosition,
@@ -3181,11 +3327,11 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
3181
3327
  onClick: onClick,
3182
3328
  mode: mode,
3183
3329
  transform: baseStyle.transform,
3184
- effectiveDisableEffects: effectiveDisableEffects,
3330
+ effectiveWithoutEffects: effectiveWithoutEffects,
3185
3331
  effectiveReducedMotion: effectiveReducedMotion,
3186
3332
  shaderVariant: shaderVariant,
3187
3333
  elasticity: elasticity,
3188
- enableLiquidBlur: enableLiquidBlur,
3334
+ withLiquidBlur: withLiquidBlur,
3189
3335
  children: children
3190
3336
  }), Boolean(onClick) && jsxRuntime.jsxs(jsxRuntime.Fragment, {
3191
3337
  children: [ jsxRuntime.jsx("div", {
@@ -3207,11 +3353,19 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
3207
3353
  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}%)`
3208
3354
  }
3209
3355
  }) ]
3210
- }), enableBorderEffect && jsxRuntime.jsxs(jsxRuntime.Fragment, {
3356
+ }), withBorder && jsxRuntime.jsxs(jsxRuntime.Fragment, {
3211
3357
  children: [ jsxRuntime.jsx("span", {
3212
- className: ATOMIX_GLASS.BORDER_1_CLASS
3358
+ className: ATOMIX_GLASS.BORDER_1_CLASS,
3359
+ style: {
3360
+ width: glassSize.width,
3361
+ height: glassSize.height
3362
+ }
3213
3363
  }), jsxRuntime.jsx("span", {
3214
- className: ATOMIX_GLASS.BORDER_2_CLASS
3364
+ className: ATOMIX_GLASS.BORDER_2_CLASS,
3365
+ style: {
3366
+ width: glassSize.width,
3367
+ height: glassSize.height
3368
+ }
3215
3369
  }) ]
3216
3370
  }) ]
3217
3371
  });
@@ -3821,7 +3975,7 @@ const Badge = React.memo((({label: label, variant: variant = "primary", size: s
3821
3975
  // Default glass settings for badges
3822
3976
  const defaultGlassProps = {
3823
3977
  displacementScale: 20,
3824
- cornerRadius: ref.current?.getBoundingClientRect().width ? ref.current?.getBoundingClientRect().width / 2 : 16,
3978
+ borderRadius: ref.current?.getBoundingClientRect().width ? ref.current?.getBoundingClientRect().width / 2 : 16,
3825
3979
  className: "c-badge--glass",
3826
3980
  elasticity: 0
3827
3981
  }, glassProps = !0 === glass ? defaultGlassProps : {
@@ -3942,7 +4096,7 @@ const useBlock = () => ({
3942
4096
  * ```
3943
4097
  */ Block.displayName = "Block";
3944
4098
 
3945
- const BreadcrumbItem = React.forwardRef((({children: children, href: href, active: active, icon: icon, onClick: onClick, className: className = "", style: style, linkAs: LinkComponent, linkProps: linkProps = {}, ...props}, ref) => {
4099
+ const BreadcrumbItem = React.forwardRef((({children: children, href: href, active: active, icon: icon, onClick: onClick, className: className = "", style: style, linkAs: linkAs, linkProps: linkProps = {}, ...props}, ref) => {
3946
4100
  const itemClasses = [ BREADCRUMB.CLASSES.ITEM, active ? BREADCRUMB.CLASSES.ACTIVE : "", className ].filter(Boolean).join(" "), linkContent = jsxRuntime.jsxs(jsxRuntime.Fragment, {
3947
4101
  children: [ icon && jsxRuntime.jsx("span", {
3948
4102
  className: "c-breadcrumb__icon",
@@ -3954,20 +4108,18 @@ const BreadcrumbItem = React.forwardRef((({children: children, href: href, acti
3954
4108
  style: style,
3955
4109
  // Apply style to the link as per legacy behavior
3956
4110
  ...linkProps
3957
- };
4111
+ }, LinkComponent = linkAs;
3958
4112
  return jsxRuntime.jsx("li", {
3959
4113
  ref: ref,
3960
4114
  className: itemClasses,
3961
4115
  style: style,
3962
4116
  ...props,
3963
- children: href && !active ? LinkComponent ? (() => {
3964
- const Component = LinkComponent;
3965
- return jsxRuntime.jsx(Component, {
3966
- href: href,
3967
- ...commonLinkProps,
3968
- children: linkContent
3969
- });
3970
- })() : jsxRuntime.jsx("a", {
4117
+ children: href && !active ? linkAs && LinkComponent ? jsxRuntime.jsx(LinkComponent, {
4118
+ href: href,
4119
+ to: href,
4120
+ ...commonLinkProps,
4121
+ children: linkContent
4122
+ }) : jsxRuntime.jsx("a", {
3971
4123
  href: href,
3972
4124
  ...commonLinkProps,
3973
4125
  children: linkContent
@@ -3980,7 +4132,7 @@ const BreadcrumbItem = React.forwardRef((({children: children, href: href, acti
3980
4132
 
3981
4133
  BreadcrumbItem.displayName = "BreadcrumbItem";
3982
4134
 
3983
- const Breadcrumb = React.memo((({items: items, divider: divider, className: className = "", "aria-label": ariaLabel = "Breadcrumb", LinkComponent: LinkComponent, style: style, children: children}) => {
4135
+ const Breadcrumb = React.memo((function({items: items, divider: divider, className: className = "", "aria-label": ariaLabel = "Breadcrumb", LinkComponent: LinkComponent, style: style, children: children}) {
3984
4136
  const breadcrumbClasses = [ BREADCRUMB.CLASSES.BASE, className ].filter(Boolean).join(" ");
3985
4137
  let content;
3986
4138
  if (items && items.length > 0)
@@ -4002,12 +4154,12 @@ const Breadcrumb = React.memo((({items: items, divider: divider, className: cla
4002
4154
  const childrenCount = React.Children.count(children);
4003
4155
  content = React.Children.map(children, ((child, index) => {
4004
4156
  if ( React.isValidElement(child)) {
4005
- const isLast = index === childrenCount - 1, childProps = child.props;
4157
+ const isLast = index === childrenCount - 1, childProps = child.props, {active: active, linkAs: linkAs, ...otherProps} = childProps, newProps = {
4158
+ active: active ?? (!!isLast || void 0),
4159
+ linkAs: linkAs ?? LinkComponent
4160
+ };
4006
4161
 
4007
- return React.cloneElement(child, {
4008
- active: childProps.active ?? (!!isLast || void 0),
4009
- linkAs: childProps.linkAs ?? LinkComponent
4010
- });
4162
+ return React.cloneElement(child, newProps);
4011
4163
  }
4012
4164
  return child;
4013
4165
  }));
@@ -4074,7 +4226,7 @@ const Spinner = React.memo((({size: size = "md", variant: variant = "primary",
4074
4226
  const defaultGlassProps = {
4075
4227
  displacementScale: 20,
4076
4228
  blurAmount: 1,
4077
- cornerRadius: 999,
4229
+ borderRadius: 999,
4078
4230
  mode: "shader"
4079
4231
  }, glassProps = !0 === glass ? defaultGlassProps : {
4080
4232
  ...defaultGlassProps,
@@ -4238,6 +4390,7 @@ const Button = React__default.default.memo( React.forwardRef((({label: label, c
4238
4390
  ref: ref,
4239
4391
  // LinkComponent usually forwards ref to anchor
4240
4392
  href: href,
4393
+ to: href,
4241
4394
  target: target,
4242
4395
  rel: "_blank" === target ? "noopener noreferrer" : void 0
4243
4396
  };
@@ -4471,7 +4624,7 @@ const Callout = React.memo((({title: title, children: children, icon: icon, var
4471
4624
  // Default glass settings for callouts
4472
4625
  const defaultGlassProps = {
4473
4626
  displacementScale: 30,
4474
- cornerRadius: 8,
4627
+ borderRadius: 8,
4475
4628
  elasticity: 0
4476
4629
  }, glassProps = !0 === glass ? defaultGlassProps : {
4477
4630
  ...defaultGlassProps,
@@ -4493,7 +4646,7 @@ const Callout = React.memo((({title: title, children: children, icon: icon, var
4493
4646
  children: jsxRuntime.jsx("div", {
4494
4647
  className: "c-callout__glass-content",
4495
4648
  style: {
4496
- borderRadius: glassProps.cornerRadius
4649
+ borderRadius: glassProps.borderRadius
4497
4650
  },
4498
4651
  children: calloutContent
4499
4652
  })
@@ -4532,6 +4685,8 @@ active: active = !1, disabled: disabled = !1, loading: loading = !1, selected: s
4532
4685
  header: header, image: image, imageAlt: imageAlt = "", title: title, text: text, actions: actions, icon: icon, footer: footer, children: children,
4533
4686
  // Interaction
4534
4687
  onClick: onClick, onHover: onHover, onFocus: onFocus, href: href, target: target,
4688
+ // Custom Link
4689
+ LinkComponent: LinkComponent,
4535
4690
  // Glass
4536
4691
  glass: glass,
4537
4692
  // Accessibility
@@ -4615,7 +4770,19 @@ className: className = "", style: style, ...rest}, ref) => {
4615
4770
  };
4616
4771
  // Render as anchor if href is provided
4617
4772
  if (href && !isDisabled) {
4618
- const anchorElement = jsxRuntime.jsx("a", {
4773
+ let anchorElement;
4774
+ if (LinkComponent) {
4775
+ const LinkComp = LinkComponent;
4776
+ anchorElement = jsxRuntime.jsx(LinkComp, {
4777
+ ...commonProps,
4778
+ ref: ref,
4779
+ href: href,
4780
+ to: href,
4781
+ target: target,
4782
+ rel: "_blank" === target ? "noopener noreferrer" : void 0,
4783
+ children: cardContent
4784
+ });
4785
+ } else anchorElement = jsxRuntime.jsx("a", {
4619
4786
  ...commonProps,
4620
4787
  ref: ref,
4621
4788
  href: href,
@@ -5179,12 +5346,22 @@ function useChart(initialProps) {
5179
5346
  left: 40
5180
5347
  }, config) => {
5181
5348
  if (!datasets || 0 === datasets.length) return null;
5182
- // Flatten all data points to find min/max values
5183
- const allDataPoints = datasets.flatMap((dataset => dataset.data));
5184
- if (0 === allDataPoints.length) return null;
5185
- const minValue = Math.min(...allDataPoints.map((point => point.value))), maxValue = Math.max(...allDataPoints.map((point => point.value))), valueRange = maxValue - minValue || 1, innerWidth = width - padding.left - padding.right, innerHeight = height - padding.top - padding.bottom;
5186
- return {
5187
- xScale: (index, dataLength = allDataPoints.length) => dataLength <= 1 ? padding.left + innerWidth / 2 : padding.left + index / (dataLength - 1) * innerWidth,
5349
+ // Calculate total points and min/max values efficiently avoiding spread operator
5350
+ let totalPoints = 0, minValue = 1 / 0, maxValue = -1 / 0, hasValidData = !1;
5351
+ for (const dataset of datasets) if (dataset.data) {
5352
+ totalPoints += dataset.data.length;
5353
+ const {min: min, max: max, hasValid: hasValid} = getDatasetBounds(dataset.data);
5354
+ hasValid && (min < minValue && (minValue = min), max > maxValue && (maxValue = max),
5355
+ hasValidData = !0);
5356
+ }
5357
+ if (0 === totalPoints) return null;
5358
+ // Handle case with no valid numeric data
5359
+ hasValidData || (minValue = 0, maxValue = 0);
5360
+ const valueRange = maxValue - minValue || 1, innerWidth = width - padding.left - padding.right, innerHeight = height - padding.top - padding.bottom;
5361
+ // Avoid division by zero
5362
+ // Apply padding
5363
+ return {
5364
+ xScale: (index, dataLength = totalPoints) => dataLength <= 1 ? padding.left + innerWidth / 2 : padding.left + index / (dataLength - 1) * innerWidth,
5188
5365
  yScale: value => padding.top + innerHeight - (value - minValue) / valueRange * innerHeight,
5189
5366
  minValue: minValue,
5190
5367
  maxValue: maxValue,
@@ -5239,6 +5416,29 @@ function useChart(initialProps) {
5239
5416
 
5240
5417
  /**
5241
5418
  * Hook for chart data processing and transformation
5419
+ */
5420
+ /**
5421
+ * Helper to calculate min/max values from a dataset efficiently
5422
+ * avoiding spread operator which can cause stack overflow on large arrays
5423
+ */
5424
+ function getDatasetBounds(data) {
5425
+ let min = 1 / 0, max = -1 / 0, hasValid = !1;
5426
+ if (data && data.length > 0) for (let i = 0; i < data.length; i++) {
5427
+ const point = data[i];
5428
+ if (point && "number" == typeof point.value) {
5429
+ const val = point.value;
5430
+ val < min && (min = val), val > max && (max = val), hasValid = !0;
5431
+ }
5432
+ }
5433
+ return {
5434
+ min: min,
5435
+ max: max,
5436
+ hasValid: hasValid
5437
+ };
5438
+ }
5439
+
5440
+ /**
5441
+ * Hook for managing chart toolbar state and generating chart-specific configurations
5242
5442
  */ const ChartToolbar = React.memo( React.forwardRef((({chartType: chartType = "line", groups: groups = [], enableDefaults: enableDefaults = !0, defaults: defaults = {
5243
5443
  refresh: !0,
5244
5444
  export: !0,
@@ -5659,11 +5859,7 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
5659
5859
  onZoomReset: handleZoomReset,
5660
5860
  onPanToggle: handlePanToggle,
5661
5861
  onReset: handleReset
5662
- })), [ onRefresh, onExport, handleFullscreenChange, handleZoomIn, handleZoomOut, handleZoomReset, handlePanToggle, handleReset ]), {state: toolbarState, handlers: toolbarHandlers, toolbarGroups: toolbarGroups} =
5663
- /**
5664
- * Hook for managing chart toolbar state and generating chart-specific configurations
5665
- */
5666
- function(chartType, config = {}, handlers = {}) {
5862
+ })), [ onRefresh, onExport, handleFullscreenChange, handleZoomIn, handleZoomOut, handleZoomReset, handlePanToggle, handleReset ]), {state: toolbarState, handlers: toolbarHandlers, toolbarGroups: toolbarGroups} = function(chartType, config = {}, handlers = {}) {
5667
5863
  const [state, setState] = React.useState({
5668
5864
  isFullscreen: !1,
5669
5865
  isExporting: !1,
@@ -6048,16 +6244,16 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
6048
6244
  aberrationIntensity: 1.5,
6049
6245
  elasticity: 0,
6050
6246
  // No elastic effect for charts
6051
- enableLiquidBlur: !1,
6247
+ withLiquidBlur: !1,
6052
6248
  // Keep it simple
6053
- enableBorderEffect: !0,
6249
+ withBorder: !0,
6054
6250
  mode: "standard",
6055
6251
  mouseContainer: chartContainerRef,
6056
6252
  reducedMotion: !1
6057
6253
  })), []), glassProps = React.useMemo((() => glass ? !0 === glass ? defaultChartGlassProps : {
6058
6254
  ...defaultChartGlassProps,
6059
6255
  ...glass
6060
- } : null), [ glass, defaultChartGlassProps ]), chartBorderRadius = React.useMemo((() => glassProps?.cornerRadius || void 0), [ glassProps?.cornerRadius ]), chartContextValue = React.useMemo((() => ({
6256
+ } : null), [ glass, defaultChartGlassProps ]), chartBorderRadius = React.useMemo((() => glassProps?.borderRadius || void 0), [ glassProps?.borderRadius ]), chartContextValue = React.useMemo((() => ({
6061
6257
  zoomLevel: zoomLevel,
6062
6258
  panOffset: panOffset,
6063
6259
  panEnabled: panEnabled,
@@ -6188,7 +6384,7 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
6188
6384
  }) ]
6189
6385
  }), wrappedChart = glassProps ? jsxRuntime.jsx(AtomixGlass, {
6190
6386
  ...glassProps,
6191
- cornerRadius: chartBorderRadius,
6387
+ borderRadius: chartBorderRadius,
6192
6388
  style: {
6193
6389
  width: "100%",
6194
6390
  height: "100%",
@@ -6241,7 +6437,13 @@ const ChartRenderer = React.memo( React.forwardRef((({datasets: datasets = [],
6241
6437
  // Get chart context (zoom/pan state from toolbar) - optional
6242
6438
  // Always call useContext to maintain consistent hook order
6243
6439
  const chartContext = React.useContext(ChartContext), {calculateScales: calculateScales, getChartColors: getChartColors} = useChart(), {processedData: processedData, isProcessing: isProcessing} = function(datasets, options) {
6244
- const [processedData, setProcessedData] = React.useState(datasets), [isProcessing, setIsProcessing] = React.useState(!1), {enableDecimation: enableDecimation = !1, maxDataPoints: maxDataPoints = 1e3, enableRealTime: enableRealTime = !1, realTimeInterval: realTimeInterval = 1e3} = options || {}, decimateData = React.useCallback(((data, maxPoints) => {
6440
+ const [processedData, setProcessedData] = React.useState(datasets), [isProcessing, setIsProcessing] = React.useState(!1), {enableDecimation: enableDecimation = !1, maxDataPoints: maxDataPoints = 1e3, enableRealTime: enableRealTime = !1, realTimeInterval: realTimeInterval = 1e3} = options || {}, lastDataSignature = React.useRef(""), getDatasetSignature = React.useCallback((data => data.map((d => `${d.label}:${JSON.stringify(d.data)}`)).join("|")), []);
6441
+ // Update signature when processedData changes (e.g. via props)
6442
+ React.useEffect((() => {
6443
+ lastDataSignature.current = getDatasetSignature(processedData);
6444
+ }), [ processedData, getDatasetSignature ]);
6445
+ // Data decimation for performance
6446
+ const decimateData = React.useCallback(((data, maxPoints) => {
6245
6447
  if (!enableDecimation || !data.length) return data;
6246
6448
  const dataLength = data[0]?.data?.length || 0;
6247
6449
  if (dataLength <= maxPoints) return data;
@@ -6261,10 +6463,17 @@ const ChartRenderer = React.memo( React.forwardRef((({datasets: datasets = [],
6261
6463
  }), []), calculateTrendLine = React.useCallback((values => {
6262
6464
  const n = values.length;
6263
6465
  if (n < 2) return values.map((() => null));
6264
- const xSum = _reduceInstanceProperty(values).call(values, ((sum, _, i) => sum + i), 0), ySum = _reduceInstanceProperty(values).call(values, ((sum, val) => sum + val), 0), slope = (n * _reduceInstanceProperty(values).call(values, ((sum, val, i) => sum + i * val), 0) - xSum * ySum) / (n * _reduceInstanceProperty(values).call(values, ((sum, _, i) => sum + i * i), 0) - xSum * xSum), intercept = (ySum - slope * xSum) / n;
6466
+ let xSum = 0, ySum = 0, xySum = 0, x2Sum = 0;
6467
+ for (let i = 0; i < n; i++) {
6468
+ const val = values[i], safeVal = "number" == typeof val ? val : 0;
6469
+ // Treat null/undefined as 0 to match original reduce behavior
6470
+ xSum += i, ySum += safeVal, xySum += i * safeVal, x2Sum += i * i;
6471
+ }
6472
+ const slope = (n * xySum - xSum * ySum) / (n * x2Sum - xSum * xSum), intercept = (ySum - slope * xSum) / n;
6265
6473
  return values.map(((_, i) => slope * i + intercept));
6266
6474
  }), []);
6267
- // Process data when datasets change
6475
+ // Moving average calculation
6476
+ // Process data when datasets change
6268
6477
  return React.useEffect((() => {
6269
6478
  setIsProcessing(!0), (async () => {
6270
6479
  let processed = [ ...datasets ];
@@ -6276,11 +6485,12 @@ const ChartRenderer = React.memo( React.forwardRef((({datasets: datasets = [],
6276
6485
  React.useEffect((() => {
6277
6486
  if (!enableRealTime) return;
6278
6487
  const interval = setInterval((() => {
6279
- setProcessedData((prev => [ ...prev ]));
6280
- // Trigger re-render for real-time updates
6281
- }), realTimeInterval);
6488
+ setProcessedData((prev =>
6489
+ // Only trigger update if signature changed
6490
+ getDatasetSignature(prev) === lastDataSignature.current ? prev : [ ...prev ]));
6491
+ }), realTimeInterval);
6282
6492
  return () => clearInterval(interval);
6283
- }), [ enableRealTime, realTimeInterval ]), {
6493
+ }), [ enableRealTime, realTimeInterval, getDatasetSignature ]), {
6284
6494
  processedData: processedData,
6285
6495
  isProcessing: isProcessing,
6286
6496
  decimateData: decimateData,
@@ -6301,12 +6511,12 @@ const ChartRenderer = React.memo( React.forwardRef((({datasets: datasets = [],
6301
6511
  */
6302
6512
  function(datasets, options) {
6303
6513
  const {enableVirtualization: enableVirtualization = !1, enableMemoization: enableMemoization = !0, debounceMs: debounceMs = 100} = options || {}, [isOptimizing, setIsOptimizing] = React.useState(!1), debounceRef = React.useRef(null), memoizedScales = React.useMemo((() => enableMemoization ? datasets.map((dataset => {
6304
- const values = dataset.data?.map((d => d.value)).filter((v => "number" == typeof v)) || [], validValues = values.length > 0 ? values : [ 0 ];
6514
+ const {min: min, max: max, hasValid: hasValid} = getDatasetBounds(dataset.data);
6305
6515
  return {
6306
6516
  label: dataset.label,
6307
6517
  dataLength: dataset.data?.length || 0,
6308
- minValue: Math.min(...validValues),
6309
- maxValue: Math.max(...validValues)
6518
+ minValue: hasValid ? min : 0,
6519
+ maxValue: hasValid ? max : 0
6310
6520
  };
6311
6521
  })) : null), [ datasets, enableMemoization ]), debouncedUpdate = React.useCallback((callback => {
6312
6522
  debounceRef.current && clearTimeout(debounceRef.current), debounceRef.current = setTimeout((() => {
@@ -6405,8 +6615,8 @@ const ChartRenderer = React.memo( React.forwardRef((({datasets: datasets = [],
6405
6615
  const getAccessibleDescription = React.useCallback((() => {
6406
6616
  if (!datasets.length) return "Empty chart";
6407
6617
  const datasetDescriptions = datasets.map(((dataset, i) => {
6408
- const dataCount = dataset.data?.length || 0, values = dataset.data?.map((d => d.value)).filter((v => "number" == typeof v)) || [], min = values.length > 0 ? Math.min(...values) : 0, max = values.length > 0 ? Math.max(...values) : 0;
6409
- return `Dataset ${i + 1}: ${dataset.label}, ${dataCount} points, range ${min} to ${max}`;
6618
+ const dataCount = dataset.data?.length || 0, {min: min, max: max, hasValid: hasValid} = getDatasetBounds(dataset.data), minVal = hasValid ? min : 0, maxVal = hasValid ? max : 0;
6619
+ return `Dataset ${i + 1}: ${dataset.label}, ${dataCount} points, range ${minVal} to ${maxVal}`;
6410
6620
  })).join(". ");
6411
6621
  return `Chart with ${datasets.length} datasets. ${datasetDescriptions}`;
6412
6622
  }), [ datasets ]);
@@ -8656,14 +8866,14 @@ const ScatterChart = React.memo( React.forwardRef((({datasets: datasets = [], c
8656
8866
 
8657
8867
  ScatterChart.displayName = "ScatterChart";
8658
8868
 
8659
- const TreemapChart = React.memo( React.forwardRef((({data: data = [], algorithm: algorithm = "squarified", colorConfig: colorConfig = {
8869
+ const DEFAULT_COLOR_CONFIG = {
8660
8870
  scheme: "category"
8661
- }, labelConfig: labelConfig = {
8871
+ }, DEFAULT_LABEL_CONFIG = {
8662
8872
  showLabels: !0,
8663
8873
  minSize: 1e3,
8664
8874
  fontSize: 12,
8665
8875
  textColor: "white"
8666
- }, onDataPointClick: onDataPointClick, config: config = {}, ...props}, ref) => {
8876
+ }, DEFAULT_CONFIG = {}, TreemapChart = React.memo( React.forwardRef((({data: data = [], algorithm: algorithm = "squarified", colorConfig: colorConfig = DEFAULT_COLOR_CONFIG, labelConfig: labelConfig = DEFAULT_LABEL_CONFIG, onDataPointClick: onDataPointClick, config: config = DEFAULT_CONFIG, ...props}, ref) => {
8667
8877
  const [hoveredNode, setHoveredNode] = React.useState(null), [selectedNode, setSelectedNode] = React.useState(null);
8668
8878
  React.useState({
8669
8879
  x: 0,
@@ -8775,87 +8985,87 @@ const TreemapChart = React.memo( React.forwardRef((({data: data = [], algorithm
8775
8985
  remainingHeight -= rowHeight), currentRow = [];
8776
8986
  }
8777
8987
  }
8778
- }), []), datasets = [ {
8988
+ }), []), renderContent = React.useCallback((({scales: scales, colors: colors, datasets: renderedDatasets, handlers: handlers, hoveredPoint: hoveredPoint}) => {
8989
+ if (!data.length) return null;
8990
+ // Calculate available space with padding
8991
+ const availableWidth = scales.width - 40, availableHeight = scales.height - 40, leafNodes = data.filter((item => !item.children || 0 === item.children.length));
8992
+ if (!leafNodes.length) return null;
8993
+ const totalValue = _reduceInstanceProperty(leafNodes).call(leafNodes, ((sum, node) => sum + node.value), 0), treemapNodes = leafNodes.map(((item, index) => ({
8994
+ id: item.id,
8995
+ label: item.label,
8996
+ value: item.value,
8997
+ color: generateColor(item, 0, index) || "transparent",
8998
+ x: 0,
8999
+ // Will be calculated by squarify
9000
+ y: 0,
9001
+ // Will be calculated by squarify
9002
+ width: 0,
9003
+ // Will be calculated by squarify
9004
+ height: 0,
9005
+ // Will be calculated by squarify
9006
+ depth: 0,
9007
+ children: [],
9008
+ originalData: item
9009
+ })));
9010
+ // Create treemap nodes with proper dimensions
9011
+ // Apply squarified algorithm to layout nodes proportionally by value
9012
+ if ("squarified" === algorithm && totalValue > 0) squarify(treemapNodes, 20, 20, availableWidth, availableHeight); else {
9013
+ // Fallback: simple grid layout (equal sizes)
9014
+ const cols = Math.ceil(Math.sqrt(leafNodes.length)), rows = Math.ceil(leafNodes.length / cols), nodeWidth = availableWidth / cols, nodeHeight = availableHeight / rows;
9015
+ treemapNodes.forEach(((node, index) => {
9016
+ const col = index % cols, row = Math.floor(index / cols);
9017
+ node.x = 20 + col * nodeWidth, node.y = 20 + row * nodeHeight, node.width = nodeWidth,
9018
+ node.height = nodeHeight;
9019
+ }));
9020
+ }
9021
+ return jsxRuntime.jsx(jsxRuntime.Fragment, {
9022
+ children: treemapNodes.map((node => {
9023
+ const isHovered = hoveredNode === node, isSelected = selectedNode === node, area = node.width * node.height, showLabel = labelConfig.showLabels && area >= (labelConfig.minSize || 1e3);
9024
+ return jsxRuntime.jsxs("g", {
9025
+ children: [ jsxRuntime.jsx("rect", {
9026
+ x: node.x,
9027
+ y: node.y,
9028
+ width: node.width,
9029
+ height: node.height,
9030
+ fill: node.color,
9031
+ className: `c-chart__treemap-node ${isHovered ? "c-chart__treemap-node--hovered" : ""} ${isSelected ? "c-chart__treemap-node--selected" : ""}`,
9032
+ onClick: () => {
9033
+ setSelectedNode(node), handlers.onDataPointClick?.(node.originalData, 0, 0);
9034
+ },
9035
+ onMouseEnter: e => {
9036
+ setHoveredNode(node);
9037
+ const rect = e.currentTarget.getBoundingClientRect();
9038
+ handlers.onPointHover(0, 0, node.x, node.y, rect.left + rect.width / 2, rect.top + rect.height / 2);
9039
+ },
9040
+ onMouseLeave: () => {
9041
+ setHoveredNode(null), handlers.onPointLeave();
9042
+ }
9043
+ }), showLabel && jsxRuntime.jsx("text", {
9044
+ x: node.x + node.width / 2,
9045
+ y: node.y + node.height / 2,
9046
+ textAnchor: "middle",
9047
+ dominantBaseline: "middle",
9048
+ className: "c-chart__treemap-label",
9049
+ style: {
9050
+ fontSize: labelConfig.fontSize,
9051
+ fill: labelConfig.textColor
9052
+ },
9053
+ children: node.label
9054
+ }) ]
9055
+ }, node.id);
9056
+ }))
9057
+ });
9058
+ }), [ data, algorithm, generateColor, squarify, labelConfig, hoveredNode, selectedNode ]), datasets = React.useMemo((() => [ {
8779
9059
  label: "Treemap Data",
8780
9060
  data: data
8781
- } ];
9061
+ } ]), [ data ]);
8782
9062
  // Squarified treemap algorithm
8783
9063
  return jsxRuntime.jsx(BaseChart, {
8784
9064
  ref: ref,
8785
9065
  type: "treemap",
8786
9066
  datasets: datasets,
8787
9067
  config: config,
8788
- renderContent: ({scales: scales, colors: colors, datasets: renderedDatasets, handlers: handlers, hoveredPoint: hoveredPoint}) => {
8789
- if (!data.length) return null;
8790
- // Calculate available space with padding
8791
- const availableWidth = scales.width - 40, availableHeight = scales.height - 40, leafNodes = data.filter((item => !item.children || 0 === item.children.length));
8792
- if (!leafNodes.length) return null;
8793
- const totalValue = _reduceInstanceProperty(leafNodes).call(leafNodes, ((sum, node) => sum + node.value), 0), treemapNodes = leafNodes.map(((item, index) => ({
8794
- id: item.id,
8795
- label: item.label,
8796
- value: item.value,
8797
- color: generateColor(item, 0, index) || "transparent",
8798
- x: 0,
8799
- // Will be calculated by squarify
8800
- y: 0,
8801
- // Will be calculated by squarify
8802
- width: 0,
8803
- // Will be calculated by squarify
8804
- height: 0,
8805
- // Will be calculated by squarify
8806
- depth: 0,
8807
- children: [],
8808
- originalData: item
8809
- })));
8810
- // Create treemap nodes with proper dimensions
8811
- // Apply squarified algorithm to layout nodes proportionally by value
8812
- if ("squarified" === algorithm && totalValue > 0) squarify(treemapNodes, 20, 20, availableWidth, availableHeight); else {
8813
- // Fallback: simple grid layout (equal sizes)
8814
- const cols = Math.ceil(Math.sqrt(leafNodes.length)), rows = Math.ceil(leafNodes.length / cols), nodeWidth = availableWidth / cols, nodeHeight = availableHeight / rows;
8815
- treemapNodes.forEach(((node, index) => {
8816
- const col = index % cols, row = Math.floor(index / cols);
8817
- node.x = 20 + col * nodeWidth, node.y = 20 + row * nodeHeight, node.width = nodeWidth,
8818
- node.height = nodeHeight;
8819
- }));
8820
- }
8821
- return jsxRuntime.jsx(jsxRuntime.Fragment, {
8822
- children: treemapNodes.map((node => {
8823
- const isHovered = hoveredNode === node, isSelected = selectedNode === node, area = node.width * node.height, showLabel = labelConfig.showLabels && area >= (labelConfig.minSize || 1e3);
8824
- return jsxRuntime.jsxs("g", {
8825
- children: [ jsxRuntime.jsx("rect", {
8826
- x: node.x,
8827
- y: node.y,
8828
- width: node.width,
8829
- height: node.height,
8830
- fill: node.color,
8831
- className: `c-chart__treemap-node ${isHovered ? "c-chart__treemap-node--hovered" : ""} ${isSelected ? "c-chart__treemap-node--selected" : ""}`,
8832
- onClick: () => {
8833
- setSelectedNode(node), handlers.onDataPointClick?.(node.originalData, 0, 0);
8834
- },
8835
- onMouseEnter: e => {
8836
- setHoveredNode(node);
8837
- const rect = e.currentTarget.getBoundingClientRect();
8838
- handlers.onPointHover(0, 0, node.x, node.y, rect.left + rect.width / 2, rect.top + rect.height / 2);
8839
- },
8840
- onMouseLeave: () => {
8841
- setHoveredNode(null), handlers.onPointLeave();
8842
- }
8843
- }), showLabel && jsxRuntime.jsx("text", {
8844
- x: node.x + node.width / 2,
8845
- y: node.y + node.height / 2,
8846
- textAnchor: "middle",
8847
- dominantBaseline: "middle",
8848
- className: "c-chart__treemap-label",
8849
- style: {
8850
- fontSize: labelConfig.fontSize,
8851
- fill: labelConfig.textColor
8852
- },
8853
- children: node.label
8854
- }) ]
8855
- }, node.id);
8856
- }))
8857
- });
8858
- },
9068
+ renderContent: renderContent,
8859
9069
  onDataPointClick: onDataPointClick,
8860
9070
  interactive: !0,
8861
9071
  ...props
@@ -9543,7 +9753,7 @@ const range = (start, end) => {
9543
9753
  blurAmount: 1,
9544
9754
  saturation: 160,
9545
9755
  aberrationIntensity: .5,
9546
- cornerRadius: 8,
9756
+ borderRadius: 8,
9547
9757
  mode: "shader"
9548
9758
  }, glassProps = !0 === glass ? defaultGlassProps : {
9549
9759
  ...defaultGlassProps,
@@ -9614,7 +9824,7 @@ const Checkbox = React__default.default.memo( React.forwardRef((({label: label,
9614
9824
  blurAmount: 1,
9615
9825
  saturation: 160,
9616
9826
  aberrationIntensity: .3,
9617
- cornerRadius: 6,
9827
+ borderRadius: 6,
9618
9828
  mode: "shader"
9619
9829
  }, glassProps = !0 === glass ? defaultGlassProps : {
9620
9830
  ...defaultGlassProps,
@@ -9674,6 +9884,7 @@ const DropdownItem = React.memo((({children: children, href: href, active: acti
9674
9884
  close());
9675
9885
  }, itemClasses = [ "c-dropdown__menu-item", active ? "is-active" : "", disabled ? "is-disabled" : "", className ].filter(Boolean).join(" "), linkProps = {
9676
9886
  href: href,
9887
+ to: href,
9677
9888
  className: itemClasses,
9678
9889
  onClick: handleClick,
9679
9890
  role: "menuitem",
@@ -9712,13 +9923,32 @@ const DropdownItem = React.memo((({children: children, href: href, active: acti
9712
9923
  }), children ]
9713
9924
  })
9714
9925
  });
9715
- })), DropdownDivider = React.memo((({className: className = ""}) => jsxRuntime.jsx("li", {
9926
+ }));
9927
+
9928
+ DropdownItem.displayName = "DropdownItem";
9929
+
9930
+ /**
9931
+ * DropdownDivider component for separating groups of items
9932
+ */
9933
+ const DropdownDivider = React.memo((({className: className = ""}) => jsxRuntime.jsx("li", {
9716
9934
  className: `c-dropdown__divider ${className}`,
9717
9935
  role: "separator"
9718
- }))), DropdownHeader = React.memo((({children: children, className: className = ""}) => jsxRuntime.jsx("li", {
9936
+ })));
9937
+
9938
+ DropdownDivider.displayName = "DropdownDivider";
9939
+
9940
+ /**
9941
+ * DropdownHeader component for section headers
9942
+ */
9943
+ const DropdownHeader = React.memo((({children: children, className: className = ""}) => jsxRuntime.jsx("li", {
9719
9944
  className: `c-dropdown__header ${className}`,
9720
9945
  children: children
9721
- }))), DropdownStyleContext = React.createContext({}), Dropdown = React.memo((({children: children, menu: menu, placement: placement = "bottom-start", trigger: trigger = "click", offset: offset = DROPDOWN.DEFAULTS.OFFSET, isOpen: controlledIsOpen, onOpenChange: onOpenChange, closeOnClickOutside: closeOnClickOutside = !0, closeOnEscape: closeOnEscape = !0, maxHeight: maxHeight, minWidth: minWidth = DROPDOWN.DEFAULTS.MIN_WIDTH, variant: variant, className: className = "", style: style, glass: glass, ...props}) => {
9946
+ })));
9947
+
9948
+ DropdownHeader.displayName = "DropdownHeader";
9949
+
9950
+ // Helper context to pass glass prop to DropdownMenu
9951
+ const DropdownStyleContext = React.createContext({}), Dropdown = React.memo((function({children: children, menu: menu, placement: placement = "bottom-start", trigger: trigger = "click", offset: offset = DROPDOWN.DEFAULTS.OFFSET, isOpen: controlledIsOpen, onOpenChange: onOpenChange, closeOnClickOutside: closeOnClickOutside = !0, closeOnEscape: closeOnEscape = !0, maxHeight: maxHeight, minWidth: minWidth = DROPDOWN.DEFAULTS.MIN_WIDTH, variant: variant, className: className = "", style: style, glass: glass, ...props}) {
9722
9952
  // Set up controlled vs uncontrolled state
9723
9953
  const [uncontrolledIsOpen, setUncontrolledIsOpen] = React.useState(!1), isControlled = void 0 !== controlledIsOpen, isOpen = isControlled ? controlledIsOpen : uncontrolledIsOpen, dropdownRef = React.useRef(null), toggleRef = React.useRef(null), menuRef = React.useRef(null), dropdownId = React.useRef(`dropdown-${Math.random().toString(36).substring(2, 9)}`).current, setIsOpen = React.useCallback((nextIsOpen => {
9724
9954
  isControlled || setUncontrolledIsOpen(nextIsOpen), onOpenChange && onOpenChange(nextIsOpen);
@@ -9870,9 +10100,7 @@ const DropdownItem = React.memo((({children: children, href: href, active: acti
9870
10100
  });
9871
10101
  }));
9872
10102
 
9873
- /**
9874
- * DropdownDivider component for separating groups of items
9875
- */ Dropdown.displayName = "Dropdown", Dropdown.Trigger = DropdownTrigger, Dropdown.Menu = DropdownMenu,
10103
+ Dropdown.displayName = "Dropdown", Dropdown.Trigger = DropdownTrigger, Dropdown.Menu = DropdownMenu,
9876
10104
  Dropdown.Item = DropdownItem, Dropdown.Divider = DropdownDivider, Dropdown.Header = DropdownHeader;
9877
10105
 
9878
10106
  /**
@@ -11296,7 +11524,7 @@ const Input = React.memo( React.forwardRef((({type: type = "text", value: value
11296
11524
  blurAmount: 1,
11297
11525
  saturation: 180,
11298
11526
  aberrationIntensity: .2,
11299
- cornerRadius: 12,
11527
+ borderRadius: 12,
11300
11528
  mode: "shader"
11301
11529
  }, glassProps = !0 === glass ? defaultGlassProps : {
11302
11530
  ...defaultGlassProps,
@@ -11336,7 +11564,7 @@ function useHero(initialProps) {
11336
11564
  * @returns Slider state and methods
11337
11565
  */
11338
11566
  function(config) {
11339
- const {slides: slides, autoplay: autoplay, loop: loop = !0, transition: transition = "fade", transitionDuration: transitionDuration = 1e3} = config, [currentIndex, setCurrentIndex] = React.useState(0), [isTransitioning, setIsTransitioning] = React.useState(!1), autoplayRef = React.useRef(null), isPausedRef = React.useRef(!1), slideRefs = React.useMemo((() => slides.map((() => React__default.default.createRef()))), [ slides.length ]), videoRefs = React.useMemo((() => slides.map((() => React__default.default.createRef()))), [ slides.length ]), handleSlideTransition = React.useCallback((nextIndex => {
11567
+ const {slides: slides, autoplay: autoplay, loop: loop = !0, transition: transition = "fade", transitionDuration: transitionDuration = 1e3} = config, [currentIndex, setCurrentIndex] = React.useState(0), [isTransitioning, setIsTransitioning] = React.useState(!1), autoplayRef = React.useRef(null), isPausedRef = React.useRef(!1), callbackRef = React.useRef(), slideRefs = React.useMemo((() => slides.map((() => React__default.default.createRef()))), [ slides.length ]), videoRefs = React.useMemo((() => slides.map((() => React__default.default.createRef()))), [ slides.length ]), handleSlideTransition = React.useCallback((nextIndex => {
11340
11568
  if (nextIndex === currentIndex || isTransitioning) return;
11341
11569
  if (nextIndex < 0 || nextIndex >= slides.length) return;
11342
11570
  setIsTransitioning(!0),
@@ -11357,7 +11585,17 @@ function useHero(initialProps) {
11357
11585
  let nextIndex;
11358
11586
  nextIndex = loop ? (currentIndex + 1) % slides.length : Math.min(currentIndex + 1, slides.length - 1),
11359
11587
  handleSlideTransition(nextIndex);
11360
- }), [ currentIndex, slides.length, loop, handleSlideTransition ]), pauseAutoplay = React.useCallback((() => {
11588
+ }), [ currentIndex, slides.length, loop, handleSlideTransition ]);
11589
+ // Update callbackRef whenever nextSlide or isTransitioning changes
11590
+ React.useEffect((() => {
11591
+ callbackRef.current = () => {
11592
+ isPausedRef.current || isTransitioning || nextSlide();
11593
+ };
11594
+ }), [ nextSlide, isTransitioning ]);
11595
+ /**
11596
+ * Pause autoplay
11597
+ */
11598
+ const pauseAutoplay = React.useCallback((() => {
11361
11599
  isPausedRef.current = !0, autoplayRef.current && (clearInterval(autoplayRef.current),
11362
11600
  autoplayRef.current = null);
11363
11601
  }), []), resumeAutoplay = React.useCallback((() => {
@@ -11366,24 +11604,26 @@ function useHero(initialProps) {
11366
11604
  const delay = "object" == typeof autoplay ? autoplay.delay : 3e3;
11367
11605
  // Restart autoplay
11368
11606
  autoplayRef.current || (autoplayRef.current = setInterval((() => {
11369
- isPausedRef.current || isTransitioning || nextSlide();
11607
+ callbackRef.current && callbackRef.current();
11370
11608
  }), delay));
11371
11609
  }
11372
- }), [ autoplay, slides.length, nextSlide, isTransitioning ]);
11610
+ }), [ autoplay, slides.length ]);
11611
+ /**
11612
+ * Resume autoplay
11613
+ */
11373
11614
  // Autoplay effect
11374
11615
  return React.useEffect((() => {
11375
11616
  if (!autoplay || slides.length <= 1) return;
11376
11617
  const delay = "object" == typeof autoplay ? autoplay.delay : 3e3;
11377
- return "object" == typeof autoplay && autoplay.pauseOnHover,
11378
11618
  // Clear any existing interval
11379
- autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null),
11619
+ return autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null),
11380
11620
  // Start autoplay if not paused
11381
11621
  isPausedRef.current || (autoplayRef.current = setInterval((() => {
11382
- isPausedRef.current || isTransitioning || nextSlide();
11622
+ callbackRef.current && callbackRef.current();
11383
11623
  }), delay)), () => {
11384
11624
  autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null);
11385
11625
  };
11386
- }), [ autoplay, slides.length, nextSlide, isTransitioning ]),
11626
+ }), [ autoplay, slides.length ]),
11387
11627
  // Initialize first video if needed
11388
11628
  React.useEffect((() => {
11389
11629
  if (slides.length > 0 && "video" === slides[currentIndex]?.type) {
@@ -12382,7 +12622,14 @@ const DEFAULT_ATOMIX_FONTS = [ {
12382
12622
  }
12383
12623
 
12384
12624
  function useSlider(options) {
12385
- const {slides: slides, slidesToShow: slidesToShow = 1, spaceBetween: spaceBetween = 0, loop: loop = !1, initialSlide: initialSlide = 0, direction: direction = "horizontal", speed: speed = 300, allowTouchMove: allowTouchMove = !0, threshold: threshold = 50, autoplay: autoplay, onSlideChange: onSlideChange} = options, containerRef = React.useRef(null), wrapperRef = React.useRef(null), repositioningRef = React.useRef(!1), autoplayRef = React.useRef(null), [autoplayRunning, setAutoplayRunning] = React.useState(!1), [realIndex, setRealIndex] = React.useState(initialSlide), [internalIndex, setInternalIndex] = React.useState(0), [isTransitioning, setIsTransitioning] = React.useState(!1), [containerSize, setContainerSize] = React.useState(0), [touching, setTouching] = React.useState(!1), [touchStart, setTouchStart] = React.useState(0), [dragOffset, setDragOffset] = React.useState(0), slideWidth = React.useMemo((() => 0 === containerSize ? 0 : (containerSize - spaceBetween * (slidesToShow - 1)) / slidesToShow), [ containerSize, spaceBetween, slidesToShow ]), allSlides = React.useMemo((() => loop && 0 !== slides.length ? [ ...slides.map(((slide, i) => ({
12625
+ const {slides: slides, slidesToShow: slidesToShow = 1, spaceBetween: spaceBetween = 0, loop: loop = !1, initialSlide: initialSlide = 0, direction: direction = "horizontal", speed: speed = 300, allowTouchMove: allowTouchMove = !0, threshold: threshold = 50, autoplay: autoplay, onSlideChange: onSlideChange} = options, containerRef = React.useRef(null), wrapperRef = React.useRef(null), repositioningRef = React.useRef(!1), autoplayRef = React.useRef(null), [autoplayRunning, setAutoplayRunning] = React.useState(!1), sliderStateRef = React.useRef({
12626
+ isTransitioning: !1,
12627
+ loop: loop,
12628
+ slides: slides,
12629
+ slidesToShow: slidesToShow,
12630
+ speed: speed,
12631
+ onSlideChange: onSlideChange
12632
+ }), [realIndex, setRealIndex] = React.useState(initialSlide), [internalIndex, setInternalIndex] = React.useState(0), [isTransitioning, setIsTransitioning] = React.useState(!1), [containerSize, setContainerSize] = React.useState(0), [touching, setTouching] = React.useState(!1), [touchStart, setTouchStart] = React.useState(0), [dragOffset, setDragOffset] = React.useState(0), slideWidth = React.useMemo((() => 0 === containerSize ? 0 : (containerSize - spaceBetween * (slidesToShow - 1)) / slidesToShow), [ containerSize, spaceBetween, slidesToShow ]), allSlides = React.useMemo((() => loop && 0 !== slides.length ? [ ...slides.map(((slide, i) => ({
12386
12633
  ...slide,
12387
12634
  id: `set1-${slide.id || i}`
12388
12635
  }))), ...slides.map(((slide, i) => ({
@@ -12392,6 +12639,17 @@ function useSlider(options) {
12392
12639
  ...slide,
12393
12640
  id: `set3-${slide.id || i}`
12394
12641
  }))) ] : slides), [ slides, loop ]), loopedSlides = slides.length, translateValue = React.useMemo((() => 0 === slideWidth ? 0 : -internalIndex * slideWidth + dragOffset), [ slideWidth, internalIndex, dragOffset ]);
12642
+ // Update the ref whenever the relevant state/props change
12643
+ React.useEffect((() => {
12644
+ sliderStateRef.current = {
12645
+ isTransitioning: isTransitioning,
12646
+ loop: loop,
12647
+ slides: slides,
12648
+ slidesToShow: slidesToShow,
12649
+ speed: speed,
12650
+ onSlideChange: onSlideChange
12651
+ };
12652
+ }), [ isTransitioning, loop, slides, slidesToShow, speed, onSlideChange ]),
12395
12653
  // Autoplay effect
12396
12654
  React.useEffect((() => {
12397
12655
  if (!autoplay) return autoplayRef.current && (clearInterval(autoplayRef.current),
@@ -12403,32 +12661,34 @@ function useSlider(options) {
12403
12661
  autoplayRef.current && clearInterval(autoplayRef.current),
12404
12662
  // Create new interval
12405
12663
  autoplayRef.current = setInterval((() => {
12664
+ // Use ref to get the latest state without resetting the interval
12665
+ const {isTransitioning: currentIsTransitioning, loop: currentLoop, slides: currentSlides, slidesToShow: currentSlidesToShow, speed: currentSpeed, onSlideChange: currentOnSlideChange} = sliderStateRef.current;
12406
12666
  // We need to use a functional update to get the latest values
12407
- setRealIndex((prevRealIndex => {
12408
- if (isTransitioning) return prevRealIndex;
12667
+ setRealIndex((prevRealIndex => {
12668
+ if (currentIsTransitioning) return prevRealIndex;
12409
12669
  // Stop autoplay on interaction if disableOnInteraction is true
12410
12670
  let nextIndex;
12411
12671
  // Trigger the slide change
12412
12672
  if (disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
12413
- autoplayRef.current = null, setAutoplayRunning(!1)), nextIndex = loop ? (prevRealIndex + 1) % slides.length : Math.min(prevRealIndex + 1, slides.length - slidesToShow),
12673
+ autoplayRef.current = null, setAutoplayRunning(!1)), nextIndex = currentLoop ? (prevRealIndex + 1) % currentSlides.length : Math.min(prevRealIndex + 1, currentSlides.length - currentSlidesToShow),
12414
12674
  reverseDirection) {
12415
12675
  // For reverse direction, we would go to previous slide
12416
- const prevIndex = loop ? 0 === prevRealIndex ? slides.length - 1 : prevRealIndex - 1 : Math.max(prevRealIndex - 1, 0);
12417
- return setInternalIndex(loop ? slides.length + prevIndex : prevIndex), setIsTransitioning(!0),
12418
- setDragOffset(0), setTimeout((() => {
12419
- setIsTransitioning(!1), onSlideChange?.(prevIndex);
12420
- }), speed), prevIndex;
12676
+ const prevIndex = currentLoop ? 0 === prevRealIndex ? currentSlides.length - 1 : prevRealIndex - 1 : Math.max(prevRealIndex - 1, 0);
12677
+ return setInternalIndex(currentLoop ? currentSlides.length + prevIndex : prevIndex),
12678
+ setIsTransitioning(!0), setDragOffset(0), setTimeout((() => {
12679
+ setIsTransitioning(!1), currentOnSlideChange?.(prevIndex);
12680
+ }), currentSpeed), prevIndex;
12421
12681
  }
12422
12682
  // Normal direction
12423
- return setInternalIndex(loop ? slides.length + nextIndex : nextIndex), setIsTransitioning(!0),
12424
- setDragOffset(0), setTimeout((() => {
12425
- setIsTransitioning(!1), onSlideChange?.(nextIndex),
12683
+ return setInternalIndex(currentLoop ? currentSlides.length + nextIndex : nextIndex),
12684
+ setIsTransitioning(!0), setDragOffset(0), setTimeout((() => {
12685
+ setIsTransitioning(!1), currentOnSlideChange?.(nextIndex),
12426
12686
  // Reposition after transition ends for looped sliders
12427
- loop && nextIndex >= 2 * slides.length && (repositioningRef.current = !0, setInternalIndex(slides.length + nextIndex),
12428
- setTimeout((() => {
12687
+ currentLoop && nextIndex >= 2 * currentSlides.length && (repositioningRef.current = !0,
12688
+ setInternalIndex(currentSlides.length + nextIndex), setTimeout((() => {
12429
12689
  repositioningRef.current = !1;
12430
12690
  }), 0));
12431
- }), speed), nextIndex;
12691
+ }), currentSpeed), nextIndex;
12432
12692
  }));
12433
12693
  }), delay), setAutoplayRunning(!0);
12434
12694
  // Handle pause on mouse enter/leave if enabled
@@ -12439,17 +12699,18 @@ function useSlider(options) {
12439
12699
  }, handleMouseLeave = () => {
12440
12700
  // Restart autoplay
12441
12701
  autoplayRef.current && clearInterval(autoplayRef.current), autoplayRef.current = setInterval((() => {
12702
+ const {isTransitioning: currentIsTransitioning, loop: currentLoop, slides: currentSlides, slidesToShow: currentSlidesToShow, speed: currentSpeed, onSlideChange: currentOnSlideChange} = sliderStateRef.current;
12442
12703
  setRealIndex((prevRealIndex => {
12443
- if (isTransitioning) return prevRealIndex;
12704
+ if (currentIsTransitioning) return prevRealIndex;
12444
12705
  let nextIndex;
12445
- return nextIndex = loop ? (prevRealIndex + 1) % slides.length : Math.min(prevRealIndex + 1, slides.length - slidesToShow),
12446
- setInternalIndex(loop ? slides.length + nextIndex : nextIndex), setIsTransitioning(!0),
12706
+ return nextIndex = currentLoop ? (prevRealIndex + 1) % currentSlides.length : Math.min(prevRealIndex + 1, currentSlides.length - currentSlidesToShow),
12707
+ setInternalIndex(currentLoop ? currentSlides.length + nextIndex : nextIndex), setIsTransitioning(!0),
12447
12708
  setDragOffset(0), setTimeout((() => {
12448
- setIsTransitioning(!1), onSlideChange?.(nextIndex), loop && nextIndex >= 2 * slides.length && (repositioningRef.current = !0,
12449
- setInternalIndex(slides.length + nextIndex), setTimeout((() => {
12709
+ setIsTransitioning(!1), currentOnSlideChange?.(nextIndex), currentLoop && nextIndex >= 2 * currentSlides.length && (repositioningRef.current = !0,
12710
+ setInternalIndex(currentSlides.length + nextIndex), setTimeout((() => {
12450
12711
  repositioningRef.current = !1;
12451
12712
  }), 0));
12452
- }), speed), nextIndex;
12713
+ }), currentSpeed), nextIndex;
12453
12714
  }));
12454
12715
  }), delay), setAutoplayRunning(!0);
12455
12716
  };
@@ -12461,7 +12722,7 @@ function useSlider(options) {
12461
12722
  containerElement && (containerElement.removeEventListener("mouseenter", handleMouseEnter),
12462
12723
  containerElement.removeEventListener("mouseleave", handleMouseLeave)), setAutoplayRunning(!1);
12463
12724
  };
12464
- }), [ autoplay, slides.length, loop, slidesToShow, isTransitioning, speed, onSlideChange, repositioningRef ]),
12725
+ }), [ autoplay, repositioningRef ]),
12465
12726
  // Initialize
12466
12727
  React.useEffect((() => {
12467
12728
  setInternalIndex(loop ? slides.length + initialSlide : initialSlide);
@@ -12921,7 +13182,7 @@ const Select = React.memo((({options: options, value: value, onChange: onChange
12921
13182
  blurAmount: 1,
12922
13183
  saturation: 180,
12923
13184
  aberrationIntensity: .2,
12924
- cornerRadius: 12,
13185
+ borderRadius: 12,
12925
13186
  mode: "shader"
12926
13187
  }, glassProps = !0 === glass ? defaultGlassProps : {
12927
13188
  ...defaultGlassProps,
@@ -12979,7 +13240,7 @@ const Radio = React.memo((({label: label, checked: checked = !1, onChange: onCh
12979
13240
  blurAmount: 1,
12980
13241
  saturation: 160,
12981
13242
  aberrationIntensity: .3,
12982
- cornerRadius: 6,
13243
+ borderRadius: 6,
12983
13244
  mode: "shader"
12984
13245
  }, glassProps = !0 === glass ? defaultGlassProps : {
12985
13246
  ...defaultGlassProps,
@@ -13045,7 +13306,7 @@ const Textarea = React.memo( React.forwardRef((({value: value, defaultValue: de
13045
13306
  blurAmount: 1,
13046
13307
  saturation: 180,
13047
13308
  aberrationIntensity: 1,
13048
- cornerRadius: 8,
13309
+ borderRadius: 8,
13049
13310
  mode: "shader"
13050
13311
  }, glassProps = !0 === glass ? defaultGlassProps : {
13051
13312
  ...defaultGlassProps,
@@ -13771,11 +14032,12 @@ const FooterLink = React.forwardRef((({href: href, icon: icon, external: extern
13771
14032
  const Component = LinkComponent, componentProps = {
13772
14033
  ref: ref,
13773
14034
  ...href && !disabled ? {
14035
+ href: href,
13774
14036
  to: href
13775
14037
  } : {},
13776
14038
  ...linkProps
13777
14039
  };
13778
- // Only pass href if the link is not disabled and href exists
14040
+ // Only pass href/to if the link is not disabled and href exists
13779
14041
  return jsxRuntime.jsxs(Component, {
13780
14042
  ...componentProps,
13781
14043
  children: [ icon && jsxRuntime.jsx("span", {
@@ -13886,7 +14148,7 @@ const Hero = ({title: title, subtitle: subtitle, text: text, imageSrc: imageSrc,
13886
14148
  blurAmount: 3,
13887
14149
  saturation: 180,
13888
14150
  aberrationIntensity: 0,
13889
- cornerRadius: 8,
14151
+ borderRadius: 8,
13890
14152
  overLight: !1,
13891
14153
  mode: "standard",
13892
14154
  children: jsxRuntime.jsxs("div", {
@@ -14094,7 +14356,7 @@ Hero.Title = ({children: children, className: className, level: level = "h1", ..
14094
14356
  blurAmount: 3,
14095
14357
  saturation: 180,
14096
14358
  aberrationIntensity: 0,
14097
- cornerRadius: 8,
14359
+ borderRadius: 8,
14098
14360
  overLight: !1,
14099
14361
  mode: "standard"
14100
14362
  } : glass;
@@ -14208,7 +14470,7 @@ const Messages = ({messages: messages = [], otherAvatar: otherAvatar, selfAvatar
14208
14470
  onSendMessage: onSendMessage
14209
14471
  }), messagesId = id || `messages-${Math.random().toString(36).substr(2, 9)}`, inputId = `${messagesId}-input`, defaultGlassProps = {
14210
14472
  displacementScale: 150,
14211
- cornerRadius: 12,
14473
+ borderRadius: 12,
14212
14474
  elasticity: 0,
14213
14475
  aberrationIntensity: 2
14214
14476
  }, messagesClasses = `${MESSAGES.CLASSES.BASE} ${glass ? "c-messages--glass" : ""} ${disabled ? "is-disabled" : ""} ${className}`, messagesContent = jsxRuntime.jsxs(jsxRuntime.Fragment, {
@@ -14354,7 +14616,7 @@ const Messages = ({messages: messages = [], otherAvatar: otherAvatar, selfAvatar
14354
14616
  children: jsxRuntime.jsx("div", {
14355
14617
  className: "c-messages__glass-content",
14356
14618
  style: {
14357
- borderRadius: glassProps.cornerRadius
14619
+ borderRadius: glassProps.borderRadius
14358
14620
  },
14359
14621
  children: messagesContent
14360
14622
  })
@@ -14582,7 +14844,7 @@ const Modal = ModalWithSubcomponents, Nav = React.forwardRef((({children: child
14582
14844
  const defaultGlassProps = {
14583
14845
  displacementScale: 60,
14584
14846
  blurAmount: 1.5,
14585
- cornerRadius: 8,
14847
+ borderRadius: 8,
14586
14848
  mode: "shader"
14587
14849
  }, glassProps = !0 === glass ? defaultGlassProps : {
14588
14850
  ...defaultGlassProps,
@@ -14610,7 +14872,24 @@ const Modal = ModalWithSubcomponents, Nav = React.forwardRef((({children: child
14610
14872
  * </NavDropdown>
14611
14873
  * </Nav>
14612
14874
  * ```
14613
- */ Nav.displayName = "Nav";
14875
+ */
14876
+ /**
14877
+ * Utility to merge multiple React refs into one
14878
+ */
14879
+ function setRef(ref, value) {
14880
+ "function" == typeof ref ? ref(value) : ref && (
14881
+ // This is safe because we're checking that ref exists first
14882
+ ref.current = value);
14883
+ }
14884
+
14885
+ /**
14886
+ * Combines two React refs into a single ref function
14887
+ * This is used when you need to use and forward a ref at the same time
14888
+ */ function useForkRef(refA, refB) {
14889
+ return React__default.default.useMemo((() => null == refA && null == refB ? null : refValue => {
14890
+ setRef(refA, refValue), setRef(refB, refValue);
14891
+ }), [ refA, refB ]);
14892
+ }
14614
14893
 
14615
14894
  /**
14616
14895
  * NavItem component represents a single navigation item that can be a link, dropdown trigger, or mega menu trigger.
@@ -14639,14 +14918,15 @@ const Modal = ModalWithSubcomponents, Nav = React.forwardRef((({children: child
14639
14918
  * </MegaMenu>
14640
14919
  * </NavItem>
14641
14920
  * ```
14642
- */
14921
+ */ Nav.displayName = "Nav";
14922
+
14643
14923
  const NavItem = React.forwardRef((({children: children, dropdown: dropdown = !1, megaMenu: megaMenu = !1, active: active = !1, href: href, onClick: onClick, className: className = "", disabled: disabled = !1, "aria-expanded": ariaExpanded, LinkComponent: LinkComponent}, ref) => {
14644
14924
  const {generateNavItemClass: generateNavItemClass, generateNavLinkClass: generateNavLinkClass, handleClick: handleClick} = useNavItem({
14645
14925
  dropdown: dropdown,
14646
14926
  megaMenu: megaMenu,
14647
14927
  active: active,
14648
14928
  disabled: disabled
14649
- }), [isActive, setIsActive] = React.useState(!1), itemRef = React.useRef(null);
14929
+ }), [isActive, setIsActive] = React.useState(!1), itemRef = React.useRef(null), combinedRef = useForkRef(ref, itemRef);
14650
14930
  // State for tracking dropdown open state
14651
14931
  // Close dropdown on outside click (desktop only)
14652
14932
  React.useEffect((() => {
@@ -14677,8 +14957,9 @@ const NavItem = React.forwardRef((({children: children, dropdown: dropdown = !1
14677
14957
  disabled: disabled,
14678
14958
  className: className
14679
14959
  }) + (isActive ? " is-active" : ""), navLinkClass = generateNavLinkClass(active, disabled, dropdown || megaMenu ? "c-nav__dropdown-toggle" : ""), childContent = React__default.default.Children.toArray(children), expanded = void 0 !== ariaExpanded ? ariaExpanded : isActive, linkProps = {
14680
- ref: itemRef,
14960
+ ref: combinedRef,
14681
14961
  href: href || "#",
14962
+ to: href || "#",
14682
14963
  className: navLinkClass,
14683
14964
  onClick: dropdown || megaMenu ? e => {
14684
14965
  (dropdown || megaMenu) && (e.preventDefault(), setIsActive(!isActive));
@@ -14688,7 +14969,6 @@ const NavItem = React.forwardRef((({children: children, dropdown: dropdown = !1
14688
14969
  "aria-current": !active || dropdown || megaMenu ? void 0 : "page"
14689
14970
  };
14690
14971
  return jsxRuntime.jsxs("li", {
14691
- ref: ref,
14692
14972
  className: navItemClass,
14693
14973
  role: "menuitem",
14694
14974
  "aria-haspopup": dropdown || megaMenu,
@@ -14794,7 +15074,7 @@ const Navbar = React.forwardRef((({brand: brand, children: children, variant: v
14794
15074
  const defaultGlassProps = {
14795
15075
  displacementScale: 30,
14796
15076
  blurAmount: 2,
14797
- cornerRadius: 0,
15077
+ borderRadius: 0,
14798
15078
  elasticity: 0,
14799
15079
  mode: "shader",
14800
15080
  shaderVariant: "premiumGlass"
@@ -14833,23 +15113,7 @@ const Navbar = React.forwardRef((({brand: brand, children: children, variant: v
14833
15113
  });
14834
15114
  }));
14835
15115
 
14836
- /**
14837
- * Utility to merge multiple React refs into one
14838
- */
14839
- function setRef(ref, value) {
14840
- "function" == typeof ref ? ref(value) : ref && (
14841
- // This is safe because we're checking that ref exists first
14842
- ref.current = value);
14843
- }
14844
-
14845
- /**
14846
- * Combines two React refs into a single ref function
14847
- * This is used when you need to use and forward a ref at the same time
14848
- */ function useForkRef(refA, refB) {
14849
- return React__default.default.useMemo((() => null == refA && null == refB ? null : refValue => {
14850
- setRef(refA, refValue), setRef(refB, refValue);
14851
- }), [ refA, refB ]);
14852
- }
15116
+ Navbar.displayName = "Navbar";
14853
15117
 
14854
15118
  /**
14855
15119
  * SideMenuList component provides a container for side menu items.
@@ -14862,8 +15126,7 @@ function setRef(ref, value) {
14862
15126
  * <SideMenuItem href="/contact">Contact</SideMenuItem>
14863
15127
  * </SideMenuList>
14864
15128
  * ```
14865
- */ Navbar.displayName = "Navbar";
14866
-
15129
+ */
14867
15130
  const SideMenuList = React.forwardRef((({children: children, className: className = ""}, ref) => {
14868
15131
  const listClass = `c-side-menu__list ${className}`.trim();
14869
15132
  return jsxRuntime.jsx("ul", {
@@ -15175,7 +15438,7 @@ const SideMenu = React.forwardRef((({title: title, children: children, menuItem
15175
15438
  const defaultGlassProps = {
15176
15439
  displacementScale: 70,
15177
15440
  blurAmount: 2,
15178
- cornerRadius: 12,
15441
+ borderRadius: 12,
15179
15442
  mode: "shader"
15180
15443
  }, glassProps = !0 === glass ? defaultGlassProps : {
15181
15444
  ...defaultGlassProps,
@@ -16754,7 +17017,7 @@ const PopoverContext = React.createContext({
16754
17017
  blurAmount: 1,
16755
17018
  saturation: 160,
16756
17019
  aberrationIntensity: .5,
16757
- cornerRadius: 8,
17020
+ borderRadius: 8,
16758
17021
  mode: "shader"
16759
17022
  }, glassProps = !0 === glass ? defaultGlassProps : {
16760
17023
  ...defaultGlassProps,
@@ -16805,7 +17068,14 @@ const PopoverContext = React.createContext({
16805
17068
  /**
16806
17069
  * Hook for managing rating component state and interactions
16807
17070
  */
16808
- const Rating = React.forwardRef((({value: valueProp = 0, defaultValue: defaultValue, maxValue: maxValue = 5, allowHalf: allowHalf = !1, readOnly: readOnly = !1, size: size = "md", variant: variant, onChange: onChange, className: className = "", style: style, label: label, id: id, useVanillaJS: useVanillaJS = !1, glass: glass, ...restProps}, ref) => {
17071
+ const calculateStarValue = (e, starValue, allowHalf) => {
17072
+ if (!allowHalf) return starValue;
17073
+ // Get the star element's bounding rectangle
17074
+ const starRect = e.currentTarget.getBoundingClientRect(), starCenterX = starRect.left + starRect.width / 2, adjustedValue = e.clientX < starCenterX ? starValue - .5 : starValue;
17075
+ // Calculate the x position within the star
17076
+ return Math.max(.5, adjustedValue);
17077
+ // Ensure minimum of 0.5
17078
+ }, Rating = React.forwardRef((({value: valueProp = 0, defaultValue: defaultValue, maxValue: maxValue = 5, allowHalf: allowHalf = !1, readOnly: readOnly = !1, size: size = "md", variant: variant, onChange: onChange, className: className = "", style: style, label: label, id: id, useVanillaJS: useVanillaJS = !1, glass: glass, ...restProps}, ref) => {
16809
17079
  const internalRef = React.useRef(null), ratingInstance = React.useRef(null), {currentValue: currentValue, hoverValue: hoverValue, focusedIndex: focusedIndex, setHoverValue: setHoverValue, setFocused: setFocused, handleKeyDown: handleKeyDown} = (({value: value = 0, maxValue: maxValue = 5, allowHalf: allowHalf = !1, readOnly: readOnly = !1, onChange: onChange}) => {
16810
17080
  // Determine if component is in controlled mode
16811
17081
  const isControlled = void 0 !== onChange, [internalValue, setInternalValue] = React.useState(value), [hoverValue, setHoverValue] = React.useState(null), [focusedIndex, setFocusedIndex] = React.useState(null), currentValue = isControlled ? value : internalValue, handleMouseEnter = React.useCallback((starValue => {
@@ -16867,30 +17137,14 @@ const Rating = React.forwardRef((({value: valueProp = 0, defaultValue: defaultV
16867
17137
  readOnly: readOnly,
16868
17138
  onChange: onChange
16869
17139
  }), forkedRef = useForkRef(internalRef, ref), handleMouseEnter = React.useCallback(((e, starValue) => {
16870
- if (!readOnly) if (allowHalf) {
16871
- // Get the star element's bounding rectangle
16872
- const starRect = e.currentTarget.getBoundingClientRect(), starCenterX = starRect.left + starRect.width / 2, adjustedValue = e.clientX < starCenterX ? starValue - .5 : starValue;
16873
- // Calculate the x position within the star
16874
- setHoverValue(Math.max(.5, adjustedValue));
16875
- } else setHoverValue(starValue);
17140
+ readOnly || setHoverValue(calculateStarValue(e, starValue, !!allowHalf));
16876
17141
  }), [ readOnly, allowHalf, setHoverValue ]), handleMouseMove = React.useCallback(((e, starValue) => {
16877
- if (readOnly || !allowHalf) return;
16878
- // Get the star element's bounding rectangle
16879
- const starRect = e.currentTarget.getBoundingClientRect(), starCenterX = starRect.left + starRect.width / 2, adjustedValue = e.clientX < starCenterX ? starValue - .5 : starValue;
16880
- // Calculate the x position within the star
16881
- setHoverValue(Math.max(.5, adjustedValue));
16882
- } // Ensure minimum of 0.5
16883
- ), [ readOnly, allowHalf, setHoverValue ]), handleMouseLeave = React.useCallback((() => {
17142
+ !readOnly && allowHalf && setHoverValue(calculateStarValue(e, starValue, !!allowHalf));
17143
+ }), [ readOnly, allowHalf, setHoverValue ]), handleMouseLeave = React.useCallback((() => {
16884
17144
  readOnly || setHoverValue(null);
16885
17145
  }), [ readOnly, setHoverValue ]), handleClick = React.useCallback(((e, starValue) => {
16886
17146
  if (readOnly) return;
16887
- let newValue = starValue;
16888
- if (allowHalf) {
16889
- // Get the star element's bounding rectangle
16890
- const starRect = e.currentTarget.getBoundingClientRect(), starCenterX = starRect.left + starRect.width / 2;
16891
- // Calculate the x position within the star
16892
- newValue = e.clientX < starCenterX ? starValue - .5 : starValue, newValue = Math.max(.5, newValue);
16893
- }
17147
+ const newValue = calculateStarValue(e, starValue, !!allowHalf);
16894
17148
  onChange?.(newValue);
16895
17149
  }), [ readOnly, onChange, allowHalf ]);
16896
17150
  // Use vanilla JS implementation if specified
@@ -16995,7 +17249,7 @@ const Rating = React.forwardRef((({value: valueProp = 0, defaultValue: defaultV
16995
17249
  blurAmount: 1,
16996
17250
  saturation: 160,
16997
17251
  aberrationIntensity: .5,
16998
- cornerRadius: 8,
17252
+ borderRadius: 8,
16999
17253
  mode: "shader"
17000
17254
  }, glassProps = !0 === glass ? defaultGlassProps : {
17001
17255
  ...defaultGlassProps,
@@ -17009,21 +17263,8 @@ const Rating = React.forwardRef((({value: valueProp = 0, defaultValue: defaultV
17009
17263
  return ratingContent;
17010
17264
  }));
17011
17265
 
17012
- /**
17013
- * Rating component for displaying and collecting star ratings
17014
- *
17015
- * @example
17016
- * // Basic usage
17017
- * <Rating value={3} onChange={handleRatingChange} />
17018
- *
17019
- * @example
17020
- * // Read-only with custom variant
17021
- * <Rating value={4.5} readOnly variant="warning" />
17022
- *
17023
- * @example
17024
- * // With half-star support
17025
- * <Rating value={3.5} allowHalf maxValue={5} />
17026
- */ Rating.displayName = "Rating";
17266
+ // Helper function to calculate star value based on mouse position
17267
+ Rating.displayName = "Rating";
17027
17268
 
17028
17269
  /**
17029
17270
  * ProductReview component for collecting user ratings and feedback
@@ -17168,7 +17409,7 @@ const Progress = React.memo( React.forwardRef((({value: value, variant: variant
17168
17409
  const defaultGlassProps = {
17169
17410
  displacementScale: 30,
17170
17411
  blurAmount: .5,
17171
- cornerRadius: 8,
17412
+ borderRadius: 8,
17172
17413
  mode: "shader"
17173
17414
  }, glassProps = !0 === glass ? defaultGlassProps : {
17174
17415
  ...defaultGlassProps,
@@ -17572,7 +17813,7 @@ const Steps = ({items: items, activeIndex: activeIndex = 0, vertical: vertical =
17572
17813
  blurAmount: 1,
17573
17814
  saturation: 160,
17574
17815
  aberrationIntensity: .5,
17575
- cornerRadius: 8,
17816
+ borderRadius: 8,
17576
17817
  mode: "shader"
17577
17818
  }, glassProps = !0 === glass ? defaultGlassProps : {
17578
17819
  ...defaultGlassProps,
@@ -17730,7 +17971,7 @@ const Tabs = React.memo((({items: items, activeIndex: activeIndex = TAB.DEFAULT
17730
17971
  blurAmount: 1,
17731
17972
  saturation: 160,
17732
17973
  aberrationIntensity: .5,
17733
- cornerRadius: 8,
17974
+ borderRadius: 8,
17734
17975
  mode: "shader"
17735
17976
  }, glassProps = !0 === glass ? defaultGlassProps : {
17736
17977
  ...defaultGlassProps,
@@ -17973,7 +18214,7 @@ const Toggle = ({checked: controlledChecked, defaultChecked: defaultChecked = !1
17973
18214
  blurAmount: 1,
17974
18215
  saturation: 160,
17975
18216
  aberrationIntensity: .5,
17976
- cornerRadius: 8,
18217
+ borderRadius: 8,
17977
18218
  mode: "shader"
17978
18219
  }, glassProps = !0 === glass ? defaultGlassProps : {
17979
18220
  ...defaultGlassProps,