// shared.jsx — Primitives shared across every page. // Loaded after services-data.js, before all other JSX. // Data (NAV_FONTS, SERVICE_ITEMS) comes from services-data.js globals. function Arrow({ size = 14 }) { return ( ); } function FontDropdown({ value, onChange }) { const [open, setOpen] = React.useState(false); const ref = React.useRef(null); React.useEffect(() => { const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); }; document.addEventListener('mousedown', onDoc); return () => document.removeEventListener('mousedown', onDoc); }, []); const current = NAV_FONTS.find((f) => f.value === value) || NAV_FONTS[0]; return (
{open && (
{NAV_FONTS.map((f) => ( ))}
)}
); } function ServicesDropdown({ overviewHref = 'services.html', active = false, activeName }) { const [open, setOpen] = React.useState(false); const ref = React.useRef(null); const timer = React.useRef(null); const openNow = () => { clearTimeout(timer.current); setOpen(true); }; const closeSoon = () => { timer.current = setTimeout(() => setOpen(false), 150); }; React.useEffect(() => { const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); }; document.addEventListener('mousedown', onDoc); return () => document.removeEventListener('mousedown', onDoc); }, []); return (
Services
{SERVICE_ITEMS.map((s) => ( {s.n} {s.name} ))}
); } Object.assign(window, { Arrow, FontDropdown, ServicesDropdown });