@shohojdhara/atomix 0.6.1 → 0.6.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 (67) hide show
  1. package/README.md +510 -106
  2. package/dist/atomix.css +30 -24
  3. package/dist/atomix.css.map +1 -1
  4. package/dist/atomix.min.css +6 -6
  5. package/dist/atomix.min.css.map +1 -1
  6. package/dist/atomix.umd.js +1 -1
  7. package/dist/atomix.umd.js.map +1 -1
  8. package/dist/atomix.umd.min.js +1 -1
  9. package/dist/charts.d.ts +11 -2
  10. package/dist/charts.js +294 -139
  11. package/dist/charts.js.map +1 -1
  12. package/dist/core.d.ts +14 -39
  13. package/dist/core.js +297 -145
  14. package/dist/core.js.map +1 -1
  15. package/dist/forms.d.ts +11 -1
  16. package/dist/forms.js +385 -185
  17. package/dist/forms.js.map +1 -1
  18. package/dist/heavy.d.ts +9 -0
  19. package/dist/heavy.js +297 -143
  20. package/dist/heavy.js.map +1 -1
  21. package/dist/index.d.ts +156 -164
  22. package/dist/index.esm.js +391 -203
  23. package/dist/index.esm.js.map +1 -1
  24. package/dist/index.js +391 -203
  25. package/dist/index.js.map +1 -1
  26. package/dist/index.min.js +1 -1
  27. package/dist/index.min.js.map +1 -1
  28. package/dist/theme.d.ts +14 -6
  29. package/dist/theme.js +2 -9
  30. package/dist/theme.js.map +1 -1
  31. package/package.json +26 -26
  32. package/src/components/AtomixGlass/AtomixGlass.tsx +1 -1
  33. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +8 -1
  34. package/src/components/AtomixGlass/deprecated/AtomixGlass.deprecated.tsx +390 -0
  35. package/src/components/AtomixGlass/glass-utils.ts +29 -0
  36. package/src/components/AtomixGlass/stories/Playground.stories.tsx +32 -1
  37. package/src/components/Button/Button.stories.tsx +1 -1
  38. package/src/components/Button/Button.tsx +6 -5
  39. package/src/components/Card/Card.tsx +2 -2
  40. package/src/components/Dropdown/Dropdown.tsx +1 -0
  41. package/src/components/EdgePanel/EdgePanel.tsx +1 -3
  42. package/src/components/Form/Select.test.tsx +75 -0
  43. package/src/components/Form/Select.tsx +348 -252
  44. package/src/components/Form/SelectOption.tsx +16 -10
  45. package/src/components/index.ts +1 -1
  46. package/src/layouts/CssGrid/index.ts +1 -0
  47. package/src/lib/composables/shared-mouse-tracker.ts +62 -6
  48. package/src/lib/composables/useAtomixGlass.ts +241 -139
  49. package/src/lib/composables/useAtomixGlassStyles.ts +201 -149
  50. package/src/lib/constants/components.ts +54 -35
  51. package/src/lib/theme/config/configLoader.ts +1 -1
  52. package/src/lib/theme/test/testTheme.ts +2 -2
  53. package/src/lib/theme/utils/themeUtils.ts +98 -110
  54. package/src/lib/types/components.ts +29 -65
  55. package/src/styles/01-settings/_settings.spacing.scss +6 -1
  56. package/src/styles/03-generic/_generic.reset.scss +1 -1
  57. package/src/styles/06-components/_components.atomix-glass.scss +20 -29
  58. package/src/styles/06-components/_components.data-table.scss +5 -4
  59. package/src/styles/06-components/_components.dynamic-background.scss +9 -8
  60. package/src/styles/06-components/_components.footer.scss +8 -7
  61. package/src/styles/06-components/_components.hero.scss +2 -2
  62. package/src/styles/06-components/_components.messages.scss +16 -16
  63. package/src/styles/06-components/_components.navbar.scss +2 -0
  64. package/src/styles/06-components/_components.select.scss +15 -2
  65. package/src/styles/06-components/_components.upload.scss +3 -3
  66. package/CHANGELOG.md +0 -165
  67. package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +0 -215
package/dist/charts.js CHANGED
@@ -502,12 +502,23 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
502
502
  },
