/* global React, ReactDOM */ const { useState, useEffect, useRef } = React; /* ---------- Cart Drawer ---------- */ function CartDrawer({ open, onClose, items, navigate, setItems }) { const subtotal = items.reduce((s, it) => s + it.price * it.qty, 0); const [gift, setGift] = useState(false); const total = subtotal + (gift ? 30 : 0); return ( <>
); } /* ---------- Search overlay ---------- */ function SearchOverlay({ open, onClose, navigate }) { const [q, setQ] = useState(""); const inputRef = useRef(null); useEffect(() => { if (open && inputRef.current) inputRef.current.focus(); }, [open]); const results = q.length < 2 ? [] : window.PEARLA_DATA.products .filter(p => (p.name + " " + p.category + " " + p.collection).toLowerCase().includes(q.toLowerCase())) .slice(0, 6); const popular = ["Midnight Muse", "Ramadan & Eid", "S'élever", "Caftans under 1000"]; return (
{open && (
e.stopPropagation()}>
setQ(e.target.value)} style={{ flex: 1, border: 0, background: "transparent", fontFamily: "var(--serif)", fontSize: 28, color: "var(--ink)" }} />
{q.length < 2 ? (
Popular searches
{popular.map(t => ( ))}
) : (
{results.length === 0 ? (

No matches. Try "abaya", "lace" or "scent".

) : ( )}
)}
)}
); } /* ---------- App ---------- */ const DEFAULTS = /*EDITMODE-BEGIN*/{ "palette": "modest-luxe", "displayFont": "Cormorant Garamond", "showPedigree": true, "showFragrance": true, "showSocial": true, "showDrop": true, "denser": false }/*EDITMODE-END*/; const PALETTES = { "modest-luxe": { name: "Modest luxe", swatch: ["#FBF7F1", "#1B1814", "#B59A66"], vars: { "--bg": "#FBF7F1", "--ink": "#1B1814", "--noir": "#100D0A", "--gold": "#B59A66", "--gold-deep": "#8A6F3F", "--bone": "#EEE7DB", "--paper": "#F5EFE5", "--line": "#E6DCCD", "--line-strong": "#D5C8B0", "--muted": "#6B5F4F" } }, "stone-noir": { name: "Stone noir", swatch: ["#EFECE4", "#1A1A1C", "#8E8276"], vars: { "--bg": "#EFECE4", "--ink": "#1A1A1C", "--noir": "#0E0E10", "--gold": "#8E8276", "--gold-deep": "#5E544A", "--bone": "#E0DCD2", "--paper": "#E6E2D8", "--line": "#D1CCBF", "--line-strong": "#B7B1A1", "--muted": "#6A645B" } }, "blush-ink": { name: "Blush & ink", swatch: ["#FAEEEA", "#22171A", "#C28A8A"], vars: { "--bg": "#FAEEEA", "--ink": "#22171A", "--noir": "#140C10", "--gold": "#C28A8A", "--gold-deep": "#8E5A5A", "--bone": "#F1DEDA", "--paper": "#F5E5E1", "--line": "#E8D2CC", "--line-strong": "#CFAAA3", "--muted": "#7A5A5A" } }, "midnight-pearl": { name: "Midnight pearl", swatch: ["#11131A", "#EDE6D8", "#B3A06B"], vars: { "--bg": "#11131A", "--ink": "#EDE6D8", "--noir": "#0A0B10", "--gold": "#B3A06B", "--gold-deep": "#D6C28A", "--bone": "#1E202A", "--paper": "#181B25", "--line": "#2A2D38", "--line-strong": "#3A3E4A", "--muted": "#9A9486" } } }; function App() { const [route, setRoute] = useState(window.location.hash.replace("#", "") || "/"); const [bag, setBag] = useState([]); const [bagOpen, setBagOpen] = useState(false); const [searchOpen, setSearchOpen] = useState(false); const [favs, setFavs] = useState(new Set()); const [toast, setToast] = useState(""); const [tweaks, setTweaks] = useState(DEFAULTS); const navigate = (r) => { setRoute(r); window.location.hash = r; window.scrollTo({ top: 0, behavior: "instant" }); }; useEffect(() => { const onHash = () => setRoute(window.location.hash.replace("#", "") || "/"); window.addEventListener("hashchange", onHash); return () => window.removeEventListener("hashchange", onHash); }, []); /* apply tweaks (palette + font) */ useEffect(() => { const root = document.documentElement; const pal = PALETTES[tweaks.palette] || PALETTES["modest-luxe"]; Object.entries(pal.vars).forEach(([k, v]) => root.style.setProperty(k, v)); root.style.setProperty("--serif", `"${tweaks.displayFont}", Georgia, serif`); document.body.dataset.denser = tweaks.denser ? "1" : "0"; }, [tweaks]); const setTweak = (key, val) => { const next = typeof key === "object" ? { ...tweaks, ...key } : { ...tweaks, [key]: val }; setTweaks(next); window.parent?.postMessage({ type: "__edit_mode_set_keys", edits: typeof key === "object" ? key : { [key]: val } }, "*"); }; const onAdd = (p, size) => { setBag(prev => { const existing = prev.findIndex(it => it.id === p.id && it.size === size); if (existing >= 0) { const c = prev.slice(); c[existing] = { ...c[existing], qty: c[existing].qty + 1 }; return c; } return [...prev, { id: p.id, name: p.name, price: p.price, image: p.image, size, qty: 1 }]; }); setToast(`Added — ${p.name}`); setTimeout(() => setToast(""), 1800); }; const toggleFav = (id) => { setFavs(prev => { const next = new Set(prev); next.has(id) ? next.delete(id) : next.add(id); return next; }); }; const bagCount = bag.reduce((s, it) => s + it.qty, 0); /* route resolver */ let page; if (route === "/" || route === "") { page = ( <> {tweaks.showPedigree && } {tweaks.showDrop && } {tweaks.showFragrance && } {tweaks.showSocial && } ); } else if (route === "/shop") { page = ; } else if (route === "/collections") { page = ; } else if (route.startsWith("/collections/")) { page = ; } else if (route.startsWith("/product/")) { page = ; } else if (route === "/fragrance") { page = ; } else if (route === "/gifting") { page = ; } else if (route === "/about") { page = ; } else if (route === "/contact") { page = ; } else { page = ; } return (
setBagOpen(true)} openSearch={() => setSearchOpen(true)} />
{page}
setBagOpen(false)} items={bag} setItems={setBag} navigate={navigate} /> setSearchOpen(false)} navigate={navigate} />
{toast}
PALETTES[k].swatch)} onChange={(swatch) => { const key = Object.keys(PALETTES).find(k => JSON.stringify(PALETTES[k].swatch) === JSON.stringify(swatch)); if (key) setTweak("palette", key); }} />
{(PALETTES[tweaks.palette] || PALETTES["modest-luxe"]).name}
setTweak("displayFont", v)} /> setTweak("showPedigree", v)} /> setTweak("showDrop", v)} /> setTweak("showFragrance", v)} /> setTweak("showSocial", v)} /> {[ ["Home", "/"], ["Shop", "/shop"], ["Collections", "/collections"], ["A Collection — Princess", "/collections/princess-and-the-pearl"], ["Product — Celestial Bloom", "/product/celestial-bloom-abaya"], ["Fragrance", "/fragrance"], ["Gifting", "/gifting"], ["About", "/about"], ["Contact", "/contact"] ].map(([label, path]) => ( navigate(path)} /> ))}
); } ReactDOM.createRoot(document.getElementById("root")).render();