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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -11,9 +11,16 @@ export function watchElementResize(
cb: (entry: ResizeObserverEntry) => void
): IDisposable {
const observer = new ResizeObserver((entires) => {
/**
* 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);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,7 +5,6 @@ import {
IPaneviewComponent,
PaneviewDndOverlayEvent,
PaneviewApi,
watchElementResize,
PaneviewDropEvent,
} from 'dockview-core';
import { usePortalsLifecycle } from '../react';
@ -42,23 +41,6 @@ export const PaneviewReact = React.forwardRef(
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(() => {
const createComponent = (
id: string,
@ -69,7 +51,8 @@ export const PaneviewReact = React.forwardRef(
addPortal,
});
const paneview = new PaneviewComponent(domRef.current!, {
const paneview = new PaneviewComponent({
parentElement: domRef.current!,
frameworkComponents: props.components,
components: {},
headerComponents: {},

View File

@ -5,7 +5,6 @@ import {
ISplitviewComponent,
SplitviewComponent,
Orientation,
watchElementResize,
} from 'dockview-core';
import { usePortalsLifecycle } from '../react';
import { PanelCollection, PanelParameters } from '../types';
@ -40,24 +39,8 @@ export const SplitviewReact = React.forwardRef(
React.useImperativeHandle(ref, () => domRef.current!, []);
React.useEffect(() => {
if (props.disableAutoResizing) {
return () => {
//
};
}
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!, {
const splitview = new SplitviewComponent({
parentElement: domRef.current!,
orientation: props.orientation || Orientation.HORIZONTAL,
frameworkComponents: props.components,
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 RenderingDockview from '@site/sandboxes/rendering-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
@ -702,7 +702,7 @@ hello 2
<App />
</div>
<!-- ## VanillaJS
## VanillaJS
> 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`.
> `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');
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: {
default: DefaultPanel,
},
parentElement: element,
});
const observer = new ResizeObserver((entires) => {
const firstEntry = entires[0];
const { width, height } = firstEntry.contentRect;
dockview.layout(width, height);
});
observer.observe(parent);
parent.appendChild(element);
const panel1 = dockview.addPanel({
id: 'panel_1',
@ -78,9 +73,6 @@ export function attach(parent: HTMLElement): {
return {
dispose: () => {
observer.unobserve(element);
observer.disconnect();
dockview.dispose();
element.remove();
},