503
503
  DEFAULTS: {
504
504
  DISPLACEMENT_SCALE: 70,
505
- BLUR_AMOUNT: 0,
506
- SATURATION: 140,
507
- ABERRATION_INTENSITY: 2,
505
+ get BLUR_AMOUNT() {
506
+ return .15 * this.DISPLACEMENT_SCALE;
507
+ // Dynamically computed based on displacement
508
+ },
509
+ get SATURATION() {
510
+ return 100 + .5 * this.DISPLACEMENT_SCALE;
511
+ // Saturate relative to intensity
512
+ },
513
+ get ABERRATION_INTENSITY() {
514
+ return .03 * this.DISPLACEMENT_SCALE;
515
+ // Scale aberration with displacement
516
+ },
508
517
  ELASTICITY: .15,
509
- CORNER_RADIUS: 20,
510
- // Default border-radius matching design system
518
+ get CORNER_RADIUS() {
519
+ return 16;
520
+ // Use 16 to match SCSS design system (was 20)
521
+ },
511
522
  PADDING: "0",
512
523
  MODE: "standard",
513
524
  OVER_LIGHT: !1,
@@ -529,6 +540,15 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
529
540
  MIN_BLUR: .1,
530
541
  MOUSE_INFLUENCE_DIVISOR: 100,
531
542
  EDGE_FADE_PIXELS: 2,
543
+ // Elasticity physics constants
544
+ ELASTICITY_TRANSLATION_FACTOR: .1,
545
+ ELASTICITY_DISTANCE_THRESHOLD: 200,
546
+ ELASTICITY_COMPRESSION_FACTOR: .3,
547
+ ELASTICITY_STIFFNESS: .1,
548
+ ELASTICITY_DAMPING: .76,
549
+ ELASTICITY_VELOCITY_FACTOR: .65,
550
+ ELASTICITY_STRETCH_RATIO: .45,
551
+ ELASTICITY_MAGNIFICATION_BASE: 1.02,
532
552
  // Note: This default must match the SCSS variable --atomix-radius-md
533
553
  // @see src/styles/01-settings/_settings.global.scss
534
554
  DEFAULT_CORNER_RADIUS: 16,
@@ -545,84 +565,126 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
545
565
  // Base angle for border gradients (degrees)
546
566
  ANGLE_MULTIPLIER: 1.2,
547
567
  // Multiplier for mouse influence on angle
568
+ VELOCITY_ANGLE_MULTIPLIER: 2.5,
569
+ // How much velocity affects gradient rotation
570
+ CHROMATIC_OFFSET: 1.5,
571
+ // Degree offset for chromatic rim layers
548
572
  BORDER_STOP_1: {
549
573
  MIN: 10,
550
574
  // Minimum percentage for border stop 1
551
575
  BASE: 33,
552
576
  // Base percentage for border stop 1
553
- MULTIPLIER: .3
577
+ get MULTIPLIER() {
578
+ return .009 * this.BASE;
579
+ }
554
580
  },
555
581
  BORDER_STOP_2: {
556
582
  MAX: 90,
557
583
  // Maximum percentage for border stop 2
558
584
  BASE: 66,
559
585
  // Base percentage for border stop 2
560
- MULTIPLIER: .4
586
+ get MULTIPLIER() {
587
+ return .006 * this.BASE;
588
+ }
561
589
  },
562
590
  BORDER_OPACITY: {
563
591
  BASE_1: .12,
564
592
  // Base opacity for border gradient 1
565
- BASE_2: .4,
593
+ get BASE_2() {
594
+ return 3.33 * this.BASE_1;
595
+ },
566
596
  // Base opacity for border gradient 2
567
- BASE_3: .32,
597
+ get BASE_3() {
598
+ return 2.66 * this.BASE_1;
599
+ },
568
600
  // Base opacity for border gradient 3
569
- BASE_4: .6,
601
+ get BASE_4() {
602
+ return 5 * this.BASE_1;
603
+ },
570
604
  // Base opacity for border gradient 4
571
- MULTIPLIER_LOW: .008,
605
+ get MULTIPLIER_LOW() {
606
+ return .066 * this.BASE_1;
607
+ },
572
608
  // Low multiplier for mouse influence on opacity
573
- MULTIPLIER_HIGH: .012
609
+ get MULTIPLIER_HIGH() {
610
+ return .1 * this.BASE_1;
611
+ }
574
612
  },
575
613
  CENTER_POSITION: 50,
576
614
  // Center position percentage (50%)
577
615
  HOVER_POSITION: {
578
616
  DIVISOR_1: 2,
579
617
  // Divisor for hover 1 position calculation
580
- DIVISOR_2: 1.5,
618
+ get DIVISOR_2() {
619
+ return .75 * this.DIVISOR_1;
620
+ },
581
621
  // Divisor for hover 2 position calculation
582
- MULTIPLIER_3: 1
622
+ get MULTIPLIER_3() {
623
+ return .5 * this.DIVISOR_1;
624
+ }
583
625
  },
584
- BASE_LAYER_MULTIPLIER: .5
626
+ get BASE_LAYER_MULTIPLIER() {
627
+ return .5;
628
+ }
585
629
  },
586
630
  // Gradient opacity values for hover effects
587
631
  GRADIENT_OPACITY: {
588
632
  HOVER_1: {
589
633
  BLACK_START: .3,
590
634
  // Start opacity for black hover 1
591
- BLACK_MID: .1,
635
+ get BLACK_MID() {
636
+ return this.BLACK_START / 3;
637
+ },
592
638
  // Mid opacity for black hover 1
593
639
  BLACK_STOP: 30,
594
640
  // Stop percentage for black hover 1
595
- BLACK_END: 60,
641
+ get BLACK_END() {
642
+ return 2 * this.BLACK_STOP;
643
+ },
596
644
  // End percentage for black hover 1
597
645
  WHITE_START: .5,
598
646
  // Start opacity for white hover 1
599
- WHITE_STOP: 50
647
+ get WHITE_STOP() {
648
+ return this.BLACK_END - 10;
649
+ }
600
650
  },
601
651
  HOVER_2: {
602
652
  BLACK_START: .4,
603
653
  // Start opacity for black hover 2
604
- BLACK_MID: .15,
654
+ get BLACK_MID() {
655
+ return .375 * this.BLACK_START;
656
+ },
605
657
  // Mid opacity for black hover 2
606
658
  BLACK_STOP: 40,
607
659
  // Stop percentage for black hover 2
608
- BLACK_END: 80,
660
+ get BLACK_END() {
661
+ return 2 * this.BLACK_STOP;
662
+ },
609
663
  // End percentage for black hover 2
610
664
  WHITE_START: 1,
611
665
  // Start opacity for white hover 2
612
- WHITE_STOP: 80
666
+ get WHITE_STOP() {
667
+ return this.BLACK_END;
668
+ }
613
669
  },
614
670
  HOVER_3: {
615
671
  BLACK_START: .5,
616
672
  // Start opacity for black hover 3
617
- BLACK_MID: .2,
673
+ get BLACK_MID() {
674
+ return .4 * this.BLACK_START;
675
+ },
618
676
  // Mid opacity for black hover 3
619
677
  BLACK_STOP: 50,
620
678
  // Stop percentage for black hover 3
621
- BLACK_END: 100,
679
+ get BLACK_END() {
680
+ return 2 * this.BLACK_STOP;
681
+ },
622
682
  // End percentage for black hover 3
623
683
  WHITE_START: 1,
624
684
  // Start opacity for white hover 3
625
- WHITE_STOP: 100
685
+ get WHITE_STOP() {
686
+ return this.BLACK_END;
687
+ }
626
688
  }
627
689
  },
628
690
  // Base and overlay gradient constants
@@ -631,34 +693,54 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
631
693
  // Gradient angle in degrees
