import { ref, Ref, reactive, inject, provide, onUnmounted, } from 'vue'; import { ITreeNode, IBlockData, } from './types'; export const SymBlockTree= Symbol('Schlechtenburg block tree'); export const SymBlockTreeRegister = Symbol('Schlechtenburg block tree register'); export const SymBlockTreeUnregister = Symbol('Schlechtenburg block tree unregister'); export const 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 register = (block: IBlockData, index: number = 0) => { if (!block.id) { throw new Error(`Cannot register a block without an id: ${JSON.stringify(block)}`); } 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, }; };