// Furnishfy — main app: router, tweaks
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
"direction": "sapphire",
"gold": window.FURN?.PRIMARY_COLOR || "#fd6221",
"secondary": window.FURN?.SECONDARY_COLOR || "#2c2c2c",
"radius": 4,
"displayFont": "Cormorant Garamond"
}/*EDITMODE-END*/;
// ---------- Search overlay ----------
function SearchOverlay({ open, onClose, go }) {
const [q, setQ] = useState("");
const { PRODUCTS } = window.FURN;
const inputRef = useRef(null);
useEffect(() => { if (open) { setQ(""); setTimeout(() => inputRef.current?.focus(), 80); } }, [open]);
const res = q.trim() ? PRODUCTS.filter((p) => (p.en + p.material.en).toLowerCase().includes(q.toLowerCase())).slice(0, 5) : [];
return (
setQ(e.target.value)} placeholder="Search the collection..."
style={{ flex: 1, background: "none", border: "none", outline: "none", color: "var(--ink)", fontFamily: "var(--font-display)", fontSize: "clamp(24px,4vw,38px)" }} />
{res.map((p) => {
const hasImg = p.thumbnail && !p.thumbnail.includes('no-product');
return (
{ onClose(); go("product", p.id); }} style={{ display: "flex", alignItems: "center", gap: 18, padding: "16px 4px", borderBottom: "1px solid var(--line)", cursor: "pointer" }} className="searchres">
{hasImg ? (
) : (
)}
{money(p.price)}
);
})}
{q.trim() && res.length === 0 &&
No results found.
}
);
}
// ---------- Story page ----------
function Story({ go }) {
useReveal();
return (
The Atelier
We build as if time stands still.
Since 1988, we have gathered the finest makers around a single bench — choosing timber by hand and refusing anything disposable.
{[["Hand-selected", "We travel to the mills ourselves and reject 9 of every 10 boards."],
["Slow-finished", "Each surface is oiled and rubbed over twelve patient days."],
["Built to repair", "Joinery is designed to be opened, mended, and passed on."]].map((b, i) => (
))}
go("shop")}>Explore collection
);
}
function var_radius3() { return getComputedStyle(document.documentElement).getPropertyValue("--radius") || "4px"; }
const { BrowserRouter, Routes, Route, useNavigate, useParams, useSearchParams, useLocation } = window.ReactRouterDOM;
function ShopWrapper({ go, lang }) {
const [searchParams] = useSearchParams();
const cat = searchParams.get("cat") || null;
return ;
}
function ProductWrapper({ go, lang }) {
const { productId } = useParams();
return ;
}
// ---------- AppContent ----------
function AppContent() {
const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
const [searchOpen, setSearchOpen] = useState(false);
const [lang, setLang] = useState("en");
const navigate = useNavigate();
const location = useLocation();
// apply tweaks → root
useEffect(() => {
const r = document.documentElement;
r.setAttribute("data-theme", t.direction);
r.style.setProperty("--gold", t.gold);
r.style.setProperty("--secondary", t.secondary || "#2c2c2c");
r.style.setProperty("--radius", t.radius + "px");
r.style.setProperty("--font-display", `"${t.displayFont}", Georgia, serif`);
}, [t]);
const go = useCallback((p, id = null, cat = null) => {
if (p !== "product") window.scrollTo({ top: 0, behavior: "instant" });
if (p === "home") {
navigate("/");
} else if (p === "shop") {
navigate(cat ? `/shop?cat=${cat}` : "/shop");
} else if (p === "rooms") {
navigate(cat ? `/rooms?cat=${cat}` : "/rooms");
} else if (p === "product") {
navigate(`/product/${id}`);
} else {
navigate(`/${p}`);
}
}, [navigate]);
// Active page determination for header active state highlighting
let activePage = "home";
const path = location.pathname;
if (path.startsWith("/shop")) activePage = "shop";
else if (path.startsWith("/rooms")) activePage = "rooms";
else if (path.startsWith("/product")) activePage = "product";
else if (path.startsWith("/story")) activePage = "story";
else if (path.startsWith("/contact")) activePage = "contact";
return (
<>
setSearchOpen(true)} lang={lang} />
} />
} />
} />
} />
} />
} />
setSearchOpen(false)} go={go} />
setTweak("direction", v)} />
setTweak("gold", v)} />
setTweak("radius", v)} />
setTweak("displayFont", v)} />
>
);
}
// ---------- App ----------
function App() {
return (
);
}
ReactDOM.createRoot(document.getElementById("root")).render( );