632
694
  BLACK_START_BASE: .15,
633
695
  // Base start opacity for black
634
- BLACK_START_MULTIPLIER: .003,
696
+ get BLACK_START_MULTIPLIER() {
697
+ return .02 * this.BLACK_START_BASE;
698
+ },
635
699
  // Multiplier for mouse X influence on start
636
700
  BLACK_MID_BASE: .1,
637
701
  // Base mid opacity for black
638
- BLACK_MID_MULTIPLIER: .002,
702
+ get BLACK_MID_MULTIPLIER() {
703
+ return .02 * this.BLACK_MID_BASE;
704
+ },
639
705
  // Multiplier for mouse Y influence on mid
640
706
  BLACK_MID_STOP: 50,
641
707
  // Mid stop percentage
642
- BLACK_END_BASE: .18,
708
+ get BLACK_END_BASE() {
709
+ return 1.2 * this.BLACK_START_BASE;
710
+ },
643
711
  // Base end opacity for black
644
- BLACK_END_MULTIPLIER: .004,
712
+ get BLACK_END_MULTIPLIER() {
713
+ return .022 * this.BLACK_END_BASE;
714
+ },
645
715
  // Multiplier for mouse X influence on end
646
- WHITE_OPACITY: .1
716
+ get WHITE_OPACITY() {
717
+ return .666 * this.BLACK_START_BASE;
718
+ }
647
719
  },
648
720
  OVERLAY_GRADIENT: {
649
721
  BLACK_START_BASE: .12,
650
722
  // Base start opacity for black overlay
651
- BLACK_START_MULTIPLIER: .003,
723
+ get BLACK_START_MULTIPLIER() {
724
+ return .025 * this.BLACK_START_BASE;
725
+ },
652
726
  // Multiplier for mouse X influence on start
653
- BLACK_MID: .06,
727
+ get BLACK_MID() {
728
+ return .5 * this.BLACK_START_BASE;
729
+ },
654
730
  // Mid opacity for black overlay
655
731
  BLACK_MID_STOP: 40,
656
732
  // Mid stop percentage
657
- BLACK_END_BASE: .15,
733
+ get BLACK_END_BASE() {
734
+ return 1.25 * this.BLACK_START_BASE;
735
+ },
658
736
  // Base end opacity for black overlay
659
- BLACK_END_MULTIPLIER: .003,
737
+ get BLACK_END_MULTIPLIER() {
738
+ return .02 * this.BLACK_END_BASE;
739
+ },
660
740
  // Multiplier for mouse Y influence on end
661
- WHITE_OPACITY: .05
741
+ get WHITE_OPACITY() {
742
+ return .416 * this.BLACK_START_BASE;
743
+ }
662
744
  },
663
745
  // Overlay highlight constants
664
746
  OVERLAY_HIGHLIGHT: {
@@ -668,9 +750,13 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
668
750
  // Y position percentage
669
751
  WHITE_OPACITY: .4,
670
752
  // White opacity in gradient
671
- STOP: 60,
753
+ get STOP() {
754
+ return 150 * this.WHITE_OPACITY;
755
+ },
672
756
  // Stop percentage
673
- OPACITY_MULTIPLIER: .7
757
+ get OPACITY_MULTIPLIER() {
758
+ return 1.75 * this.WHITE_OPACITY;
759
+ }
674
760
  },
675
761
  // Displacement and aberration multipliers
