43 lines
1.2 KiB
TypeScript
43 lines
1.2 KiB
TypeScript
|
|
import { create } from 'zustand';
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* One breadcrumb hint per pathname. Detail pages push their entity
|
|||
|
|
* hierarchy into this store on mount via `useBreadcrumbHint`; the
|
|||
|
|
* topbar Breadcrumbs component reads the hint for the current path
|
|||
|
|
* and renders Client › Mary Smith › Interest › B17 instead of the
|
|||
|
|
* URL-only Clients › Interests trail.
|
|||
|
|
*
|
|||
|
|
* Pathname-keyed (not entity-id-keyed) so concurrent route mounts
|
|||
|
|
* don't trample each other when the user navigates between details
|
|||
|
|
* via Next's client-side router.
|
|||
|
|
*/
|
|||
|
|
export interface BreadcrumbHintCrumb {
|
|||
|
|
label: string;
|
|||
|
|
href?: string;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface BreadcrumbHint {
|
|||
|
|
parents: BreadcrumbHintCrumb[];
|
|||
|
|
current: string;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
interface BreadcrumbStore {
|
|||
|
|
hints: Record<string, BreadcrumbHint>;
|
|||
|
|
setHint: (pathname: string, hint: BreadcrumbHint) => void;
|
|||
|
|
clearHint: (pathname: string) => void;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export const useBreadcrumbStore = create<BreadcrumbStore>((set) => ({
|
|||
|
|
hints: {},
|
|||
|
|
setHint: (pathname, hint) =>
|
|||
|
|
set((state) => ({
|
|||
|
|
hints: { ...state.hints, [pathname]: hint },
|
|||
|
|
})),
|
|||
|
|
clearHint: (pathname) =>
|
|||
|
|
set((state) => {
|
|||
|
|
const next = { ...state.hints };
|
|||
|
|
delete next[pathname];
|
|||
|
|
return { hints: next };
|
|||
|
|
}),
|
|||
|
|
}));
|