@shohojdhara/atomix 0.6.5 → 0.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/atomix.css +2 -2
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +1 -1
- package/dist/atomix.min.css.map +1 -1
- package/dist/atomix.umd.js +1 -1
- package/dist/atomix.umd.js.map +1 -1
- package/dist/atomix.umd.min.js +1 -1
- package/dist/charts.js +65 -255
- package/dist/charts.js.map +1 -1
- package/dist/core.js +65 -255
- package/dist/core.js.map +1 -1
- package/dist/forms.js +65 -255
- package/dist/forms.js.map +1 -1
- package/dist/heavy.js +65 -255
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +6 -37
- package/dist/index.esm.js +66 -300
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +66 -300
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +1 -1
- package/src/components/AtomixGlass/AtomixGlass.tsx +0 -9
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +0 -2
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +1 -1
- package/src/components/AtomixGlass/glass-utils.ts +82 -53
- package/src/components/AtomixGlass/shader-utils.ts +19 -77
- package/src/components/Form/Select.test.tsx +6 -6
- package/src/components/Form/Textarea.stories.tsx +5 -5
- package/src/lib/composables/useAtomixGlass.ts +2 -134
- package/src/lib/composables/useAtomixGlassStyles.ts +3 -3
- package/src/lib/composables/usePerformanceMonitor.ts +0 -66
- package/src/lib/constants/components.ts +6 -1
- package/src/styles/01-settings/_settings.atomix-glass.scss +2 -2
- package/src/styles/02-tools/_tools.button.scss +51 -42
- package/src/styles/06-components/_components.atomix-glass.scss +2 -2
- package/src/components/AtomixGlass/PerformanceDashboard.tsx +0 -171
- package/src/components/AtomixGlass/animation-system.ts +0 -578
package/dist/core.js
CHANGED
|
@@ -664,6 +664,11 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
664
664
|
MIN_BLUR: .1,
|
|
665
665
|
MOUSE_INFLUENCE_DIVISOR: 100,
|
|
666
666
|
EDGE_FADE_PIXELS: 2,
|
|
667
|
+
// Interaction intensity multipliers shared by the hook and the imperative style updater
|
|
668
|
+
INTERACTION: {
|
|
669
|
+
HOVER_INTENSITY: 1.4,
|
|
670
|
+
ACTIVE_INTENSITY: 1.6
|
|
671
|
+
},
|
|
667
672
|
// Elasticity physics constants — Apple-tuned: soft springs, fast settling, minimal stretch
|
|
668
673
|
ELASTICITY_TRANSLATION_FACTOR: .06,
|
|
669
674
|
// Subtler elastic shift (was 0.1)
|
|
@@ -861,7 +866,7 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
861
866
|
},
|
|
862
867
|
// Container shadows — hairline inner catch + soft floating lift (Apple player bar)
|
|
863
868
|
CONTAINER_SHADOW: {
|
|
864
|
-
LIGHT: "inset 0 0.5px 0 rgba(255, 255, 255, 0.32), inset 0 1px 2px rgba(255, 255, 255, 0.06), 0
|
|
869
|
+
LIGHT: "inset 0 0.5px 0 rgba(255, 255, 255, 0.32), inset 0 1px 2px rgba(255, 255, 255, 0.06), 0 4px 16px rgba(0, 0, 0, 0.12), 0 1px 4px rgba(0, 0, 0, 0.08)"
|
|
865
870
|
},
|
|
866
871
|
// Phase 1: Animation System Constants
|
|
867
872
|
ANIMATION: {
|
|
@@ -1014,7 +1019,28 @@ const {CONSTANTS: CONSTANTS$3} = ATOMIX_GLASS, calculateElementCenter = rect =>
|
|
|
1014
1019
|
}, smoothstep = t => {
|
|
1015
1020
|
const clamped = Math.max(0, Math.min(1, t));
|
|
1016
1021
|
return clamped * clamped * (3 - 2 * clamped);
|
|
1017
|
-
}, lerp
|
|
1022
|
+
}, lerp = (a, b, t) => a + (b - a) * t, softClamp = (value, max) => max <= 0 ? 0 : max * (1 - Math.exp(-value / max)), clamp = (value, min, max) => "number" != typeof value || isNaN(value) ? min : Math.max(min, Math.min(max, value)), smoothstepEdge = (edge0, edge1, x) => "number" != typeof edge0 || "number" != typeof edge1 || "number" != typeof x ? 0 : smoothstep((x - edge0) / (edge1 - edge0)), easeInOutCubic = t => {
|
|
1023
|
+
if ("number" != typeof t || isNaN(t)) return 0;
|
|
1024
|
+
const clamped = Math.max(0, Math.min(1, t));
|
|
1025
|
+
return clamped < .5 ? 4 * clamped * clamped * clamped : 1 - Math.pow(-2 * clamped + 2, 3) / 2;
|
|
1026
|
+
}, easeOutQuart = t => {
|
|
1027
|
+
if ("number" != typeof t || isNaN(t)) return 0;
|
|
1028
|
+
const clamped = Math.max(0, Math.min(1, t));
|
|
1029
|
+
return 1 - Math.pow(1 - clamped, 4);
|
|
1030
|
+
}, vec2Length = (x, y) => {
|
|
1031
|
+
if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y)) return 0;
|
|
1032
|
+
const maxComponent = Math.max(Math.abs(x), Math.abs(y));
|
|
1033
|
+
if (0 === maxComponent) return 0;
|
|
1034
|
+
const scaledX = x / maxComponent, scaledY = y / maxComponent;
|
|
1035
|
+
return maxComponent * Math.sqrt(scaledX * scaledX + scaledY * scaledY);
|
|
1036
|
+
}, getInteractionIntensity = (isHovered, isActive) => ({
|
|
1037
|
+
hoverIntensity: isHovered ? CONSTANTS$3.INTERACTION.HOVER_INTENSITY : 1,
|
|
1038
|
+
activeIntensity: isActive ? CONSTANTS$3.INTERACTION.ACTIVE_INTENSITY : 1
|
|
1039
|
+
})
|
|
1040
|
+
/**
|
|
1041
|
+
* Spring-damper integration helper
|
|
1042
|
+
* Calculates the next value based on velocity, stiffness, and damping.
|
|
1043
|
+
*/ , calculateSpring = (current, target, velocity, stiffness = .1, damping = .8) => {
|
|
1018
1044
|
const newVelocity = (velocity + (target - current) * stiffness) * damping;
|
|
1019
1045
|
return {
|
|
1020
1046
|
value: current + newVelocity,
|
|
@@ -1220,7 +1246,7 @@ const GlassFilter = memo(GlassFilterComponent, ((prevProps, nextProps) => prevP
|
|
|
1220
1246
|
}, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {}, borderRadius: borderRadius = 0, glassSize: glassSize = {
|
|
1221
1247
|
width: 0,
|
|
1222
1248
|
height: 0
|
|
1223
|
-
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, isFixedOrSticky: isFixedOrSticky = !1,
|
|
1249
|
+
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, isFixedOrSticky: isFixedOrSticky = !1, withTimeAnimation: withTimeAnimation = !1, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion = !1, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5, distortionQuality: distortionQuality = "medium", contentRef: contentRef}, ref) => {
|
|
1224
1250
|
// React 18 useId — stable, unique, and SSR-safe (no module-level counter)
|
|
1225
1251
|
const rawId = useId(), filterId = useMemo((() => `atomix-glass-filter-${rawId.replace(/:/g, "")}`), [ rawId ]), containerRef = useForkRef(ref, null), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null), shaderUpdateTimeoutRef = useRef(null), animationFrameRef = useRef(null);
|
|
1226
1252
|
// Lazy load shader utilities only when shader mode is needed
|
|
@@ -1518,7 +1544,7 @@ class {
|
|
|
1518
1544
|
}, {BORDER: BORDER, CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, BORDER_GRADIENT = BORDER.GRADIENT, WHITE = CONSTANTS$2.PALETTE.WHITE, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
|
|
1519
1545
|
if (!wrapperElement && !containerElement) return;
|
|
1520
1546
|
if (!validateGlassSize(params.glassSize)) return;
|
|
1521
|
-
const {mouseOffset: mouseOffset, globalMousePosition: globalMousePosition, glassSize: glassSize, isHovered: isHovered, isActive: isActive, isOverLight: isOverLight, baseOverLightConfig: baseOverLightConfig, effectiveBorderRadius: effectiveBorderRadius, effectiveWithoutEffects: effectiveWithoutEffects, effectiveReducedMotion: effectiveReducedMotion, elasticity: elasticity, elasticTranslation: elasticTranslation, elasticVelocity: elasticVelocity, mouseVelocity: mouseVelocity, directionalScale: directionalScale, scaleBase: scaleBase, onClick: onClick, withLiquidBlur: withLiquidBlur, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, isFixedOrSticky: isFixedOrSticky = !1, borderAnimated: borderAnimated = !0, borderOpacityMultiplier: borderOpacityMultiplier = 1} = params, mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity
|
|
1547
|
+
const {mouseOffset: mouseOffset, globalMousePosition: globalMousePosition, glassSize: glassSize, isHovered: isHovered, isActive: isActive, isOverLight: isOverLight, baseOverLightConfig: baseOverLightConfig, effectiveBorderRadius: effectiveBorderRadius, effectiveWithoutEffects: effectiveWithoutEffects, effectiveReducedMotion: effectiveReducedMotion, elasticity: elasticity, elasticTranslation: elasticTranslation, elasticVelocity: elasticVelocity, mouseVelocity: mouseVelocity, directionalScale: directionalScale, scaleBase: scaleBase, onClick: onClick, withLiquidBlur: withLiquidBlur, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, isFixedOrSticky: isFixedOrSticky = !1, borderAnimated: borderAnimated = !0, borderOpacityMultiplier: borderOpacityMultiplier = 1} = params, mouseInfluence = calculateMouseInfluence(mouseOffset), {hoverIntensity: hoverIntensity, activeIntensity: activeIntensity} = getInteractionIntensity(isHovered, isActive), overLightConfig = {
|
|
1522
1548
|
opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
|
|
1523
1549
|
contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
|
|
1524
1550
|
brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
|
|
@@ -1649,140 +1675,9 @@ class {
|
|
|
1649
1675
|
style.setProperty("--atomix-glass-container-shadow-opacity", effectiveWithoutEffects ? "0" : "1"),
|
|
1650
1676
|
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"),
|
|
1651
1677
|
style.setProperty("--atomix-glass-container-text-shadow", isOverLight ? "0px 1px 2px rgba(255, 255, 255, 0.15)" : "0px 2px 12px rgba(0, 0, 0, 0.4)"),
|
|
1652
|
-
style.setProperty("--atomix-glass-container-box-shadow", isOverLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "0
|
|
1678
|
+
style.setProperty("--atomix-glass-container-box-shadow", isOverLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "0 4px 16px rgba(0, 0, 0, 0.14), 0 1px 4px rgba(0, 0, 0, 0.10)");
|
|
1653
1679
|
}
|
|
1654
|
-
};
|
|
1655
|
-
|
|
1656
|
-
/**
|
|
1657
|
-
* Animation System for AtomixGlass Component
|
|
1658
|
-
*
|
|
1659
|
-
* Implements Phase 1 features from the AtomixGlass Feature Implementation Roadmap:
|
|
1660
|
-
* - Feature 1.1: Time-Based Animation System
|
|
1661
|
-
* - Feature 1.2: Multi-Layer Distortion System (FBM)
|
|
1662
|
-
*
|
|
1663
|
-
* @packageDocumentation
|
|
1664
|
-
*/
|
|
1665
|
-
// ============================================================================
|
|
1666
|
-
// Noise Functions for FBM (Feature 1.2)
|
|
1667
|
-
// ============================================================================
|
|
1668
|
-
/**
|
|
1669
|
-
* Perlin noise implementation for smooth gradient noise
|
|
1670
|
-
*
|
|
1671
|
-
* @param x - X coordinate
|
|
1672
|
-
* @param y - Y coordinate
|
|
1673
|
-
* @returns Noise value in range [0, 1]
|
|
1674
|
-
*/
|
|
1675
|
-
function perlinNoise(x, y) {
|
|
1676
|
-
// Simplified Perlin noise using pseudo-random gradients
|
|
1677
|
-
const X = 255 & Math.floor(x), Y = 255 & Math.floor(y), xf = x - Math.floor(x), yf = y - Math.floor(y), u = fade(xf), v = fade(yf), A = p[X] + Y & 255, B = p[X + 1] + Y & 255, ga = grad(p[A], xf, yf), gb = grad(p[B], xf - 1, yf), gc = grad(p[A + 1 & 255], xf, yf - 1), gd = grad(p[B + 1 & 255], xf - 1, yf - 1), lerpX1 = lerp(ga, gb, u), lerpX2 = lerp(gc, gd, u);
|
|
1678
|
-
// Scale to [0, 1] range
|
|
1679
|
-
return (lerp(lerpX1, lerpX2, v) + 1) / 2;
|
|
1680
|
-
}
|
|
1681
|
-
|
|
1682
|
-
// ============================================================================
|
|
1683
|
-
// Fractal Brownian Motion (FBM) Engine (Feature 1.2)
|
|
1684
|
-
// ============================================================================
|
|
1685
|
-
/**
|
|
1686
|
-
* Creates an FBM engine with configurable parameters
|
|
1687
|
-
*
|
|
1688
|
-
* @param config - FBM configuration (octaves, lacunarity, gain)
|
|
1689
|
-
* @returns Object with fbm function
|
|
1690
|
-
*
|
|
1691
|
-
* @example
|
|
1692
|
-
* ```typescript
|
|
1693
|
-
* const fbmEngine = createFBMEngine({ octaves: 5, lacunarity: 2, gain: 0.5 });
|
|
1694
|
-
*
|
|
1695
|
-
* // Generate noise at position (0.5, 0.5) with time animation
|
|
1696
|
-
* const noiseValue = fbmEngine.fbm(0.5, 0.5, Date.now());
|
|
1697
|
-
* ```
|
|
1698
|
-
*/ function createFBMEngine(config) {
|
|
1699
|
-
/**
|
|
1700
|
-
* Fractal Brownian Motion function
|
|
1701
|
-
* Combines multiple octaves of noise for complex, natural patterns
|
|
1702
|
-
*
|
|
1703
|
-
* @param x - X coordinate
|
|
1704
|
-
* @param y - Y coordinate
|
|
1705
|
-
* @param time - Optional time value for animation
|
|
1706
|
-
* @returns FBM noise value in range [0, 1]
|
|
1707
|
-
*/
|
|
1708
|
-
const fbm = (x, y, time = 0) => {
|
|
1709
|
-
let value = 0, amplitude = .5, frequency = 1, phase = .001 * time;
|
|
1710
|
-
// Convert to seconds for reasonable animation speed
|
|
1711
|
-
for (let i = 0; i < config.octaves; i++)
|
|
1712
|
-
// Apply time-based phase shift to all octaves
|
|
1713
|
-
value += perlinNoise(x * frequency + phase, y * frequency + phase) * amplitude,
|
|
1714
|
-
frequency *= config.lacunarity, // Increase frequency
|
|
1715
|
-
amplitude *= config.gain;
|
|
1716
|
-
return value;
|
|
1717
|
-
};
|
|
1718
|
-
/**
|
|
1719
|
-
* Get FBM with simple time factor
|
|
1720
|
-
*/ return {
|
|
1721
|
-
fbm: fbm,
|
|
1722
|
-
fbmWithTime: (x, y, time) => fbm(x, y, time)
|
|
1723
|
-
};
|
|
1724
|
-
}
|
|
1725
|
-
|
|
1726
|
-
/**
|
|
1727
|
-
* Gets optimal FBM config based on quality preset
|
|
1728
|
-
*
|
|
1729
|
-
* @param quality - Quality preset level
|
|
1730
|
-
* @returns FBM configuration for the quality level
|
|
1731
|
-
*/ const fbmEngineCache = new Map;
|
|
1732
|
-
|
|
1733
|
-
// ============================================================================
|
|
1734
|
-
// Shader Utility Functions for Time-Based Effects
|
|
1735
|
-
// ============================================================================
|
|
1736
|
-
/**
|
|
1737
|
-
* Liquid glass distortion with time-based animation
|
|
1738
|
-
* Uses FBM to create organic, flowing liquid effects
|
|
1739
|
-
*
|
|
1740
|
-
* @param uv - UV coordinates (normalized 0-1)
|
|
1741
|
-
* @param time - Elapsed time in milliseconds
|
|
1742
|
-
* @param config - FBM configuration
|
|
1743
|
-
* @returns Distorted UV coordinates
|
|
1744
|
-
*/ function liquidGlassWithTime(uv, time, config) {
|
|
1745
|
-
const configKey = `${config.octaves}-${config.lacunarity}-${config.gain}`;
|
|
1746
|
-
let fbmEngine = fbmEngineCache.get(configKey);
|
|
1747
|
-
fbmEngine || (fbmEngine = createFBMEngine(config), fbmEngineCache.set(configKey, fbmEngine));
|
|
1748
|
-
// Animate noise with time
|
|
1749
|
-
const animatedNoise = fbmEngine.fbmWithTime(2 * uv.x + 1e-4 * time, 2 * uv.y + 15e-5 * time, time);
|
|
1750
|
-
return {
|
|
1751
|
-
x: uv.x + .04 * (animatedNoise - .5),
|
|
1752
|
-
y: uv.y + .04 * (animatedNoise - .5)
|
|
1753
|
-
};
|
|
1754
|
-
}
|
|
1755
|
-
|
|
1756
|
-
// ============================================================================
|
|
1757
|
-
// Helper Functions
|
|
1758
|
-
// ============================================================================
|
|
1759
|
-
/**
|
|
1760
|
-
* Fade curve for smooth interpolation (Perlin's fade function)
|
|
1761
|
-
*/ function fade(t) {
|
|
1762
|
-
return t * t * t * (t * (6 * t - 15) + 10);
|
|
1763
|
-
}
|
|
1764
|
-
|
|
1765
|
-
/**
|
|
1766
|
-
* Linear interpolation
|
|
1767
|
-
*/ function lerp(a, b, t) {
|
|
1768
|
-
return a + t * (b - a);
|
|
1769
|
-
}
|
|
1770
|
-
|
|
1771
|
-
/**
|
|
1772
|
-
* Gradient calculation for Perlin noise
|
|
1773
|
-
*/ function grad(hash, x, y) {
|
|
1774
|
-
const h = 15 & hash, u = h < 8 ? x : y, v = h < 4 ? y : 12 === h || 14 === h ? x : 0;
|
|
1775
|
-
return (1 & h ? -u : u) + (2 & h ? -v : v);
|
|
1776
|
-
}
|
|
1777
|
-
|
|
1778
|
-
/**
|
|
1779
|
-
* Permutation table for Perlin noise
|
|
1780
|
-
*/ const p = (() => {
|
|
1781
|
-
const permutation = [];
|
|
1782
|
-
for (let i = 0; i < 256; i++) permutation[i] = Math.floor(256 * Math.random());
|
|
1783
|
-
// Duplicate for overflow handling
|
|
1784
|
-
return [ ...permutation, ...permutation ];
|
|
1785
|
-
})(), {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS;
|
|
1680
|
+
}, {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS;
|
|
1786
1681
|
|
|
1787
1682
|
const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
|
|
1788
1683
|
parentElement && backgroundDetectionCache.set(parentElement, {
|
|
@@ -1797,10 +1692,7 @@ const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new Weak
|
|
|
1797
1692
|
* Composable hook for AtomixGlass component logic
|
|
1798
1693
|
* Manages all state, calculations, and event handlers
|
|
1799
1694
|
*/
|
|
1800
|
-
function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef: wrapperRef, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, border: border, withBorder: withBorder = !0, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, onClick: onClick, debugBorderRadius: debugBorderRadius = !1, debugOverLight: debugOverLight = !1, children: children, blurAmount: blurAmount, saturation: saturation, withLiquidBlur: withLiquidBlur, isFixedOrSticky: isFixedOrSticky = !1, priority: priority = 1
|
|
1801
|
-
// Default priority
|
|
1802
|
-
// Phase 1: Animation System Props
|
|
1803
|
-
withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: animationSpeed = ATOMIX_GLASS.DEFAULTS.ANIMATION_SPEED, withMultiLayerDistortion: withMultiLayerDistortion = ATOMIX_GLASS.DEFAULTS.WITH_MULTI_LAYER_DISTORTION, distortionOctaves: distortionOctaves = ATOMIX_GLASS.DEFAULTS.DISTORTION_OCTAVES, distortionLacunarity: distortionLacunarity = ATOMIX_GLASS.DEFAULTS.DISTORTION_LACUNARITY, distortionGain: distortionGain = ATOMIX_GLASS.DEFAULTS.DISTORTION_GAIN, distortionQuality: distortionQuality = ATOMIX_GLASS.DEFAULTS.DISTORTION_QUALITY}) {
|
|
1695
|
+
function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef: wrapperRef, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, border: border, withBorder: withBorder = !0, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, onClick: onClick, debugBorderRadius: debugBorderRadius = !1, debugOverLight: debugOverLight = !1, children: children, blurAmount: blurAmount, saturation: saturation, withLiquidBlur: withLiquidBlur, isFixedOrSticky: isFixedOrSticky = !1, priority: priority = 1}) {
|
|
1804
1696
|
// State
|
|
1805
1697
|
const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), resolvedBorder = useMemo((() =>
|
|
1806
1698
|
/**
|
|
@@ -1852,52 +1744,10 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
1852
1744
|
}), scaleVelocityRef = useRef({
|
|
1853
1745
|
x: 0,
|
|
1854
1746
|
y: 0
|
|
1855
|
-
})
|
|
1856
|
-
useRef(0);
|
|
1857
|
-
const mouseVelocityRef = useRef({
|
|
1747
|
+
}), mouseVelocityRef = useRef({
|
|
1858
1748
|
x: 0,
|
|
1859
1749
|
y: 0
|
|
1860
|
-
}), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1),
|
|
1861
|
-
// If quality preset is provided, use it as base
|
|
1862
|
-
const preset = (quality = distortionQuality, ATOMIX_GLASS.CONSTANTS.DISTORTION_QUALITY_PRESETS[quality]);
|
|
1863
|
-
// Override with custom values if provided
|
|
1864
|
-
var quality;
|
|
1865
|
-
return {
|
|
1866
|
-
octaves: distortionOctaves ?? preset.octaves,
|
|
1867
|
-
lacunarity: distortionLacunarity ?? preset.lacunarity,
|
|
1868
|
-
gain: distortionGain ?? preset.gain
|
|
1869
|
-
};
|
|
1870
|
-
}), [ distortionQuality, distortionOctaves, distortionLacunarity, distortionGain ]), fbmEngine = useMemo((() => withMultiLayerDistortion ? createFBMEngine(fbmConfig) : null), [ withMultiLayerDistortion, fbmConfig ]), effectiveReducedMotion = useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveWithTimeAnimation = useMemo((() => withTimeAnimation && !effectiveReducedMotion), [ withTimeAnimation, effectiveReducedMotion ]);
|
|
1871
|
-
/**
|
|
1872
|
-
* Animation loop for time-based effects
|
|
1873
|
-
*/
|
|
1874
|
-
useEffect((() => {
|
|
1875
|
-
if (!effectiveWithTimeAnimation || "undefined" == typeof window) return;
|
|
1876
|
-
let lastFrameTime = performance.now();
|
|
1877
|
-
/**
|
|
1878
|
-
* Animation frame handler
|
|
1879
|
-
*/ const animate = currentTime => {
|
|
1880
|
-
// Calculate delta time
|
|
1881
|
-
const deltaTime = currentTime - lastFrameTime;
|
|
1882
|
-
lastFrameTime = currentTime;
|
|
1883
|
-
// Apply animation speed multiplier
|
|
1884
|
-
const scaledDelta = deltaTime * animationSpeed;
|
|
1885
|
-
elapsedTimeRef.current += scaledDelta, shaderTimeRef.current = elapsedTimeRef.current,
|
|
1886
|
-
// Continue animation loop
|
|
1887
|
-
animationFrameIdRef.current = requestAnimationFrame(animate);
|
|
1888
|
-
};
|
|
1889
|
-
// Start animation
|
|
1890
|
-
// Cleanup
|
|
1891
|
-
return animationStartTimeRef.current = performance.now(), animationFrameIdRef.current = requestAnimationFrame(animate),
|
|
1892
|
-
() => {
|
|
1893
|
-
null !== animationFrameIdRef.current && (cancelAnimationFrame(animationFrameIdRef.current),
|
|
1894
|
-
animationFrameIdRef.current = null);
|
|
1895
|
-
};
|
|
1896
|
-
}), [ effectiveWithTimeAnimation, animationSpeed ]);
|
|
1897
|
-
/**
|
|
1898
|
-
* Get current shader time for animations
|
|
1899
|
-
*/
|
|
1900
|
-
const getShaderTime = useCallback((() => shaderTimeRef.current), []), applyTimeBasedDistortion = useCallback((uv => effectiveWithTimeAnimation && fbmEngine ? liquidGlassWithTime(uv, shaderTimeRef.current, fbmConfig) : uv), [ effectiveWithTimeAnimation, fbmEngine, fbmConfig ]), effectiveBorderRadius = useMemo((() => void 0 !== borderRadius ? Math.max(0, borderRadius) : Math.max(0, dynamicBorderRadius)), [ borderRadius, dynamicBorderRadius ]), {glassSize: glassSize} = function({glassRef: glassRef, effectiveBorderRadius: effectiveBorderRadius, cachedRectRef: cachedRectRef}) {
|
|
1750
|
+
}), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1), effectiveReducedMotion = useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveBorderRadius = useMemo((() => void 0 !== borderRadius ? Math.max(0, borderRadius) : Math.max(0, dynamicBorderRadius)), [ borderRadius, dynamicBorderRadius ]), {glassSize: glassSize} = function({glassRef: glassRef, effectiveBorderRadius: effectiveBorderRadius, cachedRectRef: cachedRectRef}) {
|
|
1901
1751
|
const [glassSize, setGlassSize] = useState({
|
|
1902
1752
|
width: 270,
|
|
1903
1753
|
height: 69
|
|
@@ -1957,9 +1807,6 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
1957
1807
|
effectiveBorderRadius: effectiveBorderRadius,
|
|
1958
1808
|
cachedRectRef: cachedRectRef
|
|
1959
1809
|
}), effectiveHighContrast = useMemo((() => highContrast || userPrefersHighContrast), [ highContrast, userPrefersHighContrast ]), effectiveWithoutEffects = useMemo((() => withoutEffects || effectiveReducedMotion), [ withoutEffects, effectiveReducedMotion ]), globalMousePosition = externalGlobalMousePosition || internalGlobalMousePositionRef.current, mouseOffset = externalMouseOffset || internalMouseOffsetRef.current;
|
|
1960
|
-
/**
|
|
1961
|
-
* Apply time-based distortion to UV coordinates
|
|
1962
|
-
*/
|
|
1963
1810
|
// Extract border-radius from children
|
|
1964
1811
|
useEffect((() => {
|
|
1965
1812
|
const extractRadius = () => {
|
|
@@ -2119,7 +1966,7 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
2119
1966
|
* Get effective overLight value based on configuration
|
|
2120
1967
|
*/
|
|
2121
1968
|
const getEffectiveOverLight = useCallback((() => "boolean" == typeof overLight ? overLight : ("auto" === overLight || "object" == typeof overLight && null !== overLight) && detectedOverLight), [ overLight, detectedOverLight ]), validateConfigValue = useCallback(((value, min, max, defaultValue) => "number" != typeof value || isNaN(value) || !isFinite(value) ? defaultValue : Math.min(max, Math.max(min, value))), []), overLightConfig = useMemo((() => {
|
|
2122
|
-
const isOverLight = getEffectiveOverLight(), hoverIntensity
|
|
1969
|
+
const isOverLight = getEffectiveOverLight(), {hoverIntensity: hoverIntensity, activeIntensity: activeIntensity} = getInteractionIntensity(isHovered, isActive), baseConfig = {
|
|
2123
1970
|
isOverLight: isOverLight,
|
|
2124
1971
|
threshold: .7,
|
|
2125
1972
|
opacity: isOverLight ? Math.min(.6, Math.max(.2, .5 * hoverIntensity * activeIntensity)) : 0,
|
|
@@ -2163,8 +2010,8 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
2163
2010
|
};
|
|
2164
2011
|
const curG = internalGlobalMousePositionRef.current, tgtG = targetGlobalMousePositionRef.current;
|
|
2165
2012
|
internalGlobalMousePositionRef.current = {
|
|
2166
|
-
x: lerp
|
|
2167
|
-
y: lerp
|
|
2013
|
+
x: lerp(curG.x, tgtG.x, CONSTANTS.LERP_FACTOR),
|
|
2014
|
+
y: lerp(curG.y, tgtG.y, CONSTANTS.LERP_FACTOR)
|
|
2168
2015
|
};
|
|
2169
2016
|
// ── Calculate Elastic Physics ─────────────────────────────────────
|
|
2170
2017
|
let targetElasticTranslation = {
|
|
@@ -2331,8 +2178,6 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
2331
2178
|
overLightConfig: overLightConfig,
|
|
2332
2179
|
resolvedBorder: resolvedBorder,
|
|
2333
2180
|
transformStyle: transformStyle,
|
|
2334
|
-
getShaderTime: getShaderTime,
|
|
2335
|
-
applyTimeBasedDistortion: applyTimeBasedDistortion,
|
|
2336
2181
|
handleMouseEnter: handleMouseEnter,
|
|
2337
2182
|
handleMouseLeave: handleMouseLeave,
|
|
2338
2183
|
handleMouseDown: handleMouseDown,
|
|
@@ -2515,7 +2360,7 @@ const PERFORMANCE_PRESET = {
|
|
|
2515
2360
|
var explicit, position;
|
|
2516
2361
|
/**
|
|
2517
2362
|
* Extracts layout-related properties from a React `CSSProperties` object.
|
|
2518
|
-
*/ const {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveBorderRadius: effectiveBorderRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveWithoutEffects: effectiveWithoutEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle,
|
|
2363
|
+
*/ const {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, resolvedBorder: resolvedBorder} = useAtomixGlass({
|
|
2519
2364
|
glassRef: glassRef,
|
|
2520
2365
|
contentRef: contentRef,
|
|
2521
2366
|
wrapperRef: internalWrapperRef,
|
|
@@ -2539,14 +2384,7 @@ const PERFORMANCE_PRESET = {
|
|
|
2539
2384
|
withBorder: withBorder,
|
|
2540
2385
|
debugBorderRadius: debugBorderRadius,
|
|
2541
2386
|
style: style,
|
|
2542
|
-
isFixedOrSticky: isFixedOrSticky
|
|
2543
|
-
withTimeAnimation: withTimeAnimation,
|
|
2544
|
-
animationSpeed: animationSpeed,
|
|
2545
|
-
withMultiLayerDistortion: withMultiLayerDistortion,
|
|
2546
|
-
distortionOctaves: distortionOctaves,
|
|
2547
|
-
distortionLacunarity: distortionLacunarity,
|
|
2548
|
-
distortionGain: distortionGain,
|
|
2549
|
-
distortionQuality: distortionQuality
|
|
2387
|
+
isFixedOrSticky: isFixedOrSticky
|
|
2550
2388
|
});
|
|
2551
2389
|
(
|
|
2552
2390
|
/**
|
|
@@ -3124,7 +2962,6 @@ const PERFORMANCE_PRESET = {
|
|
|
3124
2962
|
shaderVariant: shaderVariant,
|
|
3125
2963
|
withLiquidBlur: withLiquidBlur,
|
|
3126
2964
|
isFixedOrSticky: isFixedOrSticky,
|
|
3127
|
-
shaderTime: getShaderTime(),
|
|
3128
2965
|
withTimeAnimation: withTimeAnimation,
|
|
3129
2966
|
animationSpeed: animationSpeed,
|
|
3130
2967
|
withMultiLayerDistortion: withMultiLayerDistortion,
|
|
@@ -4503,40 +4340,15 @@ ListGroup.displayName = "ListGroup";
|
|
|
4503
4340
|
|
|
4504
4341
|
// Adapted from https://github.com/shuding/liquid-glass
|
|
4505
4342
|
// Constants
|
|
4506
|
-
const
|
|
4507
|
-
// Add input validation
|
|
4508
|
-
if ("number" != typeof a || "number" != typeof b || "number" != typeof t) return 0;
|
|
4509
|
-
const clamped = Math.max(0, Math.min(1, (t - a) / (b - a)));
|
|
4510
|
-
return clamped * clamped * (3 - 2 * clamped);
|
|
4511
|
-
}, calculateLength = (x, y) => {
|
|
4512
|
-
// Add input validation and error handling
|
|
4513
|
-
if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y)) return 0;
|
|
4514
|
-
// Prevent potential overflow
|
|
4515
|
-
const maxX = Math.max(Math.abs(x), Math.abs(y));
|
|
4516
|
-
if (0 === maxX) return 0;
|
|
4517
|
-
const scaledX = x / maxX, scaledY = y / maxX;
|
|
4518
|
-
return maxX * Math.sqrt(scaledX * scaledX + scaledY * scaledY);
|
|
4519
|
-
}, roundedRectSDF = (x, y, width, height, radius) => {
|
|
4343
|
+
const roundedRectSDF = (x, y, width, height, radius) => {
|
|
4520
4344
|
// Add input validation
|
|
4521
4345
|
if ("number" != typeof x || "number" != typeof y || "number" != typeof width || "number" != typeof height || "number" != typeof radius) return 0;
|
|
4522
4346
|
const qx = Math.abs(x) - width + radius, qy = Math.abs(y) - height + radius;
|
|
4523
|
-
return Math.min(Math.max(qx, qy), 0) +
|
|
4347
|
+
return Math.min(Math.max(qx, qy), 0) + vec2Length(Math.max(qx, 0), Math.max(qy, 0)) - radius;
|
|
4524
4348
|
}, createTexture = (x, y) => ({
|
|
4525
4349
|
x: "number" != typeof x || isNaN(x) ? .5 : Math.max(0, Math.min(1, x)),
|
|
4526
4350
|
y: "number" != typeof y || isNaN(y) ? .5 : Math.max(0, Math.min(1, y))
|
|
4527
|
-
}), validateVec2 = vec => vec && "number" == typeof vec.x && "number" == typeof vec.y && !isNaN(vec.x) && !isNaN(vec.y),
|
|
4528
|
-
// Add input validation
|
|
4529
|
-
"number" != typeof value || "number" != typeof min || "number" != typeof max || isNaN(value) ? min : isNaN(min) ? 0 : isNaN(max) ? 1 : Math.max(min, Math.min(max, value)), easeInOutCubic = t => {
|
|
4530
|
-
// Add input validation
|
|
4531
|
-
if ("number" != typeof t || isNaN(t)) return 0;
|
|
4532
|
-
const clampedT = Math.max(0, Math.min(1, t));
|
|
4533
|
-
return clampedT < .5 ? 4 * clampedT * clampedT * clampedT : 1 - Math.pow(-2 * clampedT + 2, 3) / 2;
|
|
4534
|
-
}, easeOutQuart = t => {
|
|
4535
|
-
// Add input validation
|
|
4536
|
-
if ("number" != typeof t || isNaN(t)) return 0;
|
|
4537
|
-
const clampedT = Math.max(0, Math.min(1, t));
|
|
4538
|
-
return 1 - Math.pow(1 - clampedT, 4);
|
|
4539
|
-
}, noise2D = (x, y) => {
|
|
4351
|
+
}), validateVec2 = vec => vec && "number" == typeof vec.x && "number" == typeof vec.y && !isNaN(vec.x) && !isNaN(vec.y), noise2D = (x, y) => {
|
|
4540
4352
|
// Add input validation
|
|
4541
4353
|
if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y)) return 0;
|
|
4542
4354
|
const X = 255 & Math.floor(x), Y = 255 & Math.floor(y), xf = x - Math.floor(x), yf = y - Math.floor(y), u = easeInOutCubic(xf), v = easeInOutCubic(yf), hash = (i, j) => {
|
|
@@ -4575,13 +4387,13 @@ const smoothStep = (a, b, t) => {
|
|
|
4575
4387
|
x: .5,
|
|
4576
4388
|
y: .5
|
|
4577
4389
|
};
|
|
4578
|
-
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now(), mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance =
|
|
4390
|
+
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now(), mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = vec2Length(mouseX, mouseY), mouseFalloff = easeOutQuart(1 - Math.min(2 * mouseDistance, 1)), organicFlow = fbm(12 * (ix + .5 * mouseX) + time, 12 * (iy + .5 * mouseY) + .7 * time, 3) - .5, distanceToEdge = roundedRectSDF(ix, iy, .4, .3, .35), baseDisplacement = smoothstepEdge(.8, 0, distanceToEdge - .05), radialDist = ((x, y, strength) => {
|
|
4579
4391
|
// Add input validation
|
|
4580
4392
|
if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y) || isNaN(strength)) return {
|
|
4581
4393
|
x: 0,
|
|
4582
4394
|
y: 0
|
|
4583
4395
|
};
|
|
4584
|
-
const distance =
|
|
4396
|
+
const distance = vec2Length(x, y), distortion = Math.pow(Math.min(distance, 10), 2) * strength;
|
|
4585
4397
|
// Limit distance to prevent extreme values
|
|
4586
4398
|
return {
|
|
4587
4399
|
x: x * (1 + distortion),
|
|
@@ -4593,7 +4405,7 @@ const smoothStep = (a, b, t) => {
|
|
|
4593
4405
|
x: 0,
|
|
4594
4406
|
y: 0
|
|
4595
4407
|
};
|
|
4596
|
-
const distance =
|
|
4408
|
+
const distance = vec2Length(x, y);
|
|
4597
4409
|
// Prevent division by zero and extreme values
|
|
4598
4410
|
if (0 === distance) return {
|
|
4599
4411
|
x: 0,
|
|
@@ -4604,8 +4416,8 @@ const smoothStep = (a, b, t) => {
|
|
|
4604
4416
|
x: Math.cos(angle) * distance * intensity,
|
|
4605
4417
|
y: Math.sin(angle) * distance * intensity
|
|
4606
4418
|
};
|
|
4607
|
-
})(ix, iy, .015 * baseDisplacement), scaled =
|
|
4608
|
-
return createTexture(
|
|
4419
|
+
})(ix, iy, .015 * baseDisplacement), scaled = smoothstepEdge(0, 1, 1.15 * baseDisplacement), finalX = ix + totalDistortionX + .5 * chromaticOffset.x, finalY = iy + totalDistortionY + .5 * chromaticOffset.y;
|
|
4420
|
+
return createTexture(clamp(finalX * scaled + .5, 0, 1), clamp(finalY * scaled + .5, 0, 1));
|
|
4609
4421
|
},
|
|
4610
4422
|
// Premium Apple-style fluid glass with enhanced organic flow
|
|
4611
4423
|
appleFluid: (uv, mousePosition) => {
|
|
@@ -4613,8 +4425,8 @@ const smoothStep = (a, b, t) => {
|
|
|
4613
4425
|
x: .5,
|
|
4614
4426
|
y: .5
|
|
4615
4427
|
};
|
|
4616
|
-
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .6, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance =
|
|
4617
|
-
return createTexture(
|
|
4428
|
+
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .6, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = vec2Length(mouseX, mouseY), mouseFalloff = easeOutQuart(1 - Math.min(1.5 * mouseDistance, 1)), organicX = fbm(10 * (ix + .3 * mouseX) + time, 10 * (iy + .3 * mouseY), 5) - .5, organicY = fbm(10 * (ix - .3 * mouseX), 10 * (iy - .3 * mouseY) + .8 * time, 5) - .5, distanceToEdge = roundedRectSDF(ix, iy, .42, .32, .38), mask = smoothstepEdge(.85, -.1, distanceToEdge), fluidVelocityX = Math.sin(6 * ix + 2 * time) * Math.cos(4 * iy - time) * .025, fluidVelocityY = Math.cos(4 * ix - time) * Math.sin(6 * iy + 2 * time) * .025, vortexAngle = Math.atan2(iy - mouseY, ix - mouseX), vortexStrength = mouseFalloff * mouseDistance * .08, vortexX = Math.cos(vortexAngle + time) * vortexStrength, totalY = iy + (.035 * organicY + fluidVelocityY + Math.sin(vortexAngle + time) * vortexStrength) * mask;
|
|
4429
|
+
return createTexture(clamp(ix + (.035 * organicX + fluidVelocityX + vortexX) * mask + .5, 0, 1), clamp(totalY + .5, 0, 1));
|
|
4618
4430
|
},
|
|
4619
4431
|
// High-end glass with advanced refraction and depth
|
|
4620
4432
|
premiumGlass: (uv, mousePosition) => {
|
|
@@ -4622,7 +4434,7 @@ const smoothStep = (a, b, t) => {
|
|
|
4622
4434
|
x: .5,
|
|
4623
4435
|
y: .5
|
|
4624
4436
|
};
|
|
4625
|
-
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .4, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance =
|
|
4437
|
+
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .4, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = vec2Length(mouseX, mouseY), centerDistance = vec2Length(ix, iy), refractionStrength = .3 * Math.pow(Math.min(centerDistance, 1), 1.5), refractionAngle = Math.atan2(iy, ix);
|
|
4626
4438
|
// Multi-layer depth effect
|
|
4627
4439
|
let depthX = 0, depthY = 0;
|
|
4628
4440
|
for (let layer = 0; layer < 3; layer++) {
|
|
@@ -4630,8 +4442,8 @@ const smoothStep = (a, b, t) => {
|
|
|
4630
4442
|
depthX += Math.sin(ix * layerScale + layerTime) * layerStrength, depthY += Math.cos(iy * layerScale - layerTime) * layerStrength;
|
|
4631
4443
|
}
|
|
4632
4444
|
// Glass refraction with mouse influence
|
|
4633
|
-
const refractionX = Math.cos(refractionAngle) * refractionStrength * (1 + .5 * mouseDistance), refractionY = Math.sin(refractionAngle) * refractionStrength * (1 + .5 * mouseDistance), organicNoise = fbm(8 * ix + time, 8 * iy - time, 2) - .5, distanceToEdge = roundedRectSDF(ix, iy, .43, .33, .36), edgeMask =
|
|
4634
|
-
return createTexture(
|
|
4445
|
+
const refractionX = Math.cos(refractionAngle) * refractionStrength * (1 + .5 * mouseDistance), refractionY = Math.sin(refractionAngle) * refractionStrength * (1 + .5 * mouseDistance), organicNoise = fbm(8 * ix + time, 8 * iy - time, 2) - .5, distanceToEdge = roundedRectSDF(ix, iy, .43, .33, .36), edgeMask = smoothstepEdge(.9, -.05, distanceToEdge), finalY = iy + (refractionY + depthY + .015 * organicNoise) * edgeMask;
|
|
4446
|
+
return createTexture(clamp(ix + (refractionX + depthX + .015 * organicNoise) * edgeMask + .5, 0, 1), clamp(finalY + .5, 0, 1));
|
|
4635
4447
|
},
|
|
4636
4448
|
// Metallic liquid effect with shimmer
|
|
4637
4449
|
liquidMetal: (uv, mousePosition) => {
|
|
@@ -4639,8 +4451,8 @@ const smoothStep = (a, b, t) => {
|
|
|
4639
4451
|
x: .5,
|
|
4640
4452
|
y: .5
|
|
4641
4453
|
};
|
|
4642
|
-
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * 1.2, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, wave1 = Math.sin(20 * ix + 4 * time) * Math.cos(15 * iy - 3 * time) * .02, wave2 = Math.cos(15 * ix - 2 * time) * Math.sin(20 * iy + 5 * time) * .015, shimmer = .025 * fbm(25 * ix + 2 * time, 25 * iy - 2 * time, 4), flowAngle = Math.atan2(iy - mouseY, ix - mouseX), flowDistance =
|
|
4643
|
-
return createTexture(
|
|
4454
|
+
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * 1.2, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, wave1 = Math.sin(20 * ix + 4 * time) * Math.cos(15 * iy - 3 * time) * .02, wave2 = Math.cos(15 * ix - 2 * time) * Math.sin(20 * iy + 5 * time) * .015, shimmer = .025 * fbm(25 * ix + 2 * time, 25 * iy - 2 * time, 4), flowAngle = Math.atan2(iy - mouseY, ix - mouseX), flowDistance = vec2Length(ix - mouseX, iy - mouseY), flowEffect = .02 * Math.sin(15 * flowDistance - 6 * time) * easeOutQuart(1 - Math.min(2 * flowDistance, 1)), distanceToEdge = roundedRectSDF(ix, iy, .41, .31, .37), mask = smoothstepEdge(.88, -.08, distanceToEdge), totalX = ix + (wave1 + shimmer + Math.cos(flowAngle) * flowEffect) * mask, totalY = iy + (wave2 + .8 * shimmer + Math.sin(flowAngle) * flowEffect) * mask;
|
|
4455
|
+
return createTexture(clamp(totalX + .5, 0, 1), clamp(totalY + .5, 0, 1));
|
|
4644
4456
|
},
|
|
4645
4457
|
// basiBasi - Expert Premium Glass Shader
|
|
4646
4458
|
// The most advanced shader with caustics, spectral dispersion, parallax depth, and volumetric effects
|
|
@@ -4649,7 +4461,7 @@ const smoothStep = (a, b, t) => {
|
|
|
4649
4461
|
x: .5,
|
|
4650
4462
|
y: .5
|
|
4651
4463
|
};
|
|
4652
|
-
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .5, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance =
|
|
4464
|
+
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .5, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = vec2Length(mouseX, mouseY), mouseFalloff = easeOutQuart(1 - Math.min(1.2 * mouseDistance, 1)), causticIntensity = ((x, y, time, intensity = 1) =>
|
|
4653
4465
|
// Add input validation
|
|
4654
4466
|
"number" != typeof x || "number" != typeof y || "number" != typeof time || "number" != typeof intensity || isNaN(x) || isNaN(y) || isNaN(time) || isNaN(intensity) ? .5 : .5 * (Math.sin(8 * x + 2 * time) * Math.cos(8 * y - 2 * time) * .5 + Math.sin(8 * (x + .5) * 1.3 - 2 * time * .8) * Math.cos(8 * (y - .3) * 1.3 + 2 * time * .8) * .3 + Math.sin(8 * (x - .3) * .7 + 2 * time * 1.2) * Math.cos(8 * (y + .4) * .7 - 2 * time * 1.2) * .2 + 1) * intensity)(ix, iy, time, .8), causticDistortion = .02 * (causticIntensity - .5), refractionAngle = Math.atan2(iy, ix), spectralDispersion = ((x, y, angle) => {
|
|
4655
4467
|
// Add input validation
|
|
@@ -4667,7 +4479,7 @@ const smoothStep = (a, b, t) => {
|
|
|
4667
4479
|
y: 0
|
|
4668
4480
|
}
|
|
4669
4481
|
};
|
|
4670
|
-
const distance =
|
|
4482
|
+
const distance = vec2Length(x, y), dispersionStrength = Math.min(.025 * distance, 1), redOffset = .8 * dispersionStrength, greenOffset = 1 * dispersionStrength, blueOffset = 1.2 * dispersionStrength;
|
|
4671
4483
|
return {
|
|
4672
4484
|
r: {
|
|
4673
4485
|
x: Math.cos(angle) * redOffset,
|
|
@@ -4707,8 +4519,8 @@ const smoothStep = (a, b, t) => {
|
|
|
4707
4519
|
return turbulence;
|
|
4708
4520
|
})(6 * ix, 6 * iy, time, 6), turbulenceX = .012 * Math.cos(turbulence * Math.PI * 2), turbulenceY = .012 * Math.sin(turbulence * Math.PI * 2), microSurface = ((x, y, time) =>
|
|
4709
4521
|
// Add input validation
|
|
4710
|
-
"number" != typeof x || "number" != typeof y || "number" != typeof time || isNaN(x) || isNaN(y) || isNaN(time) ? .5 : .5 * (.7 * fbm(40 * x + .3 * time, 40 * y - .3 * time, 6) + .3 * fbm(80 * x, 80 * y, 4)))(ix, iy, time), microDetailX = .008 * (microSurface - .5), microDetailY = .008 * (microSurface - .5), centerDistance =
|
|
4711
|
-
return createTexture(
|
|
4522
|
+
"number" != typeof x || "number" != typeof y || "number" != typeof time || isNaN(x) || isNaN(y) || isNaN(time) ? .5 : .5 * (.7 * fbm(40 * x + .3 * time, 40 * y - .3 * time, 6) + .3 * fbm(80 * x, 80 * y, 4)))(ix, iy, time), microDetailX = .008 * (microSurface - .5), microDetailY = .008 * (microSurface - .5), centerDistance = vec2Length(ix, iy), dynamicRefraction = .35 * Math.pow(Math.min(centerDistance, 1), 1.8) * (1 + mouseFalloff * mouseDistance * .8), refractionX = Math.cos(refractionAngle) * dynamicRefraction, refractionY = Math.sin(refractionAngle) * dynamicRefraction, vortexAngle = Math.atan2(iy - mouseY, ix - mouseX), vortexDistance = vec2Length(ix - mouseX, iy - mouseY), vortexStrength = mouseFalloff * Math.sin(10 * vortexDistance - 3 * time) * .025, vortexX = Math.cos(vortexAngle + 2 * time) * vortexStrength, vortexY = Math.sin(vortexAngle + 2 * time) * vortexStrength, fluidX = Math.sin(10 * ix + 5 * mouseX + 2.5 * time) * Math.cos(8 * iy - 2 * time) * .018, fluidY = Math.cos(8 * ix - 2 * time) * Math.sin(10 * iy + 5 * mouseY + 2.5 * time) * .018, rippleEffect = (.012 * Math.sin(15 * Math.min(centerDistance, 10) - 4 * time) + .008 * Math.cos(20 * Math.min(centerDistance, 10) + 3 * time)) * mouseFalloff, rippleX = Math.cos(refractionAngle) * rippleEffect, rippleY = Math.sin(refractionAngle) * rippleEffect, distanceToEdge = roundedRectSDF(ix, iy, .44, .34, .39), edgeMask = smoothstepEdge(.92, -.12, distanceToEdge), edgeSoftness = smoothstepEdge(.85, .1, distanceToEdge), finalY = iy + (1.2 * refractionY + .8 * spectralY + 1.5 * parallaxY + .9 * scatteringY + 1 * turbulenceY + .6 * microDetailY + 1.3 * vortexY + 1.1 * fluidY + .7 * rippleY + .8 * causticDistortion) * edgeMask * edgeSoftness * .85;
|
|
4523
|
+
return createTexture(clamp(ix + (1.2 * refractionX + .8 * spectralX + 1.5 * parallaxX + .9 * scatteringX + 1 * turbulenceX + .6 * microDetailX + 1.3 * vortexX + 1.1 * fluidX + .7 * rippleX + causticDistortion) * edgeMask * edgeSoftness * .85 + .5, 0, 1), clamp(finalY + .5, 0, 1));
|
|
4712
4524
|
},
|
|
4713
4525
|
// Aliases for compatibility
|
|
4714
4526
|
plasma: (uv, mousePosition) => fragmentShaders.premiumGlass(uv, mousePosition),
|
|
@@ -4750,8 +4562,8 @@ const smoothStep = (a, b, t) => {
|
|
|
4750
4562
|
let dx = pos.x * w - x, dy = pos.y * h - y;
|
|
4751
4563
|
// Apply edge smoothing for Apple-like effect
|
|
4752
4564
|
const edgeX = 2 * Math.min(x / w, (w - x) / w), edgeY = 2 * Math.min(y / h, (h - y) / h), edgeFactor = Math.min(edgeX, edgeY);
|
|
4753
|
-
dx *=
|
|
4754
|
-
rawValues.push(dx, dy);
|
|
4565
|
+
dx *= smoothstepEdge(0, .2, edgeFactor), dy *= smoothstepEdge(0, .2, edgeFactor),
|
|
4566
|
+
maxScale = Math.max(maxScale, Math.abs(dx), Math.abs(dy)), rawValues.push(dx, dy);
|
|
4755
4567
|
}
|
|
4756
4568
|
// Improved normalization to prevent artifacts while maintaining intensity
|
|
4757
4569
|
maxScale = Math.max(maxScale, 1);
|
|
@@ -4761,9 +4573,9 @@ const smoothStep = (a, b, t) => {
|
|
|
4761
4573
|
let rawIndex = 0;
|
|
4762
4574
|
for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) {
|
|
4763
4575
|
const dx = rawValues[rawIndex++] || 0, dy = rawValues[rawIndex++] || 0, edgeDistance = Math.min(x, y, w - x - 1, h - y - 1), edgeFactor = Math.min(1, edgeDistance / 2), r = dx * edgeFactor / maxScale + .5, g = dy * edgeFactor / maxScale + .5, pixelIndex = 4 * (y * w + x);
|
|
4764
|
-
data[pixelIndex] =
|
|
4765
|
-
data[pixelIndex + 1] =
|
|
4766
|
-
data[pixelIndex + 2] =
|
|
4576
|
+
data[pixelIndex] = clamp(255 * r, 0, 255), // Red channel (X displacement)
|
|
4577
|
+
data[pixelIndex + 1] = clamp(255 * g, 0, 255), // Green channel (Y displacement)
|
|
4578
|
+
data[pixelIndex + 2] = clamp(255 * g, 0, 255), // Blue channel (Y displacement for SVG filter compatibility)
|
|
4767
4579
|
data[pixelIndex + 3] = 255;
|
|
4768
4580
|
}
|
|
4769
4581
|
return this.context.putImageData(imageData, 0, 0), this.canvas.toDataURL();
|
|
@@ -4791,9 +4603,7 @@ const smoothStep = (a, b, t) => {
|
|
|
4791
4603
|
return this.canvasDPI;
|
|
4792
4604
|
}
|
|
4793
4605
|
},
|
|
4794
|
-
|
|
4795
|
-
fragmentShaders: fragmentShaders,
|
|
4796
|
-
liquidGlassWithTime: liquidGlassWithTime
|
|
4606
|
+
fragmentShaders: fragmentShaders
|
|
4797
4607
|
}, Symbol.toStringTag, {
|
|
4798
4608
|
value: "Module"
|
|
4799
4609
|
}));
|