import { createSignal } from "solid-js"; // Persistence layer for collapsible (Zippy) panels. The cookie is a // best-effort hint: the page always renders all Zippies closed unless // their stable id is in the cookie's open-set, but a missing or // corrupt cookie just falls back to "everything closed", so losing it // (browser data clear, expiry, private window, write failure) is a // pure cosmetic regression. // // localStorage would arguably be a tidier home for this — it's // client-only and doesn't ride on every HTTP request — but the // payload is tiny and the user asked for a cookie, so a cookie it // is. SameSite=Lax keeps it from leaking to third-party iframes. const COOKIE_NAME = "maglev_zippy_open"; const COOKIE_MAX_AGE = 60 * 60 * 24 * 365; // 1 year function readCookie(): Set { try { const raw = document.cookie.split("; ").find((c) => c.startsWith(COOKIE_NAME + "=")); if (!raw) return new Set(); const value = decodeURIComponent(raw.slice(COOKIE_NAME.length + 1)); if (!value) return new Set(); return new Set(value.split(",")); } catch { return new Set(); } } function writeCookie(ids: Set) { try { const value = encodeURIComponent([...ids].join(",")); document.cookie = `${COOKIE_NAME}=${value}; Path=/; Max-Age=${COOKIE_MAX_AGE}; SameSite=Lax`; } catch { // best-effort — quota, third-party-cookie blocks, etc. all silently fall back } } const [openSet, setOpenSet] = createSignal>(readCookie()); export function isZippyOpen(id: string): boolean { return openSet().has(id); } export function setZippyOpen(id: string, open: boolean) { const cur = openSet(); if (open === cur.has(id)) return; const next = new Set(cur); if (open) next.add(id); else next.delete(id); setOpenSet(next); writeCookie(next); }