@shohojdhara/atomix 0.4.5 → 0.4.6

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 (40) hide show
  1. package/dist/atomix.css +33 -14
  2. package/dist/atomix.css.map +1 -1
  3. package/dist/atomix.min.css +1 -1
  4. package/dist/atomix.min.css.map +1 -1
  5. package/dist/charts.js +183 -184
  6. package/dist/charts.js.map +1 -1
  7. package/dist/core.js +183 -184
  8. package/dist/core.js.map +1 -1
  9. package/dist/forms.js +183 -184
  10. package/dist/forms.js.map +1 -1
  11. package/dist/heavy.js +183 -184
  12. package/dist/heavy.js.map +1 -1
  13. package/dist/index.d.ts +4 -31
  14. package/dist/index.esm.js +192 -283
  15. package/dist/index.esm.js.map +1 -1
  16. package/dist/index.js +194 -285
  17. package/dist/index.js.map +1 -1
  18. package/dist/index.min.js +1 -1
  19. package/dist/index.min.js.map +1 -1
  20. package/package.json +1 -1
  21. package/src/components/AtomixGlass/AtomixGlass.tsx +60 -38
  22. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +6 -35
  23. package/src/components/AtomixGlass/glass-utils.ts +27 -14
  24. package/src/components/AtomixGlass/stories/Overview.stories.tsx +19 -21
  25. package/src/components/AtomixGlass/stories/Playground.stories.tsx +1162 -515
  26. package/src/components/AtomixGlass/stories/shared-components.tsx +11 -3
  27. package/src/components/Navigation/Navbar/Navbar.tsx +13 -5
  28. package/src/lib/composables/index.ts +1 -2
  29. package/src/lib/composables/useAtomixGlass.ts +246 -222
  30. package/src/lib/composables/useAtomixGlassStyles.ts +46 -23
  31. package/src/lib/constants/components.ts +3 -1
  32. package/src/styles/06-components/_components.atomix-glass.scss +45 -20
  33. package/src/lib/composables/atomix-glass/useGlassBackgroundDetection.ts +0 -329
  34. package/src/lib/composables/atomix-glass/useGlassCornerRadius.ts +0 -82
  35. package/src/lib/composables/atomix-glass/useGlassMouseTracking.ts +0 -153
  36. package/src/lib/composables/atomix-glass/useGlassOverLight.ts +0 -198
  37. package/src/lib/composables/atomix-glass/useGlassState.ts +0 -112
  38. package/src/lib/composables/atomix-glass/useGlassTransforms.ts +0 -160
  39. package/src/lib/composables/glass-styles.ts +0 -302
  40. package/src/lib/composables/useGlassContainer.ts +0 -177
package/dist/index.js CHANGED
@@ -1753,7 +1753,9 @@ const THEME_COLORS = [ "primary", "secondary", "success", "info", "warning", "er
1753
1753
  ENABLE_OVER_LIGHT_LAYERS: !0
1754
1754
  },
1755
1755
  CONSTANTS: {
1756
- ACTIVATION_ZONE: 200,
1756
+ ACTIVATION_ZONE: 350,
1757
+ LERP_FACTOR: .08,
1758
+ SMOOTHSTEP_POWER: 2.5,
1757
1759
  MIN_BLUR: .1,
1758
1760
  MOUSE_INFLUENCE_DIVISOR: 100,
1759
1761
  EDGE_FADE_PIXELS: 2,
@@ -2048,7 +2050,7 @@ const {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateDistance = (pos1, pos2)
2048
2050
  // Silently handle errors
2049
2051
  }
2050
2052
  return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
2051
- }, getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
2053
+ }, lerp = (a, b, t) => a + (b - a) * t, softClamp = (value, max) => max <= 0 ? 0 : max * (1 - Math.exp(-value / max)), getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
2052
2054
  switch (mode) {
2053
2055
  case "standard":
2054
2056
  return displacementMap;
@@ -2408,20 +2410,12 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
2408
2410
  onClick: onClick,
2409
2411
  children: jsxRuntime.jsxs("div", {
2410
2412
  className: ATOMIX_GLASS.INNER_CLASS,
2411
- style: {
2412
- padding: "var(--atomix-glass-container-padding)",
2413
- boxShadow: "var(--atomix-glass-container-box-shadow)"
2414
- },
2415
2413
  onMouseEnter: onMouseEnter,
2416
2414
  onMouseLeave: onMouseLeave,
2417
2415
  onMouseDown: onMouseDown,
2418
2416
  onMouseUp: onMouseUp,
2419
2417
  children: [ jsxRuntime.jsxs("div", {
2420
2418
  className: ATOMIX_GLASS.FILTER_CLASS,
2421
- style: {
2422
- position: "absolute",
2423
- inset: 0
2424
- },
2425
2419
  children: [ jsxRuntime.jsx(GlassFilter, {
2426
2420
  blurAmount: blurAmount,
2427
2421
  mode: mode,
@@ -2436,26 +2430,14 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
2436
2430
  },
2437
2431
  className: ATOMIX_GLASS.FILTER_OVERLAY_CLASS,
2438
2432
  style: {
2439
- filter: `url(#${filterId})`,
2440
- backdropFilter: "var(--atomix-glass-container-backdrop)",
2441
- borderRadius: "var(--atomix-glass-container-radius)"
2433
+ filter: `url(#${filterId})`
2442
2434
  }
2443
2435
  }), jsxRuntime.jsx("div", {
2444
- className: ATOMIX_GLASS.FILTER_SHADOW_CLASS,
2445
- style: {
2446
- boxShadow: "var(--atomix-glass-container-shadow)",
2447
- opacity: "var(--atomix-glass-container-shadow-opacity)",
2448
- background: "var(--atomix-glass-container-bg)",
2449
- borderRadius: "var(--atomix-glass-container-radius)"
2450
- }
2436
+ className: ATOMIX_GLASS.FILTER_SHADOW_CLASS
2451
2437
  }) ]
2452
2438
  }), jsxRuntime.jsx("div", {
2453
2439
  ref: contentRef,
2454
2440
  className: ATOMIX_GLASS.CONTENT_CLASS,
2455
- style: {
2456
- position: "relative",
2457
- textShadow: "var(--atomix-glass-container-text-shadow)"
2458
- },
2459
2441
  children: children
2460
2442
  }) ]
2461
2443
  })
