From d0d6508ae3682bccd57086ade8b85aff716d5594 Mon Sep 17 00:00:00 2001 From: mathuo <6710312+mathuo@users.noreply.github.com> Date: Wed, 10 Jan 2024 22:23:35 +0000 Subject: [PATCH 1/2] feat: render mode --- .../src/dockview/components/panel/content.ts | 53 +---------------- .../src/overlayRenderContainer.ts | 59 +++++++++++++------ .../sandboxes/iframe-dockview/src/app.tsx | 37 +++++++----- 3 files changed, 64 insertions(+), 85 deletions(-) diff --git a/packages/dockview-core/src/dockview/components/panel/content.ts b/packages/dockview-core/src/dockview/components/panel/content.ts index 6199c9a32..35485f9fd 100644 --- a/packages/dockview-core/src/dockview/components/panel/content.ts +++ b/packages/dockview-core/src/dockview/components/panel/content.ts @@ -178,58 +178,7 @@ export class ContentContainer return; } - const renderer = panel.api.renderer; - - if ( - this.panel && - this.panel.view.content.element.parentElement === this._element - ) { - /** - * If the currently attached panel is mounted directly to the content then remove it - */ - this._element.removeChild(this.panel.view.content.element); - } - - this.panel = panel; - - let container: HTMLElement; - - switch (renderer) { - case 'always': - container = - this.accessor.overlayRenderContainer.setReferenceContentContainer( - panel, - this - ); - break; - case 'onlyWhenVisibile': - this._element.appendChild(this.panel.view.content.element); - container = this._element; - break; - } - - const _onDidFocus = this.panel.view.content.onDidFocus; - const _onDidBlur = this.panel.view.content.onDidBlur; - - const disposable = new CompositeDisposable(); - const focusTracker = trackFocus(container); - - disposable.addDisposables( - focusTracker, - focusTracker.onDidFocus(() => this._onDidFocus.fire()), - focusTracker.onDidBlur(() => this._onDidBlur.fire()) - ); - - if (_onDidFocus) { - disposable.addDisposables( - _onDidFocus(() => this._onDidFocus.fire()) - ); - } - if (_onDidBlur) { - disposable.addDisposables(_onDidBlur(() => this._onDidBlur.fire())); - } - - this.disposable.value = disposable; + this.renderPanel(panel); } public layout(_width: number, _height: number): void { diff --git a/packages/dockview-core/src/overlayRenderContainer.ts b/packages/dockview-core/src/overlayRenderContainer.ts index cee392cb2..aa10c6b4f 100644 --- a/packages/dockview-core/src/overlayRenderContainer.ts +++ b/packages/dockview-core/src/overlayRenderContainer.ts @@ -1,7 +1,12 @@ import { DragAndDropObserver } from './dnd/dnd'; import { Droptarget } from './dnd/droptarget'; import { getDomNodePagePosition, toggleClass } from './dom'; -import { CompositeDisposable, Disposable, IDisposable } from './lifecycle'; +import { + CompositeDisposable, + Disposable, + IDisposable, + MutableDisposable, +} from './lifecycle'; import { IDockviewPanel } from './dockview/dockviewPanel'; export type DockviewPanelRenderer = 'onlyWhenVisibile' | 'always'; @@ -20,7 +25,12 @@ function createFocusableElement(): HTMLDivElement { export class OverlayRenderContainer extends CompositeDisposable { private readonly map: Record< string, - { disposable: IDisposable; element: HTMLElement } + { + panel: IDockviewPanel; + disposable: IDisposable; + destroy: IDisposable; + element: HTMLElement; + } > = {}; get allIds(): string[] { @@ -30,13 +40,14 @@ export class OverlayRenderContainer extends CompositeDisposable { constructor(private readonly element: HTMLElement) { super(); - this.addDisposables({ - dispose: () => { + this.addDisposables( + Disposable.from(() => { for (const value of Object.values(this.map)) { value.disposable.dispose(); + value.destroy.dispose(); } - }, - }); + }) + ); } remove(panel: IDockviewPanel): boolean { @@ -57,12 +68,14 @@ export class OverlayRenderContainer extends CompositeDisposable { element.className = 'dv-render-overlay'; this.map[panel.api.id] = { + panel, disposable: Disposable.NONE, + destroy: Disposable.NONE, + element, }; } - this.map[panel.api.id]?.disposable.dispose(); const focusContainer = this.map[panel.api.id].element; if (panel.view.content.element.parentElement !== focusContainer) { @@ -97,11 +110,17 @@ export class OverlayRenderContainer extends CompositeDisposable { focusContainer.style.display = panel.api.isVisible ? '' : 'none'; }; + const whenVisible = (func: (event: T) => void) => { + return (event: T) => { + if (!panel.api.isVisible) { + return; + } + + func(event); + }; + }; + const disposable = new CompositeDisposable( - /** - * since container is positioned absoutely we must explicitly forward - * the dnd events for the expect behaviours to continue to occur in terms of dnd - */ new DragAndDropObserver(focusContainer, { onDragEnd: (e) => { referenceContainer.dropTarget.dnd.onDragEnd(e); @@ -119,6 +138,10 @@ export class OverlayRenderContainer extends CompositeDisposable { referenceContainer.dropTarget.dnd.onDragOver(e); }, }), + /** + * since container is positioned absoutely we must explicitly forward + * the dnd events for the expect behaviours to continue to occur in terms of dnd + */ panel.api.onDidVisibilityChange((event) => { /** * Control the visibility of the content, however even when not visible (display: none) @@ -133,15 +156,14 @@ export class OverlayRenderContainer extends CompositeDisposable { } resize(); - }), - { - dispose: () => { - focusContainer.removeChild(panel.view.content.element); - this.element.removeChild(focusContainer); - }, - } + }) ); + this.map[panel.api.id].destroy = Disposable.from(() => { + focusContainer.removeChild(panel.view.content.element); + this.element.removeChild(focusContainer); + }); + queueMicrotask(() => { if (this.isDisposed) { return; @@ -155,6 +177,7 @@ export class OverlayRenderContainer extends CompositeDisposable { visibilityChanged(); }); + this.map[panel.api.id].disposable.dispose(); this.map[panel.api.id].disposable = disposable; return focusContainer; diff --git a/packages/docs/sandboxes/iframe-dockview/src/app.tsx b/packages/docs/sandboxes/iframe-dockview/src/app.tsx index 503857b24..2b200ab12 100644 --- a/packages/docs/sandboxes/iframe-dockview/src/app.tsx +++ b/packages/docs/sandboxes/iframe-dockview/src/app.tsx @@ -7,21 +7,26 @@ import * as React from 'react'; import { HoistedDockviewPanel } from './hoistedDockviewPanel'; const components = { - iframeComponent: HoistedDockviewPanel( - (props: IDockviewPanelProps<{ color: string }>) => { - return ( -