a tool for shared writing and social publishing
at feature/footnotes 79 lines 2.8 kB view raw
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 | { entityType: "footnote"; entityID: string; parent: string } 14 | null, 15 foldedBlocks: [] as string[], 16 openPages: [] as string[], 17 selectedBlocks: [] as SelectedBlock[], 18 openPopover: null as string | null, 19 }, 20 (set) => ({ 21 setOpenPopover: (id: string | null) => { 22 set({ openPopover: id }); 23 }, 24 toggleFold: (entityID: string) => { 25 set((state) => { 26 return { 27 foldedBlocks: state.foldedBlocks.includes(entityID) 28 ? state.foldedBlocks.filter((b) => b !== entityID) 29 : [...state.foldedBlocks, entityID], 30 }; 31 }); 32 }, 33 openPage: (parent: string, page: string) => 34 set((state) => { 35 let parentPosition = state.openPages.findIndex((s) => s == parent); 36 return { 37 openPages: 38 parentPosition === -1 39 ? [page] 40 : [...state.openPages.slice(0, parentPosition + 1), page], 41 }; 42 }), 43 closePage: (pages: string | string[]) => 44 set((s) => ({ 45 openPages: s.openPages.filter((c) => ![pages].flat().includes(c)), 46 })), 47 setFocusedBlock: ( 48 b: 49 | { entityType: "page"; entityID: string } 50 | { entityType: "block"; entityID: string; parent: string } 51 | { entityType: "footnote"; entityID: string; parent: string } 52 | null, 53 ) => set(() => ({ focusedEntity: b })), 54 setSelectedBlock: (block: SelectedBlock) => 55 set((state) => { 56 return { ...state, selectedBlocks: [block] }; 57 }), 58 setSelectedBlocks: (blocks: SelectedBlock[]) => 59 set((state) => { 60 return { ...state, selectedBlocks: blocks }; 61 }), 62 addBlockToSelection: (block: SelectedBlock) => 63 set((state) => { 64 if (state.selectedBlocks.find((b) => b.value === block.value)) 65 return state; 66 return { ...state, selectedBlocks: [...state.selectedBlocks, block] }; 67 }), 68 removeBlockFromSelection: (block: { value: string }) => 69 set((state) => { 70 return { 71 ...state, 72 selectedBlocks: state.selectedBlocks.filter( 73 (f) => f.value !== block.value, 74 ), 75 }; 76 }), 77 }), 78 ), 79);