@@ -2559,31 +2541,39 @@ class {
2559
2541
  saturationBoost: baseOverLightConfig.saturationBoost
2560
2542
  };
2561
2543
  // Calculate mouse influence
2562
- // Calculate elastic translation
2563
- let elasticTranslation = {
2544
+ let computedDirectionalScale = directionalScale, elasticTranslation = {
2564
2545
  x: 0,
2565
2546
  y: 0
2566
2547
  };
2567
- if (!effectiveWithoutEffects && wrapperElement) {
2548
+ // Calculate elastic translation and directional scale
2549
+ if (!effectiveWithoutEffects && wrapperElement) {
2568
2550
  const rect = wrapperElement.getBoundingClientRect(), center = calculateElementCenter(rect);
2569
- // Calculate fade in factor
2570
- let fadeInFactor = 0;
2551
+ // Mouse presence and edge distance logic
2571
2552
  if (globalMousePosition.x && globalMousePosition.y && validateGlassSize(glassSize)) {
2572
- 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({
2553
+ const 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({
2573
2554
  x: edgeDistanceX,
2574
2555
  y: edgeDistanceY
2575
2556
  }, {
2576
2557
  x: 0,
2577
2558
  y: 0
2578
- });
2579
- fadeInFactor = edgeDistance > ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE ? 0 : 1 - edgeDistance / ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE;
2559
+ }), rawT = edgeDistance > ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE ? 0 : 1 - edgeDistance / ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE, fadeInFactor = (t => {
2560
+ const clamped = Math.max(0, Math.min(1, t));
2561
+ return clamped * clamped * (3 - 2 * clamped);
2562
+ })(rawT);
2563
+ // Directional scale
2564
+ if (elasticTranslation = {
2565
+ x: deltaX * elasticity * .1 * fadeInFactor,
2566
+ y: deltaY * elasticity * .1 * fadeInFactor
2567
+ }, !isOverLight && edgeDistance <= ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE) {
2568
+ const centerDistance = calculateDistance(globalMousePosition, center);
2569
+ if (centerDistance > 0) {
2570
+ const normalizedX = deltaX / centerDistance, normalizedY = deltaY / centerDistance, stretchIntensity = Math.min(centerDistance / 300, 1) * elasticity * rawT, scaleX = 1 + Math.abs(normalizedX) * stretchIntensity * .3 - Math.abs(normalizedY) * stretchIntensity * .15, scaleY = 1 + Math.abs(normalizedY) * stretchIntensity * .3 - Math.abs(normalizedX) * stretchIntensity * .15, softScaleX = 1 - softClamp(Math.max(0, 1 - scaleX), .2), softScaleY = 1 - softClamp(Math.max(0, 1 - scaleY), .2);
2571
+ computedDirectionalScale = `scaleX(${Math.max(.85, softScaleX)}) scaleY(${Math.max(.85, softScaleY)})`;
2572
+ }
2573
+ }
2580
2574
  }
2581
- elasticTranslation = {
2582
- x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
2583
- y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
2584
- };
2585
2575
  }
2586
- 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}`;
2576
+ const transformStyle = effectiveWithoutEffects ? isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)" : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) ${isActive && Boolean(onClick) ? "scale(0.96)" : computedDirectionalScale}`;
2587
2577
  // Update Wrapper Styles (glassVars)
2588
2578
  if (wrapperElement) {
2589
2579
  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 = {
@@ -2690,7 +2680,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
2690
2680
  }), internalMouseOffsetRef = React.useRef({
2691
2681
  x: 0,
2692
2682
  y: 0
2693
- }), [dynamicBorderRadius, setDynamicCornerRadius] = React.useState(CONSTANTS.DEFAULT_CORNER_RADIUS), [userPrefersReducedMotion, setUserPrefersReducedMotion] = React.useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = React.useState(!1), [detectedOverLight, setDetectedOverLight] = React.useState(!1), effectiveBorderRadius = React.useMemo((() => void 0 !== borderRadius ? Math.max(0, borderRadius) : Math.max(0, dynamicBorderRadius)), [ borderRadius, dynamicBorderRadius ]), {glassSize: glassSize} = function({glassRef: glassRef, effectiveBorderRadius: effectiveBorderRadius, cachedRectRef: cachedRectRef}) {
2683
+ }), targetMouseOffsetRef = React.useRef({
2684
+ x: 0,
2685
+ y: 0
2686
+ }), targetGlobalMousePositionRef = React.useRef({
2687
+ x: 0,
2688
+ y: 0
2689
+ }), lerpRafRef = React.useRef(null), lerpActiveRef = React.useRef(!1), [dynamicBorderRadius, setDynamicCornerRadius] = React.useState(CONSTANTS.DEFAULT_CORNER_RADIUS), [userPrefersReducedMotion, setUserPrefersReducedMotion] = React.useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = React.useState(!1), [detectedOverLight, setDetectedOverLight] = React.useState(!1), effectiveBorderRadius = React.useMemo((() => void 0 !== borderRadius ? Math.max(0, borderRadius) : Math.max(0, dynamicBorderRadius)), [ borderRadius, dynamicBorderRadius ]), {glassSize: glassSize} = function({glassRef: glassRef, effectiveBorderRadius: effectiveBorderRadius, cachedRectRef: cachedRectRef}) {
2694
2690
  const [glassSize, setGlassSize] = React.useState({
2695
2691
  width: 270,
2696
2692
  height: 69
@@ -2787,7 +2783,23 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
2787
2783
  const timeoutId = setTimeout(extractRadius, 100);
2788
2784
  return () => clearTimeout(timeoutId);
2789
2785
  }), [ children, debugBorderRadius, contentRef ]),
