Spaces:
Sleeping
Sleeping
File size: 1,582 Bytes
0fff343 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | "use client";
import {
createContext,
ReactNode,
useCallback,
useContext,
useRef,
useState,
} from "react";
import { PARAM_HELP, ParamKey } from "./paramHelpContent";
import ParamHelpModal from "./ParamHelpModal";
type Ctx = {
open: (key: ParamKey, returnFocusTo?: HTMLElement | null) => void;
close: () => void;
current: ParamKey | null;
};
const ParamHelpCtx = createContext<Ctx | null>(null);
export function useParamHelp(): Ctx {
const ctx = useContext(ParamHelpCtx);
if (!ctx) {
throw new Error(
"useParamHelp(): ParamHelpProvider missing — wrap the page once near the root.",
);
}
return ctx;
}
export default function ParamHelpProvider({ children }: { children: ReactNode }) {
const [current, setCurrent] = useState<ParamKey | null>(null);
const returnRef = useRef<HTMLElement | null>(null);
const open = useCallback(
(key: ParamKey, returnFocusTo: HTMLElement | null = null) => {
returnRef.current = returnFocusTo;
setCurrent(key);
},
[],
);
const close = useCallback(() => {
setCurrent(null);
const target = returnRef.current;
if (target) {
// Defer focus to the next tick so the modal has unmounted.
setTimeout(() => {
try {
target.focus();
} catch {
/* ignore */
}
}, 0);
}
}, []);
return (
<ParamHelpCtx.Provider value={{ open, close, current }}>
{children}
{current && (
<ParamHelpModal entry={PARAM_HELP[current]} onClose={close} />
)}
</ParamHelpCtx.Provider>
);
}
|