676
762
  MULTIPLIERS: {
@@ -1580,11 +1666,7 @@ const ChartToolbar = memo( forwardRef((({chartType: chartType = "line", groups:
1580
1666
 
1581
1667
  ChartToolbar.displayName = "ChartToolbar";
1582
1668
 
1583
- const {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateDistance = (pos1, pos2) => {
1584
- if (!pos1 || !pos2 || "number" != typeof pos1.x || "number" != typeof pos1.y || "number" != typeof pos2.x || "number" != typeof pos2.y) return 0;
1585
- const deltaX = pos1.x - pos2.x, deltaY = pos1.y - pos2.y;
1586
- return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
1587
- }, calculateElementCenter = rect => rect ? {
1669
+ const {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateElementCenter = rect => rect ? {
1588
1670
  x: rect.left + rect.width / 2,
1589
1671
  y: rect.top + rect.height / 2
1590
1672
  } : {
@@ -1656,7 +1738,16 @@ const {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateDistance = (pos1, pos2)
1656
1738
  // Silently handle errors
1657
1739
  }
1658
1740
  return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
1659
- }, lerp$1 = (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) => {
1741
+ }, smoothstep = t => {
1742
+ const clamped = Math.max(0, Math.min(1, t));
1743
+ return clamped * clamped * (3 - 2 * clamped);
1744
+ }, lerp$1 = (a, b, t) => a + (b - a) * t, softClamp = (value, max) => max <= 0 ? 0 : max * (1 - Math.exp(-value / max)), calculateSpring = (current, target, velocity, stiffness = .1, damping = .8) => {
1745
+ const newVelocity = (velocity + (target - current) * stiffness) * damping;
1746
+ return {
1747
+ value: current + newVelocity,
1748
+ velocity: newVelocity
1749
+ };
1750
+ }, getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
1660
1751
  switch (mode) {
1661
1752
  case "standard":
1662
1753
  return displacementMap;
@@ -2047,6 +2138,9 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
2047
2138
  }), jsx("div", {
2048
2139
  ref: contentRef,
2049
2140
  className: ATOMIX_GLASS.CONTENT_CLASS,
2141
+ style: {
2142
+ transform: "var(--atomix-glass-child-parallax, none)"
2143
+ },
2050
2144
  children: children
2051
2145
  }) ]
2052
2146
  })
@@ -2081,9 +2175,21 @@ class {
2081
2175
  y: this.lastEvent.clientY
2082
2176
  },
2083
2177
  // Notify all subscribers
2084
- this.listeners.forEach((callback => {
2178
+ this.listeners.forEach((listener => {
2085
2179
  try {
2086
- callback(this.position);
2180
+ // If the listener has an element, calculate distance-based attenuation
2181
+ if (listener.element) {
2182
+ const elementRect = listener.element.getBoundingClientRect(), elementCenter = {
2183
+ x: elementRect.left + elementRect.width / 2,
2184
+ y: elementRect.top + elementRect.height / 2
2185
+ }, distance = this.calculateDistance(this.position, elementCenter), maxDistance = listener.maxDistance || 300, attenuation = Math.max(0, 1 - distance / maxDistance), attenuatedRelativePosition = {
2186
+ x: (this.position.x - elementCenter.x) / elementRect.width * 100 * attenuation,
2187
+ y: (this.position.y - elementCenter.y) / elementRect.height * 100 * attenuation
2188
+ };
2189
+ listener.callback(attenuatedRelativePosition);
2190
+ } else
2191
+ // Send original position for listeners without distance-based attenuation
2192
+ listener.callback(this.position);
2087
2193
  } catch (error) {
2088
2194
  console.error("GlobalMouseTracker: Error in subscriber callback", error);
2089
2195
  }
@@ -2094,10 +2200,17 @@ class {
2094
2200
  /**
2095
2201
  * Subscribe to mouse position updates
2096
2202
  * @param callback Function to call when mouse position changes
2203
+ * @param element Optional element for distance-based attenuation
2204
+ * @param maxDistance Optional maximum distance for full effect
2097
2205
  * @returns Unsubscribe function
2098
- */ subscribe(callback) {
2206
+ */ subscribe(callback, element, maxDistance) {
2207
+ const listener = {
2208
+ callback: callback,
2209
+ element: element,
2210
+ maxDistance: maxDistance
2211
+ };
2099
2212
  // Return unsubscribe function
2100
- return this.listeners.add(callback),
2213
+ return this.listeners.add(listener),
2101
2214
  // Start tracking if this is the first subscriber
2102
2215
  1 === this.listeners.size && this.startTracking(),
2103
2216
  // Immediately notify with current position
@@ -2108,9 +2221,13 @@ class {
2108
2221
  /**
2109
2222
  * Unsubscribe from mouse position updates
2110
2223
  */ unsubscribe(callback) {
2111
- this.listeners.delete(callback),
2224
+ // Find and remove the listener with the given callback
2225
+ for (const listener of this.listeners) if (listener.callback === callback) {
2226
+ this.listeners.delete(listener);
2227
+ break;
2228
+ }
2112
2229
  // Stop tracking if no more subscribers
2113
- 0 === this.listeners.size && this.stopTracking();
2230
+ 0 === this.listeners.size && this.stopTracking();
2114
2231
  }
2115
2232
  /**
2116
2233
  * Start tracking mouse movement
@@ -2129,6 +2246,12 @@ class {
2129
2246
  null !== this.rafId && (cancelAnimationFrame(this.rafId), this.rafId = null), this.lastEvent = null);
2130
2247
  }
2131
2248
  /**
2249
+ * Calculate distance between two points
2250
+ */ calculateDistance(point1, point2) {
2251
+ const dx = point1.x - point2.x, dy = point1.y - point2.y;
2252
+ return Math.sqrt(dx * dx + dy * dy);
2253
+ }
2254
+ /**
2132
2255
  * Get current mouse position (synchronous)
2133
2256
  */ getPosition() {
2134
2257
  return {
@@ -2142,51 +2265,26 @@ class {
2142
2265
  }
2143
2266
  }, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
2144
2267
  if (!wrapperElement && !containerElement) return;
2145
- 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, isFixedOrSticky: isFixedOrSticky = !1} = params, mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1, overLightConfig = {
2268
+ if (!validateGlassSize(params.glassSize)) return;
2269
+ const {mouseOffset: mouseOffset, globalMousePosition: globalMousePosition, glassSize: glassSize, isHovered: isHovered, isActive: isActive, isOverLight: isOverLight, baseOverLightConfig: baseOverLightConfig, effectiveBorderRadius: effectiveBorderRadius, effectiveWithoutEffects: effectiveWithoutEffects, effectiveReducedMotion: effectiveReducedMotion, elasticity: elasticity, elasticTranslation: elasticTranslation, elasticVelocity: elasticVelocity, mouseVelocity: mouseVelocity, directionalScale: directionalScale, scaleBase: scaleBase, onClick: onClick, withLiquidBlur: withLiquidBlur, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, padding: padding = ATOMIX_GLASS.DEFAULTS.PADDING, isFixedOrSticky: isFixedOrSticky = !1} = params, mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1, overLightConfig = {
2146
2270
  opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
2147
2271
  contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
2148
2272
  brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
2149
2273
  shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
2150
2274
  borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence)),
2151
2275
  saturationBoost: baseOverLightConfig.saturationBoost
2152
- };
2153
- // Calculate mouse influence
2154
- let computedDirectionalScale = directionalScale, elasticTranslation = {
2276
+ }, scaleX = directionalScale.x * scaleBase, scaleY = directionalScale.y * scaleBase, transformStyle = effectiveWithoutEffects ? `scale(${scaleBase})` : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) scaleX(${scaleX}) scaleY(${scaleY})`, stretchMagnitude = ((pos1, pos2) => {
2277
+ if (!pos1 || !pos2 || "number" != typeof pos1.x || "number" != typeof pos1.y || "number" != typeof pos2.x || "number" != typeof pos2.y) return 0;
2278
+ const deltaX = pos1.x - pos2.x, deltaY = pos1.y - pos2.y;
2279
+ return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
2280
+ })({
2155
2281
  x: 0,
2156
2282
  y: 0
2157
- };
2158
- // Calculate elastic translation and directional scale
2159
- if (!effectiveWithoutEffects && wrapperElement) {
2160
- const rect = wrapperElement.getBoundingClientRect(), center = calculateElementCenter(rect);
2161
- // Mouse presence and edge distance logic
2162
- if (globalMousePosition.x && globalMousePosition.y && validateGlassSize(glassSize)) {
2163
- 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({
2164
- x: edgeDistanceX,
2165
- y: edgeDistanceY
2166
- }, {
2167
- x: 0,
2168
- y: 0
2169
- }), rawT = edgeDistance > ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE ? 0 : 1 - edgeDistance / ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE, fadeInFactor = (t => {
2170
- const clamped = Math.max(0, Math.min(1, t));
2171
- return clamped * clamped * (3 - 2 * clamped);
2172
- })(rawT);
2173
- // Directional scale
2174
- if (elasticTranslation = {
2175
- x: deltaX * elasticity * .1 * fadeInFactor,
2176
- y: deltaY * elasticity * .1 * fadeInFactor
2177
- }, !isOverLight && edgeDistance <= ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE) {
2178
- const centerDistance = calculateDistance(globalMousePosition, center);
2179
- if (centerDistance > 0) {
2180
- 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);
2181
- computedDirectionalScale = `scaleX(${Math.max(.85, softScaleX)}) scaleY(${Math.max(.85, softScaleY)})`;
2182
- }
2183
- }
2184
- }
2185
- }
2186
- 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}`;
2187
- // Update Wrapper Styles (glassVars)
2188
- if (wrapperElement) {
2189
- 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 = {
2283
+ }, elasticTranslation), tensionFactor = smoothstep(stretchMagnitude / 80), lightingContrast = Math.min(1.8, overLightConfig.contrast + .2 * tensionFactor), lightingBrightness = Math.min(1.2, overLightConfig.brightness + .1 * tensionFactor);
2284
+ // Calculate mouse influence
2285
+ // Update Wrapper Styles (glassVars)
2286
+ if (wrapperElement) {
2287
+ const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT, velocityRotation = (mouseVelocity.x + elasticVelocity.x) * (GRADIENT.VELOCITY_ANGLE_MULTIPLIER || 2.5), borderGradientAngle = GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER + velocityRotation, chromaticOffset = GRADIENT.CHROMATIC_OFFSET || 1.5, angleR = borderGradientAngle - chromaticOffset, angleB = borderGradientAngle + chromaticOffset, 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), tensionGlow = 1 + .5 * tensionFactor, borderOpacities = [ (GRADIENT.BORDER_OPACITY.BASE_1 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW) * tensionGlow, (GRADIENT.BORDER_OPACITY.BASE_2 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH) * tensionGlow, (GRADIENT.BORDER_OPACITY.BASE_3 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW) * tensionGlow, (GRADIENT.BORDER_OPACITY.BASE_4 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH) * tensionGlow ], configBorderOpacity = overLightConfig.borderOpacity, whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE, blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK, hoverPositions = {
2190
2288
  hover1: {
2191
2289
  x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1,
2192
2290
  y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1
@@ -2209,10 +2307,16 @@ class {
2209
2307
  base: isOverLight ? overLightConfig.opacity : 0,
2210
2308
  over: isOverLight ? 1.1 * overLightConfig.opacity : 0
2211
2309
  }, style = wrapperElement.style;
2212
- style.setProperty("--atomix-glass-transform", transformStyle || "none"),
2213
- // Gradients
2214
- 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%)`),
2215
- 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%)`),
2310
+ style.setProperty("--atomix-glass-transform", transformStyle || "none");
2311
+ // Parallax for content (liquid refraction feel)
2312
+ const parallaxFactor = .38 + .12 * tensionFactor;
2313
+ style.setProperty("--atomix-glass-child-parallax", `translate(${elasticTranslation.x * -parallaxFactor}px, ${elasticTranslation.y * -parallaxFactor}px)`),
2314
+ style.setProperty("--atomix-glass-contrast", lightingContrast.toString()), style.setProperty("--atomix-glass-brightness", lightingBrightness.toString()),
2315
+ // ── Chromatic Rim Lighting ──────────────────────────────────────
2316
+ // Layer 1: Core White/Blue highlight
2317
+ style.setProperty("--atomix-glass-border-gradient-1", `linear-gradient(${angleB}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[0] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[1] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`),
2318
+ // Layer 2: Subtle Red/Warm highlight (offset angle)
2319
+ style.setProperty("--atomix-glass-border-gradient-2", `linear-gradient(${angleR}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[2] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[3] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`),
2216
2320
  // Hover gradients
2217
2321
  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}%)`),
2218
2322
  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}%)`),
@@ -2240,7 +2344,7 @@ class {
2240
2344
  flowBlur: blurAmount * FLOW_BLUR_MULTIPLIER
2241
2345
  };
2242
2346
  if (withLiquidBlur && rect) {
2243
- 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);
2347
+ const mouseInfluence = calculateMouseInfluence(mouseOffset), maxBlur = blurAmount * MAX_BLUR_RELATIVE, baseBlur = softClamp(blurAmount + mouseInfluence * blurAmount * MOUSE_INFLUENCE_BLUR_FACTOR, maxBlur), edgeBlur = softClamp(baseBlur * (.8 + mouseInfluence * EDGE_INTENSITY_MOUSE_FACTOR * .4), maxBlur), centerBlur = softClamp(baseBlur * (.3 + mouseInfluence * CENTER_INTENSITY_MOUSE_FACTOR * .3), maxBlur), flowBlur = softClamp(baseBlur * FLOW_BLUR_MULTIPLIER, maxBlur);
2244
2348
  liquidBlur = {
2245
2349
  baseBlur: clampBlur(baseBlur),
2246
2350
  edgeBlur: clampBlur(edgeBlur),
@@ -2249,9 +2353,10 @@ class {
2249
2353
  };
2250
2354
  }
2251
2355
  // Backdrop filter
2252
- let backdropFilterString = `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`;
2253
- const dynamicSaturation = saturation + 20 * (liquidBlur.baseBlur || 0), area = rect ? rect.width * rect.height : 0;
2254
- 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})`;
2356
+ const dynamicSaturation = saturation + 40 * tensionFactor + 15 * (liquidBlur.baseBlur || 0);
2357
+ let backdropFilterString = "";
2358
+ const area = rect ? rect.width * rect.height : 0;
2359
+ 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, 250)}%) contrast(${lightingContrast}) brightness(${lightingBrightness})` : `blur(${clampBlur(.4 * liquidBlur.baseBlur + .25 * liquidBlur.edgeBlur + .15 * liquidBlur.centerBlur + .2 * liquidBlur.flowBlur)}px) saturate(${Math.min(dynamicSaturation, 250)}%) contrast(${lightingContrast}) brightness(${lightingBrightness})`;
2255
2360
  // Container variables
2256
2361
  const style = containerElement.style;
2257
2362
  style.setProperty("--atomix-glass-container-padding", padding), style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
@@ -2413,7 +2518,8 @@ const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new Weak
2413
2518
  * Composable hook for AtomixGlass component logic
2414
2519
  * Manages all state, calculations, and event handlers
2415
2520
  */
2416
- 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, children: children, blurAmount: blurAmount, saturation: saturation, padding: padding, withLiquidBlur: withLiquidBlur, isFixedOrSticky: isFixedOrSticky = !1, withTimeAnimation:
2521
+ 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 = ATOMIX_GLASS.DEFAULTS.ELASTICITY, onClick: onClick, debugBorderRadius: debugBorderRadius = !1, debugOverLight: debugOverLight = !1, children: children, blurAmount: blurAmount, saturation: saturation, padding: padding, withLiquidBlur: withLiquidBlur, isFixedOrSticky: isFixedOrSticky = !1, priority: priority = 1, withTimeAnimation:
2522
+ // Default priority
2417
2523
  // Phase 1: Animation System Props
2418
2524
  withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: animationSpeed = ATOMIX_GLASS.DEFAULTS.ANIMATION_SPEED, withMultiLayerDistortion: withMultiLayerDistortion = ATOMIX_GLASS.DEFAULTS.WITH_MULTI_LAYER_DISTORTION, distortionOctaves: distortionOctaves = ATOMIX_GLASS.DEFAULTS.DISTORTION_OCTAVES, distortionLacunarity: distortionLacunarity = ATOMIX_GLASS.DEFAULTS.DISTORTION_LACUNARITY, distortionGain: distortionGain = ATOMIX_GLASS.DEFAULTS.DISTORTION_GAIN, distortionQuality: distortionQuality = ATOMIX_GLASS.DEFAULTS.DISTORTION_QUALITY}) {
2419
2525
  // State
@@ -2429,7 +2535,24 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
2429
2535
  }), targetGlobalMousePositionRef = useRef({
2430
2536
  x: 0,
2431
2537
  y: 0
2432
- }), lerpRafRef = useRef(null), lerpActiveRef = useRef(!1), [dynamicBorderRadius, setDynamicCornerRadius] = useState(CONSTANTS.DEFAULT_CORNER_RADIUS), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1), animationFrameIdRef = useRef(null), animationStartTimeRef = useRef(0), elapsedTimeRef = useRef(0), shaderTimeRef = useRef(0), fbmConfig = useMemo((() => {
2538
+ }), lerpRafRef = useRef(null), lerpActiveRef = useRef(!1), [dynamicBorderRadius, setDynamicCornerRadius] = useState(CONSTANTS.DEFAULT_CORNER_RADIUS), elasticTranslationRef = useRef({
2539
+ x: 0,
2540
+ y: 0
2541
+ }), elasticVelocityRef = useRef({
2542
+ x: 0,
2543
+ y: 0
2544
+ }), directionalScaleRef = useRef({
2545
+ x: 1,
2546
+ y: 1
2547
+ }), scaleVelocityRef = useRef({
2548
+ x: 0,
2549
+ y: 0
2550
+ });
2551
+ useRef(0);
2552
+ const mouseVelocityRef = useRef({
2553
+ x: 0,
2554
+ y: 0
2555
+ }), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1), animationFrameIdRef = useRef(null), animationStartTimeRef = useRef(0), elapsedTimeRef = useRef(0), shaderTimeRef = useRef(0), fbmConfig = useMemo((() => {
2433
2556
  // If quality preset is provided, use it as base
2434
2557
  const preset = (quality = distortionQuality, ATOMIX_GLASS.CONSTANTS.DISTORTION_QUALITY_PRESETS[quality]);
2435
2558
  // Override with custom values if provided
@@ -2714,57 +2837,85 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
2714
2837
  return "undefined" == typeof process || process.env, finalConfig;
2715
2838
  }
2716
2839
  return "undefined" == typeof process || process.env, baseConfig;
2717
- }), [ overLight, getEffectiveOverLight, isHovered, isActive, validateConfigValue, debugOverLight ]), transformStyle = useMemo((() => effectiveWithoutEffects || isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)"), [ effectiveWithoutEffects, isActive, onClick ]), updateRectRef = useRef(null), stopLerpLoop = useCallback((() => {
2840
+ }), [ overLight, getEffectiveOverLight, isHovered, isActive, validateConfigValue, debugOverLight ]), transformStyle = useMemo((() => effectiveWithoutEffects || isActive && Boolean(onClick) ? "scale(0.99)" : "scale(1)"), [ effectiveWithoutEffects, isActive, onClick ]), updateRectRef = useRef(null), stopLerpLoop = useCallback((() => {
2718
2841
  lerpActiveRef.current = !1, null !== lerpRafRef.current && (cancelAnimationFrame(lerpRafRef.current),
2719
2842
  lerpRafRef.current = null);
2720
2843
  }), []), startLerpLoop = useCallback((() => {
2721
2844
  if (lerpActiveRef.current) return;
2722
- lerpActiveRef.current = !0;
2723
- const LERP_T = CONSTANTS.LERP_FACTOR, tick = () => {
2845
+ lerpActiveRef.current = !0, CONSTANTS.LERP_FACTOR;
2846
+ // 0.08 lower = more viscous
2847
+ const tick = () => {
2724
2848
  if (!lerpActiveRef.current) return;
2725
2849
  if (!glassRef.current) return void (lerpActiveRef.current = !1);
2726
- const cur = internalMouseOffsetRef.current, tgt = targetMouseOffsetRef.current, dx = tgt.x - cur.x, dy = tgt.y - cur.y;
2727
- // If we're close enough, snap and park
2728
- if (Math.abs(dx) < .01 && Math.abs(dy) < .01) return internalMouseOffsetRef.current = {
2729
- ...tgt
2730
- }, internalGlobalMousePositionRef.current = {
2731
- ...targetGlobalMousePositionRef.current
2732
- },
2733
- // Final update and stop
2734
- updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
2735
- mouseOffset: internalMouseOffsetRef.current,
2736
- globalMousePosition: internalGlobalMousePositionRef.current,
2737
- glassSize: glassSize,
2738
- isHovered: isHovered,
2739
- isActive: isActive,
2740
- isOverLight: overLightConfig.isOverLight,
2741
- baseOverLightConfig: overLightConfig,
2742
- effectiveBorderRadius: effectiveBorderRadius,
2743
- effectiveWithoutEffects: effectiveWithoutEffects,
2744
- effectiveReducedMotion: effectiveReducedMotion,
2745
- elasticity: elasticity,
2746
- directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
2747
- onClick: onClick,
2748
- withLiquidBlur: withLiquidBlur,
2749
- blurAmount: blurAmount,
2750
- saturation: saturation,
2751
- padding: padding,
2752
- isFixedOrSticky: isFixedOrSticky
2753
- }), void stopLerpLoop();
2754
- // Smooth step
2755
- internalMouseOffsetRef.current = {
2756
- x: lerp$1(cur.x, tgt.x, LERP_T),
2757
- y: lerp$1(cur.y, tgt.y, LERP_T)
2850
+ const cur = internalMouseOffsetRef.current, tgt = targetMouseOffsetRef.current, springX = calculateSpring(cur.x, tgt.x, mouseVelocityRef.current.x, CONSTANTS.LERP_FACTOR, CONSTANTS.ELASTICITY_DAMPING), springY = calculateSpring(cur.y, tgt.y, mouseVelocityRef.current.y, CONSTANTS.LERP_FACTOR, CONSTANTS.ELASTICITY_DAMPING);
2851
+ internalMouseOffsetRef.current = {
2852
+ x: springX.value,
2853
+ y: springY.value
2854
+ }, mouseVelocityRef.current = {
2855
+ x: springX.velocity,
2856
+ y: springY.velocity
2758
2857
  };
2759
2858
  const curG = internalGlobalMousePositionRef.current, tgtG = targetGlobalMousePositionRef.current;
2760
2859
  internalGlobalMousePositionRef.current = {
2761
- x: lerp$1(curG.x, tgtG.x, LERP_T),
2762
- y: lerp$1(curG.y, tgtG.y, LERP_T)
2860
+ x: lerp$1(curG.x, tgtG.x, CONSTANTS.LERP_FACTOR),
2861
+ y: lerp$1(curG.y, tgtG.y, CONSTANTS.LERP_FACTOR)
2862
+ };
2863
+ // ── Calculate Elastic Physics ─────────────────────────────────────
2864
+ let targetElasticTranslation = {
2865
+ x: 0,
2866
+ y: 0
2867
+ }, targetScale = {
2868
+ x: 1,
2869
+ y: 1
2870
+ };
2871
+ if (!effectiveWithoutEffects && glassRef.current) {
2872
+ const rect = cachedRectRef.current || glassRef.current.getBoundingClientRect(), center = calculateElementCenter(rect), globalPos = internalGlobalMousePositionRef.current;
2873
+ if (globalPos.x && globalPos.y) {
2874
+ const deltaX = globalPos.x - center.x, deltaY = globalPos.y - center.y, edgeDistanceX = Math.max(0, Math.abs(deltaX) - rect.width / 2), edgeDistanceY = Math.max(0, Math.abs(deltaY) - rect.height / 2), edgeDistance = Math.sqrt(edgeDistanceX * edgeDistanceX + edgeDistanceY * edgeDistanceY), activationZone = CONSTANTS.ACTIVATION_ZONE, rawT = edgeDistance > activationZone ? 0 : 1 - edgeDistance / activationZone, fadeInFactor = smoothstep(rawT);
2875
+ // Scale stretch logic (liquid surface tension)
2876
+ if (targetElasticTranslation = {
2877
+ x: deltaX * elasticity * CONSTANTS.ELASTICITY_TRANSLATION_FACTOR * fadeInFactor,
2878
+ y: deltaY * elasticity * CONSTANTS.ELASTICITY_TRANSLATION_FACTOR * fadeInFactor
2879
+ }, edgeDistance <= activationZone) {
2880
+ const centerDistance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
2881
+ if (centerDistance > 0) {
2882
+ const nx = deltaX / centerDistance, ny = deltaY / centerDistance, stretchIntensity = Math.min(centerDistance / 350, 1) * elasticity * rawT, mag = 1 + .06 * stretchIntensity;
2883
+ targetScale = {
2884
+ x: mag + Math.abs(nx) * stretchIntensity * CONSTANTS.ELASTICITY_STRETCH_RATIO,
2885
+ y: mag + Math.abs(ny) * stretchIntensity * CONSTANTS.ELASTICITY_STRETCH_RATIO
2886
+ },
2887
+ // Maintain liquid volume by compressing the perpendicular axis
2888
+ targetScale.x -= Math.abs(ny) * stretchIntensity * .15, targetScale.y -= Math.abs(nx) * stretchIntensity * .15;
2889
+ }
2890
+ }
2891
+ }
2892
+ }
2893
+ // Integrate Elastic Translation Spring
2894
+ const springTX = calculateSpring(elasticTranslationRef.current.x, targetElasticTranslation.x, elasticVelocityRef.current.x, CONSTANTS.ELASTICITY_STIFFNESS, CONSTANTS.ELASTICITY_DAMPING), springTY = calculateSpring(elasticTranslationRef.current.y, targetElasticTranslation.y, elasticVelocityRef.current.y, CONSTANTS.ELASTICITY_STIFFNESS, CONSTANTS.ELASTICITY_DAMPING);
2895
+ elasticTranslationRef.current = {
2896
+ x: springTX.value,
2897
+ y: springTY.value
2898
+ }, elasticVelocityRef.current = {
2899
+ x: springTX.velocity,
2900
+ y: springTY.velocity
2901
+ };
2902
+ // Integrate Scale Spring
2903
+ const springSX = calculateSpring(directionalScaleRef.current.x, targetScale.x, scaleVelocityRef.current.x, CONSTANTS.ELASTICITY_STIFFNESS, CONSTANTS.ELASTICITY_DAMPING), springSY = calculateSpring(directionalScaleRef.current.y, targetScale.y, scaleVelocityRef.current.y, CONSTANTS.ELASTICITY_STIFFNESS, CONSTANTS.ELASTICITY_DAMPING);
2904
+ directionalScaleRef.current = {
2905
+ x: springSX.value,
2906
+ y: springSY.value
2907
+ }, scaleVelocityRef.current = {
2908
+ x: springSX.velocity,
2909
+ y: springSY.velocity
2763
2910
  },
2764
2911
  // Imperative style update
2765
2912
  updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
2766
2913
  mouseOffset: internalMouseOffsetRef.current,
2767
2914
  globalMousePosition: internalGlobalMousePositionRef.current,
2915
+ elasticTranslation: elasticTranslationRef.current,
2916
+ elasticVelocity: elasticVelocityRef.current,
2917
+ mouseVelocity: mouseVelocityRef.current,
2918
+ directionalScale: directionalScaleRef.current,
2768
2919
  glassSize: glassSize,
2769
2920
  isHovered: isHovered,
2770
2921
  isActive: isActive,
@@ -2774,17 +2925,16 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
2774
2925
  effectiveWithoutEffects: effectiveWithoutEffects,
2775
2926
  effectiveReducedMotion: effectiveReducedMotion,
2776
2927
  elasticity: elasticity,
2777
- directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
2928
+ scaleBase: isActive && Boolean(onClick) ? .99 : 1,
2778
2929
  onClick: onClick,
2779
2930
  withLiquidBlur: withLiquidBlur,
2780
2931
  blurAmount: blurAmount,
2781
2932
  saturation: saturation,
2782
2933
  padding: padding,
2783
2934
  isFixedOrSticky: isFixedOrSticky
2784
- }), lerpRafRef.current = requestAnimationFrame(tick);
2935
+ }), Math.abs(mouseVelocityRef.current.x) < .001 && Math.abs(mouseVelocityRef.current.y) < .001 && Math.abs(elasticVelocityRef.current.x) < .001 && Math.abs(elasticVelocityRef.current.y) < .001 && Math.abs(scaleVelocityRef.current.x) < .001 && Math.abs(scaleVelocityRef.current.y) < .001 && Math.abs(internalMouseOffsetRef.current.x - targetMouseOffsetRef.current.x) < .001 && Math.abs(internalMouseOffsetRef.current.y - targetMouseOffsetRef.current.y) < .001 ? stopLerpLoop() : lerpRafRef.current = requestAnimationFrame(tick);
2785
2936
  };
