Merge pull request #227 from mathuo/226-move-resizeobserver-logic-into-dockview-core

feat: move resizeObserver logic into dockview-core
This commit is contained in:
mathuo 2023-03-26 19:51:03 +01:00 committed by GitHub
commit e95777a6a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 307 additions and 265 deletions

View File

@ -3,22 +3,12 @@ import {
GroupPanelPartInitParameters, GroupPanelPartInitParameters,
IContentRenderer, IContentRenderer,
ITabRenderer, ITabRenderer,
GroupPanelUpdateEvent,
GroupviewPanelState,
IGroupPanelInitParameters,
} from '../../dockview/types'; } from '../../dockview/types';
import { PanelUpdateEvent } from '../../panel/types'; import { PanelUpdateEvent } from '../../panel/types';
import { Orientation } from '../../splitview/splitview'; import { Orientation } from '../../splitview/splitview';
import { CompositeDisposable } from '../../lifecycle'; import { CompositeDisposable } from '../../lifecycle';
import { Emitter } from '../../events'; import { Emitter } from '../../events';
import { IDockviewPanel } from '../../dockview/dockviewPanel'; import { IDockviewPanel } from '../../dockview/dockviewPanel';
import {
DockviewPanelApi,
DockviewPanelApiImpl,
} from '../../api/dockviewPanelApi';
import { IDockviewPanelModel } from '../../dockview/dockviewPanelModel';
import { DockviewPanelModelMock } from '../__mocks__/mockDockviewPanelMode';
import { DefaultTab } from '../../dockview/components/tab/defaultTab';
import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel'; import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel';
class PanelContentPartTest implements IContentRenderer { class PanelContentPartTest implements IContentRenderer {
@ -100,7 +90,8 @@ describe('dockviewComponent', () => {
beforeEach(() => { beforeEach(() => {
container = document.createElement('div'); container = document.createElement('div');
dockview = new DockviewComponent(container, { dockview = new DockviewComponent({
parentElement: container,
components: { components: {
default: PanelContentPartTest, default: PanelContentPartTest,
}, },
@ -1037,7 +1028,8 @@ describe('dockviewComponent', () => {
test('panel is disposed of when closed', () => { test('panel is disposed of when closed', () => {
const container = document.createElement('div'); const container = document.createElement('div');
const dockview = new DockviewComponent(container, { const dockview = new DockviewComponent({
parentElement: container,
components: { default: PanelContentPartTest }, components: { default: PanelContentPartTest },
}); });
@ -1061,7 +1053,8 @@ describe('dockviewComponent', () => {
test('can add panel of same id if already removed', () => { test('can add panel of same id if already removed', () => {
const container = document.createElement('div'); const container = document.createElement('div');
const dockview = new DockviewComponent(container, { const dockview = new DockviewComponent({
parentElement: container,
components: { default: PanelContentPartTest }, components: { default: PanelContentPartTest },
}); });
@ -1095,7 +1088,8 @@ describe('dockviewComponent', () => {
test('panel is disposed of when removed', () => { test('panel is disposed of when removed', () => {
const container = document.createElement('div'); const container = document.createElement('div');
const dockview = new DockviewComponent(container, { const dockview = new DockviewComponent({
parentElement: container,
components: { default: PanelContentPartTest }, components: { default: PanelContentPartTest },
}); });
@ -1119,7 +1113,8 @@ describe('dockviewComponent', () => {
test('panel is not disposed of when moved to a new group', () => { test('panel is not disposed of when moved to a new group', () => {
const container = document.createElement('div'); const container = document.createElement('div');
const dockview = new DockviewComponent(container, { const dockview = new DockviewComponent({
parentElement: container,
components: { components: {
default: PanelContentPartTest, default: PanelContentPartTest,
}, },
@ -1160,7 +1155,8 @@ describe('dockviewComponent', () => {
test('panel is not disposed of when moved within another group', () => { test('panel is not disposed of when moved within another group', () => {
const container = document.createElement('div'); const container = document.createElement('div');
const dockview = new DockviewComponent(container, { const dockview = new DockviewComponent({
parentElement: container,
components: { components: {
default: PanelContentPartTest, default: PanelContentPartTest,
}, },
@ -1201,7 +1197,8 @@ describe('dockviewComponent', () => {
test('panel is not disposed of when moved within another group', () => { test('panel is not disposed of when moved within another group', () => {
const container = document.createElement('div'); const container = document.createElement('div');
const dockview = new DockviewComponent(container, { const dockview = new DockviewComponent({
parentElement: container,
components: { components: {
default: PanelContentPartTest, default: PanelContentPartTest,
}, },
@ -1241,7 +1238,8 @@ describe('dockviewComponent', () => {
test('panel is disposed of when group is disposed', () => { test('panel is disposed of when group is disposed', () => {
const container = document.createElement('div'); const container = document.createElement('div');
const dockview = new DockviewComponent(container, { const dockview = new DockviewComponent({
parentElement: container,
components: { components: {
default: PanelContentPartTest, default: PanelContentPartTest,
}, },
@ -1275,7 +1273,8 @@ describe('dockviewComponent', () => {
test('panel is disposed of when component is disposed', () => { test('panel is disposed of when component is disposed', () => {
const container = document.createElement('div'); const container = document.createElement('div');
const dockview = new DockviewComponent(container, { const dockview = new DockviewComponent({
parentElement: container,
components: { components: {
default: PanelContentPartTest, default: PanelContentPartTest,
}, },
@ -1309,7 +1308,8 @@ describe('dockviewComponent', () => {
test('panel is disposed of when from JSON is called', () => { test('panel is disposed of when from JSON is called', () => {
const container = document.createElement('div'); const container = document.createElement('div');
const dockview = new DockviewComponent(container, { const dockview = new DockviewComponent({
parentElement: container,
components: { components: {
default: PanelContentPartTest, default: PanelContentPartTest,
}, },
@ -1353,7 +1353,8 @@ describe('dockviewComponent', () => {
test('move entire group into another group', () => { test('move entire group into another group', () => {
const container = document.createElement('div'); const container = document.createElement('div');
const dockview = new DockviewComponent(container, { const dockview = new DockviewComponent({
parentElement: container,
components: { default: PanelContentPartTest }, components: { default: PanelContentPartTest },
}); });
@ -1566,7 +1567,8 @@ describe('dockviewComponent', () => {
test('load a layout with a non-existant tab id', () => { test('load a layout with a non-existant tab id', () => {
const container = document.createElement('div'); const container = document.createElement('div');
const dockview = new DockviewComponent(container, { const dockview = new DockviewComponent({
parentElement: container,
components: { components: {
default: PanelContentPartTest, default: PanelContentPartTest,
}, },
@ -1652,7 +1654,8 @@ describe('dockviewComponent', () => {
test('load and persist layout with custom tab header', () => { test('load and persist layout with custom tab header', () => {
const container = document.createElement('div'); const container = document.createElement('div');
const dockview = new DockviewComponent(container, { const dockview = new DockviewComponent({
parentElement: container,
components: { components: {
default: PanelContentPartTest, default: PanelContentPartTest,
}, },
@ -1760,7 +1763,8 @@ describe('dockviewComponent', () => {
test('#2', () => { test('#2', () => {
const container = document.createElement('div'); const container = document.createElement('div');
const dockview = new DockviewComponent(container, { const dockview = new DockviewComponent({
parentElement: container,
components: { components: {
default: PanelContentPartTest, default: PanelContentPartTest,
}, },
@ -1846,7 +1850,8 @@ describe('dockviewComponent', () => {
test('orthogonal realigment #1', () => { test('orthogonal realigment #1', () => {
const container = document.createElement('div'); const container = document.createElement('div');
const dockview = new DockviewComponent(container, { const dockview = new DockviewComponent({
parentElement: container,
components: { components: {
default: PanelContentPartTest, default: PanelContentPartTest,
}, },
@ -1951,7 +1956,8 @@ describe('dockviewComponent', () => {
test('orthogonal realigment #2', () => { test('orthogonal realigment #2', () => {
const container = document.createElement('div'); const container = document.createElement('div');
const dockview = new DockviewComponent(container, { const dockview = new DockviewComponent({
parentElement: container,
components: { components: {
default: PanelContentPartTest, default: PanelContentPartTest,
}, },
@ -2091,7 +2097,8 @@ describe('dockviewComponent', () => {
test('orthogonal realigment #3', () => { test('orthogonal realigment #3', () => {
const container = document.createElement('div'); const container = document.createElement('div');
const dockview = new DockviewComponent(container, { const dockview = new DockviewComponent({
parentElement: container,
components: { components: {
default: PanelContentPartTest, default: PanelContentPartTest,
}, },
@ -2218,7 +2225,8 @@ describe('dockviewComponent', () => {
test('that a empty component has no groups', () => { test('that a empty component has no groups', () => {
const container = document.createElement('div'); const container = document.createElement('div');
const dockview = new DockviewComponent(container, { const dockview = new DockviewComponent({
parentElement: container,
components: { components: {
default: PanelContentPartTest, default: PanelContentPartTest,
}, },
@ -2234,7 +2242,8 @@ describe('dockviewComponent', () => {
test('that deserializing an empty layout has zero groups and a watermark', () => { test('that deserializing an empty layout has zero groups and a watermark', () => {
const container = document.createElement('div'); const container = document.createElement('div');
const dockview = new DockviewComponent(container, { const dockview = new DockviewComponent({
parentElement: container,
components: { components: {
default: PanelContentPartTest, default: PanelContentPartTest,
}, },
@ -2273,7 +2282,8 @@ describe('dockviewComponent', () => {
test('empty', () => { test('empty', () => {
const container = document.createElement('div'); const container = document.createElement('div');
const dockview = new DockviewComponent(container, { const dockview = new DockviewComponent({
parentElement: container,
components: { components: {
default: PanelContentPartTest, default: PanelContentPartTest,
}, },

View File

@ -70,8 +70,8 @@ class TestPanel implements IGridPanelView {
} }
class ClassUnderTest extends BaseGrid<TestPanel> { class ClassUnderTest extends BaseGrid<TestPanel> {
constructor(element: HTMLElement, options: BaseGridOptions) { constructor(options: BaseGridOptions) {
super(element, options); super(options);
} }
doRemoveGroup( doRemoveGroup(
@ -108,7 +108,8 @@ class ClassUnderTest extends BaseGrid<TestPanel> {
describe('baseComponentGridview', () => { describe('baseComponentGridview', () => {
test('can add group', () => { test('can add group', () => {
const cut = new ClassUnderTest(document.createElement('div'), { const cut = new ClassUnderTest({
parentElement: document.createElement('div'),
orientation: Orientation.HORIZONTAL, orientation: Orientation.HORIZONTAL,
proportionalLayout: true, proportionalLayout: true,
}); });

View File

@ -33,7 +33,8 @@ describe('gridview', () => {
}); });
test('added views are visible by default', () => { test('added views are visible by default', () => {
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: false, proportionalLayout: false,
orientation: Orientation.VERTICAL, orientation: Orientation.VERTICAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -52,7 +53,8 @@ describe('gridview', () => {
}); });
test('remove panel', () => { test('remove panel', () => {
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: false, proportionalLayout: false,
orientation: Orientation.VERTICAL, orientation: Orientation.VERTICAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -82,7 +84,8 @@ describe('gridview', () => {
}); });
test('active panel', () => { test('active panel', () => {
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: false, proportionalLayout: false,
orientation: Orientation.VERTICAL, orientation: Orientation.VERTICAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -142,7 +145,8 @@ describe('gridview', () => {
}); });
test('deserialize and serialize a layout', () => { test('deserialize and serialize a layout', () => {
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: false, proportionalLayout: false,
orientation: Orientation.VERTICAL, orientation: Orientation.VERTICAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -269,7 +273,8 @@ describe('gridview', () => {
}); });
test('toJSON shouldnt fire any layout events', () => { test('toJSON shouldnt fire any layout events', () => {
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: false, proportionalLayout: false,
orientation: Orientation.VERTICAL, orientation: Orientation.VERTICAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -305,7 +310,8 @@ describe('gridview', () => {
}); });
test('gridview events', () => { test('gridview events', () => {
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: false, proportionalLayout: false,
orientation: Orientation.VERTICAL, orientation: Orientation.VERTICAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -428,7 +434,8 @@ describe('gridview', () => {
test('dispose of gridviewComponent', () => { test('dispose of gridviewComponent', () => {
expect(container.childNodes.length).toBe(0); expect(container.childNodes.length).toBe(0);
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: false, proportionalLayout: false,
orientation: Orientation.VERTICAL, orientation: Orientation.VERTICAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -457,7 +464,8 @@ describe('gridview', () => {
}); });
test('#1/VERTICAL', () => { test('#1/VERTICAL', () => {
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: true, proportionalLayout: true,
orientation: Orientation.VERTICAL, orientation: Orientation.VERTICAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -513,7 +521,8 @@ describe('gridview', () => {
}); });
test('#2/HORIZONTAL', () => { test('#2/HORIZONTAL', () => {
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: true, proportionalLayout: true,
orientation: Orientation.HORIZONTAL, orientation: Orientation.HORIZONTAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -571,7 +580,8 @@ describe('gridview', () => {
}); });
test('#3/HORIZONTAL', () => { test('#3/HORIZONTAL', () => {
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: true, proportionalLayout: true,
orientation: Orientation.HORIZONTAL, orientation: Orientation.HORIZONTAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -647,7 +657,8 @@ describe('gridview', () => {
}); });
test('#4/HORIZONTAL', () => { test('#4/HORIZONTAL', () => {
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: true, proportionalLayout: true,
orientation: Orientation.HORIZONTAL, orientation: Orientation.HORIZONTAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -741,7 +752,8 @@ describe('gridview', () => {
}); });
test('#5/VERTICAL', () => { test('#5/VERTICAL', () => {
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: true, proportionalLayout: true,
orientation: Orientation.VERTICAL, orientation: Orientation.VERTICAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -835,7 +847,8 @@ describe('gridview', () => {
}); });
test('#5/VERTICAL/proportional/false', () => { test('#5/VERTICAL/proportional/false', () => {
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: false, proportionalLayout: false,
orientation: Orientation.VERTICAL, orientation: Orientation.VERTICAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -928,7 +941,8 @@ describe('gridview', () => {
}); });
test('#6/VERTICAL', () => { test('#6/VERTICAL', () => {
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: true, proportionalLayout: true,
orientation: Orientation.VERTICAL, orientation: Orientation.VERTICAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -1052,7 +1066,8 @@ describe('gridview', () => {
}); });
test('#7/VERTICAL layout first', () => { test('#7/VERTICAL layout first', () => {
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: true, proportionalLayout: true,
orientation: Orientation.VERTICAL, orientation: Orientation.VERTICAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -1176,7 +1191,8 @@ describe('gridview', () => {
}); });
test('#8/VERTICAL layout after', () => { test('#8/VERTICAL layout after', () => {
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: true, proportionalLayout: true,
orientation: Orientation.VERTICAL, orientation: Orientation.VERTICAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -1299,7 +1315,8 @@ describe('gridview', () => {
}); });
test('#9/HORIZONTAL', () => { test('#9/HORIZONTAL', () => {
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: true, proportionalLayout: true,
orientation: Orientation.HORIZONTAL, orientation: Orientation.HORIZONTAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -1421,7 +1438,8 @@ describe('gridview', () => {
}); });
test('#9/HORIZONTAL/proportional/false', () => { test('#9/HORIZONTAL/proportional/false', () => {
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: false, proportionalLayout: false,
orientation: Orientation.HORIZONTAL, orientation: Orientation.HORIZONTAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -1543,7 +1561,8 @@ describe('gridview', () => {
}); });
test('#10/HORIZONTAL scale x:1.5 y:2', () => { test('#10/HORIZONTAL scale x:1.5 y:2', () => {
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: true, proportionalLayout: true,
orientation: Orientation.HORIZONTAL, orientation: Orientation.HORIZONTAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -1670,7 +1689,8 @@ describe('gridview', () => {
}); });
test('panel is disposed of when component is disposed', () => { test('panel is disposed of when component is disposed', () => {
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: false, proportionalLayout: false,
orientation: Orientation.VERTICAL, orientation: Orientation.VERTICAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -1700,7 +1720,8 @@ describe('gridview', () => {
}); });
test('panel is disposed of when removed', () => { test('panel is disposed of when removed', () => {
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: false, proportionalLayout: false,
orientation: Orientation.VERTICAL, orientation: Orientation.VERTICAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -1729,7 +1750,8 @@ describe('gridview', () => {
}); });
test('panel is disposed of when fromJSON is called', () => { test('panel is disposed of when fromJSON is called', () => {
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: false, proportionalLayout: false,
orientation: Orientation.VERTICAL, orientation: Orientation.VERTICAL,
components: { default: TestGridview }, components: { default: TestGridview },
@ -1767,7 +1789,8 @@ describe('gridview', () => {
test('fromJSON events should still fire', () => { test('fromJSON events should still fire', () => {
jest.useFakeTimers(); jest.useFakeTimers();
const gridview = new GridviewComponent(container, { const gridview = new GridviewComponent({
parentElement: container,
proportionalLayout: true, proportionalLayout: true,
orientation: Orientation.HORIZONTAL, orientation: Orientation.HORIZONTAL,
components: { default: TestGridview }, components: { default: TestGridview },

View File

@ -490,7 +490,8 @@ describe('groupview', () => {
}); });
test('that group is set on panel during onDidAddPanel event', () => { test('that group is set on panel during onDidAddPanel event', () => {
const cut = new DockviewComponent(document.createElement('div'), { const cut = new DockviewComponent({
parentElement: document.createElement('div'),
components: { components: {
component: TestContentPart, component: TestContentPart,
}, },
@ -505,14 +506,12 @@ describe('groupview', () => {
}); });
test('toJSON() default', () => { test('toJSON() default', () => {
const dockviewComponent = new DockviewComponent( const dockviewComponent = new DockviewComponent({
document.createElement('div'), parentElement: document.createElement('div'),
{ components: {
components: { component: TestContentPart,
component: TestContentPart, },
}, });
}
);
const cut = new DockviewGroupPanelModel( const cut = new DockviewGroupPanelModel(
document.createElement('div'), document.createElement('div'),
@ -530,14 +529,12 @@ describe('groupview', () => {
}); });
test('toJSON() locked and hideHeader', () => { test('toJSON() locked and hideHeader', () => {
const dockviewComponent = new DockviewComponent( const dockviewComponent = new DockviewComponent({
document.createElement('div'), parentElement: document.createElement('div'),
{ components: {
components: { component: TestContentPart,
component: TestContentPart, },
}, });
}
);
const cut = new DockviewGroupPanelModel( const cut = new DockviewGroupPanelModel(
document.createElement('div'), document.createElement('div'),
@ -560,14 +557,12 @@ describe('groupview', () => {
}); });
test("that openPanel with skipSetActive doesn't set panel to active", () => { test("that openPanel with skipSetActive doesn't set panel to active", () => {
const dockviewComponent = new DockviewComponent( const dockviewComponent = new DockviewComponent({
document.createElement('div'), parentElement: document.createElement('div'),
{ components: {
components: { component: TestContentPart,
component: TestContentPart, },
}, });
}
);
const groupviewContainer = document.createElement('div'); const groupviewContainer = document.createElement('div');
const cut = new DockviewGroupPanelModel( const cut = new DockviewGroupPanelModel(

View File

@ -48,4 +48,20 @@ describe('lifecycle', () => {
expect(d3.dispose).toHaveBeenCalledTimes(1); expect(d3.dispose).toHaveBeenCalledTimes(1);
expect(d4.dispose).toHaveBeenCalledTimes(1); expect(d4.dispose).toHaveBeenCalledTimes(1);
}); });
test('that isDisposed=true once CompositeDisposable is disposed', () => {
class Test extends CompositeDisposable {
checkIsDisposed(): boolean {
return this.isDisposed;
}
}
const cut = new Test();
expect(cut.checkIsDisposed()).toBeFalsy();
cut.dispose();
expect(cut.checkIsDisposed()).toBeTruthy();
});
}); });

View File

@ -71,7 +71,8 @@ describe('componentPaneview', () => {
test('vertical panels', () => { test('vertical panels', () => {
const disposables = new CompositeDisposable(); const disposables = new CompositeDisposable();
const paneview = new PaneviewComponent(container, { const paneview = new PaneviewComponent({
parentElement: container,
components: { components: {
testPanel: TestPanel, testPanel: TestPanel,
}, },
@ -141,7 +142,8 @@ describe('componentPaneview', () => {
}); });
test('serialization', () => { test('serialization', () => {
const paneview = new PaneviewComponent(container, { const paneview = new PaneviewComponent({
parentElement: container,
components: { components: {
testPanel: TestPanel, testPanel: TestPanel,
}, },
@ -249,7 +251,8 @@ describe('componentPaneview', () => {
}); });
test('toJSON shouldnt fire any layout events', () => { test('toJSON shouldnt fire any layout events', () => {
const paneview = new PaneviewComponent(container, { const paneview = new PaneviewComponent({
parentElement: container,
components: { components: {
testPanel: TestPanel, testPanel: TestPanel,
}, },
@ -280,7 +283,8 @@ describe('componentPaneview', () => {
test('dispose of paneviewComponent', () => { test('dispose of paneviewComponent', () => {
expect(container.childNodes.length).toBe(0); expect(container.childNodes.length).toBe(0);
const paneview = new PaneviewComponent(container, { const paneview = new PaneviewComponent({
parentElement: container,
components: { components: {
testPanel: TestPanel, testPanel: TestPanel,
}, },
@ -307,7 +311,8 @@ describe('componentPaneview', () => {
}); });
test('panel is disposed of when component is disposed', () => { test('panel is disposed of when component is disposed', () => {
const paneview = new PaneviewComponent(container, { const paneview = new PaneviewComponent({
parentElement: container,
components: { components: {
testPanel: TestPanel, testPanel: TestPanel,
}, },
@ -326,8 +331,8 @@ describe('componentPaneview', () => {
title: 'Panel 2', title: 'Panel 2',
}); });
const panel1 = paneview.getPanel('panel1'); const panel1 = paneview.getPanel('panel1')!;
const panel2 = paneview.getPanel('panel2'); const panel2 = paneview.getPanel('panel2')!;
const panel1Spy = jest.spyOn(panel1, 'dispose'); const panel1Spy = jest.spyOn(panel1, 'dispose');
const panel2Spy = jest.spyOn(panel2, 'dispose'); const panel2Spy = jest.spyOn(panel2, 'dispose');
@ -339,7 +344,8 @@ describe('componentPaneview', () => {
}); });
test('panel is disposed of when removed', () => { test('panel is disposed of when removed', () => {
const paneview = new PaneviewComponent(container, { const paneview = new PaneviewComponent({
parentElement: container,
components: { components: {
testPanel: TestPanel, testPanel: TestPanel,
}, },
@ -358,8 +364,8 @@ describe('componentPaneview', () => {
title: 'Panel 2', title: 'Panel 2',
}); });
const panel1 = paneview.getPanel('panel1'); const panel1 = paneview.getPanel('panel1')!;
const panel2 = paneview.getPanel('panel2'); const panel2 = paneview.getPanel('panel2')!;
const panel1Spy = jest.spyOn(panel1, 'dispose'); const panel1Spy = jest.spyOn(panel1, 'dispose');
const panel2Spy = jest.spyOn(panel2, 'dispose'); const panel2Spy = jest.spyOn(panel2, 'dispose');
@ -371,7 +377,8 @@ describe('componentPaneview', () => {
}); });
test('panel is disposed of when fromJSON is called', () => { test('panel is disposed of when fromJSON is called', () => {
const paneview = new PaneviewComponent(container, { const paneview = new PaneviewComponent({
parentElement: container,
components: { components: {
testPanel: TestPanel, testPanel: TestPanel,
}, },
@ -390,8 +397,8 @@ describe('componentPaneview', () => {
title: 'Panel 2', title: 'Panel 2',
}); });
const panel1 = paneview.getPanel('panel1'); const panel1 = paneview.getPanel('panel1')!;
const panel2 = paneview.getPanel('panel2'); const panel2 = paneview.getPanel('panel2')!;
const panel1Spy = jest.spyOn(panel1, 'dispose'); const panel1Spy = jest.spyOn(panel1, 'dispose');
const panel2Spy = jest.spyOn(panel2, 'dispose'); const panel2Spy = jest.spyOn(panel2, 'dispose');

View File

@ -26,7 +26,8 @@ describe('componentSplitview', () => {
}); });
test('remove panel', () => { test('remove panel', () => {
const splitview = new SplitviewComponent(container, { const splitview = new SplitviewComponent({
parentElement: container,
orientation: Orientation.VERTICAL, orientation: Orientation.VERTICAL,
components: { components: {
testPanel: TestPanel, testPanel: TestPanel,
@ -38,9 +39,9 @@ describe('componentSplitview', () => {
splitview.addPanel({ id: 'panel2', component: 'testPanel' }); splitview.addPanel({ id: 'panel2', component: 'testPanel' });
splitview.addPanel({ id: 'panel3', component: 'testPanel' }); splitview.addPanel({ id: 'panel3', component: 'testPanel' });
const panel1 = splitview.getPanel('panel1'); const panel1 = splitview.getPanel('panel1')!;
const panel2 = splitview.getPanel('panel2'); const panel2 = splitview.getPanel('panel2')!;
const panel3 = splitview.getPanel('panel3'); const panel3 = splitview.getPanel('panel3')!;
expect(panel1.api.isActive).toBeFalsy(); expect(panel1.api.isActive).toBeFalsy();
expect(panel2.api.isActive).toBeFalsy(); expect(panel2.api.isActive).toBeFalsy();
@ -61,7 +62,8 @@ describe('componentSplitview', () => {
}); });
test('horizontal dimensions', () => { test('horizontal dimensions', () => {
const splitview = new SplitviewComponent(container, { const splitview = new SplitviewComponent({
parentElement: container,
orientation: Orientation.HORIZONTAL, orientation: Orientation.HORIZONTAL,
components: { components: {
testPanel: TestPanel, testPanel: TestPanel,
@ -74,7 +76,8 @@ describe('componentSplitview', () => {
}); });
test('vertical dimensions', () => { test('vertical dimensions', () => {
const splitview = new SplitviewComponent(container, { const splitview = new SplitviewComponent({
parentElement: container,
orientation: Orientation.VERTICAL, orientation: Orientation.VERTICAL,
components: { components: {
testPanel: TestPanel, testPanel: TestPanel,
@ -87,7 +90,8 @@ describe('componentSplitview', () => {
}); });
test('api resize', () => { test('api resize', () => {
const splitview = new SplitviewComponent(container, { const splitview = new SplitviewComponent({
parentElement: container,
orientation: Orientation.VERTICAL, orientation: Orientation.VERTICAL,
components: { components: {
testPanel: TestPanel, testPanel: TestPanel,
@ -99,9 +103,9 @@ describe('componentSplitview', () => {
splitview.addPanel({ id: 'panel2', component: 'testPanel' }); splitview.addPanel({ id: 'panel2', component: 'testPanel' });
splitview.addPanel({ id: 'panel3', component: 'testPanel' }); splitview.addPanel({ id: 'panel3', component: 'testPanel' });
const panel1 = splitview.getPanel('panel1'); const panel1 = splitview.getPanel('panel1')!;
const panel2 = splitview.getPanel('panel2'); const panel2 = splitview.getPanel('panel2')!;
const panel3 = splitview.getPanel('panel3'); const panel3 = splitview.getPanel('panel3')!;
expect(panel1.width).toBe(400); expect(panel1.width).toBe(400);
expect(panel1.height).toBe(200); expect(panel1.height).toBe(200);
@ -139,7 +143,8 @@ describe('componentSplitview', () => {
}); });
test('api', () => { test('api', () => {
const splitview = new SplitviewComponent(container, { const splitview = new SplitviewComponent({
parentElement: container,
orientation: Orientation.HORIZONTAL, orientation: Orientation.HORIZONTAL,
components: { components: {
testPanel: TestPanel, testPanel: TestPanel,
@ -180,7 +185,8 @@ describe('componentSplitview', () => {
test('vertical panels', () => { test('vertical panels', () => {
const disposables = new CompositeDisposable(); const disposables = new CompositeDisposable();
const splitview = new SplitviewComponent(container, { const splitview = new SplitviewComponent({
parentElement: container,
orientation: Orientation.VERTICAL, orientation: Orientation.VERTICAL,
components: { components: {
testPanel: TestPanel, testPanel: TestPanel,
@ -229,7 +235,8 @@ describe('componentSplitview', () => {
test('horizontal panels', () => { test('horizontal panels', () => {
const disposables = new CompositeDisposable(); const disposables = new CompositeDisposable();
const splitview = new SplitviewComponent(container, { const splitview = new SplitviewComponent({
parentElement: container,
orientation: Orientation.HORIZONTAL, orientation: Orientation.HORIZONTAL,
components: { components: {
testPanel: TestPanel, testPanel: TestPanel,
@ -276,7 +283,8 @@ describe('componentSplitview', () => {
}); });
test('serialization', () => { test('serialization', () => {
const splitview = new SplitviewComponent(container, { const splitview = new SplitviewComponent({
parentElement: container,
orientation: Orientation.VERTICAL, orientation: Orientation.VERTICAL,
components: { components: {
testPanel: TestPanel, testPanel: TestPanel,
@ -330,7 +338,8 @@ describe('componentSplitview', () => {
}); });
test('toJSON shouldnt fire any layout events', () => { test('toJSON shouldnt fire any layout events', () => {
const splitview = new SplitviewComponent(container, { const splitview = new SplitviewComponent({
parentElement: container,
orientation: Orientation.HORIZONTAL, orientation: Orientation.HORIZONTAL,
components: { components: {
testPanel: TestPanel, testPanel: TestPanel,
@ -361,7 +370,8 @@ describe('componentSplitview', () => {
test('dispose of splitviewComponent', () => { test('dispose of splitviewComponent', () => {
expect(container.childNodes.length).toBe(0); expect(container.childNodes.length).toBe(0);
const splitview = new SplitviewComponent(container, { const splitview = new SplitviewComponent({
parentElement: container,
orientation: Orientation.HORIZONTAL, orientation: Orientation.HORIZONTAL,
components: { components: {
testPanel: TestPanel, testPanel: TestPanel,
@ -387,7 +397,8 @@ describe('componentSplitview', () => {
}); });
test('panel is disposed of when component is disposed', () => { test('panel is disposed of when component is disposed', () => {
const splitview = new SplitviewComponent(container, { const splitview = new SplitviewComponent({
parentElement: container,
orientation: Orientation.HORIZONTAL, orientation: Orientation.HORIZONTAL,
components: { components: {
default: TestPanel, default: TestPanel,
@ -405,8 +416,8 @@ describe('componentSplitview', () => {
component: 'default', component: 'default',
}); });
const panel1 = splitview.getPanel('panel1'); const panel1 = splitview.getPanel('panel1')!;
const panel2 = splitview.getPanel('panel2'); const panel2 = splitview.getPanel('panel2')!;
const panel1Spy = jest.spyOn(panel1, 'dispose'); const panel1Spy = jest.spyOn(panel1, 'dispose');
const panel2Spy = jest.spyOn(panel2, 'dispose'); const panel2Spy = jest.spyOn(panel2, 'dispose');
@ -418,7 +429,8 @@ describe('componentSplitview', () => {
}); });
test('panel is disposed of when removed', () => { test('panel is disposed of when removed', () => {
const splitview = new SplitviewComponent(container, { const splitview = new SplitviewComponent({
parentElement: container,
orientation: Orientation.HORIZONTAL, orientation: Orientation.HORIZONTAL,
components: { components: {
default: TestPanel, default: TestPanel,
@ -436,8 +448,8 @@ describe('componentSplitview', () => {
component: 'default', component: 'default',
}); });
const panel1 = splitview.getPanel('panel1'); const panel1 = splitview.getPanel('panel1')!;
const panel2 = splitview.getPanel('panel2'); const panel2 = splitview.getPanel('panel2')!;
const panel1Spy = jest.spyOn(panel1, 'dispose'); const panel1Spy = jest.spyOn(panel1, 'dispose');
const panel2Spy = jest.spyOn(panel2, 'dispose'); const panel2Spy = jest.spyOn(panel2, 'dispose');
@ -449,7 +461,8 @@ describe('componentSplitview', () => {
}); });
test('panel is disposed of when fromJSON is called', () => { test('panel is disposed of when fromJSON is called', () => {
const splitview = new SplitviewComponent(container, { const splitview = new SplitviewComponent({
parentElement: container,
orientation: Orientation.HORIZONTAL, orientation: Orientation.HORIZONTAL,
components: { components: {
default: TestPanel, default: TestPanel,
@ -467,8 +480,8 @@ describe('componentSplitview', () => {
component: 'default', component: 'default',
}); });
const panel1 = splitview.getPanel('panel1'); const panel1 = splitview.getPanel('panel1')!;
const panel2 = splitview.getPanel('panel2'); const panel2 = splitview.getPanel('panel2')!;
const panel1Spy = jest.spyOn(panel1, 'dispose'); const panel1Spy = jest.spyOn(panel1, 'dispose');
const panel2Spy = jest.spyOn(panel2, 'dispose'); const panel2Spy = jest.spyOn(panel2, 'dispose');

View File

@ -185,11 +185,12 @@ export class DockviewComponent
return this.options.tabHeight; return this.options.tabHeight;
} }
constructor(element: HTMLElement, options: DockviewComponentOptions) { constructor(options: DockviewComponentOptions) {
super(element, { super({
proportionalLayout: true, proportionalLayout: true,
orientation: options.orientation || Orientation.HORIZONTAL, orientation: options.orientation || Orientation.HORIZONTAL,
styles: options.styles, styles: options.styles,
parentElement: options.parentElement,
}); });
this.element.classList.add('dv-dockview'); this.element.classList.add('dv-dockview');

View File

@ -84,6 +84,7 @@ export interface DockviewComponentOptions extends DockviewRenderFunctions {
group: DockviewGroupPanel group: DockviewGroupPanel
) => IGroupControlRenderer; ) => IGroupControlRenderer;
singleTabMode?: 'fullwidth' | 'default'; singleTabMode?: 'fullwidth' | 'default';
parentElement?: HTMLElement;
} }
export interface PanelOptions { export interface PanelOptions {

View File

@ -11,8 +11,15 @@ export function watchElementResize(
cb: (entry: ResizeObserverEntry) => void cb: (entry: ResizeObserverEntry) => void
): IDisposable { ): IDisposable {
const observer = new ResizeObserver((entires) => { const observer = new ResizeObserver((entires) => {
const firstEntry = entires[0]; /**
cb(firstEntry); * Fast browser window resize produces Error: ResizeObserver loop limit exceeded.
* The error isn't visible in browser console, doesn't affect functionality, but degrades performance.
* See https://stackoverflow.com/questions/49384120/resizeobserver-loop-limit-exceeded/58701523#58701523
*/
requestAnimationFrame(() => {
const firstEntry = entires[0];
cb(firstEntry);
});
}); });
observer.observe(element); observer.observe(element);

View File

@ -1,11 +1,12 @@
import { Emitter, Event, TickDelayedEvent } from '../events'; import { Emitter, Event, TickDelayedEvent } from '../events';
import { getGridLocation, Gridview, IGridView } from './gridview'; import { getGridLocation, Gridview, IGridView } from './gridview';
import { Position } from '../dnd/droptarget'; import { Position } from '../dnd/droptarget';
import { CompositeDisposable, IValueDisposable } from '../lifecycle'; import { IValueDisposable } from '../lifecycle';
import { sequentialNumberGenerator } from '../math'; import { sequentialNumberGenerator } from '../math';
import { ISplitviewStyles, Orientation, Sizing } from '../splitview/splitview'; import { ISplitviewStyles, Orientation, Sizing } from '../splitview/splitview';
import { IPanel } from '../panel/types'; import { IPanel } from '../panel/types';
import { MovementOptions2 } from '../dockview/options'; import { MovementOptions2 } from '../dockview/options';
import { Resizable } from '../resizable';
const nextLayoutId = sequentialNumberGenerator(); const nextLayoutId = sequentialNumberGenerator();
@ -31,6 +32,7 @@ export interface BaseGridOptions {
readonly proportionalLayout: boolean; readonly proportionalLayout: boolean;
readonly orientation: Orientation; readonly orientation: Orientation;
readonly styles?: ISplitviewStyles; readonly styles?: ISplitviewStyles;
readonly parentElement?: HTMLElement;
} }
export interface IGridPanelView extends IGridView, IPanel { export interface IGridPanelView extends IGridView, IPanel {
@ -64,7 +66,7 @@ export interface IBaseGrid<T extends IGridPanelView> {
} }
export abstract class BaseGrid<T extends IGridPanelView> export abstract class BaseGrid<T extends IGridPanelView>
extends CompositeDisposable extends Resizable
implements IBaseGrid<T> implements IBaseGrid<T>
{ {
private readonly _id = nextLayoutId.next(); private readonly _id = nextLayoutId.next();
@ -92,10 +94,6 @@ export abstract class BaseGrid<T extends IGridPanelView>
return this._id; return this._id;
} }
get element(): HTMLElement {
return this._element;
}
get size(): number { get size(): number {
return this._groups.size; return this._groups.size;
} }
@ -129,11 +127,8 @@ export abstract class BaseGrid<T extends IGridPanelView>
return this._activeGroup; return this._activeGroup;
} }
constructor( constructor(options: BaseGridOptions) {
private readonly _element: HTMLElement, super(options.parentElement);
options: BaseGridOptions
) {
super();
this.gridview = new Gridview( this.gridview = new Gridview(
!!options.proportionalLayout, !!options.proportionalLayout,
@ -295,8 +290,8 @@ export abstract class BaseGrid<T extends IGridPanelView>
return; return;
} }
this.element.style.height = `${height}px`; this.gridview.element.style.height = `${height}px`;
this.element.style.width = `${width}px`; this.gridview.element.style.width = `${width}px`;
this.gridview.layout(width, height); this.gridview.layout(width, height);
} }

View File

@ -100,8 +100,9 @@ export class GridviewComponent
this._deserializer = value; this._deserializer = value;
} }
constructor(element: HTMLElement, options: GridviewComponentOptions) { constructor(options: GridviewComponentOptions) {
super(element, { super({
parentElement: options.parentElement,
proportionalLayout: options.proportionalLayout, proportionalLayout: options.proportionalLayout,
orientation: options.orientation, orientation: options.orientation,
styles: options.styles, styles: options.styles,

View File

@ -16,4 +16,5 @@ export interface GridviewComponentOptions {
frameworkComponentFactory?: FrameworkFactory<GridviewPanel>; frameworkComponentFactory?: FrameworkFactory<GridviewPanel>;
tabHeight?: number; tabHeight?: number;
styles?: ISplitviewStyles; styles?: ISplitviewStyles;
parentElement?: HTMLElement;
} }

View File

@ -17,6 +17,11 @@ export namespace Disposable {
export class CompositeDisposable { export class CompositeDisposable {
private readonly disposables: IDisposable[]; private readonly disposables: IDisposable[];
private _isDisposed = false;
protected get isDisposed(): boolean {
return this._isDisposed;
}
public static from(...args: IDisposable[]): CompositeDisposable { public static from(...args: IDisposable[]): CompositeDisposable {
return new CompositeDisposable(...args); return new CompositeDisposable(...args);
@ -32,6 +37,8 @@ export class CompositeDisposable {
public dispose(): void { public dispose(): void {
this.disposables.forEach((arg) => arg.dispose()); this.disposables.forEach((arg) => arg.dispose());
this._isDisposed = true;
} }
} }

View File

@ -25,4 +25,5 @@ export interface PaneviewComponentOptions {
}; };
disableDnd?: boolean; disableDnd?: boolean;
showDndOverlay?: (event: PaneviewDndOverlayEvent) => boolean; showDndOverlay?: (event: PaneviewDndOverlayEvent) => boolean;
parentElement?: HTMLElement;
} }

View File

@ -22,6 +22,7 @@ import {
import { DefaultHeader } from './defaultPaneviewHeader'; import { DefaultHeader } from './defaultPaneviewHeader';
import { sequentialNumberGenerator } from '../math'; import { sequentialNumberGenerator } from '../math';
import { PaneTransfer } from '../dnd/dataTransfer'; import { PaneTransfer } from '../dnd/dataTransfer';
import { Resizable } from '../resizable';
const nextLayoutId = sequentialNumberGenerator(); const nextLayoutId = sequentialNumberGenerator();
@ -126,10 +127,7 @@ export interface IPaneviewComponent extends IDisposable {
clear(): void; clear(): void;
} }
export class PaneviewComponent export class PaneviewComponent extends Resizable implements IPaneviewComponent {
extends CompositeDisposable
implements IPaneviewComponent
{
private readonly _id = nextLayoutId.next(); private readonly _id = nextLayoutId.next();
private _options: PaneviewComponentOptions; private _options: PaneviewComponentOptions;
private _disposable = new MutableDisposable(); private _disposable = new MutableDisposable();
@ -199,11 +197,8 @@ export class PaneviewComponent
return this._options; return this._options;
} }
constructor( constructor(options: PaneviewComponentOptions) {
private element: HTMLElement, super(options.parentElement);
options: PaneviewComponentOptions
) {
super();
this.addDisposables( this.addDisposables(
this._onDidLayoutChange, this._onDidLayoutChange,

View File

@ -0,0 +1,39 @@
import { watchElementResize } from './dom';
import { CompositeDisposable } from './lifecycle';
export abstract class Resizable extends CompositeDisposable {
private readonly _element: HTMLElement;
get element(): HTMLElement {
return this._element;
}
constructor(parentElement?: HTMLElement) {
super();
if (parentElement) {
this._element = parentElement;
} else {
this._element = document.createElement('div');
this._element.style.height = '100%';
this._element.style.width = '100%';
this._element.className = 'dv-resizable-container';
}
this.addDisposables(
watchElementResize(this._element, (entry) => {
if (this.isDisposed) {
/**
* resize is delayed through requestAnimationFrame so there is a small chance
* the component has already been disposed of
*/
return;
}
const { width, height } = entry.contentRect;
this.layout(width, height);
})
);
}
abstract layout(width: number, height: number): void;
}

View File

@ -26,4 +26,5 @@ export interface SplitviewComponentOptions extends SplitViewOptions {
[componentName: string]: any; [componentName: string]: any;
}; };
frameworkWrapper?: FrameworkFactory<SplitviewPanel>; frameworkWrapper?: FrameworkFactory<SplitviewPanel>;
parentElement?: HTMLElement;
} }

View File

@ -16,6 +16,7 @@ import { BaseComponentOptions } from '../panel/types';
import { Emitter, Event } from '../events'; import { Emitter, Event } from '../events';
import { SplitviewPanel, ISplitviewPanel } from './splitviewPanel'; import { SplitviewPanel, ISplitviewPanel } from './splitviewPanel';
import { createComponent } from '../panel/componentFactory'; import { createComponent } from '../panel/componentFactory';
import { Resizable } from '../resizable';
export interface SerializedSplitviewPanelData { export interface SerializedSplitviewPanelData {
id: string; id: string;
@ -79,7 +80,7 @@ export interface ISplitviewComponent extends IDisposable {
* A high-level implementation of splitview that works using 'panels' * A high-level implementation of splitview that works using 'panels'
*/ */
export class SplitviewComponent export class SplitviewComponent
extends CompositeDisposable extends Resizable
implements ISplitviewComponent implements ISplitviewComponent
{ {
private _disposable = new MutableDisposable(); private _disposable = new MutableDisposable();
@ -154,11 +155,8 @@ export class SplitviewComponent
: this.splitview.orthogonalSize; : this.splitview.orthogonalSize;
} }
constructor( constructor(options: SplitviewComponentOptions) {
private readonly element: HTMLElement, super(options.parentElement);
options: SplitviewComponentOptions
) {
super();
this._options = options; this._options = options;

View File

@ -33,11 +33,13 @@ describe('gridview react', () => {
}); });
test('is sized to container', () => { test('is sized to container', () => {
setMockRefElement({ const el = document.createElement('div');
clientHeight: 450,
clientWidth: 650, jest.spyOn(el, 'clientHeight', 'get').mockReturnValue(450);
appendChild: jest.fn(), jest.spyOn(el, 'clientWidth', 'get').mockReturnValue(650);
});
setMockRefElement(el);
let api: DockviewApi | undefined; let api: DockviewApi | undefined;
const onReady = (event: DockviewReadyEvent) => { const onReady = (event: DockviewReadyEvent) => {

View File

@ -39,11 +39,12 @@ describe('gridview react', () => {
}); });
test('is sized to container', () => { test('is sized to container', () => {
setMockRefElement({ const el = document.createElement('div') as any;
clientHeight: 450,
clientWidth: 650, jest.spyOn(el, 'clientHeight', 'get').mockReturnValue(450);
appendChild: jest.fn(), jest.spyOn(el, 'clientWidth', 'get').mockReturnValue(650);
});
setMockRefElement(el);
let api: GridviewApi | undefined; let api: GridviewApi | undefined;
const onReady = (event: GridviewReadyEvent) => { const onReady = (event: GridviewReadyEvent) => {

View File

@ -9,7 +9,7 @@ import {
import { PanelCollection } from '../../../types'; import { PanelCollection } from '../../../types';
import { setMockRefElement } from '../../__test_utils__/utils'; import { setMockRefElement } from '../../__test_utils__/utils';
describe('gridview react', () => { describe('dockview', () => {
let components: PanelCollection<IDockviewPanelProps>; let components: PanelCollection<IDockviewPanelProps>;
beforeEach(() => { beforeEach(() => {
@ -33,11 +33,12 @@ describe('gridview react', () => {
}); });
test('is sized to container', () => { test('is sized to container', () => {
setMockRefElement({ const el = document.createElement('div') as any;
clientHeight: 450, jest.spyOn(el, 'clientHeight', 'get').mockReturnValue(450);
clientWidth: 650, jest.spyOn(el, 'clientWidth', 'get').mockReturnValue(650);
appendChild: jest.fn(),
}); setMockRefElement(el);
let api: DockviewApi | undefined; let api: DockviewApi | undefined;
const onReady = (event: DockviewReadyEvent) => { const onReady = (event: DockviewReadyEvent) => {

View File

@ -9,7 +9,6 @@ import {
DockviewApi, DockviewApi,
IContentRenderer, IContentRenderer,
ITabRenderer, ITabRenderer,
watchElementResize,
DockviewGroupPanel, DockviewGroupPanel,
} from 'dockview-core'; } from 'dockview-core';
import { ReactPanelContentPart } from './reactContentPart'; import { ReactPanelContentPart } from './reactContentPart';
@ -81,23 +80,12 @@ export const DockviewReact = React.forwardRef(
React.useImperativeHandle(ref, () => domRef.current!, []); React.useImperativeHandle(ref, () => domRef.current!, []);
React.useEffect(() => { React.useEffect(() => {
if (props.disableAutoResizing) { if (!domRef.current) {
return () => { return () => {
// // noop
}; };
} }
const watcher = watchElementResize(domRef.current!, (entry) => {
const { width, height } = entry.contentRect;
dockviewRef.current?.layout(width, height);
});
return () => {
watcher.dispose();
};
}, [props.disableAutoResizing]);
React.useEffect(() => {
const factory: GroupPanelFrameworkComponentFactory = { const factory: GroupPanelFrameworkComponentFactory = {
content: { content: {
createComponent: ( createComponent: (
@ -142,8 +130,6 @@ export const DockviewReact = React.forwardRef(
}, },
}; };
const element = document.createElement('div');
const frameworkTabComponents = props.tabComponents || {}; const frameworkTabComponents = props.tabComponents || {};
if (props.defaultTabComponent) { if (props.defaultTabComponent) {
@ -151,7 +137,8 @@ export const DockviewReact = React.forwardRef(
props.defaultTabComponent; props.defaultTabComponent;
} }
const dockview = new DockviewComponent(element, { const dockview = new DockviewComponent({
parentElement: domRef.current,
frameworkComponentFactory: factory, frameworkComponentFactory: factory,
frameworkComponents: props.components, frameworkComponents: props.components,
frameworkTabComponents, frameworkTabComponents,
@ -171,9 +158,7 @@ export const DockviewReact = React.forwardRef(
singleTabMode: props.singleTabMode, singleTabMode: props.singleTabMode,
}); });
domRef.current?.appendChild(dockview.element); const { clientWidth, clientHeight } = domRef.current;
const { clientWidth, clientHeight } = domRef.current!;
dockview.layout(clientWidth, clientHeight); dockview.layout(clientWidth, clientHeight);
if (props.onReady) { if (props.onReady) {
@ -184,7 +169,6 @@ export const DockviewReact = React.forwardRef(
return () => { return () => {
dockview.dispose(); dockview.dispose();
element.remove();
}; };
}, []); }, []);

View File

@ -5,7 +5,6 @@ import {
GridviewPanelApi, GridviewPanelApi,
Orientation, Orientation,
GridviewApi, GridviewApi,
watchElementResize,
} from 'dockview-core'; } from 'dockview-core';
import { ReactGridPanelView } from './view'; import { ReactGridPanelView } from './view';
import { usePortalsLifecycle } from '../react'; import { usePortalsLifecycle } from '../react';
@ -40,26 +39,14 @@ export const GridviewReact = React.forwardRef(
React.useImperativeHandle(ref, () => domRef.current!, []); React.useImperativeHandle(ref, () => domRef.current!, []);
React.useEffect(() => { React.useEffect(() => {
if (props.disableAutoResizing) { if (!domRef.current) {
return () => { return () => {
// // noop
}; };
} }
const watcher = watchElementResize(domRef.current!, (entry) => { const gridview = new GridviewComponent({
const { width, height } = entry.contentRect; parentElement: domRef.current,
gridviewRef.current?.layout(width, height);
});
return () => {
watcher.dispose();
};
}, [props.disableAutoResizing]);
React.useEffect(() => {
const element = document.createElement('div');
const gridview = new GridviewComponent(element, {
proportionalLayout: proportionalLayout:
typeof props.proportionalLayout === 'boolean' typeof props.proportionalLayout === 'boolean'
? props.proportionalLayout ? props.proportionalLayout
@ -83,9 +70,7 @@ export const GridviewReact = React.forwardRef(
: undefined, : undefined,
}); });
domRef.current?.appendChild(gridview.element); const { clientWidth, clientHeight } = domRef.current;
const { clientWidth, clientHeight } = domRef.current!;
gridview.layout(clientWidth, clientHeight); gridview.layout(clientWidth, clientHeight);
if (props.onReady) { if (props.onReady) {
@ -96,7 +81,6 @@ export const GridviewReact = React.forwardRef(
return () => { return () => {
gridview.dispose(); gridview.dispose();
element.remove();
}; };
}, []); }, []);

View File

@ -5,7 +5,6 @@ import {
IPaneviewComponent, IPaneviewComponent,
PaneviewDndOverlayEvent, PaneviewDndOverlayEvent,
PaneviewApi, PaneviewApi,
watchElementResize,
PaneviewDropEvent, PaneviewDropEvent,
} from 'dockview-core'; } from 'dockview-core';
import { usePortalsLifecycle } from '../react'; import { usePortalsLifecycle } from '../react';
@ -42,23 +41,6 @@ export const PaneviewReact = React.forwardRef(
React.useImperativeHandle(ref, () => domRef.current!, []); React.useImperativeHandle(ref, () => domRef.current!, []);
React.useEffect(() => {
if (props.disableAutoResizing) {
return () => {
//
};
}
const watcher = watchElementResize(domRef.current!, (entry) => {
const { width, height } = entry.contentRect;
paneviewRef.current?.layout(width, height);
});
return () => {
watcher.dispose();
};
}, [props.disableAutoResizing]);
React.useEffect(() => { React.useEffect(() => {
const createComponent = ( const createComponent = (
id: string, id: string,
@ -69,7 +51,8 @@ export const PaneviewReact = React.forwardRef(
addPortal, addPortal,
}); });
const paneview = new PaneviewComponent(domRef.current!, { const paneview = new PaneviewComponent({
parentElement: domRef.current!,
frameworkComponents: props.components, frameworkComponents: props.components,
components: {}, components: {},
headerComponents: {}, headerComponents: {},

View File

@ -5,7 +5,6 @@ import {
ISplitviewComponent, ISplitviewComponent,
SplitviewComponent, SplitviewComponent,
Orientation, Orientation,
watchElementResize,
} from 'dockview-core'; } from 'dockview-core';
import { usePortalsLifecycle } from '../react'; import { usePortalsLifecycle } from '../react';
import { PanelCollection, PanelParameters } from '../types'; import { PanelCollection, PanelParameters } from '../types';
@ -40,24 +39,8 @@ export const SplitviewReact = React.forwardRef(
React.useImperativeHandle(ref, () => domRef.current!, []); React.useImperativeHandle(ref, () => domRef.current!, []);
React.useEffect(() => { React.useEffect(() => {
if (props.disableAutoResizing) { const splitview = new SplitviewComponent({
return () => { parentElement: domRef.current!,
//
};
}
const watcher = watchElementResize(domRef.current!, (entry) => {
const { width, height } = entry.contentRect;
splitviewRef.current?.layout(width, height);
});
return () => {
watcher.dispose();
};
}, [props.disableAutoResizing]);
React.useEffect(() => {
const splitview = new SplitviewComponent(domRef.current!, {
orientation: props.orientation || Orientation.HORIZONTAL, orientation: props.orientation || Orientation.HORIZONTAL,
frameworkComponents: props.components, frameworkComponents: props.components,
frameworkWrapper: { frameworkWrapper: {

View File

@ -22,7 +22,7 @@ import DockviewNative2 from '@site/sandboxes/nativeapp-dockview/src/app';
import DockviewSetTitle from '@site/sandboxes/updatetitle-dockview/src/app'; import DockviewSetTitle from '@site/sandboxes/updatetitle-dockview/src/app';
import RenderingDockview from '@site/sandboxes/rendering-dockview/src/app'; import RenderingDockview from '@site/sandboxes/rendering-dockview/src/app';
import DockviewExternalDnd from '@site/sandboxes/externaldnd-dockview/src/app'; import DockviewExternalDnd from '@site/sandboxes/externaldnd-dockview/src/app';
// import { attach as attachDockviewVanilla } from '@site/sandboxes/vanilla-dockview/src/app'; import { attach as attachDockviewVanilla } from '@site/sandboxes/vanilla-dockview/src/app';
# Dockview # Dockview
@ -702,7 +702,7 @@ hello 2
<App /> <App />
</div> </div>
<!-- ## VanillaJS ## VanillaJS
> Note: This section is experimental and support for Vanilla JS is a work in progress. > Note: This section is experimental and support for Vanilla JS is a work in progress.
@ -712,4 +712,4 @@ The core library is published as an independant package under the name `dockview
> When using `dockview` there is no need to also install `dockview-core`. > When using `dockview` there is no need to also install `dockview-core`.
> `dockview-core` is a dependency of `dockview` and automatically installed during the installation process of `dockview` via `npm install dockview`. > `dockview-core` is a dependency of `dockview` and automatically installed during the installation process of `dockview` via `npm install dockview`.
<Container injectVanillaJS={attachDockviewVanilla} /> --> <Container injectVanillaJS={attachDockviewVanilla} />

View File

@ -25,22 +25,17 @@ export function attach(parent: HTMLElement): {
} { } {
const element = document.createElement('div'); const element = document.createElement('div');
element.className = 'dockview-theme-abyss'; element.className = 'dockview-theme-abyss';
parent.appendChild(element); element.style.height = '100%';
element.style.width = '100%';
const dockview = new DockviewComponent(element, { const dockview = new DockviewComponent({
components: { components: {
default: DefaultPanel, default: DefaultPanel,
}, },
parentElement: element,
}); });
const observer = new ResizeObserver((entires) => { parent.appendChild(element);
const firstEntry = entires[0];
const { width, height } = firstEntry.contentRect;
dockview.layout(width, height);
});
observer.observe(parent);
const panel1 = dockview.addPanel({ const panel1 = dockview.addPanel({
id: 'panel_1', id: 'panel_1',
@ -78,9 +73,6 @@ export function attach(parent: HTMLElement): {
return { return {
dispose: () => { dispose: () => {
observer.unobserve(element);
observer.disconnect();
dockview.dispose(); dockview.dispose();
element.remove(); element.remove();
}, },