@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/core.js CHANGED
@@ -556,12 +556,23 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
556
556
  },
557
557
  DEFAULTS: {
558
558
  DISPLACEMENT_SCALE: 70,
559
- BLUR_AMOUNT: 0,
560
- SATURATION: 140,
561
- ABERRATION_INTENSITY: 2,
559
+ get BLUR_AMOUNT() {
560
+ return .15 * this.DISPLACEMENT_SCALE;
561
+ // Dynamically computed based on displacement
562
+ },
563
+ get SATURATION() {
564
+ return 100 + .5 * this.DISPLACEMENT_SCALE;
565
+ // Saturate relative to intensity
566
+ },
567
+ get ABERRATION_INTENSITY() {
568
+ return .03 * this.DISPLACEMENT_SCALE;
569
+ // Scale aberration with displacement
570
+ },
562
571
  ELASTICITY: .15,
563
- CORNER_RADIUS: 20,
564
- // Default border-radius matching design system
572
+ get CORNER_RADIUS() {
573
+ return 16;
574
+ // Use 16 to match SCSS design system (was 20)
575
+ },
565
576
  PADDING: "0",
566
577
  MODE: "standard",
567
578
  OVER_LIGHT: !1,
@@ -583,6 +594,15 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
583
594
  MIN_BLUR: .1,
584
595
  MOUSE_INFLUENCE_DIVISOR: 100,
585
596
  EDGE_FADE_PIXELS: 2,
597
+ // Elasticity physics constants
598
+ ELASTICITY_TRANSLATION_FACTOR: .1,
599
+ ELASTICITY_DISTANCE_THRESHOLD: 200,
600
+ ELASTICITY_COMPRESSION_FACTOR: .3,
601
+ ELASTICITY_STIFFNESS: .1,
602
+ ELASTICITY_DAMPING: .76,
603
+ ELASTICITY_VELOCITY_FACTOR: .65,
604
+ ELASTICITY_STRETCH_RATIO: .45,
605
+ ELASTICITY_MAGNIFICATION_BASE: 1.02,
586
606
  // Note: This default must match the SCSS variable --atomix-radius-md
587
607
  // @see src/styles/01-settings/_settings.global.scss
588
608
  DEFAULT_CORNER_RADIUS: 16,
@@ -599,84 +619,126 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
599
619
  // Base angle for border gradients (degrees)
600
620
  ANGLE_MULTIPLIER: 1.2,
601
621
  // Multiplier for mouse influence on angle
622
+ VELOCITY_ANGLE_MULTIPLIER: 2.5,
623
+ // How much velocity affects gradient rotation
624
+ CHROMATIC_OFFSET: 1.5,
625
+ // Degree offset for chromatic rim layers
602
626
  BORDER_STOP_1: {
603
627
  MIN: 10,
604
628
  // Minimum percentage for border stop 1
605
629
  BASE: 33,
606
630
  // Base percentage for border stop 1
607
- MULTIPLIER: .3
631
+ get MULTIPLIER() {
632
+ return .009 * this.BASE;
633
+ }
608
634
  },
609
635
  BORDER_STOP_2: {
610
636
  MAX: 90,
611
637
  // Maximum percentage for border stop 2
612
638
  BASE: 66,
613
639
  // Base percentage for border stop 2
614
- MULTIPLIER: .4
640
+ get MULTIPLIER() {
641
+ return .006 * this.BASE;
642
+ }
615
643
  },
616
644
  BORDER_OPACITY: {
617
645
  BASE_1: .12,
618
646
  // Base opacity for border gradient 1
619
- BASE_2: .4,
647
+ get BASE_2() {
648
+ return 3.33 * this.BASE_1;
649
+ },
620
650
  // Base opacity for border gradient 2
621
- BASE_3: .32,
651
+ get BASE_3() {
652
+ return 2.66 * this.BASE_1;
653
+ },
622
654
  // Base opacity for border gradient 3
623
- BASE_4: .6,
655
+ get BASE_4() {
656
+ return 5 * this.BASE_1;
657
+ },
624
658
  // Base opacity for border gradient 4
625
- MULTIPLIER_LOW: .008,
659
+ get MULTIPLIER_LOW() {
660
+ return .066 * this.BASE_1;
661
+ },
626
662
  // Low multiplier for mouse influence on opacity
627
- MULTIPLIER_HIGH: .012
663
+ get MULTIPLIER_HIGH() {
664
+ return .1 * this.BASE_1;
665
+ }
628
666
  },
629
667
  CENTER_POSITION: 50,
630
668
  // Center position percentage (50%)
631
669
  HOVER_POSITION: {
632
670
  DIVISOR_1: 2,
633
671
  // Divisor for hover 1 position calculation
634
- DIVISOR_2: 1.5,
672
+ get DIVISOR_2() {
673
+ return .75 * this.DIVISOR_1;
674
+ },
635
675
  // Divisor for hover 2 position calculation
636
- MULTIPLIER_3: 1
676
+ get MULTIPLIER_3() {
677
+ return .5 * this.DIVISOR_1;
678
+ }
637
679
  },
638
- BASE_LAYER_MULTIPLIER: .5
680
+ get BASE_LAYER_MULTIPLIER() {
681
+ return .5;
682
+ }
639
683
  },