2786
- // 0.08 – lower = more viscous
2787
- lerpRafRef.current = requestAnimationFrame(tick);
2937
+ lerpRafRef.current = requestAnimationFrame(tick);
2788
2938
  }), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding, isFixedOrSticky, stopLerpLoop ]), handleGlobalMousePosition = useCallback((globalPos => {
2789
2939
  if (externalGlobalMousePosition && externalMouseOffset) return;
2790
2940
  if (effectiveWithoutEffects) return;
@@ -2810,7 +2960,8 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
2810
2960
  useEffect((() => {
2811
2961
  if (externalGlobalMousePosition && externalMouseOffset) return;
2812
2962
  if (effectiveWithoutEffects) return;
2813
- const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition);
2963
+ const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition, glassRef.current || void 0, 300);
2964
+ // 300px max distance for full effect
2814
2965
  // Initial start
2815
2966
  startLerpLoop();
2816
2967
  const container = mouseContainer?.current || glassRef.current;
@@ -2830,6 +2981,11 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
2830
2981
  updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
2831
2982
  mouseOffset: externalMouseOffset || internalMouseOffsetRef.current,
2832
2983
  globalMousePosition: externalGlobalMousePosition || internalGlobalMousePositionRef.current,
2984
+ elasticTranslation: elasticTranslationRef.current,
2985
+ elasticVelocity: elasticVelocityRef.current,
2986
+ mouseVelocity: mouseVelocityRef.current,
2987
+ directionalScale: directionalScaleRef.current,
2988
+ scaleBase: isActive && Boolean(onClick) ? .96 : 1,
2833
2989
  glassSize: glassSize,
2834
2990
  isHovered: isHovered,
2835
2991
  isActive: isActive,
@@ -2839,7 +2995,6 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
2839
2995
  effectiveWithoutEffects: effectiveWithoutEffects,
2840
2996
  effectiveReducedMotion: effectiveReducedMotion,
2841
2997
  elasticity: elasticity,
2842
- directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
2843
2998
  onClick: onClick,
2844
2999
  withLiquidBlur: withLiquidBlur,
2845
3000
  blurAmount: blurAmount,
@@ -3823,7 +3978,7 @@ const PERFORMANCE_PRESET = {
3823
3978
  "aria-label": ariaLabel,
3824
3979
  "aria-describedby": ariaDescribedBy,
3825
3980
  "aria-disabled": !(!onClick || !effectiveWithoutEffects) || !onClick && void 0,
3826
- "aria-pressed": void 0,
3981
+ "aria-pressed": onClick ? isActive : void 0,
3827
3982
  onKeyDown: onClick ? handleKeyDown : void 0,
3828
3983
  children: [ jsx(AtomixGlassContainer, {
3829
3984
  ref: glassRef,