93 lines
2.7 KiB
TypeScript
93 lines
2.7 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect } from "react";
|
|
|
|
declare global {
|
|
interface Window {
|
|
liquidGL?: ((options: Record<string, unknown>) => unknown) & {
|
|
registerDynamic?: (elements: string | Element[]) => void;
|
|
syncWith?: () => unknown;
|
|
};
|
|
html2canvas?: unknown;
|
|
}
|
|
}
|
|
|
|
export default function LiquidGlass() {
|
|
useEffect(() => {
|
|
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
|
|
if (!window.matchMedia("(min-width: 1024px)").matches) return;
|
|
|
|
let cancelled = false;
|
|
let attempts = 0;
|
|
|
|
function loadScript(src: string) {
|
|
return new Promise<void>((resolve, reject) => {
|
|
const existing = document.querySelector<HTMLScriptElement>(`script[src="${src}"]`);
|
|
if (existing) {
|
|
if (existing.dataset.loaded === "true") resolve();
|
|
existing.addEventListener("load", () => resolve(), { once: true });
|
|
existing.addEventListener("error", () => reject(new Error(`Failed to load ${src}`)), { once: true });
|
|
return;
|
|
}
|
|
|
|
const script = document.createElement("script");
|
|
script.src = src;
|
|
script.async = true;
|
|
script.dataset.liquidDependency = "true";
|
|
script.addEventListener("load", () => {
|
|
script.dataset.loaded = "true";
|
|
resolve();
|
|
});
|
|
script.addEventListener("error", () => reject(new Error(`Failed to load ${src}`)));
|
|
document.body.appendChild(script);
|
|
});
|
|
}
|
|
|
|
const init = () => {
|
|
attempts += 1;
|
|
if (cancelled) return;
|
|
|
|
if (!window.liquidGL || !window.html2canvas) {
|
|
if (attempts < 50) window.setTimeout(init, 120);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
window.liquidGL({
|
|
snapshot: "body",
|
|
target: ".liquidGL-pane",
|
|
resolution: 1.2,
|
|
refraction: 0.012,
|
|
bevelDepth: 0.052,
|
|
bevelWidth: 0.18,
|
|
frost: 0.85,
|
|
shadow: true,
|
|
specular: true,
|
|
reveal: "fade",
|
|
tilt: window.innerWidth >= 768,
|
|
tiltFactor: 3.5,
|
|
magnify: 1.01
|
|
});
|
|
|
|
window.liquidGL.registerDynamic?.(".liquid-dynamic");
|
|
window.liquidGL.syncWith?.();
|
|
} catch (error) {
|
|
console.warn("liquidGL could not initialise; CSS glass fallback remains active.", error);
|
|
}
|
|
};
|
|
|
|
Promise.all([
|
|
loadScript("https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"),
|
|
loadScript("/scripts/liquidGL.js")
|
|
])
|
|
.then(init)
|
|
.catch((error) => console.warn("liquidGL dependencies could not load; CSS glass fallback remains active.", error));
|
|
|
|
return () => {
|
|
cancelled = true;
|
|
};
|
|
}, []);
|
|
|
|
return null;
|
|
}
|