2790
- // Media query handlers and background detection
2786
+ // Media query detection for reduced motion and high contrast
2787
+ React.useEffect((() => {
2788
+ if ("undefined" == typeof window || "function" != typeof window.matchMedia) return;
2789
+ const mediaQueryReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)"), mediaQueryHighContrast = window.matchMedia("(prefers-contrast: high)");
2790
+ setUserPrefersReducedMotion(mediaQueryReducedMotion.matches), setUserPrefersHighContrast(mediaQueryHighContrast.matches);
2791
+ const handleReducedMotionChange = e => {
2792
+ setUserPrefersReducedMotion(e.matches);
2793
+ }, handleHighContrastChange = e => {
2794
+ setUserPrefersHighContrast(e.matches);
2795
+ };
2796
+ return mediaQueryReducedMotion.addEventListener("change", handleReducedMotionChange),
2797
+ mediaQueryHighContrast.addEventListener("change", handleHighContrastChange), () => {
2798
+ mediaQueryReducedMotion.removeEventListener("change", handleReducedMotionChange),
2799
+ mediaQueryHighContrast.removeEventListener("change", handleHighContrastChange);
2800
+ };
2801
+ }), []),
2802
+ // Background detection for overLight auto-detect
2791
2803
  React.useEffect((() => {
2792
2804
  if (("auto" === overLight || "object" == typeof overLight && null !== overLight) && glassRef.current) {
2793
2805
  const element = glassRef.current, cachedResult = ((parentElement, overLightConfig) => {
@@ -2887,102 +2899,36 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
2887
2899
  }), 150);
2888
2900
  return () => clearTimeout(timeoutId);
2889
2901
  }
2890
- if ("boolean" == typeof overLight && setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
2891
- const mediaQueryReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)"), mediaQueryHighContrast = window.matchMedia("(prefers-contrast: high)");
2892
- setUserPrefersReducedMotion(mediaQueryReducedMotion.matches), setUserPrefersHighContrast(mediaQueryHighContrast.matches);
2893
- const handleReducedMotionChange = e => {
2894
- setUserPrefersReducedMotion(e.matches);
2895
- }, handleHighContrastChange = e => {
2896
- setUserPrefersHighContrast(e.matches);
2897
- };
2898
- return mediaQueryReducedMotion.addEventListener ? (mediaQueryReducedMotion.addEventListener("change", handleReducedMotionChange),
2899
- mediaQueryHighContrast.addEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.addListener && (mediaQueryReducedMotion.addListener(handleReducedMotionChange),
2900
- mediaQueryHighContrast.addListener(handleHighContrastChange)), () => {
2901
- // ignore
2902
- };
2903
- } catch (error) {
2904
- return;
2905
- }
2906
- }), [ overLight, glassRef, debugOverLight ]);
2902
+ "boolean" == typeof overLight && setDetectedOverLight(!1);
2903
+ }), [ overLight, glassRef ]);
2907
2904
  /**
2908
2905
  * Get effective overLight value based on configuration
2909
2906
  */