640
684
  // Gradient opacity values for hover effects
641
685
  GRADIENT_OPACITY: {
642
686
  HOVER_1: {
643
687
  BLACK_START: .3,
644
688
  // Start opacity for black hover 1
645
- BLACK_MID: .1,
689
+ get BLACK_MID() {
690
+ return this.BLACK_START / 3;
691
+ },
646
692
  // Mid opacity for black hover 1
647
693
  BLACK_STOP: 30,
648
694
  // Stop percentage for black hover 1
649
- BLACK_END: 60,
695
+ get BLACK_END() {
696
+ return 2 * this.BLACK_STOP;
697
+ },
650
698
  // End percentage for black hover 1
651
699
  WHITE_START: .5,
652
700
  // Start opacity for white hover 1
653
- WHITE_STOP: 50
701
+ get WHITE_STOP() {
702
+ return this.BLACK_END - 10;
703
+ }
654
704
  },
655
705
  HOVER_2: {
656
706
  BLACK_START: .4,
657
707
  // Start opacity for black hover 2
658
- BLACK_MID: .15,
708
+ get BLACK_MID() {
709
+ return .375 * this.BLACK_START;
710
+ },
659
711
  // Mid opacity for black hover 2
660
712
  BLACK_STOP: 40,
661
713
  // Stop percentage for black hover 2
662
- BLACK_END: 80,
714
+ get BLACK_END() {
715
+ return 2 * this.BLACK_STOP;
716
+ },
663
717
  // End percentage for black hover 2
664
718
  WHITE_START: 1,
665
719
  // Start opacity for white hover 2
666
- WHITE_STOP: 80
720
+ get WHITE_STOP() {
721
+ return this.BLACK_END;
722
+ }
667
723
  },
668
724
  HOVER_3: {
669
725
  BLACK_START: .5,
670
726
  // Start opacity for black hover 3
671
- BLACK_MID: .2,
727
+ get BLACK_MID() {
728
+ return .4 * this.BLACK_START;
729
+ },
672
730
  // Mid opacity for black hover 3
673
731
  BLACK_STOP: 50,
674
732
  // Stop percentage for black hover 3
675
- BLACK_END: 100,
733
+ get BLACK_END() {
734
+ return 2 * this.BLACK_STOP;
735
+ },
676
736
  // End percentage for black hover 3
677
737
  WHITE_START: 1,
678
738
  // Start opacity for white hover 3
679
- WHITE_STOP: 100
739
+ get WHITE_STOP() {
740
+ return this.BLACK_END;
741
+ }
680
742
  }
681
743
  },
682
744
  // Base and overlay gradient constants
@@ -685,34 +747,54 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
685
747
  // Gradient angle in degrees
686
748
  BLACK_START_BASE: .15,
687
749
  // Base start opacity for black
688
- BLACK_START_MULTIPLIER: .003,
750
+ get BLACK_START_MULTIPLIER() {
751
+ return .02 * this.BLACK_START_BASE;
752
+ },
689
753
  // Multiplier for mouse X influence on start
690
754
  BLACK_MID_BASE: .1,
691
755
  // Base mid opacity for black
692
- BLACK_MID_MULTIPLIER: .002,
756
+ get BLACK_MID_MULTIPLIER() {
757
+ return .02 * this.BLACK_MID_BASE;
758
+ },
693
759
  // Multiplier for mouse Y influence on mid
694
760
  BLACK_MID_STOP: 50,
695
761
  // Mid stop percentage
696
- BLACK_END_BASE: .18,
762
+ get BLACK_END_BASE() {
763
+ return 1.2 * this.BLACK_START_BASE;
764
+ },
697
765
  // Base end opacity for black
698
- BLACK_END_MULTIPLIER: .004,
766
+ get BLACK_END_MULTIPLIER() {
767
+ return .022 * this.BLACK_END_BASE;
768
+ },
699
769
  // Multiplier for mouse X influence on end
700
- WHITE_OPACITY: .1
770
+ get WHITE_OPACITY() {
771
+ return .666 * this.BLACK_START_BASE;
772
+ }
701
773
  },
