@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/forms.js
CHANGED
|
@@ -218,7 +218,7 @@ import React, { memo, forwardRef, useMemo, useState, useRef, useEffect, useCallb
|
|
|
218
218
|
HIGH_CONTRAST: 200
|
|
219
219
|
}
|
|
220
220
|
}
|
|
221
|
-
}, {CONSTANTS: CONSTANTS$
|
|
221
|
+
}, {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateDistance = (pos1, pos2) => {
|
|
222
222
|
if (!pos1 || !pos2 || "number" != typeof pos1.x || "number" != typeof pos1.y || "number" != typeof pos2.x || "number" != typeof pos2.y) return 0;
|
|
223
223
|
const deltaX = pos1.x - pos2.x, deltaY = pos1.y - pos2.y;
|
|
224
224
|
return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
@@ -231,36 +231,36 @@ import React, { memo, forwardRef, useMemo, useState, useRef, useEffect, useCallb
|
|
|
231
231
|
}, calculateMouseInfluence = mouseOffset => {
|
|
232
232
|
if (!mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y) return 0;
|
|
233
233
|
// Bounded calculation — keeps the glass effect subtle and stable
|
|
234
|
-
const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$
|
|
234
|
+
const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$2.MOUSE_INFLUENCE_DIVISOR;
|
|
235
235
|
return Math.min(.8, influence);
|
|
236
236
|
// Tighter cap to prevent blur/filter blow-out
|
|
237
|
-
}, clampBlur = value => "number" != typeof value || isNaN(value) ? CONSTANTS$
|
|
237
|
+
}, 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 => {
|
|
238
238
|
if ("number" == typeof value) return Math.max(0, value);
|
|
239
|
-
if ("string" != typeof value || !value.trim()) return CONSTANTS$
|
|
239
|
+
if ("string" != typeof value || !value.trim()) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
240
240
|
const trimmedValue = value.trim();
|
|
241
241
|
// Handle px values
|
|
242
242
|
if (trimmedValue.endsWith("px")) {
|
|
243
243
|
const parsed = parseFloat(trimmedValue);
|
|
244
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
244
|
+
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
|
|
245
245
|
}
|
|
246
246
|
// Handle rem values (assume 16px = 1rem)
|
|
247
247
|
if (trimmedValue.endsWith("rem")) {
|
|
248
248
|
const parsed = parseFloat(trimmedValue);
|
|
249
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
249
|
+
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
250
250
|
}
|
|
251
251
|
// Handle em values (assume 16px = 1em for simplicity)
|
|
252
252
|
if (trimmedValue.endsWith("em")) {
|
|
253
253
|
const parsed = parseFloat(trimmedValue);
|
|
254
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
254
|
+
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
255
255
|
}
|
|
256
256
|
// Handle percentage (convert to approximate px value, assuming 200px container)
|
|
257
257
|
if (trimmedValue.endsWith("%")) {
|
|
258
258
|
const parsed = parseFloat(trimmedValue);
|
|
259
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
259
|
+
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
|
|
260
260
|
}
|
|
261
261
|
// Handle unitless numbers
|
|
262
262
|
const numValue = parseFloat(trimmedValue);
|
|
263
|
-
return isNaN(numValue) ? CONSTANTS$
|
|
263
|
+
return isNaN(numValue) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
|
|
264
264
|
}, extractBorderRadiusFromElement = element => {
|
|
265
265
|
if (!element || !element.props) return null;
|
|
266
266
|
// Check inline styles first (highest priority)
|
|
@@ -276,11 +276,11 @@ import React, { memo, forwardRef, useMemo, useState, useRef, useEffect, useCallb
|
|
|
276
276
|
// If element has children, recursively check them
|
|
277
277
|
if (element.props.children) {
|
|
278
278
|
const childRadius = extractBorderRadiusFromChildren(element.props.children);
|
|
279
|
-
if (childRadius > 0 && childRadius !== CONSTANTS$
|
|
279
|
+
if (childRadius > 0 && childRadius !== CONSTANTS$2.DEFAULT_CORNER_RADIUS) return childRadius;
|
|
280
280
|
}
|
|
281
281
|
return null;
|
|
282
282
|
}, extractBorderRadiusFromChildren = children => {
|
|
283
|
-
if (!children) return CONSTANTS$
|
|
283
|
+
if (!children) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
284
284
|
try {
|
|
285
285
|
const childArray = React.Children.toArray(children);
|
|
286
286
|
for (let i = 0; i < childArray.length; i++) {
|
|
@@ -293,7 +293,7 @@ import React, { memo, forwardRef, useMemo, useState, useRef, useEffect, useCallb
|
|
|
293
293
|
} catch (error) {
|
|
294
294
|
// Silently handle errors
|
|
295
295
|
}
|
|
296
|
-
return CONSTANTS$
|
|
296
|
+
return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
297
297
|
}, getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
|
|
298
298
|
switch (mode) {
|
|
299
299
|
case "standard":
|
|
@@ -464,10 +464,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
464
464
|
}, globalMousePosition: globalMousePosition = {
|
|
465
465
|
x: 0,
|
|
466
466
|
y: 0
|
|
467
|
-
}, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isHovered: isHovered = !1, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {},
|
|
467
|
+
}, 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 = {
|
|
468
468
|
width: 0,
|
|
469
469
|
height: 0
|
|
470
|
-
}, onClick: onClick, mode: mode = "standard",
|
|
470
|
+
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, elasticity: elasticity = 0, contentRef: contentRef}, ref) => {
|
|
471
471
|
// Generate a stable, deterministic ID for SSR compatibility
|
|
472
472
|
// Use a module-level counter that's consistent across server and client
|
|
473
473
|
const filterId = useMemo((() => "atomix-glass-filter-" + ++idCounter), []), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null);
|
|
@@ -577,7 +577,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
577
577
|
flowBlur: 1.2 * blurAmount
|
|
578
578
|
};
|
|
579
579
|
// Enhanced validation for liquid blur
|
|
580
|
-
if (!
|
|
580
|
+
if (!withLiquidBlur || !rectCache || !mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y || isNaN(mouseOffset.x) || isNaN(mouseOffset.y)) return defaultBlur;
|
|
581
581
|
try {
|
|
582
582
|
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);
|
|
583
583
|
// NOTE: hover/active multipliers intentionally omitted here —
|
|
@@ -592,14 +592,14 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
592
592
|
return console.warn("AtomixGlassContainer: Error calculating liquid blur", error),
|
|
593
593
|
defaultBlur;
|
|
594
594
|
}
|
|
595
|
-
}), [
|
|
595
|
+
}), [ withLiquidBlur, blurAmount, mouseOffset, rectCache ]), backdropStyle = useMemo((() => {
|
|
596
596
|
try {
|
|
597
597
|
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;
|
|
598
598
|
// Validate blur values before using them
|
|
599
|
-
return !
|
|
599
|
+
return !withLiquidBlur || effectiveReducedMotion || effectiveWithoutEffects || area > 18e4 ? {
|
|
600
600
|
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})`
|
|
601
601
|
} : {
|
|
602
|
-
backdropFilter: `blur(${clampBlur(.4 * validatedBaseBlur + .25 * validatedEdgeBlur + .15 * validatedCenterBlur + .2 * validatedFlowBlur)}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1
|
|
602
|
+
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})`
|
|
603
603
|
};
|
|
604
604
|
// Single-pass fallback: stronger radius to match perceived blur of multi-pass
|
|
605
605
|
} catch (error) {
|
|
@@ -608,7 +608,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
608
608
|
backdropFilter: `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`
|
|
609
609
|
};
|
|
610
610
|
}
|
|
611
|
-
}), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion,
|
|
611
|
+
}), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveWithoutEffects, withLiquidBlur ]), containerVars = useMemo((() => {
|
|
612
612
|
try {
|
|
613
613
|
// Safe extraction of mouse offset values
|
|
614
614
|
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;
|
|
@@ -616,10 +616,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
616
616
|
"--atomix-glass-container-width": `${glassSize?.width}`,
|
|
617
617
|
"--atomix-glass-container-height": `${glassSize?.height}`,
|
|
618
618
|
"--atomix-glass-container-padding": padding || "0 0",
|
|
619
|
-
"--atomix-glass-container-radius": `${"number" != typeof
|
|
619
|
+
"--atomix-glass-container-radius": `${"number" != typeof borderRadius || isNaN(borderRadius) ? 0 : borderRadius}px`,
|
|
620
620
|
"--atomix-glass-container-backdrop": backdropStyle?.backdropFilter || "none",
|
|
621
621
|
"--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",
|
|
622
|
-
"--atomix-glass-container-shadow-opacity":
|
|
622
|
+
"--atomix-glass-container-shadow-opacity": effectiveWithoutEffects ? 0 : 1,
|
|
623
623
|
// Background and shadow values use design token-aligned RGB values
|
|
624
624
|
"--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",
|
|
625
625
|
"--atomix-glass-container-text-shadow": overLight ? "0px 2px 12px rgba(0, 0, 0, 0)" : "0px 2px 12px rgba(0, 0, 0, 0.4)",
|
|
@@ -637,14 +637,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
637
637
|
"--atomix-glass-container-text-shadow": "none"
|
|
638
638
|
};
|
|
639
639
|
}
|
|
640
|
-
}), [ glassSize, padding,
|
|
641
|
-
el && (el.style.setProperty("transition-duration", "0s", "important"), el.style.setProperty("animation-duration", "0s", "important"),
|
|
642
|
-
el.style.setProperty("transition-delay", "0s", "important"));
|
|
643
|
-
};
|
|
640
|
+
}), [ glassSize, padding, borderRadius, backdropStyle, mouseOffset, overLight, effectiveWithoutEffects ]);
|
|
644
641
|
return jsx("div", {
|
|
645
642
|
ref: el => {
|
|
646
643
|
// Apply force no-transition
|
|
647
|
-
setForceNoTransition(el),
|
|
648
644
|
// Handle forwarded ref
|
|
649
645
|
"function" == typeof ref ? ref(el) : ref && (ref.current = el);
|
|
650
646
|
},
|
|
@@ -679,7 +675,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
679
675
|
aberrationIntensity: "number" != typeof aberrationIntensity || isNaN(aberrationIntensity) ? 0 : aberrationIntensity,
|
|
680
676
|
shaderMapUrl: shaderMapUrl
|
|
681
677
|
}), jsx("div", {
|
|
682
|
-
ref:
|
|
678
|
+
ref: el => {
|
|
679
|
+
el && (el.style.setProperty("transition-duration", "0s", "important"), el.style.setProperty("animation-duration", "0s", "important"),
|
|
680
|
+
el.style.setProperty("transition-delay", "0s", "important"));
|
|
681
|
+
},
|
|
683
682
|
className: ATOMIX_GLASS.FILTER_OVERLAY_CLASS,
|
|
684
683
|
style: {
|
|
685
684
|
filter: `url(#${filterId})`,
|
|
@@ -796,7 +795,128 @@ class {
|
|
|
796
795
|
*/ getSubscriberCount() {
|
|
797
796
|
return this.listeners.size;
|
|
798
797
|
}
|
|
799
|
-
},
|
|
798
|
+
}, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
|
|
799
|
+
if (!wrapperElement && !containerElement) return;
|
|
800
|
+
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 = {
|
|
801
|
+
opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
|
|
802
|
+
contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
|
|
803
|
+
brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
|
|
804
|
+
shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
|
|
805
|
+
borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence)),
|
|
806
|
+
saturationBoost: baseOverLightConfig.saturationBoost
|
|
807
|
+
};
|
|
808
|
+
// Calculate mouse influence
|
|
809
|
+
// Calculate elastic translation
|
|
810
|
+
let elasticTranslation = {
|
|
811
|
+
x: 0,
|
|
812
|
+
y: 0
|
|
813
|
+
};
|
|
814
|
+
if (!effectiveWithoutEffects && wrapperElement) {
|
|
815
|
+
const rect = wrapperElement.getBoundingClientRect(), center = calculateElementCenter(rect);
|
|
816
|
+
// Calculate fade in factor
|
|
817
|
+
let fadeInFactor = 0;
|
|
818
|
+
if (globalMousePosition.x && globalMousePosition.y && validateGlassSize(glassSize)) {
|
|
819
|
+
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({
|
|
820
|
+
x: edgeDistanceX,
|
|
821
|
+
y: edgeDistanceY
|
|
822
|
+
}, {
|
|
823
|
+
x: 0,
|
|
824
|
+
y: 0
|
|
825
|
+
});
|
|
826
|
+
fadeInFactor = edgeDistance > ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE ? 0 : 1 - edgeDistance / ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE;
|
|
827
|
+
}
|
|
828
|
+
elasticTranslation = {
|
|
829
|
+
x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
|
|
830
|
+
y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
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}`;
|
|
834
|
+
// Update Wrapper Styles (glassVars)
|
|
835
|
+
if (wrapperElement) {
|
|
836
|
+
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 = {
|
|
837
|
+
hover1: {
|
|
838
|
+
x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1,
|
|
839
|
+
y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1
|
|
840
|
+
},
|
|
841
|
+
hover2: {
|
|
842
|
+
x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_2,
|
|
843
|
+
y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_2
|
|
844
|
+
},
|
|
845
|
+
hover3: {
|
|
846
|
+
x: GRADIENT.CENTER_POSITION + mx * GRADIENT.HOVER_POSITION.MULTIPLIER_3,
|
|
847
|
+
y: GRADIENT.CENTER_POSITION + my * GRADIENT.HOVER_POSITION.MULTIPLIER_3
|
|
848
|
+
}
|
|
849
|
+
}, basePosition = {
|
|
850
|
+
x: GRADIENT.CENTER_POSITION + mx * GRADIENT.BASE_LAYER_MULTIPLIER,
|
|
851
|
+
y: GRADIENT.CENTER_POSITION + my * GRADIENT.BASE_LAYER_MULTIPLIER
|
|
852
|
+
}, opacityValues = {
|
|
853
|
+
hover1: isHovered || isActive ? .5 : 0,
|
|
854
|
+
hover2: isActive ? .5 : 0,
|
|
855
|
+
hover3: isHovered ? .4 : isActive ? .8 : 0,
|
|
856
|
+
base: isOverLight ? overLightConfig.opacity : 0,
|
|
857
|
+
over: isOverLight ? 1.1 * overLightConfig.opacity : 0
|
|
858
|
+
}, style = wrapperElement.style;
|
|
859
|
+
style.setProperty("--atomix-glass-transform", transformStyle || "none"),
|
|
860
|
+
// Gradients
|
|
861
|
+
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%)`),
|
|
862
|
+
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%)`),
|
|
863
|
+
// Hover gradients
|
|
864
|
+
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}%)`),
|
|
865
|
+
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}%)`),
|
|
866
|
+
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}%)`),
|
|
867
|
+
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})`),
|
|
868
|
+
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})`),
|
|
869
|
+
// Opacities
|
|
870
|
+
style.setProperty("--atomix-glass-hover-1-opacity", opacityValues.hover1.toString()),
|
|
871
|
+
style.setProperty("--atomix-glass-hover-2-opacity", opacityValues.hover2.toString()),
|
|
872
|
+
style.setProperty("--atomix-glass-hover-3-opacity", opacityValues.hover3.toString()),
|
|
873
|
+
style.setProperty("--atomix-glass-base-opacity", opacityValues.base.toString()),
|
|
874
|
+
style.setProperty("--atomix-glass-overlay-opacity", opacityValues.over.toString()),
|
|
875
|
+
style.setProperty("--atomix-glass-overlay-highlight-opacity", (opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER).toString()),
|
|
876
|
+
// Other
|
|
877
|
+
style.setProperty("--atomix-glass-blend-mode", isOverLight ? "multiply" : "overlay"),
|
|
878
|
+
style.setProperty("--atomix-glass-radius", `${effectiveBorderRadius}px`);
|
|
879
|
+
}
|
|
880
|
+
// Update Container Styles (containerVars)
|
|
881
|
+
if (containerElement) {
|
|
882
|
+
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();
|
|
883
|
+
let liquidBlur = {
|
|
884
|
+
baseBlur: blurAmount,
|
|
885
|
+
edgeBlur: blurAmount * EDGE_BLUR_MULTIPLIER,
|
|
886
|
+
centerBlur: blurAmount * CENTER_BLUR_MULTIPLIER,
|
|
887
|
+
flowBlur: blurAmount * FLOW_BLUR_MULTIPLIER
|
|
888
|
+
};
|
|
889
|
+
if (withLiquidBlur && rect) {
|
|
890
|
+
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);
|
|
891
|
+
liquidBlur = {
|
|
892
|
+
baseBlur: clampBlur(baseBlur),
|
|
893
|
+
edgeBlur: clampBlur(edgeBlur),
|
|
894
|
+
centerBlur: clampBlur(centerBlur),
|
|
895
|
+
flowBlur: clampBlur(flowBlur)
|
|
896
|
+
};
|
|
897
|
+
}
|
|
898
|
+
// Backdrop filter
|
|
899
|
+
let backdropFilterString = `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`;
|
|
900
|
+
const dynamicSaturation = saturation + 20 * (liquidBlur.baseBlur || 0), area = rect ? rect.width * rect.height : 0;
|
|
901
|
+
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})`;
|
|
902
|
+
// Container variables
|
|
903
|
+
const style = containerElement.style;
|
|
904
|
+
style.setProperty("--atomix-glass-container-width", `${glassSize.width}`), style.setProperty("--atomix-glass-container-height", `${glassSize.height}`),
|
|
905
|
+
style.setProperty("--atomix-glass-container-padding", padding), style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
|
|
906
|
+
style.setProperty("--atomix-glass-container-backdrop", backdropFilterString),
|
|
907
|
+
// Shadows
|
|
908
|
+
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"),
|
|
909
|
+
style.setProperty("--atomix-glass-container-shadow-opacity", effectiveWithoutEffects ? "0" : "1"),
|
|
910
|
+
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"),
|
|
911
|
+
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)"),
|
|
912
|
+
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)");
|
|
913
|
+
}
|
|
914
|
+
}, {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS;
|
|
915
|
+
|
|
916
|
+
/**
|
|
917
|
+
* Updates the styles of the AtomixGlass wrapper and container elements imperatively
|
|
918
|
+
* to avoid React re-renders on mouse movement.
|
|
919
|
+
*/ const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
|
|
800
920
|
parentElement && backgroundDetectionCache.set(parentElement, {
|
|
801
921
|
result: result,
|
|
802
922
|
timestamp: Date.now(),
|
|
@@ -809,18 +929,74 @@ class {
|
|
|
809
929
|
* Composable hook for AtomixGlass component logic
|
|
810
930
|
* Manages all state, calculations, and event handlers
|
|
811
931
|
*/
|
|
812
|
-
function useAtomixGlass({glassRef: glassRef, contentRef: contentRef,
|
|
932
|
+
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}) {
|
|
813
933
|
// State
|
|
814
|
-
const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1),
|
|
815
|
-
width: 270,
|
|
816
|
-
height: 69
|
|
817
|
-
}), [internalGlobalMousePosition, setInternalGlobalMousePosition] = useState({
|
|
934
|
+
const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), cachedRectRef = useRef(null), internalGlobalMousePositionRef = useRef({
|
|
818
935
|
x: 0,
|
|
819
936
|
y: 0
|
|
820
|
-
}),
|
|
937
|
+
}), internalMouseOffsetRef = useRef({
|
|
821
938
|
x: 0,
|
|
822
939
|
y: 0
|
|
823
|
-
}), [
|
|
940
|
+
}), [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}) {
|
|
941
|
+
const [glassSize, setGlassSize] = useState({
|
|
942
|
+
width: 270,
|
|
943
|
+
height: 69
|
|
944
|
+
});
|
|
945
|
+
return useEffect((() => {
|
|
946
|
+
const isValidElement = element => null !== element && element instanceof HTMLElement && element.isConnected;
|
|
947
|
+
let rafId = null, lastSize = {
|
|
948
|
+
width: 0,
|
|
949
|
+
height: 0
|
|
950
|
+
}, lastCornerRadius = effectiveBorderRadius;
|
|
951
|
+
const updateGlassSize = (forceUpdate = !1) => {
|
|
952
|
+
null !== rafId && cancelAnimationFrame(rafId), rafId = requestAnimationFrame((() => {
|
|
953
|
+
if (!isValidElement(glassRef.current)) return void (rafId = null);
|
|
954
|
+
const rect = glassRef.current.getBoundingClientRect();
|
|
955
|
+
if (rect.width <= 0 || rect.height <= 0) return void (rafId = null);
|
|
956
|
+
// Measure actual rendered size without artificial offsets to avoid feedback loops
|
|
957
|
+
const newSize = {
|
|
958
|
+
width: Math.round(rect.width),
|
|
959
|
+
height: Math.round(rect.height)
|
|
960
|
+
}, cornerRadiusChanged = lastCornerRadius !== effectiveBorderRadius, dimensionsChanged = Math.abs(newSize.width - lastSize.width) > 1 || Math.abs(newSize.height - lastSize.height) > 1;
|
|
961
|
+
var size;
|
|
962
|
+
(forceUpdate || cornerRadiusChanged || dimensionsChanged) && validateGlassSize(size = newSize) && size.width <= CONSTANTS$1.MAX_SIZE && size.height <= CONSTANTS$1.MAX_SIZE && (lastSize = newSize,
|
|
963
|
+
lastCornerRadius = effectiveBorderRadius, setGlassSize(newSize)), rafId = null;
|
|
964
|
+
}));
|
|
965
|
+
};
|
|
966
|
+
let resizeTimeoutId = null;
|
|
967
|
+
const debouncedResizeHandler = () => {
|
|
968
|
+
resizeTimeoutId && clearTimeout(resizeTimeoutId), resizeTimeoutId = setTimeout((() => updateGlassSize(!1)), 16);
|
|
969
|
+
}, initialTimeoutId = setTimeout((() => updateGlassSize(!0)), 0);
|
|
970
|
+
let resizeObserver = null, resizeDebounceTimeout = null;
|
|
971
|
+
// ResizeObserver has 98%+ browser support, no need for fallback
|
|
972
|
+
if ("undefined" != typeof ResizeObserver && isValidElement(glassRef.current)) try {
|
|
973
|
+
resizeObserver = new ResizeObserver((entries => {
|
|
974
|
+
for (const entry of entries) if (entry.target === glassRef.current) {
|
|
975
|
+
// Update cached rect when size changes
|
|
976
|
+
glassRef.current && cachedRectRef && (cachedRectRef.current = glassRef.current.getBoundingClientRect()),
|
|
977
|
+
// Debounce resize updates to match RAF timing (16ms)
|
|
978
|
+
resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), resizeDebounceTimeout = setTimeout((() => updateGlassSize(!1)), 16);
|
|
979
|
+
break;
|
|
980
|
+
}
|
|
981
|
+
})), resizeObserver.observe(glassRef.current);
|
|
982
|
+
} catch (error) {
|
|
983
|
+
console.warn("AtomixGlass: ResizeObserver not available, using window resize only", error);
|
|
984
|
+
}
|
|
985
|
+
return window.addEventListener("resize", debouncedResizeHandler, {
|
|
986
|
+
passive: !0
|
|
987
|
+
}), () => {
|
|
988
|
+
clearTimeout(initialTimeoutId), null !== rafId && cancelAnimationFrame(rafId), resizeTimeoutId && clearTimeout(resizeTimeoutId),
|
|
989
|
+
resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), window.removeEventListener("resize", debouncedResizeHandler),
|
|
990
|
+
resizeObserver?.disconnect();
|
|
991
|
+
};
|
|
992
|
+
}), [ effectiveBorderRadius, glassRef, cachedRectRef ]), {
|
|
993
|
+
glassSize: glassSize
|
|
994
|
+
};
|
|
995
|
+
}({
|
|
996
|
+
glassRef: glassRef,
|
|
997
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
998
|
+
cachedRectRef: cachedRectRef
|
|
999
|
+
}), 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;
|
|
824
1000
|
// Extract border-radius from children
|
|
825
1001
|
useEffect((() => {
|
|
826
1002
|
const extractRadius = () => {
|
|
@@ -851,13 +1027,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
851
1027
|
}
|
|
852
1028
|
null !== extractedRadius && extractedRadius > 0 && setDynamicCornerRadius(extractedRadius);
|
|
853
1029
|
} catch (error) {
|
|
854
|
-
"undefined" != typeof process && "production" === process.env?.NODE_ENV || !
|
|
1030
|
+
"undefined" != typeof process && "production" === process.env?.NODE_ENV || !debugBorderRadius || console.error("[AtomixGlass] Error extracting corner radius:", error);
|
|
855
1031
|
}
|
|
856
1032
|
};
|
|
857
1033
|
extractRadius();
|
|
858
1034
|
const timeoutId = setTimeout(extractRadius, 100);
|
|
859
1035
|
return () => clearTimeout(timeoutId);
|
|
860
|
-
}), [ children,
|
|
1036
|
+
}), [ children, debugBorderRadius, contentRef ]),
|
|
861
1037
|
// Media query handlers and background detection
|
|
862
1038
|
useEffect((() => {
|
|
863
1039
|
if (("auto" === overLight || "object" == typeof overLight && null !== overLight) && glassRef.current) {
|
|
@@ -913,72 +1089,52 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
913
1089
|
const rgb = bgColor.match(/\d+/g);
|
|
914
1090
|
if (rgb && rgb.length >= 3) {
|
|
915
1091
|
const r = Number(rgb[0]), g = Number(rgb[1]), b = Number(rgb[2]);
|
|
916
|
-
|
|
917
|
-
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)) {
|
|
1092
|
+
if (!isNaN(r) && !isNaN(g) && !isNaN(b) && (r > 10 || g > 10 || b > 10)) {
|
|
918
1093
|
const luminance = (.299 * r + .587 * g + .114 * b) / 255;
|
|
919
1094
|
!isNaN(luminance) && isFinite(luminance) && (totalLuminance += luminance, validSamples++,
|
|
920
1095
|
hasValidBackground = !0);
|
|
921
1096
|
}
|
|
922
1097
|
}
|
|
923
1098
|
}
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
// For image backgrounds, assume medium luminance
|
|
927
|
-
totalLuminance += .5, validSamples++, hasValidBackground = !0);
|
|
1099
|
+
bgImage && "none" !== bgImage && "initial" !== bgImage && (totalLuminance += .5,
|
|
1100
|
+
validSamples++, hasValidBackground = !0);
|
|
928
1101
|
} catch (styleError) {
|
|
929
|
-
|
|
1102
|
+
// Silently continue
|
|
930
1103
|
}
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
// Exit loop if currentElement becomes null
|
|
934
|
-
currentElement = currentElement.parentElement, depth++;
|
|
1104
|
+
if (!currentElement) break;
|
|
1105
|
+
currentElement = currentElement.parentElement, depth++;
|
|
935
1106
|
}
|
|
936
|
-
|
|
937
|
-
if (hasValidBackground && validSamples > 0) {
|
|
1107
|
+
if (hasValidBackground && validSamples > 0) {
|
|
938
1108
|
const avgLuminance = totalLuminance / validSamples;
|
|
939
1109
|
if (!isNaN(avgLuminance) && isFinite(avgLuminance)) {
|
|
940
1110
|
let threshold = .7;
|
|
941
|
-
|
|
942
|
-
// If overLight is an object, use its threshold property with validation
|
|
943
|
-
if ("object" == typeof overLight && null !== overLight) {
|
|
1111
|
+
if ("object" == typeof overLight && null !== overLight) {
|
|
944
1112
|
const objConfig = overLight;
|
|
945
1113
|
if (void 0 !== objConfig.threshold) {
|
|
946
|
-
const configThreshold = "number"
|
|
1114
|
+
const configThreshold = "number" != typeof objConfig.threshold || isNaN(objConfig.threshold) ? .7 : objConfig.threshold;
|
|
947
1115
|
threshold = Math.min(.9, Math.max(.1, configThreshold));
|
|
948
1116
|
}
|
|
949
1117
|
}
|
|
950
1118
|
const isOverLightDetected = avgLuminance > threshold;
|
|
951
|
-
|
|
952
|
-
setCachedBackgroundDetection(element.parentElement, overLight, isOverLightDetected, threshold),
|
|
1119
|
+
setCachedBackgroundDetection(element.parentElement, overLight, isOverLightDetected, threshold),
|
|
953
1120
|
setDetectedOverLight(isOverLightDetected);
|
|
954
1121
|
} else {
|
|
955
|
-
// Invalid luminance calculation, default to false
|
|
956
1122
|
const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
|
|
957
1123
|
setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
|
|
958
1124
|
setDetectedOverLight(result);
|
|
959
1125
|
}
|
|
960
1126
|
} else {
|
|
961
|
-
// Default to false if no valid background found
|
|
962
1127
|
const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
|
|
963
1128
|
setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
|
|
964
1129
|
setDetectedOverLight(result);
|
|
965
1130
|
}
|
|
966
1131
|
} catch (error) {
|
|
967
|
-
|
|
968
|
-
"undefined" != typeof process && "development" !== process.env?.NODE_ENV || console.warn("AtomixGlass: Error detecting background brightness:", error);
|
|
969
|
-
const result = !1;
|
|
970
|
-
if (element && element.parentElement) {
|
|
971
|
-
const threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
|
|
972
|
-
setCachedBackgroundDetection(element.parentElement, overLight, result, threshold);
|
|
973
|
-
}
|
|
974
|
-
setDetectedOverLight(result);
|
|
1132
|
+
setDetectedOverLight(!1);
|
|
975
1133
|
}
|
|
976
1134
|
}), 150);
|
|
977
1135
|
return () => clearTimeout(timeoutId);
|
|
978
1136
|
}
|
|
979
|
-
if ("boolean" == typeof overLight &&
|
|
980
|
-
// For boolean values, disable auto-detection
|
|
981
|
-
setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
|
|
1137
|
+
if ("boolean" == typeof overLight && setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
|
|
982
1138
|
const mediaQueryReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)"), mediaQueryHighContrast = window.matchMedia("(prefers-contrast: high)");
|
|
983
1139
|
setUserPrefersReducedMotion(mediaQueryReducedMotion.matches), setUserPrefersHighContrast(mediaQueryHighContrast.matches);
|
|
984
1140
|
const handleReducedMotionChange = e => {
|
|
@@ -989,64 +1145,54 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
989
1145
|
return mediaQueryReducedMotion.addEventListener ? (mediaQueryReducedMotion.addEventListener("change", handleReducedMotionChange),
|
|
990
1146
|
mediaQueryHighContrast.addEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.addListener && (mediaQueryReducedMotion.addListener(handleReducedMotionChange),
|
|
991
1147
|
mediaQueryHighContrast.addListener(handleHighContrastChange)), () => {
|
|
992
|
-
|
|
993
|
-
mediaQueryReducedMotion.removeEventListener ? (mediaQueryReducedMotion.removeEventListener("change", handleReducedMotionChange),
|
|
994
|
-
mediaQueryHighContrast.removeEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.removeListener && (mediaQueryReducedMotion.removeListener(handleReducedMotionChange),
|
|
995
|
-
mediaQueryHighContrast.removeListener(handleHighContrastChange));
|
|
996
|
-
} catch (cleanupError) {
|
|
997
|
-
console.error("AtomixGlass: Error cleaning up media query listeners:", cleanupError);
|
|
998
|
-
}
|
|
1148
|
+
// ignore
|
|
999
1149
|
};
|
|
1000
1150
|
} catch (error) {
|
|
1001
|
-
return
|
|
1151
|
+
return;
|
|
1002
1152
|
}
|
|
1003
1153
|
}), [ overLight, glassRef, debugOverLight ]);
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
y: (globalPos.y - center.y) / rect.height * 100
|
|
1154
|
+
/**
|
|
1155
|
+
* Get effective overLight value based on configuration
|
|
1156
|
+
*/
|
|
1157
|
+
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((() => {
|
|
1158
|
+
const isOverLight = getEffectiveOverLight(), baseConfig = {
|
|
1159
|
+
isOverLight: isOverLight,
|
|
1160
|
+
threshold: .7,
|
|
1161
|
+
opacity: isOverLight ? Math.min(.6, Math.max(.2, .5)) : 0,
|
|
1162
|
+
contrast: 1,
|
|
1163
|
+
// Base contrast
|
|
1164
|
+
brightness: 1,
|
|
1165
|
+
// Base brightness
|
|
1166
|
+
saturationBoost: 1.3,
|
|
1167
|
+
shadowIntensity: .9,
|
|
1168
|
+
borderOpacity: .7
|
|
1020
1169
|
};
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
return;
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
|
|
1170
|
+
if ("object" == typeof overLight && null !== overLight) {
|
|
1171
|
+
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);
|
|
1172
|
+
return {
|
|
1173
|
+
...baseConfig,
|
|
1174
|
+
threshold: validatedThreshold,
|
|
1175
|
+
opacity: validatedOpacity,
|
|
1176
|
+
contrast: validatedContrast,
|
|
1177
|
+
brightness: validatedBrightness,
|
|
1178
|
+
saturationBoost: validatedSaturationBoost
|
|
1179
|
+
};
|
|
1180
|
+
}
|
|
1181
|
+
return baseConfig;
|
|
1182
|
+
}), [ overLight, getEffectiveOverLight, validateConfigValue ]), overLightConfig = useMemo((() => {
|
|
1183
|
+
const mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1;
|
|
1184
|
+
return {
|
|
1185
|
+
isOverLight: baseOverLightConfig.isOverLight,
|
|
1186
|
+
threshold: baseOverLightConfig.threshold,
|
|
1187
|
+
opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
|
|
1188
|
+
contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
|
|
1189
|
+
brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
|
|
1190
|
+
saturationBoost: baseOverLightConfig.saturationBoost,
|
|
1191
|
+
shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
|
|
1192
|
+
borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence))
|
|
1045
1193
|
};
|
|
1046
|
-
}), [
|
|
1047
|
-
|
|
1048
|
-
const calculateDirectionalScale = useCallback((() => {
|
|
1049
|
-
if (!0 === overLight || "auto" === overLight && detectedOverLight || "object" == typeof overLight && null !== overLight && detectedOverLight) return "scale(1)";
|
|
1194
|
+
}), [ baseOverLightConfig, mouseOffset, isHovered, isActive ]), updateRectRef = useRef(null), calculateDirectionalScale = useCallback((() => {
|
|
1195
|
+
if (baseOverLightConfig.isOverLight) return "scale(1)";
|
|
1050
1196
|
if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return "scale(1)";
|
|
1051
1197
|
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({
|
|
1052
1198
|
x: edgeDistanceX,
|
|
@@ -1060,7 +1206,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
1060
1206
|
if (0 === centerDistance) return "scale(1)";
|
|
1061
1207
|
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;
|
|
1062
1208
|
return `scaleX(${Math.max(.8, scaleX)}) scaleY(${Math.max(.8, scaleY)})`;
|
|
1063
|
-
}), [ globalMousePosition, elasticity, glassSize, glassRef,
|
|
1209
|
+
}), [ globalMousePosition, elasticity, glassSize, glassRef, baseOverLightConfig ]), calculateFadeInFactor = useCallback((() => {
|
|
1064
1210
|
if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return 0;
|
|
1065
1211
|
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({
|
|
1066
1212
|
x: edgeDistanceX,
|
|
@@ -1080,122 +1226,110 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
1080
1226
|
x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
|
|
1081
1227
|
y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
|
|
1082
1228
|
};
|
|
1083
|
-
}), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = useMemo((() =>
|
|
1229
|
+
}), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = useMemo((() => effectiveWithoutEffects ? {
|
|
1084
1230
|
x: 0,
|
|
1085
1231
|
y: 0
|
|
1086
|
-
} : calculateElasticTranslation()), [ calculateElasticTranslation,
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
const
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
if (rect.width <= 0 || rect.height <= 0) return void (rafId = null);
|
|
1099
|
-
// Measure actual rendered size without artificial offsets to avoid feedback loops
|
|
1100
|
-
const newSize = {
|
|
1101
|
-
width: Math.round(rect.width),
|
|
1102
|
-
height: Math.round(rect.height)
|
|
1103
|
-
}, cornerRadiusChanged = lastCornerRadius !== effectiveCornerRadius, dimensionsChanged = Math.abs(newSize.width - lastSize.width) > 1 || Math.abs(newSize.height - lastSize.height) > 1;
|
|
1104
|
-
var size;
|
|
1105
|
-
(forceUpdate || cornerRadiusChanged || dimensionsChanged) && validateGlassSize(size = newSize) && size.width <= CONSTANTS.MAX_SIZE && size.height <= CONSTANTS.MAX_SIZE && (lastSize = newSize,
|
|
1106
|
-
lastCornerRadius = effectiveCornerRadius, setGlassSize(newSize)), rafId = null;
|
|
1107
|
-
}));
|
|
1108
|
-
};
|
|
1109
|
-
let resizeTimeoutId = null;
|
|
1110
|
-
const debouncedResizeHandler = () => {
|
|
1111
|
-
resizeTimeoutId && clearTimeout(resizeTimeoutId), resizeTimeoutId = setTimeout((() => updateGlassSize(!1)), 16);
|
|
1112
|
-
}, initialTimeoutId = setTimeout((() => updateGlassSize(!0)), 0);
|
|
1113
|
-
let resizeObserver = null, resizeDebounceTimeout = null;
|
|
1114
|
-
// ResizeObserver has 98%+ browser support, no need for fallback
|
|
1115
|
-
if ("undefined" != typeof ResizeObserver && isValidElement(glassRef.current)) try {
|
|
1116
|
-
resizeObserver = new ResizeObserver((entries => {
|
|
1117
|
-
for (const entry of entries) if (entry.target === glassRef.current) {
|
|
1118
|
-
// Update cached rect when size changes
|
|
1119
|
-
glassRef.current && (cachedRectRef.current = glassRef.current.getBoundingClientRect()),
|
|
1120
|
-
// Debounce resize updates to match RAF timing (16ms)
|
|
1121
|
-
resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), resizeDebounceTimeout = setTimeout((() => updateGlassSize(!1)), 16);
|
|
1122
|
-
break;
|
|
1123
|
-
}
|
|
1124
|
-
})), resizeObserver.observe(glassRef.current);
|
|
1125
|
-
} catch (error) {
|
|
1126
|
-
console.warn("AtomixGlass: ResizeObserver not available, using window resize only", error);
|
|
1127
|
-
}
|
|
1128
|
-
return window.addEventListener("resize", debouncedResizeHandler, {
|
|
1129
|
-
passive: !0
|
|
1130
|
-
}), () => {
|
|
1131
|
-
clearTimeout(initialTimeoutId), null !== rafId && cancelAnimationFrame(rafId), resizeTimeoutId && clearTimeout(resizeTimeoutId),
|
|
1132
|
-
resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), window.removeEventListener("resize", debouncedResizeHandler),
|
|
1133
|
-
resizeObserver?.disconnect();
|
|
1232
|
+
} : 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 => {
|
|
1233
|
+
if (externalGlobalMousePosition && externalMouseOffset) return;
|
|
1234
|
+
if (effectiveWithoutEffects) return;
|
|
1235
|
+
const container = mouseContainer?.current || glassRef.current;
|
|
1236
|
+
if (!container) return;
|
|
1237
|
+
// Use cached rect if available, otherwise get new one
|
|
1238
|
+
let rect = cachedRectRef.current;
|
|
1239
|
+
if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
|
|
1240
|
+
cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
|
|
1241
|
+
const center = calculateElementCenter(rect), newOffset = {
|
|
1242
|
+
x: (globalPos.x - center.x) / rect.width * 100,
|
|
1243
|
+
y: (globalPos.y - center.y) / rect.height * 100
|
|
1134
1244
|
};
|
|
1135
|
-
|
|
1136
|
-
|
|
1245
|
+
// Calculate offset relative to this container
|
|
1246
|
+
// Store in refs instead of state
|
|
1247
|
+
internalMouseOffsetRef.current = newOffset, internalGlobalMousePositionRef.current = globalPos,
|
|
1248
|
+
// Imperative style update
|
|
1249
|
+
updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
|
|
1250
|
+
mouseOffset: newOffset,
|
|
1251
|
+
globalMousePosition: globalPos,
|
|
1252
|
+
glassSize: glassSize,
|
|
1253
|
+
isHovered: isHovered,
|
|
1254
|
+
isActive: isActive,
|
|
1255
|
+
isOverLight: baseOverLightConfig.isOverLight,
|
|
1256
|
+
baseOverLightConfig: baseOverLightConfig,
|
|
1257
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
1258
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
1259
|
+
effectiveReducedMotion: effectiveReducedMotion,
|
|
1260
|
+
elasticity: elasticity,
|
|
1261
|
+
directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
|
|
1262
|
+
// Simplified directional scale for fast path
|
|
1263
|
+
onClick: onClick,
|
|
1264
|
+
withLiquidBlur: withLiquidBlur,
|
|
1265
|
+
blurAmount: blurAmount,
|
|
1266
|
+
saturation: saturation,
|
|
1267
|
+
padding: padding
|
|
1268
|
+
});
|
|
1269
|
+
}), [ mouseContainer, glassRef, wrapperRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects, glassSize, isHovered, isActive, baseOverLightConfig, effectiveBorderRadius, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding ]);
|
|
1137
1270
|
/**
|
|
1138
|
-
*
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
const
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1271
|
+
* Validate and clamp a numeric config value
|
|
1272
|
+
*/
|
|
1273
|
+
// Subscribe to shared mouse tracker
|
|
1274
|
+
useEffect((() => {
|
|
1275
|
+
if (externalGlobalMousePosition && externalMouseOffset) return;
|
|
1276
|
+
if (effectiveWithoutEffects) return;
|
|
1277
|
+
const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition), container = mouseContainer?.current || glassRef.current;
|
|
1278
|
+
let resizeObserver = null;
|
|
1279
|
+
return container && "undefined" != typeof ResizeObserver && (resizeObserver = new ResizeObserver((() => {
|
|
1280
|
+
null !== updateRectRef.current && cancelAnimationFrame(updateRectRef.current), updateRectRef.current = requestAnimationFrame((() => {
|
|
1281
|
+
const container = mouseContainer?.current || glassRef.current;
|
|
1282
|
+
container && (cachedRectRef.current = container.getBoundingClientRect()), updateRectRef.current = null;
|
|
1283
|
+
}));
|
|
1284
|
+
})), resizeObserver.observe(container)), () => {
|
|
1285
|
+
unsubscribe(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
|
|
1286
|
+
updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
|
|
1154
1287
|
};
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1288
|
+
}), [ handleGlobalMousePosition, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects ]),
|
|
1289
|
+
// Also call updateStyles on other state changes (hover, active, etc)
|
|
1290
|
+
useEffect((() => {
|
|
1291
|
+
updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
|
|
1292
|
+
mouseOffset: externalMouseOffset || internalMouseOffsetRef.current,
|
|
1293
|
+
globalMousePosition: externalGlobalMousePosition || internalGlobalMousePositionRef.current,
|
|
1294
|
+
glassSize: glassSize,
|
|
1295
|
+
isHovered: isHovered,
|
|
1296
|
+
isActive: isActive,
|
|
1297
|
+
isOverLight: baseOverLightConfig.isOverLight,
|
|
1298
|
+
baseOverLightConfig: baseOverLightConfig,
|
|
1299
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
1300
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
1301
|
+
effectiveReducedMotion: effectiveReducedMotion,
|
|
1302
|
+
elasticity: elasticity,
|
|
1303
|
+
directionalScale: directionalScale,
|
|
1304
|
+
onClick: onClick,
|
|
1305
|
+
withLiquidBlur: withLiquidBlur,
|
|
1306
|
+
blurAmount: blurAmount,
|
|
1307
|
+
saturation: saturation,
|
|
1308
|
+
padding: padding
|
|
1309
|
+
});
|
|
1310
|
+
}), [ isHovered, isActive, glassSize, baseOverLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, directionalScale, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation, padding, onClick ]);
|
|
1311
|
+
// Event handlers
|
|
1312
|
+
const handleMouseEnter = useCallback((() => setIsHovered(!0)), []), handleMouseLeave = useCallback((() => setIsHovered(!1)), []), handleMouseDown = useCallback((() => setIsActive(!0)), []), handleMouseUp = useCallback((() => setIsActive(!1)), []), handleMouseMove = useCallback((_e => {}), []), handleKeyDown = useCallback((e => {
|
|
1170
1313
|
!onClick || "Enter" !== e.key && " " !== e.key || (e.preventDefault(), onClick());
|
|
1171
|
-
}), [ onClick ])
|
|
1172
|
-
|
|
1173
|
-
* Validate and clamp a numeric config value
|
|
1174
|
-
* @param value - The value to validate
|
|
1175
|
-
* @param min - Minimum allowed value
|
|
1176
|
-
* @param max - Maximum allowed value
|
|
1177
|
-
* @param defaultValue - Default value if validation fails
|
|
1178
|
-
* @returns Validated and clamped value
|
|
1179
|
-
*/ return {
|
|
1180
|
-
// State
|
|
1314
|
+
}), [ onClick ]);
|
|
1315
|
+
return {
|
|
1181
1316
|
isHovered: isHovered,
|
|
1182
1317
|
isActive: isActive,
|
|
1183
1318
|
glassSize: glassSize,
|
|
1184
|
-
|
|
1185
|
-
|
|
1319
|
+
dynamicBorderRadius: dynamicBorderRadius,
|
|
1320
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
1186
1321
|
effectiveReducedMotion: effectiveReducedMotion,
|
|
1187
1322
|
effectiveHighContrast: effectiveHighContrast,
|
|
1188
|
-
|
|
1323
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
1189
1324
|
detectedOverLight: detectedOverLight,
|
|
1190
1325
|
globalMousePosition: globalMousePosition,
|
|
1326
|
+
// This is now static (refs or props) unless prop changes
|
|
1191
1327
|
mouseOffset: mouseOffset,
|
|
1192
|
-
//
|
|
1328
|
+
// This is now static (refs or props) unless prop changes
|
|
1193
1329
|
overLightConfig: overLightConfig,
|
|
1194
|
-
// Transform calculations
|
|
1195
1330
|
elasticTranslation: elasticTranslation,
|
|
1196
1331
|
directionalScale: directionalScale,
|
|
1197
1332
|
transformStyle: transformStyle,
|
|
1198
|
-
// Event handlers
|
|
1199
1333
|
handleMouseEnter: handleMouseEnter,
|
|
1200
1334
|
handleMouseLeave: handleMouseLeave,
|
|
1201
1335
|
handleMouseDown: handleMouseDown,
|
|
@@ -1234,7 +1368,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
1234
1368
|
*
|
|
1235
1369
|
* @example
|
|
1236
1370
|
* // Manual border-radius override
|
|
1237
|
-
* <AtomixGlass
|
|
1371
|
+
* <AtomixGlass borderRadius={20}>
|
|
1238
1372
|
* <div>Content with 20px glass radius</div>
|
|
1239
1373
|
* </AtomixGlass>
|
|
1240
1374
|
*
|
|
@@ -1275,37 +1409,48 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
1275
1409
|
* <AtomixGlass overLight="auto" debugOverLight={true}>
|
|
1276
1410
|
* <div>Content with debug logging enabled</div>
|
|
1277
1411
|
* </AtomixGlass>
|
|
1278
|
-
*/ 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,
|
|
1279
|
-
const glassRef = useRef(null), contentRef = useRef(null), {isHovered: isHovered, isActive: isActive, glassSize: glassSize,
|
|
1412
|
+
*/ 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}) {
|
|
1413
|
+
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({
|
|
1280
1414
|
glassRef: glassRef,
|
|
1281
1415
|
contentRef: contentRef,
|
|
1282
|
-
|
|
1416
|
+
borderRadius: borderRadius,
|
|
1283
1417
|
globalMousePosition: externalGlobalMousePosition,
|
|
1284
1418
|
mouseOffset: externalMouseOffset,
|
|
1285
1419
|
mouseContainer: mouseContainer,
|
|
1286
1420
|
overLight: overLight,
|
|
1287
1421
|
reducedMotion: reducedMotion,
|
|
1288
1422
|
highContrast: highContrast,
|
|
1289
|
-
|
|
1423
|
+
withoutEffects: withoutEffects,
|
|
1290
1424
|
elasticity: elasticity,
|
|
1291
1425
|
onClick: onClick,
|
|
1292
|
-
|
|
1426
|
+
debugBorderRadius: debugBorderRadius,
|
|
1293
1427
|
debugOverLight: debugOverLight,
|
|
1294
|
-
|
|
1295
|
-
children: children
|
|
1296
|
-
|
|
1428
|
+
debugPerformance: debugPerformance,
|
|
1429
|
+
children: children,
|
|
1430
|
+
blurAmount: blurAmount,
|
|
1431
|
+
saturation: saturation,
|
|
1432
|
+
withLiquidBlur: withLiquidBlur,
|
|
1433
|
+
padding: padding,
|
|
1434
|
+
style: style
|
|
1435
|
+
}), isOverLight = useMemo((() => overLightConfig?.isOverLight), [ overLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, baseStyle = {
|
|
1297
1436
|
...style,
|
|
1298
|
-
...!
|
|
1437
|
+
...!effectiveWithoutEffects && {
|
|
1299
1438
|
transform: transformStyle
|
|
1300
1439
|
}
|
|
1301
|
-
}, componentClassName = [ ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`,
|
|
1440
|
+
}, 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((() => ({
|
|
1302
1441
|
position: style.position || "absolute",
|
|
1303
1442
|
top: style.top || 0,
|
|
1304
1443
|
left: style.left || 0
|
|
1305
|
-
})), [ style.position, style.top, style.left ]), adjustedSize = useMemo((() =>
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1444
|
+
})), [ style.position, style.top, style.left ]), adjustedSize = useMemo((() => {
|
|
1445
|
+
const resolveSize = (propValue, styleValue, measuredSize) => {
|
|
1446
|
+
const explicitSize = propValue ?? styleValue;
|
|
1447
|
+
return void 0 !== explicitSize ? "number" == typeof explicitSize ? `${explicitSize}px` : explicitSize : "fixed" === positionStyles.position ? `${Math.max(measuredSize, 0)}px` : "100%";
|
|
1448
|
+
};
|
|
1449
|
+
return {
|
|
1450
|
+
width: resolveSize(width, style.width, glassSize.width),
|
|
1451
|
+
height: resolveSize(height, style.height, glassSize.height)
|
|
1452
|
+
};
|
|
1453
|
+
}), [ width, height, style.width, style.height, positionStyles.position, glassSize.width, glassSize.height ]), gradientValues = useMemo((() => {
|
|
1309
1454
|
const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT;
|
|
1310
1455
|
return {
|
|
1311
1456
|
borderGradientAngle: GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER,
|
|
@@ -1347,13 +1492,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
1347
1492
|
}), [ isHovered, isActive, isOverLight, overLightConfig.opacity ]), glassVars = useMemo((() => {
|
|
1348
1493
|
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;
|
|
1349
1494
|
return {
|
|
1350
|
-
"--atomix-glass-radius": `${
|
|
1495
|
+
"--atomix-glass-radius": `${effectiveBorderRadius}px`,
|
|
1351
1496
|
"--atomix-glass-transform": transformStyle || "none",
|
|
1352
1497
|
"--atomix-glass-position": positionStyles.position,
|
|
1353
1498
|
"--atomix-glass-top": "fixed" !== positionStyles.top ? `${positionStyles.top}px` : "0",
|
|
1354
1499
|
"--atomix-glass-left": "fixed" !== positionStyles.left ? `${positionStyles.left}px` : "0",
|
|
1355
|
-
"--atomix-glass-width":
|
|
1356
|
-
"--atomix-glass-height":
|
|
1500
|
+
"--atomix-glass-width": adjustedSize.width,
|
|
1501
|
+
"--atomix-glass-height": adjustedSize.height,
|
|
1357
1502
|
"--atomix-glass-border-width": "var(--atomix-spacing-0-5, 0.09375rem)",
|
|
1358
1503
|
"--atomix-glass-blend-mode": isOverLight ? "multiply" : "overlay",
|
|
1359
1504
|
"--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%)`,
|
|
@@ -1369,24 +1514,25 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
1369
1514
|
"--atomix-glass-overlay-opacity": opacityValues.over,
|
|
1370
1515
|
"--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})`
|
|
1371
1516
|
};
|
|
1372
|
-
}), [ gradientValues, opacityValues,
|
|
1517
|
+
}), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle, positionStyles, adjustedSize, isOverLight, overLightConfig.borderOpacity ]), renderBackgroundLayer = layerType => jsx("div", {
|
|
1373
1518
|
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(" "),
|
|
1374
1519
|
style: {
|
|
1375
1520
|
...positionStyles,
|
|
1376
1521
|
height: adjustedSize.height,
|
|
1377
1522
|
width: adjustedSize.width,
|
|
1378
|
-
borderRadius: `${
|
|
1523
|
+
borderRadius: `${effectiveBorderRadius}px`,
|
|
1379
1524
|
transform: baseStyle.transform
|
|
1380
1525
|
}
|
|
1381
1526
|
});
|
|
1382
1527
|
return jsxs("div", {
|
|
1528
|
+
...rest,
|
|
1383
1529
|
className: componentClassName,
|
|
1384
1530
|
style: glassVars,
|
|
1385
1531
|
role: role || (onClick ? "button" : void 0),
|
|
1386
1532
|
tabIndex: onClick ? tabIndex ?? 0 : tabIndex,
|
|
1387
1533
|
"aria-label": ariaLabel,
|
|
1388
1534
|
"aria-describedby": ariaDescribedBy,
|
|
1389
|
-
"aria-disabled": !(!onClick || !
|
|
1535
|
+
"aria-disabled": !(!onClick || !effectiveWithoutEffects) || !onClick && void 0,
|
|
1390
1536
|
"aria-pressed": !(!onClick || !isActive) || !onClick && void 0,
|
|
1391
1537
|
onKeyDown: onClick ? handleKeyDown : void 0,
|
|
1392
1538
|
children: [ jsx(AtomixGlassContainer, {
|
|
@@ -1394,18 +1540,18 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
1394
1540
|
contentRef: contentRef,
|
|
1395
1541
|
className: className,
|
|
1396
1542
|
style: baseStyle,
|
|
1397
|
-
|
|
1398
|
-
displacementScale:
|
|
1399
|
-
blurAmount:
|
|
1543
|
+
borderRadius: effectiveBorderRadius,
|
|
1544
|
+
displacementScale: effectiveWithoutEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
|
|
1545
|
+
blurAmount: effectiveWithoutEffects ? 0 : blurAmount,
|
|
1400
1546
|
saturation: effectiveHighContrast ? ATOMIX_GLASS.CONSTANTS.SATURATION.HIGH_CONTRAST : isOverLight ? saturation * overLightConfig.saturationBoost : saturation,
|
|
1401
|
-
aberrationIntensity:
|
|
1547
|
+
aberrationIntensity: effectiveWithoutEffects ? 0 : "shader" === mode ? aberrationIntensity * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_ABERRATION : aberrationIntensity,
|
|
1402
1548
|
glassSize: glassSize,
|
|
1403
1549
|
padding: padding,
|
|
1404
|
-
mouseOffset:
|
|
1550
|
+
mouseOffset: effectiveWithoutEffects ? {
|
|
1405
1551
|
x: 0,
|
|
1406
1552
|
y: 0
|
|
1407
1553
|
} : mouseOffset,
|
|
1408
|
-
globalMousePosition:
|
|
1554
|
+
globalMousePosition: effectiveWithoutEffects ? {
|
|
1409
1555
|
x: 0,
|
|
1410
1556
|
y: 0
|
|
1411
1557
|
} : globalMousePosition,
|
|
@@ -1425,11 +1571,11 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
1425
1571
|
onClick: onClick,
|
|
1426
1572
|
mode: mode,
|
|
1427
1573
|
transform: baseStyle.transform,
|
|
1428
|
-
|
|
1574
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
1429
1575
|
effectiveReducedMotion: effectiveReducedMotion,
|
|
1430
1576
|
shaderVariant: shaderVariant,
|
|
1431
1577
|
elasticity: elasticity,
|
|
1432
|
-
|
|
1578
|
+
withLiquidBlur: withLiquidBlur,
|
|
1433
1579
|
children: children
|
|
1434
1580
|
}), Boolean(onClick) && jsxs(Fragment, {
|
|
1435
1581
|
children: [ jsx("div", {
|
|
@@ -1451,11 +1597,19 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
1451
1597
|
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}%)`
|
|
1452
1598
|
}
|
|
1453
1599
|
}) ]
|
|
1454
|
-
}),
|
|
1600
|
+
}), withBorder && jsxs(Fragment, {
|
|
1455
1601
|
children: [ jsx("span", {
|
|
1456
|
-
className: ATOMIX_GLASS.BORDER_1_CLASS
|
|
1602
|
+
className: ATOMIX_GLASS.BORDER_1_CLASS,
|
|
1603
|
+
style: {
|
|
1604
|
+
width: glassSize.width,
|
|
1605
|
+
height: glassSize.height
|
|
1606
|
+
}
|
|
1457
1607
|
}), jsx("span", {
|
|
1458
|
-
className: ATOMIX_GLASS.BORDER_2_CLASS
|
|
1608
|
+
className: ATOMIX_GLASS.BORDER_2_CLASS,
|
|
1609
|
+
style: {
|
|
1610
|
+
width: glassSize.width,
|
|
1611
|
+
height: glassSize.height
|
|
1612
|
+
}
|
|
1459
1613
|
}) ]
|
|
1460
1614
|
}) ]
|
|
1461
1615
|
});
|
|
@@ -1516,7 +1670,7 @@ const Checkbox = React.memo( forwardRef((({label: label, checked: checked, onCh
|
|
|
1516
1670
|
blurAmount: 1,
|
|
1517
1671
|
saturation: 160,
|
|
1518
1672
|
aberrationIntensity: .3,
|
|
1519
|
-
|
|
1673
|
+
borderRadius: 6,
|
|
1520
1674
|
mode: "shader"
|
|
1521
1675
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
1522
1676
|
...defaultGlassProps,
|
|
@@ -1741,7 +1895,7 @@ const Input = memo( forwardRef((({type: type = "text", value: value, defaultVal
|
|
|
1741
1895
|
blurAmount: 1,
|
|
1742
1896
|
saturation: 180,
|
|
1743
1897
|
aberrationIntensity: .2,
|
|
1744
|
-
|
|
1898
|
+
borderRadius: 12,
|
|
1745
1899
|
mode: "shader"
|
|
1746
1900
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
1747
1901
|
...defaultGlassProps,
|
|
@@ -1826,7 +1980,7 @@ const Radio = memo((({label: label, checked: checked = !1, onChange: onChange,
|
|
|
1826
1980
|
blurAmount: 1,
|
|
1827
1981
|
saturation: 160,
|
|
1828
1982
|
aberrationIntensity: .3,
|
|
1829
|
-
|
|
1983
|
+
borderRadius: 6,
|
|
1830
1984
|
mode: "shader"
|
|
1831
1985
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
1832
1986
|
...defaultGlassProps,
|
|
@@ -2439,7 +2593,7 @@ const Select = memo((({options: options, value: value, onChange: onChange, onBl
|
|
|
2439
2593
|
blurAmount: 1,
|
|
2440
2594
|
saturation: 180,
|
|
2441
2595
|
aberrationIntensity: .2,
|
|
2442
|
-
|
|
2596
|
+
borderRadius: 12,
|
|
2443
2597
|
mode: "shader"
|
|
2444
2598
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
2445
2599
|
...defaultGlassProps,
|
|
@@ -2527,7 +2681,7 @@ const Textarea = memo( forwardRef((({value: value, defaultValue: defaultValue,
|
|
|
2527
2681
|
blurAmount: 1,
|
|
2528
2682
|
saturation: 180,
|
|
2529
2683
|
aberrationIntensity: 1,
|
|
2530
|
-
|
|
2684
|
+
borderRadius: 8,
|
|
2531
2685
|
mode: "shader"
|
|
2532
2686
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
2533
2687
|
...defaultGlassProps,
|