From 8604b500863307acbd529f46cdbe05e3a245c368 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Mon, 10 Jun 2024 19:24:28 +0400 Subject: [PATCH] Provide symbol instance detach --- src/dom_components/index.ts | 5 +++-- src/dom_components/model/SymbolUtils.ts | 15 ++++++++++++++- src/dom_components/model/Symbols.ts | 10 ++++++++++ test/specs/dom_components/model/Symbols.ts | 21 +++++++++++++++++++++ 4 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 src/dom_components/model/Symbols.ts diff --git a/src/dom_components/index.ts b/src/dom_components/index.ts index cf2dd5801..cd20b864c 100644 --- a/src/dom_components/index.ts +++ b/src/dom_components/index.ts @@ -104,6 +104,7 @@ import ComponentsView from './view/ComponentsView'; import ComponentHead, { type as typeHead } from './model/ComponentHead'; import { getSymbolMain, getSymbolInstances, getSymbolsToUpdate, isSymbolMain } from './model/SymbolUtils'; import { SymbolInfo } from './types'; +import Symbols from './model/Symbols'; export type ComponentEvent = | 'component:create' @@ -297,7 +298,7 @@ export default class ComponentManager extends ItemManagerModule symb && !isString(symb)); } - return symbs; + return symbs || undefined; }; export const isSymbolOverride = (symbol?: Component, prop = '') => { @@ -105,6 +105,19 @@ export const getSymbolTop = (symbol: Component, opts?: any) => { return result; }; +export const detachSymbolInstance = (symbol: Component, opts: { skipRefs?: boolean } = {}) => { + const symbolMain = getSymbolMain(symbol); + const symbs = symbolMain && getSymbolInstances(symbolMain); + !opts.skipRefs && + symbs && + symbolMain.set( + keySymbols, + symbs.filter(s => s !== symbol) + ); + symbol.set(keySymbol, 0); + symbol.components().forEach(s => detachSymbolInstance(s, opts)); +}; + export const logSymbol = (symb: Component, type: string, toUp: Component[], opts: any = {}) => { const symbol = getSymbolMain(symb); const symbols = getSymbolInstances(symb); diff --git a/src/dom_components/model/Symbols.ts b/src/dom_components/model/Symbols.ts new file mode 100644 index 000000000..3a3abb37c --- /dev/null +++ b/src/dom_components/model/Symbols.ts @@ -0,0 +1,10 @@ +import Component from './Component'; +import Components from './Components'; +import { detachSymbolInstance, getSymbolInstances } from './SymbolUtils'; + +export default class Symbols extends Components { + removeChildren(removed: Component, coll?: Components, opts: any = {}) { + super.removeChildren(removed, coll, opts); + getSymbolInstances(removed)?.forEach(i => detachSymbolInstance(i, { skipRefs: true })); + } +} diff --git a/test/specs/dom_components/model/Symbols.ts b/test/specs/dom_components/model/Symbols.ts index 85256e54b..361a593c1 100644 --- a/test/specs/dom_components/model/Symbols.ts +++ b/test/specs/dom_components/model/Symbols.ts @@ -189,6 +189,27 @@ describe('Symbols', () => { expect(toHTML(comp2)).toBe(toHTML(symbol)); }); + test('When symbol is removed, all instances are detached', () => { + const comp = wrapper.append(compMultipleNodes)[0]; + const symbol = createSymbol(comp); + + [comp, ...comp.components().models].forEach(i => { + expect(getSymbolInfo(i).isInstance).toBe(true); + }); + + symbol.remove(); + + [comp, ...comp.components().models].forEach(i => { + expect(getSymbolInfo(i)).toEqual({ + isSymbol: false, + isMain: false, + isInstance: false, + instances: [], + relatives: [], + }); + }); + }); + test('Symbols and instances are correctly serialized', () => { const comp = wrapper.append(simpleComp)[0]; const symbol = createSymbol(comp);