2910
- const getEffectiveOverLight = React.useCallback((() => "boolean" == typeof overLight ? overLight : ("auto" === overLight || "object" == typeof overLight && null !== overLight) && detectedOverLight), [ overLight, detectedOverLight ]), validateConfigValue = React.useCallback(((value, min, max, defaultValue) => "number" != typeof value || isNaN(value) || !isFinite(value) ? defaultValue : Math.min(max, Math.max(min, value))), []), baseOverLightConfig = React.useMemo((() => {
2911
- const isOverLight = getEffectiveOverLight(), baseConfig = {
2907
+ const getEffectiveOverLight = React.useCallback((() => "boolean" == typeof overLight ? overLight : ("auto" === overLight || "object" == typeof overLight && null !== overLight) && detectedOverLight), [ overLight, detectedOverLight ]), validateConfigValue = React.useCallback(((value, min, max, defaultValue) => "number" != typeof value || isNaN(value) || !isFinite(value) ? defaultValue : Math.min(max, Math.max(min, value))), []), overLightConfig = React.useMemo((() => {
2908
+ const isOverLight = getEffectiveOverLight(), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1, baseConfig = {
2912
2909
  isOverLight: isOverLight,
2913
2910
  threshold: .7,
2914
- opacity: isOverLight ? Math.min(.6, Math.max(.2, .5)) : 0,
2915
- contrast: 1,
2916
- // Base contrast
2917
- brightness: 1,
2918
- // Base brightness
2911
+ opacity: isOverLight ? Math.min(.6, Math.max(.2, .5 * hoverIntensity * activeIntensity)) : 0,
2912
+ contrast: 1.4,
2913
+ brightness: .9,
2919
2914
  saturationBoost: 1.3,
2915
+ // Fixed value — dynamic saturation amplifies perceived displacement
2920
2916
  shadowIntensity: .9,
2921
2917
  borderOpacity: .7
2922
2918
  };
2923
2919
  if ("object" == typeof overLight && null !== overLight) {
2924
- 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);
2925
- return {
2920
+ 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 = {
2926
2921
  ...baseConfig,
2927
2922
  threshold: validatedThreshold,
2928
- opacity: validatedOpacity,
2923
+ opacity: validatedOpacity * hoverIntensity * activeIntensity,
2929
2924
  contrast: validatedContrast,
2930
2925
  brightness: validatedBrightness,
2931
2926
  saturationBoost: validatedSaturationBoost
2932
2927
  };
2928
+ return "undefined" == typeof process || process.env, finalConfig;
2933
2929
  }
2934
- return baseConfig;
2935
- }), [ overLight, getEffectiveOverLight, validateConfigValue ]), overLightConfig = React.useMemo((() => {
2936
- const mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1;
2937
- return {
2938
- isOverLight: baseOverLightConfig.isOverLight,
2939
- threshold: baseOverLightConfig.threshold,
2940
- opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
2941
- contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
2942
- brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
2943
- saturationBoost: baseOverLightConfig.saturationBoost,
2944
- shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
2945
- borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence))
2946
- };
2947
- }), [ baseOverLightConfig, mouseOffset, isHovered, isActive ]), updateRectRef = React.useRef(null), calculateDirectionalScale = React.useCallback((() => {
2948
- if (baseOverLightConfig.isOverLight) return "scale(1)";
2949
- if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return "scale(1)";
2950
- 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({
2951
- x: edgeDistanceX,
2952
- y: edgeDistanceY
2953
- }, {
2954
- x: 0,
2955
- y: 0
2956
- });
2957
- if (edgeDistance > CONSTANTS.ACTIVATION_ZONE) return "scale(1)";
2958
- const fadeInFactor = 1 - edgeDistance / CONSTANTS.ACTIVATION_ZONE, centerDistance = calculateDistance(globalMousePosition, center);
2959
- if (0 === centerDistance) return "scale(1)";
2960
- 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;
2961
- return `scaleX(${Math.max(.8, scaleX)}) scaleY(${Math.max(.8, scaleY)})`;
2962
- }), [ globalMousePosition, elasticity, glassSize, glassRef, baseOverLightConfig ]), calculateFadeInFactor = React.useCallback((() => {
2963
- if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return 0;
2964
- 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({
2965
- x: edgeDistanceX,
2966
- y: edgeDistanceY
2967
- }, {
2968
- x: 0,
2969
- y: 0
2970
- });
2971
- return edgeDistance > CONSTANTS.ACTIVATION_ZONE ? 0 : 1 - edgeDistance / CONSTANTS.ACTIVATION_ZONE;
2972
- }), [ globalMousePosition, glassSize, glassRef ]), calculateElasticTranslation = React.useCallback((() => {
2973
- if (!glassRef.current) return {
2974
- x: 0,
2975
- y: 0
2976
- };
2977
- const fadeInFactor = calculateFadeInFactor(), rect = glassRef.current.getBoundingClientRect(), center = calculateElementCenter(rect);
2978
- return {
2979
- x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
2980
- y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
2981
- };
2982
- }), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = React.useMemo((() => effectiveWithoutEffects ? {
2983
- x: 0,
2984
- y: 0
2985
- } : calculateElasticTranslation()), [ calculateElasticTranslation, effectiveWithoutEffects ]), directionalScale = React.useMemo((() => effectiveWithoutEffects ? "scale(1)" : calculateDirectionalScale()), [ calculateDirectionalScale, effectiveWithoutEffects ]), transformStyle = React.useMemo((() => effectiveWithoutEffects ? isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)" : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) ${isActive && Boolean(onClick) ? "scale(0.96)" : directionalScale}`), [ elasticTranslation, isActive, onClick, directionalScale, effectiveWithoutEffects ]), handleGlobalMousePosition = React.useCallback((globalPos => {
2930
+ return "undefined" == typeof process || process.env, baseConfig;
2931
+ }), [ overLight, getEffectiveOverLight, isHovered, isActive, validateConfigValue, debugOverLight ]), transformStyle = React.useMemo((() => effectiveWithoutEffects || isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)"), [ effectiveWithoutEffects, isActive, onClick ]), updateRectRef = React.useRef(null), handleGlobalMousePosition = React.useCallback((globalPos => {
2986
2932
  if (externalGlobalMousePosition && externalMouseOffset) return;
2987
2933
  if (effectiveWithoutEffects) return;
2988
2934
  const container = mouseContainer?.current || glassRef.current;
@@ -2991,35 +2937,61 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
2991
2937
  let rect = cachedRectRef.current;
2992
2938
  if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
2993
2939
  cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
2994
- const center = calculateElementCenter(rect), newOffset = {
2940
+ const center = calculateElementCenter(rect);
2941
+ // Write raw target — the lerp loop will smoothly pursue it
2942
+ targetMouseOffsetRef.current = {
2995
2943
  x: (globalPos.x - center.x) / rect.width * 100,
2996
2944
  y: (globalPos.y - center.y) / rect.height * 100
2945
+ }, targetGlobalMousePositionRef.current = globalPos;
2946
+ }), [ mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects ]), startLerpLoop = React.useCallback((() => {
2947
+ if (lerpActiveRef.current) return;
2948
+ lerpActiveRef.current = !0;
2949
+ const LERP_T = CONSTANTS.LERP_FACTOR, tick = () => {
2950
+ if (!lerpActiveRef.current) return;
2951
+ const cur = internalMouseOffsetRef.current, tgt = targetMouseOffsetRef.current, dx = tgt.x - cur.x, dy = tgt.y - cur.y;
2952
+ // If we're close enough, snap and park
2953
+ if (Math.abs(dx) < .05 && Math.abs(dy) < .05) internalMouseOffsetRef.current = {
2954
+ ...tgt
2955
+ }, internalGlobalMousePositionRef.current = {
2956
+ ...targetGlobalMousePositionRef.current
2957
+ }; else {
2958
+ internalMouseOffsetRef.current = {
2959
+ x: lerp(cur.x, tgt.x, LERP_T),
2960
+ y: lerp(cur.y, tgt.y, LERP_T)
2961
+ };
2962
+ const curG = internalGlobalMousePositionRef.current, tgtG = targetGlobalMousePositionRef.current;
2963
+ internalGlobalMousePositionRef.current = {
2964
+ x: lerp(curG.x, tgtG.x, LERP_T),
2965
+ y: lerp(curG.y, tgtG.y, LERP_T)
2966
+ };
2967
+ }
2968
+ // Imperative style update with the smoothed values
2969
+ updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
2970
+ mouseOffset: internalMouseOffsetRef.current,
2971
+ globalMousePosition: internalGlobalMousePositionRef.current,
2972
+ glassSize: glassSize,
2973
+ isHovered: isHovered,
2974
+ isActive: isActive,
2975
+ isOverLight: overLightConfig.isOverLight,
2976
+ baseOverLightConfig: overLightConfig,
2977
+ effectiveBorderRadius: effectiveBorderRadius,
2978
+ effectiveWithoutEffects: effectiveWithoutEffects,
2979
+ effectiveReducedMotion: effectiveReducedMotion,
2980
+ elasticity: elasticity,
2981
+ directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
2982
+ onClick: onClick,
2983
+ withLiquidBlur: withLiquidBlur,
2984
+ blurAmount: blurAmount,
2985
+ saturation: saturation,
2986
+ padding: padding
2987
+ }), lerpRafRef.current = requestAnimationFrame(tick);
2997
2988
  };
2998
- // Calculate offset relative to this container
2999
- // Store in refs instead of state
3000
- internalMouseOffsetRef.current = newOffset, internalGlobalMousePositionRef.current = globalPos,
3001
- // Imperative style update
3002
- updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
3003
- mouseOffset: newOffset,
3004
- globalMousePosition: globalPos,
3005
- glassSize: glassSize,
3006
- isHovered: isHovered,
3007
- isActive: isActive,
3008
- isOverLight: baseOverLightConfig.isOverLight,
3009
- baseOverLightConfig: baseOverLightConfig,
3010
- effectiveBorderRadius: effectiveBorderRadius,
3011
- effectiveWithoutEffects: effectiveWithoutEffects,
3012
- effectiveReducedMotion: effectiveReducedMotion,
3013
- elasticity: elasticity,
3014
- directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
3015
- // Simplified directional scale for fast path
3016
- onClick: onClick,
3017
- withLiquidBlur: withLiquidBlur,
3018
- blurAmount: blurAmount,
3019
- saturation: saturation,
3020
- padding: padding
3021
- });
3022
- }), [ mouseContainer, glassRef, wrapperRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects, glassSize, isHovered, isActive, baseOverLightConfig, effectiveBorderRadius, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding ]);
2989
+ // 0.08 lower = more viscous
2990
+ lerpRafRef.current = requestAnimationFrame(tick);
2991
+ }), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding ]), stopLerpLoop = React.useCallback((() => {
2992
+ lerpActiveRef.current = !1, null !== lerpRafRef.current && (cancelAnimationFrame(lerpRafRef.current),
2993
+ lerpRafRef.current = null);
2994
+ }), []);
3023
2995
  /**
3024
2996
  * Validate and clamp a numeric config value
3025
2997
  */
