a tool for shared writing and social publishing
1import { Block } from "components/Blocks/Block";
2import { create } from "zustand";
3import { combine, createJSONStorage, persist } from "zustand/middleware";
4
5type SelectedBlock = Pick<Block, "value" | "parent">;
6export const useUIState = create(
7 combine(
8 {
9 lastUsedHighlight: "1" as "1" | "2" | "3",
10 focusedEntity: null as
11 | { entityType: "page"; entityID: string }
12 | { entityType: "block"; entityID: string; parent: string }
13 | null,
14 foldedBlocks: [] as string[],
15 openPages: [] as string[],
16 selectedBlocks: [] as SelectedBlock[],
17 openPopover: null as string | null,
18 },
19 (set) => ({
20 setOpenPopover: (id: string | null) => {
21 set({ openPopover: id });
22 },
23 toggleFold: (entityID: string) => {
24 set((state) => {
25 return {
26 foldedBlocks: state.foldedBlocks.includes(entityID)
27 ? state.foldedBlocks.filter((b) => b !== entityID)
28 : [...state.foldedBlocks, entityID],
29 };
30 });
31 },
32 openPage: (parent: string, page: string) =>
33 set((state) => {
34 let parentPosition = state.openPages.findIndex((s) => s == parent);
35 return {
36 openPages:
37 parentPosition === -1
38 ? [page]
39 : [...state.openPages.slice(0, parentPosition + 1), page],
40 };
41 }),
42 closePage: (pages: string | string[]) =>
43 set((s) => ({
44 openPages: s.openPages.filter((c) => ![pages].flat().includes(c)),
45 })),
46 setFocusedBlock: (
47 b:
48 | { entityType: "page"; entityID: string }
49 | { entityType: "block"; entityID: string; parent: string }
50 | null,
51 ) => set(() => ({ focusedEntity: b })),
52 setSelectedBlock: (block: SelectedBlock) =>
53 set((state) => {
54 return { ...state, selectedBlocks: [block] };
55 }),
56 setSelectedBlocks: (blocks: SelectedBlock[]) =>
57 set((state) => {
58 return { ...state, selectedBlocks: blocks };
59 }),
60 addBlockToSelection: (block: SelectedBlock) =>
61 set((state) => {
62 if (state.selectedBlocks.find((b) => b.value === block.value))
63 return state;
64 return { ...state, selectedBlocks: [...state.selectedBlocks, block] };
65 }),
66 removeBlockFromSelection: (block: { value: string }) =>
67 set((state) => {
68 return {
69 ...state,
70 selectedBlocks: state.selectedBlocks.filter(
71 (f) => f.value !== block.value,
72 ),
73 };
74 }),
75 }),
76 ),
77);