diff --git a/packages/dockview-core/src/dockview/dockviewComponent.ts b/packages/dockview-core/src/dockview/dockviewComponent.ts index a9a285b9c..dad15a6e2 100644 --- a/packages/dockview-core/src/dockview/dockviewComponent.ts +++ b/packages/dockview-core/src/dockview/dockviewComponent.ts @@ -800,7 +800,7 @@ export class DockviewComponent group = item; const popoutReferenceGroupId = this._popoutGroups.find( - (_) => _.popoutGroup === group + (_) => _.popoutGroup.id === group.id )?.referenceGroup; const popoutReferenceGroup = popoutReferenceGroupId ? this.getPanel(popoutReferenceGroupId) @@ -1715,7 +1715,7 @@ export class DockviewComponent if (group.api.location.type === 'floating') { const floatingGroup = this._floatingGroups.find( - (_) => _.group === group + (_) => _.group.id === group.id ); if (floatingGroup) { @@ -1728,7 +1728,7 @@ export class DockviewComponent remove(this._floatingGroups, floatingGroup); floatingGroup.dispose(); - if (!options?.skipActive && this._activeGroup === group) { + if (!options?.skipActive && this._activeGroup?.id === group.id) { const groups = Array.from(this._groups.values()); this.doSetGroupAndPanelActive( @@ -1744,7 +1744,7 @@ export class DockviewComponent if (group.api.location.type === 'popout') { const selectedGroup = this._popoutGroups.find( - (_) => _.popoutGroup === group + (_) => _.popoutGroup.id === group.id ); if (selectedGroup) { @@ -1771,7 +1771,7 @@ export class DockviewComponent this.doSetGroupAndPanelActive(removedGroup); } - if (!options?.skipActive && this._activeGroup === group) { + if (!options?.skipActive && this._activeGroup?.id === group.id) { const groups = Array.from(this._groups.values()); this.doSetGroupAndPanelActive( @@ -1857,11 +1857,6 @@ export class DockviewComponent throw new Error(`No panel with id ${sourceItemId}`); } - if (sourceGroup.model.size === 0) { - // remove the group and do not set a new group as active - this.doRemoveGroup(sourceGroup, { skipActive: true }); - } - this.movingLock(() => destinationGroup.model.openPanel(removedPanel, { index: destinationIndex, @@ -1870,6 +1865,11 @@ export class DockviewComponent ); this.doSetGroupAndPanelActive(destinationGroup); + if (sourceGroup.model.size === 0) { + // remove the group and do not set a new group as active + this.doRemoveGroup(sourceGroup, { skipActive: true }); + } + this._onDidMovePanel.fire({ panel: removedPanel, from: sourceGroup, diff --git a/packages/dockview-vue/src/dockview/dockview.vue b/packages/dockview-vue/src/dockview/dockview.vue index 0290389ae..a03733360 100644 --- a/packages/dockview-vue/src/dockview/dockview.vue +++ b/packages/dockview-vue/src/dockview/dockview.vue @@ -15,6 +15,8 @@ import { onBeforeUnmount, markRaw, getCurrentInstance, + reactive, + mergeProps, } from 'vue'; import { VueHeaderActionsRenderer, @@ -22,7 +24,8 @@ import { VueWatermarkRenderer, findComponent, } from '../utils'; -import type { IDockviewVueProps, VueEvents } from './types'; +import type { IDockviewVueProps, VNodeType, VueEvents } from './types'; +import Tele from './teleport.vue' function extractCoreOptions(props: IDockviewVueProps): DockviewOptions { const coreOptions = (PROPERTY_KEYS as (keyof DockviewOptions)[]).reduce( @@ -174,8 +177,29 @@ onBeforeUnmount(() => { instance.value.dispose(); } }); + +const vnodes = reactive([]); + +defineExpose({ + add(item: VNodeType) { + vnodes.push(item) + }, + remove(key: symbol) { + const index = vnodes.findIndex(item => item.key === key); + if(index > -1) { + vnodes.splice(index, 1); + } + }, + update(key: symbol, props: Record) { + const item = vnodes.find(item => item.key === key); + if(item) { + item.props = mergeProps(item.props, props); + } + } +}) diff --git a/packages/dockview-vue/src/dockview/teleport.vue b/packages/dockview-vue/src/dockview/teleport.vue new file mode 100644 index 000000000..7e64d3084 --- /dev/null +++ b/packages/dockview-vue/src/dockview/teleport.vue @@ -0,0 +1,13 @@ + + + + diff --git a/packages/dockview-vue/src/dockview/types.ts b/packages/dockview-vue/src/dockview/types.ts index ca2e09778..68a86754b 100644 --- a/packages/dockview-vue/src/dockview/types.ts +++ b/packages/dockview-vue/src/dockview/types.ts @@ -1,4 +1,5 @@ import { type DockviewOptions, type DockviewReadyEvent } from 'dockview-core'; +import type { Component } from 'vue'; export interface VueProps { watermarkComponent?: string; @@ -13,3 +14,10 @@ export type VueEvents = { }; export type IDockviewVueProps = DockviewOptions & VueProps; + +export type VNodeType = { + key: symbol; + component: Component; + props: any; + target: HTMLElement; +} diff --git a/packages/dockview-vue/src/utils.ts b/packages/dockview-vue/src/utils.ts index a4e18a5fe..ccfe7c083 100644 --- a/packages/dockview-vue/src/utils.ts +++ b/packages/dockview-vue/src/utils.ts @@ -21,6 +21,7 @@ import { cloneVNode, type DefineComponent, type ComponentInternalInstance, + markRaw, } from 'vue'; export type ComponentInterface = ComponentOptionsBase< @@ -69,22 +70,32 @@ export function mountVueComponent>( props: T, element: HTMLElement ) { - let vNode = createVNode(component, Object.freeze(props)); + // let vNode = createVNode(component, Object.freeze(props)); - vNode.appContext = parent.appContext; + // vNode.appContext = parent.appContext; - render(vNode, element); + // render(vNode, element); - let runningProps = props; + // let runningProps = props; + + const key = Symbol(); + parent.exposed!.add({ + key, + component: markRaw(component), + target: markRaw(element), + props, + }); return { update: (newProps: any) => { - runningProps = { ...props, ...newProps }; - vNode = cloneVNode(vNode, runningProps); - render(vNode, element); + // runningProps = { ...props, ...newProps }; + // vNode = cloneVNode(vNode, runningProps); + // render(vNode, element); + parent.exposed!.update(key, newProps); }, dispose: () => { - render(null, element); + // render(null, element); + parent.exposed!.remove(key); }, }; } diff --git a/packages/dockview-vue/tsconfig.app.json b/packages/dockview-vue/tsconfig.app.json index 460449579..834b5f217 100644 --- a/packages/dockview-vue/tsconfig.app.json +++ b/packages/dockview-vue/tsconfig.app.json @@ -4,6 +4,7 @@ "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], "exclude": ["src/**/__tests__/*", "src/**/*.cy.ts"], "compilerOptions": { + "jsxImportSource": "vue", "composite": true, "baseUrl": "." }