@@ -3027,7 +2999,10 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
3027
2999
  React.useEffect((() => {
3028
3000
  if (externalGlobalMousePosition && externalMouseOffset) return;
3029
3001
  if (effectiveWithoutEffects) return;
3030
- const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition), container = mouseContainer?.current || glassRef.current;
3002
+ const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition);
3003
+ // Start the lerp loop — it will smoothly chase the target
3004
+ startLerpLoop();
3005
+ const container = mouseContainer?.current || glassRef.current;
3031
3006
  let resizeObserver = null;
3032
3007
  return container && "undefined" != typeof ResizeObserver && (resizeObserver = new ResizeObserver((() => {
3033
3008
  null !== updateRectRef.current && cancelAnimationFrame(updateRectRef.current), updateRectRef.current = requestAnimationFrame((() => {
@@ -3035,10 +3010,10 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
3035
3010
  container && (cachedRectRef.current = container.getBoundingClientRect()), updateRectRef.current = null;
3036
3011
  }));
3037
3012
  })), resizeObserver.observe(container)), () => {
3038
- unsubscribe(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
3013
+ unsubscribe(), stopLerpLoop(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
3039
3014
  updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
3040
3015
  };
3041
- }), [ handleGlobalMousePosition, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects ]),
3016
+ }), [ handleGlobalMousePosition, startLerpLoop, stopLerpLoop, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects ]),
3042
3017
  // Also call updateStyles on other state changes (hover, active, etc)
3043
3018
  React.useEffect((() => {
3044
3019
  updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
@@ -3047,22 +3022,22 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
3047
3022
  glassSize: glassSize,
3048
3023
  isHovered: isHovered,
3049
3024
  isActive: isActive,
3050
- isOverLight: baseOverLightConfig.isOverLight,
3051
- baseOverLightConfig: baseOverLightConfig,
3025
+ isOverLight: overLightConfig.isOverLight,
3026
+ baseOverLightConfig: overLightConfig,
3052
3027
  effectiveBorderRadius: effectiveBorderRadius,
3053
3028
  effectiveWithoutEffects: effectiveWithoutEffects,
3054
3029
  effectiveReducedMotion: effectiveReducedMotion,
3055
3030
  elasticity: elasticity,
3056
- directionalScale: directionalScale,
3031
+ directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
3057
3032
  onClick: onClick,
3058
3033
  withLiquidBlur: withLiquidBlur,
3059
3034
  blurAmount: blurAmount,
3060
3035
  saturation: saturation,
3061
3036
  padding: padding
3062
3037
  });
3063
- }), [ isHovered, isActive, glassSize, baseOverLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, directionalScale, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation, padding, onClick ]);
3038
+ }), [ isHovered, isActive, glassSize, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation, padding, onClick ]);
3064
3039
  // Event handlers
