// ===================== Core components: Reveal, Nav, Hero, About, Experience ===================== const { useState, useEffect, useRef, useContext } = React; // scroll reveal wrapper function Reveal({ children, delay=0, as='div', className='', ...rest }){ const ref = useRef(null); const [seen, setSeen] = useState(false); useEffect(()=>{ const el = ref.current; const io = new IntersectionObserver((es)=>{ es.forEach(e=>{ if(e.isIntersecting){ setSeen(true); io.disconnect(); } }); }, { threshold:0.12, rootMargin:'0px 0px -8% 0px' }); if(el) io.observe(el); return ()=>io.disconnect(); },[]); const Tag = as; return {children}; } function useC(){ const { lang } = useContext(window.LangCtx); return window.CONTENT[lang]; } const H = (html)=>({ dangerouslySetInnerHTML:{ __html:html } }); // ---------- NAV ---------- function Nav({ lang, setLang }){ const C = window.CONTENT[lang]; const [scrolled, setScrolled] = useState(false); useEffect(()=>{ const on = ()=>setScrolled(window.scrollY > 40); on(); window.addEventListener('scroll', on, { passive:true }); return ()=>window.removeEventListener('scroll', on); },[]); const N = C.nav; return ( ); } // ---------- HERO ---------- function Hero(){ const C = useC(); const h = C.hero; return (
{h.tag}

Patrick
Chaves

{window.SOCIALS.map((s,i)=>( {s.k} {s.v} ↗ ))}
{h.corner}
{h.b1}
Ilustração do Patrick por @sunnie.ilustra
); } // ---------- ABOUT ---------- function About(){ const C = useC(); const a = C.about; const ref = useRef(null); const [vis, setVis] = useState(false); useEffect(()=>{ const io = new IntersectionObserver((es)=>{ es.forEach(e=>{ if(e.isIntersecting) setVis(true); }); }, { threshold:0.3 }); if(ref.current) io.observe(ref.current); return ()=>io.disconnect(); },[]); return (
{a.num} · Patrick Chaves

/ {a.num}

{a.quote}
{a.stats.map((s,i)=>(
{s.n}
{s.l}
))}
{a.body.map((p,i)=>(

{p}

))}
{a.langs_title}
{a.langs.map((L,i)=>(
{L.n}{L.l}
))}
); } // ---------- EXPERIENCE ---------- function Experience(){ const C = useC(); const e = C.exp; return (
{e.num} · {e.kicker}

/ {e.num}
{e.jobs.map((j,i)=>(
{j.when} {j.live &&
{j.live}
}
{j.co}{j.ceo && CEO}
{j.role}
{j.tags.map((t,k)=>({t}))}
    {j.items.map((it,k)=>(
  • {it}
  • ))}
))}
); } Object.assign(window, { Reveal, useC, H, Nav, Hero, About, Experience });