import { ref, Ref, reactive, inject, provide, onUnmounted, } from 'vue'; import { ITreeNode, IBlockData, } from './types'; import { useDynamicBlocks } from './use-dynamic-blocks'; import { SbMode } from './mode'; export const SymBlockTree= Symbol('Schlechtenburg block tree'); export const SymBlockTreeRegister = Symbol('Schlechtenburg block tree register'); export const SymBlockTreeUnregister = Symbol('Schlechtenburg block tree unregister'); export function useBlockTree() { const blockTree: Ref = inject(SymBlockTree, ref(null)); const registerWithParent = inject(SymBlockTreeRegister, (_b: ITreeNode, _i: number) => {}); const unregisterWithParent = inject(SymBlockTreeUnregister, (_b: ITreeNode) => {}); const self: ITreeNode = reactive({ id: '', name: '', icon: '', children: [], }); // Provide a registration function to child blocks provide(SymBlockTreeRegister, (block: ITreeNode, index:number = -1) => { if (self.children.find((child: ITreeNode) => child.id === block.id)) { return; } if (index < 0) { } const normalizedIndex = index < 0 ? 0 : index; self.children =[ ...self.children.slice(0, normalizedIndex), block, ...self.children.slice(normalizedIndex), ]; }); // Provide an unregistration function to child blocks provide(SymBlockTreeUnregister, ({ id }: ITreeNode) => { self.children = self.children.filter((child: ITreeNode) => child.id !== id); }); const { mode } = useDynamicBlocks(); const register = (block: IBlockData, index: number = 0) => { if (!block.id) { throw new Error(`Cannot register a block without an id: ${JSON.stringify(block)}`); } if (mode.value !== SbMode.Edit) { console.warn('Ignoring block tree registration requests outside of edit mode.'); return; } self.id = block.id; self.name = block.name; // Register ourselves at the parent block registerWithParent(self, index); } // Unregister from parent when we get destroyed onUnmounted(() => { if (self.id) { unregisterWithParent(self); } }); return { blockTree, register, }; }