Files
Evandro Fonseca JuniorandClaude Opus 5.5 4c826e938f
CI / verify (push) Failing after 5m43s
fix(ci): lint do Biome, Next 16.3.8 (RCE em next/og) e transicoes que se remedem
- 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]>
2026-10-05 01:38:41 -03:00

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>
);
}