@shohojdhara/atomix 0.4.1 → 0.4.2
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 +9341 -9249
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +4 -4
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.d.ts +12 -19
- package/dist/charts.js +555 -358
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +16 -23
- package/dist/core.js +418 -262
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +11 -18
- package/dist/forms.js +411 -257
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +14 -21
- package/dist/heavy.js +408 -254
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +33 -40
- package/dist/index.esm.js +663 -453
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +667 -460
- 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/scripts/atomix-cli.js +34 -1
- package/src/components/AtomixGlass/AtomixGlass.tsx +82 -54
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +17 -18
- package/src/components/AtomixGlass/README.md +5 -5
- package/src/components/AtomixGlass/stories/Customization.stories.tsx +2 -2
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +42 -42
- package/src/components/AtomixGlass/stories/Modes.stories.tsx +5 -5
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +3 -3
- package/src/components/AtomixGlass/stories/Performance.stories.tsx +2 -2
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +45 -45
- package/src/components/AtomixGlass/stories/Shaders.stories.tsx +3 -3
- package/src/components/Badge/Badge.stories.tsx +1 -1
- package/src/components/Badge/Badge.tsx +1 -1
- package/src/components/Breadcrumb/Breadcrumb.tsx +90 -76
- package/src/components/Breadcrumb/index.ts +2 -2
- package/src/components/Button/Button.stories.tsx +1 -1
- package/src/components/Button/README.md +2 -2
- package/src/components/Callout/Callout.test.tsx +3 -3
- package/src/components/Callout/Callout.tsx +2 -2
- package/src/components/Callout/README.md +2 -2
- package/src/components/Chart/Chart.stories.tsx +1 -1
- package/src/components/Chart/Chart.tsx +5 -5
- package/src/components/Chart/TreemapChart.tsx +37 -29
- package/src/components/DatePicker/readme.md +3 -3
- package/src/components/Dropdown/Dropdown.stories.tsx +1 -1
- package/src/components/EdgePanel/EdgePanel.stories.tsx +7 -7
- package/src/components/Form/Checkbox.stories.tsx +1 -1
- package/src/components/Form/Checkbox.tsx +1 -1
- package/src/components/Form/Input.stories.tsx +1 -1
- package/src/components/Form/Input.tsx +1 -1
- package/src/components/Form/Radio.stories.tsx +1 -1
- package/src/components/Form/Radio.tsx +1 -1
- package/src/components/Form/Select.stories.tsx +1 -1
- package/src/components/Form/Select.tsx +1 -1
- package/src/components/Form/Textarea.stories.tsx +1 -1
- package/src/components/Form/Textarea.tsx +1 -1
- package/src/components/Hero/Hero.stories.tsx +2 -2
- package/src/components/Hero/Hero.tsx +2 -2
- package/src/components/Messages/Messages.stories.tsx +1 -1
- package/src/components/Messages/Messages.tsx +2 -2
- package/src/components/Modal/Modal.stories.tsx +1 -1
- package/src/components/Navigation/Nav/Nav.stories.tsx +2 -2
- package/src/components/Navigation/Nav/Nav.tsx +1 -1
- package/src/components/Navigation/Navbar/Navbar.stories.tsx +3 -3
- package/src/components/Navigation/Navbar/Navbar.tsx +1 -1
- package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +2 -2
- package/src/components/Navigation/SideMenu/SideMenu.tsx +1 -1
- package/src/components/Pagination/Pagination.stories.tsx +1 -1
- package/src/components/Pagination/Pagination.tsx +1 -1
- package/src/components/Popover/Popover.stories.tsx +1 -1
- package/src/components/Popover/Popover.tsx +1 -1
- package/src/components/Progress/Progress.tsx +1 -1
- package/src/components/Rating/Rating.stories.tsx +1 -1
- package/src/components/Rating/Rating.test.tsx +73 -0
- package/src/components/Rating/Rating.tsx +25 -37
- package/src/components/Spinner/Spinner.tsx +1 -1
- package/src/components/Steps/Steps.stories.tsx +1 -1
- package/src/components/Steps/Steps.tsx +2 -2
- package/src/components/Tabs/Tabs.stories.tsx +1 -1
- package/src/components/Tabs/Tabs.tsx +1 -1
- package/src/components/Todo/Todo.tsx +0 -1
- package/src/components/Toggle/Toggle.stories.tsx +1 -1
- package/src/components/Toggle/Toggle.tsx +1 -1
- package/src/components/Tooltip/Tooltip.stories.tsx +1 -1
- package/src/components/VideoPlayer/VideoPlayer.stories.tsx +2 -2
- package/src/lib/composables/__tests__/useAtomixGlassPerf.test.tsx +88 -0
- package/src/lib/composables/__tests__/useChart.test.ts +50 -0
- package/src/lib/composables/__tests__/useChart.test.tsx +139 -0
- package/src/lib/composables/__tests__/useHeroBackgroundSlider.test.tsx +59 -0
- package/src/lib/composables/__tests__/useSliderAutoplay.test.tsx +68 -0
- package/src/lib/composables/atomix-glass/useGlassBackgroundDetection.ts +329 -0
- package/src/lib/composables/atomix-glass/useGlassCornerRadius.ts +82 -0
- package/src/lib/composables/atomix-glass/useGlassMouseTracking.ts +153 -0
- package/src/lib/composables/atomix-glass/useGlassOverLight.ts +198 -0
- package/src/lib/composables/atomix-glass/useGlassSize.ts +117 -0
- package/src/lib/composables/atomix-glass/useGlassState.ts +112 -0
- package/src/lib/composables/atomix-glass/useGlassTransforms.ts +160 -0
- package/src/lib/composables/glass-styles.ts +302 -0
- package/src/lib/composables/index.ts +0 -4
- package/src/lib/composables/useAtomixGlass.ts +331 -522
- package/src/lib/composables/useAtomixGlassStyles.ts +307 -0
- package/src/lib/composables/useBarChart.ts +1 -1
- package/src/lib/composables/useBreadcrumb.ts +6 -6
- package/src/lib/composables/useChart.ts +104 -21
- package/src/lib/composables/useHeroBackgroundSlider.ts +16 -7
- package/src/lib/composables/useSlider.ts +66 -34
- package/src/lib/theme/devtools/CLI.ts +1 -1
- package/src/lib/theme/utils/__tests__/themeUtils.test.ts +213 -0
- package/src/lib/types/components.ts +13 -21
- package/src/lib/utils/__tests__/dom.test.ts +100 -0
- package/src/lib/utils/__tests__/fontPreloader.test.ts +102 -0
- package/src/styles/02-tools/_tools.breakpoints.scss +1 -1
- package/src/styles/02-tools/_tools.utility-api.scss +6 -6
- package/src/styles/06-components/_components.accordion.scss +0 -2
- package/src/styles/06-components/_components.chart.scss +0 -1
- package/src/styles/06-components/_components.dropdown.scss +0 -1
- package/src/styles/06-components/_components.edge-panel.scss +0 -2
- package/src/styles/06-components/_components.photoviewer.scss +0 -1
- package/src/styles/06-components/_components.river.scss +0 -1
- package/src/styles/06-components/_components.slider.scss +0 -3
- package/src/styles/99-utilities/_utilities.glass-fixes.scss +0 -1
- package/src/styles/99-utilities/_utilities.text.scss +1 -0
package/dist/core.js
CHANGED
|
@@ -727,7 +727,7 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
727
727
|
HIGH_CONTRAST: 200
|
|
728
728
|
}
|
|
729
729
|
}
|
|
730
|
-
}, {CONSTANTS: CONSTANTS$
|
|
730
|
+
}, {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateDistance = (pos1, pos2) => {
|
|
731
731
|
if (!pos1 || !pos2 || "number" != typeof pos1.x || "number" != typeof pos1.y || "number" != typeof pos2.x || "number" != typeof pos2.y) return 0;
|
|
732
732
|
const deltaX = pos1.x - pos2.x, deltaY = pos1.y - pos2.y;
|
|
733
733
|
return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
@@ -740,36 +740,36 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
740
740
|
}, calculateMouseInfluence = mouseOffset => {
|
|
741
741
|
if (!mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y) return 0;
|
|
742
742
|
// Bounded calculation — keeps the glass effect subtle and stable
|
|
743
|
-
const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$
|
|
743
|
+
const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$2.MOUSE_INFLUENCE_DIVISOR;
|
|
744
744
|
return Math.min(.8, influence);
|
|
745
745
|
// Tighter cap to prevent blur/filter blow-out
|
|
746
|
-
}, clampBlur = value => "number" != typeof value || isNaN(value) ? CONSTANTS$
|
|
746
|
+
}, clampBlur = value => "number" != typeof value || isNaN(value) ? CONSTANTS$2.MIN_BLUR : Math.max(CONSTANTS$2.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$2.MAX_SIZE && size.height <= CONSTANTS$2.MAX_SIZE, parseBorderRadiusValue = value => {
|
|
747
747
|
if ("number" == typeof value) return Math.max(0, value);
|
|
748
|
-
if ("string" != typeof value || !value.trim()) return CONSTANTS$
|
|
748
|
+
if ("string" != typeof value || !value.trim()) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
749
749
|
const trimmedValue = value.trim();
|
|
750
750
|
// Handle px values
|
|
751
751
|
if (trimmedValue.endsWith("px")) {
|
|
752
752
|
const parsed = parseFloat(trimmedValue);
|
|
753
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
753
|
+
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
|
|
754
754
|
}
|
|
755
755
|
// Handle rem values (assume 16px = 1rem)
|
|
756
756
|
if (trimmedValue.endsWith("rem")) {
|
|
757
757
|
const parsed = parseFloat(trimmedValue);
|
|
758
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
758
|
+
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
759
759
|
}
|
|
760
760
|
// Handle em values (assume 16px = 1em for simplicity)
|
|
761
761
|
if (trimmedValue.endsWith("em")) {
|
|
762
762
|
const parsed = parseFloat(trimmedValue);
|
|
763
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
763
|
+
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
764
764
|
}
|
|
765
765
|
// Handle percentage (convert to approximate px value, assuming 200px container)
|
|
766
766
|
if (trimmedValue.endsWith("%")) {
|
|
767
767
|
const parsed = parseFloat(trimmedValue);
|
|
768
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
768
|
+
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
|
|
769
769
|
}
|
|
770
770
|
// Handle unitless numbers
|
|
771
771
|
const numValue = parseFloat(trimmedValue);
|
|
772
|
-
return isNaN(numValue) ? CONSTANTS$
|
|
772
|
+
return isNaN(numValue) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
|
|
773
773
|
}, extractBorderRadiusFromElement = element => {
|
|
774
774
|
if (!element || !element.props) return null;
|
|
775
775
|
// Check inline styles first (highest priority)
|
|
@@ -785,11 +785,11 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
785
785
|
// If element has children, recursively check them
|
|
786
786
|
if (element.props.children) {
|
|
787
787
|
const childRadius = extractBorderRadiusFromChildren(element.props.children);
|
|
788
|
-
if (childRadius > 0 && childRadius !== CONSTANTS$
|
|
788
|
+
if (childRadius > 0 && childRadius !== CONSTANTS$2.DEFAULT_CORNER_RADIUS) return childRadius;
|
|
789
789
|
}
|
|
790
790
|
return null;
|
|
791
791
|
}, extractBorderRadiusFromChildren = children => {
|
|
792
|
-
if (!children) return CONSTANTS$
|
|
792
|
+
if (!children) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
793
793
|
try {
|
|
794
794
|
const childArray = React.Children.toArray(children);
|
|
795
795
|
for (let i = 0; i < childArray.length; i++) {
|
|
@@ -802,7 +802,7 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
802
802
|
} catch (error) {
|
|
803
803
|
// Silently handle errors
|
|
804
804
|
}
|
|
805
|
-
return CONSTANTS$
|
|
805
|
+
return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
806
806
|
}, getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
|
|
807
807
|
switch (mode) {
|
|
808
808
|
case "standard":
|
|
@@ -976,10 +976,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
976
976
|
}, globalMousePosition: globalMousePosition = {
|
|
977
977
|
x: 0,
|
|
978
978
|
y: 0
|
|
979
|
-
}, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isHovered: isHovered = !1, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {},
|
|
979
|
+
}, 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 = {
|
|
980
980
|
width: 0,
|
|
981
981
|
height: 0
|
|
982
|
-
}, onClick: onClick, mode: mode = "standard",
|
|
982
|
+
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, elasticity: elasticity = 0, contentRef: contentRef}, ref) => {
|
|
983
983
|
// Generate a stable, deterministic ID for SSR compatibility
|
|
984
984
|
// Use a module-level counter that's consistent across server and client
|
|
985
985
|
const filterId = useMemo((() => "atomix-glass-filter-" + ++idCounter), []), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null);
|
|
@@ -1089,7 +1089,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
1089
1089
|
flowBlur: 1.2 * blurAmount
|
|
1090
1090
|
};
|
|
1091
1091
|
// Enhanced validation for liquid blur
|
|
1092
|
-
if (!
|
|
1092
|
+
if (!withLiquidBlur || !rectCache || !mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y || isNaN(mouseOffset.x) || isNaN(mouseOffset.y)) return defaultBlur;
|
|
1093
1093
|
try {
|
|
1094
1094
|
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);
|
|
1095
1095
|
// NOTE: hover/active multipliers intentionally omitted here —
|
|
@@ -1104,14 +1104,14 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
1104
1104
|
return console.warn("AtomixGlassContainer: Error calculating liquid blur", error),
|
|
1105
1105
|
defaultBlur;
|
|
1106
1106
|
}
|
|
1107
|
-
}), [
|
|
1107
|
+
}), [ withLiquidBlur, blurAmount, mouseOffset, rectCache ]), backdropStyle = useMemo((() => {
|
|
1108
1108
|
try {
|
|
1109
1109
|
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;
|
|
1110
1110
|
// Validate blur values before using them
|
|
1111
|
-
return !
|
|
1111
|
+
return !withLiquidBlur || effectiveReducedMotion || effectiveWithoutEffects || area > 18e4 ? {
|
|
1112
1112
|
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})`
|
|
1113
1113
|
} : {
|
|
1114
|
-
backdropFilter: `blur(${clampBlur(.4 * validatedBaseBlur + .25 * validatedEdgeBlur + .15 * validatedCenterBlur + .2 * validatedFlowBlur)}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1
|
|
1114
|
+
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})`
|
|
1115
1115
|
};
|
|
1116
1116
|
// Single-pass fallback: stronger radius to match perceived blur of multi-pass
|
|
1117
1117
|
} catch (error) {
|
|
@@ -1120,7 +1120,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
1120
1120
|
backdropFilter: `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`
|
|
1121
1121
|
};
|
|
1122
1122
|
}
|
|
1123
|
-
}), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion,
|
|
1123
|
+
}), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveWithoutEffects, withLiquidBlur ]), containerVars = useMemo((() => {
|
|
1124
1124
|
try {
|
|
1125
1125
|
// Safe extraction of mouse offset values
|
|
1126
1126
|
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;
|
|
@@ -1128,10 +1128,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
1128
1128
|
"--atomix-glass-container-width": `${glassSize?.width}`,
|
|
1129
1129
|
"--atomix-glass-container-height": `${glassSize?.height}`,
|
|
1130
1130
|
"--atomix-glass-container-padding": padding || "0 0",
|
|
1131
|
-
"--atomix-glass-container-radius": `${"number" != typeof
|
|
1131
|
+
"--atomix-glass-container-radius": `${"number" != typeof borderRadius || isNaN(borderRadius) ? 0 : borderRadius}px`,
|
|
1132
1132
|
"--atomix-glass-container-backdrop": backdropStyle?.backdropFilter || "none",
|
|
1133
1133
|
"--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",
|
|
1134
|
-
"--atomix-glass-container-shadow-opacity":
|
|
1134
|
+
"--atomix-glass-container-shadow-opacity": effectiveWithoutEffects ? 0 : 1,
|
|
1135
1135
|
// Background and shadow values use design token-aligned RGB values
|
|
1136
1136
|
"--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",
|
|
1137
1137
|
"--atomix-glass-container-text-shadow": overLight ? "0px 2px 12px rgba(0, 0, 0, 0)" : "0px 2px 12px rgba(0, 0, 0, 0.4)",
|
|
@@ -1149,14 +1149,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
1149
1149
|
"--atomix-glass-container-text-shadow": "none"
|
|
1150
1150
|
};
|
|
1151
1151
|
}
|
|
1152
|
-
}), [ glassSize, padding,
|
|
1153
|
-
el && (el.style.setProperty("transition-duration", "0s", "important"), el.style.setProperty("animation-duration", "0s", "important"),
|
|
1154
|
-
el.style.setProperty("transition-delay", "0s", "important"));
|
|
1155
|
-
};
|
|
1152
|
+
}), [ glassSize, padding, borderRadius, backdropStyle, mouseOffset, overLight, effectiveWithoutEffects ]);
|
|
1156
1153
|
return jsx("div", {
|
|
1157
1154
|
ref: el => {
|
|
1158
1155
|
// Apply force no-transition
|
|
1159
|
-
setForceNoTransition(el),
|
|
1160
1156
|
// Handle forwarded ref
|
|
1161
1157
|
"function" == typeof ref ? ref(el) : ref && (ref.current = el);
|
|
1162
1158
|
},
|
|
@@ -1191,7 +1187,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
1191
1187
|
aberrationIntensity: "number" != typeof aberrationIntensity || isNaN(aberrationIntensity) ? 0 : aberrationIntensity,
|
|
1192
1188
|
shaderMapUrl: shaderMapUrl
|
|
1193
1189
|
}), jsx("div", {
|
|
1194
|
-
ref:
|
|
1190
|
+
ref: el => {
|
|
1191
|
+
el && (el.style.setProperty("transition-duration", "0s", "important"), el.style.setProperty("animation-duration", "0s", "important"),
|
|
1192
|
+
el.style.setProperty("transition-delay", "0s", "important"));
|
|
1193
|
+
},
|
|
1195
1194
|
className: ATOMIX_GLASS.FILTER_OVERLAY_CLASS,
|
|
1196
1195
|
style: {
|
|
1197
1196
|
filter: `url(#${filterId})`,
|
|
@@ -1308,7 +1307,128 @@ class {
|
|
|
1308
1307
|
*/ getSubscriberCount() {
|
|
1309
1308
|
return this.listeners.size;
|
|
1310
1309
|
}
|
|
1311
|
-
},
|
|
1310
|
+
}, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
|
|
1311
|
+
if (!wrapperElement && !containerElement) return;
|
|
1312
|
+
const {mouseOffset: mouseOffset, globalMousePosition: globalMousePosition, glassSize: glassSize, isHovered: isHovered, isActive: isActive, isOverLight: isOverLight, baseOverLightConfig: baseOverLightConfig, effectiveBorderRadius: effectiveBorderRadius, effectiveWithoutEffects: effectiveWithoutEffects, effectiveReducedMotion: effectiveReducedMotion, elasticity: elasticity, directionalScale: directionalScale, onClick: onClick, withLiquidBlur: withLiquidBlur, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, padding: padding = ATOMIX_GLASS.DEFAULTS.PADDING} = params, mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1, overLightConfig = {
|
|
1313
|
+
opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
|
|
1314
|
+
contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
|
|
1315
|
+
brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
|
|
1316
|
+
shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
|
|
1317
|
+
borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence)),
|
|
1318
|
+
saturationBoost: baseOverLightConfig.saturationBoost
|
|
1319
|
+
};
|
|
1320
|
+
// Calculate mouse influence
|
|
1321
|
+
// Calculate elastic translation
|
|
1322
|
+
let elasticTranslation = {
|
|
1323
|
+
x: 0,
|
|
1324
|
+
y: 0
|
|
1325
|
+
};
|
|
1326
|
+
if (!effectiveWithoutEffects && wrapperElement) {
|
|
1327
|
+
const rect = wrapperElement.getBoundingClientRect(), center = calculateElementCenter(rect);
|
|
1328
|
+
// Calculate fade in factor
|
|
1329
|
+
let fadeInFactor = 0;
|
|
1330
|
+
if (globalMousePosition.x && globalMousePosition.y && validateGlassSize(glassSize)) {
|
|
1331
|
+
const 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({
|
|
1332
|
+
x: edgeDistanceX,
|
|
1333
|
+
y: edgeDistanceY
|
|
1334
|
+
}, {
|
|
1335
|
+
x: 0,
|
|
1336
|
+
y: 0
|
|
1337
|
+
});
|
|
1338
|
+
fadeInFactor = edgeDistance > ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE ? 0 : 1 - edgeDistance / ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE;
|
|
1339
|
+
}
|
|
1340
|
+
elasticTranslation = {
|
|
1341
|
+
x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
|
|
1342
|
+
y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
|
|
1343
|
+
};
|
|
1344
|
+
}
|
|
1345
|
+
const transformStyle = effectiveWithoutEffects ? isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)" : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) ${isActive && Boolean(onClick) ? "scale(0.96)" : directionalScale}`;
|
|
1346
|
+
// Update Wrapper Styles (glassVars)
|
|
1347
|
+
if (wrapperElement) {
|
|
1348
|
+
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 = {
|
|
1349
|
+
hover1: {
|
|
1350
|
+
x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1,
|
|
1351
|
+
y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1
|
|
1352
|
+
},
|
|
1353
|
+
hover2: {
|
|
1354
|
+
x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_2,
|
|
1355
|
+
y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_2
|
|
1356
|
+
},
|
|
1357
|
+
hover3: {
|
|
1358
|
+
x: GRADIENT.CENTER_POSITION + mx * GRADIENT.HOVER_POSITION.MULTIPLIER_3,
|
|
1359
|
+
y: GRADIENT.CENTER_POSITION + my * GRADIENT.HOVER_POSITION.MULTIPLIER_3
|
|
1360
|
+
}
|
|
1361
|
+
}, basePosition = {
|
|
1362
|
+
x: GRADIENT.CENTER_POSITION + mx * GRADIENT.BASE_LAYER_MULTIPLIER,
|
|
1363
|
+
y: GRADIENT.CENTER_POSITION + my * GRADIENT.BASE_LAYER_MULTIPLIER
|
|
1364
|
+
}, opacityValues = {
|
|
1365
|
+
hover1: isHovered || isActive ? .5 : 0,
|
|
1366
|
+
hover2: isActive ? .5 : 0,
|
|
1367
|
+
hover3: isHovered ? .4 : isActive ? .8 : 0,
|
|
1368
|
+
base: isOverLight ? overLightConfig.opacity : 0,
|
|
1369
|
+
over: isOverLight ? 1.1 * overLightConfig.opacity : 0
|
|
1370
|
+
}, style = wrapperElement.style;
|
|
1371
|
+
style.setProperty("--atomix-glass-transform", transformStyle || "none"),
|
|
1372
|
+
// Gradients
|
|
1373
|
+
style.setProperty("--atomix-glass-border-gradient-1", `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[0] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[1] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`),
|
|
1374
|
+
style.setProperty("--atomix-glass-border-gradient-2", `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[2] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[3] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`),
|
|
1375
|
+
// Hover gradients
|
|
1376
|
+
style.setProperty("--atomix-glass-hover-1-gradient", isOverLight ? `radial-gradient(circle at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_END}%)` : `radial-gradient(circle at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_STOP}%)`),
|
|
1377
|
+
style.setProperty("--atomix-glass-hover-2-gradient", isOverLight ? `radial-gradient(circle at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_END}%)` : `radial-gradient(circle at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_STOP}%)`),
|
|
1378
|
+
style.setProperty("--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}%)`),
|
|
1379
|
+
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%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.WHITE_OPACITY})`),
|
|
1380
|
+
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%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.WHITE_OPACITY})`),
|
|
1381
|
+
// Opacities
|
|
1382
|
+
style.setProperty("--atomix-glass-hover-1-opacity", opacityValues.hover1.toString()),
|
|
1383
|
+
style.setProperty("--atomix-glass-hover-2-opacity", opacityValues.hover2.toString()),
|
|
1384
|
+
style.setProperty("--atomix-glass-hover-3-opacity", opacityValues.hover3.toString()),
|
|
1385
|
+
style.setProperty("--atomix-glass-base-opacity", opacityValues.base.toString()),
|
|
1386
|
+
style.setProperty("--atomix-glass-overlay-opacity", opacityValues.over.toString()),
|
|
1387
|
+
style.setProperty("--atomix-glass-overlay-highlight-opacity", (opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER).toString()),
|
|
1388
|
+
// Other
|
|
1389
|
+
style.setProperty("--atomix-glass-blend-mode", isOverLight ? "multiply" : "overlay"),
|
|
1390
|
+
style.setProperty("--atomix-glass-radius", `${effectiveBorderRadius}px`);
|
|
1391
|
+
}
|
|
1392
|
+
// Update Container Styles (containerVars)
|
|
1393
|
+
if (containerElement) {
|
|
1394
|
+
const mx = mouseOffset.x, my = mouseOffset.y, EDGE_BLUR_MULTIPLIER = 1.25, CENTER_BLUR_MULTIPLIER = 1.1, FLOW_BLUR_MULTIPLIER = 1.2, MOUSE_INFLUENCE_BLUR_FACTOR = .15, EDGE_INTENSITY_MOUSE_FACTOR = .15, CENTER_INTENSITY_MOUSE_FACTOR = .1, MAX_BLUR_RELATIVE = 2, rect = containerElement.getBoundingClientRect();
|
|
1395
|
+
let liquidBlur = {
|
|
1396
|
+
baseBlur: blurAmount,
|
|
1397
|
+
edgeBlur: blurAmount * EDGE_BLUR_MULTIPLIER,
|
|
1398
|
+
centerBlur: blurAmount * CENTER_BLUR_MULTIPLIER,
|
|
1399
|
+
flowBlur: blurAmount * FLOW_BLUR_MULTIPLIER
|
|
1400
|
+
};
|
|
1401
|
+
if (withLiquidBlur && rect) {
|
|
1402
|
+
const mouseInfluence = calculateMouseInfluence(mouseOffset), maxBlur = blurAmount * MAX_BLUR_RELATIVE, baseBlur = Math.min(maxBlur, blurAmount + mouseInfluence * blurAmount * MOUSE_INFLUENCE_BLUR_FACTOR), edgeIntensity = mouseInfluence * EDGE_INTENSITY_MOUSE_FACTOR, edgeBlur = Math.min(maxBlur, baseBlur * (.8 + .4 * edgeIntensity)), centerIntensity = mouseInfluence * CENTER_INTENSITY_MOUSE_FACTOR, centerBlur = Math.min(maxBlur, baseBlur * (.3 + .3 * centerIntensity)), flowBlur = Math.min(maxBlur, baseBlur * FLOW_BLUR_MULTIPLIER);
|
|
1403
|
+
liquidBlur = {
|
|
1404
|
+
baseBlur: clampBlur(baseBlur),
|
|
1405
|
+
edgeBlur: clampBlur(edgeBlur),
|
|
1406
|
+
centerBlur: clampBlur(centerBlur),
|
|
1407
|
+
flowBlur: clampBlur(flowBlur)
|
|
1408
|
+
};
|
|
1409
|
+
}
|
|
1410
|
+
// Backdrop filter
|
|
1411
|
+
let backdropFilterString = `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`;
|
|
1412
|
+
const dynamicSaturation = saturation + 20 * (liquidBlur.baseBlur || 0), area = rect ? rect.width * rect.height : 0;
|
|
1413
|
+
backdropFilterString = !withLiquidBlur || effectiveReducedMotion || effectiveWithoutEffects || area > 18e4 ? `blur(${clampBlur(Math.max(liquidBlur.baseBlur, .8 * liquidBlur.edgeBlur, 1.1 * liquidBlur.centerBlur, .9 * liquidBlur.flowBlur))}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig.contrast}) brightness(${overLightConfig.brightness})` : `blur(${clampBlur(.4 * liquidBlur.baseBlur + .25 * liquidBlur.edgeBlur + .15 * liquidBlur.centerBlur + .2 * liquidBlur.flowBlur)}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig.contrast}) brightness(${overLightConfig.brightness})`;
|
|
1414
|
+
// Container variables
|
|
1415
|
+
const style = containerElement.style;
|
|
1416
|
+
style.setProperty("--atomix-glass-container-width", `${glassSize.width}`), style.setProperty("--atomix-glass-container-height", `${glassSize.height}`),
|
|
1417
|
+
style.setProperty("--atomix-glass-container-padding", padding), style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
|
|
1418
|
+
style.setProperty("--atomix-glass-container-backdrop", backdropFilterString),
|
|
1419
|
+
// Shadows
|
|
1420
|
+
style.setProperty("--atomix-glass-container-shadow", isOverLight ? [ `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"),
|
|
1421
|
+
style.setProperty("--atomix-glass-container-shadow-opacity", effectiveWithoutEffects ? "0" : "1"),
|
|
1422
|
+
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"),
|
|
1423
|
+
style.setProperty("--atomix-glass-container-text-shadow", isOverLight ? "0px 2px 12px rgba(0, 0, 0, 0)" : "0px 2px 12px rgba(0, 0, 0, 0.4)"),
|
|
1424
|
+
style.setProperty("--atomix-glass-container-box-shadow", isOverLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "0px 12px 40px rgba(0, 0, 0, 0.25)");
|
|
1425
|
+
}
|
|
1426
|
+
}, {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS;
|
|
1427
|
+
|
|
1428
|
+
/**
|
|
1429
|
+
* Updates the styles of the AtomixGlass wrapper and container elements imperatively
|
|
1430
|
+
* to avoid React re-renders on mouse movement.
|
|
1431
|
+
*/ const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
|
|
1312
1432
|
parentElement && backgroundDetectionCache.set(parentElement, {
|
|
1313
1433
|
result: result,
|
|
1314
1434
|
timestamp: Date.now(),
|
|
@@ -1321,18 +1441,74 @@ class {
|
|
|
1321
1441
|
* Composable hook for AtomixGlass component logic
|
|
1322
1442
|
* Manages all state, calculations, and event handlers
|
|
1323
1443
|
*/
|
|
1324
|
-
function useAtomixGlass({glassRef: glassRef, contentRef: contentRef,
|
|
1444
|
+
function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef: wrapperRef, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, elasticity: elasticity = .05, onClick: onClick, debugBorderRadius: debugBorderRadius = !1, debugOverLight: debugOverLight = !1, debugPerformance: debugPerformance = !1, children: children, blurAmount: blurAmount, saturation: saturation, padding: padding, withLiquidBlur: withLiquidBlur}) {
|
|
1325
1445
|
// State
|
|
1326
|
-
const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1),
|
|
1327
|
-
width: 270,
|
|
1328
|
-
height: 69
|
|
1329
|
-
}), [internalGlobalMousePosition, setInternalGlobalMousePosition] = useState({
|
|
1446
|
+
const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), cachedRectRef = useRef(null), internalGlobalMousePositionRef = useRef({
|
|
1330
1447
|
x: 0,
|
|
1331
1448
|
y: 0
|
|
1332
|
-
}),
|
|
1449
|
+
}), internalMouseOffsetRef = useRef({
|
|
1333
1450
|
x: 0,
|
|
1334
1451
|
y: 0
|
|
1335
|
-
}), [
|
|
1452
|
+
}), [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}) {
|
|
1453
|
+
const [glassSize, setGlassSize] = useState({
|
|
1454
|
+
width: 270,
|
|
1455
|
+
height: 69
|
|
1456
|
+
});
|
|
1457
|
+
return useEffect((() => {
|
|
1458
|
+
const isValidElement = element => null !== element && element instanceof HTMLElement && element.isConnected;
|
|
1459
|
+
let rafId = null, lastSize = {
|
|
1460
|
+
width: 0,
|
|
1461
|
+
height: 0
|
|
1462
|
+
}, lastCornerRadius = effectiveBorderRadius;
|
|
1463
|
+
const updateGlassSize = (forceUpdate = !1) => {
|
|
1464
|
+
null !== rafId && cancelAnimationFrame(rafId), rafId = requestAnimationFrame((() => {
|
|
1465
|
+
if (!isValidElement(glassRef.current)) return void (rafId = null);
|
|
1466
|
+
const rect = glassRef.current.getBoundingClientRect();
|
|
1467
|
+
if (rect.width <= 0 || rect.height <= 0) return void (rafId = null);
|
|
1468
|
+
// Measure actual rendered size without artificial offsets to avoid feedback loops
|
|
1469
|
+
const newSize = {
|
|
1470
|
+
width: Math.round(rect.width),
|
|
1471
|
+
height: Math.round(rect.height)
|
|
1472
|
+
}, cornerRadiusChanged = lastCornerRadius !== effectiveBorderRadius, dimensionsChanged = Math.abs(newSize.width - lastSize.width) > 1 || Math.abs(newSize.height - lastSize.height) > 1;
|
|
1473
|
+
var size;
|
|
1474
|
+
(forceUpdate || cornerRadiusChanged || dimensionsChanged) && validateGlassSize(size = newSize) && size.width <= CONSTANTS$1.MAX_SIZE && size.height <= CONSTANTS$1.MAX_SIZE && (lastSize = newSize,
|
|
1475
|
+
lastCornerRadius = effectiveBorderRadius, setGlassSize(newSize)), rafId = null;
|
|
1476
|
+
}));
|
|
1477
|
+
};
|
|
1478
|
+
let resizeTimeoutId = null;
|
|
1479
|
+
const debouncedResizeHandler = () => {
|
|
1480
|
+
resizeTimeoutId && clearTimeout(resizeTimeoutId), resizeTimeoutId = setTimeout((() => updateGlassSize(!1)), 16);
|
|
1481
|
+
}, initialTimeoutId = setTimeout((() => updateGlassSize(!0)), 0);
|
|
1482
|
+
let resizeObserver = null, resizeDebounceTimeout = null;
|
|
1483
|
+
// ResizeObserver has 98%+ browser support, no need for fallback
|
|
1484
|
+
if ("undefined" != typeof ResizeObserver && isValidElement(glassRef.current)) try {
|
|
1485
|
+
resizeObserver = new ResizeObserver((entries => {
|
|
1486
|
+
for (const entry of entries) if (entry.target === glassRef.current) {
|
|
1487
|
+
// Update cached rect when size changes
|
|
1488
|
+
glassRef.current && cachedRectRef && (cachedRectRef.current = glassRef.current.getBoundingClientRect()),
|
|
1489
|
+
// Debounce resize updates to match RAF timing (16ms)
|
|
1490
|
+
resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), resizeDebounceTimeout = setTimeout((() => updateGlassSize(!1)), 16);
|
|
1491
|
+
break;
|
|
1492
|
+
}
|
|
1493
|
+
})), resizeObserver.observe(glassRef.current);
|
|
1494
|
+
} catch (error) {
|
|
1495
|
+
console.warn("AtomixGlass: ResizeObserver not available, using window resize only", error);
|
|
1496
|
+
}
|
|
1497
|
+
return window.addEventListener("resize", debouncedResizeHandler, {
|
|
1498
|
+
passive: !0
|
|
1499
|
+
}), () => {
|
|
1500
|
+
clearTimeout(initialTimeoutId), null !== rafId && cancelAnimationFrame(rafId), resizeTimeoutId && clearTimeout(resizeTimeoutId),
|
|
1501
|
+
resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), window.removeEventListener("resize", debouncedResizeHandler),
|
|
1502
|
+
resizeObserver?.disconnect();
|
|
1503
|
+
};
|
|
1504
|
+
}), [ effectiveBorderRadius, glassRef, cachedRectRef ]), {
|
|
1505
|
+
glassSize: glassSize
|
|
1506
|
+
};
|
|
1507
|
+
}({
|
|
1508
|
+
glassRef: glassRef,
|
|
1509
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
1510
|
+
cachedRectRef: cachedRectRef
|
|
1511
|
+
}), effectiveReducedMotion = useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveHighContrast = useMemo((() => highContrast || userPrefersHighContrast), [ highContrast, userPrefersHighContrast ]), effectiveWithoutEffects = useMemo((() => withoutEffects || effectiveReducedMotion), [ withoutEffects, effectiveReducedMotion ]), globalMousePosition = externalGlobalMousePosition || internalGlobalMousePositionRef.current, mouseOffset = externalMouseOffset || internalMouseOffsetRef.current;
|
|
1336
1512
|
// Extract border-radius from children
|
|
1337
1513
|
useEffect((() => {
|
|
1338
1514
|
const extractRadius = () => {
|
|
@@ -1363,13 +1539,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
1363
1539
|
}
|
|
1364
1540
|
null !== extractedRadius && extractedRadius > 0 && setDynamicCornerRadius(extractedRadius);
|
|
1365
1541
|
} catch (error) {
|
|
1366
|
-
"undefined" != typeof process && "production" === process.env?.NODE_ENV || !
|
|
1542
|
+
"undefined" != typeof process && "production" === process.env?.NODE_ENV || !debugBorderRadius || console.error("[AtomixGlass] Error extracting corner radius:", error);
|
|
1367
1543
|
}
|
|
1368
1544
|
};
|
|
1369
1545
|
extractRadius();
|
|
1370
1546
|
const timeoutId = setTimeout(extractRadius, 100);
|
|
1371
1547
|
return () => clearTimeout(timeoutId);
|
|
1372
|
-
}), [ children,
|
|
1548
|
+
}), [ children, debugBorderRadius, contentRef ]),
|
|
1373
1549
|
// Media query handlers and background detection
|
|
1374
1550
|
useEffect((() => {
|
|
1375
1551
|
if (("auto" === overLight || "object" == typeof overLight && null !== overLight) && glassRef.current) {
|
|
@@ -1425,72 +1601,52 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
1425
1601
|
const rgb = bgColor.match(/\d+/g);
|
|
1426
1602
|
if (rgb && rgb.length >= 3) {
|
|
1427
1603
|
const r = Number(rgb[0]), g = Number(rgb[1]), b = Number(rgb[2]);
|
|
1428
|
-
|
|
1429
|
-
if (!isNaN(r) && !isNaN(g) && !isNaN(b) && isFinite(r) && isFinite(g) && isFinite(b) && r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255 && (r > 10 || g > 10 || b > 10)) {
|
|
1604
|
+
if (!isNaN(r) && !isNaN(g) && !isNaN(b) && (r > 10 || g > 10 || b > 10)) {
|
|
1430
1605
|
const luminance = (.299 * r + .587 * g + .114 * b) / 255;
|
|
1431
1606
|
!isNaN(luminance) && isFinite(luminance) && (totalLuminance += luminance, validSamples++,
|
|
1432
1607
|
hasValidBackground = !0);
|
|
1433
1608
|
}
|
|
1434
1609
|
}
|
|
1435
1610
|
}
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
// For image backgrounds, assume medium luminance
|
|
1439
|
-
totalLuminance += .5, validSamples++, hasValidBackground = !0);
|
|
1611
|
+
bgImage && "none" !== bgImage && "initial" !== bgImage && (totalLuminance += .5,
|
|
1612
|
+
validSamples++, hasValidBackground = !0);
|
|
1440
1613
|
} catch (styleError) {
|
|
1441
|
-
|
|
1614
|
+
// Silently continue
|
|
1442
1615
|
}
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
// Exit loop if currentElement becomes null
|
|
1446
|
-
currentElement = currentElement.parentElement, depth++;
|
|
1616
|
+
if (!currentElement) break;
|
|
1617
|
+
currentElement = currentElement.parentElement, depth++;
|
|
1447
1618
|
}
|
|
1448
|
-
|
|
1449
|
-
if (hasValidBackground && validSamples > 0) {
|
|
1619
|
+
if (hasValidBackground && validSamples > 0) {
|
|
1450
1620
|
const avgLuminance = totalLuminance / validSamples;
|
|
1451
1621
|
if (!isNaN(avgLuminance) && isFinite(avgLuminance)) {
|
|
1452
1622
|
let threshold = .7;
|
|
1453
|
-
|
|
1454
|
-
// If overLight is an object, use its threshold property with validation
|
|
1455
|
-
if ("object" == typeof overLight && null !== overLight) {
|
|
1623
|
+
if ("object" == typeof overLight && null !== overLight) {
|
|
1456
1624
|
const objConfig = overLight;
|
|
1457
1625
|
if (void 0 !== objConfig.threshold) {
|
|
1458
|
-
const configThreshold = "number"
|
|
1626
|
+
const configThreshold = "number" != typeof objConfig.threshold || isNaN(objConfig.threshold) ? .7 : objConfig.threshold;
|
|
1459
1627
|
threshold = Math.min(.9, Math.max(.1, configThreshold));
|
|
1460
1628
|
}
|
|
1461
1629
|
}
|
|
1462
1630
|
const isOverLightDetected = avgLuminance > threshold;
|
|
1463
|
-
|
|
1464
|
-
setCachedBackgroundDetection(element.parentElement, overLight, isOverLightDetected, threshold),
|
|
1631
|
+
setCachedBackgroundDetection(element.parentElement, overLight, isOverLightDetected, threshold),
|
|
1465
1632
|
setDetectedOverLight(isOverLightDetected);
|
|
1466
1633
|
} else {
|
|
1467
|
-
// Invalid luminance calculation, default to false
|
|
1468
1634
|
const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
|
|
1469
1635
|
setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
|
|
1470
1636
|
setDetectedOverLight(result);
|
|
1471
1637
|
}
|
|
1472
1638
|
} else {
|
|
1473
|
-
// Default to false if no valid background found
|
|
1474
1639
|
const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
|
|
1475
1640
|
setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
|
|
1476
1641
|
setDetectedOverLight(result);
|
|
1477
1642
|
}
|
|
1478
1643
|
} catch (error) {
|
|
1479
|
-
|
|
1480
|
-
"undefined" != typeof process && "development" !== process.env?.NODE_ENV || console.warn("AtomixGlass: Error detecting background brightness:", error);
|
|
1481
|
-
const result = !1;
|
|
1482
|
-
if (element && element.parentElement) {
|
|
1483
|
-
const threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
|
|
1484
|
-
setCachedBackgroundDetection(element.parentElement, overLight, result, threshold);
|
|
1485
|
-
}
|
|
1486
|
-
setDetectedOverLight(result);
|
|
1644
|
+
setDetectedOverLight(!1);
|
|
1487
1645
|
}
|
|
1488
1646
|
}), 150);
|
|
1489
1647
|
return () => clearTimeout(timeoutId);
|
|
1490
1648
|
}
|
|
1491
|
-
if ("boolean" == typeof overLight &&
|
|
1492
|
-
// For boolean values, disable auto-detection
|
|
1493
|
-
setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
|
|
1649
|
+
if ("boolean" == typeof overLight && setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
|
|
1494
1650
|
const mediaQueryReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)"), mediaQueryHighContrast = window.matchMedia("(prefers-contrast: high)");
|
|
1495
1651
|
setUserPrefersReducedMotion(mediaQueryReducedMotion.matches), setUserPrefersHighContrast(mediaQueryHighContrast.matches);
|
|
1496
1652
|
const handleReducedMotionChange = e => {
|
|
@@ -1501,64 +1657,54 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
1501
1657
|
return mediaQueryReducedMotion.addEventListener ? (mediaQueryReducedMotion.addEventListener("change", handleReducedMotionChange),
|
|
1502
1658
|
mediaQueryHighContrast.addEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.addListener && (mediaQueryReducedMotion.addListener(handleReducedMotionChange),
|
|
1503
1659
|
mediaQueryHighContrast.addListener(handleHighContrastChange)), () => {
|
|
1504
|
-
|
|
1505
|
-
mediaQueryReducedMotion.removeEventListener ? (mediaQueryReducedMotion.removeEventListener("change", handleReducedMotionChange),
|
|
1506
|
-
mediaQueryHighContrast.removeEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.removeListener && (mediaQueryReducedMotion.removeListener(handleReducedMotionChange),
|
|
1507
|
-
mediaQueryHighContrast.removeListener(handleHighContrastChange));
|
|
1508
|
-
} catch (cleanupError) {
|
|
1509
|
-
console.error("AtomixGlass: Error cleaning up media query listeners:", cleanupError);
|
|
1510
|
-
}
|
|
1660
|
+
// ignore
|
|
1511
1661
|
};
|
|
1512
1662
|
} catch (error) {
|
|
1513
|
-
return
|
|
1663
|
+
return;
|
|
1514
1664
|
}
|
|
1515
1665
|
}), [ overLight, glassRef, debugOverLight ]);
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
y: (globalPos.y - center.y) / rect.height * 100
|
|
1666
|
+
/**
|
|
1667
|
+
* Get effective overLight value based on configuration
|
|
1668
|
+
*/
|
|
1669
|
+
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))), []), baseOverLightConfig = useMemo((() => {
|
|
1670
|
+
const isOverLight = getEffectiveOverLight(), baseConfig = {
|
|
1671
|
+
isOverLight: isOverLight,
|
|
1672
|
+
threshold: .7,
|
|
1673
|
+
opacity: isOverLight ? Math.min(.6, Math.max(.2, .5)) : 0,
|
|
1674
|
+
contrast: 1,
|
|
1675
|
+
// Base contrast
|
|
1676
|
+
brightness: 1,
|
|
1677
|
+
// Base brightness
|
|
1678
|
+
saturationBoost: 1.3,
|
|
1679
|
+
shadowIntensity: .9,
|
|
1680
|
+
borderOpacity: .7
|
|
1532
1681
|
};
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
return;
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
|
|
1682
|
+
if ("object" == typeof overLight && null !== overLight) {
|
|
1683
|
+
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);
|
|
1684
|
+
return {
|
|
1685
|
+
...baseConfig,
|
|
1686
|
+
threshold: validatedThreshold,
|
|
1687
|
+
opacity: validatedOpacity,
|
|
1688
|
+
contrast: validatedContrast,
|
|
1689
|
+
brightness: validatedBrightness,
|
|
1690
|
+
saturationBoost: validatedSaturationBoost
|
|
1691
|
+
};
|
|
1692
|
+
}
|
|
1693
|
+
return baseConfig;
|
|
1694
|
+
}), [ overLight, getEffectiveOverLight, validateConfigValue ]), overLightConfig = useMemo((() => {
|
|
1695
|
+
const mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1;
|
|
1696
|
+
return {
|
|
1697
|
+
isOverLight: baseOverLightConfig.isOverLight,
|
|
1698
|
+
threshold: baseOverLightConfig.threshold,
|
|
1699
|
+
opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
|
|
1700
|
+
contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
|
|
1701
|
+
brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
|
|
1702
|
+
saturationBoost: baseOverLightConfig.saturationBoost,
|
|
1703
|
+
shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
|
|
1704
|
+
borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence))
|
|
1557
1705
|
};
|
|
1558
|
-
}), [
|
|
1559
|
-
|
|
1560
|
-
const calculateDirectionalScale = useCallback((() => {
|
|
1561
|
-
if (!0 === overLight || "auto" === overLight && detectedOverLight || "object" == typeof overLight && null !== overLight && detectedOverLight) return "scale(1)";
|
|
1706
|
+
}), [ baseOverLightConfig, mouseOffset, isHovered, isActive ]), updateRectRef = useRef(null), calculateDirectionalScale = useCallback((() => {
|
|
1707
|
+
if (baseOverLightConfig.isOverLight) return "scale(1)";
|
|
1562
1708
|
if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return "scale(1)";
|
|
1563
1709
|
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({
|
|
1564
1710
|
x: edgeDistanceX,
|
|
@@ -1572,7 +1718,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
1572
1718
|
if (0 === centerDistance) return "scale(1)";
|
|
1573
1719
|
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;
|
|
1574
1720
|
return `scaleX(${Math.max(.8, scaleX)}) scaleY(${Math.max(.8, scaleY)})`;
|
|
1575
|
-
}), [ globalMousePosition, elasticity, glassSize, glassRef,
|
|
1721
|
+
}), [ globalMousePosition, elasticity, glassSize, glassRef, baseOverLightConfig ]), calculateFadeInFactor = useCallback((() => {
|
|
1576
1722
|
if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return 0;
|
|
1577
1723
|
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({
|
|
1578
1724
|
x: edgeDistanceX,
|
|
@@ -1592,122 +1738,110 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
1592
1738
|
x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
|
|
1593
1739
|
y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
|
|
1594
1740
|
};
|
|
1595
|
-
}), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = useMemo((() =>
|
|
1741
|
+
}), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = useMemo((() => effectiveWithoutEffects ? {
|
|
1596
1742
|
x: 0,
|
|
1597
1743
|
y: 0
|
|
1598
|
-
} : calculateElasticTranslation()), [ calculateElasticTranslation,
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
const
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
if (rect.width <= 0 || rect.height <= 0) return void (rafId = null);
|
|
1611
|
-
// Measure actual rendered size without artificial offsets to avoid feedback loops
|
|
1612
|
-
const newSize = {
|
|
1613
|
-
width: Math.round(rect.width),
|
|
1614
|
-
height: Math.round(rect.height)
|
|
1615
|
-
}, cornerRadiusChanged = lastCornerRadius !== effectiveCornerRadius, dimensionsChanged = Math.abs(newSize.width - lastSize.width) > 1 || Math.abs(newSize.height - lastSize.height) > 1;
|
|
1616
|
-
var size;
|
|
1617
|
-
(forceUpdate || cornerRadiusChanged || dimensionsChanged) && validateGlassSize(size = newSize) && size.width <= CONSTANTS.MAX_SIZE && size.height <= CONSTANTS.MAX_SIZE && (lastSize = newSize,
|
|
1618
|
-
lastCornerRadius = effectiveCornerRadius, setGlassSize(newSize)), rafId = null;
|
|
1619
|
-
}));
|
|
1620
|
-
};
|
|
1621
|
-
let resizeTimeoutId = null;
|
|
1622
|
-
const debouncedResizeHandler = () => {
|
|
1623
|
-
resizeTimeoutId && clearTimeout(resizeTimeoutId), resizeTimeoutId = setTimeout((() => updateGlassSize(!1)), 16);
|
|
1624
|
-
}, initialTimeoutId = setTimeout((() => updateGlassSize(!0)), 0);
|
|
1625
|
-
let resizeObserver = null, resizeDebounceTimeout = null;
|
|
1626
|
-
// ResizeObserver has 98%+ browser support, no need for fallback
|
|
1627
|
-
if ("undefined" != typeof ResizeObserver && isValidElement(glassRef.current)) try {
|
|
1628
|
-
resizeObserver = new ResizeObserver((entries => {
|
|
1629
|
-
for (const entry of entries) if (entry.target === glassRef.current) {
|
|
1630
|
-
// Update cached rect when size changes
|
|
1631
|
-
glassRef.current && (cachedRectRef.current = glassRef.current.getBoundingClientRect()),
|
|
1632
|
-
// Debounce resize updates to match RAF timing (16ms)
|
|
1633
|
-
resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), resizeDebounceTimeout = setTimeout((() => updateGlassSize(!1)), 16);
|
|
1634
|
-
break;
|
|
1635
|
-
}
|
|
1636
|
-
})), resizeObserver.observe(glassRef.current);
|
|
1637
|
-
} catch (error) {
|
|
1638
|
-
console.warn("AtomixGlass: ResizeObserver not available, using window resize only", error);
|
|
1639
|
-
}
|
|
1640
|
-
return window.addEventListener("resize", debouncedResizeHandler, {
|
|
1641
|
-
passive: !0
|
|
1642
|
-
}), () => {
|
|
1643
|
-
clearTimeout(initialTimeoutId), null !== rafId && cancelAnimationFrame(rafId), resizeTimeoutId && clearTimeout(resizeTimeoutId),
|
|
1644
|
-
resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), window.removeEventListener("resize", debouncedResizeHandler),
|
|
1645
|
-
resizeObserver?.disconnect();
|
|
1744
|
+
} : 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 => {
|
|
1745
|
+
if (externalGlobalMousePosition && externalMouseOffset) return;
|
|
1746
|
+
if (effectiveWithoutEffects) return;
|
|
1747
|
+
const container = mouseContainer?.current || glassRef.current;
|
|
1748
|
+
if (!container) return;
|
|
1749
|
+
// Use cached rect if available, otherwise get new one
|
|
1750
|
+
let rect = cachedRectRef.current;
|
|
1751
|
+
if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
|
|
1752
|
+
cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
|
|
1753
|
+
const center = calculateElementCenter(rect), newOffset = {
|
|
1754
|
+
x: (globalPos.x - center.x) / rect.width * 100,
|
|
1755
|
+
y: (globalPos.y - center.y) / rect.height * 100
|
|
1646
1756
|
};
|
|
1647
|
-
|
|
1648
|
-
|
|
1757
|
+
// Calculate offset relative to this container
|
|
1758
|
+
// Store in refs instead of state
|
|
1759
|
+
internalMouseOffsetRef.current = newOffset, internalGlobalMousePositionRef.current = globalPos,
|
|
1760
|
+
// Imperative style update
|
|
1761
|
+
updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
|
|
1762
|
+
mouseOffset: newOffset,
|
|
1763
|
+
globalMousePosition: globalPos,
|
|
1764
|
+
glassSize: glassSize,
|
|
1765
|
+
isHovered: isHovered,
|
|
1766
|
+
isActive: isActive,
|
|
1767
|
+
isOverLight: baseOverLightConfig.isOverLight,
|
|
1768
|
+
baseOverLightConfig: baseOverLightConfig,
|
|
1769
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
1770
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
1771
|
+
effectiveReducedMotion: effectiveReducedMotion,
|
|
1772
|
+
elasticity: elasticity,
|
|
1773
|
+
directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
|
|
1774
|
+
// Simplified directional scale for fast path
|
|
1775
|
+
onClick: onClick,
|
|
1776
|
+
withLiquidBlur: withLiquidBlur,
|
|
1777
|
+
blurAmount: blurAmount,
|
|
1778
|
+
saturation: saturation,
|
|
1779
|
+
padding: padding
|
|
1780
|
+
});
|
|
1781
|
+
}), [ mouseContainer, glassRef, wrapperRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects, glassSize, isHovered, isActive, baseOverLightConfig, effectiveBorderRadius, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding ]);
|
|
1649
1782
|
/**
|
|
1650
|
-
*
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
const
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1783
|
+
* Validate and clamp a numeric config value
|
|
1784
|
+
*/
|
|
1785
|
+
// Subscribe to shared mouse tracker
|
|
1786
|
+
useEffect((() => {
|
|
1787
|
+
if (externalGlobalMousePosition && externalMouseOffset) return;
|
|
1788
|
+
if (effectiveWithoutEffects) return;
|
|
1789
|
+
const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition), container = mouseContainer?.current || glassRef.current;
|
|
1790
|
+
let resizeObserver = null;
|
|
1791
|
+
return container && "undefined" != typeof ResizeObserver && (resizeObserver = new ResizeObserver((() => {
|
|
1792
|
+
null !== updateRectRef.current && cancelAnimationFrame(updateRectRef.current), updateRectRef.current = requestAnimationFrame((() => {
|
|
1793
|
+
const container = mouseContainer?.current || glassRef.current;
|
|
1794
|
+
container && (cachedRectRef.current = container.getBoundingClientRect()), updateRectRef.current = null;
|
|
1795
|
+
}));
|
|
1796
|
+
})), resizeObserver.observe(container)), () => {
|
|
1797
|
+
unsubscribe(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
|
|
1798
|
+
updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
|
|
1666
1799
|
};
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1800
|
+
}), [ handleGlobalMousePosition, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects ]),
|
|
1801
|
+
// Also call updateStyles on other state changes (hover, active, etc)
|
|
1802
|
+
useEffect((() => {
|
|
1803
|
+
updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
|
|
1804
|
+
mouseOffset: externalMouseOffset || internalMouseOffsetRef.current,
|
|
1805
|
+
globalMousePosition: externalGlobalMousePosition || internalGlobalMousePositionRef.current,
|
|
1806
|
+
glassSize: glassSize,
|
|
1807
|
+
isHovered: isHovered,
|
|
1808
|
+
isActive: isActive,
|
|
1809
|
+
isOverLight: baseOverLightConfig.isOverLight,
|
|
1810
|
+
baseOverLightConfig: baseOverLightConfig,
|
|
1811
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
1812
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
1813
|
+
effectiveReducedMotion: effectiveReducedMotion,
|
|
1814
|
+
elasticity: elasticity,
|
|
1815
|
+
directionalScale: directionalScale,
|
|
1816
|
+
onClick: onClick,
|
|
1817
|
+
withLiquidBlur: withLiquidBlur,
|
|
1818
|
+
blurAmount: blurAmount,
|
|
1819
|
+
saturation: saturation,
|
|
1820
|
+
padding: padding
|
|
1821
|
+
});
|
|
1822
|
+
}), [ isHovered, isActive, glassSize, baseOverLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, directionalScale, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation, padding, onClick ]);
|
|
1823
|
+
// Event handlers
|
|
1824
|
+
const handleMouseEnter = useCallback((() => setIsHovered(!0)), []), handleMouseLeave = useCallback((() => setIsHovered(!1)), []), handleMouseDown = useCallback((() => setIsActive(!0)), []), handleMouseUp = useCallback((() => setIsActive(!1)), []), handleMouseMove = useCallback((_e => {}), []), handleKeyDown = useCallback((e => {
|
|
1682
1825
|
!onClick || "Enter" !== e.key && " " !== e.key || (e.preventDefault(), onClick());
|
|
1683
|
-
}), [ onClick ])
|
|
1684
|
-
|
|
1685
|
-
* Validate and clamp a numeric config value
|
|
1686
|
-
* @param value - The value to validate
|
|
1687
|
-
* @param min - Minimum allowed value
|
|
1688
|
-
* @param max - Maximum allowed value
|
|
1689
|
-
* @param defaultValue - Default value if validation fails
|
|
1690
|
-
* @returns Validated and clamped value
|
|
1691
|
-
*/ return {
|
|
1692
|
-
// State
|
|
1826
|
+
}), [ onClick ]);
|
|
1827
|
+
return {
|
|
1693
1828
|
isHovered: isHovered,
|
|
1694
1829
|
isActive: isActive,
|
|
1695
1830
|
glassSize: glassSize,
|
|
1696
|
-
|
|
1697
|
-
|
|
1831
|
+
dynamicBorderRadius: dynamicBorderRadius,
|
|
1832
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
1698
1833
|
effectiveReducedMotion: effectiveReducedMotion,
|
|
1699
1834
|
effectiveHighContrast: effectiveHighContrast,
|
|
1700
|
-
|
|
1835
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
1701
1836
|
detectedOverLight: detectedOverLight,
|
|
1702
1837
|
globalMousePosition: globalMousePosition,
|
|
1838
|
+
// This is now static (refs or props) unless prop changes
|
|
1703
1839
|
mouseOffset: mouseOffset,
|
|
1704
|
-
//
|
|
1840
|
+
// This is now static (refs or props) unless prop changes
|
|
1705
1841
|
overLightConfig: overLightConfig,
|
|
1706
|
-
// Transform calculations
|
|
1707
1842
|
elasticTranslation: elasticTranslation,
|
|
1708
1843
|
directionalScale: directionalScale,
|
|
1709
1844
|
transformStyle: transformStyle,
|
|
1710
|
-
// Event handlers
|
|
1711
1845
|
handleMouseEnter: handleMouseEnter,
|
|
1712
1846
|
handleMouseLeave: handleMouseLeave,
|
|
1713
1847
|
handleMouseDown: handleMouseDown,
|
|
@@ -1746,7 +1880,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
1746
1880
|
*
|
|
1747
1881
|
* @example
|
|
1748
1882
|
* // Manual border-radius override
|
|
1749
|
-
* <AtomixGlass
|
|
1883
|
+
* <AtomixGlass borderRadius={20}>
|
|
1750
1884
|
* <div>Content with 20px glass radius</div>
|
|
1751
1885
|
* </AtomixGlass>
|
|
1752
1886
|
*
|
|
@@ -1787,37 +1921,48 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
1787
1921
|
* <AtomixGlass overLight="auto" debugOverLight={true}>
|
|
1788
1922
|
* <div>Content with debug logging enabled</div>
|
|
1789
1923
|
* </AtomixGlass>
|
|
1790
|
-
*/ function AtomixGlass({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,
|
|
1791
|
-
const glassRef = useRef(null), contentRef = useRef(null), {isHovered: isHovered, isActive: isActive, glassSize: glassSize,
|
|
1924
|
+
*/ function AtomixGlass({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 = "", padding: padding = ATOMIX_GLASS.DEFAULTS.PADDING, 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, withBorder: withBorder = !0, withOverLightLayers: withOverLightLayers = ATOMIX_GLASS.DEFAULTS.ENABLE_OVER_LIGHT_LAYERS, debugPerformance: debugPerformance = !1, debugBorderRadius: debugBorderRadius = !1, debugOverLight: debugOverLight = !1, height: height, width: width, ...rest}) {
|
|
1925
|
+
const glassRef = useRef(null), contentRef = useRef(null), {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveBorderRadius: effectiveBorderRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveWithoutEffects: effectiveWithoutEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown} = useAtomixGlass({
|
|
1792
1926
|
glassRef: glassRef,
|
|
1793
1927
|
contentRef: contentRef,
|
|
1794
|
-
|
|
1928
|
+
borderRadius: borderRadius,
|
|
1795
1929
|
globalMousePosition: externalGlobalMousePosition,
|
|
1796
1930
|
mouseOffset: externalMouseOffset,
|
|
1797
1931
|
mouseContainer: mouseContainer,
|
|
1798
1932
|
overLight: overLight,
|
|
1799
1933
|
reducedMotion: reducedMotion,
|
|
1800
1934
|
highContrast: highContrast,
|
|
1801
|
-
|
|
1935
|
+
withoutEffects: withoutEffects,
|
|
1802
1936
|
elasticity: elasticity,
|
|
1803
1937
|
onClick: onClick,
|
|
1804
|
-
|
|
1938
|
+
debugBorderRadius: debugBorderRadius,
|
|
1805
1939
|
debugOverLight: debugOverLight,
|
|
1806
|
-
|
|
1807
|
-
children: children
|
|
1808
|
-
|
|
1940
|
+
debugPerformance: debugPerformance,
|
|
1941
|
+
children: children,
|
|
1942
|
+
blurAmount: blurAmount,
|
|
1943
|
+
saturation: saturation,
|
|
1944
|
+
withLiquidBlur: withLiquidBlur,
|
|
1945
|
+
padding: padding,
|
|
1946
|
+
style: style
|
|
1947
|
+
}), isOverLight = useMemo((() => overLightConfig?.isOverLight), [ overLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, baseStyle = {
|
|
1809
1948
|
...style,
|
|
1810
|
-
...!
|
|
1949
|
+
...!effectiveWithoutEffects && {
|
|
1811
1950
|
transform: transformStyle
|
|
1812
1951
|
}
|
|
1813
|
-
}, componentClassName = [ ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`,
|
|
1952
|
+
}, 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((() => ({
|
|
1814
1953
|
position: style.position || "absolute",
|
|
1815
1954
|
top: style.top || 0,
|
|
1816
1955
|
left: style.left || 0
|
|
1817
|
-
})), [ style.position, style.top, style.left ]), adjustedSize = useMemo((() =>
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1956
|
+
})), [ style.position, style.top, style.left ]), adjustedSize = useMemo((() => {
|
|
1957
|
+
const resolveSize = (propValue, styleValue, measuredSize) => {
|
|
1958
|
+
const explicitSize = propValue ?? styleValue;
|
|
1959
|
+
return void 0 !== explicitSize ? "number" == typeof explicitSize ? `${explicitSize}px` : explicitSize : "fixed" === positionStyles.position ? `${Math.max(measuredSize, 0)}px` : "100%";
|
|
1960
|
+
};
|
|
1961
|
+
return {
|
|
1962
|
+
width: resolveSize(width, style.width, glassSize.width),
|
|
1963
|
+
height: resolveSize(height, style.height, glassSize.height)
|
|
1964
|
+
};
|
|
1965
|
+
}), [ width, height, style.width, style.height, positionStyles.position, glassSize.width, glassSize.height ]), gradientValues = useMemo((() => {
|
|
1821
1966
|
const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT;
|
|
1822
1967
|
return {
|
|
1823
1968
|
borderGradientAngle: GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER,
|
|
@@ -1859,13 +2004,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
1859
2004
|
}), [ isHovered, isActive, isOverLight, overLightConfig.opacity ]), glassVars = useMemo((() => {
|
|
1860
2005
|
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;
|
|
1861
2006
|
return {
|
|
1862
|
-
"--atomix-glass-radius": `${
|
|
2007
|
+
"--atomix-glass-radius": `${effectiveBorderRadius}px`,
|
|
1863
2008
|
"--atomix-glass-transform": transformStyle || "none",
|
|
1864
2009
|
"--atomix-glass-position": positionStyles.position,
|
|
1865
2010
|
"--atomix-glass-top": "fixed" !== positionStyles.top ? `${positionStyles.top}px` : "0",
|
|
1866
2011
|
"--atomix-glass-left": "fixed" !== positionStyles.left ? `${positionStyles.left}px` : "0",
|
|
1867
|
-
"--atomix-glass-width":
|
|
1868
|
-
"--atomix-glass-height":
|
|
2012
|
+
"--atomix-glass-width": adjustedSize.width,
|
|
2013
|
+
"--atomix-glass-height": adjustedSize.height,
|
|
1869
2014
|
"--atomix-glass-border-width": "var(--atomix-spacing-0-5, 0.09375rem)",
|
|
1870
2015
|
"--atomix-glass-blend-mode": isOverLight ? "multiply" : "overlay",
|
|
1871
2016
|
"--atomix-glass-border-gradient-1": `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[0] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[1] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
|
|
@@ -1881,24 +2026,25 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
1881
2026
|
"--atomix-glass-overlay-opacity": opacityValues.over,
|
|
1882
2027
|
"--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})`
|
|
1883
2028
|
};
|
|
1884
|
-
}), [ gradientValues, opacityValues,
|
|
2029
|
+
}), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle, positionStyles, adjustedSize, isOverLight, overLightConfig.borderOpacity ]), renderBackgroundLayer = layerType => jsx("div", {
|
|
1885
2030
|
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(" "),
|
|
1886
2031
|
style: {
|
|
1887
2032
|
...positionStyles,
|
|
1888
2033
|
height: adjustedSize.height,
|
|
1889
2034
|
width: adjustedSize.width,
|
|
1890
|
-
borderRadius: `${
|
|
2035
|
+
borderRadius: `${effectiveBorderRadius}px`,
|
|
1891
2036
|
transform: baseStyle.transform
|
|
1892
2037
|
}
|
|
1893
2038
|
});
|
|
1894
2039
|
return jsxs("div", {
|
|
2040
|
+
...rest,
|
|
1895
2041
|
className: componentClassName,
|
|
1896
2042
|
style: glassVars,
|
|
1897
2043
|
role: role || (onClick ? "button" : void 0),
|
|
1898
2044
|
tabIndex: onClick ? tabIndex ?? 0 : tabIndex,
|
|
1899
2045
|
"aria-label": ariaLabel,
|
|
1900
2046
|
"aria-describedby": ariaDescribedBy,
|
|
1901
|
-
"aria-disabled": !(!onClick || !
|
|
2047
|
+
"aria-disabled": !(!onClick || !effectiveWithoutEffects) || !onClick && void 0,
|
|
1902
2048
|
"aria-pressed": !(!onClick || !isActive) || !onClick && void 0,
|
|
1903
2049
|
onKeyDown: onClick ? handleKeyDown : void 0,
|
|
1904
2050
|
children: [ jsx(AtomixGlassContainer, {
|
|
@@ -1906,18 +2052,18 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
1906
2052
|
contentRef: contentRef,
|
|
1907
2053
|
className: className,
|
|
1908
2054
|
style: baseStyle,
|
|
1909
|
-
|
|
1910
|
-
displacementScale:
|
|
1911
|
-
blurAmount:
|
|
2055
|
+
borderRadius: effectiveBorderRadius,
|
|
2056
|
+
displacementScale: effectiveWithoutEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
|
|
2057
|
+
blurAmount: effectiveWithoutEffects ? 0 : blurAmount,
|
|
1912
2058
|
saturation: effectiveHighContrast ? ATOMIX_GLASS.CONSTANTS.SATURATION.HIGH_CONTRAST : isOverLight ? saturation * overLightConfig.saturationBoost : saturation,
|
|
1913
|
-
aberrationIntensity:
|
|
2059
|
+
aberrationIntensity: effectiveWithoutEffects ? 0 : "shader" === mode ? aberrationIntensity * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_ABERRATION : aberrationIntensity,
|
|
1914
2060
|
glassSize: glassSize,
|
|
1915
2061
|
padding: padding,
|
|
1916
|
-
mouseOffset:
|
|
2062
|
+
mouseOffset: effectiveWithoutEffects ? {
|
|
1917
2063
|
x: 0,
|
|
1918
2064
|
y: 0
|
|
1919
2065
|
} : mouseOffset,
|
|
1920
|
-
globalMousePosition:
|
|
2066
|
+
globalMousePosition: effectiveWithoutEffects ? {
|
|
1921
2067
|
x: 0,
|
|
1922
2068
|
y: 0
|
|
1923
2069
|
} : globalMousePosition,
|
|
@@ -1937,11 +2083,11 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
1937
2083
|
onClick: onClick,
|
|
1938
2084
|
mode: mode,
|
|
1939
2085
|
transform: baseStyle.transform,
|
|
1940
|
-
|
|
2086
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
1941
2087
|
effectiveReducedMotion: effectiveReducedMotion,
|
|
1942
2088
|
shaderVariant: shaderVariant,
|
|
1943
2089
|
elasticity: elasticity,
|
|
1944
|
-
|
|
2090
|
+
withLiquidBlur: withLiquidBlur,
|
|
1945
2091
|
children: children
|
|
1946
2092
|
}), Boolean(onClick) && jsxs(Fragment, {
|
|
1947
2093
|
children: [ jsx("div", {
|
|
@@ -1963,11 +2109,19 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
1963
2109
|
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}%)`
|
|
1964
2110
|
}
|
|
1965
2111
|
}) ]
|
|
1966
|
-
}),
|
|
2112
|
+
}), withBorder && jsxs(Fragment, {
|
|
1967
2113
|
children: [ jsx("span", {
|
|
1968
|
-
className: ATOMIX_GLASS.BORDER_1_CLASS
|
|
2114
|
+
className: ATOMIX_GLASS.BORDER_1_CLASS,
|
|
2115
|
+
style: {
|
|
2116
|
+
width: glassSize.width,
|
|
2117
|
+
height: glassSize.height
|
|
2118
|
+
}
|
|
1969
2119
|
}), jsx("span", {
|
|
1970
|
-
className: ATOMIX_GLASS.BORDER_2_CLASS
|
|
2120
|
+
className: ATOMIX_GLASS.BORDER_2_CLASS,
|
|
2121
|
+
style: {
|
|
2122
|
+
width: glassSize.width,
|
|
2123
|
+
height: glassSize.height
|
|
2124
|
+
}
|
|
1971
2125
|
}) ]
|
|
1972
2126
|
}) ]
|
|
1973
2127
|
});
|
|
@@ -2235,7 +2389,7 @@ const Accordion = AccordionWithSubcomponents, Badge = memo((({label: label, var
|
|
|
2235
2389
|
// Default glass settings for badges
|
|
2236
2390
|
const defaultGlassProps = {
|
|
2237
2391
|
displacementScale: 20,
|
|
2238
|
-
|
|
2392
|
+
borderRadius: ref.current?.getBoundingClientRect().width ? ref.current?.getBoundingClientRect().width / 2 : 16,
|
|
2239
2393
|
className: "c-badge--glass",
|
|
2240
2394
|
elasticity: 0
|
|
2241
2395
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
@@ -2356,7 +2510,7 @@ const Block = forwardRef((({children: children, as: Component = "section", spac
|
|
|
2356
2510
|
* ```
|
|
2357
2511
|
*/ Block.displayName = "Block";
|
|
2358
2512
|
|
|
2359
|
-
const BreadcrumbItem = forwardRef((({children: children, href: href, active: active, icon: icon, onClick: onClick, className: className = "", style: style, linkAs:
|
|
2513
|
+
const BreadcrumbItem = forwardRef((({children: children, href: href, active: active, icon: icon, onClick: onClick, className: className = "", style: style, linkAs: linkAs, linkProps: linkProps = {}, ...props}, ref) => {
|
|
2360
2514
|
const itemClasses = [ BREADCRUMB.CLASSES.ITEM, active ? BREADCRUMB.CLASSES.ACTIVE : "", className ].filter(Boolean).join(" "), linkContent = jsxs(Fragment, {
|
|
2361
2515
|
children: [ icon && jsx("span", {
|
|
2362
2516
|
className: "c-breadcrumb__icon",
|
|
@@ -2374,7 +2528,9 @@ const BreadcrumbItem = forwardRef((({children: children, href: href, active: ac
|
|
|
2374
2528
|
className: itemClasses,
|
|
2375
2529
|
style: style,
|
|
2376
2530
|
...props,
|
|
2377
|
-
children: href && !active ?
|
|
2531
|
+
children: href && !active ?
|
|
2532
|
+
// @ts-ignore - Dynamic components are tricky in TS without stricter types
|
|
2533
|
+
jsx(linkAs || "a", {
|
|
2378
2534
|
href: href,
|
|
2379
2535
|
...commonLinkProps,
|
|
2380
2536
|
children: linkContent
|
|
@@ -2387,7 +2543,7 @@ const BreadcrumbItem = forwardRef((({children: children, href: href, active: ac
|
|
|
2387
2543
|
|
|
2388
2544
|
BreadcrumbItem.displayName = "BreadcrumbItem";
|
|
2389
2545
|
|
|
2390
|
-
const Breadcrumb = memo((({items: items, divider: divider, className: className = "", "aria-label": ariaLabel = "Breadcrumb", LinkComponent: LinkComponent, style: style, children: children})
|
|
2546
|
+
const Breadcrumb = memo((function({items: items, divider: divider, className: className = "", "aria-label": ariaLabel = "Breadcrumb", LinkComponent: LinkComponent, style: style, children: children}) {
|
|
2391
2547
|
const breadcrumbClasses = [ BREADCRUMB.CLASSES.BASE, className ].filter(Boolean).join(" ");
|
|
2392
2548
|
let content;
|
|
2393
2549
|
if (items && items.length > 0)
|
|
@@ -2409,11 +2565,11 @@ const Breadcrumb = memo((({items: items, divider: divider, className: className
|
|
|
2409
2565
|
const childrenCount = Children.count(children);
|
|
2410
2566
|
content = Children.map(children, ((child, index) => {
|
|
2411
2567
|
if ( isValidElement(child)) {
|
|
2412
|
-
const isLast = index === childrenCount - 1, childProps = child.props;
|
|
2568
|
+
const isLast = index === childrenCount - 1, childProps = child.props, {active: active, linkAs: linkAs, ...otherProps} = childProps;
|
|
2413
2569
|
|
|
2414
2570
|
return cloneElement(child, {
|
|
2415
|
-
active:
|
|
2416
|
-
linkAs:
|
|
2571
|
+
active: active ?? (!!isLast || void 0),
|
|
2572
|
+
linkAs: linkAs ?? LinkComponent
|
|
2417
2573
|
});
|
|
2418
2574
|
}
|
|
2419
2575
|
return child;
|
|
@@ -2480,7 +2636,7 @@ const Spinner = memo((({size: size = "md", variant: variant = "primary", fullsc
|
|
|
2480
2636
|
const defaultGlassProps = {
|
|
2481
2637
|
displacementScale: 20,
|
|
2482
2638
|
blurAmount: 1,
|
|
2483
|
-
|
|
2639
|
+
borderRadius: 999,
|
|
2484
2640
|
mode: "shader"
|
|
2485
2641
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
2486
2642
|
...defaultGlassProps,
|
|
@@ -3135,7 +3291,7 @@ const Callout = memo((({title: title, children: children, icon: icon, variant:
|
|
|
3135
3291
|
// Default glass settings for callouts
|
|
3136
3292
|
const defaultGlassProps = {
|
|
3137
3293
|
displacementScale: 30,
|
|
3138
|
-
|
|
3294
|
+
borderRadius: 8,
|
|
3139
3295
|
elasticity: 0
|
|
3140
3296
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
3141
3297
|
...defaultGlassProps,
|
|
@@ -3157,7 +3313,7 @@ const Callout = memo((({title: title, children: children, icon: icon, variant:
|
|
|
3157
3313
|
children: jsx("div", {
|
|
3158
3314
|
className: "c-callout__glass-content",
|
|
3159
3315
|
style: {
|
|
3160
|
-
borderRadius: glassProps.
|
|
3316
|
+
borderRadius: glassProps.borderRadius
|
|
3161
3317
|
},
|
|
3162
3318
|
children: calloutContent
|
|
3163
3319
|
})
|