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);