@shohojdhara/atomix 0.4.9 → 0.5.1
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 +95 -69
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +1 -1
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.d.ts +1 -0
- package/dist/charts.js +231 -332
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +1 -0
- package/dist/core.js +232 -333
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +1 -0
- package/dist/forms.js +231 -332
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +11 -2
- package/dist/heavy.js +233 -334
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +13 -2
- package/dist/index.esm.js +228 -327
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +227 -326
- 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 +11 -1
- package/src/components/AtomixGlass/AtomixGlass.tsx +188 -128
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +62 -90
- package/src/components/AtomixGlass/PerformanceDashboard.tsx +153 -201
- package/src/components/AtomixGlass/glass-utils.ts +50 -0
- package/src/components/AtomixGlass/shader-utils.ts +1 -1
- package/src/components/AtomixGlass/stories/{Phase1-Animation.stories.tsx → AnimationFeatures.stories.tsx} +53 -47
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +573 -236
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +656 -44
- package/src/components/AtomixGlass/stories/argTypes.ts +384 -0
- package/src/components/AtomixGlass/stories/shared-components.tsx +82 -3
- package/src/components/AtomixGlass/stories/types.ts +127 -0
- package/src/lib/composables/useAtomixGlass.ts +108 -71
- package/src/lib/composables/useAtomixGlassStyles.ts +0 -2
- package/src/lib/constants/components.ts +1 -0
- package/src/lib/types/components.ts +1 -0
- package/src/lib/utils/displacement-generator.ts +1 -1
- package/src/styles/06-components/_components.atomix-glass.scss +158 -97
- package/scripts/cli/__tests__/README.md +0 -81
- package/scripts/cli/__tests__/basic.test.js +0 -116
- package/scripts/cli/__tests__/clean.test.js +0 -278
- package/scripts/cli/__tests__/component-generator.test.js +0 -332
- package/scripts/cli/__tests__/component-validator.test.js +0 -433
- package/scripts/cli/__tests__/generator.test.js +0 -613
- package/scripts/cli/__tests__/glass-motion.test.js +0 -256
- package/scripts/cli/__tests__/integration.test.js +0 -938
- package/scripts/cli/__tests__/migrate.test.js +0 -74
- package/scripts/cli/__tests__/security.test.js +0 -206
- package/scripts/cli/__tests__/test-setup.js +0 -135
- package/scripts/cli/__tests__/theme-bridge.test.js +0 -507
- package/scripts/cli/__tests__/token-manager.test.js +0 -251
- package/scripts/cli/__tests__/token-provider.test.js +0 -361
- package/scripts/cli/__tests__/utils.test.js +0 -165
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +0 -216
- package/src/components/AtomixGlass/stories/Customization.stories.tsx +0 -131
- package/src/components/AtomixGlass/stories/Modes.stories.tsx +0 -1082
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +0 -497
- package/src/components/AtomixGlass/stories/Performance.stories.tsx +0 -103
- package/src/components/AtomixGlass/stories/Phase1-Test.stories.tsx +0 -95
- package/src/components/AtomixGlass/stories/Shaders.stories.tsx +0 -395
- package/src/components/TypedButton/TypedButton.stories.tsx +0 -59
- package/src/components/TypedButton/TypedButton.tsx +0 -39
- package/src/components/TypedButton/index.ts +0 -2
- package/src/lib/composables/useTypedButton.ts +0 -66
package/dist/heavy.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
2
|
|
|
3
|
-
import React, { memo, forwardRef, useMemo, useState, useRef, useEffect, useCallback, useImperativeHandle, Children, isValidElement } from "react";
|
|
3
|
+
import React, { memo, forwardRef, useId, useMemo, useState, useRef, useEffect, useCallback, useImperativeHandle, Children, isValidElement } from "react";
|
|
4
4
|
|
|
5
5
|
import * as PhosphorIcons from "@phosphor-icons/react";
|
|
6
6
|
|
|
@@ -33,6 +33,7 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
|
|
|
33
33
|
FILTER_OVERLAY_CLASS: "c-atomix-glass__filter-overlay",
|
|
34
34
|
FILTER_SHADOW_CLASS: "c-atomix-glass__filter-shadow",
|
|
35
35
|
CONTENT_CLASS: "c-atomix-glass__content",
|
|
36
|
+
BORDER_BACKDROP_CLASS: "c-atomix-glass__border-backdrop",
|
|
36
37
|
BORDER_1_CLASS: "c-atomix-glass__border-1",
|
|
37
38
|
BORDER_2_CLASS: "c-atomix-glass__border-2",
|
|
38
39
|
HOVER_1_CLASS: "c-atomix-glass__hover-1",
|
|
@@ -378,7 +379,7 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
|
|
|
378
379
|
default:
|
|
379
380
|
return console.warn("AtomixGlass: Invalid displacement mode"), displacementMap;
|
|
380
381
|
}
|
|
381
|
-
}, GlassFilterComponent = ({id: id, displacementScale: displacementScale, aberrationIntensity: aberrationIntensity, mode: mode, shaderMapUrl: shaderMapUrl, blurAmount: blurAmount}) => jsx("svg", {
|
|
382
|
+
}, sharedShaderCache = new Map, GlassFilterComponent = ({id: id, displacementScale: displacementScale, aberrationIntensity: aberrationIntensity, mode: mode, shaderMapUrl: shaderMapUrl, blurAmount: blurAmount}) => jsx("svg", {
|
|
382
383
|
style: {
|
|
383
384
|
position: "absolute",
|
|
384
385
|
width: "100%",
|
|
@@ -517,24 +518,17 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
|
|
|
517
518
|
GlassFilterComponent.displayName = "GlassFilter";
|
|
518
519
|
|
|
519
520
|
// Memoize component to prevent unnecessary re-renders
|
|
520
|
-
const GlassFilter = memo(GlassFilterComponent, ((prevProps, nextProps) => prevProps.id === nextProps.id && prevProps.displacementScale === nextProps.displacementScale && prevProps.aberrationIntensity === nextProps.aberrationIntensity && prevProps.mode === nextProps.mode && prevProps.shaderMapUrl === nextProps.shaderMapUrl && prevProps.blurAmount === nextProps.blurAmount))
|
|
521
|
-
|
|
522
|
-
// Module-level counter for deterministic ID generation
|
|
523
|
-
let idCounter = 0;
|
|
524
|
-
|
|
525
|
-
// Module-level shared shader cache with LRU eviction
|
|
526
|
-
const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({children: children, className: className = "", style: style, displacementScale: displacementScale = 25, blurAmount: blurAmount = .0625, saturation: saturation = 180, aberrationIntensity: aberrationIntensity = 2, mouseOffset: mouseOffset = {
|
|
521
|
+
const GlassFilter = memo(GlassFilterComponent, ((prevProps, nextProps) => prevProps.id === nextProps.id && prevProps.displacementScale === nextProps.displacementScale && prevProps.aberrationIntensity === nextProps.aberrationIntensity && prevProps.mode === nextProps.mode && prevProps.shaderMapUrl === nextProps.shaderMapUrl && prevProps.blurAmount === nextProps.blurAmount)), AtomixGlassContainer = forwardRef((({children: children, className: className = "", style: style, displacementScale: displacementScale = 25, blurAmount: blurAmount = .0625, saturation: saturation = 180, aberrationIntensity: aberrationIntensity = 2, mouseOffset: mouseOffset = {
|
|
527
522
|
x: 0,
|
|
528
523
|
y: 0
|
|
529
524
|
}, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {}, borderRadius: borderRadius = 0, padding: padding = "0 0", glassSize: glassSize = {
|
|
530
525
|
width: 0,
|
|
531
526
|
height: 0
|
|
532
|
-
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1,
|
|
527
|
+
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, isFixedOrSticky: isFixedOrSticky = !1,
|
|
533
528
|
// Phase 1: Animation System props
|
|
534
529
|
shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion = !1, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5, distortionQuality: distortionQuality = "medium", contentRef: contentRef}, ref) => {
|
|
535
|
-
//
|
|
536
|
-
|
|
537
|
-
const filterId = useMemo((() => "atomix-glass-filter-" + ++idCounter), []), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null), shaderUpdateTimeoutRef = useRef(null), animationFrameRef = useRef(null);
|
|
530
|
+
// React 18 useId — stable, unique, and SSR-safe (no module-level counter)
|
|
531
|
+
const rawId = useId(), filterId = useMemo((() => `atomix-glass-filter-${rawId.replace(/:/g, "")}`), [ rawId ]), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null), shaderUpdateTimeoutRef = useRef(null), animationFrameRef = useRef(null);
|
|
538
532
|
// Lazy load shader utilities only when shader mode is needed
|
|
539
533
|
useEffect((() => {
|
|
540
534
|
"shader" === mode ?
|
|
@@ -557,9 +551,7 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
557
551
|
// Create cache key from size and variant
|
|
558
552
|
const cacheKey = `${glassSize.width}x${glassSize.height}-${shaderVariant}`, cachedUrl = (key => {
|
|
559
553
|
const entry = sharedShaderCache.get(key);
|
|
560
|
-
return entry ? (
|
|
561
|
-
// Update access timestamp for LRU
|
|
562
|
-
entry.timestamp = Date.now(), entry.url) : null;
|
|
554
|
+
return entry ? (entry.timestamp = Date.now(), entry.url) : null;
|
|
563
555
|
})(cacheKey);
|
|
564
556
|
// Check shared cache first
|
|
565
557
|
if (cachedUrl) return void setShaderMapUrl(cachedUrl);
|
|
@@ -570,29 +562,24 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
570
562
|
if (shaderUtilsRef.current) try {
|
|
571
563
|
const {ShaderDisplacementGenerator: ShaderDisplacementGenerator, fragmentShaders: fragmentShaders} = shaderUtilsRef.current;
|
|
572
564
|
shaderGeneratorRef.current?.destroy();
|
|
573
|
-
const selectedShader = fragmentShaders[shaderVariant]
|
|
565
|
+
const selectedShader = fragmentShaders[shaderVariant] ?? fragmentShaders.liquidGlass;
|
|
574
566
|
shaderGeneratorRef.current = new ShaderDisplacementGenerator({
|
|
575
567
|
width: glassSize.width,
|
|
576
568
|
height: glassSize.height,
|
|
577
569
|
fragment: selectedShader
|
|
578
570
|
}), shaderUpdateTimeoutRef.current = setTimeout((() => {
|
|
579
|
-
const url = shaderGeneratorRef.current?.updateShader()
|
|
571
|
+
const url = shaderGeneratorRef.current?.updateShader() ?? "";
|
|
580
572
|
url && ((key, url) => {
|
|
581
|
-
// Evict oldest entries if at capacity
|
|
582
573
|
if (sharedShaderCache.size >= 15) {
|
|
583
574
|
const entries = Array.from(sharedShaderCache.entries());
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
const oldestEntry = entries[0];
|
|
588
|
-
oldestEntry && sharedShaderCache.delete(oldestEntry[0]);
|
|
575
|
+
entries.sort(((a, b) => a[1].timestamp - b[1].timestamp));
|
|
576
|
+
const oldest = entries[0];
|
|
577
|
+
oldest && sharedShaderCache.delete(oldest[0]);
|
|
589
578
|
}
|
|
590
579
|
sharedShaderCache.set(key, {
|
|
591
580
|
url: url,
|
|
592
581
|
timestamp: Date.now()
|
|
593
|
-
}),
|
|
594
|
-
// Development mode: log cache size
|
|
595
|
-
"undefined" != typeof process && "production" === process.env?.NODE_ENV || sharedShaderCache.size;
|
|
582
|
+
}), "undefined" != typeof process && "production" === process.env?.NODE_ENV || sharedShaderCache.size;
|
|
596
583
|
})(cacheKey, url), setShaderMapUrl(url);
|
|
597
584
|
}), 100);
|
|
598
585
|
} catch (error) {
|
|
@@ -661,7 +648,6 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
661
648
|
console.warn("AtomixGlassContainer: Error getting element bounds", error), setRectCache(null);
|
|
662
649
|
}
|
|
663
650
|
}), [ ref, glassSize ]);
|
|
664
|
-
// Pre-calculate static multipliers outside useMemo
|
|
665
651
|
const liquidBlur = useMemo((() => {
|
|
666
652
|
const defaultBlur = {
|
|
667
653
|
baseBlur: blurAmount,
|
|
@@ -730,7 +716,6 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
730
716
|
}), [ borderRadius, backdropStyle, mouseOffset, overLight, effectiveWithoutEffects, overLightConfig ]);
|
|
731
717
|
return jsx("div", {
|
|
732
718
|
ref: el => {
|
|
733
|
-
// Apply force no-transition
|
|
734
719
|
// Handle forwarded ref
|
|
735
720
|
"function" == typeof ref ? ref(el) : ref && (ref.current = el);
|
|
736
721
|
},
|
|
@@ -772,6 +757,7 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
772
757
|
});
|
|
773
758
|
}));
|
|
774
759
|
|
|
760
|
+
// ─── Blur multiplier constants (module-level, never change at runtime) ────────
|
|
775
761
|
AtomixGlassContainer.displayName = "AtomixGlassContainer";
|
|
776
762
|
|
|
777
763
|
// Singleton instance
|
|
@@ -972,8 +958,6 @@ class {
|
|
|
972
958
|
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})`;
|
|
973
959
|
// Container variables
|
|
974
960
|
const style = containerElement.style;
|
|
975
|
-
style.setProperty("--atomix-glass-container-width", isFixedOrSticky ? `${glassSize.width}` : "100%"),
|
|
976
|
-
style.setProperty("--atomix-glass-container-height", isFixedOrSticky ? `${glassSize.height}` : "100%"),
|
|
977
961
|
style.setProperty("--atomix-glass-container-padding", padding), style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
|
|
978
962
|
style.setProperty("--atomix-glass-container-backdrop", backdropFilterString),
|
|
979
963
|
// Shadows
|
|
@@ -1434,47 +1418,55 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
1434
1418
|
return "undefined" == typeof process || process.env, finalConfig;
|
|
1435
1419
|
}
|
|
1436
1420
|
return "undefined" == typeof process || process.env, baseConfig;
|
|
1437
|
-
}), [ overLight, getEffectiveOverLight, isHovered, isActive, validateConfigValue, debugOverLight ]), transformStyle = useMemo((() => effectiveWithoutEffects || isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)"), [ effectiveWithoutEffects, isActive, onClick ]), updateRectRef = useRef(null),
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
if (!container) return;
|
|
1442
|
-
// Use cached rect if available, otherwise get new one
|
|
1443
|
-
let rect = cachedRectRef.current;
|
|
1444
|
-
if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
|
|
1445
|
-
cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
|
|
1446
|
-
const center = calculateElementCenter(rect);
|
|
1447
|
-
// Write raw target — the lerp loop will smoothly pursue it
|
|
1448
|
-
targetMouseOffsetRef.current = {
|
|
1449
|
-
x: (globalPos.x - center.x) / rect.width * 100,
|
|
1450
|
-
y: (globalPos.y - center.y) / rect.height * 100
|
|
1451
|
-
}, targetGlobalMousePositionRef.current = globalPos;
|
|
1452
|
-
}), [ mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects ]), startLerpLoop = useCallback((() => {
|
|
1421
|
+
}), [ overLight, getEffectiveOverLight, isHovered, isActive, validateConfigValue, debugOverLight ]), transformStyle = useMemo((() => effectiveWithoutEffects || isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)"), [ effectiveWithoutEffects, isActive, onClick ]), updateRectRef = useRef(null), stopLerpLoop = useCallback((() => {
|
|
1422
|
+
lerpActiveRef.current = !1, null !== lerpRafRef.current && (cancelAnimationFrame(lerpRafRef.current),
|
|
1423
|
+
lerpRafRef.current = null);
|
|
1424
|
+
}), []), startLerpLoop = useCallback((() => {
|
|
1453
1425
|
if (lerpActiveRef.current) return;
|
|
1454
1426
|
lerpActiveRef.current = !0;
|
|
1455
1427
|
const LERP_T = CONSTANTS.LERP_FACTOR, tick = () => {
|
|
1456
1428
|
if (!lerpActiveRef.current) return;
|
|
1457
|
-
|
|
1458
|
-
if (!glassRef.current || !wrapperRef?.current) return void (lerpActiveRef.current = !1);
|
|
1429
|
+
if (!glassRef.current) return void (lerpActiveRef.current = !1);
|
|
1459
1430
|
const cur = internalMouseOffsetRef.current, tgt = targetMouseOffsetRef.current, dx = tgt.x - cur.x, dy = tgt.y - cur.y;
|
|
1460
1431
|
// If we're close enough, snap and park
|
|
1461
|
-
if (Math.abs(dx) < .
|
|
1432
|
+
if (Math.abs(dx) < .01 && Math.abs(dy) < .01) return internalMouseOffsetRef.current = {
|
|
1462
1433
|
...tgt
|
|
1463
1434
|
}, internalGlobalMousePositionRef.current = {
|
|
1464
1435
|
...targetGlobalMousePositionRef.current
|
|
1465
|
-
}
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1436
|
+
},
|
|
1437
|
+
// Final update and stop
|
|
1438
|
+
updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
|
|
1439
|
+
mouseOffset: internalMouseOffsetRef.current,
|
|
1440
|
+
globalMousePosition: internalGlobalMousePositionRef.current,
|
|
1441
|
+
glassSize: glassSize,
|
|
1442
|
+
isHovered: isHovered,
|
|
1443
|
+
isActive: isActive,
|
|
1444
|
+
isOverLight: overLightConfig.isOverLight,
|
|
1445
|
+
baseOverLightConfig: overLightConfig,
|
|
1446
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
1447
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
1448
|
+
effectiveReducedMotion: effectiveReducedMotion,
|
|
1449
|
+
elasticity: elasticity,
|
|
1450
|
+
directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
|
|
1451
|
+
onClick: onClick,
|
|
1452
|
+
withLiquidBlur: withLiquidBlur,
|
|
1453
|
+
blurAmount: blurAmount,
|
|
1454
|
+
saturation: saturation,
|
|
1455
|
+
padding: padding,
|
|
1456
|
+
isFixedOrSticky: isFixedOrSticky
|
|
1457
|
+
}), void stopLerpLoop();
|
|
1458
|
+
// Smooth step
|
|
1459
|
+
internalMouseOffsetRef.current = {
|
|
1460
|
+
x: lerp$1(cur.x, tgt.x, LERP_T),
|
|
1461
|
+
y: lerp$1(cur.y, tgt.y, LERP_T)
|
|
1462
|
+
};
|
|
1463
|
+
const curG = internalGlobalMousePositionRef.current, tgtG = targetGlobalMousePositionRef.current;
|
|
1464
|
+
internalGlobalMousePositionRef.current = {
|
|
1465
|
+
x: lerp$1(curG.x, tgtG.x, LERP_T),
|
|
1466
|
+
y: lerp$1(curG.y, tgtG.y, LERP_T)
|
|
1467
|
+
},
|
|
1468
|
+
// Imperative style update
|
|
1469
|
+
updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
|
|
1478
1470
|
mouseOffset: internalMouseOffsetRef.current,
|
|
1479
1471
|
globalMousePosition: internalGlobalMousePositionRef.current,
|
|
1480
1472
|
glassSize: glassSize,
|
|
@@ -1497,10 +1489,24 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
1497
1489
|
};
|
|
1498
1490
|
// 0.08 – lower = more viscous
|
|
1499
1491
|
lerpRafRef.current = requestAnimationFrame(tick);
|
|
1500
|
-
}), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding, isFixedOrSticky ]),
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1492
|
+
}), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding, isFixedOrSticky, stopLerpLoop ]), handleGlobalMousePosition = useCallback((globalPos => {
|
|
1493
|
+
if (externalGlobalMousePosition && externalMouseOffset) return;
|
|
1494
|
+
if (effectiveWithoutEffects) return;
|
|
1495
|
+
const container = mouseContainer?.current || glassRef.current;
|
|
1496
|
+
if (!container) return;
|
|
1497
|
+
// Use cached rect if available, otherwise get new one
|
|
1498
|
+
let rect = cachedRectRef.current;
|
|
1499
|
+
if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
|
|
1500
|
+
cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
|
|
1501
|
+
const center = calculateElementCenter(rect);
|
|
1502
|
+
// Write raw target — the lerp loop will smoothly pursue it
|
|
1503
|
+
targetMouseOffsetRef.current = {
|
|
1504
|
+
x: (globalPos.x - center.x) / rect.width * 100,
|
|
1505
|
+
y: (globalPos.y - center.y) / rect.height * 100
|
|
1506
|
+
}, targetGlobalMousePositionRef.current = globalPos,
|
|
1507
|
+
// Ensure the lerp loop is running to smoothly chase the new target
|
|
1508
|
+
lerpActiveRef.current || startLerpLoop();
|
|
1509
|
+
}), [ mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects, startLerpLoop ]);
|
|
1504
1510
|
/**
|
|
1505
1511
|
* Validate and clamp a numeric config value
|
|
1506
1512
|
*/
|
|
@@ -1509,7 +1515,7 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
1509
1515
|
if (externalGlobalMousePosition && externalMouseOffset) return;
|
|
1510
1516
|
if (effectiveWithoutEffects) return;
|
|
1511
1517
|
const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition);
|
|
1512
|
-
//
|
|
1518
|
+
// Initial start
|
|
1513
1519
|
startLerpLoop();
|
|
1514
1520
|
const container = mouseContainer?.current || glassRef.current;
|
|
1515
1521
|
let resizeObserver = null;
|
|
@@ -1522,7 +1528,7 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
1522
1528
|
unsubscribe(), stopLerpLoop(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
|
|
1523
1529
|
updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
|
|
1524
1530
|
};
|
|
1525
|
-
}), [
|
|
1531
|
+
}), [ externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects, handleGlobalMousePosition, startLerpLoop, stopLerpLoop, mouseContainer, glassRef ]),
|
|
1526
1532
|
// Also call updateStyles on other state changes (hover, active, etc)
|
|
1527
1533
|
useEffect((() => {
|
|
1528
1534
|
updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
|
|
@@ -1998,184 +2004,147 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
1998
2004
|
/**
|
|
1999
2005
|
* Get GPU memory info if available (Chrome DevTools only)
|
|
2000
2006
|
*/
|
|
2007
|
+
/** Map an FPS value to a semantic color token string. */
|
|
2008
|
+
const getQualityColor = quality => {
|
|
2009
|
+
switch (quality) {
|
|
2010
|
+
case "high":
|
|
2011
|
+
return "var(--atomix-color-success, #4ade80)";
|
|
2012
|
+
|
|
2013
|
+
case "medium":
|
|
2014
|
+
return "var(--atomix-color-warning, #fbbf24)";
|
|
2015
|
+
|
|
2016
|
+
case "low":
|
|
2017
|
+
return "var(--atomix-color-danger, #ef4444)";
|
|
2018
|
+
|
|
2019
|
+
default:
|
|
2020
|
+
return "#9ca3af";
|
|
2021
|
+
}
|
|
2022
|
+
}, getFpsLabel = fps => fps >= 58 ? "Optimal" : fps >= 45 ? "Warning" : "Critical";
|
|
2023
|
+
|
|
2024
|
+
/** Map a quality level string to a semantic color token string. */
|
|
2025
|
+
// Inject keyframes once
|
|
2026
|
+
if ("undefined" != typeof document) {
|
|
2027
|
+
const styleId = "perf-dashboard-keyframes";
|
|
2028
|
+
if (!document.getElementById(styleId)) {
|
|
2029
|
+
const styleEl = document.createElement("style");
|
|
2030
|
+
styleEl.id = styleId, styleEl.textContent = "\n@keyframes perf-dashboard-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n}\n",
|
|
2031
|
+
document.head.appendChild(styleEl);
|
|
2032
|
+
}
|
|
2033
|
+
}
|
|
2034
|
+
|
|
2001
2035
|
/**
|
|
2002
|
-
* PerformanceDashboard - Real-time performance monitoring overlay
|
|
2036
|
+
* PerformanceDashboard - Real-time performance monitoring overlay.
|
|
2003
2037
|
*
|
|
2004
|
-
* Displays
|
|
2005
|
-
*
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
borderRadius: "8px",
|
|
2022
|
-
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
|
|
2023
|
-
fontFamily: "monospace",
|
|
2024
|
-
fontSize: "12px",
|
|
2025
|
-
color: "#fff",
|
|
2026
|
-
zIndex: 9999,
|
|
2027
|
-
minWidth: "200px",
|
|
2028
|
-
backdropFilter: "blur(8px)",
|
|
2029
|
-
border: "1px solid rgba(255, 255, 255, 0.1)",
|
|
2030
|
-
transition: "opacity 0.3s ease",
|
|
2031
|
-
opacity: isVisible ? 1 : 0,
|
|
2032
|
-
pointerEvents: isVisible ? "auto" : "none"
|
|
2033
|
-
})), [ isVisible ]), headerStyle = useMemo((() => ({
|
|
2034
|
-
display: "flex",
|
|
2035
|
-
justifyContent: "space-between",
|
|
2036
|
-
alignItems: "center",
|
|
2037
|
-
marginBottom: "8px",
|
|
2038
|
-
paddingBottom: "8px",
|
|
2039
|
-
borderBottom: "1px solid rgba(255, 255, 255, 0.1)"
|
|
2040
|
-
})), []), titleStyle = useMemo((() => ({
|
|
2041
|
-
fontWeight: "bold",
|
|
2042
|
-
fontSize: "13px",
|
|
2043
|
-
color: "#fff"
|
|
2044
|
-
})), []), closeButtonStyle = useMemo((() => ({
|
|
2045
|
-
background: "transparent",
|
|
2046
|
-
border: "none",
|
|
2047
|
-
color: "#9ca3af",
|
|
2048
|
-
cursor: "pointer",
|
|
2049
|
-
fontSize: "16px",
|
|
2050
|
-
padding: "0",
|
|
2051
|
-
lineHeight: "1"
|
|
2052
|
-
})), []), metricRowStyle = useMemo((() => ({
|
|
2053
|
-
display: "flex",
|
|
2054
|
-
justifyContent: "space-between",
|
|
2055
|
-
alignItems: "center",
|
|
2056
|
-
marginBottom: "6px"
|
|
2057
|
-
})), []), labelStyle = useMemo((() => ({
|
|
2058
|
-
color: "#9ca3af",
|
|
2059
|
-
marginRight: "12px"
|
|
2060
|
-
})), []), valueStyle = useMemo((() => ({
|
|
2061
|
-
fontWeight: "bold"
|
|
2062
|
-
})), []);
|
|
2063
|
-
// Get quality level badge color
|
|
2064
|
-
return isVisible ? jsxs("div", {
|
|
2065
|
-
style: dashboardStyle,
|
|
2038
|
+
* Displays FPS, frame time, quality level, GPU memory, and auto-scaling status.
|
|
2039
|
+
* Rendered only when `debugPerformance={true}` on the parent `AtomixGlass`.
|
|
2040
|
+
*/ const PerformanceDashboard = memo((({metrics: metrics, isVisible: isVisible = !0, onClose: onClose}) => {
|
|
2041
|
+
if (!isVisible) return null;
|
|
2042
|
+
const fpsColor = (fps = metrics.fps) >= 58 ? "var(--atomix-color-success, #4ade80)" : fps >= 45 ? "var(--atomix-color-warning, #fbbf24)" : "var(--atomix-color-danger, #ef4444)";
|
|
2043
|
+
var fps;
|
|
2044
|
+
const isCritical = metrics.fps < 45;
|
|
2045
|
+
return jsxs("div", {
|
|
2046
|
+
className: "c-perf-dashboard u-position-fixed u-top-4 u-end-4 u-p-3 u-px-4 u-text-xs u-font-mono u-text-white u-rounded-md u-border u-border-white-alpha-10 u-shadow-lg",
|
|
2047
|
+
style: {
|
|
2048
|
+
zIndex: 9999,
|
|
2049
|
+
minWidth: "12.5rem",
|
|
2050
|
+
// 200px
|
|
2051
|
+
backgroundColor: "rgba(17, 24, 39, 0.95)",
|
|
2052
|
+
backdropFilter: "blur(8px)",
|
|
2053
|
+
transition: "opacity 0.3s ease"
|
|
2054
|
+
},
|
|
2066
2055
|
children: [ jsxs("div", {
|
|
2067
|
-
|
|
2056
|
+
className: "u-flex u-items-center u-justify-between u-mb-2 u-pb-2 u-border-b u-border-white-alpha-10",
|
|
2068
2057
|
children: [ jsx("span", {
|
|
2069
|
-
|
|
2058
|
+
className: "u-text-sm u-font-bold u-text-white",
|
|
2070
2059
|
children: "Performance Monitor"
|
|
2071
2060
|
}), onClose && jsx("button", {
|
|
2072
|
-
|
|
2061
|
+
className: "u-bg-transparent u-border-none u-p-0 u-line-height-1 u-text-base u-text-gray-400 u-cursor-pointer hover:u-text-white",
|
|
2073
2062
|
onClick: onClose,
|
|
2074
2063
|
"aria-label": "Close performance dashboard",
|
|
2064
|
+
style: {
|
|
2065
|
+
transition: "color 0.2s ease"
|
|
2066
|
+
},
|
|
2075
2067
|
children: "×"
|
|
2076
2068
|
}) ]
|
|
2077
2069
|
}), jsxs("div", {
|
|
2078
|
-
|
|
2070
|
+
className: "u-flex u-items-center u-justify-between u-mb-1-5",
|
|
2079
2071
|
children: [ jsx("span", {
|
|
2080
|
-
|
|
2072
|
+
className: "u-text-gray-400 u-me-3",
|
|
2081
2073
|
children: "FPS"
|
|
2082
2074
|
}), jsx("span", {
|
|
2075
|
+
className: "u-font-bold",
|
|
2083
2076
|
style: {
|
|
2084
|
-
|
|
2085
|
-
color: getFpsColor(metrics.fps)
|
|
2077
|
+
color: fpsColor
|
|
2086
2078
|
},
|
|
2087
2079
|
children: Math.round(metrics.fps)
|
|
2088
2080
|
}) ]
|
|
2089
2081
|
}), jsxs("div", {
|
|
2090
|
-
|
|
2082
|
+
className: "u-flex u-items-center u-justify-between u-mb-1-5",
|
|
2091
2083
|
children: [ jsx("span", {
|
|
2092
|
-
|
|
2084
|
+
className: "u-text-gray-400 u-me-3",
|
|
2093
2085
|
children: "Frame Time"
|
|
2094
2086
|
}), jsxs("span", {
|
|
2095
|
-
|
|
2087
|
+
className: "u-font-bold",
|
|
2096
2088
|
children: [ metrics.frameTime.toFixed(2), "ms" ]
|
|
2097
2089
|
}) ]
|
|
2098
2090
|
}), jsxs("div", {
|
|
2099
|
-
|
|
2091
|
+
className: "u-flex u-items-center u-justify-between u-mb-1-5",
|
|
2100
2092
|
children: [ jsx("span", {
|
|
2101
|
-
|
|
2093
|
+
className: "u-text-gray-400 u-me-3",
|
|
2102
2094
|
children: "Quality"
|
|
2103
2095
|
}), jsx("span", {
|
|
2096
|
+
className: "u-font-bold u-text-uppercase",
|
|
2104
2097
|
style: {
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
case "high":
|
|
2109
|
-
return "#4ade80";
|
|
2110
|
-
|
|
2111
|
-
case "medium":
|
|
2112
|
-
return "#fbbf24";
|
|
2113
|
-
|
|
2114
|
-
case "low":
|
|
2115
|
-
return "#ef4444";
|
|
2116
|
-
|
|
2117
|
-
default:
|
|
2118
|
-
return "#9ca3af";
|
|
2119
|
-
}
|
|
2120
|
-
})(metrics.qualityLevel),
|
|
2121
|
-
textTransform: "uppercase",
|
|
2122
|
-
fontSize: "11px"
|
|
2098
|
+
fontSize: "0.6875rem",
|
|
2099
|
+
// 11px
|
|
2100
|
+
color: getQualityColor(metrics.qualityLevel)
|
|
2123
2101
|
},
|
|
2124
2102
|
children: metrics.qualityLevel
|
|
2125
2103
|
}) ]
|
|
2126
2104
|
}), metrics.gpuMemory && jsxs("div", {
|
|
2127
|
-
|
|
2105
|
+
className: "u-flex u-items-center u-justify-between u-mb-1-5",
|
|
2128
2106
|
children: [ jsx("span", {
|
|
2129
|
-
|
|
2107
|
+
className: "u-text-gray-400 u-me-3",
|
|
2130
2108
|
children: "GPU Memory"
|
|
2131
2109
|
}), jsxs("span", {
|
|
2132
|
-
|
|
2110
|
+
className: "u-font-bold",
|
|
2133
2111
|
children: [ "~", Math.round(metrics.gpuMemory / 1024), "MB" ]
|
|
2134
2112
|
}) ]
|
|
2135
2113
|
}), metrics.isAutoScaling && jsx("div", {
|
|
2114
|
+
className: "u-mt-2 u-pt-2 u-border-t u-border-white-alpha-10 u-text-center",
|
|
2136
2115
|
style: {
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
fontSize: "10px",
|
|
2141
|
-
color: "#6b7280",
|
|
2142
|
-
textAlign: "center"
|
|
2116
|
+
fontSize: "0.625rem",
|
|
2117
|
+
// 10px
|
|
2118
|
+
color: "#6b7280"
|
|
2143
2119
|
},
|
|
2144
2120
|
children: "Auto-scaling active"
|
|
2145
2121
|
}), jsxs("div", {
|
|
2146
|
-
|
|
2147
|
-
marginTop: "8px",
|
|
2148
|
-
paddingTop: "8px",
|
|
2149
|
-
borderTop: "1px solid rgba(255, 255, 255, 0.1)",
|
|
2150
|
-
display: "flex",
|
|
2151
|
-
alignItems: "center",
|
|
2152
|
-
gap: "6px"
|
|
2153
|
-
},
|
|
2122
|
+
className: "u-flex u-items-center u-gap-2 u-mt-2 u-pt-2 u-border-t u-border-white-alpha-10",
|
|
2154
2123
|
children: [ jsx("div", {
|
|
2124
|
+
className: "u-rounded-full",
|
|
2155
2125
|
style: {
|
|
2156
|
-
width: "
|
|
2157
|
-
height: "
|
|
2158
|
-
|
|
2159
|
-
backgroundColor:
|
|
2160
|
-
|
|
2126
|
+
width: "0.5rem",
|
|
2127
|
+
height: "0.5rem",
|
|
2128
|
+
flexShrink: 0,
|
|
2129
|
+
backgroundColor: fpsColor,
|
|
2130
|
+
...isCritical && {
|
|
2131
|
+
animation: "perf-dashboard-pulse 1s infinite"
|
|
2132
|
+
}
|
|
2161
2133
|
}
|
|
2162
2134
|
}), jsx("span", {
|
|
2135
|
+
className: "u-text-xs",
|
|
2163
2136
|
style: {
|
|
2164
|
-
fontSize: "
|
|
2165
|
-
|
|
2137
|
+
fontSize: "0.625rem",
|
|
2138
|
+
// 10px
|
|
2139
|
+
color: fpsColor
|
|
2166
2140
|
},
|
|
2167
|
-
children: metrics.fps
|
|
2141
|
+
children: getFpsLabel(metrics.fps)
|
|
2168
2142
|
}) ]
|
|
2169
2143
|
}) ]
|
|
2170
|
-
})
|
|
2171
|
-
};
|
|
2144
|
+
});
|
|
2145
|
+
}));
|
|
2172
2146
|
|
|
2173
|
-
|
|
2174
|
-
if ("undefined" != typeof document) {
|
|
2175
|
-
const styleSheet = document.createElement("style");
|
|
2176
|
-
styleSheet.textContent = "\n @keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n ",
|
|
2177
|
-
document.head.appendChild(styleSheet);
|
|
2178
|
-
}
|
|
2147
|
+
PerformanceDashboard.displayName = "PerformanceDashboard";
|
|
2179
2148
|
|
|
2180
2149
|
/**
|
|
2181
2150
|
* Mobile optimization presets
|
|
@@ -2186,7 +2155,8 @@ if ("undefined" != typeof document) {
|
|
|
2186
2155
|
/**
|
|
2187
2156
|
* Performance preset - Maximum FPS, reduced quality
|
|
2188
2157
|
* Best for low-end devices or when battery saving is priority
|
|
2189
|
-
*/
|
|
2158
|
+
*/
|
|
2159
|
+
const PERFORMANCE_PRESET = {
|
|
2190
2160
|
distortionOctaves: 2,
|
|
2191
2161
|
// Minimal FBM layers
|
|
2192
2162
|
displacementScale: 50,
|
|
@@ -2295,95 +2265,21 @@ if ("undefined" != typeof document) {
|
|
|
2295
2265
|
saturation: 70
|
|
2296
2266
|
}
|
|
2297
2267
|
}
|
|
2298
|
-
}
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
* - Dynamic border-radius extraction from children CSS properties
|
|
2311
|
-
* - Automatic light/dark theme detection via overLight prop
|
|
2312
|
-
* - Accessibility and performance optimizations
|
|
2313
|
-
* - Multiple displacement modes (standard, polar, prominent, shader)
|
|
2314
|
-
* - Design token integration for consistent theming
|
|
2315
|
-
* - Focus ring support for keyboard navigation
|
|
2316
|
-
* - Responsive breakpoints for mobile optimization
|
|
2317
|
-
* - Enhanced ARIA attributes for screen readers
|
|
2318
|
-
* - Time-based animation system with FBM distortion
|
|
2319
|
-
* - Device preset optimization for performance/quality balance
|
|
2320
|
-
*
|
|
2321
|
-
* Design System Compliance:
|
|
2322
|
-
* - Uses design tokens for opacity, spacing, and colors
|
|
2323
|
-
* - Follows BEM methodology for class naming
|
|
2324
|
-
* - Implements focus-ring mixin for accessibility
|
|
2325
|
-
* - Supports reduced motion and high contrast preferences
|
|
2326
|
-
*
|
|
2327
|
-
* @example
|
|
2328
|
-
* // Basic usage with dynamic border-radius extraction
|
|
2329
|
-
* <AtomixGlass>
|
|
2330
|
-
* <div style={{ borderRadius: '12px' }}>Content with 12px radius</div>
|
|
2331
|
-
* </AtomixGlass>
|
|
2332
|
-
*
|
|
2333
|
-
* @example
|
|
2334
|
-
* // Manual border-radius override
|
|
2335
|
-
* <AtomixGlass borderRadius={20}>
|
|
2336
|
-
* <div>Content with 20px glass radius</div>
|
|
2337
|
-
* </AtomixGlass>
|
|
2338
|
-
*
|
|
2339
|
-
* @example
|
|
2340
|
-
* // Interactive glass with click handler
|
|
2341
|
-
* <AtomixGlass onClick={() => console.log('Clicked')} aria-label="Glass card">
|
|
2342
|
-
* <div>Clickable content</div>
|
|
2343
|
-
* </AtomixGlass>
|
|
2344
|
-
*
|
|
2345
|
-
* @example
|
|
2346
|
-
* // OverLight - Boolean mode (explicit control)
|
|
2347
|
-
* <AtomixGlass overLight={true}>
|
|
2348
|
-
* <div>Content on light background</div>
|
|
2349
|
-
* </AtomixGlass>
|
|
2350
|
-
*
|
|
2351
|
-
* @example
|
|
2352
|
-
* // OverLight - Auto-detection mode
|
|
2353
|
-
* <AtomixGlass overLight="auto">
|
|
2354
|
-
* <div>Content with auto-detected background</div>
|
|
2355
|
-
* </AtomixGlass>
|
|
2356
|
-
*
|
|
2357
|
-
* @example
|
|
2358
|
-
* // OverLight - Object config with custom settings
|
|
2359
|
-
* <AtomixGlass
|
|
2360
|
-
* overLight={{
|
|
2361
|
-
* threshold: 0.8,
|
|
2362
|
-
* opacity: 0.6,
|
|
2363
|
-
* contrast: 1.8,
|
|
2364
|
-
* brightness: 1.0,
|
|
2365
|
-
* saturationBoost: 1.5
|
|
2366
|
-
* }}
|
|
2367
|
-
* >
|
|
2368
|
-
* <div>Content with custom overLight config</div>
|
|
2369
|
-
* </AtomixGlass>
|
|
2370
|
-
*
|
|
2371
|
-
* @example
|
|
2372
|
-
* // Debug mode for overLight detection
|
|
2373
|
-
* <AtomixGlass overLight="auto" debugOverLight={true}>
|
|
2374
|
-
* <div>Content with debug logging enabled</div>
|
|
2375
|
-
* </AtomixGlass>
|
|
2376
|
-
*
|
|
2377
|
-
* @example
|
|
2378
|
-
* // Performance-optimized for mobile devices
|
|
2379
|
-
* <AtomixGlass devicePreset="performance" disableResponsiveBreakpoints={false}>
|
|
2380
|
-
* <div>Mobile-optimized glass effect</div>
|
|
2381
|
-
* </AtomixGlass>
|
|
2382
|
-
*/
|
|
2383
|
-
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, debugOverLight: debugOverLight = !1, height: height, width: width, withTimeAnimation: withTimeAnimation = !1, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion = !1, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5, distortionQuality: distortionQuality = "medium", devicePreset: devicePreset = "balanced", disableResponsiveBreakpoints: disableResponsiveBreakpoints = !1, ...rest}) {
|
|
2384
|
-
const glassRef = useRef(null), contentRef = useRef(null), {zIndex: customZIndex, ...restStyle} = style, isFixedOrSticky = "fixed" === restStyle.position || "sticky" === restStyle.position, {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveBorderRadius: effectiveBorderRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveWithoutEffects: effectiveWithoutEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle, getShaderTime: getShaderTime, applyTimeBasedDistortion: applyTimeBasedDistortion, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown} = useAtomixGlass({
|
|
2268
|
+
}, AtomixGlassInner = forwardRef((function({children: children, displacementScale: displacementScale = ATOMIX_GLASS.DEFAULTS.DISPLACEMENT_SCALE, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, aberrationIntensity: aberrationIntensity = ATOMIX_GLASS.DEFAULTS.ABERRATION_INTENSITY, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer = null, className: className = "", 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, debugOverLight: debugOverLight = !1, height: height, width: width, withTimeAnimation: withTimeAnimation = !1, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion = !1, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5, distortionQuality: distortionQuality = "medium", devicePreset: devicePreset = "balanced", disableResponsiveBreakpoints: disableResponsiveBreakpoints = !1, isFixedOrSticky: propsIsFixedOrSticky, ...rest}, ref) {
|
|
2269
|
+
const glassRef = useRef(null), contentRef = useRef(null), internalWrapperRef = useRef(null), mergedRef = useMemo((() =>
|
|
2270
|
+
// Helper to merge refs
|
|
2271
|
+
function(...refs) {
|
|
2272
|
+
return node => {
|
|
2273
|
+
refs.forEach((ref => {
|
|
2274
|
+
"function" == typeof ref ? ref(node) : null != ref && (ref.current = node);
|
|
2275
|
+
}));
|
|
2276
|
+
};
|
|
2277
|
+
}
|
|
2278
|
+
// Internal implementation with forwardRef
|
|
2279
|
+
(ref, internalWrapperRef)), [ ref ]), {zIndex: customZIndex, ...restStyle} = style, isFixedOrSticky = propsIsFixedOrSticky || "fixed" === restStyle.position || "sticky" === restStyle.position, {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveBorderRadius: effectiveBorderRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveWithoutEffects: effectiveWithoutEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle, getShaderTime: getShaderTime, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown} = useAtomixGlass({
|
|
2385
2280
|
glassRef: glassRef,
|
|
2386
2281
|
contentRef: contentRef,
|
|
2282
|
+
wrapperRef: internalWrapperRef,
|
|
2387
2283
|
borderRadius: borderRadius,
|
|
2388
2284
|
globalMousePosition: externalGlobalMousePosition,
|
|
2389
2285
|
mouseOffset: externalMouseOffset,
|
|
@@ -2412,7 +2308,6 @@ function AtomixGlass({children: children, displacementScale: displacementScale =
|
|
|
2412
2308
|
distortionGain: distortionGain,
|
|
2413
2309
|
distortionQuality: distortionQuality
|
|
2414
2310
|
});
|
|
2415
|
-
// Re-calculate only when devicePreset changes
|
|
2416
2311
|
// Responsive breakpoint system - automatically adjusts parameters based on viewport
|
|
2417
2312
|
!
|
|
2418
2313
|
/**
|
|
@@ -2602,11 +2497,10 @@ function AtomixGlass({children: children, displacementScale: displacementScale =
|
|
|
2602
2497
|
},
|
|
2603
2498
|
breakpoints: MOBILE_OPTIMIZED_BREAKPOINTS,
|
|
2604
2499
|
enabled: !disableResponsiveBreakpoints && "undefined" != typeof window,
|
|
2605
|
-
// Enable unless disabled
|
|
2606
2500
|
debug: !1
|
|
2607
2501
|
});
|
|
2608
2502
|
// Performance monitoring - tracks FPS, frame time, memory usage
|
|
2609
|
-
const {metrics: performanceMetrics,
|
|
2503
|
+
const {metrics: performanceMetrics, toggleMonitoring: toggleMonitoring} =
|
|
2610
2504
|
/**
|
|
2611
2505
|
* Performance Monitor Hook
|
|
2612
2506
|
*
|
|
@@ -2770,17 +2664,17 @@ function AtomixGlass({children: children, displacementScale: displacementScale =
|
|
|
2770
2664
|
toggleMonitoring: toggleMonitoring
|
|
2771
2665
|
};
|
|
2772
2666
|
}({
|
|
2773
|
-
enabled:
|
|
2774
|
-
//
|
|
2667
|
+
enabled: debugPerformance,
|
|
2668
|
+
// Enable when debugPerformance is true
|
|
2775
2669
|
debug: !1,
|
|
2776
2670
|
showOverlay: !1
|
|
2777
2671
|
});
|
|
2778
|
-
// Auto-start performance monitoring
|
|
2672
|
+
// Auto-start performance monitoring when debugPerformance is enabled
|
|
2779
2673
|
React.useEffect((() => {
|
|
2780
|
-
|
|
2674
|
+
debugPerformance && toggleMonitoring();
|
|
2781
2675
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2782
|
-
}), []);
|
|
2783
|
-
//
|
|
2676
|
+
}), [ debugPerformance ]);
|
|
2677
|
+
// Re-run when debugPerformance changes
|
|
2784
2678
|
const isOverLight = useMemo((() => overLightConfig.isOverLight), [ overLightConfig.isOverLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, rootLayoutStyle = useMemo((() => {
|
|
2785
2679
|
if (!isFixedOrSticky) return {};
|
|
2786
2680
|
const {position: p, top: t, left: l, right: r, bottom: b} = restStyle;
|
|
@@ -2808,34 +2702,30 @@ function AtomixGlass({children: children, displacementScale: displacementScale =
|
|
|
2808
2702
|
if (isFixedOrSticky) {
|
|
2809
2703
|
const {position: _p, top: _t, left: _l, right: _r, bottom: _b, ...visualStyle} = restStyle;
|
|
2810
2704
|
return {
|
|
2811
|
-
...visualStyle
|
|
2812
|
-
...!effectiveWithoutEffects && {
|
|
2813
|
-
transform: transformStyle
|
|
2814
|
-
}
|
|
2705
|
+
...visualStyle
|
|
2815
2706
|
};
|
|
2816
2707
|
}
|
|
2817
2708
|
return {
|
|
2818
|
-
...restStyle
|
|
2819
|
-
...!effectiveWithoutEffects && {
|
|
2820
|
-
transform: transformStyle
|
|
2821
|
-
}
|
|
2709
|
+
...restStyle
|
|
2822
2710
|
};
|
|
2823
|
-
}), [ isFixedOrSticky, restStyle
|
|
2711
|
+
}), [ isFixedOrSticky, restStyle ]);
|
|
2824
2712
|
// Build className with state modifiers
|
|
2825
2713
|
const 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((() => ({
|
|
2826
2714
|
position: isFixedOrSticky ? "absolute" : restStyle.position || "absolute",
|
|
2827
|
-
top: isFixedOrSticky ?
|
|
2828
|
-
left: isFixedOrSticky ?
|
|
2829
|
-
|
|
2715
|
+
top: isFixedOrSticky ? restStyle.top ?? 0 : 0,
|
|
2716
|
+
left: isFixedOrSticky ? restStyle.left ?? 0 : 0,
|
|
2717
|
+
right: isFixedOrSticky ? restStyle.right ?? "auto" : "auto",
|
|
2718
|
+
bottom: isFixedOrSticky ? restStyle.bottom ?? "auto" : "auto"
|
|
2719
|
+
})), [ isFixedOrSticky, restStyle.position, restStyle.top, restStyle.left, restStyle.right, restStyle.bottom ]), adjustedSize = useMemo((() => {
|
|
2830
2720
|
// Keep a reference to positionStyles to avoid unused-variable lint,
|
|
2831
2721
|
// but sizing is driven by explicit width/height or measured size.
|
|
2832
2722
|
positionStyles.position;
|
|
2833
|
-
const resolveLength = (value, measured) => void 0 !== value ? "number" == typeof value ? `${value}px` : value : measured > 0 ? `${measured}px` : "100%", effectiveWidth = width ?? restStyle.width, effectiveHeight = height ?? restStyle.height;
|
|
2723
|
+
const resolveLength = (value, measured) => void 0 !== value && isFixedOrSticky ? "number" == typeof value ? `${value}px` : value : measured > 0 && isFixedOrSticky ? `${measured}px` : "100%", effectiveWidth = width ?? restStyle.width, effectiveHeight = height ?? restStyle.height;
|
|
2834
2724
|
return {
|
|
2835
2725
|
width: resolveLength(effectiveWidth, glassSize.width),
|
|
2836
2726
|
height: resolveLength(effectiveHeight, glassSize.height)
|
|
2837
2727
|
};
|
|
2838
|
-
}), [ width, height, restStyle.width, restStyle.height, positionStyles.position, glassSize.width, glassSize.height ]), gradientValues = useMemo((() => {
|
|
2728
|
+
}), [ width, height, restStyle.width, restStyle.height, positionStyles.position, glassSize.width, glassSize.height, isFixedOrSticky ]), gradientValues = useMemo((() => {
|
|
2839
2729
|
const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT;
|
|
2840
2730
|
return {
|
|
2841
2731
|
borderGradientAngle: GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER,
|
|
@@ -2865,33 +2755,32 @@ function AtomixGlass({children: children, displacementScale: displacementScale =
|
|
|
2865
2755
|
absMx: absMx,
|
|
2866
2756
|
absMy: absMy
|
|
2867
2757
|
};
|
|
2868
|
-
}), [ mouseOffset.x, mouseOffset.y ]), opacityValues = useMemo((() => {
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
};
|
|
2877
|
-
}), [ isHovered, isActive, isOverLight, overLightConfig.opacity ]), glassVars = useMemo((() => {
|
|
2878
|
-
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;
|
|
2758
|
+
}), [ mouseOffset.x, mouseOffset.y ]), clampedOverLightOpacity = Math.max(0, Math.min(1, overLightConfig?.opacity ?? .4)), clampedBorderOpacity = Math.max(0, Math.min(1, overLightConfig?.borderOpacity ?? 1)), opacityValues = useMemo((() => ({
|
|
2759
|
+
hover1: isHovered || isActive ? .5 : 0,
|
|
2760
|
+
hover2: isActive ? .5 : 0,
|
|
2761
|
+
hover3: isHovered ? .4 : isActive ? .8 : 0,
|
|
2762
|
+
base: isOverLight ? clampedOverLightOpacity || .4 : 0,
|
|
2763
|
+
over: isOverLight ? 1.1 * (clampedOverLightOpacity || .4) : 0
|
|
2764
|
+
})), [ isHovered, isActive, isOverLight, clampedOverLightOpacity ]), glassVars = useMemo((() => {
|
|
2765
|
+
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;
|
|
2879
2766
|
return {
|
|
2880
2767
|
...void 0 !== customZIndex && {
|
|
2881
2768
|
"--atomix-glass-base-z-index": customZIndex
|
|
2882
2769
|
},
|
|
2883
2770
|
"--atomix-glass-radius": `${effectiveBorderRadius}px`,
|
|
2884
2771
|
"--atomix-glass-transform": transformStyle || "none",
|
|
2885
|
-
|
|
2886
|
-
"--atomix-glass-position": rootLayoutStyle.position
|
|
2887
|
-
"--atomix-glass-top": `${isFixedOrSticky ?
|
|
2888
|
-
"--atomix-glass-left": `${isFixedOrSticky ?
|
|
2772
|
+
"--atomix-glass-container-position": `${isFixedOrSticky ? rootLayoutStyle.position : positionStyles.position}`,
|
|
2773
|
+
"--atomix-glass-position": `${isFixedOrSticky ? rootLayoutStyle.position : positionStyles.position}`,
|
|
2774
|
+
"--atomix-glass-top": `${isFixedOrSticky ? restStyle.top ?? 0 : 0}px`,
|
|
2775
|
+
"--atomix-glass-left": `${isFixedOrSticky ? restStyle.left ?? 0 : 0}px`,
|
|
2776
|
+
"--atomix-glass-right": isFixedOrSticky ? restStyle.right ?? "auto" : "auto",
|
|
2777
|
+
"--atomix-glass-bottom": isFixedOrSticky ? restStyle.bottom ?? "auto" : "auto",
|
|
2889
2778
|
"--atomix-glass-width": adjustedSize.width,
|
|
2890
2779
|
"--atomix-glass-height": adjustedSize.height,
|
|
2891
|
-
"--atomix-glass-border-width": "var(--atomix-spacing-0-5, 0.
|
|
2780
|
+
"--atomix-glass-border-width": "var(--atomix-spacing-0-5, 0.125rem)",
|
|
2892
2781
|
"--atomix-glass-blend-mode": isOverLight ? "multiply" : "overlay",
|
|
2893
|
-
"--atomix-glass-border-gradient-1": `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[0] ?? 1) *
|
|
2894
|
-
"--atomix-glass-border-gradient-2": `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[2] ?? 1) *
|
|
2782
|
+
"--atomix-glass-border-gradient-1": `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[0] ?? 1) * clampedBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[1] ?? 1) * clampedBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
|
|
2783
|
+
"--atomix-glass-border-gradient-2": `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[2] ?? 1) * clampedBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[3] ?? 1) * clampedBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
|
|
2895
2784
|
"--atomix-glass-hover-1-opacity": opacityValues.hover1,
|
|
2896
2785
|
"--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}%)`,
|
|
2897
2786
|
"--atomix-glass-hover-2-opacity": opacityValues.hover2,
|
|
@@ -2905,13 +2794,14 @@ function AtomixGlass({children: children, displacementScale: displacementScale =
|
|
|
2905
2794
|
"--atomix-glass-overlay-highlight-opacity": opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER,
|
|
2906
2795
|
"--atomix-glass-overlay-highlight-bg": `radial-gradient(circle at ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_X}% ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_Y}%, rgba(255, 255, 255, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.WHITE_OPACITY}) 0%, transparent ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.STOP}%)`
|
|
2907
2796
|
};
|
|
2908
|
-
}), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle, adjustedSize, isOverLight,
|
|
2797
|
+
}), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle, adjustedSize, isOverLight, clampedBorderOpacity, customZIndex, isFixedOrSticky, positionStyles.position, rootLayoutStyle.position, restStyle.top, restStyle.left, restStyle.right, restStyle.bottom ]), renderBackgroundLayer = layerType => jsx("div", {
|
|
2909
2798
|
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(" ")
|
|
2910
2799
|
});
|
|
2911
2800
|
// Calculate position and size styles for internal layers
|
|
2912
2801
|
// When root is fixed/sticky, internal layers use absolute (relative to root)
|
|
2913
2802
|
return jsxs("div", {
|
|
2914
2803
|
...rest,
|
|
2804
|
+
ref: mergedRef,
|
|
2915
2805
|
className: componentClassName,
|
|
2916
2806
|
style: {
|
|
2917
2807
|
...glassVars
|
|
@@ -2921,17 +2811,14 @@ function AtomixGlass({children: children, displacementScale: displacementScale =
|
|
|
2921
2811
|
"aria-label": ariaLabel,
|
|
2922
2812
|
"aria-describedby": ariaDescribedBy,
|
|
2923
2813
|
"aria-disabled": !(!onClick || !effectiveWithoutEffects) || !onClick && void 0,
|
|
2924
|
-
"aria-pressed":
|
|
2814
|
+
"aria-pressed": void 0,
|
|
2925
2815
|
onKeyDown: onClick ? handleKeyDown : void 0,
|
|
2926
2816
|
children: [ jsx(AtomixGlassContainer, {
|
|
2927
2817
|
ref: glassRef,
|
|
2928
2818
|
contentRef: contentRef,
|
|
2929
2819
|
className: className,
|
|
2930
2820
|
style: {
|
|
2931
|
-
...restStyle
|
|
2932
|
-
...!isFixedOrSticky && {
|
|
2933
|
-
position: "relative"
|
|
2934
|
-
}
|
|
2821
|
+
...restStyle
|
|
2935
2822
|
},
|
|
2936
2823
|
borderRadius: effectiveBorderRadius,
|
|
2937
2824
|
displacementScale: effectiveWithoutEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
|
|
@@ -2967,6 +2854,7 @@ function AtomixGlass({children: children, displacementScale: displacementScale =
|
|
|
2967
2854
|
effectiveReducedMotion: effectiveReducedMotion,
|
|
2968
2855
|
shaderVariant: shaderVariant,
|
|
2969
2856
|
withLiquidBlur: withLiquidBlur,
|
|
2857
|
+
isFixedOrSticky: isFixedOrSticky,
|
|
2970
2858
|
// Phase 1: Animation System props
|
|
2971
2859
|
shaderTime: getShaderTime(),
|
|
2972
2860
|
withTimeAnimation: withTimeAnimation,
|
|
@@ -2995,6 +2883,8 @@ function AtomixGlass({children: children, displacementScale: displacementScale =
|
|
|
2995
2883
|
}) ]
|
|
2996
2884
|
}), withBorder && jsxs(Fragment, {
|
|
2997
2885
|
children: [ jsx("span", {
|
|
2886
|
+
className: ATOMIX_GLASS.BORDER_BACKDROP_CLASS
|
|
2887
|
+
}), jsx("span", {
|
|
2998
2888
|
className: ATOMIX_GLASS.BORDER_1_CLASS
|
|
2999
2889
|
}), jsx("span", {
|
|
3000
2890
|
className: ATOMIX_GLASS.BORDER_2_CLASS
|
|
@@ -3005,11 +2895,18 @@ function AtomixGlass({children: children, displacementScale: displacementScale =
|
|
|
3005
2895
|
onClose: () => {}
|
|
3006
2896
|
}) ]
|
|
3007
2897
|
});
|
|
3008
|
-
}
|
|
2898
|
+
}));
|
|
3009
2899
|
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
2900
|
+
/**
|
|
2901
|
+
* Balanced preset - Good quality with reasonable performance
|
|
2902
|
+
* Default preset for most mobile devices
|
|
2903
|
+
*/ AtomixGlassInner.displayName = "AtomixGlass";
|
|
2904
|
+
|
|
2905
|
+
/**
|
|
2906
|
+
* AtomixGlass - wrapped with React.memo to prevent unnecessary re-renders.
|
|
2907
|
+
* Ref is forwarded to the root `<div>` element.
|
|
2908
|
+
*/
|
|
2909
|
+
const AtomixGlass = memo(AtomixGlassInner), smoothStep = (a, b, t) => {
|
|
3013
2910
|
// Add input validation
|
|
3014
2911
|
if ("number" != typeof a || "number" != typeof b || "number" != typeof t) return 0;
|
|
3015
2912
|
const clamped = Math.max(0, Math.min(1, (t - a) / (b - a)));
|
|
@@ -3304,6 +3201,8 @@ const smoothStep = (a, b, t) => {
|
|
|
3304
3201
|
value: "Module"
|
|
3305
3202
|
}));
|
|
3306
3203
|
|
|
3204
|
+
// Adapted from https://github.com/shuding/liquid-glass
|
|
3205
|
+
// Constants
|
|
3307
3206
|
/**
|
|
3308
3207
|
* Component Utilities
|
|
3309
3208
|
*
|