CI / verify (push) Failing after 5m43s
- Biome: formatacao, ordem de imports, max-width duplicado no cabecalho de secao, supressao justificada para nomes de view-transition, ajustes nos scripts de auditoria de SEO - next 16.3.3 -> 16.3.8: GHSA-vcvr-r3jv-pc5j (execucao remota de codigo em next/og ImageResponse, usado nas imagens de compartilhamento) - overrides de brace-expansion (GHSA-qhr7-859c-m2p7, GHSA-6j4f-fj2g-mc7p, GHSA-q2hr-2g5m-vwhr), dependencia de desenvolvimento via jest - visibilidade das cenas le as posicoes a cada quadro e o GSAP remede as passagens quando a pagina muda de altura (fontes, imagens, Experiencia) Co-Authored-By: Claude Opus 5.5 <[email protected]>
61 lines
1.7 KiB
TypeScript
61 lines
1.7 KiB
TypeScript
"use client";
|
|
|
|
import { useInView } from "motion/react";
|
|
import { type CSSProperties, useRef } from "react";
|
|
|
|
interface TextDiffuseRevealProps {
|
|
text: string;
|
|
className?: string;
|
|
startDelay?: number;
|
|
once?: boolean;
|
|
amount?: number;
|
|
}
|
|
|
|
/**
|
|
* Título que entra palavra por palavra. A animação é CSS (.text-reveal em globals.css) com transparência
|
|
* e deslocamento: a placa de vídeo compõe sem redesenhar. A versão anterior animava cada letra com
|
|
* desfoque e renderizava o React de novo a cada letra, o que pesava justamente durante as transições.
|
|
* Movimento reduzido: o CSS mostra o texto direto, sem animação.
|
|
*/
|
|
export function TextDiffuseReveal({
|
|
text,
|
|
className = "",
|
|
startDelay = 0,
|
|
once = true,
|
|
amount = 0.3,
|
|
}: Readonly<TextDiffuseRevealProps>) {
|
|
const ref = useRef<HTMLSpanElement | null>(null);
|
|
const isInView = useInView(ref, { once, amount });
|
|
let word = 0;
|
|
|
|
return (
|
|
<span
|
|
ref={ref}
|
|
className={`text-reveal ${className}`.trim()}
|
|
data-shown={isInView ? "" : undefined}
|
|
style={{ "--d": `${startDelay}s` } as CSSProperties}
|
|
>
|
|
<span className="sr-only">{text}</span>
|
|
<span aria-hidden="true">
|
|
{text
|
|
.split(/(\n|\s+)/)
|
|
.filter(Boolean)
|
|
.map((token, index) => {
|
|
const key = `${index}:${token}`;
|
|
if (token === "\n") return <br key={key} />;
|
|
if (/^\s+$/.test(token)) return " ";
|
|
return (
|
|
<span
|
|
key={key}
|
|
className="text-reveal-word"
|
|
style={{ "--i": word++ } as CSSProperties}
|
|
>
|
|
{token}
|
|
</span>
|
|
);
|
|
})}
|
|
</span>
|
|
</span>
|
|
);
|
|
}
|