@shohojdhara/atomix 0.4.4 → 0.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/atomix.css +50 -11
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +1 -1
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.js +184 -189
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +4 -4
- package/dist/core.js +194 -199
- package/dist/core.js.map +1 -1
- package/dist/forms.js +184 -189
- package/dist/forms.js.map +1 -1
- package/dist/heavy.js +189 -194
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +44 -47
- package/dist/index.esm.js +496 -613
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +528 -631
- 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/AtomixGlass/AtomixGlass.tsx +60 -39
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +8 -42
- package/src/components/AtomixGlass/glass-utils.ts +27 -14
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +19 -21
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +1162 -515
- package/src/components/AtomixGlass/stories/shared-components.tsx +11 -3
- package/src/components/Breadcrumb/Breadcrumb.tsx +5 -5
- package/src/components/Breadcrumb/BreadcrumbCompound.test.tsx +2 -2
- package/src/components/Button/Button.tsx +6 -6
- package/src/components/Card/Card.tsx +3 -3
- package/src/components/Dropdown/Dropdown.tsx +5 -3
- package/src/components/Footer/Footer.tsx +124 -166
- package/src/components/Footer/FooterLink.tsx +16 -19
- package/src/components/Footer/FooterSection.tsx +40 -39
- package/src/components/Footer/FooterSocialLink.tsx +59 -58
- package/src/components/Footer/README.md +1 -1
- package/src/components/Hero/Hero.tsx +72 -142
- package/src/components/Navigation/Menu/MegaMenu.tsx +17 -12
- package/src/components/Navigation/Menu/Menu.tsx +49 -24
- package/src/components/Navigation/Nav/NavItem.tsx +5 -3
- package/src/components/Navigation/Navbar/Navbar.tsx +13 -5
- package/src/components/Navigation/SideMenu/SideMenu.tsx +2 -2
- package/src/components/Navigation/SideMenu/SideMenuItem.tsx +4 -4
- package/src/components/Slider/Slider.tsx +7 -4
- package/src/lib/composables/index.ts +1 -2
- package/src/lib/composables/useAtomixGlass.ts +246 -222
- package/src/lib/composables/useAtomixGlassStyles.ts +46 -23
- package/src/lib/composables/useFooter.ts +117 -20
- package/src/lib/composables/useSlider.ts +3 -1
- package/src/lib/constants/components.ts +3 -1
- package/src/lib/types/components.ts +44 -12
- package/src/styles/06-components/_components.atomix-glass.scss +72 -14
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +0 -222
- package/src/lib/composables/atomix-glass/useGlassBackgroundDetection.ts +0 -329
- package/src/lib/composables/atomix-glass/useGlassCornerRadius.ts +0 -82
- package/src/lib/composables/atomix-glass/useGlassMouseTracking.ts +0 -153
- package/src/lib/composables/atomix-glass/useGlassOverLight.ts +0 -198
- package/src/lib/composables/atomix-glass/useGlassState.ts +0 -112
- package/src/lib/composables/atomix-glass/useGlassTransforms.ts +0 -160
- package/src/lib/composables/glass-styles.ts +0 -302
- package/src/lib/composables/useGlassContainer.ts +0 -177
package/dist/heavy.js
CHANGED
|
@@ -76,7 +76,9 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
|
|
|
76
76
|
ENABLE_OVER_LIGHT_LAYERS: !0
|
|
77
77
|
},
|
|
78
78
|
CONSTANTS: {
|
|
79
|
-
ACTIVATION_ZONE:
|
|
79
|
+
ACTIVATION_ZONE: 350,
|
|
80
|
+
LERP_FACTOR: .08,
|
|
81
|
+
SMOOTHSTEP_POWER: 2.5,
|
|
80
82
|
MIN_BLUR: .1,
|
|
81
83
|
MOUSE_INFLUENCE_DIVISOR: 100,
|
|
82
84
|
EDGE_FADE_PIXELS: 2,
|
|
@@ -312,7 +314,7 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
|
|
|
312
314
|
// Silently handle errors
|
|
313
315
|
}
|
|
314
316
|
return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
315
|
-
}, getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
|
|
317
|
+
}, lerp = (a, b, t) => a + (b - a) * t, softClamp = (value, max) => max <= 0 ? 0 : max * (1 - Math.exp(-value / max)), getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
|
|
316
318
|
switch (mode) {
|
|
317
319
|
case "standard":
|
|
318
320
|
return displacementMap;
|
|
@@ -483,7 +485,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
483
485
|
}, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isHovered: isHovered = !1, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {}, borderRadius: borderRadius = 0, padding: padding = "0 0", glassSize: glassSize = {
|
|
484
486
|
width: 0,
|
|
485
487
|
height: 0
|
|
486
|
-
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1,
|
|
488
|
+
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, contentRef: contentRef}, ref) => {
|
|
487
489
|
// Generate a stable, deterministic ID for SSR compatibility
|
|
488
490
|
// Use a module-level counter that's consistent across server and client
|
|
489
491
|
const filterId = useMemo((() => "atomix-glass-filter-" + ++idCounter), []), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null);
|
|
@@ -668,21 +670,12 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
668
670
|
onClick: onClick,
|
|
669
671
|
children: jsxs("div", {
|
|
670
672
|
className: ATOMIX_GLASS.INNER_CLASS,
|
|
671
|
-
style: {
|
|
672
|
-
padding: "var(--atomix-glass-container-padding)",
|
|
673
|
-
boxShadow: "var(--atomix-glass-container-box-shadow)"
|
|
674
|
-
},
|
|
675
673
|
onMouseEnter: onMouseEnter,
|
|
676
674
|
onMouseLeave: onMouseLeave,
|
|
677
675
|
onMouseDown: onMouseDown,
|
|
678
676
|
onMouseUp: onMouseUp,
|
|
679
677
|
children: [ jsxs("div", {
|
|
680
678
|
className: ATOMIX_GLASS.FILTER_CLASS,
|
|
681
|
-
style: {
|
|
682
|
-
zIndex: 1,
|
|
683
|
-
position: "absolute",
|
|
684
|
-
inset: 0
|
|
685
|
-
},
|
|
686
679
|
children: [ jsx(GlassFilter, {
|
|
687
680
|
blurAmount: blurAmount,
|
|
688
681
|
mode: mode,
|
|
@@ -697,28 +690,14 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
697
690
|
},
|
|
698
691
|
className: ATOMIX_GLASS.FILTER_OVERLAY_CLASS,
|
|
699
692
|
style: {
|
|
700
|
-
filter: `url(#${filterId})
|
|
701
|
-
backdropFilter: "var(--atomix-glass-container-backdrop)",
|
|
702
|
-
borderRadius: "var(--atomix-glass-container-radius)"
|
|
693
|
+
filter: `url(#${filterId})`
|
|
703
694
|
}
|
|
704
695
|
}), jsx("div", {
|
|
705
|
-
className: ATOMIX_GLASS.FILTER_SHADOW_CLASS
|
|
706
|
-
style: {
|
|
707
|
-
boxShadow: "var(--atomix-glass-container-shadow)",
|
|
708
|
-
opacity: "var(--atomix-glass-container-shadow-opacity)",
|
|
709
|
-
background: "var(--atomix-glass-container-bg)",
|
|
710
|
-
borderRadius: "var(--atomix-glass-container-radius)"
|
|
711
|
-
}
|
|
696
|
+
className: ATOMIX_GLASS.FILTER_SHADOW_CLASS
|
|
712
697
|
}) ]
|
|
713
698
|
}), jsx("div", {
|
|
714
699
|
ref: contentRef,
|
|
715
700
|
className: ATOMIX_GLASS.CONTENT_CLASS,
|
|
716
|
-
style: {
|
|
717
|
-
position: "relative",
|
|
718
|
-
textShadow: "var(--atomix-glass-container-text-shadow)",
|
|
719
|
-
// Ensure content is always above the filter layer (zIndex 1)
|
|
720
|
-
zIndex: elasticity > 0 ? 100 : 2
|
|
721
|
-
},
|
|
722
701
|
children: children
|
|
723
702
|
}) ]
|
|
724
703
|
})
|
|
@@ -822,31 +801,39 @@ class {
|
|
|
822
801
|
saturationBoost: baseOverLightConfig.saturationBoost
|
|
823
802
|
};
|
|
824
803
|
// Calculate mouse influence
|
|
825
|
-
|
|
826
|
-
let elasticTranslation = {
|
|
804
|
+
let computedDirectionalScale = directionalScale, elasticTranslation = {
|
|
827
805
|
x: 0,
|
|
828
806
|
y: 0
|
|
829
807
|
};
|
|
830
|
-
|
|
808
|
+
// Calculate elastic translation and directional scale
|
|
809
|
+
if (!effectiveWithoutEffects && wrapperElement) {
|
|
831
810
|
const rect = wrapperElement.getBoundingClientRect(), center = calculateElementCenter(rect);
|
|
832
|
-
//
|
|
833
|
-
let fadeInFactor = 0;
|
|
811
|
+
// Mouse presence and edge distance logic
|
|
834
812
|
if (globalMousePosition.x && globalMousePosition.y && validateGlassSize(glassSize)) {
|
|
835
|
-
const edgeDistanceX = Math.max(0, Math.abs(
|
|
813
|
+
const deltaX = globalMousePosition.x - center.x, deltaY = globalMousePosition.y - center.y, edgeDistanceX = Math.max(0, Math.abs(deltaX) - glassSize.width / 2), edgeDistanceY = Math.max(0, Math.abs(deltaY) - glassSize.height / 2), edgeDistance = calculateDistance({
|
|
836
814
|
x: edgeDistanceX,
|
|
837
815
|
y: edgeDistanceY
|
|
838
816
|
}, {
|
|
839
817
|
x: 0,
|
|
840
818
|
y: 0
|
|
841
|
-
})
|
|
842
|
-
|
|
819
|
+
}), rawT = edgeDistance > ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE ? 0 : 1 - edgeDistance / ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE, fadeInFactor = (t => {
|
|
820
|
+
const clamped = Math.max(0, Math.min(1, t));
|
|
821
|
+
return clamped * clamped * (3 - 2 * clamped);
|
|
822
|
+
})(rawT);
|
|
823
|
+
// Directional scale
|
|
824
|
+
if (elasticTranslation = {
|
|
825
|
+
x: deltaX * elasticity * .1 * fadeInFactor,
|
|
826
|
+
y: deltaY * elasticity * .1 * fadeInFactor
|
|
827
|
+
}, !isOverLight && edgeDistance <= ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE) {
|
|
828
|
+
const centerDistance = calculateDistance(globalMousePosition, center);
|
|
829
|
+
if (centerDistance > 0) {
|
|
830
|
+
const normalizedX = deltaX / centerDistance, normalizedY = deltaY / centerDistance, stretchIntensity = Math.min(centerDistance / 300, 1) * elasticity * rawT, scaleX = 1 + Math.abs(normalizedX) * stretchIntensity * .3 - Math.abs(normalizedY) * stretchIntensity * .15, scaleY = 1 + Math.abs(normalizedY) * stretchIntensity * .3 - Math.abs(normalizedX) * stretchIntensity * .15, softScaleX = 1 - softClamp(Math.max(0, 1 - scaleX), .2), softScaleY = 1 - softClamp(Math.max(0, 1 - scaleY), .2);
|
|
831
|
+
computedDirectionalScale = `scaleX(${Math.max(.85, softScaleX)}) scaleY(${Math.max(.85, softScaleY)})`;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
843
834
|
}
|
|
844
|
-
elasticTranslation = {
|
|
845
|
-
x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
|
|
846
|
-
y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
|
|
847
|
-
};
|
|
848
835
|
}
|
|
849
|
-
const transformStyle = effectiveWithoutEffects ? isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)" : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) ${isActive && Boolean(onClick) ? "scale(0.96)" :
|
|
836
|
+
const transformStyle = effectiveWithoutEffects ? isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)" : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) ${isActive && Boolean(onClick) ? "scale(0.96)" : computedDirectionalScale}`;
|
|
850
837
|
// Update Wrapper Styles (glassVars)
|
|
851
838
|
if (wrapperElement) {
|
|
852
839
|
const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT, borderGradientAngle = GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER, borderStop1 = Math.max(GRADIENT.BORDER_STOP_1.MIN, GRADIENT.BORDER_STOP_1.BASE + my * GRADIENT.BORDER_STOP_1.MULTIPLIER), borderStop2 = Math.min(GRADIENT.BORDER_STOP_2.MAX, GRADIENT.BORDER_STOP_2.BASE + my * GRADIENT.BORDER_STOP_2.MULTIPLIER), borderOpacities = [ GRADIENT.BORDER_OPACITY.BASE_1 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW, GRADIENT.BORDER_OPACITY.BASE_2 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH, GRADIENT.BORDER_OPACITY.BASE_3 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW, GRADIENT.BORDER_OPACITY.BASE_4 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH ], configBorderOpacity = overLightConfig.borderOpacity, whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE, blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK, hoverPositions = {
|
|
@@ -953,7 +940,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
953
940
|
}), internalMouseOffsetRef = useRef({
|
|
954
941
|
x: 0,
|
|
955
942
|
y: 0
|
|
956
|
-
}),
|
|
943
|
+
}), targetMouseOffsetRef = useRef({
|
|
944
|
+
x: 0,
|
|
945
|
+
y: 0
|
|
946
|
+
}), targetGlobalMousePositionRef = useRef({
|
|
947
|
+
x: 0,
|
|
948
|
+
y: 0
|
|
949
|
+
}), lerpRafRef = useRef(null), lerpActiveRef = useRef(!1), [dynamicBorderRadius, setDynamicCornerRadius] = useState(CONSTANTS.DEFAULT_CORNER_RADIUS), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1), effectiveBorderRadius = useMemo((() => void 0 !== borderRadius ? Math.max(0, borderRadius) : Math.max(0, dynamicBorderRadius)), [ borderRadius, dynamicBorderRadius ]), {glassSize: glassSize} = function({glassRef: glassRef, effectiveBorderRadius: effectiveBorderRadius, cachedRectRef: cachedRectRef}) {
|
|
957
950
|
const [glassSize, setGlassSize] = useState({
|
|
958
951
|
width: 270,
|
|
959
952
|
height: 69
|
|
@@ -1050,7 +1043,23 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
1050
1043
|
const timeoutId = setTimeout(extractRadius, 100);
|
|
1051
1044
|
return () => clearTimeout(timeoutId);
|
|
1052
1045
|
}), [ children, debugBorderRadius, contentRef ]),
|
|
1053
|
-
// Media query
|
|
1046
|
+
// Media query detection for reduced motion and high contrast
|
|
1047
|
+
useEffect((() => {
|
|
1048
|
+
if ("undefined" == typeof window || "function" != typeof window.matchMedia) return;
|
|
1049
|
+
const mediaQueryReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)"), mediaQueryHighContrast = window.matchMedia("(prefers-contrast: high)");
|
|
1050
|
+
setUserPrefersReducedMotion(mediaQueryReducedMotion.matches), setUserPrefersHighContrast(mediaQueryHighContrast.matches);
|
|
1051
|
+
const handleReducedMotionChange = e => {
|
|
1052
|
+
setUserPrefersReducedMotion(e.matches);
|
|
1053
|
+
}, handleHighContrastChange = e => {
|
|
1054
|
+
setUserPrefersHighContrast(e.matches);
|
|
1055
|
+
};
|
|
1056
|
+
return mediaQueryReducedMotion.addEventListener("change", handleReducedMotionChange),
|
|
1057
|
+
mediaQueryHighContrast.addEventListener("change", handleHighContrastChange), () => {
|
|
1058
|
+
mediaQueryReducedMotion.removeEventListener("change", handleReducedMotionChange),
|
|
1059
|
+
mediaQueryHighContrast.removeEventListener("change", handleHighContrastChange);
|
|
1060
|
+
};
|
|
1061
|
+
}), []),
|
|
1062
|
+
// Background detection for overLight auto-detect
|
|
1054
1063
|
useEffect((() => {
|
|
1055
1064
|
if (("auto" === overLight || "object" == typeof overLight && null !== overLight) && glassRef.current) {
|
|
1056
1065
|
const element = glassRef.current, cachedResult = ((parentElement, overLightConfig) => {
|
|
@@ -1150,102 +1159,36 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
1150
1159
|
}), 150);
|
|
1151
1160
|
return () => clearTimeout(timeoutId);
|
|
1152
1161
|
}
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
setUserPrefersReducedMotion(mediaQueryReducedMotion.matches), setUserPrefersHighContrast(mediaQueryHighContrast.matches);
|
|
1156
|
-
const handleReducedMotionChange = e => {
|
|
1157
|
-
setUserPrefersReducedMotion(e.matches);
|
|
1158
|
-
}, handleHighContrastChange = e => {
|
|
1159
|
-
setUserPrefersHighContrast(e.matches);
|
|
1160
|
-
};
|
|
1161
|
-
return mediaQueryReducedMotion.addEventListener ? (mediaQueryReducedMotion.addEventListener("change", handleReducedMotionChange),
|
|
1162
|
-
mediaQueryHighContrast.addEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.addListener && (mediaQueryReducedMotion.addListener(handleReducedMotionChange),
|
|
1163
|
-
mediaQueryHighContrast.addListener(handleHighContrastChange)), () => {
|
|
1164
|
-
// ignore
|
|
1165
|
-
};
|
|
1166
|
-
} catch (error) {
|
|
1167
|
-
return;
|
|
1168
|
-
}
|
|
1169
|
-
}), [ overLight, glassRef, debugOverLight ]);
|
|
1162
|
+
"boolean" == typeof overLight && setDetectedOverLight(!1);
|
|
1163
|
+
}), [ overLight, glassRef ]);
|
|
1170
1164
|
/**
|
|
1171
1165
|
* Get effective overLight value based on configuration
|
|
1172
1166
|
*/
|
|
1173
|
-
const getEffectiveOverLight = useCallback((() => "boolean" == typeof overLight ? overLight : ("auto" === overLight || "object" == typeof overLight && null !== overLight) && detectedOverLight), [ overLight, detectedOverLight ]), validateConfigValue = useCallback(((value, min, max, defaultValue) => "number" != typeof value || isNaN(value) || !isFinite(value) ? defaultValue : Math.min(max, Math.max(min, value))), []),
|
|
1174
|
-
const isOverLight = getEffectiveOverLight(), baseConfig = {
|
|
1167
|
+
const getEffectiveOverLight = useCallback((() => "boolean" == typeof overLight ? overLight : ("auto" === overLight || "object" == typeof overLight && null !== overLight) && detectedOverLight), [ overLight, detectedOverLight ]), validateConfigValue = useCallback(((value, min, max, defaultValue) => "number" != typeof value || isNaN(value) || !isFinite(value) ? defaultValue : Math.min(max, Math.max(min, value))), []), overLightConfig = useMemo((() => {
|
|
1168
|
+
const isOverLight = getEffectiveOverLight(), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1, baseConfig = {
|
|
1175
1169
|
isOverLight: isOverLight,
|
|
1176
1170
|
threshold: .7,
|
|
1177
|
-
opacity: isOverLight ? Math.min(.6, Math.max(.2, .5)) : 0,
|
|
1178
|
-
contrast: 1,
|
|
1179
|
-
|
|
1180
|
-
brightness: 1,
|
|
1181
|
-
// Base brightness
|
|
1171
|
+
opacity: isOverLight ? Math.min(.6, Math.max(.2, .5 * hoverIntensity * activeIntensity)) : 0,
|
|
1172
|
+
contrast: 1.4,
|
|
1173
|
+
brightness: .9,
|
|
1182
1174
|
saturationBoost: 1.3,
|
|
1175
|
+
// Fixed value — dynamic saturation amplifies perceived displacement
|
|
1183
1176
|
shadowIntensity: .9,
|
|
1184
1177
|
borderOpacity: .7
|
|
1185
1178
|
};
|
|
1186
1179
|
if ("object" == typeof overLight && null !== overLight) {
|
|
1187
|
-
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)
|
|
1188
|
-
return {
|
|
1180
|
+
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 = {
|
|
1189
1181
|
...baseConfig,
|
|
1190
1182
|
threshold: validatedThreshold,
|
|
1191
|
-
opacity: validatedOpacity,
|
|
1183
|
+
opacity: validatedOpacity * hoverIntensity * activeIntensity,
|
|
1192
1184
|
contrast: validatedContrast,
|
|
1193
1185
|
brightness: validatedBrightness,
|
|
1194
1186
|
saturationBoost: validatedSaturationBoost
|
|
1195
1187
|
};
|
|
1188
|
+
return "undefined" == typeof process || process.env, finalConfig;
|
|
1196
1189
|
}
|
|
1197
|
-
return baseConfig;
|
|
1198
|
-
}), [ overLight, getEffectiveOverLight, validateConfigValue ]),
|
|
1199
|
-
const mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1;
|
|
1200
|
-
return {
|
|
1201
|
-
isOverLight: baseOverLightConfig.isOverLight,
|
|
1202
|
-
threshold: baseOverLightConfig.threshold,
|
|
1203
|
-
opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
|
|
1204
|
-
contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
|
|
1205
|
-
brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
|
|
1206
|
-
saturationBoost: baseOverLightConfig.saturationBoost,
|
|
1207
|
-
shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
|
|
1208
|
-
borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence))
|
|
1209
|
-
};
|
|
1210
|
-
}), [ baseOverLightConfig, mouseOffset, isHovered, isActive ]), updateRectRef = useRef(null), calculateDirectionalScale = useCallback((() => {
|
|
1211
|
-
if (baseOverLightConfig.isOverLight) return "scale(1)";
|
|
1212
|
-
if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return "scale(1)";
|
|
1213
|
-
const rect = glassRef.current.getBoundingClientRect(), center = calculateElementCenter(rect), deltaX = globalMousePosition.x - center.x, deltaY = globalMousePosition.y - center.y, edgeDistanceX = Math.max(0, Math.abs(deltaX) - glassSize.width / 2), edgeDistanceY = Math.max(0, Math.abs(deltaY) - glassSize.height / 2), edgeDistance = calculateDistance({
|
|
1214
|
-
x: edgeDistanceX,
|
|
1215
|
-
y: edgeDistanceY
|
|
1216
|
-
}, {
|
|
1217
|
-
x: 0,
|
|
1218
|
-
y: 0
|
|
1219
|
-
});
|
|
1220
|
-
if (edgeDistance > CONSTANTS.ACTIVATION_ZONE) return "scale(1)";
|
|
1221
|
-
const fadeInFactor = 1 - edgeDistance / CONSTANTS.ACTIVATION_ZONE, centerDistance = calculateDistance(globalMousePosition, center);
|
|
1222
|
-
if (0 === centerDistance) return "scale(1)";
|
|
1223
|
-
const normalizedX = deltaX / centerDistance, normalizedY = deltaY / centerDistance, stretchIntensity = Math.min(centerDistance / 300, 1) * elasticity * fadeInFactor, scaleX = 1 + Math.abs(normalizedX) * stretchIntensity * .3 - Math.abs(normalizedY) * stretchIntensity * .15, scaleY = 1 + Math.abs(normalizedY) * stretchIntensity * .3 - Math.abs(normalizedX) * stretchIntensity * .15;
|
|
1224
|
-
return `scaleX(${Math.max(.8, scaleX)}) scaleY(${Math.max(.8, scaleY)})`;
|
|
1225
|
-
}), [ globalMousePosition, elasticity, glassSize, glassRef, baseOverLightConfig ]), calculateFadeInFactor = useCallback((() => {
|
|
1226
|
-
if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return 0;
|
|
1227
|
-
const rect = glassRef.current.getBoundingClientRect(), center = calculateElementCenter(rect), edgeDistanceX = Math.max(0, Math.abs(globalMousePosition.x - center.x) - glassSize.width / 2), edgeDistanceY = Math.max(0, Math.abs(globalMousePosition.y - center.y) - glassSize.height / 2), edgeDistance = calculateDistance({
|
|
1228
|
-
x: edgeDistanceX,
|
|
1229
|
-
y: edgeDistanceY
|
|
1230
|
-
}, {
|
|
1231
|
-
x: 0,
|
|
1232
|
-
y: 0
|
|
1233
|
-
});
|
|
1234
|
-
return edgeDistance > CONSTANTS.ACTIVATION_ZONE ? 0 : 1 - edgeDistance / CONSTANTS.ACTIVATION_ZONE;
|
|
1235
|
-
}), [ globalMousePosition, glassSize, glassRef ]), calculateElasticTranslation = useCallback((() => {
|
|
1236
|
-
if (!glassRef.current) return {
|
|
1237
|
-
x: 0,
|
|
1238
|
-
y: 0
|
|
1239
|
-
};
|
|
1240
|
-
const fadeInFactor = calculateFadeInFactor(), rect = glassRef.current.getBoundingClientRect(), center = calculateElementCenter(rect);
|
|
1241
|
-
return {
|
|
1242
|
-
x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
|
|
1243
|
-
y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
|
|
1244
|
-
};
|
|
1245
|
-
}), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = useMemo((() => effectiveWithoutEffects ? {
|
|
1246
|
-
x: 0,
|
|
1247
|
-
y: 0
|
|
1248
|
-
} : calculateElasticTranslation()), [ calculateElasticTranslation, effectiveWithoutEffects ]), directionalScale = useMemo((() => effectiveWithoutEffects ? "scale(1)" : calculateDirectionalScale()), [ calculateDirectionalScale, effectiveWithoutEffects ]), transformStyle = useMemo((() => effectiveWithoutEffects ? isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)" : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) ${isActive && Boolean(onClick) ? "scale(0.96)" : directionalScale}`), [ elasticTranslation, isActive, onClick, directionalScale, effectiveWithoutEffects ]), handleGlobalMousePosition = useCallback((globalPos => {
|
|
1190
|
+
return "undefined" == typeof process || process.env, baseConfig;
|
|
1191
|
+
}), [ overLight, getEffectiveOverLight, isHovered, isActive, validateConfigValue, debugOverLight ]), transformStyle = useMemo((() => effectiveWithoutEffects || isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)"), [ effectiveWithoutEffects, isActive, onClick ]), updateRectRef = useRef(null), handleGlobalMousePosition = useCallback((globalPos => {
|
|
1249
1192
|
if (externalGlobalMousePosition && externalMouseOffset) return;
|
|
1250
1193
|
if (effectiveWithoutEffects) return;
|
|
1251
1194
|
const container = mouseContainer?.current || glassRef.current;
|
|
@@ -1254,35 +1197,61 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
1254
1197
|
let rect = cachedRectRef.current;
|
|
1255
1198
|
if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
|
|
1256
1199
|
cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
|
|
1257
|
-
const center = calculateElementCenter(rect)
|
|
1200
|
+
const center = calculateElementCenter(rect);
|
|
1201
|
+
// Write raw target — the lerp loop will smoothly pursue it
|
|
1202
|
+
targetMouseOffsetRef.current = {
|
|
1258
1203
|
x: (globalPos.x - center.x) / rect.width * 100,
|
|
1259
1204
|
y: (globalPos.y - center.y) / rect.height * 100
|
|
1205
|
+
}, targetGlobalMousePositionRef.current = globalPos;
|
|
1206
|
+
}), [ mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects ]), startLerpLoop = useCallback((() => {
|
|
1207
|
+
if (lerpActiveRef.current) return;
|
|
1208
|
+
lerpActiveRef.current = !0;
|
|
1209
|
+
const LERP_T = CONSTANTS.LERP_FACTOR, tick = () => {
|
|
1210
|
+
if (!lerpActiveRef.current) return;
|
|
1211
|
+
const cur = internalMouseOffsetRef.current, tgt = targetMouseOffsetRef.current, dx = tgt.x - cur.x, dy = tgt.y - cur.y;
|
|
1212
|
+
// If we're close enough, snap and park
|
|
1213
|
+
if (Math.abs(dx) < .05 && Math.abs(dy) < .05) internalMouseOffsetRef.current = {
|
|
1214
|
+
...tgt
|
|
1215
|
+
}, internalGlobalMousePositionRef.current = {
|
|
1216
|
+
...targetGlobalMousePositionRef.current
|
|
1217
|
+
}; else {
|
|
1218
|
+
internalMouseOffsetRef.current = {
|
|
1219
|
+
x: lerp(cur.x, tgt.x, LERP_T),
|
|
1220
|
+
y: lerp(cur.y, tgt.y, LERP_T)
|
|
1221
|
+
};
|
|
1222
|
+
const curG = internalGlobalMousePositionRef.current, tgtG = targetGlobalMousePositionRef.current;
|
|
1223
|
+
internalGlobalMousePositionRef.current = {
|
|
1224
|
+
x: lerp(curG.x, tgtG.x, LERP_T),
|
|
1225
|
+
y: lerp(curG.y, tgtG.y, LERP_T)
|
|
1226
|
+
};
|
|
1227
|
+
}
|
|
1228
|
+
// Imperative style update with the smoothed values
|
|
1229
|
+
updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
|
|
1230
|
+
mouseOffset: internalMouseOffsetRef.current,
|
|
1231
|
+
globalMousePosition: internalGlobalMousePositionRef.current,
|
|
1232
|
+
glassSize: glassSize,
|
|
1233
|
+
isHovered: isHovered,
|
|
1234
|
+
isActive: isActive,
|
|
1235
|
+
isOverLight: overLightConfig.isOverLight,
|
|
1236
|
+
baseOverLightConfig: overLightConfig,
|
|
1237
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
1238
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
1239
|
+
effectiveReducedMotion: effectiveReducedMotion,
|
|
1240
|
+
elasticity: elasticity,
|
|
1241
|
+
directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
|
|
1242
|
+
onClick: onClick,
|
|
1243
|
+
withLiquidBlur: withLiquidBlur,
|
|
1244
|
+
blurAmount: blurAmount,
|
|
1245
|
+
saturation: saturation,
|
|
1246
|
+
padding: padding
|
|
1247
|
+
}), lerpRafRef.current = requestAnimationFrame(tick);
|
|
1260
1248
|
};
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
globalMousePosition: globalPos,
|
|
1268
|
-
glassSize: glassSize,
|
|
1269
|
-
isHovered: isHovered,
|
|
1270
|
-
isActive: isActive,
|
|
1271
|
-
isOverLight: baseOverLightConfig.isOverLight,
|
|
1272
|
-
baseOverLightConfig: baseOverLightConfig,
|
|
1273
|
-
effectiveBorderRadius: effectiveBorderRadius,
|
|
1274
|
-
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
1275
|
-
effectiveReducedMotion: effectiveReducedMotion,
|
|
1276
|
-
elasticity: elasticity,
|
|
1277
|
-
directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
|
|
1278
|
-
// Simplified directional scale for fast path
|
|
1279
|
-
onClick: onClick,
|
|
1280
|
-
withLiquidBlur: withLiquidBlur,
|
|
1281
|
-
blurAmount: blurAmount,
|
|
1282
|
-
saturation: saturation,
|
|
1283
|
-
padding: padding
|
|
1284
|
-
});
|
|
1285
|
-
}), [ mouseContainer, glassRef, wrapperRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects, glassSize, isHovered, isActive, baseOverLightConfig, effectiveBorderRadius, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding ]);
|
|
1249
|
+
// 0.08 – lower = more viscous
|
|
1250
|
+
lerpRafRef.current = requestAnimationFrame(tick);
|
|
1251
|
+
}), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding ]), stopLerpLoop = useCallback((() => {
|
|
1252
|
+
lerpActiveRef.current = !1, null !== lerpRafRef.current && (cancelAnimationFrame(lerpRafRef.current),
|
|
1253
|
+
lerpRafRef.current = null);
|
|
1254
|
+
}), []);
|
|
1286
1255
|
/**
|
|
1287
1256
|
* Validate and clamp a numeric config value
|
|
1288
1257
|
*/
|
|
@@ -1290,7 +1259,10 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
1290
1259
|
useEffect((() => {
|
|
1291
1260
|
if (externalGlobalMousePosition && externalMouseOffset) return;
|
|
1292
1261
|
if (effectiveWithoutEffects) return;
|
|
1293
|
-
const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition)
|
|
1262
|
+
const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition);
|
|
1263
|
+
// Start the lerp loop — it will smoothly chase the target
|
|
1264
|
+
startLerpLoop();
|
|
1265
|
+
const container = mouseContainer?.current || glassRef.current;
|
|
1294
1266
|
let resizeObserver = null;
|
|
1295
1267
|
return container && "undefined" != typeof ResizeObserver && (resizeObserver = new ResizeObserver((() => {
|
|
1296
1268
|
null !== updateRectRef.current && cancelAnimationFrame(updateRectRef.current), updateRectRef.current = requestAnimationFrame((() => {
|
|
@@ -1298,10 +1270,10 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
1298
1270
|
container && (cachedRectRef.current = container.getBoundingClientRect()), updateRectRef.current = null;
|
|
1299
1271
|
}));
|
|
1300
1272
|
})), resizeObserver.observe(container)), () => {
|
|
1301
|
-
unsubscribe(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
|
|
1273
|
+
unsubscribe(), stopLerpLoop(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
|
|
1302
1274
|
updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
|
|
1303
1275
|
};
|
|
1304
|
-
}), [ handleGlobalMousePosition, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects ]),
|
|
1276
|
+
}), [ handleGlobalMousePosition, startLerpLoop, stopLerpLoop, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects ]),
|
|
1305
1277
|
// Also call updateStyles on other state changes (hover, active, etc)
|
|
1306
1278
|
useEffect((() => {
|
|
1307
1279
|
updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
|
|
@@ -1310,22 +1282,22 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
1310
1282
|
glassSize: glassSize,
|
|
1311
1283
|
isHovered: isHovered,
|
|
1312
1284
|
isActive: isActive,
|
|
1313
|
-
isOverLight:
|
|
1314
|
-
baseOverLightConfig:
|
|
1285
|
+
isOverLight: overLightConfig.isOverLight,
|
|
1286
|
+
baseOverLightConfig: overLightConfig,
|
|
1315
1287
|
effectiveBorderRadius: effectiveBorderRadius,
|
|
1316
1288
|
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
1317
1289
|
effectiveReducedMotion: effectiveReducedMotion,
|
|
1318
1290
|
elasticity: elasticity,
|
|
1319
|
-
directionalScale:
|
|
1291
|
+
directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
|
|
1320
1292
|
onClick: onClick,
|
|
1321
1293
|
withLiquidBlur: withLiquidBlur,
|
|
1322
1294
|
blurAmount: blurAmount,
|
|
1323
1295
|
saturation: saturation,
|
|
1324
1296
|
padding: padding
|
|
1325
1297
|
});
|
|
1326
|
-
}), [ isHovered, isActive, glassSize,
|
|
1298
|
+
}), [ isHovered, isActive, glassSize, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation, padding, onClick ]);
|
|
1327
1299
|
// Event handlers
|
|
1328
|
-
const handleMouseEnter = useCallback((() => setIsHovered(!0)), []), handleMouseLeave = useCallback((() => setIsHovered(!1)), []), handleMouseDown = useCallback((() => setIsActive(!0)), []), handleMouseUp = useCallback((() => setIsActive(!1)), []),
|
|
1300
|
+
const handleMouseEnter = useCallback((() => setIsHovered(!0)), []), handleMouseLeave = useCallback((() => setIsHovered(!1)), []), handleMouseDown = useCallback((() => setIsActive(!0)), []), handleMouseUp = useCallback((() => setIsActive(!1)), []), handleKeyDown = useCallback((e => {
|
|
1329
1301
|
!onClick || "Enter" !== e.key && " " !== e.key || (e.preventDefault(), onClick());
|
|
1330
1302
|
}), [ onClick ]);
|
|
1331
1303
|
return {
|
|
@@ -1343,14 +1315,11 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
1343
1315
|
mouseOffset: mouseOffset,
|
|
1344
1316
|
// This is now static (refs or props) unless prop changes
|
|
1345
1317
|
overLightConfig: overLightConfig,
|
|
1346
|
-
elasticTranslation: elasticTranslation,
|
|
1347
|
-
directionalScale: directionalScale,
|
|
1348
1318
|
transformStyle: transformStyle,
|
|
1349
1319
|
handleMouseEnter: handleMouseEnter,
|
|
1350
1320
|
handleMouseLeave: handleMouseLeave,
|
|
1351
1321
|
handleMouseDown: handleMouseDown,
|
|
1352
1322
|
handleMouseUp: handleMouseUp,
|
|
1353
|
-
handleMouseMove: handleMouseMove,
|
|
1354
1323
|
handleKeyDown: handleKeyDown
|
|
1355
1324
|
};
|
|
1356
1325
|
}
|
|
@@ -1448,25 +1417,56 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
1448
1417
|
withLiquidBlur: withLiquidBlur,
|
|
1449
1418
|
padding: padding,
|
|
1450
1419
|
style: style
|
|
1451
|
-
}), isOverLight = useMemo((() => overLightConfig
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1420
|
+
}), isOverLight = useMemo((() => overLightConfig.isOverLight), [ overLightConfig.isOverLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, {zIndex: customZIndex, ...restStyle} = style, isFixedOrSticky = "fixed" === restStyle.position || "sticky" === restStyle.position, rootLayoutStyle = useMemo((() => {
|
|
1421
|
+
if (!isFixedOrSticky) return {};
|
|
1422
|
+
const {position: p, top: t, left: l, right: r, bottom: b} = restStyle;
|
|
1423
|
+
return {
|
|
1424
|
+
...p && {
|
|
1425
|
+
position: p
|
|
1426
|
+
},
|
|
1427
|
+
...void 0 !== t && {
|
|
1428
|
+
top: t
|
|
1429
|
+
},
|
|
1430
|
+
...void 0 !== l && {
|
|
1431
|
+
left: l
|
|
1432
|
+
},
|
|
1433
|
+
...void 0 !== r && {
|
|
1434
|
+
right: r
|
|
1435
|
+
},
|
|
1436
|
+
...void 0 !== b && {
|
|
1437
|
+
bottom: b
|
|
1438
|
+
}
|
|
1439
|
+
};
|
|
1440
|
+
}), [ isFixedOrSticky, restStyle ]), baseStyle = useMemo((() => {
|
|
1441
|
+
if (isFixedOrSticky) {
|
|
1442
|
+
const {position: _p, top: _t, left: _l, right: _r, bottom: _b, ...visualStyle} = restStyle;
|
|
1443
|
+
return {
|
|
1444
|
+
...visualStyle,
|
|
1445
|
+
...!effectiveWithoutEffects && {
|
|
1446
|
+
transform: transformStyle
|
|
1447
|
+
}
|
|
1448
|
+
};
|
|
1455
1449
|
}
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1450
|
+
return {
|
|
1451
|
+
...restStyle,
|
|
1452
|
+
...!effectiveWithoutEffects && {
|
|
1453
|
+
transform: transformStyle
|
|
1454
|
+
}
|
|
1455
|
+
};
|
|
1456
|
+
}), [ isFixedOrSticky, restStyle, effectiveWithoutEffects, transformStyle ]), componentClassName = [ ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`, effectiveWithoutEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`, className ].filter(Boolean).join(" "), positionStyles = useMemo((() => ({
|
|
1457
|
+
position: isFixedOrSticky ? "absolute" : restStyle.position || "absolute",
|
|
1458
|
+
top: isFixedOrSticky ? 0 : restStyle.top || 0,
|
|
1459
|
+
left: isFixedOrSticky ? 0 : restStyle.left || 0
|
|
1460
|
+
})), [ isFixedOrSticky, restStyle.position, restStyle.top, restStyle.left ]), adjustedSize = useMemo((() => {
|
|
1461
1461
|
const resolveSize = (propValue, styleValue, measuredSize) => {
|
|
1462
1462
|
const explicitSize = propValue ?? styleValue;
|
|
1463
1463
|
return void 0 !== explicitSize ? "number" == typeof explicitSize ? `${explicitSize}px` : explicitSize : "fixed" === positionStyles.position ? `${Math.max(measuredSize, 0)}px` : "100%";
|
|
1464
1464
|
};
|
|
1465
1465
|
return {
|
|
1466
|
-
width: resolveSize(width,
|
|
1467
|
-
height: resolveSize(height,
|
|
1466
|
+
width: resolveSize(width, restStyle.width, glassSize.width),
|
|
1467
|
+
height: resolveSize(height, restStyle.height, glassSize.height)
|
|
1468
1468
|
};
|
|
1469
|
-
}), [ width, height,
|
|
1469
|
+
}), [ width, height, restStyle.width, restStyle.height, positionStyles.position, glassSize.width, glassSize.height ]), gradientValues = useMemo((() => {
|
|
1470
1470
|
const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT;
|
|
1471
1471
|
return {
|
|
1472
1472
|
borderGradientAngle: GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER,
|
|
@@ -1508,6 +1508,9 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
1508
1508
|
}), [ isHovered, isActive, isOverLight, overLightConfig.opacity ]), glassVars = useMemo((() => {
|
|
1509
1509
|
const whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE, blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK, {borderGradientAngle: borderGradientAngle, borderStop1: borderStop1, borderStop2: borderStop2, borderOpacities: borderOpacities, hoverPositions: hoverPositions, basePosition: basePosition, mx: mx, my: my, absMx: absMx, absMy: absMy} = gradientValues, configBorderOpacity = overLightConfig?.borderOpacity ?? 1;
|
|
1510
1510
|
return {
|
|
1511
|
+
...void 0 !== customZIndex && {
|
|
1512
|
+
"--atomix-glass-base-z-index": customZIndex
|
|
1513
|
+
},
|
|
1511
1514
|
"--atomix-glass-radius": `${effectiveBorderRadius}px`,
|
|
1512
1515
|
"--atomix-glass-transform": transformStyle || "none",
|
|
1513
1516
|
"--atomix-glass-position": positionStyles.position,
|
|
@@ -1528,22 +1531,19 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
1528
1531
|
"--atomix-glass-base-opacity": opacityValues.base,
|
|
1529
1532
|
"--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})`,
|
|
1530
1533
|
"--atomix-glass-overlay-opacity": opacityValues.over,
|
|
1531
|
-
"--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})
|
|
1534
|
+
"--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})`,
|
|
1535
|
+
"--atomix-glass-overlay-highlight-opacity": opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER,
|
|
1536
|
+
"--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}%)`
|
|
1532
1537
|
};
|
|
1533
|
-
}), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle, positionStyles, adjustedSize, isOverLight, overLightConfig.borderOpacity ]), renderBackgroundLayer = layerType => jsx("div", {
|
|
1534
|
-
className: [ ATOMIX_GLASS.BACKGROUND_LAYER_CLASS, "dark" === layerType ? ATOMIX_GLASS.BACKGROUND_LAYER_DARK_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_BLACK_CLASS, isOverLight ? ATOMIX_GLASS.BACKGROUND_LAYER_OVER_LIGHT_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_HIDDEN_CLASS ].filter(Boolean).join(" ")
|
|
1535
|
-
style: {
|
|
1536
|
-
...positionStyles,
|
|
1537
|
-
height: adjustedSize.height,
|
|
1538
|
-
width: adjustedSize.width,
|
|
1539
|
-
borderRadius: `${effectiveBorderRadius}px`,
|
|
1540
|
-
transform: baseStyle.transform
|
|
1541
|
-
}
|
|
1538
|
+
}), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle, positionStyles, adjustedSize, isOverLight, overLightConfig.borderOpacity, customZIndex ]), renderBackgroundLayer = layerType => jsx("div", {
|
|
1539
|
+
className: [ ATOMIX_GLASS.BACKGROUND_LAYER_CLASS, "dark" === layerType ? ATOMIX_GLASS.BACKGROUND_LAYER_DARK_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_BLACK_CLASS, isOverLight ? ATOMIX_GLASS.BACKGROUND_LAYER_OVER_LIGHT_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_HIDDEN_CLASS ].filter(Boolean).join(" ")
|
|
1542
1540
|
});
|
|
1543
1541
|
return jsxs("div", {
|
|
1544
1542
|
...rest,
|
|
1545
1543
|
className: componentClassName,
|
|
1546
|
-
style:
|
|
1544
|
+
style: {
|
|
1545
|
+
...glassVars
|
|
1546
|
+
},
|
|
1547
1547
|
role: role || (onClick ? "button" : void 0),
|
|
1548
1548
|
tabIndex: onClick ? tabIndex ?? 0 : tabIndex,
|
|
1549
1549
|
"aria-label": ariaLabel,
|
|
@@ -1555,7 +1555,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
1555
1555
|
ref: glassRef,
|
|
1556
1556
|
contentRef: contentRef,
|
|
1557
1557
|
className: className,
|
|
1558
|
-
style:
|
|
1558
|
+
style: rootLayoutStyle,
|
|
1559
1559
|
borderRadius: effectiveBorderRadius,
|
|
1560
1560
|
displacementScale: effectiveWithoutEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
|
|
1561
1561
|
blurAmount: effectiveWithoutEffects ? 0 : blurAmount,
|
|
@@ -1590,7 +1590,6 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
1590
1590
|
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
1591
1591
|
effectiveReducedMotion: effectiveReducedMotion,
|
|
1592
1592
|
shaderVariant: shaderVariant,
|
|
1593
|
-
elasticity: elasticity,
|
|
1594
1593
|
withLiquidBlur: withLiquidBlur,
|
|
1595
1594
|
children: children
|
|
1596
1595
|
}), Boolean(onClick) && jsxs(Fragment, {
|
|
@@ -1607,11 +1606,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
1607
1606
|
}), jsx("div", {
|
|
1608
1607
|
className: ATOMIX_GLASS.OVERLAY_LAYER_CLASS
|
|
1609
1608
|
}), jsx("div", {
|
|
1610
|
-
className: ATOMIX_GLASS.OVERLAY_HIGHLIGHT_CLASS
|
|
1611
|
-
style: {
|
|
1612
|
-
opacity: opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER,
|
|
1613
|
-
background: `radial-gradient(circle at ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_X}% ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_Y}%, rgba(255, 255, 255, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.WHITE_OPACITY}) 0%, transparent ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.STOP}%)`
|
|
1614
|
-
}
|
|
1609
|
+
className: ATOMIX_GLASS.OVERLAY_HIGHLIGHT_CLASS
|
|
1615
1610
|
}) ]
|
|
1616
1611
|
}), withBorder && jsxs(Fragment, {
|
|
1617
1612
|
children: [ jsx("span", {
|
|
@@ -3434,7 +3429,7 @@ class ThemeNaming {
|
|
|
3434
3429
|
|
|
3435
3430
|
ThemeNaming.prefix = "atomix";
|
|
3436
3431
|
|
|
3437
|
-
const Button = React.memo( forwardRef((({label: label, children: children, onClick: onClick, variant: variant = "primary", size: size = "md", disabled: disabled = !1, loading: loading = !1, loadingText: loadingText, icon: icon, iconName: iconName, iconSize: iconSize = "sm", iconPosition: iconPosition = "start", iconOnly: iconOnly = !1, rounded: rounded = !1, fullWidth: fullWidth = !1, block: block = !1, active: active = !1, selected: selected = !1, type: type = "button", className: className = "", as: Component = "button", href: href, target: target, glass: glass, onHover: onHover, onFocus: onFocus, onBlur: onBlur, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, "aria-expanded": ariaExpanded, "aria-controls": ariaControls, tabIndex: tabIndex, style: style,
|
|
3432
|
+
const Button = React.memo( forwardRef((({label: label, children: children, onClick: onClick, variant: variant = "primary", size: size = "md", disabled: disabled = !1, loading: loading = !1, loadingText: loadingText, icon: icon, iconName: iconName, iconSize: iconSize = "sm", iconPosition: iconPosition = "start", iconOnly: iconOnly = !1, rounded: rounded = !1, fullWidth: fullWidth = !1, block: block = !1, active: active = !1, selected: selected = !1, type: type = "button", className: className = "", as: Component = "button", href: href, target: target, glass: glass, onHover: onHover, onFocus: onFocus, onBlur: onBlur, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, "aria-expanded": ariaExpanded, "aria-controls": ariaControls, tabIndex: tabIndex, style: style, linkComponent: linkComponent, ...props}, ref) => {
|
|
3438
3433
|
const isDisabled = disabled || loading, shouldRenderAsLink = Boolean(href && !isDisabled), iconElement = iconName ? jsx(Icon, {
|
|
3439
3434
|
name: iconName,
|
|
3440
3435
|
size: iconSize
|
|
@@ -3485,12 +3480,12 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
|
|
|
3485
3480
|
let content;
|
|
3486
3481
|
// Render as anchor if href is provided
|
|
3487
3482
|
if (shouldRenderAsLink)
|
|
3488
|
-
// Use custom
|
|
3489
|
-
if (
|
|
3490
|
-
const LinkComp =
|
|
3483
|
+
// Use custom linkComponent if provided (e.g., Next.js Link)
|
|
3484
|
+
if (linkComponent) {
|
|
3485
|
+
const LinkComp = linkComponent, linkProps = {
|
|
3491
3486
|
...buttonProps,
|
|
3492
3487
|
ref: ref,
|
|
3493
|
-
//
|
|
3488
|
+
// linkComponent usually forwards ref to anchor
|
|
3494
3489
|
href: href,
|
|
3495
3490
|
to: href,
|
|
3496
3491
|
target: target,
|