// OEG Homepage — App shell // Composes Nav + Hero (one of 3 variants) + body sections + Footer + Tweaks panel const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "theme": "light", "heroVariant": "cube" }/*EDITMODE-END*/; const FALLBACK_NAV_LIBRARIES = [ { slug: "basic-process-science", name: "Basic Process Science" }, { slug: "pumps", name: "Centrifugal Pumps" }, { slug: "compressors", name: "Compressors" }, { slug: "distillation", name: "Distillation" }, { slug: "fcc", name: "Fluid Catalytic Cracking" }, { slug: "fired-heaters", name: "Fired Heaters" }, { slug: "gear-pumps", name: "Gear Pumps" }, { slug: "heat-exchangers", name: "Heat Exchangers" }, { slug: "instrumentation", name: "Instrumentation" }, { slug: "midstream", name: "Midstream" }, { slug: "valves", name: "Valves" }, ]; const NavBar = ({ mc = {} }) => { const [trainingOpen, setTrainingOpen] = React.useState(false); const [mobileOpen, setMobileOpen] = React.useState(false); const rawLibs = (mc.trainingLibraries && mc.trainingLibraries.length) ? mc.trainingLibraries : FALLBACK_NAV_LIBRARIES; const libraries = rawLibs.filter(l => !l.hidden); const customPages = (mc.customPages || []).filter(p => !p.hidden); const close = () => setMobileOpen(false); return ( Home Knowledge Library TAP Reference Library {customPages.map(p => ( {p.navLabel || p.name} ))} {/* Training Solutions dropdown */} setTrainingOpen(true)} onMouseLeave={() => setTrainingOpen(false)}> Training Solutions {trainingOpen && ( Content Libraries {libraries.map(lib => ( {lib.name} ))} )} About Contact setMobileOpen(m => !m)} aria-label={mobileOpen ? "Close menu" : "Open menu"} aria-expanded={mobileOpen} > {mobileOpen ? : } ); }; const App = () => { const [t, setTweak] = useTweaks(TWEAK_DEFAULTS); // Media config loaded from managed-media/site-media-config.json const [mc, setMc] = React.useState({}); React.useEffect(() => { fetch('managed-media/site-media-config.json') .then(r => r.json()) .then(setMc) .catch(() => {}); // fail silently — hardcoded fallbacks take over in each component }, []); // Sync theme from localStorage on first load React.useEffect(() => { const saved = localStorage.getItem('oeg_theme_pref'); if (saved) setTweak('theme', saved); }, []); // Listen for footer theme toggle React.useEffect(() => { const handler = (e) => setTweak('theme', e.detail); window.addEventListener('oeg:theme', handler); return () => window.removeEventListener('oeg:theme', handler); }, []); React.useEffect(() => { document.body.setAttribute("data-theme", t.theme || "light"); }, [t.theme]); let Hero; if (t.heroVariant === "split") Hero = HeroSplit; else if (t.heroVariant === "cube") Hero = HeroCube; else Hero = HeroBold; return ( <> setTweak("theme", v)} options={[ { value: "light", label: "Light" }, { value: "dark", label: "Dark" }, ]} /> setTweak("heroVariant", v)} options={[ { value: "bold", label: "01 — Bold statement + screenshot" }, { value: "split", label: "02 — Split: Studio | Library" }, { value: "cube", label: "03 — Isometric cube centerpiece" }, ]} /> > ); }; ReactDOM.createRoot(document.getElementById("root")).render();