702
774
  OVERLAY_GRADIENT: {
703
775
  BLACK_START_BASE: .12,
704
776
  // Base start opacity for black overlay
705
- BLACK_START_MULTIPLIER: .003,
777
+ get BLACK_START_MULTIPLIER() {
778
+ return .025 * this.BLACK_START_BASE;
779
+ },
706
780
  // Multiplier for mouse X influence on start
707
- BLACK_MID: .06,
781
+ get BLACK_MID() {
782
+ return .5 * this.BLACK_START_BASE;
783
+ },
708
784
  // Mid opacity for black overlay
709
785
  BLACK_MID_STOP: 40,
710
786
  // Mid stop percentage
711
- BLACK_END_BASE: .15,
787
+ get BLACK_END_BASE() {
788
+ return 1.25 * this.BLACK_START_BASE;
789
+ },
712
790
  // Base end opacity for black overlay
713
- BLACK_END_MULTIPLIER: .003,
791
+ get BLACK_END_MULTIPLIER() {
792
+ return .02 * this.BLACK_END_BASE;
793
+ },
714
794
  // Multiplier for mouse Y influence on end
715
- WHITE_OPACITY: .05
795
+ get WHITE_OPACITY() {
796
+ return .416 * this.BLACK_START_BASE;
797
+ }
716
798
  },
717
799
  // Overlay highlight constants
718
800
  OVERLAY_HIGHLIGHT: {
@@ -722,9 +804,13 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
722
804
  // Y position percentage
723
805
  WHITE_OPACITY: .4,
724
806
  // White opacity in gradient
725
- STOP: 60,
807
+ get STOP() {
808
+ return 150 * this.WHITE_OPACITY;
809
+ },
726
810
  // Stop percentage
727
- OPACITY_MULTIPLIER: .7
811
+ get OPACITY_MULTIPLIER() {
812
+ return 1.75 * this.WHITE_OPACITY;
813
+ }
728
814
  },
729
815
  // Displacement and aberration multipliers
730
816
  MULTIPLIERS: {
@@ -777,11 +863,7 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
777
863
  }
778
864
  }
779
865
  }
780
- }, {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateDistance = (pos1, pos2) => {
781
- if (!pos1 || !pos2 || "number" != typeof pos1.x || "number" != typeof pos1.y || "number" != typeof pos2.x || "number" != typeof pos2.y) return 0;
782
- const deltaX = pos1.x - pos2.x, deltaY = pos1.y - pos2.y;
783
- return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
784
- }, calculateElementCenter = rect => rect ? {
866
+ }, {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateElementCenter = rect => rect ? {
785
867
  x: rect.left + rect.width / 2,
786
868
  y: rect.top + rect.height / 2
787
869
  } : {
@@ -853,7 +935,16 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
853
935
  // Silently handle errors
854
936
  }
855
937
  return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
856
- }, 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) => {
938
+ }, smoothstep = t => {
939
+ const clamped = Math.max(0, Math.min(1, t));
940
+ return clamped * clamped * (3 - 2 * clamped);
941
+ }, 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) => {
942
+ const newVelocity = (velocity + (target - current) * stiffness) * damping;
943
+ return {
944
+ value: current + newVelocity,
945
+ velocity: newVelocity
946
+ };
947
+ }, getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
857
948
  switch (mode) {
858
949
  case "standard":
859
950
  return displacementMap;
@@ -1247,6 +1338,9 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
1247
1338
  }), jsx("div", {
1248
1339
  ref: contentRef,
1249
1340
  className: ATOMIX_GLASS.CONTENT_CLASS,
1341
+ style: {
1342
+ transform: "var(--atomix-glass-child-parallax, none)"
1343
+ },
1250
1344
  children: children
1251
1345
  }) ]
1252
1346
  })
@@ -1281,9 +1375,21 @@ class {
1281
1375
  y: this.lastEvent.clientY
1282
1376
  },
1283
1377
  // Notify all subscribers
