feat(ui): vendor Aceternity registry components + showcase gallery
Vendor 50 Aceternity UI components into components/ui from the official registry (ui.aceternity.com/registry/<slug>.json), adapted for this template's stack: Tailwind v4, motion/react 13, cn util, React 19. Add a live showcase gallery (/ui + /docs/... navigation is unchanged): app/ui/page.tsx renders <ShowcaseGallery> with 30+ demos — 3d-pin, aurora, background-beams, bento, card-stack, card-spotlight, direction-aware-hover, encrypted-text, evervault-card, flip-words, hero-highlight, hero-parallax, infinite-moving-cards, moving-border, sparkles, tracing-beam, animated-tooltip, typewriter-effect, placeholders-and-vanish-input and friends. Toolchain stays zero-warning: vendored animation code is scoped in eslint.config.mjs (react-hooks/react-compiler advisory rules, no-any, prefer-const, no-img-element) so app code keeps a 0-error gate. typecheck, build, 7 vitest tests and 2 test suites all green.
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
"use client";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { createNoise3D } from "simplex-noise";
|
||||
|
||||
export const WavyBackground = ({
|
||||
children,
|
||||
className,
|
||||
containerClassName,
|
||||
colors,
|
||||
waveWidth,
|
||||
backgroundFill,
|
||||
blur = 10,
|
||||
speed = "fast",
|
||||
waveOpacity = 0.5,
|
||||
...props
|
||||
}: {
|
||||
children?: any;
|
||||
className?: string;
|
||||
containerClassName?: string;
|
||||
colors?: string[];
|
||||
waveWidth?: number;
|
||||
backgroundFill?: string;
|
||||
blur?: number;
|
||||
speed?: "slow" | "fast";
|
||||
waveOpacity?: number;
|
||||
[key: string]: any;
|
||||
}) => {
|
||||
const noise = createNoise3D();
|
||||
let w: number, h: number, nt: number, i: number, x: number, ctx: any, canvas: any;
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
const getSpeed = () => {
|
||||
switch (speed) {
|
||||
case "slow":
|
||||
return 0.001;
|
||||
case "fast":
|
||||
return 0.002;
|
||||
default:
|
||||
return 0.001;
|
||||
}
|
||||
};
|
||||
|
||||
const init = () => {
|
||||
canvas = canvasRef.current;
|
||||
ctx = canvas.getContext("2d");
|
||||
w = ctx.canvas.width = window.innerWidth;
|
||||
h = ctx.canvas.height = window.innerHeight;
|
||||
ctx.filter = `blur(${blur}px)`;
|
||||
nt = 0;
|
||||
window.onresize = function () {
|
||||
w = ctx.canvas.width = window.innerWidth;
|
||||
h = ctx.canvas.height = window.innerHeight;
|
||||
ctx.filter = `blur(${blur}px)`;
|
||||
};
|
||||
render();
|
||||
};
|
||||
|
||||
const waveColors = colors ?? ["#38bdf8", "#818cf8", "#c084fc", "#e879f9", "#22d3ee"];
|
||||
const drawWave = (n: number) => {
|
||||
nt += getSpeed();
|
||||
for (i = 0; i < n; i++) {
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = waveWidth || 50;
|
||||
ctx.strokeStyle = waveColors[i % waveColors.length];
|
||||
for (x = 0; x < w; x += 5) {
|
||||
const y = noise(x / 800, 0.3 * i, nt) * 100;
|
||||
ctx.lineTo(x, y + h * 0.5); // adjust for height, currently at 50% of the container
|
||||
}
|
||||
ctx.stroke();
|
||||
ctx.closePath();
|
||||
}
|
||||
};
|
||||
|
||||
let animationId: number;
|
||||
const render = () => {
|
||||
ctx.fillStyle = backgroundFill || "black";
|
||||
ctx.globalAlpha = waveOpacity || 0.5;
|
||||
ctx.fillRect(0, 0, w, h);
|
||||
drawWave(5);
|
||||
animationId = requestAnimationFrame(render);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
init();
|
||||
return () => {
|
||||
cancelAnimationFrame(animationId);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const [isSafari, setIsSafari] = useState(false);
|
||||
useEffect(() => {
|
||||
// I'm sorry but i have got to support it on safari.
|
||||
setIsSafari(
|
||||
typeof window !== "undefined" &&
|
||||
navigator.userAgent.includes("Safari") &&
|
||||
!navigator.userAgent.includes("Chrome")
|
||||
);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={cn("flex h-screen flex-col items-center justify-center", containerClassName)}>
|
||||
<canvas
|
||||
className="absolute inset-0 z-0"
|
||||
ref={canvasRef}
|
||||
id="canvas"
|
||||
style={{
|
||||
...(isSafari ? { filter: `blur(${blur}px)` } : {}),
|
||||
}}
|
||||
></canvas>
|
||||
<div className={cn("relative z-10", className)} {...props}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user