@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.esm.js CHANGED
@@ -1949,7 +1949,7 @@ function useAccordion(initialProps) {
1949
1949
  };
1950
1950
  }
1951
1951
 
1952
- const {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS, calculateDistance = (pos1, pos2) => {
1952
+ const {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateDistance = (pos1, pos2) => {
1953
1953
  if (!pos1 || !pos2 || "number" != typeof pos1.x || "number" != typeof pos1.y || "number" != typeof pos2.x || "number" != typeof pos2.y) return 0;
1954
1954
  const deltaX = pos1.x - pos2.x, deltaY = pos1.y - pos2.y;
1955
1955
  return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
@@ -1962,36 +1962,36 @@ const {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS, calculateDistance = (pos1, pos2)
1962
1962
  }, calculateMouseInfluence = mouseOffset => {
1963
1963
  if (!mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y) return 0;
1964
1964
  // Bounded calculation — keeps the glass effect subtle and stable
1965
- const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$1.MOUSE_INFLUENCE_DIVISOR;
1965
+ const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$2.MOUSE_INFLUENCE_DIVISOR;
1966
1966
  return Math.min(.8, influence);
1967
1967
  // Tighter cap to prevent blur/filter blow-out
1968
- }, 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 => {
1968
+ }, 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 => {
1969
1969
  if ("number" == typeof value) return Math.max(0, value);
1970
- if ("string" != typeof value || !value.trim()) return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
1970
+ if ("string" != typeof value || !value.trim()) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
1971
1971
  const trimmedValue = value.trim();
1972
1972
  // Handle px values
1973
1973
  if (trimmedValue.endsWith("px")) {
1974
1974
  const parsed = parseFloat(trimmedValue);
1975
- return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
1975
+ return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
1976
1976
  }
1977
1977
  // Handle rem values (assume 16px = 1rem)
1978
1978
  if (trimmedValue.endsWith("rem")) {
1979
1979
  const parsed = parseFloat(trimmedValue);
1980
- return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
1980
+ return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
1981
1981
  }
1982
1982
  // Handle em values (assume 16px = 1em for simplicity)
1983
1983
  if (trimmedValue.endsWith("em")) {
1984
1984
  const parsed = parseFloat(trimmedValue);
1985
- return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
1985
+ return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
1986
1986
  }
1987
1987
  // Handle percentage (convert to approximate px value, assuming 200px container)
1988
1988
  if (trimmedValue.endsWith("%")) {
1989
1989
  const parsed = parseFloat(trimmedValue);
1990
- return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
1990
+ return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
1991
1991
  }
1992
1992
  // Handle unitless numbers
1993
1993
  const numValue = parseFloat(trimmedValue);
1994
- return isNaN(numValue) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
1994
+ return isNaN(numValue) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
1995
1995
  }, extractBorderRadiusFromElement = element => {
1996
1996
  if (!element || !element.props) return null;
1997
1997
  // Check inline styles first (highest priority)
@@ -2007,11 +2007,11 @@ const {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS, calculateDistance = (pos1, pos2)
2007
2007
  // If element has children, recursively check them
2008
2008
  if (element.props.children) {
2009
2009
  const childRadius = extractBorderRadiusFromChildren(element.props.children);
2010
- if (childRadius > 0 && childRadius !== CONSTANTS$1.DEFAULT_CORNER_RADIUS) return childRadius;
2010
+ if (childRadius > 0 && childRadius !== CONSTANTS$2.DEFAULT_CORNER_RADIUS) return childRadius;
2011
2011
  }
2012
2012
  return null;
2013
2013
  }, extractBorderRadiusFromChildren = children => {
2014
- if (!children) return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
2014
+ if (!children) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
2015
2015
  try {
2016
2016
  const childArray = React.Children.toArray(children);
2017
2017
  for (let i = 0; i < childArray.length; i++) {
@@ -2024,7 +2024,7 @@ const {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS, calculateDistance = (pos1, pos2)
2024
2024
  } catch (error) {
2025
2025
  // Silently handle errors
2026
2026
  }
2027
- return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
2027
+ return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
2028
2028
  }, getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
2029
2029
  switch (mode) {
2030
2030
  case "standard":
@@ -2195,10 +2195,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
2195
2195
  }, globalMousePosition: globalMousePosition = {
2196
2196
  x: 0,
2197
2197
  y: 0
2198
- }, 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 = {
2198
+ }, 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 = {
2199
2199
  width: 0,
2200
2200
  height: 0
2201
- }, onClick: onClick, mode: mode = "standard", effectiveDisableEffects: effectiveDisableEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", enableLiquidBlur: enableLiquidBlur = !1, elasticity: elasticity = 0, contentRef: contentRef}, ref) => {
2201
+ }, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, elasticity: elasticity = 0, contentRef: contentRef}, ref) => {
2202
2202
  // Generate a stable, deterministic ID for SSR compatibility
2203
2203
  // Use a module-level counter that's consistent across server and client
2204
2204
  const filterId = useMemo((() => "atomix-glass-filter-" + ++idCounter), []), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null);
@@ -2308,7 +2308,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
2308
2308
  flowBlur: 1.2 * blurAmount
2309
2309
  };
2310
2310
  // Enhanced validation for liquid blur
2311
- if (!enableLiquidBlur || !rectCache || !mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y || isNaN(mouseOffset.x) || isNaN(mouseOffset.y)) return defaultBlur;
2311
+ if (!withLiquidBlur || !rectCache || !mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y || isNaN(mouseOffset.x) || isNaN(mouseOffset.y)) return defaultBlur;
2312
2312
  try {
2313
2313
  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);
2314
2314
  // NOTE: hover/active multipliers intentionally omitted here —
@@ -2323,14 +2323,14 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
2323
2323
  return console.warn("AtomixGlassContainer: Error calculating liquid blur", error),
2324
2324
  defaultBlur;
2325
2325
  }
2326
- }), [ enableLiquidBlur, blurAmount, mouseOffset, rectCache ]), backdropStyle = useMemo((() => {
2326
+ }), [ withLiquidBlur, blurAmount, mouseOffset, rectCache ]), backdropStyle = useMemo((() => {
2327
2327
  try {
2328
2328
  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;
2329
2329
  // Validate blur values before using them
2330
- return !enableLiquidBlur || effectiveReducedMotion || effectiveDisableEffects || area > 18e4 ? {
2330
+ return !withLiquidBlur || effectiveReducedMotion || effectiveWithoutEffects || area > 18e4 ? {
2331
2331
  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})`
2332
2332
  } : {
2333
- 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})`
2333
+ 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})`
2334
2334
  };
2335
2335
  // Single-pass fallback: stronger radius to match perceived blur of multi-pass
2336
2336
  } catch (error) {
@@ -2339,7 +2339,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
2339
2339
  backdropFilter: `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`
2340
2340
  };
2341
2341
  }
2342
- }), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveDisableEffects, enableLiquidBlur ]), containerVars = useMemo((() => {
2342
+ }), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveWithoutEffects, withLiquidBlur ]), containerVars = useMemo((() => {
2343
2343
  try {
2344
2344
  // Safe extraction of mouse offset values
2345
2345
  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;
@@ -2347,10 +2347,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
2347
2347
  "--atomix-glass-container-width": `${glassSize?.width}`,
2348
2348
  "--atomix-glass-container-height": `${glassSize?.height}`,
2349
2349
  "--atomix-glass-container-padding": padding || "0 0",
2350
- "--atomix-glass-container-radius": `${"number" != typeof cornerRadius || isNaN(cornerRadius) ? 0 : cornerRadius}px`,
2350
+ "--atomix-glass-container-radius": `${"number" != typeof borderRadius || isNaN(borderRadius) ? 0 : borderRadius}px`,
2351
2351
  "--atomix-glass-container-backdrop": backdropStyle?.backdropFilter || "none",
2352
2352
  "--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",
2353
- "--atomix-glass-container-shadow-opacity": effectiveDisableEffects ? 0 : 1,
2353
+ "--atomix-glass-container-shadow-opacity": effectiveWithoutEffects ? 0 : 1,
2354
2354
  // Background and shadow values use design token-aligned RGB values
2355
2355
  "--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",
2356
2356
  "--atomix-glass-container-text-shadow": overLight ? "0px 2px 12px rgba(0, 0, 0, 0)" : "0px 2px 12px rgba(0, 0, 0, 0.4)",
@@ -2368,14 +2368,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
2368
2368
  "--atomix-glass-container-text-shadow": "none"
2369
2369
  };
2370
2370
  }
2371
- }), [ glassSize, padding, cornerRadius, backdropStyle, mouseOffset, overLight, effectiveDisableEffects ]), setForceNoTransition = el => {
2372
- el && (el.style.setProperty("transition-duration", "0s", "important"), el.style.setProperty("animation-duration", "0s", "important"),
2373
- el.style.setProperty("transition-delay", "0s", "important"));
2374
- };
2371
+ }), [ glassSize, padding, borderRadius, backdropStyle, mouseOffset, overLight, effectiveWithoutEffects ]);
2375
2372
  return jsx("div", {
2376
2373
  ref: el => {
2377
2374
  // Apply force no-transition
2378
- setForceNoTransition(el),
2379
2375
  // Handle forwarded ref
2380
2376
  "function" == typeof ref ? ref(el) : ref && (ref.current = el);
2381
2377
  },
@@ -2410,7 +2406,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
2410
2406
  aberrationIntensity: "number" != typeof aberrationIntensity || isNaN(aberrationIntensity) ? 0 : aberrationIntensity,
2411
2407
  shaderMapUrl: shaderMapUrl
2412
2408
  }), jsx("div", {
2413
- ref: setForceNoTransition,
2409
+ ref: el => {
2410
+ el && (el.style.setProperty("transition-duration", "0s", "important"), el.style.setProperty("animation-duration", "0s", "important"),
2411
+ el.style.setProperty("transition-delay", "0s", "important"));
2412
+ },
2414
2413
  className: ATOMIX_GLASS.FILTER_OVERLAY_CLASS,
2415
2414
  style: {
2416
2415
  filter: `url(#${filterId})`,
@@ -2527,7 +2526,128 @@ class {
2527
2526
  */ getSubscriberCount() {
2528
2527
  return this.listeners.size;
2529
2528
  }
2530
- }, {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
2529
+ }, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
2530
+ if (!wrapperElement && !containerElement) return;
2531
+ 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 = {
2532
+ opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
2533
+ contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
2534
+ brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
2535
+ shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
2536
+ borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence)),
2537
+ saturationBoost: baseOverLightConfig.saturationBoost
2538
+ };
2539
+ // Calculate mouse influence
2540
+ // Calculate elastic translation
2541
+ let elasticTranslation = {
2542
+ x: 0,
2543
+ y: 0
2544
+ };
2545
+ if (!effectiveWithoutEffects && wrapperElement) {
2546
+ const rect = wrapperElement.getBoundingClientRect(), center = calculateElementCenter(rect);
2547
+ // Calculate fade in factor
2548
+ let fadeInFactor = 0;
2549
+ if (globalMousePosition.x && globalMousePosition.y && validateGlassSize(glassSize)) {
2550
+ 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({
2551
+ x: edgeDistanceX,
2552
+ y: edgeDistanceY
2553
+ }, {
2554
+ x: 0,
2555
+ y: 0
2556
+ });
2557
+ fadeInFactor = edgeDistance > ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE ? 0 : 1 - edgeDistance / ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE;
2558
+ }
2559
+ elasticTranslation = {
2560
+ x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
2561
+ y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
2562
+ };
2563
+ }
2564
+ 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}`;
2565
+ // Update Wrapper Styles (glassVars)
2566
+ if (wrapperElement) {
2567
+ 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 = {
2568
+ hover1: {
2569
+ x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1,
2570
+ y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1
2571
+ },
2572
+ hover2: {
2573
+ x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_2,
2574
+ y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_2
2575
+ },
2576
+ hover3: {
2577
+ x: GRADIENT.CENTER_POSITION + mx * GRADIENT.HOVER_POSITION.MULTIPLIER_3,
2578
+ y: GRADIENT.CENTER_POSITION + my * GRADIENT.HOVER_POSITION.MULTIPLIER_3
2579
+ }
2580
+ }, basePosition = {
2581
+ x: GRADIENT.CENTER_POSITION + mx * GRADIENT.BASE_LAYER_MULTIPLIER,
2582
+ y: GRADIENT.CENTER_POSITION + my * GRADIENT.BASE_LAYER_MULTIPLIER
2583
+ }, opacityValues = {
2584
+ hover1: isHovered || isActive ? .5 : 0,
2585
+ hover2: isActive ? .5 : 0,
2586
+ hover3: isHovered ? .4 : isActive ? .8 : 0,
2587
+ base: isOverLight ? overLightConfig.opacity : 0,
2588
+ over: isOverLight ? 1.1 * overLightConfig.opacity : 0
2589
+ }, style = wrapperElement.style;
2590
+ style.setProperty("--atomix-glass-transform", transformStyle || "none"),
2591
+ // Gradients
2592
+ 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%)`),
2593
+ 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%)`),
2594
+ // Hover gradients
2595
+ 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}%)`),
2596
+ 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}%)`),
2597
+ 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}%)`),
2598
+ 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})`),
2599
+ 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})`),
2600
+ // Opacities
2601
+ style.setProperty("--atomix-glass-hover-1-opacity", opacityValues.hover1.toString()),
2602
+ style.setProperty("--atomix-glass-hover-2-opacity", opacityValues.hover2.toString()),
2603
+ style.setProperty("--atomix-glass-hover-3-opacity", opacityValues.hover3.toString()),
2604
+ style.setProperty("--atomix-glass-base-opacity", opacityValues.base.toString()),
2605
+ style.setProperty("--atomix-glass-overlay-opacity", opacityValues.over.toString()),
2606
+ style.setProperty("--atomix-glass-overlay-highlight-opacity", (opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER).toString()),
2607
+ // Other
2608
+ style.setProperty("--atomix-glass-blend-mode", isOverLight ? "multiply" : "overlay"),
2609
+ style.setProperty("--atomix-glass-radius", `${effectiveBorderRadius}px`);
2610
+ }
2611
+ // Update Container Styles (containerVars)
2612
+ if (containerElement) {
2613
+ 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();
2614
+ let liquidBlur = {
2615
+ baseBlur: blurAmount,
2616
+ edgeBlur: blurAmount * EDGE_BLUR_MULTIPLIER,
2617
+ centerBlur: blurAmount * CENTER_BLUR_MULTIPLIER,
2618
+ flowBlur: blurAmount * FLOW_BLUR_MULTIPLIER
2619
+ };
2620
+ if (withLiquidBlur && rect) {
2621
+ 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);
2622
+ liquidBlur = {
2623
+ baseBlur: clampBlur(baseBlur),
2624
+ edgeBlur: clampBlur(edgeBlur),
2625
+ centerBlur: clampBlur(centerBlur),
2626
+ flowBlur: clampBlur(flowBlur)
2627
+ };
2628
+ }
2629
+ // Backdrop filter
2630
+ let backdropFilterString = `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`;
2631
+ const dynamicSaturation = saturation + 20 * (liquidBlur.baseBlur || 0), area = rect ? rect.width * rect.height : 0;
2632
+ 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})`;
2633
+ // Container variables
2634
+ const style = containerElement.style;
2635
+ style.setProperty("--atomix-glass-container-width", `${glassSize.width}`), style.setProperty("--atomix-glass-container-height", `${glassSize.height}`),
2636
+ style.setProperty("--atomix-glass-container-padding", padding), style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
2637
+ style.setProperty("--atomix-glass-container-backdrop", backdropFilterString),
2638
+ // Shadows
2639
+ 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"),
2640
+ style.setProperty("--atomix-glass-container-shadow-opacity", effectiveWithoutEffects ? "0" : "1"),
2641
+ 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"),
2642
+ 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)"),
2643
+ 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)");
2644
+ }
2645
+ }, {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS;
2646
+
2647
+ /**
2648
+ * Updates the styles of the AtomixGlass wrapper and container elements imperatively
2649
+ * to avoid React re-renders on mouse movement.
2650
+ */ const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
2531
2651
  parentElement && backgroundDetectionCache.set(parentElement, {
2532
2652
  result: result,
2533
2653
  timestamp: Date.now(),
@@ -2540,18 +2660,74 @@ class {
2540
2660
  * Composable hook for AtomixGlass component logic
2541
2661
  * Manages all state, calculations, and event handlers
2542
2662
  */
2543
- 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}) {
2663
+ 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}) {
2544
2664
  // State
2545
- const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), [glassSize, setGlassSize] = useState({
2546
- width: 270,
2547
- height: 69
2548
- }), [internalGlobalMousePosition, setInternalGlobalMousePosition] = useState({
2665
+ const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), cachedRectRef = useRef(null), internalGlobalMousePositionRef = useRef({
2549
2666
  x: 0,
2550
2667
  y: 0
2551
- }), [internalMouseOffset, setInternalMouseOffset] = useState({
2668
+ }), internalMouseOffsetRef = useRef({
2552
2669
  x: 0,
2553
2670
  y: 0
2554
- }), [dynamicCornerRadius, setDynamicCornerRadius] = useState(CONSTANTS.DEFAULT_CORNER_RADIUS), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1), effectiveCornerRadius = useMemo((() => void 0 !== cornerRadius ? Math.max(0, cornerRadius) : Math.max(0, dynamicCornerRadius)), [ cornerRadius, dynamicCornerRadius ]), effectiveReducedMotion = useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveHighContrast = useMemo((() => highContrast || userPrefersHighContrast), [ highContrast, userPrefersHighContrast ]), effectiveDisableEffects = useMemo((() => disableEffects || effectiveReducedMotion), [ disableEffects, effectiveReducedMotion ]), globalMousePosition = useMemo((() => externalGlobalMousePosition || internalGlobalMousePosition), [ externalGlobalMousePosition, internalGlobalMousePosition ]), mouseOffset = useMemo((() => externalMouseOffset || internalMouseOffset), [ externalMouseOffset, internalMouseOffset ]);
2671
+ }), [dynamicBorderRadius, setDynamicCornerRadius] = useState(CONSTANTS.DEFAULT_CORNER_RADIUS), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1), effectiveBorderRadius = useMemo((() => void 0 !== borderRadius ? Math.max(0, borderRadius) : Math.max(0, dynamicBorderRadius)), [ borderRadius, dynamicBorderRadius ]), {glassSize: glassSize} = function({glassRef: glassRef, effectiveBorderRadius: effectiveBorderRadius, cachedRectRef: cachedRectRef}) {
2672
+ const [glassSize, setGlassSize] = useState({
2673
+ width: 270,
2674
+ height: 69
2675
+ });
2676
+ return useEffect((() => {
2677
+ const isValidElement = element => null !== element && element instanceof HTMLElement && element.isConnected;
2678
+ let rafId = null, lastSize = {
2679
+ width: 0,
2680
+ height: 0
2681
+ }, lastCornerRadius = effectiveBorderRadius;
2682
+ const updateGlassSize = (forceUpdate = !1) => {
2683
+ null !== rafId && cancelAnimationFrame(rafId), rafId = requestAnimationFrame((() => {
2684
+ if (!isValidElement(glassRef.current)) return void (rafId = null);
2685
+ const rect = glassRef.current.getBoundingClientRect();
2686
+ if (rect.width <= 0 || rect.height <= 0) return void (rafId = null);
2687
+ // Measure actual rendered size without artificial offsets to avoid feedback loops
2688
+ const newSize = {
2689
+ width: Math.round(rect.width),
2690
+ height: Math.round(rect.height)
2691
+ }, cornerRadiusChanged = lastCornerRadius !== effectiveBorderRadius, dimensionsChanged = Math.abs(newSize.width - lastSize.width) > 1 || Math.abs(newSize.height - lastSize.height) > 1;
2692
+ var size;
2693
+ (forceUpdate || cornerRadiusChanged || dimensionsChanged) && validateGlassSize(size = newSize) && size.width <= CONSTANTS$1.MAX_SIZE && size.height <= CONSTANTS$1.MAX_SIZE && (lastSize = newSize,
2694
+ lastCornerRadius = effectiveBorderRadius, setGlassSize(newSize)), rafId = null;
2695
+ }));
2696
+ };
2697
+ let resizeTimeoutId = null;
2698
+ const debouncedResizeHandler = () => {
2699
+ resizeTimeoutId && clearTimeout(resizeTimeoutId), resizeTimeoutId = setTimeout((() => updateGlassSize(!1)), 16);
2700
+ }, initialTimeoutId = setTimeout((() => updateGlassSize(!0)), 0);
2701
+ let resizeObserver = null, resizeDebounceTimeout = null;
2702
+ // ResizeObserver has 98%+ browser support, no need for fallback
2703
+ if ("undefined" != typeof ResizeObserver && isValidElement(glassRef.current)) try {
2704
+ resizeObserver = new ResizeObserver((entries => {
2705
+ for (const entry of entries) if (entry.target === glassRef.current) {
2706
+ // Update cached rect when size changes
2707
+ glassRef.current && cachedRectRef && (cachedRectRef.current = glassRef.current.getBoundingClientRect()),
2708
+ // Debounce resize updates to match RAF timing (16ms)
2709
+ resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), resizeDebounceTimeout = setTimeout((() => updateGlassSize(!1)), 16);
2710
+ break;
2711
+ }
2712
+ })), resizeObserver.observe(glassRef.current);
2713
+ } catch (error) {
2714
+ console.warn("AtomixGlass: ResizeObserver not available, using window resize only", error);
2715
+ }
2716
+ return window.addEventListener("resize", debouncedResizeHandler, {
2717
+ passive: !0
2718
+ }), () => {
2719
+ clearTimeout(initialTimeoutId), null !== rafId && cancelAnimationFrame(rafId), resizeTimeoutId && clearTimeout(resizeTimeoutId),
2720
+ resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), window.removeEventListener("resize", debouncedResizeHandler),
2721
+ resizeObserver?.disconnect();
2722
+ };
2723
+ }), [ effectiveBorderRadius, glassRef, cachedRectRef ]), {
2724
+ glassSize: glassSize
2725
+ };
2726
+ }({
2727
+ glassRef: glassRef,
2728
+ effectiveBorderRadius: effectiveBorderRadius,
2729
+ cachedRectRef: cachedRectRef
2730
+ }), effectiveReducedMotion = useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveHighContrast = useMemo((() => highContrast || userPrefersHighContrast), [ highContrast, userPrefersHighContrast ]), effectiveWithoutEffects = useMemo((() => withoutEffects || effectiveReducedMotion), [ withoutEffects, effectiveReducedMotion ]), globalMousePosition = externalGlobalMousePosition || internalGlobalMousePositionRef.current, mouseOffset = externalMouseOffset || internalMouseOffsetRef.current;
2555
2731
  // Extract border-radius from children
2556
2732
  useEffect((() => {
2557
2733
  const extractRadius = () => {
@@ -2582,13 +2758,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2582
2758
  }
2583
2759
  null !== extractedRadius && extractedRadius > 0 && setDynamicCornerRadius(extractedRadius);
2584
2760
  } catch (error) {
2585
- "undefined" != typeof process && "production" === process.env?.NODE_ENV || !debugCornerRadius || console.error("[AtomixGlass] Error extracting corner radius:", error);
2761
+ "undefined" != typeof process && "production" === process.env?.NODE_ENV || !debugBorderRadius || console.error("[AtomixGlass] Error extracting corner radius:", error);
2586
2762
  }
2587
2763
  };
2588
2764
  extractRadius();
2589
2765
  const timeoutId = setTimeout(extractRadius, 100);
2590
2766
  return () => clearTimeout(timeoutId);
2591
- }), [ children, debugCornerRadius, contentRef ]),
2767
+ }), [ children, debugBorderRadius, contentRef ]),
2592
2768
  // Media query handlers and background detection
2593
2769
  useEffect((() => {
2594
2770
  if (("auto" === overLight || "object" == typeof overLight && null !== overLight) && glassRef.current) {
@@ -2644,72 +2820,52 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2644
2820
  const rgb = bgColor.match(/\d+/g);
2645
2821
  if (rgb && rgb.length >= 3) {
2646
2822
  const r = Number(rgb[0]), g = Number(rgb[1]), b = Number(rgb[2]);
2647
- // Validate RGB values are valid numbers
2648
- 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)) {
2823
+ if (!isNaN(r) && !isNaN(g) && !isNaN(b) && (r > 10 || g > 10 || b > 10)) {
2649
2824
  const luminance = (.299 * r + .587 * g + .114 * b) / 255;
2650
2825
  !isNaN(luminance) && isFinite(luminance) && (totalLuminance += luminance, validSamples++,
2651
2826
  hasValidBackground = !0);
2652
2827
  }
2653
2828
  }
2654
2829
  }
2655
- // Check for image backgrounds
2656
- bgImage && "none" !== bgImage && "initial" !== bgImage && (
2657
- // For image backgrounds, assume medium luminance
2658
- totalLuminance += .5, validSamples++, hasValidBackground = !0);
2830
+ bgImage && "none" !== bgImage && "initial" !== bgImage && (totalLuminance += .5,
2831
+ validSamples++, hasValidBackground = !0);
2659
2832
  } catch (styleError) {
2660
- "undefined" == typeof process || process.env;
2833
+ // Silently continue
2661
2834
  }
2662
- // Move to parent element for next iteration
2663
- if (!currentElement) break;
2664
- // Exit loop if currentElement becomes null
2665
- currentElement = currentElement.parentElement, depth++;
2835
+ if (!currentElement) break;
2836
+ currentElement = currentElement.parentElement, depth++;
2666
2837
  }
2667
- // More conservative detection with better error handling
2668
- if (hasValidBackground && validSamples > 0) {
2838
+ if (hasValidBackground && validSamples > 0) {
2669
2839
  const avgLuminance = totalLuminance / validSamples;
2670
2840
  if (!isNaN(avgLuminance) && isFinite(avgLuminance)) {
2671
2841
  let threshold = .7;
2672
- // Conservative threshold for overlight
2673
- // If overLight is an object, use its threshold property with validation
2674
- if ("object" == typeof overLight && null !== overLight) {
2842
+ if ("object" == typeof overLight && null !== overLight) {
2675
2843
  const objConfig = overLight;
2676
2844
  if (void 0 !== objConfig.threshold) {
2677
- const configThreshold = "number" == typeof objConfig.threshold && !isNaN(objConfig.threshold) && isFinite(objConfig.threshold) ? objConfig.threshold : .7;
2845
+ const configThreshold = "number" != typeof objConfig.threshold || isNaN(objConfig.threshold) ? .7 : objConfig.threshold;
2678
2846
  threshold = Math.min(.9, Math.max(.1, configThreshold));
2679
2847
  }
2680
2848
  }
2681
2849
  const isOverLightDetected = avgLuminance > threshold;
2682
- // Cache the result in shared cache
2683
- setCachedBackgroundDetection(element.parentElement, overLight, isOverLightDetected, threshold),
2850
+ setCachedBackgroundDetection(element.parentElement, overLight, isOverLightDetected, threshold),
2684
2851
  setDetectedOverLight(isOverLightDetected);
2685
2852
  } else {
2686
- // Invalid luminance calculation, default to false
2687
2853
  const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
2688
2854
  setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
2689
2855
  setDetectedOverLight(result);
2690
2856
  }
2691
2857
  } else {
2692
- // Default to false if no valid background found
2693
2858
  const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
2694
2859
  setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
2695
2860
  setDetectedOverLight(result);
2696
2861
  }
2697
2862
  } catch (error) {
2698
- // Enhanced error logging with context
2699
- "undefined" != typeof process && "development" !== process.env?.NODE_ENV || console.warn("AtomixGlass: Error detecting background brightness:", error);
2700
- const result = !1;
2701
- if (element && element.parentElement) {
2702
- const threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
2703
- setCachedBackgroundDetection(element.parentElement, overLight, result, threshold);
2704
- }
2705
- setDetectedOverLight(result);
2863
+ setDetectedOverLight(!1);
2706
2864
  }
2707
2865
  }), 150);
2708
2866
  return () => clearTimeout(timeoutId);
2709
2867
  }
2710
- if ("boolean" == typeof overLight &&
2711
- // For boolean values, disable auto-detection
2712
- setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
2868
+ if ("boolean" == typeof overLight && setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
2713
2869
  const mediaQueryReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)"), mediaQueryHighContrast = window.matchMedia("(prefers-contrast: high)");
2714
2870
  setUserPrefersReducedMotion(mediaQueryReducedMotion.matches), setUserPrefersHighContrast(mediaQueryHighContrast.matches);
2715
2871
  const handleReducedMotionChange = e => {
@@ -2720,64 +2876,54 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2720
2876
  return mediaQueryReducedMotion.addEventListener ? (mediaQueryReducedMotion.addEventListener("change", handleReducedMotionChange),
2721
2877
  mediaQueryHighContrast.addEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.addListener && (mediaQueryReducedMotion.addListener(handleReducedMotionChange),
2722
2878
  mediaQueryHighContrast.addListener(handleHighContrastChange)), () => {
2723
- try {
2724
- mediaQueryReducedMotion.removeEventListener ? (mediaQueryReducedMotion.removeEventListener("change", handleReducedMotionChange),
2725
- mediaQueryHighContrast.removeEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.removeListener && (mediaQueryReducedMotion.removeListener(handleReducedMotionChange),
2726
- mediaQueryHighContrast.removeListener(handleHighContrastChange));
2727
- } catch (cleanupError) {
2728
- console.error("AtomixGlass: Error cleaning up media query listeners:", cleanupError);
2729
- }
2879
+ // ignore
2730
2880
  };
2731
2881
  } catch (error) {
2732
- return void console.error("AtomixGlass: Error setting up media queries:", error);
2882
+ return;
2733
2883
  }
2734
2884
  }), [ overLight, glassRef, debugOverLight ]);
2735
- // Mouse tracking using shared global tracker
2736
- // Cache bounding rect to avoid repeated getBoundingClientRect calls
2737
- const cachedRectRef = useRef(null), updateRectRef = useRef(null), handleGlobalMousePosition = useCallback((globalPos => {
2738
- if (externalGlobalMousePosition && externalMouseOffset)
2739
- // External mouse position provided, skip internal tracking
2740
- return;
2741
- if (effectiveDisableEffects) return;
2742
- const container = mouseContainer?.current || glassRef.current;
2743
- if (!container) return;
2744
- // Use cached rect if available, otherwise get new one
2745
- let rect = cachedRectRef.current;
2746
- if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
2747
- cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
2748
- const center = calculateElementCenter(rect), newOffset = {
2749
- x: (globalPos.x - center.x) / rect.width * 100,
2750
- y: (globalPos.y - center.y) / rect.height * 100
2885
+ /**
2886
+ * Get effective overLight value based on configuration
2887
+ */
2888
+ const getEffectiveOverLight = useCallback((() => "boolean" == typeof overLight ? overLight : ("auto" === overLight || "object" == typeof overLight && null !== overLight) && detectedOverLight), [ overLight, detectedOverLight ]), validateConfigValue = useCallback(((value, min, max, defaultValue) => "number" != typeof value || isNaN(value) || !isFinite(value) ? defaultValue : Math.min(max, Math.max(min, value))), []), baseOverLightConfig = useMemo((() => {
2889
+ const isOverLight = getEffectiveOverLight(), baseConfig = {
2890
+ isOverLight: isOverLight,
2891
+ threshold: .7,
2892
+ opacity: isOverLight ? Math.min(.6, Math.max(.2, .5)) : 0,
2893
+ contrast: 1,
2894
+ // Base contrast
2895
+ brightness: 1,
2896
+ // Base brightness
2897
+ saturationBoost: 1.3,
2898
+ shadowIntensity: .9,
2899
+ borderOpacity: .7
2751
2900
  };
2752
- // Calculate offset relative to this container
2753
- // React 18 automatically batches these updates
2754
- setInternalMouseOffset(newOffset), setInternalGlobalMousePosition(globalPos);
2755
- }), [ mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveDisableEffects ]);
2756
- // Subscribe to shared mouse tracker
2757
- useEffect((() => {
2758
- if (externalGlobalMousePosition && externalMouseOffset)
2759
- // External mouse position provided, don't subscribe
2760
- return;
2761
- if (effectiveDisableEffects)
2762
- // Effects disabled, don't subscribe
2763
- return;
2764
- // Subscribe to shared tracker
2765
- const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition), container = mouseContainer?.current || glassRef.current;
2766
- // Update cached rect when container size changes
2767
- let resizeObserver = null;
2768
- return container && "undefined" != typeof ResizeObserver && (resizeObserver = new ResizeObserver((() => {
2769
- null !== updateRectRef.current && cancelAnimationFrame(updateRectRef.current), updateRectRef.current = requestAnimationFrame((() => {
2770
- const container = mouseContainer?.current || glassRef.current;
2771
- container && (cachedRectRef.current = container.getBoundingClientRect()), updateRectRef.current = null;
2772
- }));
2773
- })), resizeObserver.observe(container)), () => {
2774
- unsubscribe(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
2775
- updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
2901
+ if ("object" == typeof overLight && null !== overLight) {
2902
+ 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);
2903
+ return {
2904
+ ...baseConfig,
2905
+ threshold: validatedThreshold,
2906
+ opacity: validatedOpacity,
2907
+ contrast: validatedContrast,
2908
+ brightness: validatedBrightness,
2909
+ saturationBoost: validatedSaturationBoost
2910
+ };
2911
+ }
2912
+ return baseConfig;
2913
+ }), [ overLight, getEffectiveOverLight, validateConfigValue ]), overLightConfig = useMemo((() => {
2914
+ const mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1;
2915
+ return {
2916
+ isOverLight: baseOverLightConfig.isOverLight,
2917
+ threshold: baseOverLightConfig.threshold,
2918
+ opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
2919
+ contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
2920
+ brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
2921
+ saturationBoost: baseOverLightConfig.saturationBoost,
2922
+ shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
2923
+ borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence))
2776
2924
  };
2777
- }), [ handleGlobalMousePosition, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveDisableEffects ]);
2778
- // Transform calculations
2779
- const calculateDirectionalScale = useCallback((() => {
2780
- if (!0 === overLight || "auto" === overLight && detectedOverLight || "object" == typeof overLight && null !== overLight && detectedOverLight) return "scale(1)";
2925
+ }), [ baseOverLightConfig, mouseOffset, isHovered, isActive ]), updateRectRef = useRef(null), calculateDirectionalScale = useCallback((() => {
2926
+ if (baseOverLightConfig.isOverLight) return "scale(1)";
2781
2927
  if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return "scale(1)";
2782
2928
  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({
2783
2929
  x: edgeDistanceX,
@@ -2791,7 +2937,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2791
2937
  if (0 === centerDistance) return "scale(1)";
2792
2938
  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;
2793
2939
  return `scaleX(${Math.max(.8, scaleX)}) scaleY(${Math.max(.8, scaleY)})`;
2794
- }), [ globalMousePosition, elasticity, glassSize, glassRef, overLight, detectedOverLight ]), calculateFadeInFactor = useCallback((() => {
2940
+ }), [ globalMousePosition, elasticity, glassSize, glassRef, baseOverLightConfig ]), calculateFadeInFactor = useCallback((() => {
2795
2941
  if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return 0;
2796
2942
  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({
2797
2943
  x: edgeDistanceX,
@@ -2811,122 +2957,110 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2811
2957
  x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
2812
2958
  y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
2813
2959
  };
2814
- }), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = useMemo((() => effectiveDisableEffects ? {
2960
+ }), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = useMemo((() => effectiveWithoutEffects ? {
2815
2961
  x: 0,
2816
2962
  y: 0
2817
- } : calculateElasticTranslation()), [ calculateElasticTranslation, effectiveDisableEffects ]), directionalScale = useMemo((() => effectiveDisableEffects ? "scale(1)" : calculateDirectionalScale()), [ calculateDirectionalScale, effectiveDisableEffects ]), transformStyle = useMemo((() => effectiveDisableEffects ? isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)" : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) ${isActive && Boolean(onClick) ? "scale(0.96)" : directionalScale}`), [ elasticTranslation, isActive, onClick, directionalScale, effectiveDisableEffects ]);
2818
- // Size management
2819
- useEffect((() => {
2820
- const isValidElement = element => null !== element && element instanceof HTMLElement && element.isConnected;
2821
- let rafId = null, lastSize = {
2822
- width: 0,
2823
- height: 0
2824
- }, lastCornerRadius = effectiveCornerRadius;
2825
- const updateGlassSize = (forceUpdate = !1) => {
2826
- null !== rafId && cancelAnimationFrame(rafId), rafId = requestAnimationFrame((() => {
2827
- if (!isValidElement(glassRef.current)) return void (rafId = null);
2828
- const rect = glassRef.current.getBoundingClientRect();
2829
- if (rect.width <= 0 || rect.height <= 0) return void (rafId = null);
2830
- // Measure actual rendered size without artificial offsets to avoid feedback loops
2831
- const newSize = {
2832
- width: Math.round(rect.width),
2833
- height: Math.round(rect.height)
2834
- }, cornerRadiusChanged = lastCornerRadius !== effectiveCornerRadius, dimensionsChanged = Math.abs(newSize.width - lastSize.width) > 1 || Math.abs(newSize.height - lastSize.height) > 1;
2835
- var size;
2836
- (forceUpdate || cornerRadiusChanged || dimensionsChanged) && validateGlassSize(size = newSize) && size.width <= CONSTANTS.MAX_SIZE && size.height <= CONSTANTS.MAX_SIZE && (lastSize = newSize,
2837
- lastCornerRadius = effectiveCornerRadius, setGlassSize(newSize)), rafId = null;
2838
- }));
2839
- };
2840
- let resizeTimeoutId = null;
2841
- const debouncedResizeHandler = () => {
2842
- resizeTimeoutId && clearTimeout(resizeTimeoutId), resizeTimeoutId = setTimeout((() => updateGlassSize(!1)), 16);
2843
- }, initialTimeoutId = setTimeout((() => updateGlassSize(!0)), 0);
2844
- let resizeObserver = null, resizeDebounceTimeout = null;
2845
- // ResizeObserver has 98%+ browser support, no need for fallback
2846
- if ("undefined" != typeof ResizeObserver && isValidElement(glassRef.current)) try {
2847
- resizeObserver = new ResizeObserver((entries => {
2848
- for (const entry of entries) if (entry.target === glassRef.current) {
2849
- // Update cached rect when size changes
2850
- glassRef.current && (cachedRectRef.current = glassRef.current.getBoundingClientRect()),
2851
- // Debounce resize updates to match RAF timing (16ms)
2852
- resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), resizeDebounceTimeout = setTimeout((() => updateGlassSize(!1)), 16);
2853
- break;
2854
- }
2855
- })), resizeObserver.observe(glassRef.current);
2856
- } catch (error) {
2857
- console.warn("AtomixGlass: ResizeObserver not available, using window resize only", error);
2858
- }
2859
- return window.addEventListener("resize", debouncedResizeHandler, {
2860
- passive: !0
2861
- }), () => {
2862
- clearTimeout(initialTimeoutId), null !== rafId && cancelAnimationFrame(rafId), resizeTimeoutId && clearTimeout(resizeTimeoutId),
2863
- resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), window.removeEventListener("resize", debouncedResizeHandler),
2864
- resizeObserver?.disconnect();
2963
+ } : calculateElasticTranslation()), [ calculateElasticTranslation, effectiveWithoutEffects ]), directionalScale = useMemo((() => effectiveWithoutEffects ? "scale(1)" : calculateDirectionalScale()), [ calculateDirectionalScale, effectiveWithoutEffects ]), transformStyle = useMemo((() => effectiveWithoutEffects ? isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)" : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) ${isActive && Boolean(onClick) ? "scale(0.96)" : directionalScale}`), [ elasticTranslation, isActive, onClick, directionalScale, effectiveWithoutEffects ]), handleGlobalMousePosition = useCallback((globalPos => {
2964
+ if (externalGlobalMousePosition && externalMouseOffset) return;
2965
+ if (effectiveWithoutEffects) return;
2966
+ const container = mouseContainer?.current || glassRef.current;
2967
+ if (!container) return;
2968
+ // Use cached rect if available, otherwise get new one
2969
+ let rect = cachedRectRef.current;
2970
+ if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
2971
+ cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
2972
+ const center = calculateElementCenter(rect), newOffset = {
2973
+ x: (globalPos.x - center.x) / rect.width * 100,
2974
+ y: (globalPos.y - center.y) / rect.height * 100
2865
2975
  };
2866
- }), [ effectiveCornerRadius, glassRef ]);
2867
- // OverLight config
2976
+ // Calculate offset relative to this container
2977
+ // Store in refs instead of state
2978
+ internalMouseOffsetRef.current = newOffset, internalGlobalMousePositionRef.current = globalPos,
2979
+ // Imperative style update
2980
+ updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
2981
+ mouseOffset: newOffset,
2982
+ globalMousePosition: globalPos,
2983
+ glassSize: glassSize,
2984
+ isHovered: isHovered,
2985
+ isActive: isActive,
2986
+ isOverLight: baseOverLightConfig.isOverLight,
2987
+ baseOverLightConfig: baseOverLightConfig,
2988
+ effectiveBorderRadius: effectiveBorderRadius,
2989
+ effectiveWithoutEffects: effectiveWithoutEffects,
2990
+ effectiveReducedMotion: effectiveReducedMotion,
2991
+ elasticity: elasticity,
2992
+ directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
2993
+ // Simplified directional scale for fast path
2994
+ onClick: onClick,
2995
+ withLiquidBlur: withLiquidBlur,
2996
+ blurAmount: blurAmount,
2997
+ saturation: saturation,
2998
+ padding: padding
2999
+ });
3000
+ }), [ mouseContainer, glassRef, wrapperRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects, glassSize, isHovered, isActive, baseOverLightConfig, effectiveBorderRadius, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding ]);
2868
3001
  /**
2869
- * Get effective overLight value based on configuration
2870
- * - boolean: returns the boolean value directly
2871
- * - 'auto': returns detectedOverLight (auto-detected from background)
2872
- * - object: returns detectedOverLight (auto-detected, but config object provides customization)
2873
- */
2874
- const getEffectiveOverLight = useCallback((() => "boolean" == typeof overLight ? overLight : ("auto" === overLight || "object" == typeof overLight && null !== overLight) && detectedOverLight), [ overLight, detectedOverLight ]), validateConfigValue = useCallback(((value, min, max, defaultValue) => "number" != typeof value || isNaN(value) || !isFinite(value) ? defaultValue : Math.min(max, Math.max(min, value))), []), overLightConfig = useMemo((() => {
2875
- const isOverLight = getEffectiveOverLight(), mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1, baseConfig = {
2876
- isOverLight: isOverLight,
2877
- threshold: .7,
2878
- opacity: isOverLight ? Math.min(.6, Math.max(.2, .5 * hoverIntensity * activeIntensity)) : 0,
2879
- contrast: Math.min(1.6, Math.max(1, 1.4 + .1 * mouseInfluence)),
2880
- brightness: Math.min(1.1, Math.max(.8, .9 + .05 * mouseInfluence)),
2881
- saturationBoost: 1.3,
2882
- // Fixed value dynamic saturation amplifies perceived displacement
2883
- shadowIntensity: Math.min(1.2, Math.max(.5, .9 + .2 * mouseInfluence)),
2884
- borderOpacity: Math.min(1, Math.max(.3, .7 + .1 * mouseInfluence))
3002
+ * Validate and clamp a numeric config value
3003
+ */
3004
+ // Subscribe to shared mouse tracker
3005
+ useEffect((() => {
3006
+ if (externalGlobalMousePosition && externalMouseOffset) return;
3007
+ if (effectiveWithoutEffects) return;
3008
+ const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition), container = mouseContainer?.current || glassRef.current;
3009
+ let resizeObserver = null;
3010
+ return container && "undefined" != typeof ResizeObserver && (resizeObserver = new ResizeObserver((() => {
3011
+ null !== updateRectRef.current && cancelAnimationFrame(updateRectRef.current), updateRectRef.current = requestAnimationFrame((() => {
3012
+ const container = mouseContainer?.current || glassRef.current;
3013
+ container && (cachedRectRef.current = container.getBoundingClientRect()), updateRectRef.current = null;
3014
+ }));
3015
+ })), resizeObserver.observe(container)), () => {
3016
+ unsubscribe(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
3017
+ updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
2885
3018
  };
2886
- if ("object" == typeof overLight && null !== overLight) {
2887
- 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 = {
2888
- ...baseConfig,
2889
- threshold: validatedThreshold,
2890
- opacity: validatedOpacity * hoverIntensity * activeIntensity,
2891
- contrast: Math.min(1.6, validatedContrast + .1 * mouseInfluence),
2892
- brightness: Math.min(1.1, validatedBrightness + .05 * mouseInfluence),
2893
- saturationBoost: validatedSaturationBoost
2894
- };
2895
- // Validate and apply object config values with proper clamping
2896
- return "undefined" == typeof process || process.env, finalConfig;
2897
- }
2898
- // Debug logging for non-object configs
2899
- return "undefined" == typeof process || process.env, baseConfig;
2900
- }), [ overLight, getEffectiveOverLight, mouseOffset, isHovered, isActive, validateConfigValue, debugOverLight ]), handleMouseEnter = useCallback((() => setIsHovered(!0)), []), handleMouseLeave = useCallback((() => setIsHovered(!1)), []), handleMouseDown = useCallback((() => setIsActive(!0)), []), handleMouseUp = useCallback((() => setIsActive(!1)), []), handleKeyDown = useCallback((e => {
3019
+ }), [ handleGlobalMousePosition, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects ]),
3020
+ // Also call updateStyles on other state changes (hover, active, etc)
3021
+ useEffect((() => {
3022
+ updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
3023
+ mouseOffset: externalMouseOffset || internalMouseOffsetRef.current,
3024
+ globalMousePosition: externalGlobalMousePosition || internalGlobalMousePositionRef.current,
3025
+ glassSize: glassSize,
3026
+ isHovered: isHovered,
3027
+ isActive: isActive,
3028
+ isOverLight: baseOverLightConfig.isOverLight,
3029
+ baseOverLightConfig: baseOverLightConfig,
3030
+ effectiveBorderRadius: effectiveBorderRadius,
3031
+ effectiveWithoutEffects: effectiveWithoutEffects,
3032
+ effectiveReducedMotion: effectiveReducedMotion,
3033
+ elasticity: elasticity,
3034
+ directionalScale: directionalScale,
3035
+ onClick: onClick,
3036
+ withLiquidBlur: withLiquidBlur,
3037
+ blurAmount: blurAmount,
3038
+ saturation: saturation,
3039
+ padding: padding
3040
+ });
3041
+ }), [ isHovered, isActive, glassSize, baseOverLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, directionalScale, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation, padding, onClick ]);
3042
+ // Event handlers
3043
+ const handleMouseEnter = useCallback((() => setIsHovered(!0)), []), handleMouseLeave = useCallback((() => setIsHovered(!1)), []), handleMouseDown = useCallback((() => setIsActive(!0)), []), handleMouseUp = useCallback((() => setIsActive(!1)), []), handleMouseMove = useCallback((_e => {}), []), handleKeyDown = useCallback((e => {
2901
3044
  !onClick || "Enter" !== e.key && " " !== e.key || (e.preventDefault(), onClick());
2902
- }), [ onClick ]), handleMouseMove = useCallback((_e => {}), []);
2903
- /**
2904
- * Validate and clamp a numeric config value
2905
- * @param value - The value to validate
2906
- * @param min - Minimum allowed value
2907
- * @param max - Maximum allowed value
2908
- * @param defaultValue - Default value if validation fails
2909
- * @returns Validated and clamped value
2910
- */ return {
2911
- // State
3045
+ }), [ onClick ]);
3046
+ return {
2912
3047
  isHovered: isHovered,
2913
3048
  isActive: isActive,
2914
3049
  glassSize: glassSize,
2915
- dynamicCornerRadius: dynamicCornerRadius,
2916
- effectiveCornerRadius: effectiveCornerRadius,
3050
+ dynamicBorderRadius: dynamicBorderRadius,
3051
+ effectiveBorderRadius: effectiveBorderRadius,
2917
3052
  effectiveReducedMotion: effectiveReducedMotion,
2918
3053
  effectiveHighContrast: effectiveHighContrast,
2919
- effectiveDisableEffects: effectiveDisableEffects,
3054
+ effectiveWithoutEffects: effectiveWithoutEffects,
2920
3055
  detectedOverLight: detectedOverLight,
2921
3056
  globalMousePosition: globalMousePosition,
3057
+ // This is now static (refs or props) unless prop changes
2922
3058
  mouseOffset: mouseOffset,
2923
- // OverLight config
3059
+ // This is now static (refs or props) unless prop changes
2924
3060
  overLightConfig: overLightConfig,
2925
- // Transform calculations
2926
3061
  elasticTranslation: elasticTranslation,
2927
3062
  directionalScale: directionalScale,
2928
3063
  transformStyle: transformStyle,
2929
- // Event handlers
2930
3064
  handleMouseEnter: handleMouseEnter,
2931
3065
  handleMouseLeave: handleMouseLeave,
2932
3066
  handleMouseDown: handleMouseDown,
@@ -2965,7 +3099,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2965
3099
  *
2966
3100
  * @example
2967
3101
  * // Manual border-radius override
2968
- * <AtomixGlass cornerRadius={20}>
3102
+ * <AtomixGlass borderRadius={20}>
2969
3103
  * <div>Content with 20px glass radius</div>
2970
3104
  * </AtomixGlass>
2971
3105
  *
@@ -3006,37 +3140,48 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
3006
3140
  * <AtomixGlass overLight="auto" debugOverLight={true}>
3007
3141
  * <div>Content with debug logging enabled</div>
3008
3142
  * </AtomixGlass>
3009
- */ 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}) {
3010
- const glassRef = useRef(null), contentRef = useRef(null), {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveCornerRadius: effectiveCornerRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveDisableEffects: effectiveDisableEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown} = useAtomixGlass({
3143
+ */ 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}) {
3144
+ const glassRef = useRef(null), contentRef = useRef(null), {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveBorderRadius: effectiveBorderRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveWithoutEffects: effectiveWithoutEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown} = useAtomixGlass({
3011
3145
  glassRef: glassRef,
3012
3146
  contentRef: contentRef,
3013
- cornerRadius: cornerRadius,
3147
+ borderRadius: borderRadius,
3014
3148
  globalMousePosition: externalGlobalMousePosition,
3015
3149
  mouseOffset: externalMouseOffset,
3016
3150
  mouseContainer: mouseContainer,
3017
3151
  overLight: overLight,
3018
3152
  reducedMotion: reducedMotion,
3019
3153
  highContrast: highContrast,
3020
- disableEffects: disableEffects,
3154
+ withoutEffects: withoutEffects,
3021
3155
  elasticity: elasticity,
3022
3156
  onClick: onClick,
3023
- debugCornerRadius: debugCornerRadius,
3157
+ debugBorderRadius: debugBorderRadius,
3024
3158
  debugOverLight: debugOverLight,
3025
- enablePerformanceMonitoring: enablePerformanceMonitoring,
3026
- children: children
3027
- }), isOverLight = useMemo((() => overLightConfig?.isOverLight), [ overLight ]), shouldRenderOverLightLayers = enableOverLightLayers && isOverLight, baseStyle = {
3159
+ debugPerformance: debugPerformance,
3160
+ children: children,
3161
+ blurAmount: blurAmount,
3162
+ saturation: saturation,
3163
+ withLiquidBlur: withLiquidBlur,
3164
+ padding: padding,
3165
+ style: style
3166
+ }), isOverLight = useMemo((() => overLightConfig?.isOverLight), [ overLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, baseStyle = {
3028
3167
  ...style,
3029
- ...!effectiveDisableEffects && {
3168
+ ...!effectiveWithoutEffects && {
3030
3169
  transform: transformStyle
3031
3170
  }
3032
- }, componentClassName = [ ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`, effectiveDisableEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`, className ].filter(Boolean).join(" "), positionStyles = useMemo((() => ({
3171
+ }, componentClassName = [ ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`, effectiveWithoutEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`, className ].filter(Boolean).join(" "), positionStyles = useMemo((() => ({
3033
3172
  position: style.position || "absolute",
3034
3173
  top: style.top || 0,
3035
3174
  left: style.left || 0
3036
- })), [ style.position, style.top, style.left ]), adjustedSize = useMemo((() => ({
3037
- width: "fixed" !== style.position ? "100%" : style.width ? style.width : Math.max(glassSize.width, 0),
3038
- height: "fixed" !== style.position ? "100%" : style.height ? style.height : Math.max(glassSize.height, 0)
3039
- })), [ style.position, style.width, style.height, glassSize.width, glassSize.height ]), gradientValues = useMemo((() => {
3175
+ })), [ style.position, style.top, style.left ]), adjustedSize = useMemo((() => {
3176
+ const resolveSize = (propValue, styleValue, measuredSize) => {
3177
+ const explicitSize = propValue ?? styleValue;
3178
+ return void 0 !== explicitSize ? "number" == typeof explicitSize ? `${explicitSize}px` : explicitSize : "fixed" === positionStyles.position ? `${Math.max(measuredSize, 0)}px` : "100%";
3179
+ };
3180
+ return {
3181
+ width: resolveSize(width, style.width, glassSize.width),
3182
+ height: resolveSize(height, style.height, glassSize.height)
3183
+ };
3184
+ }), [ width, height, style.width, style.height, positionStyles.position, glassSize.width, glassSize.height ]), gradientValues = useMemo((() => {
3040
3185
  const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT;
3041
3186
  return {
3042
3187
  borderGradientAngle: GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER,
@@ -3078,13 +3223,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
3078
3223
  }), [ isHovered, isActive, isOverLight, overLightConfig.opacity ]), glassVars = useMemo((() => {
3079
3224
  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;
3080
3225
  return {
3081
- "--atomix-glass-radius": `${effectiveCornerRadius}px`,
3226
+ "--atomix-glass-radius": `${effectiveBorderRadius}px`,
3082
3227
  "--atomix-glass-transform": transformStyle || "none",
3083
3228
  "--atomix-glass-position": positionStyles.position,
3084
3229
  "--atomix-glass-top": "fixed" !== positionStyles.top ? `${positionStyles.top}px` : "0",
3085
3230
  "--atomix-glass-left": "fixed" !== positionStyles.left ? `${positionStyles.left}px` : "0",
3086
- "--atomix-glass-width": "fixed" !== style.position ? adjustedSize.width : `${adjustedSize.width}px`,
3087
- "--atomix-glass-height": "fixed" !== style.position ? adjustedSize.height : `${adjustedSize.height}px`,
3231
+ "--atomix-glass-width": adjustedSize.width,
3232
+ "--atomix-glass-height": adjustedSize.height,
3088
3233
  "--atomix-glass-border-width": "var(--atomix-spacing-0-5, 0.09375rem)",
3089
3234
  "--atomix-glass-blend-mode": isOverLight ? "multiply" : "overlay",
3090
3235
  "--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%)`,
@@ -3100,24 +3245,25 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
3100
3245
  "--atomix-glass-overlay-opacity": opacityValues.over,
3101
3246
  "--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})`
3102
3247
  };
3103
- }), [ gradientValues, opacityValues, effectiveCornerRadius, transformStyle, positionStyles, adjustedSize, style.position, isOverLight, overLightConfig.borderOpacity ]), renderBackgroundLayer = layerType => jsx("div", {
3248
+ }), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle, positionStyles, adjustedSize, isOverLight, overLightConfig.borderOpacity ]), renderBackgroundLayer = layerType => jsx("div", {
3104
3249
  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(" "),
3105
3250
  style: {
3106
3251
  ...positionStyles,
3107
3252
  height: adjustedSize.height,
3108
3253
  width: adjustedSize.width,
3109
- borderRadius: `${effectiveCornerRadius}px`,
3254
+ borderRadius: `${effectiveBorderRadius}px`,
3110
3255
  transform: baseStyle.transform
3111
3256
  }
3112
3257
  });
3113
3258
  return jsxs("div", {
3259
+ ...rest,
3114
3260
  className: componentClassName,
3115
3261
  style: glassVars,
3116
3262
  role: role || (onClick ? "button" : void 0),
3117
3263
  tabIndex: onClick ? tabIndex ?? 0 : tabIndex,
3118
3264
  "aria-label": ariaLabel,
3119
3265
  "aria-describedby": ariaDescribedBy,
3120
- "aria-disabled": !(!onClick || !effectiveDisableEffects) || !onClick && void 0,
3266
+ "aria-disabled": !(!onClick || !effectiveWithoutEffects) || !onClick && void 0,
3121
3267
  "aria-pressed": !(!onClick || !isActive) || !onClick && void 0,
3122
3268
  onKeyDown: onClick ? handleKeyDown : void 0,
3123
3269
  children: [ jsx(AtomixGlassContainer, {
@@ -3125,18 +3271,18 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
3125
3271
  contentRef: contentRef,
3126
3272
  className: className,
3127
3273
  style: baseStyle,
3128
- cornerRadius: effectiveCornerRadius,
3129
- displacementScale: effectiveDisableEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
3130
- blurAmount: effectiveDisableEffects ? 0 : blurAmount,
3274
+ borderRadius: effectiveBorderRadius,
3275
+ displacementScale: effectiveWithoutEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
3276
+ blurAmount: effectiveWithoutEffects ? 0 : blurAmount,
3131
3277
  saturation: effectiveHighContrast ? ATOMIX_GLASS.CONSTANTS.SATURATION.HIGH_CONTRAST : isOverLight ? saturation * overLightConfig.saturationBoost : saturation,
3132
- aberrationIntensity: effectiveDisableEffects ? 0 : "shader" === mode ? aberrationIntensity * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_ABERRATION : aberrationIntensity,
3278
+ aberrationIntensity: effectiveWithoutEffects ? 0 : "shader" === mode ? aberrationIntensity * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_ABERRATION : aberrationIntensity,
3133
3279
  glassSize: glassSize,
3134
3280
  padding: padding,
3135
- mouseOffset: effectiveDisableEffects ? {
3281
+ mouseOffset: effectiveWithoutEffects ? {
3136
3282
  x: 0,
3137
3283
  y: 0
3138
3284
  } : mouseOffset,
3139
- globalMousePosition: effectiveDisableEffects ? {
3285
+ globalMousePosition: effectiveWithoutEffects ? {
3140
3286
  x: 0,
3141
3287
  y: 0
3142
3288
  } : globalMousePosition,
@@ -3156,11 +3302,11 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
3156
3302
  onClick: onClick,
3157
3303
  mode: mode,
3158
3304
  transform: baseStyle.transform,
3159
- effectiveDisableEffects: effectiveDisableEffects,
3305
+ effectiveWithoutEffects: effectiveWithoutEffects,
3160
3306
  effectiveReducedMotion: effectiveReducedMotion,
3161
3307
  shaderVariant: shaderVariant,
3162
3308
  elasticity: elasticity,
3163
- enableLiquidBlur: enableLiquidBlur,
3309
+ withLiquidBlur: withLiquidBlur,
3164
3310
  children: children
3165
3311
  }), Boolean(onClick) && jsxs(Fragment, {
3166
3312
  children: [ jsx("div", {
@@ -3182,11 +3328,19 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
3182
3328
  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}%)`
3183
3329
  }
3184
3330
  }) ]
3185
- }), enableBorderEffect && jsxs(Fragment, {
3331
+ }), withBorder && jsxs(Fragment, {
3186
3332
  children: [ jsx("span", {
3187
- className: ATOMIX_GLASS.BORDER_1_CLASS
3333
+ className: ATOMIX_GLASS.BORDER_1_CLASS,
3334
+ style: {
3335
+ width: glassSize.width,
3336
+ height: glassSize.height
3337
+ }
3188
3338
  }), jsx("span", {
3189
- className: ATOMIX_GLASS.BORDER_2_CLASS
3339
+ className: ATOMIX_GLASS.BORDER_2_CLASS,
3340
+ style: {
3341
+ width: glassSize.width,
3342
+ height: glassSize.height
3343
+ }
3190
3344
  }) ]
3191
3345
  }) ]
3192
3346
  });
@@ -3788,7 +3942,7 @@ const Badge = memo((({label: label, variant: variant = "primary", size: size =
3788
3942
  // Default glass settings for badges
3789
3943
  const defaultGlassProps = {
3790
3944
  displacementScale: 20,
3791
- cornerRadius: ref.current?.getBoundingClientRect().width ? ref.current?.getBoundingClientRect().width / 2 : 16,
3945
+ borderRadius: ref.current?.getBoundingClientRect().width ? ref.current?.getBoundingClientRect().width / 2 : 16,
3792
3946
  className: "c-badge--glass",
3793
3947
  elasticity: 0
3794
3948
  }, glassProps = !0 === glass ? defaultGlassProps : {
@@ -3909,7 +4063,7 @@ const useBlock = () => ({
3909
4063
  * ```
3910
4064
  */ Block.displayName = "Block";
3911
4065
 
3912
- const BreadcrumbItem = forwardRef((({children: children, href: href, active: active, icon: icon, onClick: onClick, className: className = "", style: style, linkAs: LinkComponent, linkProps: linkProps = {}, ...props}, ref) => {
4066
+ const BreadcrumbItem = forwardRef((({children: children, href: href, active: active, icon: icon, onClick: onClick, className: className = "", style: style, linkAs: linkAs, linkProps: linkProps = {}, ...props}, ref) => {
3913
4067
  const itemClasses = [ BREADCRUMB.CLASSES.ITEM, active ? BREADCRUMB.CLASSES.ACTIVE : "", className ].filter(Boolean).join(" "), linkContent = jsxs(Fragment, {
3914
4068
  children: [ icon && jsx("span", {
3915
4069
  className: "c-breadcrumb__icon",
@@ -3927,7 +4081,12 @@ const BreadcrumbItem = forwardRef((({children: children, href: href, active: ac
3927
4081
  className: itemClasses,
3928
4082
  style: style,
3929
4083
  ...props,
3930
- children: href && !active ? jsx(LinkComponent || "a", {
4084
+ children: href && !active ? linkAs && linkAs ? jsx(linkAs, {
4085
+ href: href,
4086
+ to: href,
4087
+ ...commonLinkProps,
4088
+ children: linkContent
4089
+ }) : jsx("a", {
3931
4090
  href: href,
3932
4091
  ...commonLinkProps,
3933
4092
  children: linkContent
@@ -3940,7 +4099,7 @@ const BreadcrumbItem = forwardRef((({children: children, href: href, active: ac
3940
4099
 
3941
4100
  BreadcrumbItem.displayName = "BreadcrumbItem";
3942
4101
 
3943
- const Breadcrumb = memo((({items: items, divider: divider, className: className = "", "aria-label": ariaLabel = "Breadcrumb", LinkComponent: LinkComponent, style: style, children: children}) => {
4102
+ const Breadcrumb = memo((function({items: items, divider: divider, className: className = "", "aria-label": ariaLabel = "Breadcrumb", LinkComponent: LinkComponent, style: style, children: children}) {
3944
4103
  const breadcrumbClasses = [ BREADCRUMB.CLASSES.BASE, className ].filter(Boolean).join(" ");
3945
4104
  let content;
3946
4105
  if (items && items.length > 0)
@@ -3962,11 +4121,11 @@ const Breadcrumb = memo((({items: items, divider: divider, className: className
3962
4121
  const childrenCount = Children.count(children);
3963
4122
  content = Children.map(children, ((child, index) => {
3964
4123
  if ( isValidElement(child)) {
3965
- const isLast = index === childrenCount - 1, childProps = child.props;
4124
+ const isLast = index === childrenCount - 1, childProps = child.props, {active: active, linkAs: linkAs, ...otherProps} = childProps;
3966
4125
 
3967
4126
  return cloneElement(child, {
3968
- active: childProps.active ?? (!!isLast || void 0),
3969
- linkAs: childProps.linkAs ?? LinkComponent
4127
+ active: active ?? (!!isLast || void 0),
4128
+ linkAs: linkAs ?? LinkComponent
3970
4129
  });
3971
4130
  }
3972
4131
  return child;
@@ -4034,7 +4193,7 @@ const Spinner = memo((({size: size = "md", variant: variant = "primary", fullsc
4034
4193
  const defaultGlassProps = {
4035
4194
  displacementScale: 20,
4036
4195
  blurAmount: 1,
4037
- cornerRadius: 999,
4196
+ borderRadius: 999,
4038
4197
  mode: "shader"
4039
4198
  }, glassProps = !0 === glass ? defaultGlassProps : {
4040
4199
  ...defaultGlassProps,
@@ -4198,6 +4357,7 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
4198
4357
  ref: ref,
4199
4358
  // LinkComponent usually forwards ref to anchor
4200
4359
  href: href,
4360
+ to: href,
4201
4361
  target: target,
4202
4362
  rel: "_blank" === target ? "noopener noreferrer" : void 0
4203
4363
  };
@@ -4431,7 +4591,7 @@ const Callout = memo((({title: title, children: children, icon: icon, variant:
4431
4591
  // Default glass settings for callouts
4432
4592
  const defaultGlassProps = {
4433
4593
  displacementScale: 30,
4434
- cornerRadius: 8,
4594
+ borderRadius: 8,
4435
4595
  elasticity: 0
4436
4596
  }, glassProps = !0 === glass ? defaultGlassProps : {
4437
4597
  ...defaultGlassProps,
@@ -4453,7 +4613,7 @@ const Callout = memo((({title: title, children: children, icon: icon, variant:
4453
4613
  children: jsx("div", {
4454
4614
  className: "c-callout__glass-content",
4455
4615
  style: {
4456
- borderRadius: glassProps.cornerRadius
4616
+ borderRadius: glassProps.borderRadius
4457
4617
  },
4458
4618
  children: calloutContent
4459
4619
  })
@@ -4492,6 +4652,8 @@ active: active = !1, disabled: disabled = !1, loading: loading = !1, selected: s
4492
4652
  header: header, image: image, imageAlt: imageAlt = "", title: title, text: text, actions: actions, icon: icon, footer: footer, children: children,
4493
4653
  // Interaction
4494
4654
  onClick: onClick, onHover: onHover, onFocus: onFocus, href: href, target: target,
4655
+ // Custom Link
4656
+ LinkComponent: LinkComponent,
4495
4657
  // Glass
4496
4658
  glass: glass,
4497
4659
  // Accessibility
@@ -4575,15 +4737,23 @@ className: className = "", style: style, ...rest}, ref) => {
4575
4737
  };
4576
4738
  // Render as anchor if href is provided
4577
4739
  if (href && !isDisabled) {
4578
- const anchorElement = jsx("a", {
4740
+ let anchorElement;
4741
+ return anchorElement = LinkComponent ? jsx(LinkComponent, {
4579
4742
  ...commonProps,
4580
4743
  ref: ref,
4581
4744
  href: href,
4745
+ to: href,
4582
4746
  target: target,
4583
4747
  rel: "_blank" === target ? "noopener noreferrer" : void 0,
4584
4748
  children: cardContent
4585
- });
4586
- return glass ? jsx(AtomixGlass, {
4749
+ }) : jsx("a", {
4750
+ ...commonProps,
4751
+ ref: ref,
4752
+ href: href,
4753
+ target: target,
4754
+ rel: "_blank" === target ? "noopener noreferrer" : void 0,
4755
+ children: cardContent
4756
+ }), glass ? jsx(AtomixGlass, {
4587
4757
  ...!0 === glass ? {} : glass,
4588
4758
  elasticity: 0,
4589
4759
  children: anchorElement
@@ -5132,12 +5302,22 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
5132
5302
  left: 40
5133
5303
  }, config) => {
5134
5304
  if (!datasets || 0 === datasets.length) return null;
5135
- // Flatten all data points to find min/max values
5136
- const allDataPoints = datasets.flatMap((dataset => dataset.data));
5137
- if (0 === allDataPoints.length) return null;
5138
- 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;
5139
- return {
5140
- xScale: (index, dataLength = allDataPoints.length) => dataLength <= 1 ? padding.left + innerWidth / 2 : padding.left + index / (dataLength - 1) * innerWidth,
5305
+ // Calculate total points and min/max values efficiently avoiding spread operator
5306
+ let totalPoints = 0, minValue = 1 / 0, maxValue = -1 / 0, hasValidData = !1;
5307
+ for (const dataset of datasets) if (dataset.data) {
5308
+ totalPoints += dataset.data.length;
5309
+ const {min: min, max: max, hasValid: hasValid} = getDatasetBounds(dataset.data);
5310
+ hasValid && (min < minValue && (minValue = min), max > maxValue && (maxValue = max),
5311
+ hasValidData = !0);
5312
+ }
5313
+ if (0 === totalPoints) return null;
5314
+ // Handle case with no valid numeric data
5315
+ hasValidData || (minValue = 0, maxValue = 0);
5316
+ const valueRange = maxValue - minValue || 1, innerWidth = width - padding.left - padding.right, innerHeight = height - padding.top - padding.bottom;
5317
+ // Avoid division by zero
5318
+ // Apply padding
5319
+ return {
5320
+ xScale: (index, dataLength = totalPoints) => dataLength <= 1 ? padding.left + innerWidth / 2 : padding.left + index / (dataLength - 1) * innerWidth,
5141
5321
  yScale: value => padding.top + innerHeight - (value - minValue) / valueRange * innerHeight,
5142
5322
  minValue: minValue,
5143
5323
  maxValue: maxValue,
@@ -5192,6 +5372,29 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
5192
5372
 
5193
5373
  /**
5194
5374
  * Hook for chart data processing and transformation
5375
+ */
5376
+ /**
5377
+ * Helper to calculate min/max values from a dataset efficiently
5378
+ * avoiding spread operator which can cause stack overflow on large arrays
5379
+ */
5380
+ function getDatasetBounds(data) {
5381
+ let min = 1 / 0, max = -1 / 0, hasValid = !1;
5382
+ if (data && data.length > 0) for (let i = 0; i < data.length; i++) {
5383
+ const point = data[i];
5384
+ if (point && "number" == typeof point.value) {
5385
+ const val = point.value;
5386
+ val < min && (min = val), val > max && (max = val), hasValid = !0;
5387
+ }
5388
+ }
5389
+ return {
5390
+ min: min,
5391
+ max: max,
5392
+ hasValid: hasValid
5393
+ };
5394
+ }
5395
+
5396
+ /**
5397
+ * Hook for managing chart toolbar state and generating chart-specific configurations
5195
5398
  */ const ChartToolbar = memo( forwardRef((({chartType: chartType = "line", groups: groups = [], enableDefaults: enableDefaults = !0, defaults: defaults = {
5196
5399
  refresh: !0,
5197
5400
  export: !0,
@@ -5612,11 +5815,7 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
5612
5815
  onZoomReset: handleZoomReset,
5613
5816
  onPanToggle: handlePanToggle,
5614
5817
  onReset: handleReset
5615
- })), [ onRefresh, onExport, handleFullscreenChange, handleZoomIn, handleZoomOut, handleZoomReset, handlePanToggle, handleReset ]), {state: toolbarState, handlers: toolbarHandlers, toolbarGroups: toolbarGroups} =
5616
- /**
5617
- * Hook for managing chart toolbar state and generating chart-specific configurations
5618
- */
5619
- function(chartType, config = {}, handlers = {}) {
5818
+ })), [ onRefresh, onExport, handleFullscreenChange, handleZoomIn, handleZoomOut, handleZoomReset, handlePanToggle, handleReset ]), {state: toolbarState, handlers: toolbarHandlers, toolbarGroups: toolbarGroups} = function(chartType, config = {}, handlers = {}) {
5620
5819
  const [state, setState] = useState({
5621
5820
  isFullscreen: !1,
5622
5821
  isExporting: !1,
@@ -6001,16 +6200,16 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
6001
6200
  aberrationIntensity: 1.5,
6002
6201
  elasticity: 0,
6003
6202
  // No elastic effect for charts
6004
- enableLiquidBlur: !1,
6203
+ withLiquidBlur: !1,
6005
6204
  // Keep it simple
6006
- enableBorderEffect: !0,
6205
+ withBorder: !0,
6007
6206
  mode: "standard",
6008
6207
  mouseContainer: chartContainerRef,
6009
6208
  reducedMotion: !1
6010
6209
  })), []), glassProps = useMemo((() => glass ? !0 === glass ? defaultChartGlassProps : {
6011
6210
  ...defaultChartGlassProps,
6012
6211
  ...glass
6013
- } : null), [ glass, defaultChartGlassProps ]), chartBorderRadius = useMemo((() => glassProps?.cornerRadius || void 0), [ glassProps?.cornerRadius ]), chartContextValue = useMemo((() => ({
6212
+ } : null), [ glass, defaultChartGlassProps ]), chartBorderRadius = useMemo((() => glassProps?.borderRadius || void 0), [ glassProps?.borderRadius ]), chartContextValue = useMemo((() => ({
6014
6213
  zoomLevel: zoomLevel,
6015
6214
  panOffset: panOffset,
6016
6215
  panEnabled: panEnabled,
@@ -6141,7 +6340,7 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
6141
6340
  }) ]
6142
6341
  }), wrappedChart = glassProps ? jsx(AtomixGlass, {
6143
6342
  ...glassProps,
6144
- cornerRadius: chartBorderRadius,
6343
+ borderRadius: chartBorderRadius,
6145
6344
  style: {
6146
6345
  width: "100%",
6147
6346
  height: "100%",
@@ -6194,7 +6393,13 @@ const ChartRenderer = memo( forwardRef((({datasets: datasets = [], config: conf
6194
6393
  // Get chart context (zoom/pan state from toolbar) - optional
6195
6394
  // Always call useContext to maintain consistent hook order
6196
6395
  const chartContext = useContext(ChartContext), {calculateScales: calculateScales, getChartColors: getChartColors} = useChart(), {processedData: processedData, isProcessing: isProcessing} = function(datasets, options) {
6197
- const [processedData, setProcessedData] = useState(datasets), [isProcessing, setIsProcessing] = useState(!1), {enableDecimation: enableDecimation = !1, maxDataPoints: maxDataPoints = 1e3, enableRealTime: enableRealTime = !1, realTimeInterval: realTimeInterval = 1e3} = options || {}, decimateData = useCallback(((data, maxPoints) => {
6396
+ const [processedData, setProcessedData] = useState(datasets), [isProcessing, setIsProcessing] = useState(!1), {enableDecimation: enableDecimation = !1, maxDataPoints: maxDataPoints = 1e3, enableRealTime: enableRealTime = !1, realTimeInterval: realTimeInterval = 1e3} = options || {}, lastDataSignature = useRef(""), getDatasetSignature = useCallback((data => data.map((d => `${d.label}:${JSON.stringify(d.data)}`)).join("|")), []);
6397
+ // Update signature when processedData changes (e.g. via props)
6398
+ useEffect((() => {
6399
+ lastDataSignature.current = getDatasetSignature(processedData);
6400
+ }), [ processedData, getDatasetSignature ]);
6401
+ // Data decimation for performance
6402
+ const decimateData = useCallback(((data, maxPoints) => {
6198
6403
  if (!enableDecimation || !data.length) return data;
6199
6404
  const dataLength = data[0]?.data?.length || 0;
6200
6405
  if (dataLength <= maxPoints) return data;
@@ -6214,10 +6419,17 @@ const ChartRenderer = memo( forwardRef((({datasets: datasets = [], config: conf
6214
6419
  }), []), calculateTrendLine = useCallback((values => {
6215
6420
  const n = values.length;
6216
6421
  if (n < 2) return values.map((() => null));
6217
- 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;
6422
+ let xSum = 0, ySum = 0, xySum = 0, x2Sum = 0;
6423
+ for (let i = 0; i < n; i++) {
6424
+ const val = values[i], safeVal = "number" == typeof val ? val : 0;
6425
+ // Treat null/undefined as 0 to match original reduce behavior
6426
+ xSum += i, ySum += safeVal, xySum += i * safeVal, x2Sum += i * i;
6427
+ }
6428
+ const slope = (n * xySum - xSum * ySum) / (n * x2Sum - xSum * xSum), intercept = (ySum - slope * xSum) / n;
6218
6429
  return values.map(((_, i) => slope * i + intercept));
6219
6430
  }), []);
6220
- // Process data when datasets change
6431
+ // Moving average calculation
6432
+ // Process data when datasets change
6221
6433
  return useEffect((() => {
6222
6434
  setIsProcessing(!0), (async () => {
6223
6435
  let processed = [ ...datasets ];
@@ -6229,11 +6441,12 @@ const ChartRenderer = memo( forwardRef((({datasets: datasets = [], config: conf
6229
6441
  useEffect((() => {
6230
6442
  if (!enableRealTime) return;
6231
6443
  const interval = setInterval((() => {
6232
- setProcessedData((prev => [ ...prev ]));
6233
- // Trigger re-render for real-time updates
6234
- }), realTimeInterval);
6444
+ setProcessedData((prev =>
6445
+ // Only trigger update if signature changed
6446
+ getDatasetSignature(prev) === lastDataSignature.current ? prev : [ ...prev ]));
6447
+ }), realTimeInterval);
6235
6448
  return () => clearInterval(interval);
6236
- }), [ enableRealTime, realTimeInterval ]), {
6449
+ }), [ enableRealTime, realTimeInterval, getDatasetSignature ]), {
6237
6450
  processedData: processedData,
6238
6451
  isProcessing: isProcessing,
6239
6452
  decimateData: decimateData,
@@ -6254,12 +6467,12 @@ const ChartRenderer = memo( forwardRef((({datasets: datasets = [], config: conf
6254
6467
  */
6255
6468
  function(datasets, options) {
6256
6469
  const {enableVirtualization: enableVirtualization = !1, enableMemoization: enableMemoization = !0, debounceMs: debounceMs = 100} = options || {}, [isOptimizing, setIsOptimizing] = useState(!1), debounceRef = useRef(null), memoizedScales = useMemo((() => enableMemoization ? datasets.map((dataset => {
6257
- const values = dataset.data?.map((d => d.value)).filter((v => "number" == typeof v)) || [], validValues = values.length > 0 ? values : [ 0 ];
6470
+ const {min: min, max: max, hasValid: hasValid} = getDatasetBounds(dataset.data);
6258
6471
  return {
6259
6472
  label: dataset.label,
6260
6473
  dataLength: dataset.data?.length || 0,
6261
- minValue: Math.min(...validValues),
6262
- maxValue: Math.max(...validValues)
6474
+ minValue: hasValid ? min : 0,
6475
+ maxValue: hasValid ? max : 0
6263
6476
  };
6264
6477
  })) : null), [ datasets, enableMemoization ]), debouncedUpdate = useCallback((callback => {
6265
6478
  debounceRef.current && clearTimeout(debounceRef.current), debounceRef.current = setTimeout((() => {
@@ -6358,8 +6571,8 @@ const ChartRenderer = memo( forwardRef((({datasets: datasets = [], config: conf
6358
6571
  const getAccessibleDescription = useCallback((() => {
6359
6572
  if (!datasets.length) return "Empty chart";
6360
6573
  const datasetDescriptions = datasets.map(((dataset, i) => {
6361
- 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;
6362
- return `Dataset ${i + 1}: ${dataset.label}, ${dataCount} points, range ${min} to ${max}`;
6574
+ const dataCount = dataset.data?.length || 0, {min: min, max: max, hasValid: hasValid} = getDatasetBounds(dataset.data), minVal = hasValid ? min : 0, maxVal = hasValid ? max : 0;
6575
+ return `Dataset ${i + 1}: ${dataset.label}, ${dataCount} points, range ${minVal} to ${maxVal}`;
6363
6576
  })).join(". ");
6364
6577
  return `Chart with ${datasets.length} datasets. ${datasetDescriptions}`;
6365
6578
  }), [ datasets ]);
@@ -8605,14 +8818,14 @@ const ScatterChart = memo( forwardRef((({datasets: datasets = [], config: confi
8605
8818
 
8606
8819
  ScatterChart.displayName = "ScatterChart";
8607
8820
 
8608
- const TreemapChart = memo( forwardRef((({data: data = [], algorithm: algorithm = "squarified", colorConfig: colorConfig = {
8821
+ const DEFAULT_COLOR_CONFIG = {
8609
8822
  scheme: "category"
8610
- }, labelConfig: labelConfig = {
8823
+ }, DEFAULT_LABEL_CONFIG = {
8611
8824
  showLabels: !0,
8612
8825
  minSize: 1e3,
8613
8826
  fontSize: 12,
8614
8827
  textColor: "white"
8615
- }, onDataPointClick: onDataPointClick, config: config = {}, ...props}, ref) => {
8828
+ }, DEFAULT_CONFIG = {}, TreemapChart = memo( forwardRef((({data: data = [], algorithm: algorithm = "squarified", colorConfig: colorConfig = DEFAULT_COLOR_CONFIG, labelConfig: labelConfig = DEFAULT_LABEL_CONFIG, onDataPointClick: onDataPointClick, config: config = DEFAULT_CONFIG, ...props}, ref) => {
8616
8829
  const [hoveredNode, setHoveredNode] = useState(null), [selectedNode, setSelectedNode] = useState(null);
8617
8830
  useState({
8618
8831
  x: 0,
@@ -8724,87 +8937,87 @@ const TreemapChart = memo( forwardRef((({data: data = [], algorithm: algorithm
8724
8937
  remainingHeight -= rowHeight), currentRow = [];
8725
8938
  }
8726
8939
  }
8727
- }), []);
8940
+ }), []), renderContent = useCallback((({scales: scales, colors: colors, datasets: renderedDatasets, handlers: handlers, hoveredPoint: hoveredPoint}) => {
8941
+ if (!data.length) return null;
8942
+ // Calculate available space with padding
8943
+ const availableWidth = scales.width - 40, availableHeight = scales.height - 40, leafNodes = data.filter((item => !item.children || 0 === item.children.length));
8944
+ if (!leafNodes.length) return null;
8945
+ const totalValue = _reduceInstanceProperty(leafNodes).call(leafNodes, ((sum, node) => sum + node.value), 0), treemapNodes = leafNodes.map(((item, index) => ({
8946
+ id: item.id,
8947
+ label: item.label,
8948
+ value: item.value,
8949
+ color: generateColor(item, 0, index) || "transparent",
8950
+ x: 0,
8951
+ // Will be calculated by squarify
8952
+ y: 0,
8953
+ // Will be calculated by squarify
8954
+ width: 0,
8955
+ // Will be calculated by squarify
8956
+ height: 0,
8957
+ // Will be calculated by squarify
8958
+ depth: 0,
8959
+ children: [],
8960
+ originalData: item
8961
+ })));
8962
+ // Create treemap nodes with proper dimensions
8963
+ // Apply squarified algorithm to layout nodes proportionally by value
8964
+ if ("squarified" === algorithm && totalValue > 0) squarify(treemapNodes, 20, 20, availableWidth, availableHeight); else {
8965
+ // Fallback: simple grid layout (equal sizes)
8966
+ const cols = Math.ceil(Math.sqrt(leafNodes.length)), rows = Math.ceil(leafNodes.length / cols), nodeWidth = availableWidth / cols, nodeHeight = availableHeight / rows;
8967
+ treemapNodes.forEach(((node, index) => {
8968
+ const col = index % cols, row = Math.floor(index / cols);
8969
+ node.x = 20 + col * nodeWidth, node.y = 20 + row * nodeHeight, node.width = nodeWidth,
8970
+ node.height = nodeHeight;
8971
+ }));
8972
+ }
8973
+ return jsx(Fragment, {
8974
+ children: treemapNodes.map((node => {
8975
+ const isHovered = hoveredNode === node, isSelected = selectedNode === node, area = node.width * node.height, showLabel = labelConfig.showLabels && area >= (labelConfig.minSize || 1e3);
8976
+ return jsxs("g", {
8977
+ children: [ jsx("rect", {
8978
+ x: node.x,
8979
+ y: node.y,
8980
+ width: node.width,
8981
+ height: node.height,
8982
+ fill: node.color,
8983
+ className: `c-chart__treemap-node ${isHovered ? "c-chart__treemap-node--hovered" : ""} ${isSelected ? "c-chart__treemap-node--selected" : ""}`,
8984
+ onClick: () => {
8985
+ setSelectedNode(node), handlers.onDataPointClick?.(node.originalData, 0, 0);
8986
+ },
8987
+ onMouseEnter: e => {
8988
+ setHoveredNode(node);
8989
+ const rect = e.currentTarget.getBoundingClientRect();
8990
+ handlers.onPointHover(0, 0, node.x, node.y, rect.left + rect.width / 2, rect.top + rect.height / 2);
8991
+ },
8992
+ onMouseLeave: () => {
8993
+ setHoveredNode(null), handlers.onPointLeave();
8994
+ }
8995
+ }), showLabel && jsx("text", {
8996
+ x: node.x + node.width / 2,
8997
+ y: node.y + node.height / 2,
8998
+ textAnchor: "middle",
8999
+ dominantBaseline: "middle",
9000
+ className: "c-chart__treemap-label",
9001
+ style: {
9002
+ fontSize: labelConfig.fontSize,
9003
+ fill: labelConfig.textColor
9004
+ },
9005
+ children: node.label
9006
+ }) ]
9007
+ }, node.id);
9008
+ }))
9009
+ });
9010
+ }), [ data, algorithm, generateColor, squarify, labelConfig, hoveredNode, selectedNode ]), datasets = useMemo((() => [ {
9011
+ label: "Treemap Data",
9012
+ data: data
9013
+ } ]), [ data ]);
8728
9014
  // Squarified treemap algorithm
8729
9015
  return jsx(BaseChart, {
8730
9016
  ref: ref,
8731
9017
  type: "treemap",
8732
- datasets: [ {
8733
- label: "Treemap Data",
8734
- data: data
8735
- } ],
9018
+ datasets: datasets,
8736
9019
  config: config,
8737
- renderContent: ({scales: scales, colors: colors, datasets: renderedDatasets, handlers: handlers, hoveredPoint: hoveredPoint}) => {
8738
- if (!data.length) return null;
8739
- // Calculate available space with padding
8740
- const availableWidth = scales.width - 40, availableHeight = scales.height - 40, leafNodes = data.filter((item => !item.children || 0 === item.children.length));
8741
- if (!leafNodes.length) return null;
8742
- const totalValue = _reduceInstanceProperty(leafNodes).call(leafNodes, ((sum, node) => sum + node.value), 0), treemapNodes = leafNodes.map(((item, index) => ({
8743
- id: item.id,
8744
- label: item.label,
8745
- value: item.value,
8746
- color: generateColor(item, 0, index) || "transparent",
8747
- x: 0,
8748
- // Will be calculated by squarify
8749
- y: 0,
8750
- // Will be calculated by squarify
8751
- width: 0,
8752
- // Will be calculated by squarify
8753
- height: 0,
8754
- // Will be calculated by squarify
8755
- depth: 0,
8756
- children: [],
8757
- originalData: item
8758
- })));
8759
- // Create treemap nodes with proper dimensions
8760
- // Apply squarified algorithm to layout nodes proportionally by value
8761
- if ("squarified" === algorithm && totalValue > 0) squarify(treemapNodes, 20, 20, availableWidth, availableHeight); else {
8762
- // Fallback: simple grid layout (equal sizes)
8763
- const cols = Math.ceil(Math.sqrt(leafNodes.length)), rows = Math.ceil(leafNodes.length / cols), nodeWidth = availableWidth / cols, nodeHeight = availableHeight / rows;
8764
- treemapNodes.forEach(((node, index) => {
8765
- const col = index % cols, row = Math.floor(index / cols);
8766
- node.x = 20 + col * nodeWidth, node.y = 20 + row * nodeHeight, node.width = nodeWidth,
8767
- node.height = nodeHeight;
8768
- }));
8769
- }
8770
- return jsx(Fragment, {
8771
- children: treemapNodes.map((node => {
8772
- const isHovered = hoveredNode === node, isSelected = selectedNode === node, area = node.width * node.height, showLabel = labelConfig.showLabels && area >= (labelConfig.minSize || 1e3);
8773
- return jsxs("g", {
8774
- children: [ jsx("rect", {
8775
- x: node.x,
8776
- y: node.y,
8777
- width: node.width,
8778
- height: node.height,
8779
- fill: node.color,
8780
- className: `c-chart__treemap-node ${isHovered ? "c-chart__treemap-node--hovered" : ""} ${isSelected ? "c-chart__treemap-node--selected" : ""}`,
8781
- onClick: () => {
8782
- setSelectedNode(node), handlers.onDataPointClick?.(node.originalData, 0, 0);
8783
- },
8784
- onMouseEnter: e => {
8785
- setHoveredNode(node);
8786
- const rect = e.currentTarget.getBoundingClientRect();
8787
- handlers.onPointHover(0, 0, node.x, node.y, rect.left + rect.width / 2, rect.top + rect.height / 2);
8788
- },
8789
- onMouseLeave: () => {
8790
- setHoveredNode(null), handlers.onPointLeave();
8791
- }
8792
- }), showLabel && jsx("text", {
8793
- x: node.x + node.width / 2,
8794
- y: node.y + node.height / 2,
8795
- textAnchor: "middle",
8796
- dominantBaseline: "middle",
8797
- className: "c-chart__treemap-label",
8798
- style: {
8799
- fontSize: labelConfig.fontSize,
8800
- fill: labelConfig.textColor
8801
- },
8802
- children: node.label
8803
- }) ]
8804
- }, node.id);
8805
- }))
8806
- });
8807
- },
9020
+ renderContent: renderContent,
8808
9021
  onDataPointClick: onDataPointClick,
8809
9022
  interactive: !0,
8810
9023
  ...props
@@ -9492,7 +9705,7 @@ const DOTS = "...", range = (start, end) => {
9492
9705
  blurAmount: 1,
9493
9706
  saturation: 160,
9494
9707
  aberrationIntensity: .5,
9495
- cornerRadius: 8,
9708
+ borderRadius: 8,
9496
9709
  mode: "shader"
9497
9710
  }, glassProps = !0 === glass ? defaultGlassProps : {
9498
9711
  ...defaultGlassProps,
@@ -9563,7 +9776,7 @@ const Checkbox = React.memo( forwardRef((({label: label, checked: checked, onCh
9563
9776
  blurAmount: 1,
9564
9777
  saturation: 160,
9565
9778
  aberrationIntensity: .3,
9566
- cornerRadius: 6,
9779
+ borderRadius: 6,
9567
9780
  mode: "shader"
9568
9781
  }, glassProps = !0 === glass ? defaultGlassProps : {
9569
9782
  ...defaultGlassProps,
@@ -9623,6 +9836,7 @@ const DropdownItem = memo((({children: children, href: href, active: active = !
9623
9836
  close());
9624
9837
  }, itemClasses = [ "c-dropdown__menu-item", active ? "is-active" : "", disabled ? "is-disabled" : "", className ].filter(Boolean).join(" "), linkProps = {
9625
9838
  href: href,
9839
+ to: href,
9626
9840
  className: itemClasses,
9627
9841
  onClick: handleClick,
9628
9842
  role: "menuitem",
@@ -9652,13 +9866,32 @@ const DropdownItem = memo((({children: children, href: href, active: active = !
9652
9866
  }), children ]
9653
9867
  })
9654
9868
  });
9655
- })), DropdownDivider = memo((({className: className = ""}) => jsx("li", {
9869
+ }));
9870
+
9871
+ DropdownItem.displayName = "DropdownItem";
9872
+
9873
+ /**
9874
+ * DropdownDivider component for separating groups of items
9875
+ */
9876
+ const DropdownDivider = memo((({className: className = ""}) => jsx("li", {
9656
9877
  className: `c-dropdown__divider ${className}`,
9657
9878
  role: "separator"
9658
- }))), DropdownHeader = memo((({children: children, className: className = ""}) => jsx("li", {
9879
+ })));
9880
+
9881
+ DropdownDivider.displayName = "DropdownDivider";
9882
+
9883
+ /**
9884
+ * DropdownHeader component for section headers
9885
+ */
9886
+ const DropdownHeader = memo((({children: children, className: className = ""}) => jsx("li", {
9659
9887
  className: `c-dropdown__header ${className}`,
9660
9888
  children: children
9661
- }))), DropdownStyleContext = createContext({}), Dropdown = 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}) => {
9889
+ })));
9890
+
9891
+ DropdownHeader.displayName = "DropdownHeader";
9892
+
9893
+ // Helper context to pass glass prop to DropdownMenu
9894
+ const DropdownStyleContext = createContext({}), Dropdown = 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}) {
9662
9895
  // Set up controlled vs uncontrolled state
9663
9896
  const [uncontrolledIsOpen, setUncontrolledIsOpen] = useState(!1), isControlled = void 0 !== controlledIsOpen, isOpen = isControlled ? controlledIsOpen : uncontrolledIsOpen, dropdownRef = useRef(null), toggleRef = useRef(null), menuRef = useRef(null), dropdownId = useRef(`dropdown-${Math.random().toString(36).substring(2, 9)}`).current, setIsOpen = useCallback((nextIsOpen => {
9664
9897
  isControlled || setUncontrolledIsOpen(nextIsOpen), onOpenChange && onOpenChange(nextIsOpen);
@@ -9810,9 +10043,7 @@ const DropdownItem = memo((({children: children, href: href, active: active = !
9810
10043
  });
9811
10044
  }));
9812
10045
 
9813
- /**
9814
- * DropdownDivider component for separating groups of items
9815
- */ Dropdown.displayName = "Dropdown", Dropdown.Trigger = DropdownTrigger, Dropdown.Menu = DropdownMenu,
10046
+ Dropdown.displayName = "Dropdown", Dropdown.Trigger = DropdownTrigger, Dropdown.Menu = DropdownMenu,
9816
10047
  Dropdown.Item = DropdownItem, Dropdown.Divider = DropdownDivider, Dropdown.Header = DropdownHeader;
9817
10048
 
9818
10049
  /**
@@ -11236,7 +11467,7 @@ const Input = memo( forwardRef((({type: type = "text", value: value, defaultVal
11236
11467
  blurAmount: 1,
11237
11468
  saturation: 180,
11238
11469
  aberrationIntensity: .2,
11239
- cornerRadius: 12,
11470
+ borderRadius: 12,
11240
11471
  mode: "shader"
11241
11472
  }, glassProps = !0 === glass ? defaultGlassProps : {
11242
11473
  ...defaultGlassProps,
@@ -11276,7 +11507,7 @@ function useHero(initialProps) {
11276
11507
  * @returns Slider state and methods
11277
11508
  */
11278
11509
  function(config) {
11279
- const {slides: slides, autoplay: autoplay, loop: loop = !0, transition: transition = "fade", transitionDuration: transitionDuration = 1e3} = config, [currentIndex, setCurrentIndex] = useState(0), [isTransitioning, setIsTransitioning] = useState(!1), autoplayRef = useRef(null), isPausedRef = useRef(!1), slideRefs = useMemo((() => slides.map((() => React.createRef()))), [ slides.length ]), videoRefs = useMemo((() => slides.map((() => React.createRef()))), [ slides.length ]), handleSlideTransition = useCallback((nextIndex => {
11510
+ const {slides: slides, autoplay: autoplay, loop: loop = !0, transition: transition = "fade", transitionDuration: transitionDuration = 1e3} = config, [currentIndex, setCurrentIndex] = useState(0), [isTransitioning, setIsTransitioning] = useState(!1), autoplayRef = useRef(null), isPausedRef = useRef(!1), callbackRef = useRef(), slideRefs = useMemo((() => slides.map((() => React.createRef()))), [ slides.length ]), videoRefs = useMemo((() => slides.map((() => React.createRef()))), [ slides.length ]), handleSlideTransition = useCallback((nextIndex => {
11280
11511
  if (nextIndex === currentIndex || isTransitioning) return;
11281
11512
  if (nextIndex < 0 || nextIndex >= slides.length) return;
11282
11513
  setIsTransitioning(!0),
@@ -11297,7 +11528,17 @@ function useHero(initialProps) {
11297
11528
  let nextIndex;
11298
11529
  nextIndex = loop ? (currentIndex + 1) % slides.length : Math.min(currentIndex + 1, slides.length - 1),
11299
11530
  handleSlideTransition(nextIndex);
11300
- }), [ currentIndex, slides.length, loop, handleSlideTransition ]), pauseAutoplay = useCallback((() => {
11531
+ }), [ currentIndex, slides.length, loop, handleSlideTransition ]);
11532
+ // Update callbackRef whenever nextSlide or isTransitioning changes
11533
+ useEffect((() => {
11534
+ callbackRef.current = () => {
11535
+ isPausedRef.current || isTransitioning || nextSlide();
11536
+ };
11537
+ }), [ nextSlide, isTransitioning ]);
11538
+ /**
11539
+ * Pause autoplay
11540
+ */
11541
+ const pauseAutoplay = useCallback((() => {
11301
11542
  isPausedRef.current = !0, autoplayRef.current && (clearInterval(autoplayRef.current),
11302
11543
  autoplayRef.current = null);
11303
11544
  }), []), resumeAutoplay = useCallback((() => {
@@ -11306,24 +11547,26 @@ function useHero(initialProps) {
11306
11547
  const delay = "object" == typeof autoplay ? autoplay.delay : 3e3;
11307
11548
  // Restart autoplay
11308
11549
  autoplayRef.current || (autoplayRef.current = setInterval((() => {
11309
- isPausedRef.current || isTransitioning || nextSlide();
11550
+ callbackRef.current && callbackRef.current();
11310
11551
  }), delay));
11311
11552
  }
11312
- }), [ autoplay, slides.length, nextSlide, isTransitioning ]);
11553
+ }), [ autoplay, slides.length ]);
11554
+ /**
11555
+ * Resume autoplay
11556
+ */
11313
11557
  // Autoplay effect
11314
11558
  return useEffect((() => {
11315
11559
  if (!autoplay || slides.length <= 1) return;
11316
11560
  const delay = "object" == typeof autoplay ? autoplay.delay : 3e3;
11317
- return "object" == typeof autoplay && autoplay.pauseOnHover,
11318
11561
  // Clear any existing interval
11319
- autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null),
11562
+ return autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null),
11320
11563
  // Start autoplay if not paused
11321
11564
  isPausedRef.current || (autoplayRef.current = setInterval((() => {
11322
- isPausedRef.current || isTransitioning || nextSlide();
11565
+ callbackRef.current && callbackRef.current();
11323
11566
  }), delay)), () => {
11324
11567
  autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null);
11325
11568
  };
11326
- }), [ autoplay, slides.length, nextSlide, isTransitioning ]),
11569
+ }), [ autoplay, slides.length ]),
11327
11570
  // Initialize first video if needed
11328
11571
  useEffect((() => {
11329
11572
  if (slides.length > 0 && "video" === slides[currentIndex]?.type) {
@@ -12324,7 +12567,14 @@ function useTodo(initialProps) {
12324
12567
  }
12325
12568
 
12326
12569
  function useSlider(options) {
12327
- 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 = useRef(null), wrapperRef = useRef(null), repositioningRef = useRef(!1), autoplayRef = useRef(null), [autoplayRunning, setAutoplayRunning] = useState(!1), [realIndex, setRealIndex] = useState(initialSlide), [internalIndex, setInternalIndex] = useState(0), [isTransitioning, setIsTransitioning] = useState(!1), [containerSize, setContainerSize] = useState(0), [touching, setTouching] = useState(!1), [touchStart, setTouchStart] = useState(0), [dragOffset, setDragOffset] = useState(0), slideWidth = useMemo((() => 0 === containerSize ? 0 : (containerSize - spaceBetween * (slidesToShow - 1)) / slidesToShow), [ containerSize, spaceBetween, slidesToShow ]), allSlides = useMemo((() => loop && 0 !== slides.length ? [ ...slides.map(((slide, i) => ({
12570
+ 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 = useRef(null), wrapperRef = useRef(null), repositioningRef = useRef(!1), autoplayRef = useRef(null), [autoplayRunning, setAutoplayRunning] = useState(!1), sliderStateRef = useRef({
12571
+ isTransitioning: !1,
12572
+ loop: loop,
12573
+ slides: slides,
12574
+ slidesToShow: slidesToShow,
12575
+ speed: speed,
12576
+ onSlideChange: onSlideChange
12577
+ }), [realIndex, setRealIndex] = useState(initialSlide), [internalIndex, setInternalIndex] = useState(0), [isTransitioning, setIsTransitioning] = useState(!1), [containerSize, setContainerSize] = useState(0), [touching, setTouching] = useState(!1), [touchStart, setTouchStart] = useState(0), [dragOffset, setDragOffset] = useState(0), slideWidth = useMemo((() => 0 === containerSize ? 0 : (containerSize - spaceBetween * (slidesToShow - 1)) / slidesToShow), [ containerSize, spaceBetween, slidesToShow ]), allSlides = useMemo((() => loop && 0 !== slides.length ? [ ...slides.map(((slide, i) => ({
12328
12578
  ...slide,
12329
12579
  id: `set1-${slide.id || i}`
12330
12580
  }))), ...slides.map(((slide, i) => ({
@@ -12334,6 +12584,17 @@ function useSlider(options) {
12334
12584
  ...slide,
12335
12585
  id: `set3-${slide.id || i}`
12336
12586
  }))) ] : slides), [ slides, loop ]), loopedSlides = slides.length, translateValue = useMemo((() => 0 === slideWidth ? 0 : -internalIndex * slideWidth + dragOffset), [ slideWidth, internalIndex, dragOffset ]);
12587
+ // Update the ref whenever the relevant state/props change
12588
+ useEffect((() => {
12589
+ sliderStateRef.current = {
12590
+ isTransitioning: isTransitioning,
12591
+ loop: loop,
12592
+ slides: slides,
12593
+ slidesToShow: slidesToShow,
12594
+ speed: speed,
12595
+ onSlideChange: onSlideChange
12596
+ };
12597
+ }), [ isTransitioning, loop, slides, slidesToShow, speed, onSlideChange ]),
12337
12598
  // Autoplay effect
12338
12599
  useEffect((() => {
12339
12600
  if (!autoplay) return autoplayRef.current && (clearInterval(autoplayRef.current),
@@ -12345,32 +12606,34 @@ function useSlider(options) {
12345
12606
  autoplayRef.current && clearInterval(autoplayRef.current),
12346
12607
  // Create new interval
12347
12608
  autoplayRef.current = setInterval((() => {
12609
+ // Use ref to get the latest state without resetting the interval
12610
+ const {isTransitioning: currentIsTransitioning, loop: currentLoop, slides: currentSlides, slidesToShow: currentSlidesToShow, speed: currentSpeed, onSlideChange: currentOnSlideChange} = sliderStateRef.current;
12348
12611
  // We need to use a functional update to get the latest values
12349
- setRealIndex((prevRealIndex => {
12350
- if (isTransitioning) return prevRealIndex;
12612
+ setRealIndex((prevRealIndex => {
12613
+ if (currentIsTransitioning) return prevRealIndex;
12351
12614
  // Stop autoplay on interaction if disableOnInteraction is true
12352
12615
  let nextIndex;
12353
12616
  // Trigger the slide change
12354
12617
  if (disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
12355
- autoplayRef.current = null, setAutoplayRunning(!1)), nextIndex = loop ? (prevRealIndex + 1) % slides.length : Math.min(prevRealIndex + 1, slides.length - slidesToShow),
12618
+ autoplayRef.current = null, setAutoplayRunning(!1)), nextIndex = currentLoop ? (prevRealIndex + 1) % currentSlides.length : Math.min(prevRealIndex + 1, currentSlides.length - currentSlidesToShow),
12356
12619
  reverseDirection) {
12357
12620
  // For reverse direction, we would go to previous slide
12358
- const prevIndex = loop ? 0 === prevRealIndex ? slides.length - 1 : prevRealIndex - 1 : Math.max(prevRealIndex - 1, 0);
12359
- return setInternalIndex(loop ? slides.length + prevIndex : prevIndex), setIsTransitioning(!0),
12360
- setDragOffset(0), setTimeout((() => {
12361
- setIsTransitioning(!1), onSlideChange?.(prevIndex);
12362
- }), speed), prevIndex;
12621
+ const prevIndex = currentLoop ? 0 === prevRealIndex ? currentSlides.length - 1 : prevRealIndex - 1 : Math.max(prevRealIndex - 1, 0);
12622
+ return setInternalIndex(currentLoop ? currentSlides.length + prevIndex : prevIndex),
12623
+ setIsTransitioning(!0), setDragOffset(0), setTimeout((() => {
12624
+ setIsTransitioning(!1), currentOnSlideChange?.(prevIndex);
12625
+ }), currentSpeed), prevIndex;
12363
12626
  }
12364
12627
  // Normal direction
12365
- return setInternalIndex(loop ? slides.length + nextIndex : nextIndex), setIsTransitioning(!0),
12366
- setDragOffset(0), setTimeout((() => {
12367
- setIsTransitioning(!1), onSlideChange?.(nextIndex),
12628
+ return setInternalIndex(currentLoop ? currentSlides.length + nextIndex : nextIndex),
12629
+ setIsTransitioning(!0), setDragOffset(0), setTimeout((() => {
12630
+ setIsTransitioning(!1), currentOnSlideChange?.(nextIndex),
12368
12631
  // Reposition after transition ends for looped sliders
12369
- loop && nextIndex >= 2 * slides.length && (repositioningRef.current = !0, setInternalIndex(slides.length + nextIndex),
12370
- setTimeout((() => {
12632
+ currentLoop && nextIndex >= 2 * currentSlides.length && (repositioningRef.current = !0,
12633
+ setInternalIndex(currentSlides.length + nextIndex), setTimeout((() => {
12371
12634
  repositioningRef.current = !1;
12372
12635
  }), 0));
12373
- }), speed), nextIndex;
12636
+ }), currentSpeed), nextIndex;
12374
12637
  }));
12375
12638
  }), delay), setAutoplayRunning(!0);
12376
12639
  // Handle pause on mouse enter/leave if enabled
@@ -12381,17 +12644,18 @@ function useSlider(options) {
12381
12644
  }, handleMouseLeave = () => {
12382
12645
  // Restart autoplay
12383
12646
  autoplayRef.current && clearInterval(autoplayRef.current), autoplayRef.current = setInterval((() => {
12647
+ const {isTransitioning: currentIsTransitioning, loop: currentLoop, slides: currentSlides, slidesToShow: currentSlidesToShow, speed: currentSpeed, onSlideChange: currentOnSlideChange} = sliderStateRef.current;
12384
12648
  setRealIndex((prevRealIndex => {
12385
- if (isTransitioning) return prevRealIndex;
12649
+ if (currentIsTransitioning) return prevRealIndex;
12386
12650
  let nextIndex;
12387
- return nextIndex = loop ? (prevRealIndex + 1) % slides.length : Math.min(prevRealIndex + 1, slides.length - slidesToShow),
12388
- setInternalIndex(loop ? slides.length + nextIndex : nextIndex), setIsTransitioning(!0),
12651
+ return nextIndex = currentLoop ? (prevRealIndex + 1) % currentSlides.length : Math.min(prevRealIndex + 1, currentSlides.length - currentSlidesToShow),
12652
+ setInternalIndex(currentLoop ? currentSlides.length + nextIndex : nextIndex), setIsTransitioning(!0),
12389
12653
  setDragOffset(0), setTimeout((() => {
12390
- setIsTransitioning(!1), onSlideChange?.(nextIndex), loop && nextIndex >= 2 * slides.length && (repositioningRef.current = !0,
12391
- setInternalIndex(slides.length + nextIndex), setTimeout((() => {
12654
+ setIsTransitioning(!1), currentOnSlideChange?.(nextIndex), currentLoop && nextIndex >= 2 * currentSlides.length && (repositioningRef.current = !0,
12655
+ setInternalIndex(currentSlides.length + nextIndex), setTimeout((() => {
12392
12656
  repositioningRef.current = !1;
12393
12657
  }), 0));
12394
- }), speed), nextIndex;
12658
+ }), currentSpeed), nextIndex;
12395
12659
  }));
12396
12660
  }), delay), setAutoplayRunning(!0);
12397
12661
  };
@@ -12403,7 +12667,7 @@ function useSlider(options) {
12403
12667
  containerElement && (containerElement.removeEventListener("mouseenter", handleMouseEnter),
12404
12668
  containerElement.removeEventListener("mouseleave", handleMouseLeave)), setAutoplayRunning(!1);
12405
12669
  };
12406
- }), [ autoplay, slides.length, loop, slidesToShow, isTransitioning, speed, onSlideChange, repositioningRef ]),
12670
+ }), [ autoplay, repositioningRef ]),
12407
12671
  // Initialize
12408
12672
  useEffect((() => {
12409
12673
  setInternalIndex(loop ? slides.length + initialSlide : initialSlide);
@@ -12863,7 +13127,7 @@ const Select = memo((({options: options, value: value, onChange: onChange, onBl
12863
13127
  blurAmount: 1,
12864
13128
  saturation: 180,
12865
13129
  aberrationIntensity: .2,
12866
- cornerRadius: 12,
13130
+ borderRadius: 12,
12867
13131
  mode: "shader"
12868
13132
  }, glassProps = !0 === glass ? defaultGlassProps : {
12869
13133
  ...defaultGlassProps,
@@ -12921,7 +13185,7 @@ const Radio = memo((({label: label, checked: checked = !1, onChange: onChange,
12921
13185
  blurAmount: 1,
12922
13186
  saturation: 160,
12923
13187
  aberrationIntensity: .3,
12924
- cornerRadius: 6,
13188
+ borderRadius: 6,
12925
13189
  mode: "shader"
12926
13190
  }, glassProps = !0 === glass ? defaultGlassProps : {
12927
13191
  ...defaultGlassProps,
@@ -12987,7 +13251,7 @@ const Textarea = memo( forwardRef((({value: value, defaultValue: defaultValue,
12987
13251
  blurAmount: 1,
12988
13252
  saturation: 180,
12989
13253
  aberrationIntensity: 1,
12990
- cornerRadius: 8,
13254
+ borderRadius: 8,
12991
13255
  mode: "shader"
12992
13256
  }, glassProps = !0 === glass ? defaultGlassProps : {
12993
13257
  ...defaultGlassProps,
@@ -13713,11 +13977,12 @@ const FooterLink = forwardRef((({href: href, icon: icon, external: external = !
13713
13977
  const Component = LinkComponent, componentProps = {
13714
13978
  ref: ref,
13715
13979
  ...href && !disabled ? {
13980
+ href: href,
13716
13981
  to: href
13717
13982
  } : {},
13718
13983
  ...linkProps
13719
13984
  };
13720
- // Only pass href if the link is not disabled and href exists
13985
+ // Only pass href/to if the link is not disabled and href exists
13721
13986
  return jsxs(Component, {
13722
13987
  ...componentProps,
13723
13988
  children: [ icon && jsx("span", {
@@ -13828,7 +14093,7 @@ const Hero = ({title: title, subtitle: subtitle, text: text, imageSrc: imageSrc,
13828
14093
  blurAmount: 3,
13829
14094
  saturation: 180,
13830
14095
  aberrationIntensity: 0,
13831
- cornerRadius: 8,
14096
+ borderRadius: 8,
13832
14097
  overLight: !1,
13833
14098
  mode: "standard",
13834
14099
  children: jsxs("div", {
@@ -14033,7 +14298,7 @@ Hero.Title = ({children: children, className: className, level: level = "h1", ..
14033
14298
  blurAmount: 3,
14034
14299
  saturation: 180,
14035
14300
  aberrationIntensity: 0,
14036
- cornerRadius: 8,
14301
+ borderRadius: 8,
14037
14302
  overLight: !1,
14038
14303
  mode: "standard"
14039
14304
  } : glass;
@@ -14147,7 +14412,7 @@ const Messages = ({messages: messages = [], otherAvatar: otherAvatar, selfAvatar
14147
14412
  onSendMessage: onSendMessage
14148
14413
  }), messagesId = id || `messages-${Math.random().toString(36).substr(2, 9)}`, inputId = `${messagesId}-input`, defaultGlassProps = {
14149
14414
  displacementScale: 150,
14150
- cornerRadius: 12,
14415
+ borderRadius: 12,
14151
14416
  elasticity: 0,
14152
14417
  aberrationIntensity: 2
14153
14418
  }, messagesClasses = `${MESSAGES.CLASSES.BASE} ${glass ? "c-messages--glass" : ""} ${disabled ? "is-disabled" : ""} ${className}`, messagesContent = jsxs(Fragment, {
@@ -14293,7 +14558,7 @@ const Messages = ({messages: messages = [], otherAvatar: otherAvatar, selfAvatar
14293
14558
  children: jsx("div", {
14294
14559
  className: "c-messages__glass-content",
14295
14560
  style: {
14296
- borderRadius: glassProps.cornerRadius
14561
+ borderRadius: glassProps.borderRadius
14297
14562
  },
14298
14563
  children: messagesContent
14299
14564
  })
@@ -14521,7 +14786,7 @@ const Modal = ModalWithSubcomponents, Nav = forwardRef((({children: children, a
14521
14786
  const defaultGlassProps = {
14522
14787
  displacementScale: 60,
14523
14788
  blurAmount: 1.5,
14524
- cornerRadius: 8,
14789
+ borderRadius: 8,
14525
14790
  mode: "shader"
14526
14791
  }, glassProps = !0 === glass ? defaultGlassProps : {
14527
14792
  ...defaultGlassProps,
@@ -14549,7 +14814,24 @@ const Modal = ModalWithSubcomponents, Nav = forwardRef((({children: children, a
14549
14814
  * </NavDropdown>
14550
14815
  * </Nav>
14551
14816
  * ```
14552
- */ Nav.displayName = "Nav";
14817
+ */
14818
+ /**
14819
+ * Utility to merge multiple React refs into one
14820
+ */
14821
+ function setRef(ref, value) {
14822
+ "function" == typeof ref ? ref(value) : ref && (
14823
+ // This is safe because we're checking that ref exists first
14824
+ ref.current = value);
14825
+ }
14826
+
14827
+ /**
14828
+ * Combines two React refs into a single ref function
14829
+ * This is used when you need to use and forward a ref at the same time
14830
+ */ function useForkRef(refA, refB) {
14831
+ return React.useMemo((() => null == refA && null == refB ? null : refValue => {
14832
+ setRef(refA, refValue), setRef(refB, refValue);
14833
+ }), [ refA, refB ]);
14834
+ }
14553
14835
 
14554
14836
  /**
14555
14837
  * NavItem component represents a single navigation item that can be a link, dropdown trigger, or mega menu trigger.
@@ -14578,14 +14860,15 @@ const Modal = ModalWithSubcomponents, Nav = forwardRef((({children: children, a
14578
14860
  * </MegaMenu>
14579
14861
  * </NavItem>
14580
14862
  * ```
14581
- */
14863
+ */ Nav.displayName = "Nav";
14864
+
14582
14865
  const NavItem = 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) => {
14583
14866
  const {generateNavItemClass: generateNavItemClass, generateNavLinkClass: generateNavLinkClass, handleClick: handleClick} = useNavItem({
14584
14867
  dropdown: dropdown,
14585
14868
  megaMenu: megaMenu,
14586
14869
  active: active,
14587
14870
  disabled: disabled
14588
- }), [isActive, setIsActive] = useState(!1), itemRef = useRef(null);
14871
+ }), [isActive, setIsActive] = useState(!1), itemRef = useRef(null), combinedRef = useForkRef(ref, itemRef);
14589
14872
  // State for tracking dropdown open state
14590
14873
  // Close dropdown on outside click (desktop only)
14591
14874
  useEffect((() => {
@@ -14616,8 +14899,9 @@ const NavItem = forwardRef((({children: children, dropdown: dropdown = !1, mega
14616
14899
  disabled: disabled,
14617
14900
  className: className
14618
14901
  }) + (isActive ? " is-active" : ""), navLinkClass = generateNavLinkClass(active, disabled, dropdown || megaMenu ? "c-nav__dropdown-toggle" : ""), childContent = React.Children.toArray(children), expanded = void 0 !== ariaExpanded ? ariaExpanded : isActive, linkProps = {
14619
- ref: itemRef,
14902
+ ref: combinedRef,
14620
14903
  href: href || "#",
14904
+ to: href || "#",
14621
14905
  className: navLinkClass,
14622
14906
  onClick: dropdown || megaMenu ? e => {
14623
14907
  (dropdown || megaMenu) && (e.preventDefault(), setIsActive(!isActive));
@@ -14627,7 +14911,6 @@ const NavItem = forwardRef((({children: children, dropdown: dropdown = !1, mega
14627
14911
  "aria-current": !active || dropdown || megaMenu ? void 0 : "page"
14628
14912
  };
14629
14913
  return jsxs("li", {
14630
- ref: ref,
14631
14914
  className: navItemClass,
14632
14915
  role: "menuitem",
14633
14916
  "aria-haspopup": dropdown || megaMenu,
@@ -14727,7 +15010,7 @@ const Navbar = forwardRef((({brand: brand, children: children, variant: variant
14727
15010
  const defaultGlassProps = {
14728
15011
  displacementScale: 30,
14729
15012
  blurAmount: 2,
14730
- cornerRadius: 0,
15013
+ borderRadius: 0,
14731
15014
  elasticity: 0,
14732
15015
  mode: "shader",
14733
15016
  shaderVariant: "premiumGlass"
@@ -14766,23 +15049,7 @@ const Navbar = forwardRef((({brand: brand, children: children, variant: variant
14766
15049
  });
14767
15050
  }));
14768
15051
 
14769
- /**
14770
- * Utility to merge multiple React refs into one
14771
- */
14772
- function setRef(ref, value) {
14773
- "function" == typeof ref ? ref(value) : ref && (
14774
- // This is safe because we're checking that ref exists first
14775
- ref.current = value);
14776
- }
14777
-
14778
- /**
14779
- * Combines two React refs into a single ref function
14780
- * This is used when you need to use and forward a ref at the same time
14781
- */ function useForkRef(refA, refB) {
14782
- return React.useMemo((() => null == refA && null == refB ? null : refValue => {
14783
- setRef(refA, refValue), setRef(refB, refValue);
14784
- }), [ refA, refB ]);
14785
- }
15052
+ Navbar.displayName = "Navbar";
14786
15053
 
14787
15054
  /**
14788
15055
  * SideMenuList component provides a container for side menu items.
@@ -14795,8 +15062,7 @@ function setRef(ref, value) {
14795
15062
  * <SideMenuItem href="/contact">Contact</SideMenuItem>
14796
15063
  * </SideMenuList>
14797
15064
  * ```
14798
- */ Navbar.displayName = "Navbar";
14799
-
15065
+ */
14800
15066
  const SideMenuList = forwardRef((({children: children, className: className = ""}, ref) => {
14801
15067
  const listClass = `c-side-menu__list ${className}`.trim();
14802
15068
  return jsx("ul", {
@@ -15108,7 +15374,7 @@ const SideMenu = forwardRef((({title: title, children: children, menuItems: men
15108
15374
  const defaultGlassProps = {
15109
15375
  displacementScale: 70,
15110
15376
  blurAmount: 2,
15111
- cornerRadius: 12,
15377
+ borderRadius: 12,
15112
15378
  mode: "shader"
15113
15379
  }, glassProps = !0 === glass ? defaultGlassProps : {
15114
15380
  ...defaultGlassProps,
@@ -16681,7 +16947,7 @@ const PopoverContext = createContext({
16681
16947
  blurAmount: 1,
16682
16948
  saturation: 160,
16683
16949
  aberrationIntensity: .5,
16684
- cornerRadius: 8,
16950
+ borderRadius: 8,
16685
16951
  mode: "shader"
16686
16952
  }, glassProps = !0 === glass ? defaultGlassProps : {
16687
16953
  ...defaultGlassProps,
@@ -16732,7 +16998,14 @@ const PopoverContext = createContext({
16732
16998
  /**
16733
16999
  * Hook for managing rating component state and interactions
16734
17000
  */
16735
- const Rating = 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) => {
17001
+ const calculateStarValue = (e, starValue, allowHalf) => {
17002
+ if (!allowHalf) return starValue;
17003
+ // Get the star element's bounding rectangle
17004
+ const starRect = e.currentTarget.getBoundingClientRect(), starCenterX = starRect.left + starRect.width / 2, adjustedValue = e.clientX < starCenterX ? starValue - .5 : starValue;
17005
+ // Calculate the x position within the star
17006
+ return Math.max(.5, adjustedValue);
17007
+ // Ensure minimum of 0.5
17008
+ }, Rating = 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) => {
16736
17009
  const internalRef = useRef(null), ratingInstance = 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}) => {
16737
17010
  // Determine if component is in controlled mode
16738
17011
  const isControlled = void 0 !== onChange, [internalValue, setInternalValue] = useState(value), [hoverValue, setHoverValue] = useState(null), [focusedIndex, setFocusedIndex] = useState(null), currentValue = isControlled ? value : internalValue, handleMouseEnter = useCallback((starValue => {
@@ -16794,30 +17067,14 @@ const Rating = forwardRef((({value: valueProp = 0, defaultValue: defaultValue,
16794
17067
  readOnly: readOnly,
16795
17068
  onChange: onChange
16796
17069
  }), forkedRef = useForkRef(internalRef, ref), handleMouseEnter = useCallback(((e, starValue) => {
16797
- if (!readOnly) if (allowHalf) {
16798
- // Get the star element's bounding rectangle
16799
- const starRect = e.currentTarget.getBoundingClientRect(), starCenterX = starRect.left + starRect.width / 2, adjustedValue = e.clientX < starCenterX ? starValue - .5 : starValue;
16800
- // Calculate the x position within the star
16801
- setHoverValue(Math.max(.5, adjustedValue));
16802
- } else setHoverValue(starValue);
17070
+ readOnly || setHoverValue(calculateStarValue(e, starValue, !!allowHalf));
16803
17071
  }), [ readOnly, allowHalf, setHoverValue ]), handleMouseMove = useCallback(((e, starValue) => {
16804
- if (readOnly || !allowHalf) return;
16805
- // Get the star element's bounding rectangle
16806
- const starRect = e.currentTarget.getBoundingClientRect(), starCenterX = starRect.left + starRect.width / 2, adjustedValue = e.clientX < starCenterX ? starValue - .5 : starValue;
16807
- // Calculate the x position within the star
16808
- setHoverValue(Math.max(.5, adjustedValue));
16809
- } // Ensure minimum of 0.5
16810
- ), [ readOnly, allowHalf, setHoverValue ]), handleMouseLeave = useCallback((() => {
17072
+ !readOnly && allowHalf && setHoverValue(calculateStarValue(e, starValue, !!allowHalf));
17073
+ }), [ readOnly, allowHalf, setHoverValue ]), handleMouseLeave = useCallback((() => {
16811
17074
  readOnly || setHoverValue(null);
16812
17075
  }), [ readOnly, setHoverValue ]), handleClick = useCallback(((e, starValue) => {
16813
17076
  if (readOnly) return;
16814
- let newValue = starValue;
16815
- if (allowHalf) {
16816
- // Get the star element's bounding rectangle
16817
- const starRect = e.currentTarget.getBoundingClientRect(), starCenterX = starRect.left + starRect.width / 2;
16818
- // Calculate the x position within the star
16819
- newValue = e.clientX < starCenterX ? starValue - .5 : starValue, newValue = Math.max(.5, newValue);
16820
- }
17077
+ const newValue = calculateStarValue(e, starValue, !!allowHalf);
16821
17078
  onChange?.(newValue);
16822
17079
  }), [ readOnly, onChange, allowHalf ]);
16823
17080
  // Use vanilla JS implementation if specified
@@ -16922,7 +17179,7 @@ const Rating = forwardRef((({value: valueProp = 0, defaultValue: defaultValue,
16922
17179
  blurAmount: 1,
16923
17180
  saturation: 160,
16924
17181
  aberrationIntensity: .5,
16925
- cornerRadius: 8,
17182
+ borderRadius: 8,
16926
17183
  mode: "shader"
16927
17184
  }, glassProps = !0 === glass ? defaultGlassProps : {
16928
17185
  ...defaultGlassProps,
@@ -16936,21 +17193,8 @@ const Rating = forwardRef((({value: valueProp = 0, defaultValue: defaultValue,
16936
17193
  return ratingContent;
16937
17194
  }));
16938
17195
 
16939
- /**
16940
- * Rating component for displaying and collecting star ratings
16941
- *
16942
- * @example
16943
- * // Basic usage
16944
- * <Rating value={3} onChange={handleRatingChange} />
16945
- *
16946
- * @example
16947
- * // Read-only with custom variant
16948
- * <Rating value={4.5} readOnly variant="warning" />
16949
- *
16950
- * @example
16951
- * // With half-star support
16952
- * <Rating value={3.5} allowHalf maxValue={5} />
16953
- */ Rating.displayName = "Rating";
17196
+ // Helper function to calculate star value based on mouse position
17197
+ Rating.displayName = "Rating";
16954
17198
 
16955
17199
  /**
16956
17200
  * ProductReview component for collecting user ratings and feedback
@@ -17095,7 +17339,7 @@ const Progress = memo( forwardRef((({value: value, variant: variant = "primary"
17095
17339
  const defaultGlassProps = {
17096
17340
  displacementScale: 30,
17097
17341
  blurAmount: .5,
17098
- cornerRadius: 8,
17342
+ borderRadius: 8,
17099
17343
  mode: "shader"
17100
17344
  }, glassProps = !0 === glass ? defaultGlassProps : {
17101
17345
  ...defaultGlassProps,
@@ -17499,7 +17743,7 @@ const Steps = ({items: items, activeIndex: activeIndex = 0, vertical: vertical =
17499
17743
  blurAmount: 1,
17500
17744
  saturation: 160,
17501
17745
  aberrationIntensity: .5,
17502
- cornerRadius: 8,
17746
+ borderRadius: 8,
17503
17747
  mode: "shader"
17504
17748
  }, glassProps = !0 === glass ? defaultGlassProps : {
17505
17749
  ...defaultGlassProps,
@@ -17657,7 +17901,7 @@ const Tabs = memo((({items: items, activeIndex: activeIndex = TAB.DEFAULTS.ACTI
17657
17901
  blurAmount: 1,
17658
17902
  saturation: 160,
17659
17903
  aberrationIntensity: .5,
17660
- cornerRadius: 8,
17904
+ borderRadius: 8,
17661
17905
  mode: "shader"
17662
17906
  }, glassProps = !0 === glass ? defaultGlassProps : {
17663
17907
  ...defaultGlassProps,
@@ -17900,7 +18144,7 @@ const Toggle = ({checked: controlledChecked, defaultChecked: defaultChecked = !1
17900
18144
  blurAmount: 1,
17901
18145
  saturation: 160,
17902
18146
  aberrationIntensity: .5,
17903
- cornerRadius: 8,
18147
+ borderRadius: 8,
17904
18148
  mode: "shader"
17905
18149
  }, glassProps = !0 === glass ? defaultGlassProps : {
17906
18150
  ...defaultGlassProps,