1284
- this.listeners.forEach((callback => {
1378
+ this.listeners.forEach((listener => {
1285
1379
  try {
1286
- callback(this.position);
1380
+ // If the listener has an element, calculate distance-based attenuation
1381
+ if (listener.element) {
1382
+ const elementRect = listener.element.getBoundingClientRect(), elementCenter = {
1383
+ x: elementRect.left + elementRect.width / 2,
1384
+ y: elementRect.top + elementRect.height / 2
1385
+ }, distance = this.calculateDistance(this.position, elementCenter), maxDistance = listener.maxDistance || 300, attenuation = Math.max(0, 1 - distance / maxDistance), attenuatedRelativePosition = {
1386
+ x: (this.position.x - elementCenter.x) / elementRect.width * 100 * attenuation,
1387
+ y: (this.position.y - elementCenter.y) / elementRect.height * 100 * attenuation
1388
+ };
1389
+ listener.callback(attenuatedRelativePosition);
1390
+ } else
1391
+ // Send original position for listeners without distance-based attenuation
1392
+ listener.callback(this.position);
1287
1393
  } catch (error) {
1288
1394
  console.error("GlobalMouseTracker: Error in subscriber callback", error);
1289
1395
  }
@@ -1294,10 +1400,17 @@ class {
1294
1400
  /**
1295
1401
  * Subscribe to mouse position updates
1296
1402
  * @param callback Function to call when mouse position changes
1403
+ * @param element Optional element for distance-based attenuation
1404
+ * @param maxDistance Optional maximum distance for full effect
1297
1405
  * @returns Unsubscribe function
1298
- */ subscribe(callback) {
1406
+ */ subscribe(callback, element, maxDistance) {
1407
+ const listener = {
1408
+ callback: callback,
1409
+ element: element,
1410
+ maxDistance: maxDistance
1411
+ };
1299
1412
  // Return unsubscribe function
1300
- return this.listeners.add(callback),
1413
+ return this.listeners.add(listener),
1301
1414
  // Start tracking if this is the first subscriber
1302
1415
  1 === this.listeners.size && this.startTracking(),
1303
1416
  // Immediately notify with current position
@@ -1308,9 +1421,13 @@ class {
1308
1421
  /**
1309
1422
  * Unsubscribe from mouse position updates
1310
1423
  */ unsubscribe(callback) {
1311
- this.listeners.delete(callback),
1424
+ // Find and remove the listener with the given callback
1425
+ for (const listener of this.listeners) if (listener.callback === callback) {
1426
+ this.listeners.delete(listener);
1427
+ break;
1428
+ }
1312
1429
  // Stop tracking if no more subscribers
1313
- 0 === this.listeners.size && this.stopTracking();
1430
+ 0 === this.listeners.size && this.stopTracking();
1314
1431
  }
1315
1432
  /**
1316
1433
  * Start tracking mouse movement
@@ -1329,6 +1446,12 @@ class {
1329
1446
  null !== this.rafId && (cancelAnimationFrame(this.rafId), this.rafId = null), this.lastEvent = null);
1330
1447
  }
1331
1448
  /**
1449
+ * Calculate distance between two points
1450
+ */ calculateDistance(point1, point2) {
1451
+ const dx = point1.x - point2.x, dy = point1.y - point2.y;
1452
+ return Math.sqrt(dx * dx + dy * dy);
1453
+ }
1454
+ /**
1332
1455
  * Get current mouse position (synchronous)
1333
1456
  */ getPosition() {
1334
1457
  return {
@@ -1342,51 +1465,26 @@ class {
1342
1465
  }
1343
1466
  }, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
1344
1467
  if (!wrapperElement && !containerElement) return;
1345
- 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 = {
1468
+ if (!validateGlassSize(params.glassSize)) return;
1469
+ 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 = {
1346
1470
  opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
1347
1471
  contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
1348
1472
  brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
1349
1473
  shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
1350
1474
  borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence)),
1351
1475
  saturationBoost: baseOverLightConfig.saturationBoost
1352
- };
1353
- // Calculate mouse influence
1354
- let computedDirectionalScale = directionalScale, elasticTranslation = {
1476
+ }, 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) => {
1477
+ if (!pos1 || !pos2 || "number" != typeof pos1.x || "number" != typeof pos1.y || "number" != typeof pos2.x || "number" != typeof pos2.y) return 0;
1478
+ const deltaX = pos1.x - pos2.x, deltaY = pos1.y - pos2.y;
1479
+ return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
1480
+ })({
1355
1481
  x: 0,
1356
1482
  y: 0
1357
- };
1358
- // Calculate elastic translation and directional scale
1359
- if (!effectiveWithoutEffects && wrapperElement) {
1360
- const rect = wrapperElement.getBoundingClientRect(), center = calculateElementCenter(rect);
1361
- // Mouse presence and edge distance logic
1362
- if (globalMousePosition.x && globalMousePosition.y && validateGlassSize(glassSize)) {
1363
- 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({
1364
- x: edgeDistanceX,
1365
- y: edgeDistanceY
1366
- }, {
1367
- x: 0,
1368
- y: 0
1369
- }), rawT = edgeDistance > ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE ? 0 : 1 - edgeDistance / ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE, fadeInFactor = (t => {
1370
- const clamped = Math.max(0, Math.min(1, t));
1371
- return clamped * clamped * (3 - 2 * clamped);
1372
- })(rawT);
1373
- // Directional scale
1374
- if (elasticTranslation = {
1375
- x: deltaX * elasticity * .1 * fadeInFactor,
1376
- y: deltaY * elasticity * .1 * fadeInFactor
1377
- }, !isOverLight && edgeDistance <= ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE) {
1378
- const centerDistance = calculateDistance(globalMousePosition, center);
1379
- if (centerDistance > 0) {
1380
- 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);
1381
- computedDirectionalScale = `scaleX(${Math.max(.85, softScaleX)}) scaleY(${Math.max(.85, softScaleY)})`;
1382
- }
1383
- }
1384
- }
1385
- }
1386
- 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}`;
1387
- // Update Wrapper Styles (glassVars)
1388
- if (wrapperElement) {
1389
- 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 = {
1483
+ }, elasticTranslation), tensionFactor = smoothstep(stretchMagnitude / 80), lightingContrast = Math.min(1.8, overLightConfig.contrast + .2 * tensionFactor), lightingBrightness = Math.min(1.2, overLightConfig.brightness + .1 * tensionFactor);
1484
+ // Calculate mouse influence
1485
+ // Update Wrapper Styles (glassVars)
1486
+ if (wrapperElement) {
1487
+ 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 = {
1390
1488
  hover1: {
1391
1489
  x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1,
1392
1490
  y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1
@@ -1409,10 +1507,16 @@ class {
1409
1507
  base: isOverLight ? overLightConfig.opacity : 0,
1410
1508
  over: isOverLight ? 1.1 * overLightConfig.opacity : 0
1411
1509
  }, style = wrapperElement.style;
1412
- style.setProperty("--atomix-glass-transform", transformStyle || "none"),
1413
- // Gradients
1414
- 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%)`),
1415
- 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%)`),
1510
+ style.setProperty("--atomix-glass-transform", transformStyle || "none");
1511
+ // Parallax for content (liquid refraction feel)
1512
+ const parallaxFactor = .38 + .12 * tensionFactor;
1513
+ style.setProperty("--atomix-glass-child-parallax", `translate(${elasticTranslation.x * -parallaxFactor}px, ${elasticTranslation.y * -parallaxFactor}px)`),
1514
+ style.setProperty("--atomix-glass-contrast", lightingContrast.toString()), style.setProperty("--atomix-glass-brightness", lightingBrightness.toString()),
1515
+ // ── Chromatic Rim Lighting ──────────────────────────────────────
1516
+ // Layer 1: Core White/Blue highlight
1517
+ 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%)`),
1518
+ // Layer 2: Subtle Red/Warm highlight (offset angle)
1519
+ 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%)`),
1416
1520
  // Hover gradients
1417
1521
  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}%)`),
1418
1522
  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}%)`),
@@ -1440,7 +1544,7 @@ class {
1440
1544
  flowBlur: blurAmount * FLOW_BLUR_MULTIPLIER
1441
1545
  };
1442
1546
  if (withLiquidBlur && rect) {
1443
- 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);
1547
+ 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);
1444
1548
  liquidBlur = {
1445
1549
  baseBlur: clampBlur(baseBlur),
1446
1550
  edgeBlur: clampBlur(edgeBlur),
@@ -1449,9 +1553,10 @@ class {
1449
1553
  };
1450
1554
  }
1451
1555
  // Backdrop filter
1452
- let backdropFilterString = `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`;
1453
- const dynamicSaturation = saturation + 20 * (liquidBlur.baseBlur || 0), area = rect ? rect.width * rect.height : 0;
1454
- 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})`;
1556
+ const dynamicSaturation = saturation + 40 * tensionFactor + 15 * (liquidBlur.baseBlur || 0);
1557
+ let backdropFilterString = "";
1558
+ const area = rect ? rect.width * rect.height : 0;
1559
+ 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})`;
1455
1560
  // Container variables
1456
1561
  const style = containerElement.style;
1457
1562
  style.setProperty("--atomix-glass-container-padding", padding), style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
@@ -1613,7 +1718,8 @@ const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new Weak
1613
1718
  * Composable hook for AtomixGlass component logic
1614
1719
  * Manages all state, calculations, and event handlers
1615
1720
  */
1616
- 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:
1721
+ 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:
1722
+ // Default priority
1617
1723
  // Phase 1: Animation System Props
1618
1724
  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}) {
1619
1725
  // State
@@ -1629,7 +1735,24 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
1629
1735
  }), targetGlobalMousePositionRef = useRef({
1630
1736
  x: 0,
1631
1737
  y: 0
1632
- }), 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((() => {
1738
+ }), lerpRafRef = useRef(null), lerpActiveRef = useRef(!1), [dynamicBorderRadius, setDynamicCornerRadius] = useState(CONSTANTS.DEFAULT_CORNER_RADIUS), elasticTranslationRef = useRef({
1739
+ x: 0,
1740
+ y: 0
1741
+ }), elasticVelocityRef = useRef({
1742
+ x: 0,
1743
+ y: 0
1744
+ }), directionalScaleRef = useRef({
1745
+ x: 1,
1746
+ y: 1
1747
+ }), scaleVelocityRef = useRef({
1748
+ x: 0,
1749
+ y: 0
1750
+ });
1751
+ useRef(0);
1752
+ const mouseVelocityRef = useRef({
1753
+ x: 0,
1754
+ y: 0
1755
+ }), [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((() => {
1633
1756
  // If quality preset is provided, use it as base
1634
1757
  const preset = (quality = distortionQuality, ATOMIX_GLASS.CONSTANTS.DISTORTION_QUALITY_PRESETS[quality]);
1635
1758
  // Override with custom values if provided
@@ -1914,57 +2037,85 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
1914
2037
  return "undefined" == typeof process || process.env, finalConfig;
1915
2038
  }
1916
2039
  return "undefined" == typeof process || process.env, baseConfig;
1917
- }), [ 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((() => {
2040
+ }), [ 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((() => {
1918
2041
  lerpActiveRef.current = !1, null !== lerpRafRef.current && (cancelAnimationFrame(lerpRafRef.current),
1919
2042
  lerpRafRef.current = null);
1920
2043
  }), []), startLerpLoop = useCallback((() => {
1921
2044
  if (lerpActiveRef.current) return;
1922
- lerpActiveRef.current = !0;
1923
- const LERP_T = CONSTANTS.LERP_FACTOR, tick = () => {
2045
+ lerpActiveRef.current = !0, CONSTANTS.LERP_FACTOR;
2046
+ // 0.08 lower = more viscous
2047
+ const tick = () => {
1924
2048
  if (!lerpActiveRef.current) return;
1925
2049
  if (!glassRef.current) return void (lerpActiveRef.current = !1);
1926
- const cur = internalMouseOffsetRef.current, tgt = targetMouseOffsetRef.current, dx = tgt.x - cur.x, dy = tgt.y - cur.y;
1927
- // If we're close enough, snap and park
1928
- if (Math.abs(dx) < .01 && Math.abs(dy) < .01) return internalMouseOffsetRef.current = {
1929
- ...tgt
1930
- }, internalGlobalMousePositionRef.current = {
1931
- ...targetGlobalMousePositionRef.current
1932
- },
1933
- // Final update and stop
1934
- updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
1935
- mouseOffset: internalMouseOffsetRef.current,
1936
- globalMousePosition: internalGlobalMousePositionRef.current,
1937
- glassSize: glassSize,
1938
- isHovered: isHovered,
1939
- isActive: isActive,
1940
- isOverLight: overLightConfig.isOverLight,
1941
- baseOverLightConfig: overLightConfig,
1942
- effectiveBorderRadius: effectiveBorderRadius,
1943
- effectiveWithoutEffects: effectiveWithoutEffects,
1944
- effectiveReducedMotion: effectiveReducedMotion,
1945
- elasticity: elasticity,
1946
- directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
1947
- onClick: onClick,
1948
- withLiquidBlur: withLiquidBlur,
1949
- blurAmount: blurAmount,
1950
- saturation: saturation,
1951
- padding: padding,
1952
- isFixedOrSticky: isFixedOrSticky
1953
- }), void stopLerpLoop();
1954
- // Smooth step
1955
- internalMouseOffsetRef.current = {
1956
- x: lerp$1(cur.x, tgt.x, LERP_T),
1957
- y: lerp$1(cur.y, tgt.y, LERP_T)
2050
+ 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);
2051
+ internalMouseOffsetRef.current = {
2052
+ x: springX.value,
2053
+ y: springY.value
2054
+ }, mouseVelocityRef.current = {
2055
+ x: springX.velocity,
2056
+ y: springY.velocity
1958
2057
  };
1959
2058
  const curG = internalGlobalMousePositionRef.current, tgtG = targetGlobalMousePositionRef.current;
1960
2059
  internalGlobalMousePositionRef.current = {
1961
- x: lerp$1(curG.x, tgtG.x, LERP_T),
1962
- y: lerp$1(curG.y, tgtG.y, LERP_T)
2060
+ x: lerp$1(curG.x, tgtG.x, CONSTANTS.LERP_FACTOR),
2061
+ y: lerp$1(curG.y, tgtG.y, CONSTANTS.LERP_FACTOR)
2062
+ };
2063
+ // ── Calculate Elastic Physics ─────────────────────────────────────
2064
+ let targetElasticTranslation = {
2065
+ x: 0,
2066
+ y: 0
2067
+ }, targetScale = {
2068
+ x: 1,
2069
+ y: 1
2070
+ };
2071
+ if (!effectiveWithoutEffects && glassRef.current) {
2072
+ const rect = cachedRectRef.current || glassRef.current.getBoundingClientRect(), center = calculateElementCenter(rect), globalPos = internalGlobalMousePositionRef.current;
2073
+ if (globalPos.x && globalPos.y) {
2074
+ 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);
2075
+ // Scale stretch logic (liquid surface tension)
2076
+ if (targetElasticTranslation = {
2077
+ x: deltaX * elasticity * CONSTANTS.ELASTICITY_TRANSLATION_FACTOR * fadeInFactor,
2078
+ y: deltaY * elasticity * CONSTANTS.ELASTICITY_TRANSLATION_FACTOR * fadeInFactor
2079
+ }, edgeDistance <= activationZone) {
2080
+ const centerDistance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
2081
+ if (centerDistance > 0) {
2082
+ const nx = deltaX / centerDistance, ny = deltaY / centerDistance, stretchIntensity = Math.min(centerDistance / 350, 1) * elasticity * rawT, mag = 1 + .06 * stretchIntensity;
2083
+ targetScale = {
2084
+ x: mag + Math.abs(nx) * stretchIntensity * CONSTANTS.ELASTICITY_STRETCH_RATIO,
2085
+ y: mag + Math.abs(ny) * stretchIntensity * CONSTANTS.ELASTICITY_STRETCH_RATIO
2086
+ },
2087
+ // Maintain liquid volume by compressing the perpendicular axis
2088
+ targetScale.x -= Math.abs(ny) * stretchIntensity * .15, targetScale.y -= Math.abs(nx) * stretchIntensity * .15;
2089
+ }
2090
+ }
2091
+ }
2092
+ }
2093
+ // Integrate Elastic Translation Spring
2094
+ 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);
2095
+ elasticTranslationRef.current = {
2096
+ x: springTX.value,
2097
+ y: springTY.value
2098
+ }, elasticVelocityRef.current = {
2099
+ x: springTX.velocity,
2100
+ y: springTY.velocity
2101
+ };
2102
+ // Integrate Scale Spring
2103
+ 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);
2104
+ directionalScaleRef.current = {
2105
+ x: springSX.value,
2106
+ y: springSY.value
2107
+ }, scaleVelocityRef.current = {
2108
+ x: springSX.velocity,
2109
+ y: springSY.velocity
1963
2110
  },
1964
2111
  // Imperative style update
1965
2112
  updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
1966
2113
  mouseOffset: internalMouseOffsetRef.current,
1967
2114
  globalMousePosition: internalGlobalMousePositionRef.current,
2115
+ elasticTranslation: elasticTranslationRef.current,
2116
+ elasticVelocity: elasticVelocityRef.current,
2117
+ mouseVelocity: mouseVelocityRef.current,
2118
+ directionalScale: directionalScaleRef.current,
1968
2119
  glassSize: glassSize,
1969
2120
  isHovered: isHovered,
1970
2121
  isActive: isActive,
@@ -1974,17 +2125,16 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
1974
2125
  effectiveWithoutEffects: effectiveWithoutEffects,
1975
2126
  effectiveReducedMotion: effectiveReducedMotion,
1976
2127
  elasticity: elasticity,
1977
- directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
2128
+ scaleBase: isActive && Boolean(onClick) ? .99 : 1,
1978
2129
  onClick: onClick,
1979
2130
  withLiquidBlur: withLiquidBlur,
1980
2131
  blurAmount: blurAmount,
1981
2132
  saturation: saturation,
1982
2133
  padding: padding,
1983
2134
  isFixedOrSticky: isFixedOrSticky
1984
- }), lerpRafRef.current = requestAnimationFrame(tick);
2135
+ }), 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);
1985
2136
  };
1986
- // 0.08 – lower = more viscous
1987
- lerpRafRef.current = requestAnimationFrame(tick);
2137
+ lerpRafRef.current = requestAnimationFrame(tick);
1988
2138
  }), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding, isFixedOrSticky, stopLerpLoop ]), handleGlobalMousePosition = useCallback((globalPos => {
1989
2139
  if (externalGlobalMousePosition && externalMouseOffset) return;
1990
2140
  if (effectiveWithoutEffects) return;
@@ -2010,7 +2160,8 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
2010
2160
  useEffect((() => {
2011
2161
  if (externalGlobalMousePosition && externalMouseOffset) return;
2012
2162
  if (effectiveWithoutEffects) return;
2013
- const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition);
2163
+ const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition, glassRef.current || void 0, 300);
2164
+ // 300px max distance for full effect
2014
2165
  // Initial start
2015
2166
  startLerpLoop();
2016
2167
  const container = mouseContainer?.current || glassRef.current;
@@ -2030,6 +2181,11 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
2030
2181
  updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
2031
2182
  mouseOffset: externalMouseOffset || internalMouseOffsetRef.current,
2032
2183
  globalMousePosition: externalGlobalMousePosition || internalGlobalMousePositionRef.current,
2184
+ elasticTranslation: elasticTranslationRef.current,
2185
+ elasticVelocity: elasticVelocityRef.current,
2186
+ mouseVelocity: mouseVelocityRef.current,
2187
+ directionalScale: directionalScaleRef.current,
2188
+ scaleBase: isActive && Boolean(onClick) ? .96 : 1,
2033
2189
  glassSize: glassSize,
2034
2190
  isHovered: isHovered,
2035
2191
  isActive: isActive,
@@ -2039,7 +2195,6 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
2039
2195
  effectiveWithoutEffects: effectiveWithoutEffects,
2040
2196
  effectiveReducedMotion: effectiveReducedMotion,
2041
2197
  elasticity: elasticity,
2042
- directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
2043
2198
  onClick: onClick,
2044
2199
  withLiquidBlur: withLiquidBlur,
2045
2200
  blurAmount: blurAmount,
@@ -2936,7 +3091,7 @@ const PERFORMANCE_PRESET = {
2936
3091
  "aria-label": ariaLabel,
2937
3092
  "aria-describedby": ariaDescribedBy,
2938
3093
  "aria-disabled": !(!onClick || !effectiveWithoutEffects) || !onClick && void 0,
2939
- "aria-pressed": void 0,
3094
+ "aria-pressed": onClick ? isActive : void 0,
2940
3095
  onKeyDown: onClick ? handleKeyDown : void 0,
2941
3096
  children: [ jsx(AtomixGlassContainer, {
2942
3097
  ref: glassRef,
@@ -3738,10 +3893,10 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
3738
3893
  children: renderSlot(slots?.spinner, {
3739
3894
  className: ThemeNaming.bemClass("btn", "spinner"),
3740
3895
  size: spinnerSize,
3741
- variant: "link" === variant || "string" == typeof variant && variant.startsWith("outline-") ? "primary" : "danger" === variant ? "error" : variant
3896
+ variant: "link" === variant || "ghost" === variant || "string" == typeof variant && variant.startsWith("outline-") ? "primary" : "danger" === variant ? "danger" : variant
3742
3897
  }, jsx(Spinner, {
3743
3898
  size: spinnerSize,
3744
- variant: "link" === variant || "string" == typeof variant && variant.startsWith("outline-") ? "primary" : "danger" === variant ? "error" : variant
3899
+ variant: "link" === variant || "ghost" === variant || "string" == typeof variant && variant.startsWith("outline-") ? "primary" : "danger" === variant ? "danger" : variant
3745
3900
  }))
3746
3901
  }), iconElement && !loading && jsx("span", {
3747
3902
  className: ThemeNaming.bemClass("btn", "icon"),
@@ -3830,8 +3985,7 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
3830
3985
  const defaultGlassProps = {
3831
3986
  displacementScale: 20,
3832
3987
  blurAmount: 0,
3833
- saturation: 200,
3834
- elasticity: 0
3988
+ saturation: 200
3835
3989
  }, glassProps = !0 === glass ? defaultGlassProps : {
3836
3990
  ...defaultGlassProps,
3837
3991
  ...glass
@@ -4019,7 +4173,6 @@ className: className = "", style: style, ...rest}, ref) => {
4019
4173
  children: cardContent
4020
4174
  }), glass ? jsx(AtomixGlass, {
4021
4175
  ...!0 === glass ? {} : glass,
4022
- elasticity: 0,
4023
4176
  children: anchorElement
4024
4177
  }) : anchorElement;
4025
4178
  }
@@ -4031,7 +4184,6 @@ className: className = "", style: style, ...rest}, ref) => {
4031
4184
  });
4032
4185
  return glass ? jsx(AtomixGlass, {
4033
4186
  ...!0 === glass ? {} : glass,
4034
- elasticity: 0,
4035
4187
  children: divElement
4036
4188
  }) : divElement;
4037
4189
  })));