import { Block } from "components/Blocks/Block"; import { create } from "zustand"; import { combine, createJSONStorage, persist } from "zustand/middleware"; type SelectedBlock = Pick; export type EditorIframePage = { type: "iframe"; url: string }; export type EditorOpenPage = string | EditorIframePage; export const getEditorPageKey = (page: EditorOpenPage): string => typeof page === "string" ? page : `iframe:${page.url}`; export const useUIState = create( combine( { lastUsedHighlight: "1" as "1" | "2" | "3", focusedEntity: null as | { entityType: "page"; entityID: string } | { entityType: "block"; entityID: string; parent: string } | { entityType: "footnote"; entityID: string; parent: string } | null, foldedBlocks: [] as string[], openPages: [] as EditorOpenPage[], selectedBlocks: [] as SelectedBlock[], openPopover: null as string | null, }, (set) => ({ setOpenPopover: (id: string | null) => { set({ openPopover: id }); }, toggleFold: (entityID: string) => { set((state) => { return { foldedBlocks: state.foldedBlocks.includes(entityID) ? state.foldedBlocks.filter((b) => b !== entityID) : [...state.foldedBlocks, entityID], }; }); }, openPage: (parent: EditorOpenPage, page: EditorOpenPage) => set((state) => { let parentKey = getEditorPageKey(parent); let parentPosition = state.openPages.findIndex( (s) => getEditorPageKey(s) === parentKey, ); return { openPages: parentPosition === -1 ? [page] : [...state.openPages.slice(0, parentPosition + 1), page], }; }), closePage: (pages: EditorOpenPage | EditorOpenPage[]) => set((s) => { let keys = [pages].flat().map(getEditorPageKey); return { openPages: s.openPages.filter( (c) => !keys.includes(getEditorPageKey(c)), ), }; }), setFocusedBlock: ( b: | { entityType: "page"; entityID: string } | { entityType: "block"; entityID: string; parent: string } | { entityType: "footnote"; entityID: string; parent: string } | null, ) => set(() => ({ focusedEntity: b })), setSelectedBlock: (block: SelectedBlock) => set((state) => { return { ...state, selectedBlocks: [block] }; }), setSelectedBlocks: (blocks: SelectedBlock[]) => set((state) => { return { ...state, selectedBlocks: blocks }; }), addBlockToSelection: (block: SelectedBlock) => set((state) => { if (state.selectedBlocks.find((b) => b.value === block.value)) return state; return { ...state, selectedBlocks: [...state.selectedBlocks, block] }; }), removeBlockFromSelection: (block: { value: string }) => set((state) => { return { ...state, selectedBlocks: state.selectedBlocks.filter( (f) => f.value !== block.value, ), }; }), }), ), );