@shohojdhara/atomix 0.6.4 → 0.6.5
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.
- package/dist/atomix.css +117 -38
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +1 -1
- package/dist/atomix.min.css.map +1 -1
- package/dist/atomix.umd.js +1 -1
- package/dist/atomix.umd.js.map +1 -1
- package/dist/atomix.umd.min.js +1 -1
- package/dist/charts.d.ts +30 -1
- package/dist/charts.js +566 -597
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +30 -1
- package/dist/core.js +600 -624
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +30 -1
- package/dist/forms.js +1122 -1163
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +31 -89
- package/dist/heavy.js +1015 -1045
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +378 -104
- package/dist/index.esm.js +10959 -10837
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +10935 -10812
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Accordion/Accordion.tsx +2 -5
- package/src/components/AtomixGlass/AtomixGlass.test.tsx +14 -16
- package/src/components/AtomixGlass/AtomixGlass.tsx +137 -355
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +32 -249
- package/src/components/AtomixGlass/GlassFilter.tsx +62 -68
- package/src/components/AtomixGlass/README.md +2 -1
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +19 -18
- package/src/components/AtomixGlass/glass-border-styles.test.ts +58 -0
- package/src/components/AtomixGlass/glass-border-styles.ts +136 -0
- package/src/components/AtomixGlass/glass-utils.ts +411 -6
- package/src/components/AtomixGlass/stories/AnimationFeatures.stories.tsx +158 -537
- package/src/components/AtomixGlass/stories/Border.stories.tsx +149 -0
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +229 -89
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +29 -340
- package/src/components/AtomixGlass/stories/argTypes.ts +30 -13
- package/src/components/AtomixGlass/stories/premium-presets.ts +206 -0
- package/src/components/AtomixGlass/stories/shared-components.tsx +52 -8
- package/src/components/Badge/Badge.tsx +4 -4
- package/src/components/Button/Button.tsx +2 -6
- package/src/components/Callout/Callout.test.tsx +4 -3
- package/src/components/Callout/Callout.tsx +2 -5
- package/src/components/Dropdown/Dropdown.tsx +3 -7
- package/src/components/Form/Checkbox.tsx +2 -8
- package/src/components/Form/Input.tsx +2 -9
- package/src/components/Form/Radio.tsx +2 -9
- package/src/components/Form/Select.tsx +2 -7
- package/src/components/Form/Textarea.tsx +2 -9
- package/src/components/Messages/Messages.tsx +2 -8
- package/src/components/Modal/Modal.tsx +4 -5
- package/src/components/Navigation/Nav/Nav.tsx +2 -6
- package/src/components/Navigation/Navbar/Navbar.tsx +2 -9
- package/src/components/Navigation/SideMenu/SideMenu.tsx +2 -6
- package/src/components/Pagination/Pagination.tsx +2 -10
- package/src/components/Popover/Popover.tsx +2 -9
- package/src/components/Progress/Progress.tsx +2 -7
- package/src/components/Rating/Rating.tsx +2 -10
- package/src/components/Spinner/Spinner.tsx +2 -7
- package/src/components/Steps/Steps.tsx +2 -10
- package/src/components/Tabs/Tabs.tsx +2 -9
- package/src/components/Toggle/Toggle.tsx +2 -10
- package/src/components/Tooltip/Tooltip.tsx +2 -5
- package/src/lib/composables/useAtomixGlass.ts +41 -10
- package/src/lib/composables/useAtomixGlassStyles.ts +59 -75
- package/src/lib/composables/usePerformanceMonitor.ts +5 -0
- package/src/lib/constants/components.ts +358 -46
- package/src/lib/types/components.ts +33 -1
- package/src/styles/01-settings/_settings.atomix-glass.scss +66 -28
- package/src/styles/02-tools/_tools.glass.scss +45 -3
- package/src/styles/06-components/_components.atomix-glass.scss +114 -77
- package/src/components/AtomixGlass/deprecated/AtomixGlass.deprecated.tsx +0 -390
package/dist/core.js
CHANGED
|
@@ -516,6 +516,62 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
516
516
|
SIZES: [ "xs", "sm", "md", "lg", "xl", "none" ],
|
|
517
517
|
DEFAULT: "md"
|
|
518
518
|
}
|
|
519
|
+
}, GLASS_DEFAULTS_BUTTON = {
|
|
520
|
+
displacementScale: 16,
|
|
521
|
+
saturation: 180,
|
|
522
|
+
elasticity: 0
|
|
523
|
+
}, GLASS_DEFAULTS_BADGE = {
|
|
524
|
+
displacementScale: 14,
|
|
525
|
+
borderRadius: 16,
|
|
526
|
+
elasticity: 0
|
|
527
|
+
}, GLASS_DEFAULTS_ACCORDION = {
|
|
528
|
+
displacementScale: 18,
|
|
529
|
+
elasticity: 0
|
|
530
|
+
}, GLASS_DEFAULTS_CALLOUT = {
|
|
531
|
+
displacementScale: 22,
|
|
532
|
+
borderRadius: 8,
|
|
533
|
+
elasticity: 0
|
|
534
|
+
}, GLASS_DEFAULTS_SPINNER = {
|
|
535
|
+
displacementScale: 12,
|
|
536
|
+
elasticity: 0
|
|
537
|
+
}, GLASS_BORDER_GRADIENT = {
|
|
538
|
+
BASE_ANGLE: 135,
|
|
539
|
+
ANGLE_MULTIPLIER: .5,
|
|
540
|
+
VELOCITY_ANGLE_MULTIPLIER: .5,
|
|
541
|
+
CHROMATIC_OFFSET: 1.5,
|
|
542
|
+
STOP_1: {
|
|
543
|
+
MIN: 10,
|
|
544
|
+
BASE: 33,
|
|
545
|
+
get MULTIPLIER() {
|
|
546
|
+
return .009 * this.BASE;
|
|
547
|
+
}
|
|
548
|
+
},
|
|
549
|
+
STOP_2: {
|
|
550
|
+
MAX: 90,
|
|
551
|
+
BASE: 66,
|
|
552
|
+
get MULTIPLIER() {
|
|
553
|
+
return .006 * this.BASE;
|
|
554
|
+
}
|
|
555
|
+
},
|
|
556
|
+
OPACITY: {
|
|
557
|
+
/** Matches $glass-border-1-opacity (0.08) */
|
|
558
|
+
BASE_1: .08,
|
|
559
|
+
get BASE_2() {
|
|
560
|
+
return 3.33 * this.BASE_1;
|
|
561
|
+
},
|
|
562
|
+
get BASE_3() {
|
|
563
|
+
return 2.66 * this.BASE_1;
|
|
564
|
+
},
|
|
565
|
+
get BASE_4() {
|
|
566
|
+
return 5 * this.BASE_1;
|
|
567
|
+
},
|
|
568
|
+
get MULTIPLIER_LOW() {
|
|
569
|
+
return .066 * this.BASE_1;
|
|
570
|
+
},
|
|
571
|
+
get MULTIPLIER_HIGH() {
|
|
572
|
+
return .1 * this.BASE_1;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
519
575
|
}, ATOMIX_GLASS = {
|
|
520
576
|
BASE_CLASS: "c-atomix-glass",
|
|
521
577
|
CONTAINER_CLASS: "c-atomix-glass__container",
|
|
@@ -527,6 +583,22 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
527
583
|
BORDER_BACKDROP_CLASS: "c-atomix-glass__border-backdrop",
|
|
528
584
|
BORDER_1_CLASS: "c-atomix-glass__border-1",
|
|
529
585
|
BORDER_2_CLASS: "c-atomix-glass__border-2",
|
|
586
|
+
/** Centralized liquid glass rim configuration */
|
|
587
|
+
BORDER: {
|
|
588
|
+
WIDTH_CSS_VAR: "--atomix-glass-border-width",
|
|
589
|
+
DEFAULT_WIDTH: "0.5px",
|
|
590
|
+
GRADIENT_CSS_VARS: {
|
|
591
|
+
GRADIENT_1: "--atomix-glass-border-gradient-1",
|
|
592
|
+
GRADIENT_2: "--atomix-glass-border-gradient-2"
|
|
593
|
+
},
|
|
594
|
+
GRADIENT: GLASS_BORDER_GRADIENT,
|
|
595
|
+
OVER_LIGHT: {
|
|
596
|
+
opacity: .7
|
|
597
|
+
},
|
|
598
|
+
DARK: {
|
|
599
|
+
opacity: .35
|
|
600
|
+
}
|
|
601
|
+
},
|
|
530
602
|
HOVER_1_CLASS: "c-atomix-glass__hover-1",
|
|
531
603
|
HOVER_2_CLASS: "c-atomix-glass__hover-2",
|
|
532
604
|
HOVER_3_CLASS: "c-atomix-glass__hover-3",
|
|
@@ -555,25 +627,22 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
555
627
|
SHADER: "c-atomix-glass--shader"
|
|
556
628
|
},
|
|
557
629
|
DEFAULTS: {
|
|
558
|
-
|
|
630
|
+
/** Subtle refraction — Apple UI chrome avoids heavy liquid distortion */
|
|
631
|
+
DISPLACEMENT_SCALE: 28,
|
|
559
632
|
get BLUR_AMOUNT() {
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
// Saturate relative to intensity
|
|
566
|
-
},
|
|
633
|
+
// Apple Music sidebar / player bar: ~20–40px frost (see $glass-backdrop-filter)
|
|
634
|
+
return Math.max(20, .72 * this.DISPLACEMENT_SCALE);
|
|
635
|
+
},
|
|
636
|
+
/** Fixed 180% matches Apple's saturate(180%) backdrop recipe */
|
|
637
|
+
SATURATION: 180,
|
|
567
638
|
get ABERRATION_INTENSITY() {
|
|
568
|
-
return .
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
ELASTICITY: .15,
|
|
639
|
+
return .02 * this.DISPLACEMENT_SCALE;
|
|
640
|
+
},
|
|
641
|
+
ELASTICITY: .05,
|
|
572
642
|
get CORNER_RADIUS() {
|
|
573
643
|
return 16;
|
|
574
644
|
// Use 16 to match SCSS design system (was 20)
|
|
575
645
|
},
|
|
576
|
-
PADDING: "0",
|
|
577
646
|
MODE: "standard",
|
|
578
647
|
OVER_LIGHT: !1,
|
|
579
648
|
ENABLE_OVER_LIGHT_LAYERS: !0,
|
|
@@ -589,19 +658,24 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
589
658
|
},
|
|
590
659
|
CONSTANTS: {
|
|
591
660
|
ACTIVATION_ZONE: 200,
|
|
592
|
-
LERP_FACTOR: .
|
|
661
|
+
LERP_FACTOR: .05,
|
|
662
|
+
// Lower = more viscous, liquid-smooth tracking (Apple feel)
|
|
593
663
|
SMOOTHSTEP_POWER: 2.5,
|
|
594
664
|
MIN_BLUR: .1,
|
|
595
665
|
MOUSE_INFLUENCE_DIVISOR: 100,
|
|
596
666
|
EDGE_FADE_PIXELS: 2,
|
|
597
|
-
// Elasticity physics constants
|
|
598
|
-
ELASTICITY_TRANSLATION_FACTOR: .
|
|
667
|
+
// Elasticity physics constants — Apple-tuned: soft springs, fast settling, minimal stretch
|
|
668
|
+
ELASTICITY_TRANSLATION_FACTOR: .06,
|
|
669
|
+
// Subtler elastic shift (was 0.1)
|
|
599
670
|
ELASTICITY_DISTANCE_THRESHOLD: 200,
|
|
600
671
|
ELASTICITY_COMPRESSION_FACTOR: .3,
|
|
601
|
-
ELASTICITY_STIFFNESS: .
|
|
602
|
-
|
|
672
|
+
ELASTICITY_STIFFNESS: .06,
|
|
673
|
+
// Softer springs = gentler motion (was 0.1)
|
|
674
|
+
ELASTICITY_DAMPING: .88,
|
|
675
|
+
// Fast settling, no wobble (was 0.76)
|
|
603
676
|
ELASTICITY_VELOCITY_FACTOR: .65,
|
|
604
|
-
ELASTICITY_STRETCH_RATIO: .
|
|
677
|
+
ELASTICITY_STRETCH_RATIO: .25,
|
|
678
|
+
// Less visible surface tension stretch (was 0.45)
|
|
605
679
|
ELASTICITY_MAGNIFICATION_BASE: 1.02,
|
|
606
680
|
// Note: This default must match the SCSS variable --atomix-radius-md
|
|
607
681
|
// @see src/styles/01-settings/_settings.global.scss
|
|
@@ -615,55 +689,16 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
615
689
|
},
|
|
616
690
|
// Gradient calculation constants
|
|
617
691
|
GRADIENT: {
|
|
618
|
-
BASE_ANGLE:
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
// Minimum percentage for border stop 1
|
|
629
|
-
BASE: 33,
|
|
630
|
-
// Base percentage for border stop 1
|
|
631
|
-
get MULTIPLIER() {
|
|
632
|
-
return .009 * this.BASE;
|
|
633
|
-
}
|
|
634
|
-
},
|
|
635
|
-
BORDER_STOP_2: {
|
|
636
|
-
MAX: 90,
|
|
637
|
-
// Maximum percentage for border stop 2
|
|
638
|
-
BASE: 66,
|
|
639
|
-
// Base percentage for border stop 2
|
|
640
|
-
get MULTIPLIER() {
|
|
641
|
-
return .006 * this.BASE;
|
|
642
|
-
}
|
|
643
|
-
},
|
|
644
|
-
BORDER_OPACITY: {
|
|
645
|
-
BASE_1: .12,
|
|
646
|
-
// Base opacity for border gradient 1
|
|
647
|
-
get BASE_2() {
|
|
648
|
-
return 3.33 * this.BASE_1;
|
|
649
|
-
},
|
|
650
|
-
// Base opacity for border gradient 2
|
|
651
|
-
get BASE_3() {
|
|
652
|
-
return 2.66 * this.BASE_1;
|
|
653
|
-
},
|
|
654
|
-
// Base opacity for border gradient 3
|
|
655
|
-
get BASE_4() {
|
|
656
|
-
return 5 * this.BASE_1;
|
|
657
|
-
},
|
|
658
|
-
// Base opacity for border gradient 4
|
|
659
|
-
get MULTIPLIER_LOW() {
|
|
660
|
-
return .066 * this.BASE_1;
|
|
661
|
-
},
|
|
662
|
-
// Low multiplier for mouse influence on opacity
|
|
663
|
-
get MULTIPLIER_HIGH() {
|
|
664
|
-
return .1 * this.BASE_1;
|
|
665
|
-
}
|
|
666
|
-
},
|
|
692
|
+
BASE_ANGLE: GLASS_BORDER_GRADIENT.BASE_ANGLE,
|
|
693
|
+
ANGLE_MULTIPLIER: GLASS_BORDER_GRADIENT.ANGLE_MULTIPLIER,
|
|
694
|
+
VELOCITY_ANGLE_MULTIPLIER: GLASS_BORDER_GRADIENT.VELOCITY_ANGLE_MULTIPLIER,
|
|
695
|
+
CHROMATIC_OFFSET: GLASS_BORDER_GRADIENT.CHROMATIC_OFFSET,
|
|
696
|
+
/** @deprecated Use ATOMIX_GLASS.BORDER.GRADIENT.STOP_1 */
|
|
697
|
+
BORDER_STOP_1: GLASS_BORDER_GRADIENT.STOP_1,
|
|
698
|
+
/** @deprecated Use ATOMIX_GLASS.BORDER.GRADIENT.STOP_2 */
|
|
699
|
+
BORDER_STOP_2: GLASS_BORDER_GRADIENT.STOP_2,
|
|
700
|
+
/** @deprecated Use ATOMIX_GLASS.BORDER.GRADIENT.OPACITY */
|
|
701
|
+
BORDER_OPACITY: GLASS_BORDER_GRADIENT.OPACITY,
|
|
667
702
|
CENTER_POSITION: 50,
|
|
668
703
|
// Center position percentage (50%)
|
|
669
704
|
HOVER_POSITION: {
|
|
@@ -696,8 +731,8 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
696
731
|
return 2 * this.BLACK_STOP;
|
|
697
732
|
},
|
|
698
733
|
// End percentage for black hover 1
|
|
699
|
-
WHITE_START: .
|
|
700
|
-
//
|
|
734
|
+
WHITE_START: .35,
|
|
735
|
+
// Gentler hover flash — Apple hover is barely visible
|
|
701
736
|
get WHITE_STOP() {
|
|
702
737
|
return this.BLACK_END - 10;
|
|
703
738
|
}
|
|
@@ -715,8 +750,8 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
715
750
|
return 2 * this.BLACK_STOP;
|
|
716
751
|
},
|
|
717
752
|
// End percentage for black hover 2
|
|
718
|
-
WHITE_START:
|
|
719
|
-
//
|
|
753
|
+
WHITE_START: .7,
|
|
754
|
+
// Gentler hover flash
|
|
720
755
|
get WHITE_STOP() {
|
|
721
756
|
return this.BLACK_END;
|
|
722
757
|
}
|
|
@@ -734,8 +769,8 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
734
769
|
return 2 * this.BLACK_STOP;
|
|
735
770
|
},
|
|
736
771
|
// End percentage for black hover 3
|
|
737
|
-
WHITE_START:
|
|
738
|
-
//
|
|
772
|
+
WHITE_START: .7,
|
|
773
|
+
// Gentler hover flash
|
|
739
774
|
get WHITE_STOP() {
|
|
740
775
|
return this.BLACK_END;
|
|
741
776
|
}
|
|
@@ -745,13 +780,13 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
745
780
|
BASE_GRADIENT: {
|
|
746
781
|
ANGLE: 135,
|
|
747
782
|
// Gradient angle in degrees
|
|
748
|
-
BLACK_START_BASE: .
|
|
783
|
+
BLACK_START_BASE: .1,
|
|
749
784
|
// Base start opacity for black
|
|
750
785
|
get BLACK_START_MULTIPLIER() {
|
|
751
786
|
return .02 * this.BLACK_START_BASE;
|
|
752
787
|
},
|
|
753
788
|
// Multiplier for mouse X influence on start
|
|
754
|
-
BLACK_MID_BASE: .
|
|
789
|
+
BLACK_MID_BASE: .07,
|
|
755
790
|
// Base mid opacity for black
|
|
756
791
|
get BLACK_MID_MULTIPLIER() {
|
|
757
792
|
return .02 * this.BLACK_MID_BASE;
|
|
@@ -772,7 +807,7 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
772
807
|
}
|
|
773
808
|
},
|
|
774
809
|
OVERLAY_GRADIENT: {
|
|
775
|
-
BLACK_START_BASE: .
|
|
810
|
+
BLACK_START_BASE: .08,
|
|
776
811
|
// Base start opacity for black overlay
|
|
777
812
|
get BLACK_START_MULTIPLIER() {
|
|
778
813
|
return .025 * this.BLACK_START_BASE;
|
|
@@ -796,14 +831,14 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
796
831
|
return .416 * this.BLACK_START_BASE;
|
|
797
832
|
}
|
|
798
833
|
},
|
|
799
|
-
// Overlay highlight constants
|
|
834
|
+
// Overlay highlight constants — Apple places specular at the top-center
|
|
800
835
|
OVERLAY_HIGHLIGHT: {
|
|
801
|
-
POSITION_X:
|
|
802
|
-
//
|
|
803
|
-
POSITION_Y:
|
|
804
|
-
//
|
|
805
|
-
WHITE_OPACITY: .
|
|
806
|
-
//
|
|
836
|
+
POSITION_X: 50,
|
|
837
|
+
// Centered horizontal — Apple's top-center specular
|
|
838
|
+
POSITION_Y: 5,
|
|
839
|
+
// Very top — catches light like a curved glass surface
|
|
840
|
+
WHITE_OPACITY: .28,
|
|
841
|
+
// Softer specular — visible but not glaring
|
|
807
842
|
get STOP() {
|
|
808
843
|
return 150 * this.WHITE_OPACITY;
|
|
809
844
|
},
|
|
@@ -824,6 +859,10 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
824
859
|
SATURATION: {
|
|
825
860
|
HIGH_CONTRAST: 200
|
|
826
861
|
},
|
|
862
|
+
// Container shadows — hairline inner catch + soft floating lift (Apple player bar)
|
|
863
|
+
CONTAINER_SHADOW: {
|
|
864
|
+
LIGHT: "inset 0 0.5px 0 rgba(255, 255, 255, 0.32), inset 0 1px 2px rgba(255, 255, 255, 0.06), 0 8px 32px rgba(0, 0, 0, 0.28), 0 2px 8px rgba(0, 0, 0, 0.16)"
|
|
865
|
+
},
|
|
827
866
|
// Phase 1: Animation System Constants
|
|
828
867
|
ANIMATION: {
|
|
829
868
|
// Breathing effect timing (in milliseconds)
|
|
@@ -863,7 +902,44 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
863
902
|
}
|
|
864
903
|
}
|
|
865
904
|
}
|
|
866
|
-
}
|
|
905
|
+
};
|
|
906
|
+
|
|
907
|
+
/**
|
|
908
|
+
* Default theme colors for components
|
|
909
|
+
*/
|
|
910
|
+
/**
|
|
911
|
+
* Button-specific constants
|
|
912
|
+
*/
|
|
913
|
+
/**
|
|
914
|
+
* Component Utilities
|
|
915
|
+
*
|
|
916
|
+
* Helper functions for component development with the new customization system
|
|
917
|
+
*/
|
|
918
|
+
/**
|
|
919
|
+
* Merge multiple class names
|
|
920
|
+
*/
|
|
921
|
+
function mergeClassNames(...classes) {
|
|
922
|
+
return classes.filter(Boolean).join(" ");
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
/**
|
|
926
|
+
* Utility to merge multiple React refs into one
|
|
927
|
+
*/ function setRef(ref, value) {
|
|
928
|
+
"function" == typeof ref ? ref(value) : ref && (
|
|
929
|
+
// This is safe because we're checking that ref exists first
|
|
930
|
+
ref.current = value);
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
/**
|
|
934
|
+
* Combines two React refs into a single ref function
|
|
935
|
+
* This is used when you need to use and forward a ref at the same time
|
|
936
|
+
*/ function useForkRef(refA, refB) {
|
|
937
|
+
return React.useMemo((() => null == refA && null == refB ? null : refValue => {
|
|
938
|
+
setRef(refA, refValue), setRef(refB, refValue);
|
|
939
|
+
}), [ refA, refB ]);
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
const {CONSTANTS: CONSTANTS$3} = ATOMIX_GLASS, calculateElementCenter = rect => rect ? {
|
|
867
943
|
x: rect.left + rect.width / 2,
|
|
868
944
|
y: rect.top + rect.height / 2
|
|
869
945
|
} : {
|
|
@@ -871,37 +947,37 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
871
947
|
y: 0
|
|
872
948
|
}, calculateMouseInfluence = mouseOffset => {
|
|
873
949
|
if (!mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y) return 0;
|
|
874
|
-
//
|
|
875
|
-
const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$
|
|
950
|
+
// Clamp influence to keep mouse response subtle and stable.
|
|
951
|
+
const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$3.MOUSE_INFLUENCE_DIVISOR;
|
|
876
952
|
return Math.min(.8, influence);
|
|
877
953
|
// Tighter cap to prevent blur/filter blow-out
|
|
878
|
-
}, clampBlur = value => "number" != typeof value || isNaN(value) ? CONSTANTS$
|
|
954
|
+
}, clampBlur = value => "number" != typeof value || isNaN(value) ? CONSTANTS$3.MIN_BLUR : Math.max(CONSTANTS$3.MIN_BLUR, Math.min(50, value)), validateGlassSize = size => size && "number" == typeof size.width && "number" == typeof size.height && size.width > 0 && size.height > 0 && size.width <= CONSTANTS$3.MAX_SIZE && size.height <= CONSTANTS$3.MAX_SIZE, parseBorderRadiusValue = value => {
|
|
879
955
|
if ("number" == typeof value) return Math.max(0, value);
|
|
880
|
-
if ("string" != typeof value || !value.trim()) return CONSTANTS$
|
|
956
|
+
if ("string" != typeof value || !value.trim()) return CONSTANTS$3.DEFAULT_CORNER_RADIUS;
|
|
881
957
|
const trimmedValue = value.trim();
|
|
882
958
|
// Handle px values
|
|
883
959
|
if (trimmedValue.endsWith("px")) {
|
|
884
960
|
const parsed = parseFloat(trimmedValue);
|
|
885
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
961
|
+
return isNaN(parsed) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
|
|
886
962
|
}
|
|
887
963
|
// Handle rem values (assume 16px = 1rem)
|
|
888
964
|
if (trimmedValue.endsWith("rem")) {
|
|
889
965
|
const parsed = parseFloat(trimmedValue);
|
|
890
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
966
|
+
return isNaN(parsed) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
891
967
|
}
|
|
892
968
|
// Handle em values (assume 16px = 1em for simplicity)
|
|
893
969
|
if (trimmedValue.endsWith("em")) {
|
|
894
970
|
const parsed = parseFloat(trimmedValue);
|
|
895
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
971
|
+
return isNaN(parsed) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
896
972
|
}
|
|
897
973
|
// Handle percentage (convert to approximate px value, assuming 200px container)
|
|
898
974
|
if (trimmedValue.endsWith("%")) {
|
|
899
975
|
const parsed = parseFloat(trimmedValue);
|
|
900
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
976
|
+
return isNaN(parsed) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
|
|
901
977
|
}
|
|
902
978
|
// Handle unitless numbers
|
|
903
979
|
const numValue = parseFloat(trimmedValue);
|
|
904
|
-
return isNaN(numValue) ? CONSTANTS$
|
|
980
|
+
return isNaN(numValue) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
|
|
905
981
|
}, extractBorderRadiusFromElement = element => {
|
|
906
982
|
if (!element || !element.props) return null;
|
|
907
983
|
// Check inline styles first (highest priority)
|
|
@@ -917,11 +993,11 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
917
993
|
// If element has children, recursively check them
|
|
918
994
|
if (element.props.children) {
|
|
919
995
|
const childRadius = extractBorderRadiusFromChildren(element.props.children);
|
|
920
|
-
if (childRadius > 0 && childRadius !== CONSTANTS$
|
|
996
|
+
if (childRadius > 0 && childRadius !== CONSTANTS$3.DEFAULT_CORNER_RADIUS) return childRadius;
|
|
921
997
|
}
|
|
922
998
|
return null;
|
|
923
999
|
}, extractBorderRadiusFromChildren = children => {
|
|
924
|
-
if (!children) return CONSTANTS$
|
|
1000
|
+
if (!children) return CONSTANTS$3.DEFAULT_CORNER_RADIUS;
|
|
925
1001
|
try {
|
|
926
1002
|
const childArray = React.Children.toArray(children);
|
|
927
1003
|
for (let i = 0; i < childArray.length; i++) {
|
|
@@ -934,7 +1010,7 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
934
1010
|
} catch (error) {
|
|
935
1011
|
// Silently handle errors
|
|
936
1012
|
}
|
|
937
|
-
return CONSTANTS$
|
|
1013
|
+
return CONSTANTS$3.DEFAULT_CORNER_RADIUS;
|
|
938
1014
|
}, smoothstep = t => {
|
|
939
1015
|
const clamped = Math.max(0, Math.min(1, t));
|
|
940
1016
|
return clamped * clamped * (3 - 2 * clamped);
|
|
@@ -944,7 +1020,47 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
944
1020
|
value: current + newVelocity,
|
|
945
1021
|
velocity: newVelocity
|
|
946
1022
|
};
|
|
947
|
-
}
|
|
1023
|
+
};
|
|
1024
|
+
|
|
1025
|
+
/**
|
|
1026
|
+
* Calculate element center from bounding rect
|
|
1027
|
+
*/
|
|
1028
|
+
/**
|
|
1029
|
+
* Normalizes a layout inset for use in CSS custom properties.
|
|
1030
|
+
*
|
|
1031
|
+
* @param value - Raw inset from `style` (number, px string, or `auto`).
|
|
1032
|
+
* @param fallback - Value used when `value` is undefined.
|
|
1033
|
+
*/
|
|
1034
|
+
function formatGlassInsetValue(value, fallback = "auto") {
|
|
1035
|
+
return void 0 === value ? "number" == typeof fallback ? `${fallback}px` : String(fallback) : "auto" === value ? "auto" : "number" == typeof value ? `${value}px` : value;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
/**
|
|
1039
|
+
* Determines whether the glass should use fixed/sticky layout semantics.
|
|
1040
|
+
*
|
|
1041
|
+
* @param explicit - Value of the `isFixedOrSticky` prop.
|
|
1042
|
+
* @param position - `position` from the consumer `style` object.
|
|
1043
|
+
*/
|
|
1044
|
+
/** Coerces a value to a finite number, returning `fallback` when invalid. */
|
|
1045
|
+
function toSafeNumber(value, fallback = 0) {
|
|
1046
|
+
return "number" != typeof value || isNaN(value) ? fallback : value;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
/**
|
|
1050
|
+
* Calculates the target frame rate for shader time-animation loops.
|
|
1051
|
+
*
|
|
1052
|
+
* Balances visual quality against distortion complexity and `animationSpeed`.
|
|
1053
|
+
*/
|
|
1054
|
+
/**
|
|
1055
|
+
* Computes per-channel displacement scale for the SVG chromatic-aberration filter.
|
|
1056
|
+
*/
|
|
1057
|
+
function getChromaticDisplacementScale(mode, displacementScale, aberrationIntensity, channelFactor) {
|
|
1058
|
+
return displacementScale * (("shader" === mode ? 1 : -1) - aberrationIntensity * channelFactor);
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
/**
|
|
1062
|
+
* Get displacement map URL based on mode
|
|
1063
|
+
*/ const getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
|
|
948
1064
|
switch (mode) {
|
|
949
1065
|
case "standard":
|
|
950
1066
|
return displacementMap;
|
|
@@ -961,13 +1077,28 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
961
1077
|
default:
|
|
962
1078
|
return console.warn("AtomixGlass: Invalid displacement mode"), displacementMap;
|
|
963
1079
|
}
|
|
964
|
-
}, sharedShaderCache = new Map,
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
1080
|
+
}, sharedShaderCache = new Map, CHROMATIC_CHANNELS = [ {
|
|
1081
|
+
result: "RED_DISPLACED",
|
|
1082
|
+
channelResult: "RED_CHANNEL",
|
|
1083
|
+
aberrationFactor: 0,
|
|
1084
|
+
colorMatrix: "1 0 0 0 0\n0 0 0 0 0\n0 0 0 0 0\n0 0 0 1 0"
|
|
1085
|
+
}, {
|
|
1086
|
+
result: "GREEN_DISPLACED",
|
|
1087
|
+
channelResult: "GREEN_CHANNEL",
|
|
1088
|
+
aberrationFactor: .02,
|
|
1089
|
+
colorMatrix: "0 0 0 0 0\n0 1 0 0 0\n0 0 0 0 0\n0 0 0 1 0"
|
|
1090
|
+
}, {
|
|
1091
|
+
result: "BLUE_DISPLACED",
|
|
1092
|
+
channelResult: "BLUE_CHANNEL",
|
|
1093
|
+
aberrationFactor: .03,
|
|
1094
|
+
colorMatrix: "0 0 0 0 0\n0 0 0 0 0\n0 0 1 0 0\n0 0 0 1 0"
|
|
1095
|
+
} ], FILTER_SVG_STYLE = {
|
|
1096
|
+
position: "absolute",
|
|
1097
|
+
width: "100%",
|
|
1098
|
+
height: "100%",
|
|
1099
|
+
inset: 0
|
|
1100
|
+
}, GlassFilterComponent = ({id: id, displacementScale: displacementScale, aberrationIntensity: aberrationIntensity, mode: mode, shaderMapUrl: shaderMapUrl, blurAmount: blurAmount}) => jsx("svg", {
|
|
1101
|
+
style: FILTER_SVG_STYLE,
|
|
971
1102
|
"aria-hidden": "true",
|
|
972
1103
|
children: jsxs("defs", {
|
|
973
1104
|
children: [ jsxs("radialGradient", {
|
|
@@ -1021,43 +1152,21 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
1021
1152
|
dx: "0",
|
|
1022
1153
|
dy: "0",
|
|
1023
1154
|
result: "CENTER_ORIGINAL"
|
|
1024
|
-
}),
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
scale: displacementScale * (("shader" === mode ? 1 : -1) - .02 * aberrationIntensity),
|
|
1040
|
-
xChannelSelector: "R",
|
|
1041
|
-
yChannelSelector: "B",
|
|
1042
|
-
result: "GREEN_DISPLACED"
|
|
1043
|
-
}), jsx("feColorMatrix", {
|
|
1044
|
-
in: "GREEN_DISPLACED",
|
|
1045
|
-
type: "matrix",
|
|
1046
|
-
values: "0 0 0 0 0\n 0 1 0 0 0\n 0 0 0 0 0\n 0 0 0 1 0",
|
|
1047
|
-
result: "GREEN_CHANNEL"
|
|
1048
|
-
}), jsx("feDisplacementMap", {
|
|
1049
|
-
in: "SourceGraphic",
|
|
1050
|
-
in2: "DISPLACEMENT_MAP",
|
|
1051
|
-
scale: displacementScale * (("shader" === mode ? 1 : -1) - .03 * aberrationIntensity),
|
|
1052
|
-
xChannelSelector: "R",
|
|
1053
|
-
yChannelSelector: "B",
|
|
1054
|
-
result: "BLUE_DISPLACED"
|
|
1055
|
-
}), jsx("feColorMatrix", {
|
|
1056
|
-
in: "BLUE_DISPLACED",
|
|
1057
|
-
type: "matrix",
|
|
1058
|
-
values: "0 0 0 0 0\n 0 0 0 0 0\n 0 0 1 0 0\n 0 0 0 1 0",
|
|
1059
|
-
result: "BLUE_CHANNEL"
|
|
1060
|
-
}), jsx("feBlend", {
|
|
1155
|
+
}), CHROMATIC_CHANNELS.map((channel => jsxs(React.Fragment, {
|
|
1156
|
+
children: [ jsx("feDisplacementMap", {
|
|
1157
|
+
in: "SourceGraphic",
|
|
1158
|
+
in2: "DISPLACEMENT_MAP",
|
|
1159
|
+
scale: getChromaticDisplacementScale(mode, displacementScale, aberrationIntensity, channel.aberrationFactor),
|
|
1160
|
+
xChannelSelector: "R",
|
|
1161
|
+
yChannelSelector: "B",
|
|
1162
|
+
result: channel.result
|
|
1163
|
+
}), jsx("feColorMatrix", {
|
|
1164
|
+
in: channel.result,
|
|
1165
|
+
type: "matrix",
|
|
1166
|
+
values: channel.colorMatrix,
|
|
1167
|
+
result: channel.channelResult
|
|
1168
|
+
}) ]
|
|
1169
|
+
}, channel.channelResult))), jsx("feBlend", {
|
|
1061
1170
|
in: "GREEN_CHANNEL",
|
|
1062
1171
|
in2: "BLUE_CHANNEL",
|
|
1063
1172
|
mode: "screen",
|
|
@@ -1098,24 +1207,22 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
1098
1207
|
});
|
|
1099
1208
|
|
|
1100
1209
|
/**
|
|
1101
|
-
*
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
*
|
|
1210
|
+
* Module-level LRU cache for shader displacement maps.
|
|
1211
|
+
*
|
|
1212
|
+
* Shared across all `AtomixGlassContainer` instances so identical size and
|
|
1213
|
+
* variant combinations are generated once.
|
|
1105
1214
|
*/ GlassFilterComponent.displayName = "GlassFilter";
|
|
1106
1215
|
|
|
1107
|
-
|
|
1216
|
+
/** Shallow prop comparison to avoid redundant SVG filter regeneration. */
|
|
1108
1217
|
const GlassFilter = memo(GlassFilterComponent, ((prevProps, nextProps) => prevProps.id === nextProps.id && prevProps.displacementScale === nextProps.displacementScale && prevProps.aberrationIntensity === nextProps.aberrationIntensity && prevProps.mode === nextProps.mode && prevProps.shaderMapUrl === nextProps.shaderMapUrl && prevProps.blurAmount === nextProps.blurAmount)), AtomixGlassContainer = forwardRef((({children: children, className: className = "", style: style, displacementScale: displacementScale = 25, blurAmount: blurAmount = .0625, saturation: saturation = 180, aberrationIntensity: aberrationIntensity = 2, mouseOffset: mouseOffset = {
|
|
1109
1218
|
x: 0,
|
|
1110
1219
|
y: 0
|
|
1111
|
-
}, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {}, borderRadius: borderRadius = 0,
|
|
1220
|
+
}, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {}, borderRadius: borderRadius = 0, glassSize: glassSize = {
|
|
1112
1221
|
width: 0,
|
|
1113
1222
|
height: 0
|
|
1114
|
-
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, isFixedOrSticky: isFixedOrSticky = !1,
|
|
1115
|
-
// Phase 1: Animation System props
|
|
1116
|
-
shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion = !1, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5, distortionQuality: distortionQuality = "medium", contentRef: contentRef}, ref) => {
|
|
1223
|
+
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, isFixedOrSticky: isFixedOrSticky = !1, shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion = !1, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5, distortionQuality: distortionQuality = "medium", contentRef: contentRef}, ref) => {
|
|
1117
1224
|
// React 18 useId — stable, unique, and SSR-safe (no module-level counter)
|
|
1118
|
-
const rawId = useId(), filterId = useMemo((() => `atomix-glass-filter-${rawId.replace(/:/g, "")}`), [ rawId ]), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null), shaderUpdateTimeoutRef = useRef(null), animationFrameRef = useRef(null);
|
|
1225
|
+
const rawId = useId(), filterId = useMemo((() => `atomix-glass-filter-${rawId.replace(/:/g, "")}`), [ rawId ]), containerRef = useForkRef(ref, null), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null), shaderUpdateTimeoutRef = useRef(null), animationFrameRef = useRef(null);
|
|
1119
1226
|
// Lazy load shader utilities only when shader mode is needed
|
|
1120
1227
|
useEffect((() => {
|
|
1121
1228
|
"shader" === mode ?
|
|
@@ -1193,15 +1300,23 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
1193
1300
|
shaderGeneratorRef.current = null;
|
|
1194
1301
|
}
|
|
1195
1302
|
};
|
|
1196
|
-
}), [ mode, glassSize, shaderVariant ]),
|
|
1197
|
-
// Phase 1: Time-Based Animation Loop - Continuous shader regeneration
|
|
1198
|
-
useEffect((() => {
|
|
1303
|
+
}), [ mode, glassSize, shaderVariant ]), useEffect((() => {
|
|
1199
1304
|
// Only run animations in shader mode with time animation enabled
|
|
1200
1305
|
if ("shader" !== mode || !withTimeAnimation || effectiveReducedMotion || effectiveWithoutEffects)
|
|
1201
1306
|
// Cancel any existing animation frame
|
|
1202
1307
|
return void (null !== animationFrameRef.current && (cancelAnimationFrame(animationFrameRef.current),
|
|
1203
1308
|
animationFrameRef.current = null));
|
|
1204
|
-
const
|
|
1309
|
+
const targetFps = function(options) {
|
|
1310
|
+
const {distortionQuality: distortionQuality, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5} = options, baseFps = "ultra" === distortionQuality ? 60 : "high" === distortionQuality ? 30 : "medium" === distortionQuality ? 24 : 20, effectiveSpeed = Math.max(.5, Math.min(2, animationSpeed)), complexity = withMultiLayerDistortion ? Math.max(1, distortionOctaves / 3 + .25 * Math.max(0, distortionLacunarity - 2) + Math.max(0, distortionGain - .5)) : 1;
|
|
1311
|
+
return Math.max(12, Math.min(60, Math.round(baseFps * effectiveSpeed / complexity)));
|
|
1312
|
+
}({
|
|
1313
|
+
distortionQuality: distortionQuality,
|
|
1314
|
+
animationSpeed: animationSpeed,
|
|
1315
|
+
withMultiLayerDistortion: withMultiLayerDistortion,
|
|
1316
|
+
distortionOctaves: distortionOctaves,
|
|
1317
|
+
distortionLacunarity: distortionLacunarity,
|
|
1318
|
+
distortionGain: distortionGain
|
|
1319
|
+
}), frameInterval = 1e3 / targetFps;
|
|
1205
1320
|
let lastUpdate = 0, isCancelled = !1;
|
|
1206
1321
|
const animate = currentTime => {
|
|
1207
1322
|
if (!isCancelled) {
|
|
@@ -1225,88 +1340,21 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
1225
1340
|
};
|
|
1226
1341
|
}), [ mode, withTimeAnimation, animationSpeed, displacementScale, withMultiLayerDistortion, distortionOctaves, distortionLacunarity, distortionGain, distortionQuality, effectiveReducedMotion, effectiveWithoutEffects, glassSize ]);
|
|
1227
1342
|
// Removed forced reflow to avoid layout thrash and potential feedback sizing loops
|
|
1228
|
-
const
|
|
1229
|
-
useEffect((() => {
|
|
1230
|
-
if (!ref || "function" == typeof ref) return;
|
|
1231
|
-
const element = ref.current;
|
|
1232
|
-
if (element) try {
|
|
1233
|
-
setRectCache(element.getBoundingClientRect());
|
|
1234
|
-
} catch (error) {
|
|
1235
|
-
console.warn("AtomixGlassContainer: Error getting element bounds", error), setRectCache(null);
|
|
1236
|
-
}
|
|
1237
|
-
}), [ ref, glassSize ]);
|
|
1238
|
-
const liquidBlur = useMemo((() => {
|
|
1239
|
-
const defaultBlur = {
|
|
1240
|
-
baseBlur: blurAmount,
|
|
1241
|
-
edgeBlur: 1.25 * blurAmount,
|
|
1242
|
-
centerBlur: 1.1 * blurAmount,
|
|
1243
|
-
flowBlur: 1.2 * blurAmount
|
|
1244
|
-
};
|
|
1245
|
-
// Enhanced validation for liquid blur
|
|
1246
|
-
if (!withLiquidBlur || !rectCache || !mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y || isNaN(mouseOffset.x) || isNaN(mouseOffset.y)) return defaultBlur;
|
|
1343
|
+
const containerVars = useMemo((() => {
|
|
1247
1344
|
try {
|
|
1248
|
-
const mouseInfluence = calculateMouseInfluence(mouseOffset), maxBlur = 2 * blurAmount, baseBlur = Math.min(maxBlur, blurAmount + mouseInfluence * blurAmount * .15), edgeIntensity = .15 * mouseInfluence, edgeBlur = Math.min(maxBlur, baseBlur * (.8 + .4 * edgeIntensity)), centerIntensity = .1 * mouseInfluence, centerBlur = Math.min(maxBlur, baseBlur * (.3 + .3 * centerIntensity)), flowBlur = Math.min(maxBlur, 1.2 * baseBlur);
|
|
1249
|
-
// NOTE: hover/active multipliers intentionally omitted here —
|
|
1250
|
-
// they belong on opacity layers, not the blur filter itself.
|
|
1251
1345
|
return {
|
|
1252
|
-
|
|
1253
|
-
edgeBlur: clampBlur(edgeBlur),
|
|
1254
|
-
centerBlur: clampBlur(centerBlur),
|
|
1255
|
-
flowBlur: clampBlur(flowBlur)
|
|
1256
|
-
};
|
|
1257
|
-
} catch (error) {
|
|
1258
|
-
return console.warn("AtomixGlassContainer: Error calculating liquid blur", error),
|
|
1259
|
-
defaultBlur;
|
|
1260
|
-
}
|
|
1261
|
-
}), [ withLiquidBlur, blurAmount, mouseOffset, rectCache ]), backdropStyle = useMemo((() => {
|
|
1262
|
-
try {
|
|
1263
|
-
const dynamicSaturation = saturation + 20 * (liquidBlur.baseBlur || 0), validatedBaseBlur = "number" != typeof liquidBlur.baseBlur || isNaN(liquidBlur.baseBlur) ? 0 : liquidBlur.baseBlur, validatedEdgeBlur = "number" != typeof liquidBlur.edgeBlur || isNaN(liquidBlur.edgeBlur) ? 0 : liquidBlur.edgeBlur, validatedCenterBlur = "number" != typeof liquidBlur.centerBlur || isNaN(liquidBlur.centerBlur) ? 0 : liquidBlur.centerBlur, validatedFlowBlur = "number" != typeof liquidBlur.flowBlur || isNaN(liquidBlur.flowBlur) ? 0 : liquidBlur.flowBlur, area = rectCache ? rectCache.width * rectCache.height : 0;
|
|
1264
|
-
// Validate blur values before using them
|
|
1265
|
-
return !withLiquidBlur || effectiveReducedMotion || effectiveWithoutEffects || area > 18e4 ? {
|
|
1266
|
-
backdropFilter: `blur(${clampBlur(Math.max(validatedBaseBlur, .8 * validatedEdgeBlur, 1.1 * validatedCenterBlur, .9 * validatedFlowBlur))}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1.05}) brightness(${overLightConfig?.brightness || 1.05})`
|
|
1267
|
-
} : {
|
|
1268
|
-
backdropFilter: `blur(${clampBlur(.4 * validatedBaseBlur + .25 * validatedEdgeBlur + .15 * validatedCenterBlur + .2 * validatedFlowBlur)}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1}) brightness(${overLightConfig?.brightness || 1})`
|
|
1269
|
-
};
|
|
1270
|
-
// Single-pass fallback: stronger radius to match perceived blur of multi-pass
|
|
1271
|
-
} catch (error) {
|
|
1272
|
-
return console.warn("AtomixGlassContainer: Error calculating backdrop style", error),
|
|
1273
|
-
{
|
|
1274
|
-
backdropFilter: `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`
|
|
1275
|
-
};
|
|
1276
|
-
}
|
|
1277
|
-
}), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveWithoutEffects, withLiquidBlur, overLightConfig ]), containerVars = useMemo((() => {
|
|
1278
|
-
try {
|
|
1279
|
-
// Safe extraction of mouse offset values
|
|
1280
|
-
const mx = mouseOffset && "number" == typeof mouseOffset.x && !isNaN(mouseOffset.x) ? mouseOffset.x : 0, my = mouseOffset && "number" == typeof mouseOffset.y && !isNaN(mouseOffset.y) ? mouseOffset.y : 0;
|
|
1281
|
-
return {
|
|
1282
|
-
"--atomix-glass-container-radius": `${"number" != typeof borderRadius || isNaN(borderRadius) ? 0 : borderRadius}px`,
|
|
1283
|
-
"--atomix-glass-container-backdrop": backdropStyle?.backdropFilter || "none",
|
|
1284
|
-
"--atomix-glass-container-shadow": overLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${(.4 + .002 * mx) * (overLightConfig?.shadowIntensity || 1)})`, `inset 0 -1px 0 rgba(0, 0, 0, ${(.2 + .001 * Math.abs(my)) * (overLightConfig?.shadowIntensity || 1)})`, `inset 0 0 20px rgba(0, 0, 0, ${(.08 + .001 * Math.abs(mx + my)) * (overLightConfig?.shadowIntensity || 1)})`, `0 2px 12px rgba(0, 0, 0, ${(.12 + .002 * Math.abs(my)) * (overLightConfig?.shadowIntensity || 1)})` ].join(", ") : "0 0 20px rgba(0, 0, 0, 0.15) inset, 0 4px 8px rgba(0, 0, 0, 0.08) inset",
|
|
1285
|
-
"--atomix-glass-container-shadow-opacity": effectiveWithoutEffects ? 0 : 1,
|
|
1286
|
-
// Background and shadow values use design token-aligned RGB values
|
|
1287
|
-
"--atomix-glass-container-bg": overLight ? `linear-gradient(${180 + .5 * mx}deg, rgba(255, 255, 255, 0.1) 0%, transparent 20%, transparent 80%, rgba(0, 0, 0, 0.05) 100%)` : "none",
|
|
1288
|
-
"--atomix-glass-container-text-shadow": overLight ? "0px 1px 2px rgba(255, 255, 255, 0.15)" : "0px 2px 12px rgba(0, 0, 0, 0.4)",
|
|
1289
|
-
"--atomix-glass-container-box-shadow": overLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "0px 12px 40px rgba(0, 0, 0, 0.25)"
|
|
1346
|
+
"--atomix-glass-container-radius": `${"number" != typeof borderRadius || isNaN(borderRadius) ? 0 : borderRadius}px`
|
|
1290
1347
|
};
|
|
1291
1348
|
} catch (error) {
|
|
1292
1349
|
return console.warn("AtomixGlassContainer: Error generating container variables", error),
|
|
1293
1350
|
{
|
|
1294
|
-
"--atomix-glass-container-
|
|
1295
|
-
"--atomix-glass-container-radius": "0px",
|
|
1296
|
-
"--atomix-glass-container-backdrop": "none",
|
|
1297
|
-
"--atomix-glass-container-shadow": "none",
|
|
1298
|
-
"--atomix-glass-container-shadow-opacity": 1,
|
|
1299
|
-
"--atomix-glass-container-bg": "none",
|
|
1300
|
-
"--atomix-glass-container-text-shadow": "none"
|
|
1351
|
+
"--atomix-glass-container-radius": "0px"
|
|
1301
1352
|
};
|
|
1302
1353
|
}
|
|
1303
|
-
}), [ borderRadius
|
|
1354
|
+
}), [ borderRadius ]);
|
|
1304
1355
|
return jsx("div", {
|
|
1305
|
-
ref:
|
|
1306
|
-
|
|
1307
|
-
"function" == typeof ref ? ref(el) : ref && (ref.current = el);
|
|
1308
|
-
},
|
|
1309
|
-
className: `${ATOMIX_GLASS.CONTAINER_CLASS} ${className} ${isActive ? ATOMIX_GLASS.CLASSES.ACTIVE : ""} ${overLight ? ATOMIX_GLASS.CLASSES.OVER_LIGHT : ""}`,
|
|
1356
|
+
ref: containerRef,
|
|
1357
|
+
className: mergeClassNames(ATOMIX_GLASS.CONTAINER_CLASS, className, isActive && ATOMIX_GLASS.CLASSES.ACTIVE, overLight && ATOMIX_GLASS.CLASSES.OVER_LIGHT),
|
|
1310
1358
|
style: {
|
|
1311
1359
|
...style,
|
|
1312
1360
|
...containerVars
|
|
@@ -1324,8 +1372,8 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
1324
1372
|
blurAmount: blurAmount,
|
|
1325
1373
|
mode: mode,
|
|
1326
1374
|
id: filterId,
|
|
1327
|
-
displacementScale:
|
|
1328
|
-
aberrationIntensity:
|
|
1375
|
+
displacementScale: toSafeNumber(displacementScale),
|
|
1376
|
+
aberrationIntensity: toSafeNumber(aberrationIntensity),
|
|
1329
1377
|
shaderMapUrl: shaderMapUrl
|
|
1330
1378
|
}), jsx("div", {
|
|
1331
1379
|
className: ATOMIX_GLASS.FILTER_OVERLAY_CLASS,
|
|
@@ -1347,8 +1395,12 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
1347
1395
|
});
|
|
1348
1396
|
}));
|
|
1349
1397
|
|
|
1350
|
-
|
|
1351
|
-
|
|
1398
|
+
/**
|
|
1399
|
+
* Internal glass surface that owns backdrop-filter, SVG distortion, and content.
|
|
1400
|
+
*
|
|
1401
|
+
* Layout and stacking styles are applied via the `style` prop from the parent.
|
|
1402
|
+
* The root wrapper supplies CSS custom properties only.
|
|
1403
|
+
*/ AtomixGlassContainer.displayName = "AtomixGlassContainer";
|
|
1352
1404
|
|
|
1353
1405
|
// Singleton instance
|
|
1354
1406
|
const globalMouseTracker = new
|
|
@@ -1463,28 +1515,32 @@ class {
|
|
|
1463
1515
|
*/ getSubscriberCount() {
|
|
1464
1516
|
return this.listeners.size;
|
|
1465
1517
|
}
|
|
1466
|
-
}, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
|
|
1518
|
+
}, {BORDER: BORDER, CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, BORDER_GRADIENT = BORDER.GRADIENT, WHITE = CONSTANTS$2.PALETTE.WHITE, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
|
|
1467
1519
|
if (!wrapperElement && !containerElement) return;
|
|
1468
1520
|
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,
|
|
1521
|
+
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, isFixedOrSticky: isFixedOrSticky = !1, borderAnimated: borderAnimated = !0, borderOpacityMultiplier: borderOpacityMultiplier = 1} = params, mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1, overLightConfig = {
|
|
1470
1522
|
opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
|
|
1471
1523
|
contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
|
|
1472
1524
|
brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
|
|
1473
1525
|
shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
|
|
1474
1526
|
borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence)),
|
|
1475
1527
|
saturationBoost: baseOverLightConfig.saturationBoost
|
|
1476
|
-
}, scaleX = directionalScale.x * scaleBase, scaleY = directionalScale.y * scaleBase, transformStyle = effectiveWithoutEffects ? `scale(${scaleBase})` : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) scaleX(${scaleX}) scaleY(${scaleY})`,
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
x
|
|
1482
|
-
|
|
1483
|
-
}
|
|
1528
|
+
}, scaleX = directionalScale.x * scaleBase, scaleY = directionalScale.y * scaleBase, transformStyle = effectiveWithoutEffects ? `scale(${scaleBase})` : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) scaleX(${scaleX}) scaleY(${scaleY})`, tensionFactor =
|
|
1529
|
+
/**
|
|
1530
|
+
* Computes tension factor from elastic translation magnitude (0–1).
|
|
1531
|
+
*/
|
|
1532
|
+
function(elasticTranslation) {
|
|
1533
|
+
const magnitude = Math.hypot(elasticTranslation.x, elasticTranslation.y);
|
|
1534
|
+
return smoothstep(magnitude / 80);
|
|
1535
|
+
}
|
|
1536
|
+
/**
|
|
1537
|
+
* Updates the styles of the AtomixGlass wrapper and container elements imperatively
|
|
1538
|
+
* to avoid React re-renders on mouse movement.
|
|
1539
|
+
*/ (elasticTranslation), lightingContrast = Math.min(1.8, overLightConfig.contrast + .2 * tensionFactor), lightingBrightness = Math.min(1.2, overLightConfig.brightness + .1 * tensionFactor);
|
|
1484
1540
|
// Calculate mouse influence
|
|
1485
1541
|
// Update Wrapper Styles (glassVars)
|
|
1486
1542
|
if (wrapperElement) {
|
|
1487
|
-
const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT,
|
|
1543
|
+
const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT, whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE, blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK, hoverPositions = {
|
|
1488
1544
|
hover1: {
|
|
1489
1545
|
x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1,
|
|
1490
1546
|
y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1
|
|
@@ -1501,28 +1557,55 @@ class {
|
|
|
1501
1557
|
x: GRADIENT.CENTER_POSITION + mx * GRADIENT.BASE_LAYER_MULTIPLIER,
|
|
1502
1558
|
y: GRADIENT.CENTER_POSITION + my * GRADIENT.BASE_LAYER_MULTIPLIER
|
|
1503
1559
|
}, opacityValues = {
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1560
|
+
// hover-1: ambient highlight glow — present on hover and during press
|
|
1561
|
+
hover1: isHovered || isActive ? 1 : 0,
|
|
1562
|
+
// hover-2: press depth shadow — only fires on active (mousedown)
|
|
1563
|
+
hover2: isActive ? 1 : 0,
|
|
1564
|
+
// hover-3: global soft-light surface shift — half-strength on hover, full on press
|
|
1565
|
+
hover3: isActive ? 1 : isHovered ? .55 : 0,
|
|
1566
|
+
// Dark chrome: faint smoky tint; over-light keeps stronger fill
|
|
1567
|
+
base: isOverLight ? overLightConfig.opacity : .14,
|
|
1568
|
+
over: isOverLight ? 1.1 * overLightConfig.opacity : .1
|
|
1509
1569
|
}, style = wrapperElement.style;
|
|
1510
1570
|
style.setProperty("--atomix-glass-transform", transformStyle || "none");
|
|
1511
1571
|
// Parallax for content (liquid refraction feel)
|
|
1512
1572
|
const parallaxFactor = .38 + .12 * tensionFactor;
|
|
1513
1573
|
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())
|
|
1574
|
+
style.setProperty("--atomix-glass-contrast", lightingContrast.toString()), style.setProperty("--atomix-glass-brightness", lightingBrightness.toString());
|
|
1515
1575
|
// ── Chromatic Rim Lighting ──────────────────────────────────────
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1576
|
+
const borderVars = ATOMIX_GLASS.BORDER.GRADIENT_CSS_VARS;
|
|
1577
|
+
if (borderAnimated && !effectiveWithoutEffects) {
|
|
1578
|
+
const borderCssVars =
|
|
1579
|
+
/**
|
|
1580
|
+
* Builds animated chromatic rim CSS variables for border layers 1 and 2.
|
|
1581
|
+
* When empty, SCSS static conic/linear fallbacks apply.
|
|
1582
|
+
*/
|
|
1583
|
+
function(params) {
|
|
1584
|
+
const {mouseOffset: mouseOffset, mouseVelocity: mouseVelocity, elasticVelocity: elasticVelocity, borderOpacity: borderOpacity, opacityMultiplier: opacityMultiplier = 1, tensionFactor: tensionFactor = 0} = params, mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), velocityRotation = (mouseVelocity.x + elasticVelocity.x) * BORDER_GRADIENT.VELOCITY_ANGLE_MULTIPLIER, borderGradientAngle = BORDER_GRADIENT.BASE_ANGLE + mx * BORDER_GRADIENT.ANGLE_MULTIPLIER + velocityRotation, chromaticOffset = BORDER_GRADIENT.CHROMATIC_OFFSET, angleR = borderGradientAngle - chromaticOffset, angleB = borderGradientAngle + chromaticOffset, borderStop1 = Math.max(BORDER_GRADIENT.STOP_1.MIN, BORDER_GRADIENT.STOP_1.BASE + my * BORDER_GRADIENT.STOP_1.MULTIPLIER), borderStop2 = Math.min(BORDER_GRADIENT.STOP_2.MAX, BORDER_GRADIENT.STOP_2.BASE + my * BORDER_GRADIENT.STOP_2.MULTIPLIER), tensionGlow = 1 + .5 * tensionFactor, opacities = BORDER_GRADIENT.OPACITY, borderOpacities = [ (opacities.BASE_1 + absMx * opacities.MULTIPLIER_LOW) * tensionGlow, (opacities.BASE_2 + absMx * opacities.MULTIPLIER_HIGH) * tensionGlow, (opacities.BASE_3 + absMx * opacities.MULTIPLIER_LOW) * tensionGlow, (opacities.BASE_4 + absMx * opacities.MULTIPLIER_HIGH) * tensionGlow ], configBorderOpacity = borderOpacity * opacityMultiplier, gradient1 = `linear-gradient(${angleB}deg, rgba(${WHITE}, 0) 0%, rgba(${WHITE}, ${(borderOpacities[0] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${WHITE}, ${(borderOpacities[1] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${WHITE}, 0) 100%)`, gradient2 = `linear-gradient(${angleR}deg, rgba(${WHITE}, 0) 0%, rgba(${WHITE}, ${(borderOpacities[2] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${WHITE}, ${(borderOpacities[3] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${WHITE}, 0) 100%)`;
|
|
1585
|
+
return {
|
|
1586
|
+
[BORDER.GRADIENT_CSS_VARS.GRADIENT_1]: gradient1,
|
|
1587
|
+
[BORDER.GRADIENT_CSS_VARS.GRADIENT_2]: gradient2
|
|
1588
|
+
};
|
|
1589
|
+
}({
|
|
1590
|
+
mouseOffset: mouseOffset,
|
|
1591
|
+
mouseVelocity: mouseVelocity,
|
|
1592
|
+
elasticVelocity: elasticVelocity,
|
|
1593
|
+
borderOpacity: overLightConfig.borderOpacity,
|
|
1594
|
+
opacityMultiplier: borderOpacityMultiplier,
|
|
1595
|
+
tensionFactor: tensionFactor
|
|
1596
|
+
});
|
|
1597
|
+
style.setProperty(borderVars.GRADIENT_1, borderCssVars[borderVars.GRADIENT_1] ?? ""),
|
|
1598
|
+
style.setProperty(borderVars.GRADIENT_2, borderCssVars[borderVars.GRADIENT_2] ?? "");
|
|
1599
|
+
} else style.removeProperty(borderVars.GRADIENT_1), style.removeProperty(borderVars.GRADIENT_2);
|
|
1600
|
+
// Hover gradients — cursor-relative radial positions for realistic light tracking.
|
|
1601
|
+
// hover-1: white overlay highlight following cursor (works on both dark + light)
|
|
1602
|
+
style.setProperty("--atomix-glass-hover-1-gradient", `radial-gradient(65% 55% at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${whiteColor}, 0.24) 0%, rgba(${whiteColor}, 0.06) 45%, rgba(${whiteColor}, 0) 72%)`),
|
|
1603
|
+
// hover-2: press depth — darkens at cursor with multiply blend, isOverLight uses stronger black
|
|
1604
|
+
style.setProperty("--atomix-glass-hover-2-gradient", isOverLight ? `radial-gradient(60% 50% at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(${blackColor}, 0.22) 0%, rgba(${blackColor}, 0.06) 50%, rgba(${blackColor}, 0) 72%)` : `radial-gradient(60% 50% at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(${blackColor}, 0.18) 0%, rgba(${blackColor}, 0.04) 50%, rgba(${blackColor}, 0) 72%)`),
|
|
1605
|
+
// hover-3: full-surface soft-light tint; linear gradient angled with cursor X
|
|
1606
|
+
style.setProperty("--atomix-glass-hover-3-gradient", `linear-gradient(${150 + .3 * mx}deg, rgba(${whiteColor}, ${isOverLight ? .08 : .12}) 0%, rgba(${whiteColor}, 0.04) 55%, rgba(${whiteColor}, 0) 100%)`),
|
|
1607
|
+
style.setProperty("--atomix-glass-base-gradient", isOverLight ? `linear-gradient(${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.ANGLE}deg, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_BASE + mx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_BASE + my * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_MULTIPLIER}) ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_BASE + absMx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `linear-gradient(180deg, rgba(${blackColor}, 0.42) 0%, rgba(${blackColor}, 0.22) 55%, rgba(${blackColor}, 0.12) 100%)`),
|
|
1608
|
+
style.setProperty("--atomix-glass-overlay-gradient", isOverLight ? `radial-gradient(circle at ${basePosition.x}% ${basePosition.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_BASE + absMx * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_BASE + absMy * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `radial-gradient(120% 80% at 50% 0%, rgba(${whiteColor}, 0.14) 0%, rgba(${whiteColor}, 0) 55%)`),
|
|
1526
1609
|
// Opacities
|
|
1527
1610
|
style.setProperty("--atomix-glass-hover-1-opacity", opacityValues.hover1.toString()),
|
|
1528
1611
|
style.setProperty("--atomix-glass-hover-2-opacity", opacityValues.hover2.toString()),
|
|
@@ -1559,21 +1642,17 @@ class {
|
|
|
1559
1642
|
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})`;
|
|
1560
1643
|
// Container variables
|
|
1561
1644
|
const style = containerElement.style;
|
|
1562
|
-
style.setProperty("--atomix-glass-container-
|
|
1645
|
+
style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
|
|
1563
1646
|
style.setProperty("--atomix-glass-container-backdrop", backdropFilterString),
|
|
1564
1647
|
// Shadows
|
|
1565
|
-
style.setProperty("--atomix-glass-container-shadow", isOverLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${(.
|
|
1648
|
+
style.setProperty("--atomix-glass-container-shadow", isOverLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${(.35 + .002 * mx) * (overLightConfig.shadowIntensity || 1)})`, `inset 0 -1px 0 rgba(0, 0, 0, ${(.15 + .001 * Math.abs(my)) * (overLightConfig.shadowIntensity || 1)})`, `inset 0 0 20px rgba(0, 0, 0, ${(.06 + .001 * Math.abs(mx + my)) * (overLightConfig.shadowIntensity || 1)})`, `0 2px 12px rgba(0, 0, 0, ${(.08 + .002 * Math.abs(my)) * (overLightConfig.shadowIntensity || 1)})` ].join(", ") : ATOMIX_GLASS.CONSTANTS.CONTAINER_SHADOW.LIGHT),
|
|
1566
1649
|
style.setProperty("--atomix-glass-container-shadow-opacity", effectiveWithoutEffects ? "0" : "1"),
|
|
1567
1650
|
style.setProperty("--atomix-glass-container-bg", isOverLight ? `linear-gradient(${180 + .5 * mx}deg, rgba(255, 255, 255, 0.1) 0%, transparent 20%, transparent 80%, rgba(0, 0, 0, 0.05) 100%)` : "none"),
|
|
1568
1651
|
style.setProperty("--atomix-glass-container-text-shadow", isOverLight ? "0px 1px 2px rgba(255, 255, 255, 0.15)" : "0px 2px 12px rgba(0, 0, 0, 0.4)"),
|
|
1569
|
-
style.setProperty("--atomix-glass-container-box-shadow", isOverLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "
|
|
1652
|
+
style.setProperty("--atomix-glass-container-box-shadow", isOverLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "0 8px 32px rgba(0, 0, 0, 0.32), 0 2px 8px rgba(0, 0, 0, 0.18)");
|
|
1570
1653
|
}
|
|
1571
1654
|
};
|
|
1572
1655
|
|
|
1573
|
-
/**
|
|
1574
|
-
* Updates the styles of the AtomixGlass wrapper and container elements imperatively
|
|
1575
|
-
* to avoid React re-renders on mouse movement.
|
|
1576
|
-
*/
|
|
1577
1656
|
/**
|
|
1578
1657
|
* Animation System for AtomixGlass Component
|
|
1579
1658
|
*
|
|
@@ -1718,12 +1797,38 @@ const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new Weak
|
|
|
1718
1797
|
* Composable hook for AtomixGlass component logic
|
|
1719
1798
|
* Manages all state, calculations, and event handlers
|
|
1720
1799
|
*/
|
|
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,
|
|
1800
|
+
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, border: border, withBorder: withBorder = !0, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, onClick: onClick, debugBorderRadius: debugBorderRadius = !1, debugOverLight: debugOverLight = !1, children: children, blurAmount: blurAmount, saturation: saturation, withLiquidBlur: withLiquidBlur, isFixedOrSticky: isFixedOrSticky = !1, priority: priority = 1, withTimeAnimation:
|
|
1722
1801
|
// Default priority
|
|
1723
1802
|
// Phase 1: Animation System Props
|
|
1724
1803
|
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}) {
|
|
1725
1804
|
// State
|
|
1726
|
-
const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1),
|
|
1805
|
+
const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), resolvedBorder = useMemo((() =>
|
|
1806
|
+
/**
|
|
1807
|
+
* Resolves `border` and legacy `withBorder` into a single configuration object.
|
|
1808
|
+
*/
|
|
1809
|
+
function(border, withBorder) {
|
|
1810
|
+
const legacyDefault = withBorder ?? !0;
|
|
1811
|
+
return void 0 === border ? {
|
|
1812
|
+
enabled: legacyDefault,
|
|
1813
|
+
width: BORDER.DEFAULT_WIDTH,
|
|
1814
|
+
opacityMultiplier: 1,
|
|
1815
|
+
animated: !0
|
|
1816
|
+
} : "boolean" == typeof border ? {
|
|
1817
|
+
enabled: border,
|
|
1818
|
+
width: BORDER.DEFAULT_WIDTH,
|
|
1819
|
+
opacityMultiplier: 1,
|
|
1820
|
+
animated: !0
|
|
1821
|
+
} : {
|
|
1822
|
+
enabled: border.enabled ?? legacyDefault,
|
|
1823
|
+
width: (value = border.width, void 0 === value ? BORDER.DEFAULT_WIDTH : "number" == typeof value ? `${value}px` : value),
|
|
1824
|
+
opacityMultiplier: border.opacity ?? 1,
|
|
1825
|
+
animated: !1 !== border.animated
|
|
1826
|
+
};
|
|
1827
|
+
/**
|
|
1828
|
+
* Formats border width for CSS custom properties.
|
|
1829
|
+
*/
|
|
1830
|
+
var value;
|
|
1831
|
+
}(border, withBorder)), [ border, withBorder ]), cachedRectRef = useRef(null), internalGlobalMousePositionRef = useRef({
|
|
1727
1832
|
x: 0,
|
|
1728
1833
|
y: 0
|
|
1729
1834
|
}), internalMouseOffsetRef = useRef({
|
|
@@ -2018,21 +2123,22 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
2018
2123
|
isOverLight: isOverLight,
|
|
2019
2124
|
threshold: .7,
|
|
2020
2125
|
opacity: isOverLight ? Math.min(.6, Math.max(.2, .5 * hoverIntensity * activeIntensity)) : 0,
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
shadowIntensity: .9,
|
|
2026
|
-
borderOpacity: .
|
|
2126
|
+
// Dark UI (Apple Music): neutral contrast + slight brightness lift
|
|
2127
|
+
contrast: isOverLight ? 1.4 : 1.02,
|
|
2128
|
+
brightness: isOverLight ? .9 : 1.02,
|
|
2129
|
+
saturationBoost: isOverLight ? 1.3 : 1,
|
|
2130
|
+
shadowIntensity: isOverLight ? .9 : 1,
|
|
2131
|
+
borderOpacity: isOverLight ? ATOMIX_GLASS.BORDER.OVER_LIGHT.opacity : ATOMIX_GLASS.BORDER.DARK.opacity
|
|
2027
2132
|
};
|
|
2028
2133
|
if ("object" == typeof overLight && null !== overLight) {
|
|
2029
|
-
const objConfig = overLight, validatedThreshold = validateConfigValue(objConfig.threshold, .1, 1, baseConfig.threshold), validatedOpacity = validateConfigValue(objConfig.opacity, .1, 1, baseConfig.opacity), validatedContrast = validateConfigValue(objConfig.contrast, .5, 2.5, baseConfig.contrast), validatedBrightness = validateConfigValue(objConfig.brightness, .5, 2, baseConfig.brightness), validatedSaturationBoost = validateConfigValue(objConfig.saturationBoost, .5, 3, baseConfig.saturationBoost), finalConfig = {
|
|
2134
|
+
const objConfig = overLight, validatedThreshold = validateConfigValue(objConfig.threshold, .1, 1, baseConfig.threshold), validatedOpacity = validateConfigValue(objConfig.opacity, .1, 1, baseConfig.opacity), validatedContrast = validateConfigValue(objConfig.contrast, .5, 2.5, baseConfig.contrast), validatedBrightness = validateConfigValue(objConfig.brightness, .5, 2, baseConfig.brightness), validatedSaturationBoost = validateConfigValue(objConfig.saturationBoost, .5, 3, baseConfig.saturationBoost), validatedBorderOpacity = validateConfigValue(objConfig.borderOpacity, .1, 1, baseConfig.borderOpacity), finalConfig = {
|
|
2030
2135
|
...baseConfig,
|
|
2031
2136
|
threshold: validatedThreshold,
|
|
2032
2137
|
opacity: validatedOpacity * hoverIntensity * activeIntensity,
|
|
2033
2138
|
contrast: validatedContrast,
|
|
2034
2139
|
brightness: validatedBrightness,
|
|
2035
|
-
saturationBoost: validatedSaturationBoost
|
|
2140
|
+
saturationBoost: validatedSaturationBoost,
|
|
2141
|
+
borderOpacity: validatedBorderOpacity
|
|
2036
2142
|
};
|
|
2037
2143
|
return "undefined" == typeof process || process.env, finalConfig;
|
|
2038
2144
|
}
|
|
@@ -2130,12 +2236,13 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
2130
2236
|
withLiquidBlur: withLiquidBlur,
|
|
2131
2237
|
blurAmount: blurAmount,
|
|
2132
2238
|
saturation: saturation,
|
|
2133
|
-
|
|
2134
|
-
|
|
2239
|
+
isFixedOrSticky: isFixedOrSticky,
|
|
2240
|
+
borderAnimated: resolvedBorder.animated,
|
|
2241
|
+
borderOpacityMultiplier: resolvedBorder.opacityMultiplier
|
|
2135
2242
|
}), 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);
|
|
2136
2243
|
};
|
|
2137
2244
|
lerpRafRef.current = requestAnimationFrame(tick);
|
|
2138
|
-
}), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation,
|
|
2245
|
+
}), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, isFixedOrSticky, resolvedBorder.animated, resolvedBorder.opacityMultiplier, stopLerpLoop ]), handleGlobalMousePosition = useCallback((globalPos => {
|
|
2139
2246
|
if (externalGlobalMousePosition && externalMouseOffset) return;
|
|
2140
2247
|
if (effectiveWithoutEffects) return;
|
|
2141
2248
|
const container = mouseContainer?.current || glassRef.current;
|
|
@@ -2199,9 +2306,10 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
2199
2306
|
withLiquidBlur: withLiquidBlur,
|
|
2200
2307
|
blurAmount: blurAmount,
|
|
2201
2308
|
saturation: saturation,
|
|
2202
|
-
|
|
2309
|
+
borderAnimated: resolvedBorder.animated,
|
|
2310
|
+
borderOpacityMultiplier: resolvedBorder.opacityMultiplier
|
|
2203
2311
|
});
|
|
2204
|
-
}), [ isHovered, isActive, glassSize, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation,
|
|
2312
|
+
}), [ isHovered, isActive, glassSize, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation, resolvedBorder.animated, resolvedBorder.opacityMultiplier, onClick ]);
|
|
2205
2313
|
// Event handlers
|
|
2206
2314
|
const handleMouseEnter = useCallback((() => setIsHovered(!0)), []), handleMouseLeave = useCallback((() => setIsHovered(!1)), []), handleMouseDown = useCallback((() => setIsActive(!0)), []), handleMouseUp = useCallback((() => setIsActive(!1)), []), handleKeyDown = useCallback((e => {
|
|
2207
2315
|
!onClick || "Enter" !== e.key && " " !== e.key || (e.preventDefault(), onClick());
|
|
@@ -2221,6 +2329,7 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
2221
2329
|
mouseOffset: mouseOffset,
|
|
2222
2330
|
// This is now static (refs or props) unless prop changes
|
|
2223
2331
|
overLightConfig: overLightConfig,
|
|
2332
|
+
resolvedBorder: resolvedBorder,
|
|
2224
2333
|
transformStyle: transformStyle,
|
|
2225
2334
|
getShaderTime: getShaderTime,
|
|
2226
2335
|
applyTimeBasedDistortion: applyTimeBasedDistortion,
|
|
@@ -2281,148 +2390,6 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
2281
2390
|
*
|
|
2282
2391
|
* @returns Performance tier classification
|
|
2283
2392
|
*/
|
|
2284
|
-
/** Map an FPS value to a semantic color token string. */
|
|
2285
|
-
const getQualityColor = quality => {
|
|
2286
|
-
switch (quality) {
|
|
2287
|
-
case "high":
|
|
2288
|
-
return "var(--atomix-color-success, #4ade80)";
|
|
2289
|
-
|
|
2290
|
-
case "medium":
|
|
2291
|
-
return "var(--atomix-color-warning, #fbbf24)";
|
|
2292
|
-
|
|
2293
|
-
case "low":
|
|
2294
|
-
return "var(--atomix-color-danger, #ef4444)";
|
|
2295
|
-
|
|
2296
|
-
default:
|
|
2297
|
-
return "#9ca3af";
|
|
2298
|
-
}
|
|
2299
|
-
}, getFpsLabel = fps => fps >= 58 ? "Optimal" : fps >= 45 ? "Warning" : "Critical";
|
|
2300
|
-
|
|
2301
|
-
/** Map a quality level string to a semantic color token string. */
|
|
2302
|
-
// Inject keyframes once
|
|
2303
|
-
if ("undefined" != typeof document) {
|
|
2304
|
-
const styleId = "perf-dashboard-keyframes";
|
|
2305
|
-
if (!document.getElementById(styleId)) {
|
|
2306
|
-
const styleEl = document.createElement("style");
|
|
2307
|
-
styleEl.id = styleId, styleEl.textContent = "\n@keyframes perf-dashboard-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n}\n",
|
|
2308
|
-
document.head.appendChild(styleEl);
|
|
2309
|
-
}
|
|
2310
|
-
}
|
|
2311
|
-
|
|
2312
|
-
/**
|
|
2313
|
-
* PerformanceDashboard - Real-time performance monitoring overlay.
|
|
2314
|
-
*
|
|
2315
|
-
* Displays FPS, frame time, quality level, GPU memory, and auto-scaling status.
|
|
2316
|
-
* Rendered only when `debugPerformance={true}` on the parent `AtomixGlass`.
|
|
2317
|
-
*/ const PerformanceDashboard = memo((({metrics: metrics, isVisible: isVisible = !0, onClose: onClose}) => {
|
|
2318
|
-
if (!isVisible) return null;
|
|
2319
|
-
const fpsColor = (fps = metrics.fps) >= 58 ? "var(--atomix-color-success, #4ade80)" : fps >= 45 ? "var(--atomix-color-warning, #fbbf24)" : "var(--atomix-color-danger, #ef4444)";
|
|
2320
|
-
var fps;
|
|
2321
|
-
const isCritical = metrics.fps < 45;
|
|
2322
|
-
return jsxs("div", {
|
|
2323
|
-
className: "c-perf-dashboard u-position-fixed u-top-4 u-end-4 u-p-3 u-px-4 u-text-xs u-font-mono u-text-white u-rounded-md u-border u-border-white-alpha-10 u-shadow-lg",
|
|
2324
|
-
style: {
|
|
2325
|
-
zIndex: 9999,
|
|
2326
|
-
minWidth: "12.5rem",
|
|
2327
|
-
// 200px
|
|
2328
|
-
backgroundColor: "rgba(17, 24, 39, 0.95)",
|
|
2329
|
-
backdropFilter: "blur(8px)",
|
|
2330
|
-
transition: "opacity 0.3s ease"
|
|
2331
|
-
},
|
|
2332
|
-
children: [ jsxs("div", {
|
|
2333
|
-
className: "u-flex u-items-center u-justify-between u-mb-2 u-pb-2 u-border-b u-border-white-alpha-10",
|
|
2334
|
-
children: [ jsx("span", {
|
|
2335
|
-
className: "u-text-sm u-font-bold u-text-white",
|
|
2336
|
-
children: "Performance Monitor"
|
|
2337
|
-
}), onClose && jsx("button", {
|
|
2338
|
-
className: "u-bg-transparent u-border-none u-p-0 u-line-height-1 u-text-base u-text-gray-400 u-cursor-pointer hover:u-text-white",
|
|
2339
|
-
onClick: onClose,
|
|
2340
|
-
"aria-label": "Close performance dashboard",
|
|
2341
|
-
style: {
|
|
2342
|
-
transition: "color 0.2s ease"
|
|
2343
|
-
},
|
|
2344
|
-
children: "×"
|
|
2345
|
-
}) ]
|
|
2346
|
-
}), jsxs("div", {
|
|
2347
|
-
className: "u-flex u-items-center u-justify-between u-mb-1-5",
|
|
2348
|
-
children: [ jsx("span", {
|
|
2349
|
-
className: "u-text-gray-400 u-me-3",
|
|
2350
|
-
children: "FPS"
|
|
2351
|
-
}), jsx("span", {
|
|
2352
|
-
className: "u-font-bold",
|
|
2353
|
-
style: {
|
|
2354
|
-
color: fpsColor
|
|
2355
|
-
},
|
|
2356
|
-
children: Math.round(metrics.fps)
|
|
2357
|
-
}) ]
|
|
2358
|
-
}), jsxs("div", {
|
|
2359
|
-
className: "u-flex u-items-center u-justify-between u-mb-1-5",
|
|
2360
|
-
children: [ jsx("span", {
|
|
2361
|
-
className: "u-text-gray-400 u-me-3",
|
|
2362
|
-
children: "Frame Time"
|
|
2363
|
-
}), jsxs("span", {
|
|
2364
|
-
className: "u-font-bold",
|
|
2365
|
-
children: [ metrics.frameTime.toFixed(2), "ms" ]
|
|
2366
|
-
}) ]
|
|
2367
|
-
}), jsxs("div", {
|
|
2368
|
-
className: "u-flex u-items-center u-justify-between u-mb-1-5",
|
|
2369
|
-
children: [ jsx("span", {
|
|
2370
|
-
className: "u-text-gray-400 u-me-3",
|
|
2371
|
-
children: "Quality"
|
|
2372
|
-
}), jsx("span", {
|
|
2373
|
-
className: "u-font-bold u-text-uppercase",
|
|
2374
|
-
style: {
|
|
2375
|
-
fontSize: "0.6875rem",
|
|
2376
|
-
// 11px
|
|
2377
|
-
color: getQualityColor(metrics.qualityLevel)
|
|
2378
|
-
},
|
|
2379
|
-
children: metrics.qualityLevel
|
|
2380
|
-
}) ]
|
|
2381
|
-
}), metrics.gpuMemory && jsxs("div", {
|
|
2382
|
-
className: "u-flex u-items-center u-justify-between u-mb-1-5",
|
|
2383
|
-
children: [ jsx("span", {
|
|
2384
|
-
className: "u-text-gray-400 u-me-3",
|
|
2385
|
-
children: "GPU Memory"
|
|
2386
|
-
}), jsxs("span", {
|
|
2387
|
-
className: "u-font-bold",
|
|
2388
|
-
children: [ "~", Math.round(metrics.gpuMemory / 1024), "MB" ]
|
|
2389
|
-
}) ]
|
|
2390
|
-
}), metrics.isAutoScaling && jsx("div", {
|
|
2391
|
-
className: "u-mt-2 u-pt-2 u-border-t u-border-white-alpha-10 u-text-center",
|
|
2392
|
-
style: {
|
|
2393
|
-
fontSize: "0.625rem",
|
|
2394
|
-
// 10px
|
|
2395
|
-
color: "#6b7280"
|
|
2396
|
-
},
|
|
2397
|
-
children: "Auto-scaling active"
|
|
2398
|
-
}), jsxs("div", {
|
|
2399
|
-
className: "u-flex u-items-center u-gap-2 u-mt-2 u-pt-2 u-border-t u-border-white-alpha-10",
|
|
2400
|
-
children: [ jsx("div", {
|
|
2401
|
-
className: "u-rounded-full",
|
|
2402
|
-
style: {
|
|
2403
|
-
width: "0.5rem",
|
|
2404
|
-
height: "0.5rem",
|
|
2405
|
-
flexShrink: 0,
|
|
2406
|
-
backgroundColor: fpsColor,
|
|
2407
|
-
...isCritical && {
|
|
2408
|
-
animation: "perf-dashboard-pulse 1s infinite"
|
|
2409
|
-
}
|
|
2410
|
-
}
|
|
2411
|
-
}), jsx("span", {
|
|
2412
|
-
className: "u-text-xs",
|
|
2413
|
-
style: {
|
|
2414
|
-
fontSize: "0.625rem",
|
|
2415
|
-
// 10px
|
|
2416
|
-
color: fpsColor
|
|
2417
|
-
},
|
|
2418
|
-
children: getFpsLabel(metrics.fps)
|
|
2419
|
-
}) ]
|
|
2420
|
-
}) ]
|
|
2421
|
-
});
|
|
2422
|
-
}));
|
|
2423
|
-
|
|
2424
|
-
PerformanceDashboard.displayName = "PerformanceDashboard";
|
|
2425
|
-
|
|
2426
2393
|
/**
|
|
2427
2394
|
* Mobile optimization presets
|
|
2428
2395
|
*
|
|
@@ -2542,18 +2509,13 @@ const PERFORMANCE_PRESET = {
|
|
|
2542
2509
|
saturation: 70
|
|
2543
2510
|
}
|
|
2544
2511
|
}
|
|
2545
|
-
}, AtomixGlassInner = forwardRef((function({children: children, displacementScale: displacementScale = ATOMIX_GLASS.DEFAULTS.DISPLACEMENT_SCALE, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, aberrationIntensity: aberrationIntensity = ATOMIX_GLASS.DEFAULTS.ABERRATION_INTENSITY, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer = null, className: className = "",
|
|
2546
|
-
const glassRef = useRef(null), contentRef = useRef(null), internalWrapperRef = useRef(null), mergedRef =
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
}));
|
|
2553
|
-
};
|
|
2554
|
-
}
|
|
2555
|
-
// Internal implementation with forwardRef
|
|
2556
|
-
(ref, internalWrapperRef)), [ ref ]), {zIndex: customZIndex, ...restStyle} = style, isFixedOrSticky = propsIsFixedOrSticky || "fixed" === restStyle.position || "sticky" === restStyle.position, {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveBorderRadius: effectiveBorderRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveWithoutEffects: effectiveWithoutEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle, getShaderTime: getShaderTime, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown} = useAtomixGlass({
|
|
2512
|
+
}, AtomixGlassInner = forwardRef((function({children: children, displacementScale: displacementScale = ATOMIX_GLASS.DEFAULTS.DISPLACEMENT_SCALE, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, aberrationIntensity: aberrationIntensity = ATOMIX_GLASS.DEFAULTS.ABERRATION_INTENSITY, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer = null, className: className = "", overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, style: style = {}, mode: mode = ATOMIX_GLASS.DEFAULTS.MODE, onClick: onClick, shaderVariant: shaderVariant = "liquidGlass", "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, role: role, tabIndex: tabIndex, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, withLiquidBlur: withLiquidBlur = !1, border: border, withBorder: withBorder = !0, debugBorderRadius: debugBorderRadius = !1, withOverLightLayers: withOverLightLayers = ATOMIX_GLASS.DEFAULTS.ENABLE_OVER_LIGHT_LAYERS, debugPerformance: debugPerformance = !1, debugOverLight: debugOverLight = !1, height: height, width: width, withTimeAnimation: withTimeAnimation = !1, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion = !1, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5, distortionQuality: distortionQuality = "medium", devicePreset: devicePreset = "balanced", disableResponsiveBreakpoints: disableResponsiveBreakpoints = !1, isFixedOrSticky: propsIsFixedOrSticky, ...rest}, ref) {
|
|
2513
|
+
const glassRef = useRef(null), contentRef = useRef(null), internalWrapperRef = useRef(null), mergedRef = useForkRef(ref, internalWrapperRef), {zIndex: customZIndex, ...restStyle} = style, isFixedOrSticky = (explicit = propsIsFixedOrSticky,
|
|
2514
|
+
position = restStyle.position, Boolean(explicit || "fixed" === position || "sticky" === position));
|
|
2515
|
+
var explicit, position;
|
|
2516
|
+
/**
|
|
2517
|
+
* Extracts layout-related properties from a React `CSSProperties` object.
|
|
2518
|
+
*/ const {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveBorderRadius: effectiveBorderRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveWithoutEffects: effectiveWithoutEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle, getShaderTime: getShaderTime, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown, resolvedBorder: resolvedBorder} = useAtomixGlass({
|
|
2557
2519
|
glassRef: glassRef,
|
|
2558
2520
|
contentRef: contentRef,
|
|
2559
2521
|
wrapperRef: internalWrapperRef,
|
|
@@ -2573,10 +2535,11 @@ const PERFORMANCE_PRESET = {
|
|
|
2573
2535
|
blurAmount: blurAmount,
|
|
2574
2536
|
saturation: saturation,
|
|
2575
2537
|
withLiquidBlur: withLiquidBlur,
|
|
2576
|
-
|
|
2538
|
+
border: border,
|
|
2539
|
+
withBorder: withBorder,
|
|
2540
|
+
debugBorderRadius: debugBorderRadius,
|
|
2577
2541
|
style: style,
|
|
2578
2542
|
isFixedOrSticky: isFixedOrSticky,
|
|
2579
|
-
// Phase 1: Animation System props
|
|
2580
2543
|
withTimeAnimation: withTimeAnimation,
|
|
2581
2544
|
animationSpeed: animationSpeed,
|
|
2582
2545
|
withMultiLayerDistortion: withMultiLayerDistortion,
|
|
@@ -2585,8 +2548,7 @@ const PERFORMANCE_PRESET = {
|
|
|
2585
2548
|
distortionGain: distortionGain,
|
|
2586
2549
|
distortionQuality: distortionQuality
|
|
2587
2550
|
});
|
|
2588
|
-
|
|
2589
|
-
!
|
|
2551
|
+
(
|
|
2590
2552
|
/**
|
|
2591
2553
|
* Responsive Glass Parameters Hook
|
|
2592
2554
|
*
|
|
@@ -2744,7 +2706,7 @@ const PERFORMANCE_PRESET = {
|
|
|
2744
2706
|
}
|
|
2745
2707
|
/**
|
|
2746
2708
|
* Get GPU memory info if available (Chrome DevTools only)
|
|
2747
|
-
*/
|
|
2709
|
+
*/)({
|
|
2748
2710
|
baseParams: {
|
|
2749
2711
|
...useMemo((() =>
|
|
2750
2712
|
/**
|
|
@@ -2778,9 +2740,7 @@ const PERFORMANCE_PRESET = {
|
|
|
2778
2740
|
breakpoints: MOBILE_OPTIMIZED_BREAKPOINTS,
|
|
2779
2741
|
enabled: !disableResponsiveBreakpoints && "undefined" != typeof window,
|
|
2780
2742
|
debug: !1
|
|
2781
|
-
})
|
|
2782
|
-
// Performance monitoring - tracks FPS, frame time, memory usage
|
|
2783
|
-
const {metrics: performanceMetrics, toggleMonitoring: toggleMonitoring} =
|
|
2743
|
+
}),
|
|
2784
2744
|
/**
|
|
2785
2745
|
* Performance Monitor Hook
|
|
2786
2746
|
*
|
|
@@ -2815,7 +2775,13 @@ const PERFORMANCE_PRESET = {
|
|
|
2815
2775
|
timestamp: 0,
|
|
2816
2776
|
isAutoScaling: !0,
|
|
2817
2777
|
lowFpsCount: 0
|
|
2818
|
-
}), [manualOverride, setManualOverride] = useState(!1), [isEnabled, setIsEnabled] = useState(enabled)
|
|
2778
|
+
}), [manualOverride, setManualOverride] = useState(!1), [isEnabled, setIsEnabled] = useState(enabled);
|
|
2779
|
+
// Sync external `enabled` prop changes into internal state
|
|
2780
|
+
useEffect((() => {
|
|
2781
|
+
setIsEnabled(enabled ?? !0);
|
|
2782
|
+
}), [ enabled ]);
|
|
2783
|
+
// Refs for frame tracking
|
|
2784
|
+
const frameCountRef = useRef(0), lastFpsUpdateRef = useRef(0), lastFrameTimeRef = useRef(0), animationFrameRef = useRef(null), lowFpsCountRef = useRef(0), highFpsCountRef = useRef(0), qualityLevelRef = useRef("medium"), updateMetrics = useCallback((newMetrics => {
|
|
2819
2785
|
setMetrics((prev => ({
|
|
2820
2786
|
...prev,
|
|
2821
2787
|
...newMetrics,
|
|
@@ -2935,191 +2901,214 @@ const PERFORMANCE_PRESET = {
|
|
|
2935
2901
|
/**
|
|
2936
2902
|
* Reset to auto-scaling mode
|
|
2937
2903
|
*/ var fps, currentQuality;
|
|
2938
|
-
|
|
2939
|
-
metrics: metrics,
|
|
2940
|
-
recommendedQuality: (fps = metrics.fps, currentQuality = metrics.qualityLevel, fps >= 58 ? "high" : fps >= 45 ? "high" === currentQuality ? "high" : "medium" : "low"),
|
|
2941
|
-
isUnderperforming: metrics.fps < minFps,
|
|
2942
|
-
setQualityLevel: setQualityLevel,
|
|
2943
|
-
resetAutoScaling: resetAutoScaling,
|
|
2944
|
-
toggleMonitoring: toggleMonitoring
|
|
2945
|
-
};
|
|
2904
|
+
fps = metrics.fps, currentQuality = metrics.qualityLevel, metrics.fps;
|
|
2946
2905
|
}({
|
|
2947
2906
|
enabled: debugPerformance,
|
|
2948
|
-
// Enable when debugPerformance is true
|
|
2949
2907
|
debug: !1,
|
|
2950
2908
|
showOverlay: !1
|
|
2951
2909
|
});
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
}), [ debugPerformance ]);
|
|
2957
|
-
// Re-run when debugPerformance changes
|
|
2958
|
-
const isOverLight = useMemo((() => overLightConfig.isOverLight), [ overLightConfig.isOverLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, rootLayoutStyle = useMemo((() => {
|
|
2959
|
-
if (!isFixedOrSticky) return {};
|
|
2960
|
-
const {position: p, top: t, left: l, right: r, bottom: b} = restStyle;
|
|
2961
|
-
return {
|
|
2962
|
-
...p && {
|
|
2963
|
-
position: p
|
|
2964
|
-
},
|
|
2965
|
-
...void 0 !== t && {
|
|
2966
|
-
top: t
|
|
2967
|
-
},
|
|
2968
|
-
...void 0 !== l && {
|
|
2969
|
-
left: l
|
|
2970
|
-
},
|
|
2971
|
-
...void 0 !== r && {
|
|
2972
|
-
right: r
|
|
2973
|
-
},
|
|
2974
|
-
...void 0 !== b && {
|
|
2975
|
-
bottom: b
|
|
2976
|
-
}
|
|
2977
|
-
};
|
|
2978
|
-
}), [ isFixedOrSticky, restStyle ]);
|
|
2979
|
-
// Calculate base style with transforms
|
|
2980
|
-
// When layout is hoisted to the root, strip those props from the container
|
|
2981
|
-
useMemo((() => {
|
|
2982
|
-
if (isFixedOrSticky) {
|
|
2983
|
-
const {position: _p, top: _t, left: _l, right: _r, bottom: _b, ...visualStyle} = restStyle;
|
|
2984
|
-
return {
|
|
2985
|
-
...visualStyle
|
|
2986
|
-
};
|
|
2910
|
+
const isOverLight = useMemo((() => overLightConfig.isOverLight), [ overLightConfig.isOverLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, containerStyle = useMemo((() => ({
|
|
2911
|
+
...restStyle,
|
|
2912
|
+
...void 0 !== customZIndex && {
|
|
2913
|
+
zIndex: customZIndex
|
|
2987
2914
|
}
|
|
2915
|
+
})), [ restStyle, customZIndex ]), componentClassName = mergeClassNames(ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`, effectiveWithoutEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`, className), positionStyles = useMemo((() =>
|
|
2916
|
+
/**
|
|
2917
|
+
* Returns the internal positioning context for effect layers relative to the root.
|
|
2918
|
+
*/
|
|
2919
|
+
function(isFixedOrSticky, restStyle) {
|
|
2988
2920
|
return {
|
|
2989
|
-
|
|
2921
|
+
position: isFixedOrSticky ? "absolute" : restStyle.position || "absolute",
|
|
2922
|
+
top: 0,
|
|
2923
|
+
left: 0,
|
|
2924
|
+
right: "auto",
|
|
2925
|
+
bottom: "auto"
|
|
2990
2926
|
};
|
|
2991
|
-
}
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
})), [ isFixedOrSticky, restStyle.position, restStyle.top, restStyle.left, restStyle.right, restStyle.bottom ]), adjustedSize = useMemo((() => {
|
|
3000
|
-
// Keep a reference to positionStyles to avoid unused-variable lint,
|
|
3001
|
-
// but sizing is driven by explicit width/height or measured size.
|
|
3002
|
-
positionStyles.position;
|
|
3003
|
-
const resolveLength = (value, measured) => void 0 !== value && isFixedOrSticky ? "number" == typeof value ? `${value}px` : value : measured > 0 && isFixedOrSticky ? `${measured}px` : "100%", effectiveWidth = width ?? restStyle.width, effectiveHeight = height ?? restStyle.height;
|
|
2927
|
+
}
|
|
2928
|
+
/**
|
|
2929
|
+
* Computes `--atomix-glass-width` and `--atomix-glass-height` values.
|
|
2930
|
+
*
|
|
2931
|
+
* Fixed/sticky elements prefer explicit dimensions or measured size; in-flow
|
|
2932
|
+
* elements default to `100%`.
|
|
2933
|
+
*/ (isFixedOrSticky, restStyle)), [ isFixedOrSticky, restStyle ]), adjustedSize = useMemo((() => function(options) {
|
|
2934
|
+
const {width: width, height: height, restStyle: restStyle, glassSize: glassSize, isFixedOrSticky: isFixedOrSticky} = options, resolveLength = (value, measured) => void 0 !== value && isFixedOrSticky ? "number" == typeof value ? `${value}px` : value : measured > 0 && isFixedOrSticky ? `${measured}px` : "100%", effectiveWidth = width ?? restStyle.width, effectiveHeight = height ?? restStyle.height;
|
|
3004
2935
|
return {
|
|
3005
2936
|
width: resolveLength(effectiveWidth, glassSize.width),
|
|
3006
2937
|
height: resolveLength(effectiveHeight, glassSize.height)
|
|
3007
2938
|
};
|
|
3008
|
-
}
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
2939
|
+
}
|
|
2940
|
+
/**
|
|
2941
|
+
* Builds the CSS custom properties applied to the root `.c-atomix-glass` element.
|
|
2942
|
+
*
|
|
2943
|
+
* These variables drive layer geometry, transforms, and stacking offsets. They
|
|
2944
|
+
* must not include layout properties that would interfere with backdrop-filter.
|
|
2945
|
+
*/ ({
|
|
2946
|
+
width: width,
|
|
2947
|
+
height: height,
|
|
2948
|
+
restStyle: restStyle,
|
|
2949
|
+
glassSize: glassSize,
|
|
2950
|
+
isFixedOrSticky: isFixedOrSticky
|
|
2951
|
+
})), [ width, height, restStyle, glassSize, isFixedOrSticky ]), glassVars = useMemo((() => function(input) {
|
|
2952
|
+
const {effectiveBorderRadius: effectiveBorderRadius, transformStyle: transformStyle, adjustedSize: adjustedSize, isOverLight: isOverLight, customZIndex: customZIndex, isFixedOrSticky: isFixedOrSticky, positionStyles: positionStyles, restStyle: restStyle, borderWidth: borderWidth = ATOMIX_GLASS.BORDER.DEFAULT_WIDTH} = input, layerPosition =
|
|
2953
|
+
/**
|
|
2954
|
+
* Resolves the `--atomix-glass-position` value for decorative layers.
|
|
2955
|
+
*
|
|
2956
|
+
* Fixed/sticky layers use the same positioning mode as the container; in-flow
|
|
2957
|
+
* layers default to the internal absolute positioning context.
|
|
2958
|
+
*/
|
|
2959
|
+
function(isFixedOrSticky, positionStyles, restStyle) {
|
|
2960
|
+
return isFixedOrSticky ? `${function(style) {
|
|
2961
|
+
const {position: position, top: top, left: left, right: right, bottom: bottom, inset: inset} = style;
|
|
2962
|
+
return {
|
|
2963
|
+
...null != position && {
|
|
2964
|
+
position: position
|
|
2965
|
+
},
|
|
2966
|
+
...void 0 !== top && {
|
|
2967
|
+
top: top
|
|
2968
|
+
},
|
|
2969
|
+
...void 0 !== left && {
|
|
2970
|
+
left: left
|
|
2971
|
+
},
|
|
2972
|
+
...void 0 !== right && {
|
|
2973
|
+
right: right
|
|
2974
|
+
},
|
|
2975
|
+
...void 0 !== bottom && {
|
|
2976
|
+
bottom: bottom
|
|
2977
|
+
},
|
|
2978
|
+
...void 0 !== inset && {
|
|
2979
|
+
inset: inset
|
|
2980
|
+
}
|
|
2981
|
+
};
|
|
2982
|
+
}
|
|
2983
|
+
/**
|
|
2984
|
+
* Resolves inset custom properties for decorative layers (hover, borders, backgrounds).
|
|
2985
|
+
*
|
|
2986
|
+
* For fixed and sticky modes, insets mirror the container so sibling layers remain
|
|
2987
|
+
* aligned. In-flow modes, insets follow the consumer `style` when a non-default
|
|
2988
|
+
* `position` is provided.
|
|
2989
|
+
*/ (restStyle).position ?? restStyle.position ?? "fixed"}` : `${positionStyles.position}`;
|
|
2990
|
+
}(isFixedOrSticky, positionStyles, restStyle), layerInsets = function(isFixedOrSticky, restStyle) {
|
|
2991
|
+
if (isFixedOrSticky) return {
|
|
2992
|
+
top: formatGlassInsetValue(restStyle.top, 0),
|
|
2993
|
+
left: formatGlassInsetValue(restStyle.left, 0),
|
|
2994
|
+
right: formatGlassInsetValue(restStyle.right, "auto"),
|
|
2995
|
+
bottom: formatGlassInsetValue(restStyle.bottom, "auto")
|
|
2996
|
+
};
|
|
2997
|
+
const position = restStyle.position;
|
|
2998
|
+
return null != position && "static" !== position && "relative" !== position ? {
|
|
2999
|
+
top: formatGlassInsetValue(restStyle.top, 0),
|
|
3000
|
+
left: formatGlassInsetValue(restStyle.left, 0),
|
|
3001
|
+
right: formatGlassInsetValue(restStyle.right, "auto"),
|
|
3002
|
+
bottom: formatGlassInsetValue(restStyle.bottom, "auto")
|
|
3003
|
+
} : {
|
|
3004
|
+
top: "0px",
|
|
3005
|
+
left: "0px",
|
|
3006
|
+
right: "auto",
|
|
3007
|
+
bottom: "auto"
|
|
3008
|
+
};
|
|
3009
|
+
}(isFixedOrSticky, restStyle);
|
|
3046
3010
|
return {
|
|
3047
3011
|
...void 0 !== customZIndex && {
|
|
3048
3012
|
"--atomix-glass-base-z-index": customZIndex
|
|
3049
3013
|
},
|
|
3050
3014
|
"--atomix-glass-radius": `${effectiveBorderRadius}px`,
|
|
3051
3015
|
"--atomix-glass-transform": transformStyle || "none",
|
|
3052
|
-
"--atomix-glass-container-position":
|
|
3053
|
-
"--atomix-glass-position":
|
|
3054
|
-
"--atomix-glass-top":
|
|
3055
|
-
"--atomix-glass-left":
|
|
3056
|
-
"--atomix-glass-right":
|
|
3057
|
-
"--atomix-glass-bottom":
|
|
3016
|
+
"--atomix-glass-container-position": layerPosition,
|
|
3017
|
+
"--atomix-glass-position": layerPosition,
|
|
3018
|
+
"--atomix-glass-top": layerInsets.top,
|
|
3019
|
+
"--atomix-glass-left": layerInsets.left,
|
|
3020
|
+
"--atomix-glass-right": layerInsets.right,
|
|
3021
|
+
"--atomix-glass-bottom": layerInsets.bottom,
|
|
3058
3022
|
"--atomix-glass-width": adjustedSize.width,
|
|
3059
3023
|
"--atomix-glass-height": adjustedSize.height,
|
|
3060
|
-
|
|
3061
|
-
"--atomix-glass-
|
|
3062
|
-
"--atomix-glass-
|
|
3063
|
-
|
|
3064
|
-
"--atomix-glass-
|
|
3065
|
-
"--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}%)`,
|
|
3066
|
-
"--atomix-glass-hover-2-opacity": opacityValues.hover2,
|
|
3067
|
-
"--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}%)`,
|
|
3068
|
-
"--atomix-glass-hover-3-opacity": opacityValues.hover3,
|
|
3069
|
-
"--atomix-glass-hover-3-gradient": isOverLight ? `radial-gradient(circle at ${hoverPositions.hover3.x}% ${hoverPositions.hover3.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_END}%)` : `radial-gradient(circle at ${hoverPositions.hover3.x}% ${hoverPositions.hover3.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_STOP}%)`,
|
|
3070
|
-
"--atomix-glass-base-opacity": opacityValues.base,
|
|
3071
|
-
"--atomix-glass-base-gradient": isOverLight ? `linear-gradient(${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.ANGLE}deg, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_BASE + mx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_BASE + my * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_MULTIPLIER}) ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_BASE + absMx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.WHITE_OPACITY})`,
|
|
3072
|
-
"--atomix-glass-overlay-opacity": opacityValues.over,
|
|
3073
|
-
"--atomix-glass-overlay-gradient": isOverLight ? `radial-gradient(circle at ${basePosition.x}% ${basePosition.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_BASE + absMx * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_BASE + absMy * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.WHITE_OPACITY})`,
|
|
3074
|
-
"--atomix-glass-overlay-highlight-opacity": opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER,
|
|
3075
|
-
"--atomix-glass-overlay-highlight-bg": `radial-gradient(circle at ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_X}% ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_Y}%, rgba(255, 255, 255, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.WHITE_OPACITY}) 0%, transparent ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.STOP}%)`
|
|
3024
|
+
// Aliases maintained for backward compatibility and consumer overrides.
|
|
3025
|
+
"--atomix-glass-container-width": adjustedSize.width,
|
|
3026
|
+
"--atomix-glass-container-height": adjustedSize.height,
|
|
3027
|
+
[ATOMIX_GLASS.BORDER.WIDTH_CSS_VAR]: borderWidth,
|
|
3028
|
+
"--atomix-glass-blend-mode": isOverLight ? "multiply" : "overlay"
|
|
3076
3029
|
};
|
|
3077
|
-
}
|
|
3078
|
-
|
|
3030
|
+
}
|
|
3031
|
+
/**
|
|
3032
|
+
* Applies mode-specific multipliers and accessibility overrides to container effects.
|
|
3033
|
+
*/ ({
|
|
3034
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
3035
|
+
transformStyle: transformStyle,
|
|
3036
|
+
adjustedSize: adjustedSize,
|
|
3037
|
+
isOverLight: isOverLight,
|
|
3038
|
+
customZIndex: customZIndex,
|
|
3039
|
+
isFixedOrSticky: isFixedOrSticky,
|
|
3040
|
+
positionStyles: positionStyles,
|
|
3041
|
+
restStyle: restStyle,
|
|
3042
|
+
borderWidth: resolvedBorder.width
|
|
3043
|
+
})), [ effectiveBorderRadius, transformStyle, adjustedSize, isOverLight, customZIndex, isFixedOrSticky, positionStyles, restStyle, resolvedBorder.width ]), containerEffects = useMemo((() => function(options) {
|
|
3044
|
+
const {MULTIPLIERS: MULTIPLIERS, SATURATION: SATURATION} = ATOMIX_GLASS.CONSTANTS, zeroMouse = {
|
|
3045
|
+
x: 0,
|
|
3046
|
+
y: 0
|
|
3047
|
+
}, resolveSaturation = () => options.effectiveHighContrast ? SATURATION.HIGH_CONTRAST : options.isOverLight ? options.saturation * options.saturationBoost : options.saturation;
|
|
3048
|
+
if (options.effectiveWithoutEffects) return {
|
|
3049
|
+
displacementScale: 0,
|
|
3050
|
+
blurAmount: 0,
|
|
3051
|
+
saturation: resolveSaturation(),
|
|
3052
|
+
aberrationIntensity: 0,
|
|
3053
|
+
mouseOffset: zeroMouse,
|
|
3054
|
+
globalMousePosition: zeroMouse
|
|
3055
|
+
};
|
|
3056
|
+
let resolvedDisplacement = options.displacementScale;
|
|
3057
|
+
"shader" === options.mode ? resolvedDisplacement *= MULTIPLIERS.SHADER_DISPLACEMENT : options.isOverLight && (resolvedDisplacement *= MULTIPLIERS.OVER_LIGHT_DISPLACEMENT);
|
|
3058
|
+
let resolvedAberration = options.aberrationIntensity;
|
|
3059
|
+
return "shader" === options.mode && (resolvedAberration *= MULTIPLIERS.SHADER_ABERRATION),
|
|
3060
|
+
{
|
|
3061
|
+
displacementScale: resolvedDisplacement,
|
|
3062
|
+
blurAmount: options.blurAmount,
|
|
3063
|
+
saturation: resolveSaturation(),
|
|
3064
|
+
aberrationIntensity: resolvedAberration,
|
|
3065
|
+
mouseOffset: options.mouseOffset,
|
|
3066
|
+
globalMousePosition: options.globalMousePosition
|
|
3067
|
+
};
|
|
3068
|
+
}({
|
|
3069
|
+
displacementScale: displacementScale,
|
|
3070
|
+
blurAmount: blurAmount,
|
|
3071
|
+
saturation: saturation,
|
|
3072
|
+
aberrationIntensity: aberrationIntensity,
|
|
3073
|
+
mode: mode,
|
|
3074
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
3075
|
+
effectiveHighContrast: effectiveHighContrast,
|
|
3076
|
+
isOverLight: isOverLight,
|
|
3077
|
+
saturationBoost: overLightConfig.saturationBoost,
|
|
3078
|
+
mouseOffset: mouseOffset,
|
|
3079
|
+
globalMousePosition: globalMousePosition
|
|
3080
|
+
})), [ displacementScale, blurAmount, saturation, aberrationIntensity, mode, effectiveWithoutEffects, effectiveHighContrast, isOverLight, overLightConfig.saturationBoost, mouseOffset, globalMousePosition ]), renderBackgroundLayer = layerType => jsx("div", {
|
|
3081
|
+
"aria-hidden": "true",
|
|
3082
|
+
className: mergeClassNames(ATOMIX_GLASS.BACKGROUND_LAYER_CLASS, "dark" === layerType ? ATOMIX_GLASS.BACKGROUND_LAYER_DARK_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_BLACK_CLASS, isOverLight ? ATOMIX_GLASS.BACKGROUND_LAYER_OVER_LIGHT_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_HIDDEN_CLASS)
|
|
3079
3083
|
});
|
|
3080
|
-
|
|
3081
|
-
// When root is fixed/sticky, internal layers use absolute (relative to root)
|
|
3082
|
-
return jsxs("div", {
|
|
3084
|
+
return jsxs("div", {
|
|
3083
3085
|
...rest,
|
|
3084
3086
|
ref: mergedRef,
|
|
3085
3087
|
className: componentClassName,
|
|
3086
|
-
style:
|
|
3087
|
-
...glassVars
|
|
3088
|
-
},
|
|
3088
|
+
style: glassVars,
|
|
3089
3089
|
role: role || (onClick ? "button" : void 0),
|
|
3090
3090
|
tabIndex: onClick ? tabIndex ?? 0 : tabIndex,
|
|
3091
3091
|
"aria-label": ariaLabel,
|
|
3092
3092
|
"aria-describedby": ariaDescribedBy,
|
|
3093
3093
|
"aria-disabled": !(!onClick || !effectiveWithoutEffects) || !onClick && void 0,
|
|
3094
|
-
"aria-pressed": onClick ? isActive : void 0,
|
|
3095
3094
|
onKeyDown: onClick ? handleKeyDown : void 0,
|
|
3096
3095
|
children: [ jsx(AtomixGlassContainer, {
|
|
3097
3096
|
ref: glassRef,
|
|
3098
3097
|
contentRef: contentRef,
|
|
3099
3098
|
className: className,
|
|
3100
|
-
style:
|
|
3101
|
-
...restStyle
|
|
3102
|
-
},
|
|
3099
|
+
style: containerStyle,
|
|
3103
3100
|
borderRadius: effectiveBorderRadius,
|
|
3104
|
-
displacementScale:
|
|
3105
|
-
blurAmount:
|
|
3106
|
-
saturation:
|
|
3107
|
-
aberrationIntensity:
|
|
3101
|
+
displacementScale: containerEffects.displacementScale,
|
|
3102
|
+
blurAmount: containerEffects.blurAmount,
|
|
3103
|
+
saturation: containerEffects.saturation,
|
|
3104
|
+
aberrationIntensity: containerEffects.aberrationIntensity,
|
|
3108
3105
|
glassSize: glassSize,
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
x: 0,
|
|
3112
|
-
y: 0
|
|
3113
|
-
} : mouseOffset,
|
|
3114
|
-
globalMousePosition: effectiveWithoutEffects ? {
|
|
3115
|
-
x: 0,
|
|
3116
|
-
y: 0
|
|
3117
|
-
} : globalMousePosition,
|
|
3106
|
+
mouseOffset: containerEffects.mouseOffset,
|
|
3107
|
+
globalMousePosition: containerEffects.globalMousePosition,
|
|
3118
3108
|
onMouseEnter: handleMouseEnter,
|
|
3119
3109
|
onMouseLeave: handleMouseLeave,
|
|
3120
3110
|
onMouseDown: handleMouseDown,
|
|
3121
3111
|
onMouseUp: handleMouseUp,
|
|
3122
|
-
isHovered: isHovered,
|
|
3123
3112
|
isActive: isActive,
|
|
3124
3113
|
overLight: isOverLight,
|
|
3125
3114
|
overLightConfig: {
|
|
@@ -3135,7 +3124,6 @@ const PERFORMANCE_PRESET = {
|
|
|
3135
3124
|
shaderVariant: shaderVariant,
|
|
3136
3125
|
withLiquidBlur: withLiquidBlur,
|
|
3137
3126
|
isFixedOrSticky: isFixedOrSticky,
|
|
3138
|
-
// Phase 1: Animation System props
|
|
3139
3127
|
shaderTime: getShaderTime(),
|
|
3140
3128
|
withTimeAnimation: withTimeAnimation,
|
|
3141
3129
|
animationSpeed: animationSpeed,
|
|
@@ -3147,32 +3135,39 @@ const PERFORMANCE_PRESET = {
|
|
|
3147
3135
|
children: children
|
|
3148
3136
|
}), Boolean(onClick) && jsxs(Fragment, {
|
|
3149
3137
|
children: [ jsx("div", {
|
|
3138
|
+
"aria-hidden": "true",
|
|
3150
3139
|
className: ATOMIX_GLASS.HOVER_1_CLASS
|
|
3151
3140
|
}), jsx("div", {
|
|
3141
|
+
"aria-hidden": "true",
|
|
3152
3142
|
className: ATOMIX_GLASS.HOVER_2_CLASS
|
|
3153
3143
|
}), jsx("div", {
|
|
3144
|
+
"aria-hidden": "true",
|
|
3154
3145
|
className: ATOMIX_GLASS.HOVER_3_CLASS
|
|
3155
3146
|
}) ]
|
|
3156
|
-
}),
|
|
3147
|
+
}), [ "dark", "black" ].map((layerType => jsx(React.Fragment, {
|
|
3148
|
+
children: renderBackgroundLayer(layerType)
|
|
3149
|
+
}, layerType))), shouldRenderOverLightLayers && jsxs(Fragment, {
|
|
3157
3150
|
children: [ jsx("div", {
|
|
3151
|
+
"aria-hidden": "true",
|
|
3158
3152
|
className: ATOMIX_GLASS.BASE_LAYER_CLASS
|
|
3159
3153
|
}), jsx("div", {
|
|
3154
|
+
"aria-hidden": "true",
|
|
3160
3155
|
className: ATOMIX_GLASS.OVERLAY_LAYER_CLASS
|
|
3161
3156
|
}), jsx("div", {
|
|
3157
|
+
"aria-hidden": "true",
|
|
3162
3158
|
className: ATOMIX_GLASS.OVERLAY_HIGHLIGHT_CLASS
|
|
3163
3159
|
}) ]
|
|
3164
|
-
}),
|
|
3160
|
+
}), resolvedBorder.enabled && jsxs(Fragment, {
|
|
3165
3161
|
children: [ jsx("span", {
|
|
3162
|
+
"aria-hidden": "true",
|
|
3166
3163
|
className: ATOMIX_GLASS.BORDER_BACKDROP_CLASS
|
|
3167
3164
|
}), jsx("span", {
|
|
3165
|
+
"aria-hidden": "true",
|
|
3168
3166
|
className: ATOMIX_GLASS.BORDER_1_CLASS
|
|
3169
3167
|
}), jsx("span", {
|
|
3168
|
+
"aria-hidden": "true",
|
|
3170
3169
|
className: ATOMIX_GLASS.BORDER_2_CLASS
|
|
3171
3170
|
}) ]
|
|
3172
|
-
}), debugPerformance && performanceMetrics && jsx(PerformanceDashboard, {
|
|
3173
|
-
metrics: performanceMetrics,
|
|
3174
|
-
isVisible: !0,
|
|
3175
|
-
onClose: () => {}
|
|
3176
3171
|
}) ]
|
|
3177
3172
|
});
|
|
3178
3173
|
}));
|
|
@@ -3182,10 +3177,7 @@ const PERFORMANCE_PRESET = {
|
|
|
3182
3177
|
* Default preset for most mobile devices
|
|
3183
3178
|
*/ AtomixGlassInner.displayName = "AtomixGlass";
|
|
3184
3179
|
|
|
3185
|
-
/**
|
|
3186
|
-
* AtomixGlass - wrapped with React.memo to prevent unnecessary re-renders.
|
|
3187
|
-
* Ref is forwarded to the root `<div>` element.
|
|
3188
|
-
*/
|
|
3180
|
+
/** Memoized public export. Ref targets the root `.c-atomix-glass` wrapper. */
|
|
3189
3181
|
const AtomixGlass = memo(AtomixGlassInner), DefaultIcon = () => jsx("i", {
|
|
3190
3182
|
className: "c-accordion__icon",
|
|
3191
3183
|
"aria-hidden": "true",
|
|
@@ -3364,10 +3356,7 @@ const AccordionImpl = memo((({title: title, children: children, defaultOpen: de
|
|
|
3364
3356
|
});
|
|
3365
3357
|
if (glass) {
|
|
3366
3358
|
// Default glass settings for accordions
|
|
3367
|
-
const defaultGlassProps = {
|
|
3368
|
-
displacementScale: 20,
|
|
3369
|
-
elasticity: 0
|
|
3370
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
3359
|
+
const defaultGlassProps = GLASS_DEFAULTS_ACCORDION, glassProps = !0 === glass ? defaultGlassProps : {
|
|
3371
3360
|
...defaultGlassProps,
|
|
3372
3361
|
...glass
|
|
3373
3362
|
};
|
|
@@ -3444,10 +3433,10 @@ const Accordion = AccordionWithSubcomponents, Badge = memo((({label: label, var
|
|
|
3444
3433
|
if (glass) {
|
|
3445
3434
|
// Default glass settings for badges
|
|
3446
3435
|
const defaultGlassProps = {
|
|
3447
|
-
|
|
3448
|
-
borderRadius
|
|
3449
|
-
|
|
3450
|
-
|
|
3436
|
+
...GLASS_DEFAULTS_BADGE,
|
|
3437
|
+
// Override borderRadius dynamically if the ref is available
|
|
3438
|
+
borderRadius: ref.current?.getBoundingClientRect().width ? ref.current?.getBoundingClientRect().width / 2 : GLASS_DEFAULTS_BADGE.borderRadius,
|
|
3439
|
+
className: "c-badge--glass"
|
|
3451
3440
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
3452
3441
|
...defaultGlassProps,
|
|
3453
3442
|
...glass
|
|
@@ -3697,12 +3686,7 @@ const Spinner = memo( forwardRef((({size: size = "md", variant: variant = "prim
|
|
|
3697
3686
|
})
|
|
3698
3687
|
});
|
|
3699
3688
|
if (glass) {
|
|
3700
|
-
const defaultGlassProps = {
|
|
3701
|
-
displacementScale: 20,
|
|
3702
|
-
blurAmount: 1,
|
|
3703
|
-
borderRadius: 999,
|
|
3704
|
-
mode: "shader"
|
|
3705
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
3689
|
+
const defaultGlassProps = GLASS_DEFAULTS_SPINNER, glassProps = !0 === glass ? defaultGlassProps : {
|
|
3706
3690
|
...defaultGlassProps,
|
|
3707
3691
|
...glass
|
|
3708
3692
|
};
|
|
@@ -3982,11 +3966,7 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
|
|
|
3982
3966
|
// This is a safe fallback for disabled links.
|
|
3983
3967
|
if (glass) {
|
|
3984
3968
|
// Default glass props
|
|
3985
|
-
const defaultGlassProps = {
|
|
3986
|
-
displacementScale: 20,
|
|
3987
|
-
blurAmount: 0,
|
|
3988
|
-
saturation: 200
|
|
3989
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
3969
|
+
const defaultGlassProps = GLASS_DEFAULTS_BUTTON, glassProps = !0 === glass ? defaultGlassProps : {
|
|
3990
3970
|
...defaultGlassProps,
|
|
3991
3971
|
...glass
|
|
3992
3972
|
};
|
|
@@ -4426,11 +4406,7 @@ const Callout = memo((({title: title, children: children, icon: icon, variant:
|
|
|
4426
4406
|
// Determine appropriate ARIA attributes based on variant
|
|
4427
4407
|
if (glass) {
|
|
4428
4408
|
// Default glass settings for callouts
|
|
4429
|
-
const defaultGlassProps = {
|
|
4430
|
-
displacementScale: 30,
|
|
4431
|
-
borderRadius: 8,
|
|
4432
|
-
elasticity: 0
|
|
4433
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
4409
|
+
const defaultGlassProps = GLASS_DEFAULTS_CALLOUT, glassProps = !0 === glass ? defaultGlassProps : {
|
|
4434
4410
|
...defaultGlassProps,
|
|
4435
4411
|
...glass
|
|
4436
4412
|
};
|