3065
- const handleMouseEnter = React.useCallback((() => setIsHovered(!0)), []), handleMouseLeave = React.useCallback((() => setIsHovered(!1)), []), handleMouseDown = React.useCallback((() => setIsActive(!0)), []), handleMouseUp = React.useCallback((() => setIsActive(!1)), []), handleMouseMove = React.useCallback((_e => {}), []), handleKeyDown = React.useCallback((e => {
3040
+ const handleMouseEnter = React.useCallback((() => setIsHovered(!0)), []), handleMouseLeave = React.useCallback((() => setIsHovered(!1)), []), handleMouseDown = React.useCallback((() => setIsActive(!0)), []), handleMouseUp = React.useCallback((() => setIsActive(!1)), []), handleKeyDown = React.useCallback((e => {
3066
3041
  !onClick || "Enter" !== e.key && " " !== e.key || (e.preventDefault(), onClick());
3067
3042
  }), [ onClick ]);
3068
3043
  return {
@@ -3080,14 +3055,11 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
3080
3055
  mouseOffset: mouseOffset,
3081
3056
  // This is now static (refs or props) unless prop changes
3082
3057
  overLightConfig: overLightConfig,
3083
- elasticTranslation: elasticTranslation,
3084
- directionalScale: directionalScale,
3085
3058
  transformStyle: transformStyle,
3086
3059
  handleMouseEnter: handleMouseEnter,
3087
3060
  handleMouseLeave: handleMouseLeave,
3088
3061
  handleMouseDown: handleMouseDown,
3089
3062
  handleMouseUp: handleMouseUp,
3090
- handleMouseMove: handleMouseMove,
3091
3063
  handleKeyDown: handleKeyDown
3092
3064
  };
3093
3065
  }
@@ -3185,25 +3157,56 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
3185
3157
  withLiquidBlur: withLiquidBlur,
3186
3158
  padding: padding,
3187
3159
  style: style
3188
- }), isOverLight = React.useMemo((() => overLightConfig?.isOverLight), [ overLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, baseStyle = {
3189
- ...style,
3190
- ...!effectiveWithoutEffects && {
3191
- transform: transformStyle
3160
+ }), isOverLight = React.useMemo((() => overLightConfig.isOverLight), [ overLightConfig.isOverLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, {zIndex: customZIndex, ...restStyle} = style, isFixedOrSticky = "fixed" === restStyle.position || "sticky" === restStyle.position, rootLayoutStyle = React.useMemo((() => {
3161
+ if (!isFixedOrSticky) return {};
3162
+ const {position: p, top: t, left: l, right: r, bottom: b} = restStyle;
3163
+ return {
3164
+ ...p && {
3165
+ position: p
3166
+ },
3167
+ ...void 0 !== t && {
3168
+ top: t
3169
+ },
3170
+ ...void 0 !== l && {
3171
+ left: l
3172
+ },
3173
+ ...void 0 !== r && {
3174
+ right: r
3175
+ },
3176
+ ...void 0 !== b && {
3177
+ bottom: b
3178
+ }
3179
+ };
3180
+ }), [ isFixedOrSticky, restStyle ]), baseStyle = React.useMemo((() => {
3181
+ if (isFixedOrSticky) {
3182
+ const {position: _p, top: _t, left: _l, right: _r, bottom: _b, ...visualStyle} = restStyle;
3183
+ return {
3184
+ ...visualStyle,
3185
+ ...!effectiveWithoutEffects && {
3186
+ transform: transformStyle
3187
+ }
3188
+ };
3192
3189
  }
3193
- }, componentClassName = [ ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`, effectiveWithoutEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`, className ].filter(Boolean).join(" "), positionStyles = React.useMemo((() => ({
3194
- position: style.position || "absolute",
3195
- top: style.top || 0,
3196
- left: style.left || 0
3197
- })), [ style.position, style.top, style.left ]), adjustedSize = React.useMemo((() => {
3190
+ return {
3191
+ ...restStyle,
3192
+ ...!effectiveWithoutEffects && {
3193
+ transform: transformStyle
3194
+ }
3195
+ };
3196
+ }), [ isFixedOrSticky, restStyle, effectiveWithoutEffects, transformStyle ]), componentClassName = [ ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`, effectiveWithoutEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`, className ].filter(Boolean).join(" "), positionStyles = React.useMemo((() => ({
3197
+ position: isFixedOrSticky ? "absolute" : restStyle.position || "absolute",
3198
+ top: isFixedOrSticky ? 0 : restStyle.top || 0,
3199
+ left: isFixedOrSticky ? 0 : restStyle.left || 0
3200
+ })), [ isFixedOrSticky, restStyle.position, restStyle.top, restStyle.left ]), adjustedSize = React.useMemo((() => {
3198
3201
  const resolveSize = (propValue, styleValue, measuredSize) => {
3199
3202
  const explicitSize = propValue ?? styleValue;
3200
3203
  return void 0 !== explicitSize ? "number" == typeof explicitSize ? `${explicitSize}px` : explicitSize : "fixed" === positionStyles.position ? `${Math.max(measuredSize, 0)}px` : "100%";
3201
3204
  };
3202
3205
  return {
3203
- width: resolveSize(width, style.width, glassSize.width),
3204
- height: resolveSize(height, style.height, glassSize.height)
3206
+ width: resolveSize(width, restStyle.width, glassSize.width),
3207
+ height: resolveSize(height, restStyle.height, glassSize.height)
3205
3208
  };
3206
- }), [ width, height, style.width, style.height, positionStyles.position, glassSize.width, glassSize.height ]), gradientValues = React.useMemo((() => {
3209
+ }), [ width, height, restStyle.width, restStyle.height, positionStyles.position, glassSize.width, glassSize.height ]), gradientValues = React.useMemo((() => {
3207
3210
  const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT;
3208
3211
  return {
3209
3212
  borderGradientAngle: GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER,
@@ -3245,6 +3248,9 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
3245
3248
  }), [ isHovered, isActive, isOverLight, overLightConfig.opacity ]), glassVars = React.useMemo((() => {
3246
3249
  const whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE, blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK, {borderGradientAngle: borderGradientAngle, borderStop1: borderStop1, borderStop2: borderStop2, borderOpacities: borderOpacities, hoverPositions: hoverPositions, basePosition: basePosition, mx: mx, my: my, absMx: absMx, absMy: absMy} = gradientValues, configBorderOpacity = overLightConfig?.borderOpacity ?? 1;
3247
3250
  return {
3251
+ ...void 0 !== customZIndex && {
3252
+ "--atomix-glass-base-z-index": customZIndex
3253
+ },
3248
3254
  "--atomix-glass-radius": `${effectiveBorderRadius}px`,
3249
3255
  "--atomix-glass-transform": transformStyle || "none",
3250
3256
  "--atomix-glass-position": positionStyles.position,
@@ -3265,22 +3271,19 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
3265
3271
  "--atomix-glass-base-opacity": opacityValues.base,
3266
3272
  "--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})`,
3267
3273
  "--atomix-glass-overlay-opacity": opacityValues.over,
3268
- "--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})`
3274
+ "--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})`,
3275
+ "--atomix-glass-overlay-highlight-opacity": opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER,
3276
+ "--atomix-glass-overlay-highlight-bg": `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}%)`
3269
3277
  };
3270
- }), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle, positionStyles, adjustedSize, isOverLight, overLightConfig.borderOpacity ]), renderBackgroundLayer = layerType => jsxRuntime.jsx("div", {
3271
- 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(" "),
3272
- style: {
3273
- ...positionStyles,
3274
- height: adjustedSize.height,
3275
- width: adjustedSize.width,
3276
- borderRadius: `${effectiveBorderRadius}px`,
3277
- transform: baseStyle.transform
3278
- }
3278
+ }), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle, positionStyles, adjustedSize, isOverLight, overLightConfig.borderOpacity, customZIndex ]), renderBackgroundLayer = layerType => jsxRuntime.jsx("div", {
3279
+ 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(" ")
3279
3280
  });
3280
3281
  return jsxRuntime.jsxs("div", {
3281
3282
  ...rest,
3282
3283
  className: componentClassName,
3283
- style: glassVars,
3284
+ style: {
3285
+ ...glassVars
3286
+ },
3284
3287
  role: role || (onClick ? "button" : void 0),
3285
3288
  tabIndex: onClick ? tabIndex ?? 0 : tabIndex,
3286
3289
  "aria-label": ariaLabel,
@@ -3292,7 +3295,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
3292
3295
  ref: glassRef,
3293
3296
  contentRef: contentRef,
3294
3297
  className: className,
3295
- style: baseStyle,
3298
+ style: rootLayoutStyle,
3296
3299
  borderRadius: effectiveBorderRadius,
3297
3300
  displacementScale: effectiveWithoutEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
3298
3301
  blurAmount: effectiveWithoutEffects ? 0 : blurAmount,
@@ -3343,11 +3346,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
3343
3346
  }), jsxRuntime.jsx("div", {
3344
3347
  className: ATOMIX_GLASS.OVERLAY_LAYER_CLASS
3345
3348
  }), jsxRuntime.jsx("div", {
3346
- className: ATOMIX_GLASS.OVERLAY_HIGHLIGHT_CLASS,
3347
- style: {
3348
- opacity: opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER,
3349
- 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}%)`
3350
- }
3349
+ className: ATOMIX_GLASS.OVERLAY_HIGHLIGHT_CLASS
3351
3350
  }) ]
3352
3351
  }), withBorder && jsxRuntime.jsxs(jsxRuntime.Fragment, {
3353
3352
  children: [ jsxRuntime.jsx("span", {
@@ -12373,96 +12372,6 @@ const DEFAULT_ATOMIX_FONTS = [ {
12373
12372
  };
12374
12373
  }
12375
12374
 
12376
- /**
12377
- * Custom hook for managing GlassContainer state and interactions
12378
- */ function useGlassContainer(props) {
12379
- const {glassSize: glassSize = {
12380
- width: 270,
12381
- height: 69
12382
- }, elasticity: elasticity = .15, mouseContainer: mouseContainer, globalMousePos: externalGlobalMousePos, mouseOffset: externalMouseOffset} = props, filterId = React.useId(), glassRef = React.useRef(null), [isHovered, setIsHovered] = React.useState(!1), [isActive, setIsActive] = React.useState(!1), [currentGlassSize, setCurrentGlassSize] = React.useState(glassSize), [internalGlobalMousePos, setInternalGlobalMousePos] = React.useState({
12383
- x: 0,
12384
- y: 0
12385
- }), [internalMouseOffset, setInternalMouseOffset] = React.useState({
12386
- x: 0,
12387
- y: 0
12388
- }), globalMousePos = externalGlobalMousePos || internalGlobalMousePos, mouseOffset = externalMouseOffset || internalMouseOffset, handleMouseMove = React.useCallback((e => {
12389
- const container = mouseContainer?.current || glassRef.current;
12390
- if (!container) return;
12391
- const rect = container.getBoundingClientRect(), centerX = rect.left + rect.width / 2, centerY = rect.top + rect.height / 2;
12392
- setInternalMouseOffset({
12393
- x: (e.clientX - centerX) / rect.width * 100,
12394
- y: (e.clientY - centerY) / rect.height * 100
12395
- }), setInternalGlobalMousePos({
12396
- x: e.clientX,
12397
- y: e.clientY
12398
- });
12399
- }), [ mouseContainer ]);
12400
- // Set up mouse tracking if no external mouse position is provided
12401
- React.useEffect((() => {
12402
- if (externalGlobalMousePos && externalMouseOffset) return;
12403
- const container = mouseContainer?.current || glassRef.current;
12404
- return container ? (container.addEventListener("mousemove", handleMouseMove), () => container.removeEventListener("mousemove", handleMouseMove)) : void 0;
12405
- }), [ handleMouseMove, mouseContainer, externalGlobalMousePos, externalMouseOffset ]);
12406
- // Calculate directional scaling based on mouse position
12407
- const calculateDirectionalScale = React.useCallback((() => {
12408
- if (!globalMousePos.x || !globalMousePos.y || !glassRef.current) return "scale(1)";
12409
- const rect = glassRef.current.getBoundingClientRect(), pillCenterX = rect.left + rect.width / 2, pillCenterY = rect.top + rect.height / 2, pillWidth = currentGlassSize.width, pillHeight = currentGlassSize.height, deltaX = globalMousePos.x - pillCenterX, deltaY = globalMousePos.y - pillCenterY, edgeDistanceX = Math.max(0, Math.abs(deltaX) - pillWidth / 2), edgeDistanceY = Math.max(0, Math.abs(deltaY) - pillHeight / 2), edgeDistance = Math.sqrt(edgeDistanceX * edgeDistanceX + edgeDistanceY * edgeDistanceY);
12410
- if (edgeDistance > 200) return "scale(1)";
12411
- const fadeInFactor = 1 - edgeDistance / 200, centerDistance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
12412
- if (0 === centerDistance) return "scale(1)";
12413
- 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;
12414
- return `scaleX(${Math.max(.8, scaleX)}) scaleY(${Math.max(.8, scaleY)})`;
12415
- }), [ globalMousePos, elasticity, currentGlassSize ]), calculateElasticTranslation = React.useCallback((() => {
12416
- if (!glassRef.current) return {
12417
- x: 0,
12418
- y: 0
12419
- };
12420
- const rect = glassRef.current.getBoundingClientRect(), pillCenterX = rect.left + rect.width / 2, pillCenterY = rect.top + rect.height / 2, pillWidth = currentGlassSize.width, pillHeight = currentGlassSize.height, edgeDistanceX = Math.max(0, Math.abs(globalMousePos.x - pillCenterX) - pillWidth / 2), edgeDistanceY = Math.max(0, Math.abs(globalMousePos.y - pillCenterY) - pillHeight / 2), edgeDistance = Math.sqrt(edgeDistanceX * edgeDistanceX + edgeDistanceY * edgeDistanceY), fadeInFactor = edgeDistance > 200 ? 0 : 1 - edgeDistance / 200;
12421
- return {
12422
- x: (globalMousePos.x - pillCenterX) * elasticity * .1 * fadeInFactor,
12423
- y: (globalMousePos.y - pillCenterY) * elasticity * .1 * fadeInFactor
12424
- };
12425
- }), [ globalMousePos, elasticity, currentGlassSize ]);
12426
- // Calculate elastic translation
12427
- // Update glass size
12428
- React.useEffect((() => {
12429
- const updateGlassSize = () => {
12430
- if (glassRef.current) {
12431
- const rect = glassRef.current.getBoundingClientRect();
12432
- setCurrentGlassSize({
12433
- width: rect.width,
12434
- height: rect.height
12435
- });
12436
- }
12437
- };
12438
- return updateGlassSize(), window.addEventListener("resize", updateGlassSize), () => window.removeEventListener("resize", updateGlassSize);
12439
- }), []);
12440
- const handleMouseEnter = React.useCallback((() => {
12441
- setIsHovered(!0);
12442
- }), []), handleMouseLeave = React.useCallback((() => {
12443
- setIsHovered(!1);
12444
- }), []), handleMouseDown = React.useCallback((() => {
12445
- setIsActive(!0);
12446
- }), []), handleMouseUp = React.useCallback((() => {
12447
- setIsActive(!1);
12448
- }), []);
12449
- return {
12450
- filterId: filterId,
12451
- glassRef: glassRef,
12452
- isHovered: isHovered,
12453
- isActive: isActive,
12454
- currentGlassSize: currentGlassSize,
12455
- globalMousePos: globalMousePos,
12456
- mouseOffset: mouseOffset,
12457
- calculateDirectionalScale: calculateDirectionalScale,
12458
- calculateElasticTranslation: calculateElasticTranslation,
12459
- handleMouseEnter: handleMouseEnter,
12460
- handleMouseLeave: handleMouseLeave,
12461
- handleMouseDown: handleMouseDown,
12462
- handleMouseUp: handleMouseUp
12463
- };
12464
- }
12465
-
12466
12375
  /**
12467
12376
  * Radio state and functionality
12468
12377
  * @param initialProps - Initial radio properties
@@ -12955,7 +12864,6 @@ var composablesImport = Object.freeze({
12955
12864
  useEdgePanel: useEdgePanel,
12956
12865
  useForm: useForm,
12957
12866
  useFormGroup: useFormGroup,
12958
- useGlassContainer: useGlassContainer,
12959
12867
  useHero: useHero,
12960
12868
  useInput: useInput,
12961
12869
  useLineChart: useLineChart,
@@ -15035,17 +14943,18 @@ const Navbar = React.forwardRef((({brand: brand, children: children, variant: v
15035
14943
  }, glassProps = !0 === glass ? defaultGlassProps : {
15036
14944
  ...defaultGlassProps,
15037
14945
  ...glass
15038
- };
14946
+ }, isFixed = "fixed" === position || "fixed-bottom" === position;
15039
14947
  return jsxRuntime.jsx(AtomixGlass, {
15040
14948
  ...glassProps,
15041
14949
  style: {
15042
- ..."fixed" === position && {
15043
- position: "fixed"
15044
- },
15045
- left: 0,
15046
- right: 0,
15047
- top: 0,
15048
- zIndex: 1e3
14950
+ ...isFixed && {
14951
+ position: "fixed",
14952
+ top: "fixed" === position ? 0 : void 0,
14953
+ bottom: "fixed-bottom" === position ? 0 : void 0,
14954
+ left: 0,
14955
+ right: 0,
14956
+ zIndex: 1030
14957
+ }
15049
14958
  },
15050
14959
  children: jsxRuntime.jsx("nav", {
15051
14960
  ref: ref,
@@ -25595,8 +25504,8 @@ function(component, props) {
25595
25504
  * Hook to merge default props with provided props
25596
25505
  */ , exports.useComponentTheme = useComponentTheme, exports.useDataTable = useDataTable,
25597
25506
  exports.useEdgePanel = useEdgePanel, exports.useForm = useForm, exports.useFormGroup = useFormGroup,
25598
- exports.useGlassContainer = useGlassContainer, exports.useHero = useHero, exports.useHistory = useHistory,
25599
- exports.useInput = useInput, exports.useLineChart = useLineChart, exports.useMergedProps = function(defaultProps, props) {
25507
+ exports.useHero = useHero, exports.useHistory = useHistory, exports.useInput = useInput,
25508
+ exports.useLineChart = useLineChart, exports.useMergedProps = function(defaultProps, props) {
25600
25509
  return React.useMemo((() => ({
25601
25510
  ...defaultProps,
25602
25511
  ...props