lightswind
Version:
A collection of beautifully crafted React Components, Blocks & Templates for Modern Developers. Create stunning web applications effortlessly by using our 160+ professional and animated react components.
620 lines (597 loc) • 30.4 kB
JavaScript
"use strict";
"use client";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = LiquidSurface;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const THREE = __importStar(require("three"));
const gsap_1 = __importDefault(require("gsap"));
const utils_1 = require("@/components/lib/utils");
// --- Utils ---
function hexToRgb(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result
? {
r: parseInt(result[1], 16) / 255,
g: parseInt(result[2], 16) / 255,
b: parseInt(result[3], 16) / 255,
}
: null;
}
function rgbToHex(r, g, b) {
const toHex = (n) => {
const hex = Math.round(n * 255).toString(16);
return hex.length === 1 ? "0" + hex : hex;
};
return "#" + toHex(r) + toHex(g) + toHex(b);
}
// --- Classes ---
class TouchTexture {
constructor() {
this.size = 64;
this.width = this.height = this.size;
this.maxAge = 64;
this.radius = 0.25 * this.size;
this.speed = 1 / this.maxAge;
this.trail = [];
this.last = null;
this.initTexture();
}
initTexture() {
this.canvas = document.createElement("canvas");
this.canvas.width = this.width;
this.canvas.height = this.height;
this.ctx = this.canvas.getContext("2d");
this.ctx.fillStyle = "black";
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
this.texture = new THREE.CanvasTexture(this.canvas);
}
update() {
this.clear();
let speed = this.speed;
for (let i = this.trail.length - 1; i >= 0; i--) {
const point = this.trail[i];
let f = point.force * speed * (1 - point.age / this.maxAge);
point.x += point.vx * f;
point.y += point.vy * f;
point.age++;
if (point.age > this.maxAge) {
this.trail.splice(i, 1);
}
else {
this.drawPoint(point);
}
}
this.texture.needsUpdate = true;
}
clear() {
this.ctx.fillStyle = "black";
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
}
addTouch(point) {
let force = 0;
let vx = 0;
let vy = 0;
const last = this.last;
if (last) {
const dx = point.x - last.x;
const dy = point.y - last.y;
if (dx === 0 && dy === 0)
return;
const dd = dx * dx + dy * dy;
let d = Math.sqrt(dd);
vx = dx / d;
vy = dy / d;
force = Math.min(dd * 20000, 2.0);
}
this.last = { x: point.x, y: point.y };
this.trail.push({ x: point.x, y: point.y, age: 0, force, vx, vy });
}
drawPoint(point) {
const pos = {
x: point.x * this.width,
y: (1 - point.y) * this.height,
};
let intensity = 1;
if (point.age < this.maxAge * 0.3) {
intensity = Math.sin((point.age / (this.maxAge * 0.3)) * (Math.PI / 2));
}
else {
const t = 1 - (point.age - this.maxAge * 0.3) / (this.maxAge * 0.7);
intensity = -t * (t - 2);
}
intensity *= point.force;
const radius = this.radius;
let color = `${((point.vx + 1) / 2) * 255}, ${((point.vy + 1) / 2) * 255}, ${intensity * 255}`;
let offset = this.size * 5;
this.ctx.shadowOffsetX = offset;
this.ctx.shadowOffsetY = offset;
this.ctx.shadowBlur = radius * 1;
this.ctx.shadowColor = `rgba(${color},${0.2 * intensity})`;
this.ctx.beginPath();
this.ctx.fillStyle = "rgba(255,0,0,1)";
this.ctx.arc(pos.x - offset, pos.y - offset, radius, 0, Math.PI * 2);
this.ctx.fill();
}
}
class GradientBackground {
constructor(sceneManager, props) {
this.sceneManager = sceneManager;
this.mesh = null;
this.uniforms = {
uTime: { value: 0 },
uResolution: { value: new THREE.Vector2(100, 100) },
uColor1: { value: new THREE.Vector3(0.945, 0.353, 0.133) },
uColor2: { value: new THREE.Vector3(0.039, 0.055, 0.153) },
uColor3: { value: new THREE.Vector3(0.945, 0.353, 0.133) },
uColor4: { value: new THREE.Vector3(0.039, 0.055, 0.153) },
uColor5: { value: new THREE.Vector3(0.945, 0.353, 0.133) },
uColor6: { value: new THREE.Vector3(0.039, 0.055, 0.153) },
uSpeed: { value: props.speed || 1.2 },
uIntensity: { value: props.intensity || 1.8 },
uTouchTexture: { value: null },
uGrainIntensity: { value: props.grainIntensity || 0.08 },
uZoom: { value: props.zoom || 1.0 },
uDarkNavy: { value: new THREE.Vector3(0.039, 0.055, 0.153) },
uGradientSize: { value: props.gradientSize || 1.0 },
uGradientCount: { value: props.gradientCount || 6.0 },
uColor1Weight: { value: props.color1Weight || 1.0 },
uColor2Weight: { value: props.color2Weight || 1.0 },
};
}
init() {
const viewSize = this.sceneManager.getViewSize();
const geometry = new THREE.PlaneGeometry(viewSize.width, viewSize.height, 1, 1);
const material = new THREE.ShaderMaterial({
uniforms: this.uniforms,
vertexShader: `
varying vec2 vUv;
void main() {
vec3 pos = position.xyz;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.);
vUv = uv;
}
`,
fragmentShader: `
uniform float uTime;
uniform vec2 uResolution;
uniform vec3 uColor1; uniform vec3 uColor2; uniform vec3 uColor3;
uniform vec3 uColor4; uniform vec3 uColor5; uniform vec3 uColor6;
uniform float uSpeed; uniform float uIntensity; uniform sampler2D uTouchTexture;
uniform float uGrainIntensity; uniform float uZoom; uniform vec3 uDarkNavy;
uniform float uGradientSize; uniform float uGradientCount;
uniform float uColor1Weight; uniform float uColor2Weight;
varying vec2 vUv;
#define PI 3.14159265359
float grain(vec2 uv, float time) {
vec2 grainUv = uv * uResolution * 0.5;
float grainValue = fract(sin(dot(grainUv + time, vec2(12.9898, 78.233))) * 43758.5453);
return grainValue * 2.0 - 1.0;
}
vec3 getGradientColor(vec2 uv, float time) {
float gradientRadius = uGradientSize;
vec2 center1 = vec2(0.5 + sin(time * uSpeed * 0.4) * 0.4, 0.5 + cos(time * uSpeed * 0.5) * 0.4);
vec2 center2 = vec2(0.5 + cos(time * uSpeed * 0.6) * 0.5, 0.5 + sin(time * uSpeed * 0.45) * 0.5);
vec2 center3 = vec2(0.5 + sin(time * uSpeed * 0.35) * 0.45, 0.5 + cos(time * uSpeed * 0.55) * 0.45);
vec2 center4 = vec2(0.5 + cos(time * uSpeed * 0.5) * 0.4, 0.5 + sin(time * uSpeed * 0.4) * 0.4);
vec2 center5 = vec2(0.5 + sin(time * uSpeed * 0.7) * 0.35, 0.5 + cos(time * uSpeed * 0.6) * 0.35);
vec2 center6 = vec2(0.5 + cos(time * uSpeed * 0.45) * 0.5, 0.5 + sin(time * uSpeed * 0.65) * 0.5);
vec2 center7 = vec2(0.5 + sin(time * uSpeed * 0.55) * 0.38, 0.5 + cos(time * uSpeed * 0.48) * 0.42);
vec2 center8 = vec2(0.5 + cos(time * uSpeed * 0.65) * 0.36, 0.5 + sin(time * uSpeed * 0.52) * 0.44);
vec2 center9 = vec2(0.5 + sin(time * uSpeed * 0.42) * 0.41, 0.5 + cos(time * uSpeed * 0.58) * 0.39);
vec2 center10 = vec2(0.5 + cos(time * uSpeed * 0.48) * 0.37, 0.5 + sin(time * uSpeed * 0.62) * 0.43);
vec2 center11 = vec2(0.5 + sin(time * uSpeed * 0.68) * 0.33, 0.5 + cos(time * uSpeed * 0.44) * 0.46);
vec2 center12 = vec2(0.5 + cos(time * uSpeed * 0.38) * 0.39, 0.5 + sin(time * uSpeed * 0.56) * 0.41);
float dist1 = length(uv - center1); float dist2 = length(uv - center2);
float dist3 = length(uv - center3); float dist4 = length(uv - center4);
float dist5 = length(uv - center5); float dist6 = length(uv - center6);
float dist7 = length(uv - center7); float dist8 = length(uv - center8);
float dist9 = length(uv - center9); float dist10 = length(uv - center10);
float dist11 = length(uv - center11); float dist12 = length(uv - center12);
float influence1 = 1.0 - smoothstep(0.0, gradientRadius, dist1);
float influence2 = 1.0 - smoothstep(0.0, gradientRadius, dist2);
float influence3 = 1.0 - smoothstep(0.0, gradientRadius, dist3);
float influence4 = 1.0 - smoothstep(0.0, gradientRadius, dist4);
float influence5 = 1.0 - smoothstep(0.0, gradientRadius, dist5);
float influence6 = 1.0 - smoothstep(0.0, gradientRadius, dist6);
float influence7 = 1.0 - smoothstep(0.0, gradientRadius, dist7);
float influence8 = 1.0 - smoothstep(0.0, gradientRadius, dist8);
float influence9 = 1.0 - smoothstep(0.0, gradientRadius, dist9);
float influence10 = 1.0 - smoothstep(0.0, gradientRadius, dist10);
float influence11 = 1.0 - smoothstep(0.0, gradientRadius, dist11);
float influence12 = 1.0 - smoothstep(0.0, gradientRadius, dist12);
vec2 rotatedUv1 = uv - 0.5;
float angle1 = time * uSpeed * 0.15;
rotatedUv1 = vec2(rotatedUv1.x * cos(angle1) - rotatedUv1.y * sin(angle1), rotatedUv1.x * sin(angle1) + rotatedUv1.y * cos(angle1)) + 0.5;
vec2 rotatedUv2 = uv - 0.5;
float angle2 = -time * uSpeed * 0.12;
rotatedUv2 = vec2(rotatedUv2.x * cos(angle2) - rotatedUv2.y * sin(angle2), rotatedUv2.x * sin(angle2) + rotatedUv2.y * cos(angle2)) + 0.5;
float radialGradient1 = length(rotatedUv1 - 0.5);
float radialGradient2 = length(rotatedUv2 - 0.5);
float radialInfluence1 = 1.0 - smoothstep(0.0, 0.8, radialGradient1);
float radialInfluence2 = 1.0 - smoothstep(0.0, 0.8, radialGradient2);
vec3 color = vec3(0.0);
color += uColor1 * influence1 * (0.55 + 0.45 * sin(time * uSpeed)) * uColor1Weight;
color += uColor2 * influence2 * (0.55 + 0.45 * cos(time * uSpeed * 1.2)) * uColor2Weight;
color += uColor3 * influence3 * (0.55 + 0.45 * sin(time * uSpeed * 0.8)) * uColor1Weight;
color += uColor4 * influence4 * (0.55 + 0.45 * cos(time * uSpeed * 1.3)) * uColor2Weight;
color += uColor5 * influence5 * (0.55 + 0.45 * sin(time * uSpeed * 1.1)) * uColor1Weight;
color += uColor6 * influence6 * (0.55 + 0.45 * cos(time * uSpeed * 0.9)) * uColor2Weight;
if (uGradientCount > 6.0) {
color += uColor1 * influence7 * (0.55 + 0.45 * sin(time * uSpeed * 1.4)) * uColor1Weight;
color += uColor2 * influence8 * (0.55 + 0.45 * cos(time * uSpeed * 1.5)) * uColor2Weight;
color += uColor3 * influence9 * (0.55 + 0.45 * sin(time * uSpeed * 1.6)) * uColor1Weight;
color += uColor4 * influence10 * (0.55 + 0.45 * cos(time * uSpeed * 1.7)) * uColor2Weight;
}
if (uGradientCount > 10.0) {
color += uColor5 * influence11 * (0.55 + 0.45 * sin(time * uSpeed * 1.8)) * uColor1Weight;
color += uColor6 * influence12 * (0.55 + 0.45 * cos(time * uSpeed * 1.9)) * uColor2Weight;
}
color += mix(uColor1, uColor3, radialInfluence1) * 0.45 * uColor1Weight;
color += mix(uColor2, uColor4, radialInfluence2) * 0.4 * uColor2Weight;
color = clamp(color, vec3(0.0), vec3(1.0)) * uIntensity;
float luminance = dot(color, vec3(0.299, 0.587, 0.114));
color = mix(vec3(luminance), color, 1.35);
color = pow(color, vec3(0.92));
float brightness1 = length(color);
float mixFactor1 = max(brightness1 * 1.2, 0.15);
color = mix(uDarkNavy, color, mixFactor1);
float brightness = length(color);
if (brightness > 1.0) color = color * (1.0 / brightness);
return color;
}
void main() {
vec2 uv = vUv;
vec4 touchTex = texture2D(uTouchTexture, uv);
float vx = -(touchTex.r * 2.0 - 1.0);
float vy = -(touchTex.g * 2.0 - 1.0);
float intensity = touchTex.b;
uv.x += vx * 0.8 * intensity;
uv.y += vy * 0.8 * intensity;
vec2 center = vec2(0.5);
float dist = length(uv - center);
float ripple = sin(dist * 20.0 - uTime * 3.0) * 0.04 * intensity;
float wave = sin(dist * 15.0 - uTime * 2.0) * 0.03 * intensity;
uv += vec2(ripple + wave);
vec3 color = getGradientColor(uv, uTime);
color += grain(uv, uTime) * uGrainIntensity;
float timeShift = uTime * 0.5;
color.r += sin(timeShift) * 0.02;
color.g += cos(timeShift * 1.4) * 0.02;
color.b += sin(timeShift * 1.2) * 0.02;
float brightness2 = length(color);
float mixFactor2 = max(brightness2 * 1.2, 0.15);
color = mix(uDarkNavy, color, mixFactor2);
color = clamp(color, vec3(0.0), vec3(1.0));
float brightness = length(color);
if (brightness > 1.0) color = color * (1.0 / brightness);
gl_FragColor = vec4(color, 1.0);
}
`,
});
this.mesh = new THREE.Mesh(geometry, material);
this.mesh.position.z = 0;
this.sceneManager.scene.add(this.mesh);
}
update(delta) {
if (this.uniforms.uTime) {
this.uniforms.uTime.value += delta;
}
}
onResize(width, height) {
const viewSize = this.sceneManager.getViewSize();
if (this.mesh) {
this.mesh.geometry.dispose();
this.mesh.geometry = new THREE.PlaneGeometry(viewSize.width, viewSize.height, 1, 1);
}
if (this.uniforms.uResolution) {
this.uniforms.uResolution.value.set(width, height);
}
}
}
class WebGLApp {
constructor(container, props) {
this.animationId = 0;
this.props = props;
this.renderer = new THREE.WebGLRenderer({ antialias: true, powerPreference: "high-performance" });
this.renderer.setSize(container.clientWidth, container.clientHeight);
this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
// Safety check: remove any existing canvases to prevent duplicates
if (container.children.length > 0) {
container.innerHTML = "";
}
container.appendChild(this.renderer.domElement);
this.camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 10000);
this.camera.position.z = 50;
this.scene = new THREE.Scene();
const bgHex = props.darkNavyColor ? parseInt(props.darkNavyColor.replace("#", ""), 16) : 0x0a0e27;
this.scene.background = new THREE.Color(bgHex);
this.clock = new THREE.Clock();
this.touchTexture = new TouchTexture();
this.gradientBackground = new GradientBackground(this, props);
this.gradientBackground.uniforms.uTouchTexture.value = this.touchTexture.texture;
this.colorSchemes = {
1: { color1: new THREE.Vector3(0.945, 0.353, 0.133), color2: new THREE.Vector3(0.039, 0.055, 0.153) },
2: { color1: new THREE.Vector3(1.0, 0.424, 0.314), color2: new THREE.Vector3(0.251, 0.878, 0.816) },
3: {
color1: new THREE.Vector3(0.945, 0.353, 0.133),
color2: new THREE.Vector3(0.039, 0.055, 0.153),
color3: new THREE.Vector3(0.251, 0.878, 0.816),
},
4: {
color1: new THREE.Vector3(0.949, 0.4, 0.2),
color2: new THREE.Vector3(0.176, 0.42, 0.427),
color3: new THREE.Vector3(0.82, 0.686, 0.612),
},
5: {
color1: new THREE.Vector3(0.945, 0.353, 0.133),
color2: new THREE.Vector3(0.0, 0.259, 0.22),
color3: new THREE.Vector3(0.945, 0.353, 0.133),
color4: new THREE.Vector3(0.0, 0.0, 0.0),
color5: new THREE.Vector3(0.945, 0.353, 0.133),
color6: new THREE.Vector3(0.0, 0.0, 0.0),
},
};
this.currentScheme = props.scheme || 1;
this.mouse = { x: 0, y: 0 };
this.init();
}
setColorScheme(scheme) {
if (!this.colorSchemes[scheme])
return;
this.currentScheme = scheme;
const colors = this.colorSchemes[scheme];
const uniforms = this.gradientBackground.uniforms;
if (scheme === 3) {
uniforms.uColor1.value.copy(colors.color1);
uniforms.uColor2.value.copy(colors.color2);
uniforms.uColor3.value.copy(colors.color3);
uniforms.uColor4.value.copy(colors.color1);
uniforms.uColor5.value.copy(colors.color2);
uniforms.uColor6.value.copy(colors.color3);
}
else if (scheme === 4) {
uniforms.uColor1.value.copy(colors.color1);
uniforms.uColor2.value.copy(colors.color2);
uniforms.uColor3.value.copy(colors.color3);
uniforms.uColor4.value.copy(colors.color1);
uniforms.uColor5.value.copy(colors.color2);
uniforms.uColor6.value.copy(colors.color3);
}
else if (scheme === 5) {
uniforms.uColor1.value.copy(colors.color1);
uniforms.uColor2.value.copy(colors.color2);
uniforms.uColor3.value.copy(colors.color3);
uniforms.uColor4.value.copy(colors.color4);
uniforms.uColor5.value.copy(colors.color5);
uniforms.uColor6.value.copy(colors.color6);
}
else {
uniforms.uColor1.value.copy(colors.color1);
uniforms.uColor2.value.copy(colors.color2);
uniforms.uColor3.value.copy(colors.color1);
uniforms.uColor4.value.copy(colors.color2);
uniforms.uColor5.value.copy(colors.color1);
uniforms.uColor6.value.copy(colors.color2);
}
if (scheme === 1 || scheme === 6 || scheme === 7 || scheme === 8 || scheme === 5) {
const bgHex = this.props.darkNavyColor ? parseInt(this.props.darkNavyColor.replace("#", ""), 16) : 0x0a0e27;
this.scene.background = new THREE.Color(bgHex);
const darkRgb = hexToRgb(this.props.darkNavyColor || "#0a0e27");
if (darkRgb)
uniforms.uDarkNavy.value.set(darkRgb.r, darkRgb.g, darkRgb.b);
uniforms.uGradientSize.value = 0.45;
uniforms.uGradientCount.value = 12.0;
uniforms.uSpeed.value = 1.5;
uniforms.uColor1Weight.value = 0.5;
uniforms.uColor2Weight.value = 1.8;
}
else if (scheme === 4) {
this.scene.background = new THREE.Color(0xffffff);
uniforms.uDarkNavy.value.set(0, 0, 0);
}
else {
const bgHex = this.props.darkNavyColor ? parseInt(this.props.darkNavyColor.replace("#", ""), 16) : 0x0a0e27;
this.scene.background = new THREE.Color(bgHex);
const darkRgb = hexToRgb(this.props.darkNavyColor || "#0a0e27");
if (darkRgb)
uniforms.uDarkNavy.value.set(darkRgb.r, darkRgb.g, darkRgb.b);
uniforms.uGradientSize.value = 1.0;
uniforms.uGradientCount.value = 6.0;
uniforms.uSpeed.value = 1.2;
uniforms.uColor1Weight.value = 1.0;
uniforms.uColor2Weight.value = 1.0;
}
}
updateColors(colorArray) {
const uniforms = this.gradientBackground.uniforms;
colorArray.forEach((hex, i) => {
const rgb = hexToRgb(hex);
if (rgb) {
const u = uniforms[`uColor${i + 1}`];
if (u)
u.value.set(rgb.r, rgb.g, rgb.b);
}
});
}
init() {
this.gradientBackground.init();
this.setColorScheme(this.currentScheme);
if (this.props.colors) {
this.updateColors(this.props.colors);
}
this.tick();
}
getViewSize() {
const fovInRadians = (this.camera.fov * Math.PI) / 180;
const height = Math.abs(this.camera.position.z * Math.tan(fovInRadians / 2) * 2);
return { width: height * this.camera.aspect, height };
}
tick() {
const delta = Math.min(this.clock.getDelta(), 0.1);
this.touchTexture.update();
this.gradientBackground.update(delta);
this.renderer.render(this.scene, this.camera);
this.animationId = requestAnimationFrame(() => this.tick());
}
onResize(width, height) {
this.camera.aspect = width / height;
this.camera.updateProjectionMatrix();
this.renderer.setSize(width, height);
this.gradientBackground.onResize(width, height);
}
handleTouch(x, y, width, height) {
this.touchTexture.addTouch({ x: x / width, y: 1 - y / height });
}
dispose() {
cancelAnimationFrame(this.animationId);
this.renderer.dispose();
}
}
function LiquidSurface({ className, style, colors, speed, intensity, grainIntensity, zoom, gradientSize, gradientCount, color1Weight, color2Weight, darkNavyColor, scheme, heading, showCursor = true, }) {
const containerRef = (0, react_1.useRef)(null);
const cursorRef = (0, react_1.useRef)(null);
const appRef = (0, react_1.useRef)(null);
(0, react_1.useEffect)(() => {
if (!containerRef.current)
return;
const app = new WebGLApp(containerRef.current, {
speed,
intensity,
grainIntensity,
zoom,
gradientSize,
gradientCount,
color1Weight,
color2Weight,
darkNavyColor,
scheme,
colors,
});
appRef.current = app;
const onResize = () => {
if (containerRef.current) {
app.onResize(containerRef.current.clientWidth, containerRef.current.clientHeight);
}
};
const onMouseMove = (e) => {
if (containerRef.current) {
const rect = containerRef.current.getBoundingClientRect();
app.handleTouch(e.clientX - rect.left, e.clientY - rect.top, rect.width, rect.height);
}
if (showCursor && cursorRef.current) {
gsap_1.default.to(cursorRef.current, {
x: e.clientX,
y: e.clientY,
duration: 0.1,
ease: "power2.out",
});
}
};
const onTouchMove = (e) => {
if (containerRef.current) {
const rect = containerRef.current.getBoundingClientRect();
app.handleTouch(e.touches[0].clientX - rect.left, e.touches[0].clientY - rect.top, rect.width, rect.height);
}
};
const containerNode = containerRef.current.parentElement;
if (containerNode) {
containerNode.addEventListener("mousemove", onMouseMove);
containerNode.addEventListener("touchmove", onTouchMove, { passive: false });
}
window.addEventListener("resize", onResize);
// Initial resize with a small delay to ensure container has dimensions
const timeoutId = setTimeout(onResize, 50);
return () => {
clearTimeout(timeoutId);
window.removeEventListener("resize", onResize);
if (containerNode) {
containerNode.removeEventListener("mousemove", onMouseMove);
containerNode.removeEventListener("touchmove", onTouchMove);
}
// Use local app instance for cleanup to ensure correct disposal in React Strict Mode
app.dispose();
if (containerRef.current) {
containerRef.current.innerHTML = "";
}
};
}, []); // Only initialize once
// Handle prop updates
(0, react_1.useEffect)(() => {
if (appRef.current) {
if (scheme !== undefined)
appRef.current.setColorScheme(scheme);
if (colors)
appRef.current.updateColors(colors);
const uniforms = appRef.current.gradientBackground.uniforms;
if (speed !== undefined)
uniforms.uSpeed.value = speed;
if (intensity !== undefined)
uniforms.uIntensity.value = intensity;
if (grainIntensity !== undefined)
uniforms.uGrainIntensity.value = grainIntensity;
if (zoom !== undefined)
uniforms.uZoom.value = zoom;
if (gradientSize !== undefined)
uniforms.uGradientSize.value = gradientSize;
if (gradientCount !== undefined)
uniforms.uGradientCount.value = gradientCount;
if (color1Weight !== undefined)
uniforms.uColor1Weight.value = color1Weight;
if (color2Weight !== undefined)
uniforms.uColor2Weight.value = color2Weight;
if (darkNavyColor) {
const darkRgb = hexToRgb(darkNavyColor);
if (darkRgb)
uniforms.uDarkNavy.value.set(darkRgb.r, darkRgb.g, darkRgb.b);
}
}
}, [scheme, colors, speed, intensity, grainIntensity, zoom, gradientSize, gradientCount, color1Weight, color2Weight, darkNavyColor]);
// Hover for custom cursor
const handleMouseEnter = () => {
if (showCursor)
gsap_1.default.to(cursorRef.current, { width: 50, height: 50, borderWidth: 3, duration: 0.2 });
};
const handleMouseLeave = () => {
if (showCursor)
gsap_1.default.to(cursorRef.current, { width: 40, height: 40, borderWidth: 2, duration: 0.2 });
};
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)("relative w-full h-full overflow-hidden bg-black ", className), style: { ...style, cursor: showCursor ? "none" : "auto" }, children: [showCursor && ((0, jsx_runtime_1.jsx)("div", { ref: cursorRef, className: "fixed top-0 left-0 w-10 h-10 border-2 border-white rounded-full pointer-events-none z-[1000] mix-blend-difference -translate-x-1/2 -translate-y-1/2 flex items-center justify-center", children: (0, jsx_runtime_1.jsx)("div", { className: "w-2 h-2 bg-white rounded-full" }) })), (0, jsx_runtime_1.jsx)("div", { ref: containerRef, className: "absolute inset-0 z-0" }), heading && ((0, jsx_runtime_1.jsx)("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-center z-10 w-full h-full text-white text-center", children: (0, jsx_runtime_1.jsx)("h1", { className: "font-bold tracking-tight px-4", style: { fontSize: "clamp(3.5rem, 9vw, 9rem)" }, dangerouslySetInnerHTML: { __html: heading } }) }))] }));
}
//# sourceMappingURL=liquid-surface.js.map