46 lines
1.4 KiB
TypeScript
46 lines
1.4 KiB
TypeScript
"use client";
|
|
|
|
import { createContext, useContext, useEffect, useState } from "react";
|
|
|
|
const STORAGE_KEY = "organize:board-view";
|
|
|
|
// A plain string union rather than an enum -- adding a future view is just
|
|
// one more literal here plus one more radio item in ViewSwitcher.
|
|
export type BoardView = "default" | "compact";
|
|
|
|
interface BoardViewContextValue {
|
|
view: BoardView;
|
|
setView: (view: BoardView) => void;
|
|
}
|
|
|
|
const BoardViewContext = createContext<BoardViewContextValue | null>(null);
|
|
|
|
export function BoardViewProvider({ children }: { children: React.ReactNode }) {
|
|
// Default to "default" on both server and first client render to avoid a
|
|
// hydration mismatch; the real persisted value is applied right after
|
|
// mount, trading a one-frame flash for zero hydration warnings.
|
|
const [view, setViewState] = useState<BoardView>("default");
|
|
|
|
useEffect(() => {
|
|
const stored = localStorage.getItem(STORAGE_KEY);
|
|
if (stored === "default" || stored === "compact") setViewState(stored);
|
|
}, []);
|
|
|
|
function setView(next: BoardView) {
|
|
setViewState(next);
|
|
localStorage.setItem(STORAGE_KEY, next);
|
|
}
|
|
|
|
return (
|
|
<BoardViewContext.Provider value={{ view, setView }}>
|
|
{children}
|
|
</BoardViewContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useBoardView() {
|
|
const ctx = useContext(BoardViewContext);
|
|
if (!ctx) throw new Error("useBoardView must be used within a BoardViewProvider");
|
|
return ctx;
|
|
}
|