@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/charts.js
CHANGED
|
@@ -462,6 +462,44 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
462
462
|
POSITIONS: [ "top", "bottom", "left", "right" ],
|
|
463
463
|
ACTION_VARIANTS: [ "primary", "secondary", "success", "info", "warning", "error" ]
|
|
464
464
|
}
|
|
465
|
+
}, GLASS_BORDER_GRADIENT = {
|
|
466
|
+
BASE_ANGLE: 135,
|
|
467
|
+
ANGLE_MULTIPLIER: .5,
|
|
468
|
+
VELOCITY_ANGLE_MULTIPLIER: .5,
|
|
469
|
+
CHROMATIC_OFFSET: 1.5,
|
|
470
|
+
STOP_1: {
|
|
471
|
+
MIN: 10,
|
|
472
|
+
BASE: 33,
|
|
473
|
+
get MULTIPLIER() {
|
|
474
|
+
return .009 * this.BASE;
|
|
475
|
+
}
|
|
476
|
+
},
|
|
477
|
+
STOP_2: {
|
|
478
|
+
MAX: 90,
|
|
479
|
+
BASE: 66,
|
|
480
|
+
get MULTIPLIER() {
|
|
481
|
+
return .006 * this.BASE;
|
|
482
|
+
}
|
|
483
|
+
},
|
|
484
|
+
OPACITY: {
|
|
485
|
+
/** Matches $glass-border-1-opacity (0.08) */
|
|
486
|
+
BASE_1: .08,
|
|
487
|
+
get BASE_2() {
|
|
488
|
+
return 3.33 * this.BASE_1;
|
|
489
|
+
},
|
|
490
|
+
get BASE_3() {
|
|
491
|
+
return 2.66 * this.BASE_1;
|
|
492
|
+
},
|
|
493
|
+
get BASE_4() {
|
|
494
|
+
return 5 * this.BASE_1;
|
|
495
|
+
},
|
|
496
|
+
get MULTIPLIER_LOW() {
|
|
497
|
+
return .066 * this.BASE_1;
|
|
498
|
+
},
|
|
499
|
+
get MULTIPLIER_HIGH() {
|
|
500
|
+
return .1 * this.BASE_1;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
465
503
|
}, ATOMIX_GLASS = {
|
|
466
504
|
BASE_CLASS: "c-atomix-glass",
|
|
467
505
|
CONTAINER_CLASS: "c-atomix-glass__container",
|
|
@@ -473,6 +511,22 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
473
511
|
BORDER_BACKDROP_CLASS: "c-atomix-glass__border-backdrop",
|
|
474
512
|
BORDER_1_CLASS: "c-atomix-glass__border-1",
|
|
475
513
|
BORDER_2_CLASS: "c-atomix-glass__border-2",
|
|
514
|
+
/** Centralized liquid glass rim configuration */
|
|
515
|
+
BORDER: {
|
|
516
|
+
WIDTH_CSS_VAR: "--atomix-glass-border-width",
|
|
517
|
+
DEFAULT_WIDTH: "0.5px",
|
|
518
|
+
GRADIENT_CSS_VARS: {
|
|
519
|
+
GRADIENT_1: "--atomix-glass-border-gradient-1",
|
|
520
|
+
GRADIENT_2: "--atomix-glass-border-gradient-2"
|
|
521
|
+
},
|
|
522
|
+
GRADIENT: GLASS_BORDER_GRADIENT,
|
|
523
|
+
OVER_LIGHT: {
|
|
524
|
+
opacity: .7
|
|
525
|
+
},
|
|
526
|
+
DARK: {
|
|
527
|
+
opacity: .35
|
|
528
|
+
}
|
|
529
|
+
},
|
|
476
530
|
HOVER_1_CLASS: "c-atomix-glass__hover-1",
|
|
477
531
|
HOVER_2_CLASS: "c-atomix-glass__hover-2",
|
|
478
532
|
HOVER_3_CLASS: "c-atomix-glass__hover-3",
|
|
@@ -501,25 +555,22 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
501
555
|
SHADER: "c-atomix-glass--shader"
|
|
502
556
|
},
|
|
503
557
|
DEFAULTS: {
|
|
504
|
-
|
|
558
|
+
/** Subtle refraction — Apple UI chrome avoids heavy liquid distortion */
|
|
559
|
+
DISPLACEMENT_SCALE: 28,
|
|
505
560
|
get BLUR_AMOUNT() {
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
// Saturate relative to intensity
|
|
512
|
-
},
|
|
561
|
+
// Apple Music sidebar / player bar: ~20–40px frost (see $glass-backdrop-filter)
|
|
562
|
+
return Math.max(20, .72 * this.DISPLACEMENT_SCALE);
|
|
563
|
+
},
|
|
564
|
+
/** Fixed 180% matches Apple's saturate(180%) backdrop recipe */
|
|
565
|
+
SATURATION: 180,
|
|
513
566
|
get ABERRATION_INTENSITY() {
|
|
514
|
-
return .
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
ELASTICITY: .15,
|
|
567
|
+
return .02 * this.DISPLACEMENT_SCALE;
|
|
568
|
+
},
|
|
569
|
+
ELASTICITY: .05,
|
|
518
570
|
get CORNER_RADIUS() {
|
|
519
571
|
return 16;
|
|
520
572
|
// Use 16 to match SCSS design system (was 20)
|
|
521
573
|
},
|
|
522
|
-
PADDING: "0",
|
|
523
574
|
MODE: "standard",
|
|
524
575
|
OVER_LIGHT: !1,
|
|
525
576
|
ENABLE_OVER_LIGHT_LAYERS: !0,
|
|
@@ -535,19 +586,24 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
535
586
|
},
|
|
536
587
|
CONSTANTS: {
|
|
537
588
|
ACTIVATION_ZONE: 200,
|
|
538
|
-
LERP_FACTOR: .
|
|
589
|
+
LERP_FACTOR: .05,
|
|
590
|
+
// Lower = more viscous, liquid-smooth tracking (Apple feel)
|
|
539
591
|
SMOOTHSTEP_POWER: 2.5,
|
|
540
592
|
MIN_BLUR: .1,
|
|
541
593
|
MOUSE_INFLUENCE_DIVISOR: 100,
|
|
542
594
|
EDGE_FADE_PIXELS: 2,
|
|
543
|
-
// Elasticity physics constants
|
|
544
|
-
ELASTICITY_TRANSLATION_FACTOR: .
|
|
595
|
+
// Elasticity physics constants — Apple-tuned: soft springs, fast settling, minimal stretch
|
|
596
|
+
ELASTICITY_TRANSLATION_FACTOR: .06,
|
|
597
|
+
// Subtler elastic shift (was 0.1)
|
|
545
598
|
ELASTICITY_DISTANCE_THRESHOLD: 200,
|
|
546
599
|
ELASTICITY_COMPRESSION_FACTOR: .3,
|
|
547
|
-
ELASTICITY_STIFFNESS: .
|
|
548
|
-
|
|
600
|
+
ELASTICITY_STIFFNESS: .06,
|
|
601
|
+
// Softer springs = gentler motion (was 0.1)
|
|
602
|
+
ELASTICITY_DAMPING: .88,
|
|
603
|
+
// Fast settling, no wobble (was 0.76)
|
|
549
604
|
ELASTICITY_VELOCITY_FACTOR: .65,
|
|
550
|
-
ELASTICITY_STRETCH_RATIO: .
|
|
605
|
+
ELASTICITY_STRETCH_RATIO: .25,
|
|
606
|
+
// Less visible surface tension stretch (was 0.45)
|
|
551
607
|
ELASTICITY_MAGNIFICATION_BASE: 1.02,
|
|
552
608
|
// Note: This default must match the SCSS variable --atomix-radius-md
|
|
553
609
|
// @see src/styles/01-settings/_settings.global.scss
|
|
@@ -561,55 +617,16 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
561
617
|
},
|
|
562
618
|
// Gradient calculation constants
|
|
563
619
|
GRADIENT: {
|
|
564
|
-
BASE_ANGLE:
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
// Minimum percentage for border stop 1
|
|
575
|
-
BASE: 33,
|
|
576
|
-
// Base percentage for border stop 1
|
|
577
|
-
get MULTIPLIER() {
|
|
578
|
-
return .009 * this.BASE;
|
|
579
|
-
}
|
|
580
|
-
},
|
|
581
|
-
BORDER_STOP_2: {
|
|
582
|
-
MAX: 90,
|
|
583
|
-
// Maximum percentage for border stop 2
|
|
584
|
-
BASE: 66,
|
|
585
|
-
// Base percentage for border stop 2
|
|
586
|
-
get MULTIPLIER() {
|
|
587
|
-
return .006 * this.BASE;
|
|
588
|
-
}
|
|
589
|
-
},
|
|
590
|
-
BORDER_OPACITY: {
|
|
591
|
-
BASE_1: .12,
|
|
592
|
-
// Base opacity for border gradient 1
|
|
593
|
-
get BASE_2() {
|
|
594
|
-
return 3.33 * this.BASE_1;
|
|
595
|
-
},
|
|
596
|
-
// Base opacity for border gradient 2
|
|
597
|
-
get BASE_3() {
|
|
598
|
-
return 2.66 * this.BASE_1;
|
|
599
|
-
},
|
|
600
|
-
// Base opacity for border gradient 3
|
|
601
|
-
get BASE_4() {
|
|
602
|
-
return 5 * this.BASE_1;
|
|
603
|
-
},
|
|
604
|
-
// Base opacity for border gradient 4
|
|
605
|
-
get MULTIPLIER_LOW() {
|
|
606
|
-
return .066 * this.BASE_1;
|
|
607
|
-
},
|
|
608
|
-
// Low multiplier for mouse influence on opacity
|
|
609
|
-
get MULTIPLIER_HIGH() {
|
|
610
|
-
return .1 * this.BASE_1;
|
|
611
|
-
}
|
|
612
|
-
},
|
|
620
|
+
BASE_ANGLE: GLASS_BORDER_GRADIENT.BASE_ANGLE,
|
|
621
|
+
ANGLE_MULTIPLIER: GLASS_BORDER_GRADIENT.ANGLE_MULTIPLIER,
|
|
622
|
+
VELOCITY_ANGLE_MULTIPLIER: GLASS_BORDER_GRADIENT.VELOCITY_ANGLE_MULTIPLIER,
|
|
623
|
+
CHROMATIC_OFFSET: GLASS_BORDER_GRADIENT.CHROMATIC_OFFSET,
|
|
624
|
+
/** @deprecated Use ATOMIX_GLASS.BORDER.GRADIENT.STOP_1 */
|
|
625
|
+
BORDER_STOP_1: GLASS_BORDER_GRADIENT.STOP_1,
|
|
626
|
+
/** @deprecated Use ATOMIX_GLASS.BORDER.GRADIENT.STOP_2 */
|
|
627
|
+
BORDER_STOP_2: GLASS_BORDER_GRADIENT.STOP_2,
|
|
628
|
+
/** @deprecated Use ATOMIX_GLASS.BORDER.GRADIENT.OPACITY */
|
|
629
|
+
BORDER_OPACITY: GLASS_BORDER_GRADIENT.OPACITY,
|
|
613
630
|
CENTER_POSITION: 50,
|
|
614
631
|
// Center position percentage (50%)
|
|
615
632
|
HOVER_POSITION: {
|
|
@@ -642,8 +659,8 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
642
659
|
return 2 * this.BLACK_STOP;
|
|
643
660
|
},
|
|
644
661
|
// End percentage for black hover 1
|
|
645
|
-
WHITE_START: .
|
|
646
|
-
//
|
|
662
|
+
WHITE_START: .35,
|
|
663
|
+
// Gentler hover flash — Apple hover is barely visible
|
|
647
664
|
get WHITE_STOP() {
|
|
648
665
|
return this.BLACK_END - 10;
|
|
649
666
|
}
|
|
@@ -661,8 +678,8 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
661
678
|
return 2 * this.BLACK_STOP;
|
|
662
679
|
},
|
|
663
680
|
// End percentage for black hover 2
|
|
664
|
-
WHITE_START:
|
|
665
|
-
//
|
|
681
|
+
WHITE_START: .7,
|
|
682
|
+
// Gentler hover flash
|
|
666
683
|
get WHITE_STOP() {
|
|
667
684
|
return this.BLACK_END;
|
|
668
685
|
}
|
|
@@ -680,8 +697,8 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
680
697
|
return 2 * this.BLACK_STOP;
|
|
681
698
|
},
|
|
682
699
|
// End percentage for black hover 3
|
|
683
|
-
WHITE_START:
|
|
684
|
-
//
|
|
700
|
+
WHITE_START: .7,
|
|
701
|
+
// Gentler hover flash
|
|
685
702
|
get WHITE_STOP() {
|
|
686
703
|
return this.BLACK_END;
|
|
687
704
|
}
|
|
@@ -691,13 +708,13 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
691
708
|
BASE_GRADIENT: {
|
|
692
709
|
ANGLE: 135,
|
|
693
710
|
// Gradient angle in degrees
|
|
694
|
-
BLACK_START_BASE: .
|
|
711
|
+
BLACK_START_BASE: .1,
|
|
695
712
|
// Base start opacity for black
|
|
696
713
|
get BLACK_START_MULTIPLIER() {
|
|
697
714
|
return .02 * this.BLACK_START_BASE;
|
|
698
715
|
},
|
|
699
716
|
// Multiplier for mouse X influence on start
|
|
700
|
-
BLACK_MID_BASE: .
|
|
717
|
+
BLACK_MID_BASE: .07,
|
|
701
718
|
// Base mid opacity for black
|
|
702
719
|
get BLACK_MID_MULTIPLIER() {
|
|
703
720
|
return .02 * this.BLACK_MID_BASE;
|
|
@@ -718,7 +735,7 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
718
735
|
}
|
|
719
736
|
},
|
|
720
737
|
OVERLAY_GRADIENT: {
|
|
721
|
-
BLACK_START_BASE: .
|
|
738
|
+
BLACK_START_BASE: .08,
|
|
722
739
|
// Base start opacity for black overlay
|
|
723
740
|
get BLACK_START_MULTIPLIER() {
|
|
724
741
|
return .025 * this.BLACK_START_BASE;
|
|
@@ -742,14 +759,14 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
742
759
|
return .416 * this.BLACK_START_BASE;
|
|
743
760
|
}
|
|
744
761
|
},
|
|
745
|
-
// Overlay highlight constants
|
|
762
|
+
// Overlay highlight constants — Apple places specular at the top-center
|
|
746
763
|
OVERLAY_HIGHLIGHT: {
|
|
747
|
-
POSITION_X:
|
|
748
|
-
//
|
|
749
|
-
POSITION_Y:
|
|
750
|
-
//
|
|
751
|
-
WHITE_OPACITY: .
|
|
752
|
-
//
|
|
764
|
+
POSITION_X: 50,
|
|
765
|
+
// Centered horizontal — Apple's top-center specular
|
|
766
|
+
POSITION_Y: 5,
|
|
767
|
+
// Very top — catches light like a curved glass surface
|
|
768
|
+
WHITE_OPACITY: .28,
|
|
769
|
+
// Softer specular — visible but not glaring
|
|
753
770
|
get STOP() {
|
|
754
771
|
return 150 * this.WHITE_OPACITY;
|
|
755
772
|
},
|
|
@@ -770,6 +787,10 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
770
787
|
SATURATION: {
|
|
771
788
|
HIGH_CONTRAST: 200
|
|
772
789
|
},
|
|
790
|
+
// Container shadows — hairline inner catch + soft floating lift (Apple player bar)
|
|
791
|
+
CONTAINER_SHADOW: {
|
|
792
|
+
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)"
|
|
793
|
+
},
|
|
773
794
|
// Phase 1: Animation System Constants
|
|
774
795
|
ANIMATION: {
|
|
775
796
|
// Breathing effect timing (in milliseconds)
|
|
@@ -1664,9 +1685,38 @@ const ChartToolbar = memo( forwardRef((({chartType: chartType = "line", groups:
|
|
|
1664
1685
|
});
|
|
1665
1686
|
})));
|
|
1666
1687
|
|
|
1688
|
+
/**
|
|
1689
|
+
* Component Utilities
|
|
1690
|
+
*
|
|
1691
|
+
* Helper functions for component development with the new customization system
|
|
1692
|
+
*/
|
|
1693
|
+
/**
|
|
1694
|
+
* Merge multiple class names
|
|
1695
|
+
*/
|
|
1696
|
+
function mergeClassNames(...classes) {
|
|
1697
|
+
return classes.filter(Boolean).join(" ");
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
/**
|
|
1701
|
+
* Utility to merge multiple React refs into one
|
|
1702
|
+
*/ function setRef(ref, value) {
|
|
1703
|
+
"function" == typeof ref ? ref(value) : ref && (
|
|
1704
|
+
// This is safe because we're checking that ref exists first
|
|
1705
|
+
ref.current = value);
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
/**
|
|
1709
|
+
* Combines two React refs into a single ref function
|
|
1710
|
+
* This is used when you need to use and forward a ref at the same time
|
|
1711
|
+
*/ function useForkRef(refA, refB) {
|
|
1712
|
+
return React.useMemo((() => null == refA && null == refB ? null : refValue => {
|
|
1713
|
+
setRef(refA, refValue), setRef(refB, refValue);
|
|
1714
|
+
}), [ refA, refB ]);
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1667
1717
|
ChartToolbar.displayName = "ChartToolbar";
|
|
1668
1718
|
|
|
1669
|
-
const {CONSTANTS: CONSTANTS$
|
|
1719
|
+
const {CONSTANTS: CONSTANTS$3} = ATOMIX_GLASS, calculateElementCenter = rect => rect ? {
|
|
1670
1720
|
x: rect.left + rect.width / 2,
|
|
1671
1721
|
y: rect.top + rect.height / 2
|
|
1672
1722
|
} : {
|
|
@@ -1674,37 +1724,37 @@ const {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateElementCenter = rect =>
|
|
|
1674
1724
|
y: 0
|
|
1675
1725
|
}, calculateMouseInfluence = mouseOffset => {
|
|
1676
1726
|
if (!mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y) return 0;
|
|
1677
|
-
//
|
|
1678
|
-
const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$
|
|
1727
|
+
// Clamp influence to keep mouse response subtle and stable.
|
|
1728
|
+
const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$3.MOUSE_INFLUENCE_DIVISOR;
|
|
1679
1729
|
return Math.min(.8, influence);
|
|
1680
1730
|
// Tighter cap to prevent blur/filter blow-out
|
|
1681
|
-
}, clampBlur = value => "number" != typeof value || isNaN(value) ? CONSTANTS$
|
|
1731
|
+
}, 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 => {
|
|
1682
1732
|
if ("number" == typeof value) return Math.max(0, value);
|
|
1683
|
-
if ("string" != typeof value || !value.trim()) return CONSTANTS$
|
|
1733
|
+
if ("string" != typeof value || !value.trim()) return CONSTANTS$3.DEFAULT_CORNER_RADIUS;
|
|
1684
1734
|
const trimmedValue = value.trim();
|
|
1685
1735
|
// Handle px values
|
|
1686
1736
|
if (trimmedValue.endsWith("px")) {
|
|
1687
1737
|
const parsed = parseFloat(trimmedValue);
|
|
1688
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
1738
|
+
return isNaN(parsed) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
|
|
1689
1739
|
}
|
|
1690
1740
|
// Handle rem values (assume 16px = 1rem)
|
|
1691
1741
|
if (trimmedValue.endsWith("rem")) {
|
|
1692
1742
|
const parsed = parseFloat(trimmedValue);
|
|
1693
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
1743
|
+
return isNaN(parsed) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
1694
1744
|
}
|
|
1695
1745
|
// Handle em values (assume 16px = 1em for simplicity)
|
|
1696
1746
|
if (trimmedValue.endsWith("em")) {
|
|
1697
1747
|
const parsed = parseFloat(trimmedValue);
|
|
1698
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
1748
|
+
return isNaN(parsed) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
1699
1749
|
}
|
|
1700
1750
|
// Handle percentage (convert to approximate px value, assuming 200px container)
|
|
1701
1751
|
if (trimmedValue.endsWith("%")) {
|
|
1702
1752
|
const parsed = parseFloat(trimmedValue);
|
|
1703
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
1753
|
+
return isNaN(parsed) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
|
|
1704
1754
|
}
|
|
1705
1755
|
// Handle unitless numbers
|
|
1706
1756
|
const numValue = parseFloat(trimmedValue);
|
|
1707
|
-
return isNaN(numValue) ? CONSTANTS$
|
|
1757
|
+
return isNaN(numValue) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
|
|
1708
1758
|
}, extractBorderRadiusFromElement = element => {
|
|
1709
1759
|
if (!element || !element.props) return null;
|
|
1710
1760
|
// Check inline styles first (highest priority)
|
|
@@ -1720,11 +1770,11 @@ const {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateElementCenter = rect =>
|
|
|
1720
1770
|
// If element has children, recursively check them
|
|
1721
1771
|
if (element.props.children) {
|
|
1722
1772
|
const childRadius = extractBorderRadiusFromChildren(element.props.children);
|
|
1723
|
-
if (childRadius > 0 && childRadius !== CONSTANTS$
|
|
1773
|
+
if (childRadius > 0 && childRadius !== CONSTANTS$3.DEFAULT_CORNER_RADIUS) return childRadius;
|
|
1724
1774
|
}
|
|
1725
1775
|
return null;
|
|
1726
1776
|
}, extractBorderRadiusFromChildren = children => {
|
|
1727
|
-
if (!children) return CONSTANTS$
|
|
1777
|
+
if (!children) return CONSTANTS$3.DEFAULT_CORNER_RADIUS;
|
|
1728
1778
|
try {
|
|
1729
1779
|
const childArray = React.Children.toArray(children);
|
|
1730
1780
|
for (let i = 0; i < childArray.length; i++) {
|
|
@@ -1737,7 +1787,7 @@ const {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateElementCenter = rect =>
|
|
|
1737
1787
|
} catch (error) {
|
|
1738
1788
|
// Silently handle errors
|
|
1739
1789
|
}
|
|
1740
|
-
return CONSTANTS$
|
|
1790
|
+
return CONSTANTS$3.DEFAULT_CORNER_RADIUS;
|
|
1741
1791
|
}, smoothstep = t => {
|
|
1742
1792
|
const clamped = Math.max(0, Math.min(1, t));
|
|
1743
1793
|
return clamped * clamped * (3 - 2 * clamped);
|
|
@@ -1747,7 +1797,47 @@ const {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateElementCenter = rect =>
|
|
|
1747
1797
|
value: current + newVelocity,
|
|
1748
1798
|
velocity: newVelocity
|
|
1749
1799
|
};
|
|
1750
|
-
}
|
|
1800
|
+
};
|
|
1801
|
+
|
|
1802
|
+
/**
|
|
1803
|
+
* Calculate element center from bounding rect
|
|
1804
|
+
*/
|
|
1805
|
+
/**
|
|
1806
|
+
* Normalizes a layout inset for use in CSS custom properties.
|
|
1807
|
+
*
|
|
1808
|
+
* @param value - Raw inset from `style` (number, px string, or `auto`).
|
|
1809
|
+
* @param fallback - Value used when `value` is undefined.
|
|
1810
|
+
*/
|
|
1811
|
+
function formatGlassInsetValue(value, fallback = "auto") {
|
|
1812
|
+
return void 0 === value ? "number" == typeof fallback ? `${fallback}px` : String(fallback) : "auto" === value ? "auto" : "number" == typeof value ? `${value}px` : value;
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1815
|
+
/**
|
|
1816
|
+
* Determines whether the glass should use fixed/sticky layout semantics.
|
|
1817
|
+
*
|
|
1818
|
+
* @param explicit - Value of the `isFixedOrSticky` prop.
|
|
1819
|
+
* @param position - `position` from the consumer `style` object.
|
|
1820
|
+
*/
|
|
1821
|
+
/** Coerces a value to a finite number, returning `fallback` when invalid. */
|
|
1822
|
+
function toSafeNumber(value, fallback = 0) {
|
|
1823
|
+
return "number" != typeof value || isNaN(value) ? fallback : value;
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1826
|
+
/**
|
|
1827
|
+
* Calculates the target frame rate for shader time-animation loops.
|
|
1828
|
+
*
|
|
1829
|
+
* Balances visual quality against distortion complexity and `animationSpeed`.
|
|
1830
|
+
*/
|
|
1831
|
+
/**
|
|
1832
|
+
* Computes per-channel displacement scale for the SVG chromatic-aberration filter.
|
|
1833
|
+
*/
|
|
1834
|
+
function getChromaticDisplacementScale(mode, displacementScale, aberrationIntensity, channelFactor) {
|
|
1835
|
+
return displacementScale * (("shader" === mode ? 1 : -1) - aberrationIntensity * channelFactor);
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1838
|
+
/**
|
|
1839
|
+
* Get displacement map URL based on mode
|
|
1840
|
+
*/ const getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
|
|
1751
1841
|
switch (mode) {
|
|
1752
1842
|
case "standard":
|
|
1753
1843
|
return displacementMap;
|
|
@@ -1764,13 +1854,28 @@ const {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateElementCenter = rect =>
|
|
|
1764
1854
|
default:
|
|
1765
1855
|
return console.warn("AtomixGlass: Invalid displacement mode"), displacementMap;
|
|
1766
1856
|
}
|
|
1767
|
-
}, sharedShaderCache = new Map,
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1857
|
+
}, sharedShaderCache = new Map, CHROMATIC_CHANNELS = [ {
|
|
1858
|
+
result: "RED_DISPLACED",
|
|
1859
|
+
channelResult: "RED_CHANNEL",
|
|
1860
|
+
aberrationFactor: 0,
|
|
1861
|
+
colorMatrix: "1 0 0 0 0\n0 0 0 0 0\n0 0 0 0 0\n0 0 0 1 0"
|
|
1862
|
+
}, {
|
|
1863
|
+
result: "GREEN_DISPLACED",
|
|
1864
|
+
channelResult: "GREEN_CHANNEL",
|
|
1865
|
+
aberrationFactor: .02,
|
|
1866
|
+
colorMatrix: "0 0 0 0 0\n0 1 0 0 0\n0 0 0 0 0\n0 0 0 1 0"
|
|
1867
|
+
}, {
|
|
1868
|
+
result: "BLUE_DISPLACED",
|
|
1869
|
+
channelResult: "BLUE_CHANNEL",
|
|
1870
|
+
aberrationFactor: .03,
|
|
1871
|
+
colorMatrix: "0 0 0 0 0\n0 0 0 0 0\n0 0 1 0 0\n0 0 0 1 0"
|
|
1872
|
+
} ], FILTER_SVG_STYLE = {
|
|
1873
|
+
position: "absolute",
|
|
1874
|
+
width: "100%",
|
|
1875
|
+
height: "100%",
|
|
1876
|
+
inset: 0
|
|
1877
|
+
}, GlassFilterComponent = ({id: id, displacementScale: displacementScale, aberrationIntensity: aberrationIntensity, mode: mode, shaderMapUrl: shaderMapUrl, blurAmount: blurAmount}) => jsx("svg", {
|
|
1878
|
+
style: FILTER_SVG_STYLE,
|
|
1774
1879
|
"aria-hidden": "true",
|
|
1775
1880
|
children: jsxs("defs", {
|
|
1776
1881
|
children: [ jsxs("radialGradient", {
|
|
@@ -1824,43 +1929,21 @@ const {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateElementCenter = rect =>
|
|
|
1824
1929
|
dx: "0",
|
|
1825
1930
|
dy: "0",
|
|
1826
1931
|
result: "CENTER_ORIGINAL"
|
|
1827
|
-
}),
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
scale: displacementScale * (("shader" === mode ? 1 : -1) - .02 * aberrationIntensity),
|
|
1843
|
-
xChannelSelector: "R",
|
|
1844
|
-
yChannelSelector: "B",
|
|
1845
|
-
result: "GREEN_DISPLACED"
|
|
1846
|
-
}), jsx("feColorMatrix", {
|
|
1847
|
-
in: "GREEN_DISPLACED",
|
|
1848
|
-
type: "matrix",
|
|
1849
|
-
values: "0 0 0 0 0\n 0 1 0 0 0\n 0 0 0 0 0\n 0 0 0 1 0",
|
|
1850
|
-
result: "GREEN_CHANNEL"
|
|
1851
|
-
}), jsx("feDisplacementMap", {
|
|
1852
|
-
in: "SourceGraphic",
|
|
1853
|
-
in2: "DISPLACEMENT_MAP",
|
|
1854
|
-
scale: displacementScale * (("shader" === mode ? 1 : -1) - .03 * aberrationIntensity),
|
|
1855
|
-
xChannelSelector: "R",
|
|
1856
|
-
yChannelSelector: "B",
|
|
1857
|
-
result: "BLUE_DISPLACED"
|
|
1858
|
-
}), jsx("feColorMatrix", {
|
|
1859
|
-
in: "BLUE_DISPLACED",
|
|
1860
|
-
type: "matrix",
|
|
1861
|
-
values: "0 0 0 0 0\n 0 0 0 0 0\n 0 0 1 0 0\n 0 0 0 1 0",
|
|
1862
|
-
result: "BLUE_CHANNEL"
|
|
1863
|
-
}), jsx("feBlend", {
|
|
1932
|
+
}), CHROMATIC_CHANNELS.map((channel => jsxs(React.Fragment, {
|
|
1933
|
+
children: [ jsx("feDisplacementMap", {
|
|
1934
|
+
in: "SourceGraphic",
|
|
1935
|
+
in2: "DISPLACEMENT_MAP",
|
|
1936
|
+
scale: getChromaticDisplacementScale(mode, displacementScale, aberrationIntensity, channel.aberrationFactor),
|
|
1937
|
+
xChannelSelector: "R",
|
|
1938
|
+
yChannelSelector: "B",
|
|
1939
|
+
result: channel.result
|
|
1940
|
+
}), jsx("feColorMatrix", {
|
|
1941
|
+
in: channel.result,
|
|
1942
|
+
type: "matrix",
|
|
1943
|
+
values: channel.colorMatrix,
|
|
1944
|
+
result: channel.channelResult
|
|
1945
|
+
}) ]
|
|
1946
|
+
}, channel.channelResult))), jsx("feBlend", {
|
|
1864
1947
|
in: "GREEN_CHANNEL",
|
|
1865
1948
|
in2: "BLUE_CHANNEL",
|
|
1866
1949
|
mode: "screen",
|
|
@@ -1901,21 +1984,22 @@ const {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateElementCenter = rect =>
|
|
|
1901
1984
|
});
|
|
1902
1985
|
|
|
1903
1986
|
/**
|
|
1904
|
-
*
|
|
1987
|
+
* Module-level LRU cache for shader displacement maps.
|
|
1988
|
+
*
|
|
1989
|
+
* Shared across all `AtomixGlassContainer` instances so identical size and
|
|
1990
|
+
* variant combinations are generated once.
|
|
1905
1991
|
*/ GlassFilterComponent.displayName = "GlassFilter";
|
|
1906
1992
|
|
|
1907
|
-
|
|
1993
|
+
/** Shallow prop comparison to avoid redundant SVG filter regeneration. */
|
|
1908
1994
|
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 = {
|
|
1909
1995
|
x: 0,
|
|
1910
1996
|
y: 0
|
|
1911
|
-
}, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {}, borderRadius: borderRadius = 0,
|
|
1997
|
+
}, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {}, borderRadius: borderRadius = 0, glassSize: glassSize = {
|
|
1912
1998
|
width: 0,
|
|
1913
1999
|
height: 0
|
|
1914
|
-
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, isFixedOrSticky: isFixedOrSticky = !1,
|
|
1915
|
-
// Phase 1: Animation System props
|
|
1916
|
-
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) => {
|
|
2000
|
+
}, 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) => {
|
|
1917
2001
|
// React 18 useId — stable, unique, and SSR-safe (no module-level counter)
|
|
1918
|
-
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);
|
|
2002
|
+
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);
|
|
1919
2003
|
// Lazy load shader utilities only when shader mode is needed
|
|
1920
2004
|
useEffect((() => {
|
|
1921
2005
|
"shader" === mode ?
|
|
@@ -1993,15 +2077,23 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
1993
2077
|
shaderGeneratorRef.current = null;
|
|
1994
2078
|
}
|
|
1995
2079
|
};
|
|
1996
|
-
}), [ mode, glassSize, shaderVariant ]),
|
|
1997
|
-
// Phase 1: Time-Based Animation Loop - Continuous shader regeneration
|
|
1998
|
-
useEffect((() => {
|
|
2080
|
+
}), [ mode, glassSize, shaderVariant ]), useEffect((() => {
|
|
1999
2081
|
// Only run animations in shader mode with time animation enabled
|
|
2000
2082
|
if ("shader" !== mode || !withTimeAnimation || effectiveReducedMotion || effectiveWithoutEffects)
|
|
2001
2083
|
// Cancel any existing animation frame
|
|
2002
2084
|
return void (null !== animationFrameRef.current && (cancelAnimationFrame(animationFrameRef.current),
|
|
2003
2085
|
animationFrameRef.current = null));
|
|
2004
|
-
const
|
|
2086
|
+
const targetFps = function(options) {
|
|
2087
|
+
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;
|
|
2088
|
+
return Math.max(12, Math.min(60, Math.round(baseFps * effectiveSpeed / complexity)));
|
|
2089
|
+
}({
|
|
2090
|
+
distortionQuality: distortionQuality,
|
|
2091
|
+
animationSpeed: animationSpeed,
|
|
2092
|
+
withMultiLayerDistortion: withMultiLayerDistortion,
|
|
2093
|
+
distortionOctaves: distortionOctaves,
|
|
2094
|
+
distortionLacunarity: distortionLacunarity,
|
|
2095
|
+
distortionGain: distortionGain
|
|
2096
|
+
}), frameInterval = 1e3 / targetFps;
|
|
2005
2097
|
let lastUpdate = 0, isCancelled = !1;
|
|
2006
2098
|
const animate = currentTime => {
|
|
2007
2099
|
if (!isCancelled) {
|
|
@@ -2025,88 +2117,21 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
2025
2117
|
};
|
|
2026
2118
|
}), [ mode, withTimeAnimation, animationSpeed, displacementScale, withMultiLayerDistortion, distortionOctaves, distortionLacunarity, distortionGain, distortionQuality, effectiveReducedMotion, effectiveWithoutEffects, glassSize ]);
|
|
2027
2119
|
// Removed forced reflow to avoid layout thrash and potential feedback sizing loops
|
|
2028
|
-
const
|
|
2029
|
-
useEffect((() => {
|
|
2030
|
-
if (!ref || "function" == typeof ref) return;
|
|
2031
|
-
const element = ref.current;
|
|
2032
|
-
if (element) try {
|
|
2033
|
-
setRectCache(element.getBoundingClientRect());
|
|
2034
|
-
} catch (error) {
|
|
2035
|
-
console.warn("AtomixGlassContainer: Error getting element bounds", error), setRectCache(null);
|
|
2036
|
-
}
|
|
2037
|
-
}), [ ref, glassSize ]);
|
|
2038
|
-
const liquidBlur = useMemo((() => {
|
|
2039
|
-
const defaultBlur = {
|
|
2040
|
-
baseBlur: blurAmount,
|
|
2041
|
-
edgeBlur: 1.25 * blurAmount,
|
|
2042
|
-
centerBlur: 1.1 * blurAmount,
|
|
2043
|
-
flowBlur: 1.2 * blurAmount
|
|
2044
|
-
};
|
|
2045
|
-
// Enhanced validation for liquid blur
|
|
2046
|
-
if (!withLiquidBlur || !rectCache || !mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y || isNaN(mouseOffset.x) || isNaN(mouseOffset.y)) return defaultBlur;
|
|
2047
|
-
try {
|
|
2048
|
-
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);
|
|
2049
|
-
// NOTE: hover/active multipliers intentionally omitted here —
|
|
2050
|
-
// they belong on opacity layers, not the blur filter itself.
|
|
2051
|
-
return {
|
|
2052
|
-
baseBlur: clampBlur(baseBlur),
|
|
2053
|
-
edgeBlur: clampBlur(edgeBlur),
|
|
2054
|
-
centerBlur: clampBlur(centerBlur),
|
|
2055
|
-
flowBlur: clampBlur(flowBlur)
|
|
2056
|
-
};
|
|
2057
|
-
} catch (error) {
|
|
2058
|
-
return console.warn("AtomixGlassContainer: Error calculating liquid blur", error),
|
|
2059
|
-
defaultBlur;
|
|
2060
|
-
}
|
|
2061
|
-
}), [ withLiquidBlur, blurAmount, mouseOffset, rectCache ]), backdropStyle = useMemo((() => {
|
|
2120
|
+
const containerVars = useMemo((() => {
|
|
2062
2121
|
try {
|
|
2063
|
-
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;
|
|
2064
|
-
// Validate blur values before using them
|
|
2065
|
-
return !withLiquidBlur || effectiveReducedMotion || effectiveWithoutEffects || area > 18e4 ? {
|
|
2066
|
-
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})`
|
|
2067
|
-
} : {
|
|
2068
|
-
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})`
|
|
2069
|
-
};
|
|
2070
|
-
// Single-pass fallback: stronger radius to match perceived blur of multi-pass
|
|
2071
|
-
} catch (error) {
|
|
2072
|
-
return console.warn("AtomixGlassContainer: Error calculating backdrop style", error),
|
|
2073
|
-
{
|
|
2074
|
-
backdropFilter: `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`
|
|
2075
|
-
};
|
|
2076
|
-
}
|
|
2077
|
-
}), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveWithoutEffects, withLiquidBlur, overLightConfig ]), containerVars = useMemo((() => {
|
|
2078
|
-
try {
|
|
2079
|
-
// Safe extraction of mouse offset values
|
|
2080
|
-
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;
|
|
2081
2122
|
return {
|
|
2082
|
-
"--atomix-glass-container-radius": `${"number" != typeof borderRadius || isNaN(borderRadius) ? 0 : borderRadius}px
|
|
2083
|
-
"--atomix-glass-container-backdrop": backdropStyle?.backdropFilter || "none",
|
|
2084
|
-
"--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",
|
|
2085
|
-
"--atomix-glass-container-shadow-opacity": effectiveWithoutEffects ? 0 : 1,
|
|
2086
|
-
// Background and shadow values use design token-aligned RGB values
|
|
2087
|
-
"--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",
|
|
2088
|
-
"--atomix-glass-container-text-shadow": overLight ? "0px 1px 2px rgba(255, 255, 255, 0.15)" : "0px 2px 12px rgba(0, 0, 0, 0.4)",
|
|
2089
|
-
"--atomix-glass-container-box-shadow": overLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "0px 12px 40px rgba(0, 0, 0, 0.25)"
|
|
2123
|
+
"--atomix-glass-container-radius": `${"number" != typeof borderRadius || isNaN(borderRadius) ? 0 : borderRadius}px`
|
|
2090
2124
|
};
|
|
2091
2125
|
} catch (error) {
|
|
2092
2126
|
return console.warn("AtomixGlassContainer: Error generating container variables", error),
|
|
2093
2127
|
{
|
|
2094
|
-
"--atomix-glass-container-
|
|
2095
|
-
"--atomix-glass-container-radius": "0px",
|
|
2096
|
-
"--atomix-glass-container-backdrop": "none",
|
|
2097
|
-
"--atomix-glass-container-shadow": "none",
|
|
2098
|
-
"--atomix-glass-container-shadow-opacity": 1,
|
|
2099
|
-
"--atomix-glass-container-bg": "none",
|
|
2100
|
-
"--atomix-glass-container-text-shadow": "none"
|
|
2128
|
+
"--atomix-glass-container-radius": "0px"
|
|
2101
2129
|
};
|
|
2102
2130
|
}
|
|
2103
|
-
}), [ borderRadius
|
|
2131
|
+
}), [ borderRadius ]);
|
|
2104
2132
|
return jsx("div", {
|
|
2105
|
-
ref:
|
|
2106
|
-
|
|
2107
|
-
"function" == typeof ref ? ref(el) : ref && (ref.current = el);
|
|
2108
|
-
},
|
|
2109
|
-
className: `${ATOMIX_GLASS.CONTAINER_CLASS} ${className} ${isActive ? ATOMIX_GLASS.CLASSES.ACTIVE : ""} ${overLight ? ATOMIX_GLASS.CLASSES.OVER_LIGHT : ""}`,
|
|
2133
|
+
ref: containerRef,
|
|
2134
|
+
className: mergeClassNames(ATOMIX_GLASS.CONTAINER_CLASS, className, isActive && ATOMIX_GLASS.CLASSES.ACTIVE, overLight && ATOMIX_GLASS.CLASSES.OVER_LIGHT),
|
|
2110
2135
|
style: {
|
|
2111
2136
|
...style,
|
|
2112
2137
|
...containerVars
|
|
@@ -2124,8 +2149,8 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
2124
2149
|
blurAmount: blurAmount,
|
|
2125
2150
|
mode: mode,
|
|
2126
2151
|
id: filterId,
|
|
2127
|
-
displacementScale:
|
|
2128
|
-
aberrationIntensity:
|
|
2152
|
+
displacementScale: toSafeNumber(displacementScale),
|
|
2153
|
+
aberrationIntensity: toSafeNumber(aberrationIntensity),
|
|
2129
2154
|
shaderMapUrl: shaderMapUrl
|
|
2130
2155
|
}), jsx("div", {
|
|
2131
2156
|
className: ATOMIX_GLASS.FILTER_OVERLAY_CLASS,
|
|
@@ -2147,8 +2172,12 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
2147
2172
|
});
|
|
2148
2173
|
}));
|
|
2149
2174
|
|
|
2150
|
-
|
|
2151
|
-
|
|
2175
|
+
/**
|
|
2176
|
+
* Internal glass surface that owns backdrop-filter, SVG distortion, and content.
|
|
2177
|
+
*
|
|
2178
|
+
* Layout and stacking styles are applied via the `style` prop from the parent.
|
|
2179
|
+
* The root wrapper supplies CSS custom properties only.
|
|
2180
|
+
*/ AtomixGlassContainer.displayName = "AtomixGlassContainer";
|
|
2152
2181
|
|
|
2153
2182
|
// Singleton instance
|
|
2154
2183
|
const globalMouseTracker = new
|
|
@@ -2263,28 +2292,32 @@ class {
|
|
|
2263
2292
|
*/ getSubscriberCount() {
|
|
2264
2293
|
return this.listeners.size;
|
|
2265
2294
|
}
|
|
2266
|
-
}, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
|
|
2295
|
+
}, {BORDER: BORDER, CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, BORDER_GRADIENT = BORDER.GRADIENT, WHITE = CONSTANTS$2.PALETTE.WHITE, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
|
|
2267
2296
|
if (!wrapperElement && !containerElement) return;
|
|
2268
2297
|
if (!validateGlassSize(params.glassSize)) return;
|
|
2269
|
-
const {mouseOffset: mouseOffset, globalMousePosition: globalMousePosition, glassSize: glassSize, isHovered: isHovered, isActive: isActive, isOverLight: isOverLight, baseOverLightConfig: baseOverLightConfig, effectiveBorderRadius: effectiveBorderRadius, effectiveWithoutEffects: effectiveWithoutEffects, effectiveReducedMotion: effectiveReducedMotion, elasticity: elasticity, elasticTranslation: elasticTranslation, elasticVelocity: elasticVelocity, mouseVelocity: mouseVelocity, directionalScale: directionalScale, scaleBase: scaleBase, onClick: onClick, withLiquidBlur: withLiquidBlur, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION,
|
|
2298
|
+
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 = {
|
|
2270
2299
|
opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
|
|
2271
2300
|
contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
|
|
2272
2301
|
brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
|
|
2273
2302
|
shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
|
|
2274
2303
|
borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence)),
|
|
2275
2304
|
saturationBoost: baseOverLightConfig.saturationBoost
|
|
2276
|
-
}, scaleX = directionalScale.x * scaleBase, scaleY = directionalScale.y * scaleBase, transformStyle = effectiveWithoutEffects ? `scale(${scaleBase})` : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) scaleX(${scaleX}) scaleY(${scaleY})`,
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
x
|
|
2282
|
-
|
|
2283
|
-
}
|
|
2305
|
+
}, scaleX = directionalScale.x * scaleBase, scaleY = directionalScale.y * scaleBase, transformStyle = effectiveWithoutEffects ? `scale(${scaleBase})` : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) scaleX(${scaleX}) scaleY(${scaleY})`, tensionFactor =
|
|
2306
|
+
/**
|
|
2307
|
+
* Computes tension factor from elastic translation magnitude (0–1).
|
|
2308
|
+
*/
|
|
2309
|
+
function(elasticTranslation) {
|
|
2310
|
+
const magnitude = Math.hypot(elasticTranslation.x, elasticTranslation.y);
|
|
2311
|
+
return smoothstep(magnitude / 80);
|
|
2312
|
+
}
|
|
2313
|
+
/**
|
|
2314
|
+
* Updates the styles of the AtomixGlass wrapper and container elements imperatively
|
|
2315
|
+
* to avoid React re-renders on mouse movement.
|
|
2316
|
+
*/ (elasticTranslation), lightingContrast = Math.min(1.8, overLightConfig.contrast + .2 * tensionFactor), lightingBrightness = Math.min(1.2, overLightConfig.brightness + .1 * tensionFactor);
|
|
2284
2317
|
// Calculate mouse influence
|
|
2285
2318
|
// Update Wrapper Styles (glassVars)
|
|
2286
2319
|
if (wrapperElement) {
|
|
2287
|
-
const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT,
|
|
2320
|
+
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 = {
|
|
2288
2321
|
hover1: {
|
|
2289
2322
|
x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1,
|
|
2290
2323
|
y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1
|
|
@@ -2301,28 +2334,55 @@ class {
|
|
|
2301
2334
|
x: GRADIENT.CENTER_POSITION + mx * GRADIENT.BASE_LAYER_MULTIPLIER,
|
|
2302
2335
|
y: GRADIENT.CENTER_POSITION + my * GRADIENT.BASE_LAYER_MULTIPLIER
|
|
2303
2336
|
}, opacityValues = {
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2337
|
+
// hover-1: ambient highlight glow — present on hover and during press
|
|
2338
|
+
hover1: isHovered || isActive ? 1 : 0,
|
|
2339
|
+
// hover-2: press depth shadow — only fires on active (mousedown)
|
|
2340
|
+
hover2: isActive ? 1 : 0,
|
|
2341
|
+
// hover-3: global soft-light surface shift — half-strength on hover, full on press
|
|
2342
|
+
hover3: isActive ? 1 : isHovered ? .55 : 0,
|
|
2343
|
+
// Dark chrome: faint smoky tint; over-light keeps stronger fill
|
|
2344
|
+
base: isOverLight ? overLightConfig.opacity : .14,
|
|
2345
|
+
over: isOverLight ? 1.1 * overLightConfig.opacity : .1
|
|
2309
2346
|
}, style = wrapperElement.style;
|
|
2310
2347
|
style.setProperty("--atomix-glass-transform", transformStyle || "none");
|
|
2311
2348
|
// Parallax for content (liquid refraction feel)
|
|
2312
2349
|
const parallaxFactor = .38 + .12 * tensionFactor;
|
|
2313
2350
|
style.setProperty("--atomix-glass-child-parallax", `translate(${elasticTranslation.x * -parallaxFactor}px, ${elasticTranslation.y * -parallaxFactor}px)`),
|
|
2314
|
-
style.setProperty("--atomix-glass-contrast", lightingContrast.toString()), style.setProperty("--atomix-glass-brightness", lightingBrightness.toString())
|
|
2351
|
+
style.setProperty("--atomix-glass-contrast", lightingContrast.toString()), style.setProperty("--atomix-glass-brightness", lightingBrightness.toString());
|
|
2315
2352
|
// ── Chromatic Rim Lighting ──────────────────────────────────────
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2353
|
+
const borderVars = ATOMIX_GLASS.BORDER.GRADIENT_CSS_VARS;
|
|
2354
|
+
if (borderAnimated && !effectiveWithoutEffects) {
|
|
2355
|
+
const borderCssVars =
|
|
2356
|
+
/**
|
|
2357
|
+
* Builds animated chromatic rim CSS variables for border layers 1 and 2.
|
|
2358
|
+
* When empty, SCSS static conic/linear fallbacks apply.
|
|
2359
|
+
*/
|
|
2360
|
+
function(params) {
|
|
2361
|
+
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%)`;
|
|
2362
|
+
return {
|
|
2363
|
+
[BORDER.GRADIENT_CSS_VARS.GRADIENT_1]: gradient1,
|
|
2364
|
+
[BORDER.GRADIENT_CSS_VARS.GRADIENT_2]: gradient2
|
|
2365
|
+
};
|
|
2366
|
+
}({
|
|
2367
|
+
mouseOffset: mouseOffset,
|
|
2368
|
+
mouseVelocity: mouseVelocity,
|
|
2369
|
+
elasticVelocity: elasticVelocity,
|
|
2370
|
+
borderOpacity: overLightConfig.borderOpacity,
|
|
2371
|
+
opacityMultiplier: borderOpacityMultiplier,
|
|
2372
|
+
tensionFactor: tensionFactor
|
|
2373
|
+
});
|
|
2374
|
+
style.setProperty(borderVars.GRADIENT_1, borderCssVars[borderVars.GRADIENT_1] ?? ""),
|
|
2375
|
+
style.setProperty(borderVars.GRADIENT_2, borderCssVars[borderVars.GRADIENT_2] ?? "");
|
|
2376
|
+
} else style.removeProperty(borderVars.GRADIENT_1), style.removeProperty(borderVars.GRADIENT_2);
|
|
2377
|
+
// Hover gradients — cursor-relative radial positions for realistic light tracking.
|
|
2378
|
+
// hover-1: white overlay highlight following cursor (works on both dark + light)
|
|
2379
|
+
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%)`),
|
|
2380
|
+
// hover-2: press depth — darkens at cursor with multiply blend, isOverLight uses stronger black
|
|
2381
|
+
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%)`),
|
|
2382
|
+
// hover-3: full-surface soft-light tint; linear gradient angled with cursor X
|
|
2383
|
+
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%)`),
|
|
2384
|
+
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%)`),
|
|
2385
|
+
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%)`),
|
|
2326
2386
|
// Opacities
|
|
2327
2387
|
style.setProperty("--atomix-glass-hover-1-opacity", opacityValues.hover1.toString()),
|
|
2328
2388
|
style.setProperty("--atomix-glass-hover-2-opacity", opacityValues.hover2.toString()),
|
|
@@ -2359,21 +2419,17 @@ class {
|
|
|
2359
2419
|
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})`;
|
|
2360
2420
|
// Container variables
|
|
2361
2421
|
const style = containerElement.style;
|
|
2362
|
-
style.setProperty("--atomix-glass-container-
|
|
2422
|
+
style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
|
|
2363
2423
|
style.setProperty("--atomix-glass-container-backdrop", backdropFilterString),
|
|
2364
2424
|
// Shadows
|
|
2365
|
-
style.setProperty("--atomix-glass-container-shadow", isOverLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${(.
|
|
2425
|
+
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),
|
|
2366
2426
|
style.setProperty("--atomix-glass-container-shadow-opacity", effectiveWithoutEffects ? "0" : "1"),
|
|
2367
2427
|
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"),
|
|
2368
2428
|
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)"),
|
|
2369
|
-
style.setProperty("--atomix-glass-container-box-shadow", isOverLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "
|
|
2429
|
+
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)");
|
|
2370
2430
|
}
|
|
2371
2431
|
};
|
|
2372
2432
|
|
|
2373
|
-
/**
|
|
2374
|
-
* Updates the styles of the AtomixGlass wrapper and container elements imperatively
|
|
2375
|
-
* to avoid React re-renders on mouse movement.
|
|
2376
|
-
*/
|
|
2377
2433
|
/**
|
|
2378
2434
|
* Animation System for AtomixGlass Component
|
|
2379
2435
|
*
|
|
@@ -2518,12 +2574,38 @@ const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new Weak
|
|
|
2518
2574
|
* Composable hook for AtomixGlass component logic
|
|
2519
2575
|
* Manages all state, calculations, and event handlers
|
|
2520
2576
|
*/
|
|
2521
|
-
function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef: wrapperRef, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, onClick: onClick, debugBorderRadius: debugBorderRadius = !1, debugOverLight: debugOverLight = !1, children: children, blurAmount: blurAmount, saturation: saturation,
|
|
2577
|
+
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:
|
|
2522
2578
|
// Default priority
|
|
2523
2579
|
// Phase 1: Animation System Props
|
|
2524
2580
|
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}) {
|
|
2525
2581
|
// State
|
|
2526
|
-
const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1),
|
|
2582
|
+
const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), resolvedBorder = useMemo((() =>
|
|
2583
|
+
/**
|
|
2584
|
+
* Resolves `border` and legacy `withBorder` into a single configuration object.
|
|
2585
|
+
*/
|
|
2586
|
+
function(border, withBorder) {
|
|
2587
|
+
const legacyDefault = withBorder ?? !0;
|
|
2588
|
+
return void 0 === border ? {
|
|
2589
|
+
enabled: legacyDefault,
|
|
2590
|
+
width: BORDER.DEFAULT_WIDTH,
|
|
2591
|
+
opacityMultiplier: 1,
|
|
2592
|
+
animated: !0
|
|
2593
|
+
} : "boolean" == typeof border ? {
|
|
2594
|
+
enabled: border,
|
|
2595
|
+
width: BORDER.DEFAULT_WIDTH,
|
|
2596
|
+
opacityMultiplier: 1,
|
|
2597
|
+
animated: !0
|
|
2598
|
+
} : {
|
|
2599
|
+
enabled: border.enabled ?? legacyDefault,
|
|
2600
|
+
width: (value = border.width, void 0 === value ? BORDER.DEFAULT_WIDTH : "number" == typeof value ? `${value}px` : value),
|
|
2601
|
+
opacityMultiplier: border.opacity ?? 1,
|
|
2602
|
+
animated: !1 !== border.animated
|
|
2603
|
+
};
|
|
2604
|
+
/**
|
|
2605
|
+
* Formats border width for CSS custom properties.
|
|
2606
|
+
*/
|
|
2607
|
+
var value;
|
|
2608
|
+
}(border, withBorder)), [ border, withBorder ]), cachedRectRef = useRef(null), internalGlobalMousePositionRef = useRef({
|
|
2527
2609
|
x: 0,
|
|
2528
2610
|
y: 0
|
|
2529
2611
|
}), internalMouseOffsetRef = useRef({
|
|
@@ -2818,21 +2900,22 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
2818
2900
|
isOverLight: isOverLight,
|
|
2819
2901
|
threshold: .7,
|
|
2820
2902
|
opacity: isOverLight ? Math.min(.6, Math.max(.2, .5 * hoverIntensity * activeIntensity)) : 0,
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
shadowIntensity: .9,
|
|
2826
|
-
borderOpacity: .
|
|
2903
|
+
// Dark UI (Apple Music): neutral contrast + slight brightness lift
|
|
2904
|
+
contrast: isOverLight ? 1.4 : 1.02,
|
|
2905
|
+
brightness: isOverLight ? .9 : 1.02,
|
|
2906
|
+
saturationBoost: isOverLight ? 1.3 : 1,
|
|
2907
|
+
shadowIntensity: isOverLight ? .9 : 1,
|
|
2908
|
+
borderOpacity: isOverLight ? ATOMIX_GLASS.BORDER.OVER_LIGHT.opacity : ATOMIX_GLASS.BORDER.DARK.opacity
|
|
2827
2909
|
};
|
|
2828
2910
|
if ("object" == typeof overLight && null !== overLight) {
|
|
2829
|
-
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 = {
|
|
2911
|
+
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 = {
|
|
2830
2912
|
...baseConfig,
|
|
2831
2913
|
threshold: validatedThreshold,
|
|
2832
2914
|
opacity: validatedOpacity * hoverIntensity * activeIntensity,
|
|
2833
2915
|
contrast: validatedContrast,
|
|
2834
2916
|
brightness: validatedBrightness,
|
|
2835
|
-
saturationBoost: validatedSaturationBoost
|
|
2917
|
+
saturationBoost: validatedSaturationBoost,
|
|
2918
|
+
borderOpacity: validatedBorderOpacity
|
|
2836
2919
|
};
|
|
2837
2920
|
return "undefined" == typeof process || process.env, finalConfig;
|
|
2838
2921
|
}
|
|
@@ -2930,12 +3013,13 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
2930
3013
|
withLiquidBlur: withLiquidBlur,
|
|
2931
3014
|
blurAmount: blurAmount,
|
|
2932
3015
|
saturation: saturation,
|
|
2933
|
-
|
|
2934
|
-
|
|
3016
|
+
isFixedOrSticky: isFixedOrSticky,
|
|
3017
|
+
borderAnimated: resolvedBorder.animated,
|
|
3018
|
+
borderOpacityMultiplier: resolvedBorder.opacityMultiplier
|
|
2935
3019
|
}), 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);
|
|
2936
3020
|
};
|
|
2937
3021
|
lerpRafRef.current = requestAnimationFrame(tick);
|
|
2938
|
-
}), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation,
|
|
3022
|
+
}), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, isFixedOrSticky, resolvedBorder.animated, resolvedBorder.opacityMultiplier, stopLerpLoop ]), handleGlobalMousePosition = useCallback((globalPos => {
|
|
2939
3023
|
if (externalGlobalMousePosition && externalMouseOffset) return;
|
|
2940
3024
|
if (effectiveWithoutEffects) return;
|
|
2941
3025
|
const container = mouseContainer?.current || glassRef.current;
|
|
@@ -2999,9 +3083,10 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
2999
3083
|
withLiquidBlur: withLiquidBlur,
|
|
3000
3084
|
blurAmount: blurAmount,
|
|
3001
3085
|
saturation: saturation,
|
|
3002
|
-
|
|
3086
|
+
borderAnimated: resolvedBorder.animated,
|
|
3087
|
+
borderOpacityMultiplier: resolvedBorder.opacityMultiplier
|
|
3003
3088
|
});
|
|
3004
|
-
}), [ isHovered, isActive, glassSize, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation,
|
|
3089
|
+
}), [ isHovered, isActive, glassSize, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation, resolvedBorder.animated, resolvedBorder.opacityMultiplier, onClick ]);
|
|
3005
3090
|
// Event handlers
|
|
3006
3091
|
const handleMouseEnter = useCallback((() => setIsHovered(!0)), []), handleMouseLeave = useCallback((() => setIsHovered(!1)), []), handleMouseDown = useCallback((() => setIsActive(!0)), []), handleMouseUp = useCallback((() => setIsActive(!1)), []), handleKeyDown = useCallback((e => {
|
|
3007
3092
|
!onClick || "Enter" !== e.key && " " !== e.key || (e.preventDefault(), onClick());
|
|
@@ -3021,6 +3106,7 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
3021
3106
|
mouseOffset: mouseOffset,
|
|
3022
3107
|
// This is now static (refs or props) unless prop changes
|
|
3023
3108
|
overLightConfig: overLightConfig,
|
|
3109
|
+
resolvedBorder: resolvedBorder,
|
|
3024
3110
|
transformStyle: transformStyle,
|
|
3025
3111
|
getShaderTime: getShaderTime,
|
|
3026
3112
|
applyTimeBasedDistortion: applyTimeBasedDistortion,
|
|
@@ -3171,148 +3257,6 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
3171
3257
|
/**
|
|
3172
3258
|
* Get GPU memory info if available (Chrome DevTools only)
|
|
3173
3259
|
*/
|
|
3174
|
-
/** Map an FPS value to a semantic color token string. */
|
|
3175
|
-
const getQualityColor = quality => {
|
|
3176
|
-
switch (quality) {
|
|
3177
|
-
case "high":
|
|
3178
|
-
return "var(--atomix-color-success, #4ade80)";
|
|
3179
|
-
|
|
3180
|
-
case "medium":
|
|
3181
|
-
return "var(--atomix-color-warning, #fbbf24)";
|
|
3182
|
-
|
|
3183
|
-
case "low":
|
|
3184
|
-
return "var(--atomix-color-danger, #ef4444)";
|
|
3185
|
-
|
|
3186
|
-
default:
|
|
3187
|
-
return "#9ca3af";
|
|
3188
|
-
}
|
|
3189
|
-
}, getFpsLabel = fps => fps >= 58 ? "Optimal" : fps >= 45 ? "Warning" : "Critical";
|
|
3190
|
-
|
|
3191
|
-
/** Map a quality level string to a semantic color token string. */
|
|
3192
|
-
// Inject keyframes once
|
|
3193
|
-
if ("undefined" != typeof document) {
|
|
3194
|
-
const styleId = "perf-dashboard-keyframes";
|
|
3195
|
-
if (!document.getElementById(styleId)) {
|
|
3196
|
-
const styleEl = document.createElement("style");
|
|
3197
|
-
styleEl.id = styleId, styleEl.textContent = "\n@keyframes perf-dashboard-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n}\n",
|
|
3198
|
-
document.head.appendChild(styleEl);
|
|
3199
|
-
}
|
|
3200
|
-
}
|
|
3201
|
-
|
|
3202
|
-
/**
|
|
3203
|
-
* PerformanceDashboard - Real-time performance monitoring overlay.
|
|
3204
|
-
*
|
|
3205
|
-
* Displays FPS, frame time, quality level, GPU memory, and auto-scaling status.
|
|
3206
|
-
* Rendered only when `debugPerformance={true}` on the parent `AtomixGlass`.
|
|
3207
|
-
*/ const PerformanceDashboard = memo((({metrics: metrics, isVisible: isVisible = !0, onClose: onClose}) => {
|
|
3208
|
-
if (!isVisible) return null;
|
|
3209
|
-
const fpsColor = (fps = metrics.fps) >= 58 ? "var(--atomix-color-success, #4ade80)" : fps >= 45 ? "var(--atomix-color-warning, #fbbf24)" : "var(--atomix-color-danger, #ef4444)";
|
|
3210
|
-
var fps;
|
|
3211
|
-
const isCritical = metrics.fps < 45;
|
|
3212
|
-
return jsxs("div", {
|
|
3213
|
-
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",
|
|
3214
|
-
style: {
|
|
3215
|
-
zIndex: 9999,
|
|
3216
|
-
minWidth: "12.5rem",
|
|
3217
|
-
// 200px
|
|
3218
|
-
backgroundColor: "rgba(17, 24, 39, 0.95)",
|
|
3219
|
-
backdropFilter: "blur(8px)",
|
|
3220
|
-
transition: "opacity 0.3s ease"
|
|
3221
|
-
},
|
|
3222
|
-
children: [ jsxs("div", {
|
|
3223
|
-
className: "u-flex u-items-center u-justify-between u-mb-2 u-pb-2 u-border-b u-border-white-alpha-10",
|
|
3224
|
-
children: [ jsx("span", {
|
|
3225
|
-
className: "u-text-sm u-font-bold u-text-white",
|
|
3226
|
-
children: "Performance Monitor"
|
|
3227
|
-
}), onClose && jsx("button", {
|
|
3228
|
-
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",
|
|
3229
|
-
onClick: onClose,
|
|
3230
|
-
"aria-label": "Close performance dashboard",
|
|
3231
|
-
style: {
|
|
3232
|
-
transition: "color 0.2s ease"
|
|
3233
|
-
},
|
|
3234
|
-
children: "×"
|
|
3235
|
-
}) ]
|
|
3236
|
-
}), jsxs("div", {
|
|
3237
|
-
className: "u-flex u-items-center u-justify-between u-mb-1-5",
|
|
3238
|
-
children: [ jsx("span", {
|
|
3239
|
-
className: "u-text-gray-400 u-me-3",
|
|
3240
|
-
children: "FPS"
|
|
3241
|
-
}), jsx("span", {
|
|
3242
|
-
className: "u-font-bold",
|
|
3243
|
-
style: {
|
|
3244
|
-
color: fpsColor
|
|
3245
|
-
},
|
|
3246
|
-
children: Math.round(metrics.fps)
|
|
3247
|
-
}) ]
|
|
3248
|
-
}), jsxs("div", {
|
|
3249
|
-
className: "u-flex u-items-center u-justify-between u-mb-1-5",
|
|
3250
|
-
children: [ jsx("span", {
|
|
3251
|
-
className: "u-text-gray-400 u-me-3",
|
|
3252
|
-
children: "Frame Time"
|
|
3253
|
-
}), jsxs("span", {
|
|
3254
|
-
className: "u-font-bold",
|
|
3255
|
-
children: [ metrics.frameTime.toFixed(2), "ms" ]
|
|
3256
|
-
}) ]
|
|
3257
|
-
}), jsxs("div", {
|
|
3258
|
-
className: "u-flex u-items-center u-justify-between u-mb-1-5",
|
|
3259
|
-
children: [ jsx("span", {
|
|
3260
|
-
className: "u-text-gray-400 u-me-3",
|
|
3261
|
-
children: "Quality"
|
|
3262
|
-
}), jsx("span", {
|
|
3263
|
-
className: "u-font-bold u-text-uppercase",
|
|
3264
|
-
style: {
|
|
3265
|
-
fontSize: "0.6875rem",
|
|
3266
|
-
// 11px
|
|
3267
|
-
color: getQualityColor(metrics.qualityLevel)
|
|
3268
|
-
},
|
|
3269
|
-
children: metrics.qualityLevel
|
|
3270
|
-
}) ]
|
|
3271
|
-
}), metrics.gpuMemory && jsxs("div", {
|
|
3272
|
-
className: "u-flex u-items-center u-justify-between u-mb-1-5",
|
|
3273
|
-
children: [ jsx("span", {
|
|
3274
|
-
className: "u-text-gray-400 u-me-3",
|
|
3275
|
-
children: "GPU Memory"
|
|
3276
|
-
}), jsxs("span", {
|
|
3277
|
-
className: "u-font-bold",
|
|
3278
|
-
children: [ "~", Math.round(metrics.gpuMemory / 1024), "MB" ]
|
|
3279
|
-
}) ]
|
|
3280
|
-
}), metrics.isAutoScaling && jsx("div", {
|
|
3281
|
-
className: "u-mt-2 u-pt-2 u-border-t u-border-white-alpha-10 u-text-center",
|
|
3282
|
-
style: {
|
|
3283
|
-
fontSize: "0.625rem",
|
|
3284
|
-
// 10px
|
|
3285
|
-
color: "#6b7280"
|
|
3286
|
-
},
|
|
3287
|
-
children: "Auto-scaling active"
|
|
3288
|
-
}), jsxs("div", {
|
|
3289
|
-
className: "u-flex u-items-center u-gap-2 u-mt-2 u-pt-2 u-border-t u-border-white-alpha-10",
|
|
3290
|
-
children: [ jsx("div", {
|
|
3291
|
-
className: "u-rounded-full",
|
|
3292
|
-
style: {
|
|
3293
|
-
width: "0.5rem",
|
|
3294
|
-
height: "0.5rem",
|
|
3295
|
-
flexShrink: 0,
|
|
3296
|
-
backgroundColor: fpsColor,
|
|
3297
|
-
...isCritical && {
|
|
3298
|
-
animation: "perf-dashboard-pulse 1s infinite"
|
|
3299
|
-
}
|
|
3300
|
-
}
|
|
3301
|
-
}), jsx("span", {
|
|
3302
|
-
className: "u-text-xs",
|
|
3303
|
-
style: {
|
|
3304
|
-
fontSize: "0.625rem",
|
|
3305
|
-
// 10px
|
|
3306
|
-
color: fpsColor
|
|
3307
|
-
},
|
|
3308
|
-
children: getFpsLabel(metrics.fps)
|
|
3309
|
-
}) ]
|
|
3310
|
-
}) ]
|
|
3311
|
-
});
|
|
3312
|
-
}));
|
|
3313
|
-
|
|
3314
|
-
PerformanceDashboard.displayName = "PerformanceDashboard";
|
|
3315
|
-
|
|
3316
3260
|
/**
|
|
3317
3261
|
* Mobile optimization presets
|
|
3318
3262
|
*
|
|
@@ -3432,18 +3376,13 @@ const PERFORMANCE_PRESET = {
|
|
|
3432
3376
|
saturation: 70
|
|
3433
3377
|
}
|
|
3434
3378
|
}
|
|
3435
|
-
}, 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 = "",
|
|
3436
|
-
const glassRef = useRef(null), contentRef = useRef(null), internalWrapperRef = useRef(null), mergedRef =
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
}));
|
|
3443
|
-
};
|
|
3444
|
-
}
|
|
3445
|
-
// Internal implementation with forwardRef
|
|
3446
|
-
(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({
|
|
3379
|
+
}, 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) {
|
|
3380
|
+
const glassRef = useRef(null), contentRef = useRef(null), internalWrapperRef = useRef(null), mergedRef = useForkRef(ref, internalWrapperRef), {zIndex: customZIndex, ...restStyle} = style, isFixedOrSticky = (explicit = propsIsFixedOrSticky,
|
|
3381
|
+
position = restStyle.position, Boolean(explicit || "fixed" === position || "sticky" === position));
|
|
3382
|
+
var explicit, position;
|
|
3383
|
+
/**
|
|
3384
|
+
* Extracts layout-related properties from a React `CSSProperties` object.
|
|
3385
|
+
*/ 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({
|
|
3447
3386
|
glassRef: glassRef,
|
|
3448
3387
|
contentRef: contentRef,
|
|
3449
3388
|
wrapperRef: internalWrapperRef,
|
|
@@ -3463,10 +3402,11 @@ const PERFORMANCE_PRESET = {
|
|
|
3463
3402
|
blurAmount: blurAmount,
|
|
3464
3403
|
saturation: saturation,
|
|
3465
3404
|
withLiquidBlur: withLiquidBlur,
|
|
3466
|
-
|
|
3405
|
+
border: border,
|
|
3406
|
+
withBorder: withBorder,
|
|
3407
|
+
debugBorderRadius: debugBorderRadius,
|
|
3467
3408
|
style: style,
|
|
3468
3409
|
isFixedOrSticky: isFixedOrSticky,
|
|
3469
|
-
// Phase 1: Animation System props
|
|
3470
3410
|
withTimeAnimation: withTimeAnimation,
|
|
3471
3411
|
animationSpeed: animationSpeed,
|
|
3472
3412
|
withMultiLayerDistortion: withMultiLayerDistortion,
|
|
@@ -3475,8 +3415,7 @@ const PERFORMANCE_PRESET = {
|
|
|
3475
3415
|
distortionGain: distortionGain,
|
|
3476
3416
|
distortionQuality: distortionQuality
|
|
3477
3417
|
});
|
|
3478
|
-
|
|
3479
|
-
!
|
|
3418
|
+
(
|
|
3480
3419
|
/**
|
|
3481
3420
|
* Responsive Glass Parameters Hook
|
|
3482
3421
|
*
|
|
@@ -3631,7 +3570,7 @@ const PERFORMANCE_PRESET = {
|
|
|
3631
3570
|
}), [ enabled ]), useCallback((() => {
|
|
3632
3571
|
calculateParams();
|
|
3633
3572
|
}), [ calculateParams ]);
|
|
3634
|
-
}({
|
|
3573
|
+
})({
|
|
3635
3574
|
baseParams: {
|
|
3636
3575
|
...useMemo((() =>
|
|
3637
3576
|
/**
|
|
@@ -3665,9 +3604,7 @@ const PERFORMANCE_PRESET = {
|
|
|
3665
3604
|
breakpoints: MOBILE_OPTIMIZED_BREAKPOINTS,
|
|
3666
3605
|
enabled: !disableResponsiveBreakpoints && "undefined" != typeof window,
|
|
3667
3606
|
debug: !1
|
|
3668
|
-
})
|
|
3669
|
-
// Performance monitoring - tracks FPS, frame time, memory usage
|
|
3670
|
-
const {metrics: performanceMetrics, toggleMonitoring: toggleMonitoring} =
|
|
3607
|
+
}),
|
|
3671
3608
|
/**
|
|
3672
3609
|
* Performance Monitor Hook
|
|
3673
3610
|
*
|
|
@@ -3702,7 +3639,13 @@ const PERFORMANCE_PRESET = {
|
|
|
3702
3639
|
timestamp: 0,
|
|
3703
3640
|
isAutoScaling: !0,
|
|
3704
3641
|
lowFpsCount: 0
|
|
3705
|
-
}), [manualOverride, setManualOverride] = useState(!1), [isEnabled, setIsEnabled] = useState(enabled)
|
|
3642
|
+
}), [manualOverride, setManualOverride] = useState(!1), [isEnabled, setIsEnabled] = useState(enabled);
|
|
3643
|
+
// Sync external `enabled` prop changes into internal state
|
|
3644
|
+
useEffect((() => {
|
|
3645
|
+
setIsEnabled(enabled ?? !0);
|
|
3646
|
+
}), [ enabled ]);
|
|
3647
|
+
// Refs for frame tracking
|
|
3648
|
+
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 => {
|
|
3706
3649
|
setMetrics((prev => ({
|
|
3707
3650
|
...prev,
|
|
3708
3651
|
...newMetrics,
|
|
@@ -3822,191 +3765,214 @@ const PERFORMANCE_PRESET = {
|
|
|
3822
3765
|
/**
|
|
3823
3766
|
* Reset to auto-scaling mode
|
|
3824
3767
|
*/ var fps, currentQuality;
|
|
3825
|
-
|
|
3826
|
-
metrics: metrics,
|
|
3827
|
-
recommendedQuality: (fps = metrics.fps, currentQuality = metrics.qualityLevel, fps >= 58 ? "high" : fps >= 45 ? "high" === currentQuality ? "high" : "medium" : "low"),
|
|
3828
|
-
isUnderperforming: metrics.fps < minFps,
|
|
3829
|
-
setQualityLevel: setQualityLevel,
|
|
3830
|
-
resetAutoScaling: resetAutoScaling,
|
|
3831
|
-
toggleMonitoring: toggleMonitoring
|
|
3832
|
-
};
|
|
3768
|
+
fps = metrics.fps, currentQuality = metrics.qualityLevel, metrics.fps;
|
|
3833
3769
|
}({
|
|
3834
3770
|
enabled: debugPerformance,
|
|
3835
|
-
// Enable when debugPerformance is true
|
|
3836
3771
|
debug: !1,
|
|
3837
3772
|
showOverlay: !1
|
|
3838
3773
|
});
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
}), [ debugPerformance ]);
|
|
3844
|
-
// Re-run when debugPerformance changes
|
|
3845
|
-
const isOverLight = useMemo((() => overLightConfig.isOverLight), [ overLightConfig.isOverLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, rootLayoutStyle = useMemo((() => {
|
|
3846
|
-
if (!isFixedOrSticky) return {};
|
|
3847
|
-
const {position: p, top: t, left: l, right: r, bottom: b} = restStyle;
|
|
3848
|
-
return {
|
|
3849
|
-
...p && {
|
|
3850
|
-
position: p
|
|
3851
|
-
},
|
|
3852
|
-
...void 0 !== t && {
|
|
3853
|
-
top: t
|
|
3854
|
-
},
|
|
3855
|
-
...void 0 !== l && {
|
|
3856
|
-
left: l
|
|
3857
|
-
},
|
|
3858
|
-
...void 0 !== r && {
|
|
3859
|
-
right: r
|
|
3860
|
-
},
|
|
3861
|
-
...void 0 !== b && {
|
|
3862
|
-
bottom: b
|
|
3863
|
-
}
|
|
3864
|
-
};
|
|
3865
|
-
}), [ isFixedOrSticky, restStyle ]);
|
|
3866
|
-
// Calculate base style with transforms
|
|
3867
|
-
// When layout is hoisted to the root, strip those props from the container
|
|
3868
|
-
useMemo((() => {
|
|
3869
|
-
if (isFixedOrSticky) {
|
|
3870
|
-
const {position: _p, top: _t, left: _l, right: _r, bottom: _b, ...visualStyle} = restStyle;
|
|
3871
|
-
return {
|
|
3872
|
-
...visualStyle
|
|
3873
|
-
};
|
|
3774
|
+
const isOverLight = useMemo((() => overLightConfig.isOverLight), [ overLightConfig.isOverLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, containerStyle = useMemo((() => ({
|
|
3775
|
+
...restStyle,
|
|
3776
|
+
...void 0 !== customZIndex && {
|
|
3777
|
+
zIndex: customZIndex
|
|
3874
3778
|
}
|
|
3779
|
+
})), [ 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((() =>
|
|
3780
|
+
/**
|
|
3781
|
+
* Returns the internal positioning context for effect layers relative to the root.
|
|
3782
|
+
*/
|
|
3783
|
+
function(isFixedOrSticky, restStyle) {
|
|
3875
3784
|
return {
|
|
3876
|
-
|
|
3785
|
+
position: isFixedOrSticky ? "absolute" : restStyle.position || "absolute",
|
|
3786
|
+
top: 0,
|
|
3787
|
+
left: 0,
|
|
3788
|
+
right: "auto",
|
|
3789
|
+
bottom: "auto"
|
|
3877
3790
|
};
|
|
3878
|
-
}
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
})), [ isFixedOrSticky, restStyle.position, restStyle.top, restStyle.left, restStyle.right, restStyle.bottom ]), adjustedSize = useMemo((() => {
|
|
3887
|
-
// Keep a reference to positionStyles to avoid unused-variable lint,
|
|
3888
|
-
// but sizing is driven by explicit width/height or measured size.
|
|
3889
|
-
positionStyles.position;
|
|
3890
|
-
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;
|
|
3791
|
+
}
|
|
3792
|
+
/**
|
|
3793
|
+
* Computes `--atomix-glass-width` and `--atomix-glass-height` values.
|
|
3794
|
+
*
|
|
3795
|
+
* Fixed/sticky elements prefer explicit dimensions or measured size; in-flow
|
|
3796
|
+
* elements default to `100%`.
|
|
3797
|
+
*/ (isFixedOrSticky, restStyle)), [ isFixedOrSticky, restStyle ]), adjustedSize = useMemo((() => function(options) {
|
|
3798
|
+
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;
|
|
3891
3799
|
return {
|
|
3892
3800
|
width: resolveLength(effectiveWidth, glassSize.width),
|
|
3893
3801
|
height: resolveLength(effectiveHeight, glassSize.height)
|
|
3894
3802
|
};
|
|
3895
|
-
}
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3803
|
+
}
|
|
3804
|
+
/**
|
|
3805
|
+
* Builds the CSS custom properties applied to the root `.c-atomix-glass` element.
|
|
3806
|
+
*
|
|
3807
|
+
* These variables drive layer geometry, transforms, and stacking offsets. They
|
|
3808
|
+
* must not include layout properties that would interfere with backdrop-filter.
|
|
3809
|
+
*/ ({
|
|
3810
|
+
width: width,
|
|
3811
|
+
height: height,
|
|
3812
|
+
restStyle: restStyle,
|
|
3813
|
+
glassSize: glassSize,
|
|
3814
|
+
isFixedOrSticky: isFixedOrSticky
|
|
3815
|
+
})), [ width, height, restStyle, glassSize, isFixedOrSticky ]), glassVars = useMemo((() => function(input) {
|
|
3816
|
+
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 =
|
|
3817
|
+
/**
|
|
3818
|
+
* Resolves the `--atomix-glass-position` value for decorative layers.
|
|
3819
|
+
*
|
|
3820
|
+
* Fixed/sticky layers use the same positioning mode as the container; in-flow
|
|
3821
|
+
* layers default to the internal absolute positioning context.
|
|
3822
|
+
*/
|
|
3823
|
+
function(isFixedOrSticky, positionStyles, restStyle) {
|
|
3824
|
+
return isFixedOrSticky ? `${function(style) {
|
|
3825
|
+
const {position: position, top: top, left: left, right: right, bottom: bottom, inset: inset} = style;
|
|
3826
|
+
return {
|
|
3827
|
+
...null != position && {
|
|
3828
|
+
position: position
|
|
3829
|
+
},
|
|
3830
|
+
...void 0 !== top && {
|
|
3831
|
+
top: top
|
|
3832
|
+
},
|
|
3833
|
+
...void 0 !== left && {
|
|
3834
|
+
left: left
|
|
3835
|
+
},
|
|
3836
|
+
...void 0 !== right && {
|
|
3837
|
+
right: right
|
|
3838
|
+
},
|
|
3839
|
+
...void 0 !== bottom && {
|
|
3840
|
+
bottom: bottom
|
|
3841
|
+
},
|
|
3842
|
+
...void 0 !== inset && {
|
|
3843
|
+
inset: inset
|
|
3844
|
+
}
|
|
3845
|
+
};
|
|
3846
|
+
}
|
|
3847
|
+
/**
|
|
3848
|
+
* Resolves inset custom properties for decorative layers (hover, borders, backgrounds).
|
|
3849
|
+
*
|
|
3850
|
+
* For fixed and sticky modes, insets mirror the container so sibling layers remain
|
|
3851
|
+
* aligned. In-flow modes, insets follow the consumer `style` when a non-default
|
|
3852
|
+
* `position` is provided.
|
|
3853
|
+
*/ (restStyle).position ?? restStyle.position ?? "fixed"}` : `${positionStyles.position}`;
|
|
3854
|
+
}(isFixedOrSticky, positionStyles, restStyle), layerInsets = function(isFixedOrSticky, restStyle) {
|
|
3855
|
+
if (isFixedOrSticky) return {
|
|
3856
|
+
top: formatGlassInsetValue(restStyle.top, 0),
|
|
3857
|
+
left: formatGlassInsetValue(restStyle.left, 0),
|
|
3858
|
+
right: formatGlassInsetValue(restStyle.right, "auto"),
|
|
3859
|
+
bottom: formatGlassInsetValue(restStyle.bottom, "auto")
|
|
3860
|
+
};
|
|
3861
|
+
const position = restStyle.position;
|
|
3862
|
+
return null != position && "static" !== position && "relative" !== position ? {
|
|
3863
|
+
top: formatGlassInsetValue(restStyle.top, 0),
|
|
3864
|
+
left: formatGlassInsetValue(restStyle.left, 0),
|
|
3865
|
+
right: formatGlassInsetValue(restStyle.right, "auto"),
|
|
3866
|
+
bottom: formatGlassInsetValue(restStyle.bottom, "auto")
|
|
3867
|
+
} : {
|
|
3868
|
+
top: "0px",
|
|
3869
|
+
left: "0px",
|
|
3870
|
+
right: "auto",
|
|
3871
|
+
bottom: "auto"
|
|
3872
|
+
};
|
|
3873
|
+
}(isFixedOrSticky, restStyle);
|
|
3933
3874
|
return {
|
|
3934
3875
|
...void 0 !== customZIndex && {
|
|
3935
3876
|
"--atomix-glass-base-z-index": customZIndex
|
|
3936
3877
|
},
|
|
3937
3878
|
"--atomix-glass-radius": `${effectiveBorderRadius}px`,
|
|
3938
3879
|
"--atomix-glass-transform": transformStyle || "none",
|
|
3939
|
-
"--atomix-glass-container-position":
|
|
3940
|
-
"--atomix-glass-position":
|
|
3941
|
-
"--atomix-glass-top":
|
|
3942
|
-
"--atomix-glass-left":
|
|
3943
|
-
"--atomix-glass-right":
|
|
3944
|
-
"--atomix-glass-bottom":
|
|
3880
|
+
"--atomix-glass-container-position": layerPosition,
|
|
3881
|
+
"--atomix-glass-position": layerPosition,
|
|
3882
|
+
"--atomix-glass-top": layerInsets.top,
|
|
3883
|
+
"--atomix-glass-left": layerInsets.left,
|
|
3884
|
+
"--atomix-glass-right": layerInsets.right,
|
|
3885
|
+
"--atomix-glass-bottom": layerInsets.bottom,
|
|
3945
3886
|
"--atomix-glass-width": adjustedSize.width,
|
|
3946
3887
|
"--atomix-glass-height": adjustedSize.height,
|
|
3947
|
-
|
|
3948
|
-
"--atomix-glass-
|
|
3949
|
-
"--atomix-glass-
|
|
3950
|
-
|
|
3951
|
-
"--atomix-glass-
|
|
3952
|
-
"--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}%)`,
|
|
3953
|
-
"--atomix-glass-hover-2-opacity": opacityValues.hover2,
|
|
3954
|
-
"--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}%)`,
|
|
3955
|
-
"--atomix-glass-hover-3-opacity": opacityValues.hover3,
|
|
3956
|
-
"--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}%)`,
|
|
3957
|
-
"--atomix-glass-base-opacity": opacityValues.base,
|
|
3958
|
-
"--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})`,
|
|
3959
|
-
"--atomix-glass-overlay-opacity": opacityValues.over,
|
|
3960
|
-
"--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})`,
|
|
3961
|
-
"--atomix-glass-overlay-highlight-opacity": opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER,
|
|
3962
|
-
"--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}%)`
|
|
3888
|
+
// Aliases maintained for backward compatibility and consumer overrides.
|
|
3889
|
+
"--atomix-glass-container-width": adjustedSize.width,
|
|
3890
|
+
"--atomix-glass-container-height": adjustedSize.height,
|
|
3891
|
+
[ATOMIX_GLASS.BORDER.WIDTH_CSS_VAR]: borderWidth,
|
|
3892
|
+
"--atomix-glass-blend-mode": isOverLight ? "multiply" : "overlay"
|
|
3963
3893
|
};
|
|
3964
|
-
}
|
|
3965
|
-
|
|
3894
|
+
}
|
|
3895
|
+
/**
|
|
3896
|
+
* Applies mode-specific multipliers and accessibility overrides to container effects.
|
|
3897
|
+
*/ ({
|
|
3898
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
3899
|
+
transformStyle: transformStyle,
|
|
3900
|
+
adjustedSize: adjustedSize,
|
|
3901
|
+
isOverLight: isOverLight,
|
|
3902
|
+
customZIndex: customZIndex,
|
|
3903
|
+
isFixedOrSticky: isFixedOrSticky,
|
|
3904
|
+
positionStyles: positionStyles,
|
|
3905
|
+
restStyle: restStyle,
|
|
3906
|
+
borderWidth: resolvedBorder.width
|
|
3907
|
+
})), [ effectiveBorderRadius, transformStyle, adjustedSize, isOverLight, customZIndex, isFixedOrSticky, positionStyles, restStyle, resolvedBorder.width ]), containerEffects = useMemo((() => function(options) {
|
|
3908
|
+
const {MULTIPLIERS: MULTIPLIERS, SATURATION: SATURATION} = ATOMIX_GLASS.CONSTANTS, zeroMouse = {
|
|
3909
|
+
x: 0,
|
|
3910
|
+
y: 0
|
|
3911
|
+
}, resolveSaturation = () => options.effectiveHighContrast ? SATURATION.HIGH_CONTRAST : options.isOverLight ? options.saturation * options.saturationBoost : options.saturation;
|
|
3912
|
+
if (options.effectiveWithoutEffects) return {
|
|
3913
|
+
displacementScale: 0,
|
|
3914
|
+
blurAmount: 0,
|
|
3915
|
+
saturation: resolveSaturation(),
|
|
3916
|
+
aberrationIntensity: 0,
|
|
3917
|
+
mouseOffset: zeroMouse,
|
|
3918
|
+
globalMousePosition: zeroMouse
|
|
3919
|
+
};
|
|
3920
|
+
let resolvedDisplacement = options.displacementScale;
|
|
3921
|
+
"shader" === options.mode ? resolvedDisplacement *= MULTIPLIERS.SHADER_DISPLACEMENT : options.isOverLight && (resolvedDisplacement *= MULTIPLIERS.OVER_LIGHT_DISPLACEMENT);
|
|
3922
|
+
let resolvedAberration = options.aberrationIntensity;
|
|
3923
|
+
return "shader" === options.mode && (resolvedAberration *= MULTIPLIERS.SHADER_ABERRATION),
|
|
3924
|
+
{
|
|
3925
|
+
displacementScale: resolvedDisplacement,
|
|
3926
|
+
blurAmount: options.blurAmount,
|
|
3927
|
+
saturation: resolveSaturation(),
|
|
3928
|
+
aberrationIntensity: resolvedAberration,
|
|
3929
|
+
mouseOffset: options.mouseOffset,
|
|
3930
|
+
globalMousePosition: options.globalMousePosition
|
|
3931
|
+
};
|
|
3932
|
+
}({
|
|
3933
|
+
displacementScale: displacementScale,
|
|
3934
|
+
blurAmount: blurAmount,
|
|
3935
|
+
saturation: saturation,
|
|
3936
|
+
aberrationIntensity: aberrationIntensity,
|
|
3937
|
+
mode: mode,
|
|
3938
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
3939
|
+
effectiveHighContrast: effectiveHighContrast,
|
|
3940
|
+
isOverLight: isOverLight,
|
|
3941
|
+
saturationBoost: overLightConfig.saturationBoost,
|
|
3942
|
+
mouseOffset: mouseOffset,
|
|
3943
|
+
globalMousePosition: globalMousePosition
|
|
3944
|
+
})), [ displacementScale, blurAmount, saturation, aberrationIntensity, mode, effectiveWithoutEffects, effectiveHighContrast, isOverLight, overLightConfig.saturationBoost, mouseOffset, globalMousePosition ]), renderBackgroundLayer = layerType => jsx("div", {
|
|
3945
|
+
"aria-hidden": "true",
|
|
3946
|
+
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)
|
|
3966
3947
|
});
|
|
3967
|
-
|
|
3968
|
-
// When root is fixed/sticky, internal layers use absolute (relative to root)
|
|
3969
|
-
return jsxs("div", {
|
|
3948
|
+
return jsxs("div", {
|
|
3970
3949
|
...rest,
|
|
3971
3950
|
ref: mergedRef,
|
|
3972
3951
|
className: componentClassName,
|
|
3973
|
-
style:
|
|
3974
|
-
...glassVars
|
|
3975
|
-
},
|
|
3952
|
+
style: glassVars,
|
|
3976
3953
|
role: role || (onClick ? "button" : void 0),
|
|
3977
3954
|
tabIndex: onClick ? tabIndex ?? 0 : tabIndex,
|
|
3978
3955
|
"aria-label": ariaLabel,
|
|
3979
3956
|
"aria-describedby": ariaDescribedBy,
|
|
3980
3957
|
"aria-disabled": !(!onClick || !effectiveWithoutEffects) || !onClick && void 0,
|
|
3981
|
-
"aria-pressed": onClick ? isActive : void 0,
|
|
3982
3958
|
onKeyDown: onClick ? handleKeyDown : void 0,
|
|
3983
3959
|
children: [ jsx(AtomixGlassContainer, {
|
|
3984
3960
|
ref: glassRef,
|
|
3985
3961
|
contentRef: contentRef,
|
|
3986
3962
|
className: className,
|
|
3987
|
-
style:
|
|
3988
|
-
...restStyle
|
|
3989
|
-
},
|
|
3963
|
+
style: containerStyle,
|
|
3990
3964
|
borderRadius: effectiveBorderRadius,
|
|
3991
|
-
displacementScale:
|
|
3992
|
-
blurAmount:
|
|
3993
|
-
saturation:
|
|
3994
|
-
aberrationIntensity:
|
|
3965
|
+
displacementScale: containerEffects.displacementScale,
|
|
3966
|
+
blurAmount: containerEffects.blurAmount,
|
|
3967
|
+
saturation: containerEffects.saturation,
|
|
3968
|
+
aberrationIntensity: containerEffects.aberrationIntensity,
|
|
3995
3969
|
glassSize: glassSize,
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
x: 0,
|
|
3999
|
-
y: 0
|
|
4000
|
-
} : mouseOffset,
|
|
4001
|
-
globalMousePosition: effectiveWithoutEffects ? {
|
|
4002
|
-
x: 0,
|
|
4003
|
-
y: 0
|
|
4004
|
-
} : globalMousePosition,
|
|
3970
|
+
mouseOffset: containerEffects.mouseOffset,
|
|
3971
|
+
globalMousePosition: containerEffects.globalMousePosition,
|
|
4005
3972
|
onMouseEnter: handleMouseEnter,
|
|
4006
3973
|
onMouseLeave: handleMouseLeave,
|
|
4007
3974
|
onMouseDown: handleMouseDown,
|
|
4008
3975
|
onMouseUp: handleMouseUp,
|
|
4009
|
-
isHovered: isHovered,
|
|
4010
3976
|
isActive: isActive,
|
|
4011
3977
|
overLight: isOverLight,
|
|
4012
3978
|
overLightConfig: {
|
|
@@ -4022,7 +3988,6 @@ const PERFORMANCE_PRESET = {
|
|
|
4022
3988
|
shaderVariant: shaderVariant,
|
|
4023
3989
|
withLiquidBlur: withLiquidBlur,
|
|
4024
3990
|
isFixedOrSticky: isFixedOrSticky,
|
|
4025
|
-
// Phase 1: Animation System props
|
|
4026
3991
|
shaderTime: getShaderTime(),
|
|
4027
3992
|
withTimeAnimation: withTimeAnimation,
|
|
4028
3993
|
animationSpeed: animationSpeed,
|
|
@@ -4034,32 +3999,39 @@ const PERFORMANCE_PRESET = {
|
|
|
4034
3999
|
children: children
|
|
4035
4000
|
}), Boolean(onClick) && jsxs(Fragment, {
|
|
4036
4001
|
children: [ jsx("div", {
|
|
4002
|
+
"aria-hidden": "true",
|
|
4037
4003
|
className: ATOMIX_GLASS.HOVER_1_CLASS
|
|
4038
4004
|
}), jsx("div", {
|
|
4005
|
+
"aria-hidden": "true",
|
|
4039
4006
|
className: ATOMIX_GLASS.HOVER_2_CLASS
|
|
4040
4007
|
}), jsx("div", {
|
|
4008
|
+
"aria-hidden": "true",
|
|
4041
4009
|
className: ATOMIX_GLASS.HOVER_3_CLASS
|
|
4042
4010
|
}) ]
|
|
4043
|
-
}),
|
|
4011
|
+
}), [ "dark", "black" ].map((layerType => jsx(React.Fragment, {
|
|
4012
|
+
children: renderBackgroundLayer(layerType)
|
|
4013
|
+
}, layerType))), shouldRenderOverLightLayers && jsxs(Fragment, {
|
|
4044
4014
|
children: [ jsx("div", {
|
|
4015
|
+
"aria-hidden": "true",
|
|
4045
4016
|
className: ATOMIX_GLASS.BASE_LAYER_CLASS
|
|
4046
4017
|
}), jsx("div", {
|
|
4018
|
+
"aria-hidden": "true",
|
|
4047
4019
|
className: ATOMIX_GLASS.OVERLAY_LAYER_CLASS
|
|
4048
4020
|
}), jsx("div", {
|
|
4021
|
+
"aria-hidden": "true",
|
|
4049
4022
|
className: ATOMIX_GLASS.OVERLAY_HIGHLIGHT_CLASS
|
|
4050
4023
|
}) ]
|
|
4051
|
-
}),
|
|
4024
|
+
}), resolvedBorder.enabled && jsxs(Fragment, {
|
|
4052
4025
|
children: [ jsx("span", {
|
|
4026
|
+
"aria-hidden": "true",
|
|
4053
4027
|
className: ATOMIX_GLASS.BORDER_BACKDROP_CLASS
|
|
4054
4028
|
}), jsx("span", {
|
|
4029
|
+
"aria-hidden": "true",
|
|
4055
4030
|
className: ATOMIX_GLASS.BORDER_1_CLASS
|
|
4056
4031
|
}), jsx("span", {
|
|
4032
|
+
"aria-hidden": "true",
|
|
4057
4033
|
className: ATOMIX_GLASS.BORDER_2_CLASS
|
|
4058
4034
|
}) ]
|
|
4059
|
-
}), debugPerformance && performanceMetrics && jsx(PerformanceDashboard, {
|
|
4060
|
-
metrics: performanceMetrics,
|
|
4061
|
-
isVisible: !0,
|
|
4062
|
-
onClose: () => {}
|
|
4063
4035
|
}) ]
|
|
4064
4036
|
});
|
|
4065
4037
|
}));
|
|
@@ -4069,10 +4041,7 @@ const PERFORMANCE_PRESET = {
|
|
|
4069
4041
|
* Default preset for most mobile devices
|
|
4070
4042
|
*/ AtomixGlassInner.displayName = "AtomixGlass";
|
|
4071
4043
|
|
|
4072
|
-
/**
|
|
4073
|
-
* AtomixGlass - wrapped with React.memo to prevent unnecessary re-renders.
|
|
4074
|
-
* Ref is forwarded to the root `<div>` element.
|
|
4075
|
-
*/
|
|
4044
|
+
/** Memoized public export. Ref targets the root `.c-atomix-glass` wrapper. */
|
|
4076
4045
|
const AtomixGlass = memo(AtomixGlassInner), ChartContext = createContext(null), Chart = memo( forwardRef((({children: children, type: type = "line", size: size = "md", variant: variant = "primary", title: title, subtitle: subtitle, loading: loading = !1, error: error, className: className = "", "aria-label": ariaLabel, onFullscreen: onFullscreen, onExport: onExport, onRefresh: onRefresh, showToolbar: showToolbar = !1, enableFullscreen: enableFullscreen = !1, enableExport: enableExport = !1, enableRefresh: enableRefresh = !1, exportFormats: exportFormats = [ "png", "svg", "csv" ], datasets: datasets, config: config,
|
|
4077
4046
|
// Destructure non-DOM props to prevent passing to DOM element
|
|
4078
4047
|
toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, customToolbarGroups: customToolbarGroups, data: data, showLegend: showLegend, interactive: interactive, fullscreen: fullscreen, onDataPointClick: onDataPointClick, onLegendItemClick: onLegendItemClick, glass: glass, ...props}, ref) => {
|