Merge pull request #576 from mathuo/562-dockview-framework-wrappers-vuejs-angular-javascript-etc

feat: vue3 prep
This commit is contained in:
mathuo 2024-04-25 23:04:36 +01:00 committed by GitHub
commit dc684d05a7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
46 changed files with 1775 additions and 1845 deletions

View File

@ -1,16 +1,16 @@
import { DockviewPanelApiImpl } from '../../api/dockviewPanelApi'; import { DockviewPanelApiImpl } from '../../api/dockviewPanelApi';
import { DockviewComponent } from '../../dockview/dockviewComponent'; import { DockviewComponent } from '../../dockview/dockviewComponent';
import { DockviewPanel, IDockviewPanel } from '../../dockview/dockviewPanel'; import { DockviewPanel } from '../../dockview/dockviewPanel';
import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel'; import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel';
import { fromPartial } from '@total-typescript/shoehorn'; import { fromPartial } from '@total-typescript/shoehorn';
describe('groupPanelApi', () => { describe('groupPanelApi', () => {
test('title', () => { test('title', () => {
const accessor: Partial<DockviewComponent> = { const accessor = fromPartial<DockviewComponent>({
onDidAddPanel: jest.fn(), onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(), onDidRemovePanel: jest.fn(),
options: { parentElement: document.createElement('div') }, options: { parentElement: document.createElement('div') },
}; });
const panelMock = jest.fn<DockviewPanel, []>(() => { const panelMock = jest.fn<DockviewPanel, []>(() => {
return { return {
@ -46,11 +46,12 @@ describe('groupPanelApi', () => {
update: jest.fn(), update: jest.fn(),
}; };
const accessor: Partial<DockviewComponent> = { const accessor = fromPartial<DockviewComponent>({
onDidAddPanel: jest.fn(), onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(), onDidRemovePanel: jest.fn(),
options: { parentElement: document.createElement('div') }, options: { parentElement: document.createElement('div') },
}; });
const groupViewPanel = new DockviewGroupPanel( const groupViewPanel = new DockviewGroupPanel(
<DockviewComponent>accessor, <DockviewComponent>accessor,
'', '',
@ -77,11 +78,12 @@ describe('groupPanelApi', () => {
id: 'test_id', id: 'test_id',
}; };
const accessor: Partial<DockviewComponent> = { const accessor = fromPartial<DockviewComponent>({
onDidAddPanel: jest.fn(), onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(), onDidRemovePanel: jest.fn(),
options: { parentElement: document.createElement('div') }, options: { parentElement: document.createElement('div') },
}; });
const groupViewPanel = new DockviewGroupPanel( const groupViewPanel = new DockviewGroupPanel(
<DockviewComponent>accessor, <DockviewComponent>accessor,
'', '',

View File

@ -13,13 +13,12 @@ import { fromPartial } from '@total-typescript/shoehorn';
describe('tabsContainer', () => { describe('tabsContainer', () => {
test('that an external event does not render a drop target and calls through to the group mode', () => { test('that an external event does not render a drop target and calls through to the group mode', () => {
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => { const accessor = fromPartial<DockviewComponent>({
return { onDidAddPanel: jest.fn(),
onDidAddPanel: jest.fn(), onDidRemovePanel: jest.fn(),
onDidRemovePanel: jest.fn(), options: { parentElement: document.createElement('div') },
options: { parentElement: document.createElement('div') },
};
}); });
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>( const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
() => { () => {
return { return {
@ -36,14 +35,13 @@ describe('tabsContainer', () => {
}; };
}); });
const accessor = new accessorMock() as DockviewComponent;
const groupPanel = new groupPanelMock() as DockviewGroupPanel; const groupPanel = new groupPanelMock() as DockviewGroupPanel;
const cut = new TabsContainer(accessor, groupPanel); const cut = new TabsContainer(accessor, groupPanel);
const emptySpace = cut.element const emptySpace = cut.element
.getElementsByClassName('void-container') .getElementsByClassName('void-container')
.item(0) .item(0);
if (!emptySpace!) { if (!emptySpace!) {
fail('element not found'); fail('element not found');
@ -67,14 +65,13 @@ describe('tabsContainer', () => {
}); });
test('that a drag over event from another tab should render a drop target', () => { test('that a drag over event from another tab should render a drop target', () => {
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => { const accessor = fromPartial<DockviewComponent>({
return { id: 'testcomponentid',
id: 'testcomponentid', onDidAddPanel: jest.fn(),
onDidAddPanel: jest.fn(), onDidRemovePanel: jest.fn(),
onDidRemovePanel: jest.fn(), options: { parentElement: document.createElement('div') },
options: { parentElement: document.createElement('div') },
};
}); });
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>( const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
() => { () => {
return { return {
@ -93,7 +90,6 @@ describe('tabsContainer', () => {
}; };
}); });
const accessor = new accessorMock() as DockviewComponent;
const groupPanel = new groupPanelMock() as DockviewGroupPanel; const groupPanel = new groupPanelMock() as DockviewGroupPanel;
const cut = new TabsContainer(accessor, groupPanel); const cut = new TabsContainer(accessor, groupPanel);
@ -135,14 +131,13 @@ describe('tabsContainer', () => {
}); });
test('that dropping over the empty space should render a drop target', () => { test('that dropping over the empty space should render a drop target', () => {
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => { const accessor = fromPartial<DockviewComponent>({
return { id: 'testcomponentid',
id: 'testcomponentid', onDidAddPanel: jest.fn(),
onDidAddPanel: jest.fn(), onDidRemovePanel: jest.fn(),
onDidRemovePanel: jest.fn(), options: { parentElement: document.createElement('div') },
options: { parentElement: document.createElement('div') },
};
}); });
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>( const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
() => { () => {
return { return {
@ -161,7 +156,6 @@ describe('tabsContainer', () => {
}; };
}); });
const accessor = new accessorMock() as DockviewComponent;
const groupPanel = new groupPanelMock() as DockviewGroupPanel; const groupPanel = new groupPanelMock() as DockviewGroupPanel;
const cut = new TabsContainer(accessor, groupPanel); const cut = new TabsContainer(accessor, groupPanel);
@ -200,14 +194,13 @@ describe('tabsContainer', () => {
}); });
test('that dropping the first tab should render a drop target', () => { test('that dropping the first tab should render a drop target', () => {
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => { const accessor = fromPartial<DockviewComponent>({
return { id: 'testcomponentid',
id: 'testcomponentid', onDidAddPanel: jest.fn(),
onDidAddPanel: jest.fn(), onDidRemovePanel: jest.fn(),
onDidRemovePanel: jest.fn(), options: { parentElement: document.createElement('div') },
options: { parentElement: document.createElement('div') },
};
}); });
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>( const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
() => { () => {
return { return {
@ -226,7 +219,6 @@ describe('tabsContainer', () => {
}; };
}); });
const accessor = new accessorMock() as DockviewComponent;
const groupPanel = new groupPanelMock() as DockviewGroupPanel; const groupPanel = new groupPanelMock() as DockviewGroupPanel;
const cut = new TabsContainer(accessor, groupPanel); const cut = new TabsContainer(accessor, groupPanel);
@ -265,14 +257,13 @@ describe('tabsContainer', () => {
}); });
test('that dropping a tab from another component should not render a drop target', () => { test('that dropping a tab from another component should not render a drop target', () => {
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => { const accessor = fromPartial<DockviewComponent>({
return { id: 'testcomponentid',
id: 'testcomponentid', onDidAddPanel: jest.fn(),
onDidAddPanel: jest.fn(), onDidRemovePanel: jest.fn(),
onDidRemovePanel: jest.fn(), options: { parentElement: document.createElement('div') },
options: { parentElement: document.createElement('div') },
};
}); });
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>( const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
() => { () => {
return { return {
@ -290,7 +281,6 @@ describe('tabsContainer', () => {
}; };
}); });
const accessor = new accessorMock() as DockviewComponent;
const groupPanel = new groupPanelMock() as DockviewGroupPanel; const groupPanel = new groupPanelMock() as DockviewGroupPanel;
const cut = new TabsContainer(accessor, groupPanel); const cut = new TabsContainer(accessor, groupPanel);
@ -335,19 +325,17 @@ describe('tabsContainer', () => {
}); });
test('left actions', () => { test('left actions', () => {
const accessorMock = jest.fn<DockviewComponent, []>(() => { const accessor = fromPartial<DockviewComponent>({
return (<Partial<DockviewComponent>>{ id: 'testcomponentid',
options: { parentElement: document.createElement('div') }, onDidAddPanel: jest.fn(),
onDidAddPanel: jest.fn(), onDidRemovePanel: jest.fn(),
onDidRemovePanel: jest.fn(), options: { parentElement: document.createElement('div') },
}) as DockviewComponent;
}); });
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => { const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
return (<Partial<DockviewGroupPanel>>{}) as DockviewGroupPanel; return (<Partial<DockviewGroupPanel>>{}) as DockviewGroupPanel;
}); });
const accessor = new accessorMock();
const groupPanel = new groupPanelMock(); const groupPanel = new groupPanelMock();
const cut = new TabsContainer(accessor, groupPanel); const cut = new TabsContainer(accessor, groupPanel);
@ -401,19 +389,17 @@ describe('tabsContainer', () => {
}); });
test('right actions', () => { test('right actions', () => {
const accessorMock = jest.fn<DockviewComponent, []>(() => { const accessor = fromPartial<DockviewComponent>({
return (<Partial<DockviewComponent>>{ id: 'testcomponentid',
options: { parentElement: document.createElement('div') }, onDidAddPanel: jest.fn(),
onDidAddPanel: jest.fn(), onDidRemovePanel: jest.fn(),
onDidRemovePanel: jest.fn(), options: { parentElement: document.createElement('div') },
}) as DockviewComponent;
}); });
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => { const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
return (<Partial<DockviewGroupPanel>>{}) as DockviewGroupPanel; return (<Partial<DockviewGroupPanel>>{}) as DockviewGroupPanel;
}); });
const accessor = new accessorMock();
const groupPanel = new groupPanelMock(); const groupPanel = new groupPanelMock();
const cut = new TabsContainer(accessor, groupPanel); const cut = new TabsContainer(accessor, groupPanel);
@ -467,14 +453,12 @@ describe('tabsContainer', () => {
}); });
test('that a tab will become floating when clicked if not floating and shift is selected', () => { test('that a tab will become floating when clicked if not floating and shift is selected', () => {
const accessorMock = jest.fn<DockviewComponent, []>(() => { const accessor = fromPartial<DockviewComponent>({
return (<Partial<DockviewComponent>>{ options: { parentElement: document.createElement('div') },
options: { parentElement: document.createElement('div') }, onDidAddPanel: jest.fn(),
onDidAddPanel: jest.fn(), onDidRemovePanel: jest.fn(),
onDidRemovePanel: jest.fn(), element: document.createElement('div'),
element: document.createElement('div'), addFloatingGroup: jest.fn(),
addFloatingGroup: jest.fn(),
}) as DockviewComponent;
}); });
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => { const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
@ -483,7 +467,6 @@ describe('tabsContainer', () => {
}) as DockviewGroupPanel; }) as DockviewGroupPanel;
}); });
const accessor = new accessorMock();
const groupPanel = new groupPanelMock(); const groupPanel = new groupPanelMock();
const cut = new TabsContainer(accessor, groupPanel); const cut = new TabsContainer(accessor, groupPanel);
@ -527,14 +510,12 @@ describe('tabsContainer', () => {
}); });
test('that a tab that is already floating cannot be floated again', () => { test('that a tab that is already floating cannot be floated again', () => {
const accessorMock = jest.fn<DockviewComponent, []>(() => { const accessor = fromPartial<DockviewComponent>({
return (<Partial<DockviewComponent>>{ options: { parentElement: document.createElement('div') },
options: { parentElement: document.createElement('div') }, onDidAddPanel: jest.fn(),
onDidAddPanel: jest.fn(), onDidRemovePanel: jest.fn(),
onDidRemovePanel: jest.fn(), element: document.createElement('div'),
element: document.createElement('div'), addFloatingGroup: jest.fn(),
addFloatingGroup: jest.fn(),
}) as DockviewComponent;
}); });
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => { const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
@ -543,7 +524,6 @@ describe('tabsContainer', () => {
}) as DockviewGroupPanel; }) as DockviewGroupPanel;
}); });
const accessor = new accessorMock();
const groupPanel = new groupPanelMock(); const groupPanel = new groupPanelMock();
const cut = new TabsContainer(accessor, groupPanel); const cut = new TabsContainer(accessor, groupPanel);
@ -579,15 +559,13 @@ describe('tabsContainer', () => {
}); });
test('that selecting a tab with shift down will move that tab into a new floating group', () => { test('that selecting a tab with shift down will move that tab into a new floating group', () => {
const accessorMock = jest.fn<DockviewComponent, []>(() => { const accessor = fromPartial<DockviewComponent>({
return (<Partial<DockviewComponent>>{ options: { parentElement: document.createElement('div') },
options: { parentElement: document.createElement('div') }, onDidAddPanel: jest.fn(),
onDidAddPanel: jest.fn(), onDidRemovePanel: jest.fn(),
onDidRemovePanel: jest.fn(), element: document.createElement('div'),
element: document.createElement('div'), addFloatingGroup: jest.fn(),
addFloatingGroup: jest.fn(), getGroupPanel: jest.fn(),
getGroupPanel: jest.fn(),
}) as DockviewComponent;
}); });
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => { const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
@ -597,7 +575,6 @@ describe('tabsContainer', () => {
}) as DockviewGroupPanel; }) as DockviewGroupPanel;
}); });
const accessor = new accessorMock();
const groupPanel = new groupPanelMock(); const groupPanel = new groupPanelMock();
const cut = new TabsContainer(accessor, groupPanel); const cut = new TabsContainer(accessor, groupPanel);
@ -638,15 +615,13 @@ describe('tabsContainer', () => {
}); });
test('pre header actions', () => { test('pre header actions', () => {
const accessorMock = jest.fn<DockviewComponent, []>(() => { const accessor = fromPartial<DockviewComponent>({
return (<Partial<DockviewComponent>>{ options: { parentElement: document.createElement('div') },
options: { parentElement: document.createElement('div') }, onDidAddPanel: jest.fn(),
onDidAddPanel: jest.fn(), onDidRemovePanel: jest.fn(),
onDidRemovePanel: jest.fn(), element: document.createElement('div'),
element: document.createElement('div'), addFloatingGroup: jest.fn(),
addFloatingGroup: jest.fn(), getGroupPanel: jest.fn(),
getGroupPanel: jest.fn(),
}) as DockviewComponent;
}); });
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => { const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
@ -656,7 +631,6 @@ describe('tabsContainer', () => {
}) as DockviewGroupPanel; }) as DockviewGroupPanel;
}); });
const accessor = new accessorMock();
const groupPanel = new groupPanelMock(); const groupPanel = new groupPanelMock();
const cut = new TabsContainer(accessor, groupPanel); const cut = new TabsContainer(accessor, groupPanel);
@ -708,15 +682,13 @@ describe('tabsContainer', () => {
}); });
test('left header actions', () => { test('left header actions', () => {
const accessorMock = jest.fn<DockviewComponent, []>(() => { const accessor = fromPartial<DockviewComponent>({
return (<Partial<DockviewComponent>>{ options: { parentElement: document.createElement('div') },
options: { parentElement: document.createElement('div') }, onDidAddPanel: jest.fn(),
onDidAddPanel: jest.fn(), onDidRemovePanel: jest.fn(),
onDidRemovePanel: jest.fn(), element: document.createElement('div'),
element: document.createElement('div'), addFloatingGroup: jest.fn(),
addFloatingGroup: jest.fn(), getGroupPanel: jest.fn(),
getGroupPanel: jest.fn(),
}) as DockviewComponent;
}); });
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => { const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
@ -726,7 +698,6 @@ describe('tabsContainer', () => {
}) as DockviewGroupPanel; }) as DockviewGroupPanel;
}); });
const accessor = new accessorMock();
const groupPanel = new groupPanelMock(); const groupPanel = new groupPanelMock();
const cut = new TabsContainer(accessor, groupPanel); const cut = new TabsContainer(accessor, groupPanel);
@ -778,15 +749,13 @@ describe('tabsContainer', () => {
}); });
test('right header actions', () => { test('right header actions', () => {
const accessorMock = jest.fn<DockviewComponent, []>(() => { const accessor = fromPartial<DockviewComponent>({
return (<Partial<DockviewComponent>>{ options: { parentElement: document.createElement('div') },
options: { parentElement: document.createElement('div') }, onDidAddPanel: jest.fn(),
onDidAddPanel: jest.fn(), onDidRemovePanel: jest.fn(),
onDidRemovePanel: jest.fn(), element: document.createElement('div'),
element: document.createElement('div'), addFloatingGroup: jest.fn(),
addFloatingGroup: jest.fn(), getGroupPanel: jest.fn(),
getGroupPanel: jest.fn(),
}) as DockviewComponent;
}); });
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => { const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
@ -796,7 +765,6 @@ describe('tabsContainer', () => {
}) as DockviewGroupPanel; }) as DockviewGroupPanel;
}); });
const accessor = new accessorMock();
const groupPanel = new groupPanelMock(); const groupPanel = new groupPanelMock();
const cut = new TabsContainer(accessor, groupPanel); const cut = new TabsContainer(accessor, groupPanel);

View File

@ -275,7 +275,7 @@ describe('dockviewGroupPanelModel', () => {
onDidParametersChange: new Emitter().event, onDidParametersChange: new Emitter().event,
}); });
dockview = (<Partial<DockviewComponent>>{ dockview = fromPartial<DockviewComponent>({
options: { parentElement: document.createElement('div') }, options: { parentElement: document.createElement('div') },
createWatermarkComponent: () => new Watermark(), createWatermarkComponent: () => new Watermark(),
doSetGroupActive: jest.fn(), doSetGroupActive: jest.fn(),
@ -287,7 +287,7 @@ describe('dockviewGroupPanelModel', () => {
overlayRenderContainer: new OverlayRenderContainer( overlayRenderContainer: new OverlayRenderContainer(
document.createElement('div') document.createElement('div')
), ),
}) as DockviewComponent; });
groupview = new DockviewGroupPanel(dockview, 'groupview-1', options); groupview = new DockviewGroupPanel(dockview, 'groupview-1', options);
groupview.initialize(); groupview.initialize();
@ -529,8 +529,13 @@ describe('dockviewGroupPanelModel', () => {
test('that group is set on panel during onDidAddPanel event', () => { test('that group is set on panel during onDidAddPanel event', () => {
const cut = new DockviewComponent({ const cut = new DockviewComponent({
parentElement: document.createElement('div'), parentElement: document.createElement('div'),
components: { createComponent(options) {
component: TestContentPart, switch (options.name) {
case 'component':
return new TestContentPart(options.id);
default:
throw new Error(`unsupported`);
}
}, },
}); });
@ -545,8 +550,13 @@ describe('dockviewGroupPanelModel', () => {
test('toJSON() default', () => { test('toJSON() default', () => {
const dockviewComponent = new DockviewComponent({ const dockviewComponent = new DockviewComponent({
parentElement: document.createElement('div'), parentElement: document.createElement('div'),
components: { createComponent(options) {
component: TestContentPart, switch (options.name) {
case 'component':
return new TestContentPart(options.id);
default:
throw new Error(`unsupported`);
}
}, },
}); });
@ -568,8 +578,13 @@ describe('dockviewGroupPanelModel', () => {
test('toJSON() locked and hideHeader', () => { test('toJSON() locked and hideHeader', () => {
const dockviewComponent = new DockviewComponent({ const dockviewComponent = new DockviewComponent({
parentElement: document.createElement('div'), parentElement: document.createElement('div'),
components: { createComponent(options) {
component: TestContentPart, switch (options.name) {
case 'component':
return new TestContentPart(options.id);
default:
throw new Error(`unsupported`);
}
}, },
}); });
@ -596,8 +611,13 @@ describe('dockviewGroupPanelModel', () => {
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({
parentElement: document.createElement('div'), parentElement: document.createElement('div'),
components: { createComponent(options) {
component: TestContentPart, switch (options.name) {
case 'component':
return new TestContentPart(options.id);
default:
throw new Error(`unsupported`);
}
}, },
}); });
@ -637,19 +657,16 @@ describe('dockviewGroupPanelModel', () => {
}); });
test('that should not show drop target is external event', () => { test('that should not show drop target is external event', () => {
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => { const accessor = fromPartial<DockviewComponent>({
return { id: 'testcomponentid',
id: 'testcomponentid', options: {
options: { parentElement: document.createElement('div'),
parentElement: document.createElement('div'), },
}, getPanel: jest.fn(),
getPanel: jest.fn(), onDidAddPanel: jest.fn(),
onDidAddPanel: jest.fn(), onDidRemovePanel: jest.fn(),
onDidRemovePanel: jest.fn(),
};
}); });
const accessor = new accessorMock() as DockviewComponent;
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>( const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
() => { () => {
return { return {
@ -704,18 +721,16 @@ describe('dockviewGroupPanelModel', () => {
}); });
test('that the .locked behaviour is as', () => { test('that the .locked behaviour is as', () => {
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => { const accessor = fromPartial<DockviewComponent>({
return { id: 'testcomponentid',
id: 'testcomponentid', options: {
options: { parentElement: document.createElement('div'),
parentElement: document.createElement('div'), },
}, getPanel: jest.fn(),
getPanel: jest.fn(), onDidAddPanel: jest.fn(),
onDidAddPanel: jest.fn(), onDidRemovePanel: jest.fn(),
onDidRemovePanel: jest.fn(),
};
}); });
const accessor = new accessorMock() as DockviewComponent;
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>( const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
() => { () => {
return { return {
@ -799,22 +814,20 @@ describe('dockviewGroupPanelModel', () => {
}); });
test('that should not show drop target if dropping on self', () => { test('that should not show drop target if dropping on self', () => {
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => { const accessor = fromPartial<DockviewComponent>({
return { id: 'testcomponentid',
id: 'testcomponentid', options: {
options: { parentElement: document.createElement('div'),
parentElement: document.createElement('div'), },
}, getPanel: jest.fn(),
getPanel: jest.fn(), doSetGroupActive: jest.fn(),
doSetGroupActive: jest.fn(), onDidAddPanel: jest.fn(),
onDidAddPanel: jest.fn(), onDidRemovePanel: jest.fn(),
onDidRemovePanel: jest.fn(), overlayRenderContainer: new OverlayRenderContainer(
overlayRenderContainer: new OverlayRenderContainer( document.createElement('div')
document.createElement('div') ),
),
};
}); });
const accessor = new accessorMock() as DockviewComponent;
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>( const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
() => { () => {
return { return {
@ -874,22 +887,20 @@ describe('dockviewGroupPanelModel', () => {
}); });
test('that should not allow drop when dropping on self for same component id', () => { test('that should not allow drop when dropping on self for same component id', () => {
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => { const accessor = fromPartial<DockviewComponent>({
return { id: 'testcomponentid',
id: 'testcomponentid', options: {
options: { parentElement: document.createElement('div'),
parentElement: document.createElement('div'), },
}, getPanel: jest.fn(),
getPanel: jest.fn(), doSetGroupActive: jest.fn(),
doSetGroupActive: jest.fn(), onDidAddPanel: jest.fn(),
onDidAddPanel: jest.fn(), onDidRemovePanel: jest.fn(),
onDidRemovePanel: jest.fn(), overlayRenderContainer: new OverlayRenderContainer(
overlayRenderContainer: new OverlayRenderContainer( document.createElement('div')
document.createElement('div') ),
),
};
}); });
const accessor = new accessorMock() as DockviewComponent;
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>( const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
() => { () => {
return { return {
@ -950,22 +961,20 @@ describe('dockviewGroupPanelModel', () => {
}); });
test('that should not allow drop when not dropping for different component id', () => { test('that should not allow drop when not dropping for different component id', () => {
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => { const accessor = fromPartial<DockviewComponent>({
return { id: 'testcomponentid',
id: 'testcomponentid', options: {
options: { parentElement: document.createElement('div'),
parentElement: document.createElement('div'), },
}, getPanel: jest.fn(),
getPanel: jest.fn(), doSetGroupActive: jest.fn(),
doSetGroupActive: jest.fn(), onDidAddPanel: jest.fn(),
onDidAddPanel: jest.fn(), onDidRemovePanel: jest.fn(),
onDidRemovePanel: jest.fn(), overlayRenderContainer: new OverlayRenderContainer(
overlayRenderContainer: new OverlayRenderContainer( document.createElement('div')
document.createElement('div') ),
),
};
}); });
const accessor = new accessorMock() as DockviewComponent;
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>( const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
() => { () => {
return { return {

View File

@ -1,16 +1,13 @@
import { import { DockviewComponent } from '../../dockview/dockviewComponent';
DockviewComponent,
IDockviewComponent,
} from '../../dockview/dockviewComponent';
import { DockviewPanelModel } from '../../dockview/dockviewPanelModel'; import { DockviewPanelModel } from '../../dockview/dockviewPanelModel';
import { IContentRenderer, ITabRenderer } from '../../dockview/types'; import { IContentRenderer, ITabRenderer } from '../../dockview/types';
import { GroupPanelFrameworkComponentFactory } from '../../dockview/options';
import { DefaultTab } from '../../dockview/components/tab/defaultTab'; import { DefaultTab } from '../../dockview/components/tab/defaultTab';
import { fromPartial } from '@total-typescript/shoehorn';
describe('dockviewGroupPanel', () => { describe('dockviewGroupPanel', () => {
let contentMock: jest.Mock<IContentRenderer>; let contentMock: jest.Mock<IContentRenderer>;
let tabMock: jest.Mock<ITabRenderer>; let tabMock: jest.Mock<ITabRenderer>;
let accessorMock: jest.Mock<IDockviewComponent>; let accessorMock: DockviewComponent;
beforeEach(() => { beforeEach(() => {
contentMock = jest.fn<IContentRenderer, []>(() => { contentMock = jest.fn<IContentRenderer, []>(() => {
@ -18,8 +15,6 @@ describe('dockviewGroupPanel', () => {
element: document.createElement('div'), element: document.createElement('div'),
dispose: jest.fn(), dispose: jest.fn(),
update: jest.fn(), update: jest.fn(),
// onGroupChange: jest.fn(),
// onPanelVisibleChange: jest.fn(),
}; };
return partial as IContentRenderer; return partial as IContentRenderer;
}); });
@ -29,32 +24,36 @@ describe('dockviewGroupPanel', () => {
element: document.createElement('div'), element: document.createElement('div'),
dispose: jest.fn(), dispose: jest.fn(),
update: jest.fn(), update: jest.fn(),
// onGroupChange: jest.fn(),
// onPanelVisibleChange: jest.fn(),
}; };
return partial as IContentRenderer; return partial as IContentRenderer;
}); });
accessorMock = jest.fn<DockviewComponent, []>(() => { accessorMock = fromPartial<DockviewComponent>({
const partial: Partial<DockviewComponent> = { options: {
options: { parentElement: document.createElement('div'),
parentElement: document.createElement('div'), createComponent(options) {
components: { switch (options.name) {
contentComponent: contentMock, case 'contentComponent':
}, return new contentMock(options.id, options.name);
tabComponents: { default:
tabComponent: tabMock, throw new Error(`unsupported`);
}, }
}, },
}; createTabComponent(options) {
switch (options.name) {
return partial as DockviewComponent; case 'tabComponent':
return new tabMock(options.id, options.name);
default:
throw new Error(`unsupported`);
}
},
},
}); });
}); });
test('that dispose is called on content and tab renderers when present', () => { test('that dispose is called on content and tab renderers when present', () => {
const cut = new DockviewPanelModel( const cut = new DockviewPanelModel(
<IDockviewComponent>new accessorMock(), accessorMock,
'id', 'id',
'contentComponent', 'contentComponent',
'tabComponent' 'tabComponent'
@ -68,7 +67,7 @@ describe('dockviewGroupPanel', () => {
test('that update is called on content and tab renderers when present', () => { test('that update is called on content and tab renderers when present', () => {
const cut = new DockviewPanelModel( const cut = new DockviewPanelModel(
<IDockviewComponent>new accessorMock(), accessorMock,
'id', 'id',
'contentComponent', 'contentComponent',
'tabComponent' 'tabComponent'
@ -82,73 +81,31 @@ describe('dockviewGroupPanel', () => {
expect(cut.tab.update).toHaveBeenCalled(); expect(cut.tab.update).toHaveBeenCalled();
}); });
// test('that events are fired', () => {
// const cut = new DockviewPanelModel(
// <IDockviewComponent>new accessorMock(),
// 'id',
// 'contentComponent',
// 'tabComponent'
// );
// const group1 = jest.fn() as any;
// const group2 = jest.fn() as any;
// cut.updateParentGroup(group1, false);
// expect(cut.content.onGroupChange).toHaveBeenNthCalledWith(1, group1);
// expect(cut.tab.onGroupChange).toHaveBeenNthCalledWith(1, group1);
// expect(cut.content.onPanelVisibleChange).toHaveBeenNthCalledWith(
// 1,
// false
// );
// expect(cut.tab.onPanelVisibleChange).toHaveBeenNthCalledWith(1, false);
// expect(cut.content.onGroupChange).toHaveBeenCalledTimes(1);
// expect(cut.tab.onGroupChange).toHaveBeenCalledTimes(1);
// expect(cut.content.onPanelVisibleChange).toHaveBeenCalledTimes(1);
// expect(cut.tab.onPanelVisibleChange).toHaveBeenCalledTimes(1);
// cut.updateParentGroup(group1, true);
// expect(cut.content.onPanelVisibleChange).toHaveBeenNthCalledWith(
// 2,
// true
// );
// expect(cut.tab.onPanelVisibleChange).toHaveBeenNthCalledWith(2, true);
// expect(cut.content.onGroupChange).toHaveBeenCalledTimes(1);
// expect(cut.tab.onGroupChange).toHaveBeenCalledTimes(1);
// expect(cut.content.onPanelVisibleChange).toHaveBeenCalledTimes(2);
// expect(cut.tab.onPanelVisibleChange).toHaveBeenCalledTimes(2);
// cut.updateParentGroup(group2, true);
// expect(cut.content.onGroupChange).toHaveBeenNthCalledWith(2, group2);
// expect(cut.tab.onGroupChange).toHaveBeenNthCalledWith(2, group2);
// expect(cut.content.onGroupChange).toHaveBeenCalledTimes(2);
// expect(cut.tab.onGroupChange).toHaveBeenCalledTimes(2);
// expect(cut.content.onPanelVisibleChange).toHaveBeenCalledTimes(2);
// expect(cut.tab.onPanelVisibleChange).toHaveBeenCalledTimes(2);
// });
test('that the default tab is created', () => { test('that the default tab is created', () => {
accessorMock = jest.fn<DockviewComponent, []>(() => { accessorMock = fromPartial<DockviewComponent>({
const partial: Partial<DockviewComponent> = { options: {
options: { parentElement: document.createElement('div'),
parentElement: document.createElement('div'), createComponent(options) {
components: { switch (options.name) {
contentComponent: contentMock, case 'contentComponent':
}, return new contentMock(options.id, options.name);
tabComponents: { default:
tabComponent: jest throw new Error(`unsupported`);
.fn() }
.mockImplementation(() => tabMock),
},
}, },
}; createTabComponent(options) {
switch (options.name) {
return partial as DockviewComponent; case 'tabComponent':
return tabMock;
default:
throw new Error(`unsupported`);
}
},
},
}); });
const cut = new DockviewPanelModel( const cut = new DockviewPanelModel(
<IDockviewComponent>new accessorMock(), accessorMock,
'id', 'id',
'contentComponent', 'contentComponent',
'tabComponent' 'tabComponent'
@ -158,27 +115,31 @@ describe('dockviewGroupPanel', () => {
}); });
test('that the provided default tab is chosen when no implementation is provided', () => { test('that the provided default tab is chosen when no implementation is provided', () => {
accessorMock = jest.fn<DockviewComponent, []>(() => { accessorMock = fromPartial<DockviewComponent>({
const partial: Partial<DockviewComponent> = { options: {
options: { parentElement: document.createElement('div'),
parentElement: document.createElement('div'), defaultTabComponent: 'tabComponent',
components: { createComponent(options) {
contentComponent: contentMock, switch (options.name) {
}, case 'contentComponent':
tabComponents: { return new contentMock(options.id, options.name);
tabComponent: jest default:
.fn() throw new Error(`unsupported`);
.mockImplementation(() => tabMock), }
},
defaultTabComponent: 'tabComponent',
}, },
}; createTabComponent(options) {
switch (options.name) {
return partial as DockviewComponent; case 'tabComponent':
return tabMock;
default:
throw new Error(`unsupported`);
}
},
},
}); });
const cut = new DockviewPanelModel( const cut = new DockviewPanelModel(
<IDockviewComponent>new accessorMock(), accessorMock,
'id', 'id',
'contentComponent' 'contentComponent'
); );
@ -186,58 +147,23 @@ describe('dockviewGroupPanel', () => {
expect(cut.tab).toEqual(tabMock); expect(cut.tab).toEqual(tabMock);
}); });
test('that the framework tab is created when provided tab is a framework tab', () => {
const tab = jest.fn();
const tabFactory = jest.fn().mockImplementation(() => tab);
accessorMock = jest.fn<DockviewComponent, []>(() => {
const partial: Partial<DockviewComponent> = {
options: {
parentElement: document.createElement('div'),
components: {
contentComponent: contentMock,
},
frameworkTabComponents: {
tabComponent: tabMock,
},
frameworkComponentFactory: (<
Partial<GroupPanelFrameworkComponentFactory>
>{
tab: { createComponent: tabFactory },
}) as GroupPanelFrameworkComponentFactory,
},
};
return partial as DockviewComponent;
});
const cut = new DockviewPanelModel(
<IDockviewComponent>new accessorMock(),
'id',
'contentComponent',
'tabComponent'
);
expect(tabFactory).toHaveBeenCalledWith('id', 'tabComponent', tabMock);
expect(cut.tab).toEqual(tab);
});
test('that is library default tab instance is created when no alternative exists', () => { test('that is library default tab instance is created when no alternative exists', () => {
accessorMock = jest.fn<DockviewComponent, []>(() => { accessorMock = fromPartial<DockviewComponent>({
const partial: Partial<DockviewComponent> = { options: {
options: { parentElement: document.createElement('div'),
parentElement: document.createElement('div'), createComponent(options) {
components: { switch (options.name) {
contentComponent: contentMock, case 'contentComponent':
}, return new contentMock(options.id, options.name);
default:
throw new Error(`unsupported`);
}
}, },
}; },
return partial as DockviewComponent;
}); });
const cut = new DockviewPanelModel( const cut = new DockviewPanelModel(
<IDockviewComponent>new accessorMock(), accessorMock,
'id', 'id',
'contentComponent' 'contentComponent'
); );
@ -246,63 +172,34 @@ describe('dockviewGroupPanel', () => {
}); });
test('that the default content is created', () => { test('that the default content is created', () => {
accessorMock = jest.fn<DockviewComponent, []>(() => { accessorMock = fromPartial<DockviewComponent>({
const partial: Partial<DockviewComponent> = { options: {
options: { parentElement: document.createElement('div'),
parentElement: document.createElement('div'), createComponent(options) {
components: { switch (options.name) {
contentComponent: jest.fn().mockImplementation(() => { case 'contentComponent':
return contentMock; return contentMock;
}), default:
}, throw new Error(`unsupported`);
}
}, },
}; createTabComponent(options) {
switch (options.name) {
return partial as DockviewComponent; case 'tabComponent':
return tabMock;
default:
throw new Error(`unsupported`);
}
},
},
}); });
const cut = new DockviewPanelModel( const cut = new DockviewPanelModel(
<IDockviewComponent>new accessorMock(), accessorMock,
'id', 'id',
'contentComponent' 'contentComponent'
); );
expect(cut.content).toEqual(contentMock); expect(cut.content).toEqual(contentMock);
}); });
test('that the framework content is created', () => {
const content = jest.fn();
const contentFactory = jest.fn().mockImplementation(() => content);
accessorMock = jest.fn<DockviewComponent, []>(() => {
const partial: Partial<DockviewComponent> = {
options: {
parentElement: document.createElement('div'),
frameworkComponents: {
contentComponent: contentMock,
},
frameworkComponentFactory: (<
Partial<GroupPanelFrameworkComponentFactory>
>{
content: { createComponent: contentFactory },
}) as GroupPanelFrameworkComponentFactory,
},
};
return partial as DockviewComponent;
});
const cut = new DockviewPanelModel(
<IDockviewComponent>new accessorMock(),
'id',
'contentComponent'
);
expect(contentFactory).toHaveBeenCalledWith(
'id',
'contentComponent',
contentMock
);
expect(cut.content).toEqual(content);
});
}); });

View File

@ -18,7 +18,6 @@ import { Watermark } from './components/watermark/watermark';
import { IWatermarkRenderer, GroupviewPanelState } from './types'; import { IWatermarkRenderer, GroupviewPanelState } from './types';
import { sequentialNumberGenerator } from '../math'; import { sequentialNumberGenerator } from '../math';
import { DefaultDockviewDeserialzier } from './deserializer'; import { DefaultDockviewDeserialzier } from './deserializer';
import { createComponent } from '../panel/componentFactory';
import { import {
AddGroupOptions, AddGroupOptions,
AddPanelOptions, AddPanelOptions,
@ -68,7 +67,6 @@ import {
OverlayRenderContainer, OverlayRenderContainer,
} from '../overlayRenderContainer'; } from '../overlayRenderContainer';
import { PopoutWindow } from '../popoutWindow'; import { PopoutWindow } from '../popoutWindow';
import { TitleEvent } from '../api/dockviewPanelApi';
const DEFAULT_ROOT_OVERLAY_MODEL: DroptargetOverlayModel = { const DEFAULT_ROOT_OVERLAY_MODEL: DroptargetOverlayModel = {
activationSize: { type: 'pixels', value: 10 }, activationSize: { type: 'pixels', value: 10 },
@ -503,25 +501,6 @@ export class DockviewComponent
this._options = options; this._options = options;
if (!this.options.components) {
this.options.components = {};
}
if (!this.options.frameworkComponents) {
this.options.frameworkComponents = {};
}
if (!this.options.frameworkTabComponents) {
this.options.frameworkTabComponents = {};
}
if (!this.options.tabComponents) {
this.options.tabComponents = {};
}
if (
!this.options.watermarkComponent &&
!this.options.watermarkFrameworkComponent
) {
this.options.watermarkComponent = Watermark;
}
this._rootDropTarget = new Droptarget(this.element, { this._rootDropTarget = new Droptarget(this.element, {
canDisplayOverlay: (event, position) => { canDisplayOverlay: (event, position) => {
const data = getPanelData(); const data = getPanelData();
@ -1606,17 +1585,10 @@ export class DockviewComponent
} }
createWatermarkComponent(): IWatermarkRenderer { createWatermarkComponent(): IWatermarkRenderer {
return createComponent( if (this.options.createWatermarkComponent) {
'watermark-id', return this.options.createWatermarkComponent();
'watermark-name', }
this.options.watermarkComponent return new Watermark();
? { 'watermark-name': this.options.watermarkComponent }
: {},
this.options.watermarkFrameworkComponent
? { 'watermark-name': this.options.watermarkFrameworkComponent }
: {},
this.options.frameworkComponentFactory?.watermark
);
} }
private updateWatermark(): void { private updateWatermark(): void {

View File

@ -546,9 +546,9 @@ export class DockviewGroupPanelModel
this.setActive(this.isActive, true); this.setActive(this.isActive, true);
this.updateContainer(); this.updateContainer();
if (this.accessor.options.headerRightActionComponent) { if (this.accessor.options.createRightHeaderActionComponent) {
this._rightHeaderActions = this._rightHeaderActions =
this.accessor.options.headerRightActionComponent( this.accessor.options.createRightHeaderActionComponent(
this.groupPanel this.groupPanel
); );
this.addDisposables(this._rightHeaderActions); this.addDisposables(this._rightHeaderActions);
@ -562,9 +562,9 @@ export class DockviewGroupPanelModel
); );
} }
if (this.accessor.options.headerLeftActionComponent) { if (this.accessor.options.createLeftHeaderActionComponent) {
this._leftHeaderActions = this._leftHeaderActions =
this.accessor.options.headerLeftActionComponent( this.accessor.options.createLeftHeaderActionComponent(
this.groupPanel this.groupPanel
); );
this.addDisposables(this._leftHeaderActions); this.addDisposables(this._leftHeaderActions);
@ -578,9 +578,9 @@ export class DockviewGroupPanelModel
); );
} }
if (this.accessor.options.headerPrefixActionComponent) { if (this.accessor.options.createPrefixHeaderActionComponent) {
this._prefixHeaderActions = this._prefixHeaderActions =
this.accessor.options.headerPrefixActionComponent( this.accessor.options.createPrefixHeaderActionComponent(
this.groupPanel this.groupPanel
); );
this.addDisposables(this._prefixHeaderActions); this.addDisposables(this._prefixHeaderActions);

View File

@ -6,7 +6,6 @@ import {
} from './types'; } from './types';
import { DockviewGroupPanel } from './dockviewGroupPanel'; import { DockviewGroupPanel } from './dockviewGroupPanel';
import { IDisposable } from '../lifecycle'; import { IDisposable } from '../lifecycle';
import { createComponent } from '../panel/componentFactory';
import { IDockviewComponent } from './dockviewComponent'; import { IDockviewComponent } from './dockviewComponent';
import { PanelUpdateEvent } from '../panel/types'; import { PanelUpdateEvent } from '../panel/types';
@ -73,39 +72,37 @@ export class DockviewPanelModel implements IDockviewPanelModel {
id: string, id: string,
componentName: string componentName: string
): IContentRenderer { ): IContentRenderer {
return createComponent( return this.accessor.options.createComponent({
id, id,
componentName, name: componentName,
this.accessor.options.components ?? {}, });
this.accessor.options.frameworkComponents,
this.accessor.options.frameworkComponentFactory?.content
);
} }
private createTabComponent( private createTabComponent(
id: string, id: string,
componentName?: string componentName?: string
): ITabRenderer { ): ITabRenderer {
if (componentName) { const name = componentName ?? this.accessor.options.defaultTabComponent;
return createComponent(
id, if (name) {
componentName, if (this.accessor.options.createTabComponent) {
this.accessor.options.tabComponents, const component = this.accessor.options.createTabComponent({
this.accessor.options.frameworkTabComponents, id,
this.accessor.options.frameworkComponentFactory?.tab, name,
() => new DefaultTab() });
if (component) {
return component;
} else {
return new DefaultTab();
}
}
console.warn(
`dockview: tabComponent '${componentName}' was not found. falling back to the default tab.`
); );
} else if (this.accessor.options.defaultTabComponent) {
return createComponent(
id,
this.accessor.options.defaultTabComponent,
this.accessor.options.tabComponents,
this.accessor.options.frameworkTabComponents,
this.accessor.options.frameworkComponentFactory?.tab,
() => new DefaultTab()
);
} else {
return new DefaultTab();
} }
return new DefaultTab();
} }
} }

View File

@ -1,12 +1,7 @@
import { DockviewApi } from '../api/component.api'; import { DockviewApi } from '../api/component.api';
import { Direction } from '../gridview/baseComponentGridview'; import { Direction } from '../gridview/baseComponentGridview';
import { IGridView } from '../gridview/gridview'; import { IGridView } from '../gridview/gridview';
import { import { IContentRenderer, ITabRenderer, IWatermarkRenderer } from './types';
IContentRenderer,
ITabRenderer,
WatermarkConstructor,
IWatermarkRenderer,
} from './types';
import { Parameters } from '../panel/types'; import { Parameters } from '../panel/types';
import { DockviewGroupPanel } from './dockviewGroupPanel'; import { DockviewGroupPanel } from './dockviewGroupPanel';
import { PanelTransfer } from '../dnd/dataTransfer'; import { PanelTransfer } from '../dnd/dataTransfer';
@ -17,10 +12,6 @@ import {
GroupOptions, GroupOptions,
} from './dockviewGroupPanelModel'; } from './dockviewGroupPanelModel';
import { IDockviewPanel } from './dockviewPanel'; import { IDockviewPanel } from './dockviewPanel';
import {
ComponentConstructor,
FrameworkFactory,
} from '../panel/componentFactory';
import { DockviewPanelRenderer } from '../overlayRenderContainer'; import { DockviewPanelRenderer } from '../overlayRenderContainer';
import { IGroupHeaderProps } from './framework'; import { IGroupHeaderProps } from './framework';
@ -29,12 +20,6 @@ export interface IHeaderActionsRenderer extends IDisposable {
init(params: IGroupHeaderProps): void; init(params: IGroupHeaderProps): void;
} }
export interface GroupPanelFrameworkComponentFactory {
content: FrameworkFactory<IContentRenderer>;
tab: FrameworkFactory<ITabRenderer>;
watermark: FrameworkFactory<IWatermarkRenderer>;
}
export interface TabContextMenuEvent { export interface TabContextMenuEvent {
event: MouseEvent; event: MouseEvent;
api: DockviewApi; api: DockviewApi;
@ -119,32 +104,26 @@ export const PROPERTY_KEYS: (keyof DockviewOptions)[] = (() => {
})(); })();
export interface DockviewFrameworkOptions { export interface DockviewFrameworkOptions {
headerRightActionComponent?: (
group: DockviewGroupPanel
) => IHeaderActionsRenderer;
headerLeftActionComponent?: (
group: DockviewGroupPanel
) => IHeaderActionsRenderer;
headerPrefixActionComponent?: (
group: DockviewGroupPanel
) => IHeaderActionsRenderer;
tabComponents?: {
[componentName: string]: ComponentConstructor<ITabRenderer>;
};
components?: {
[componentName: string]: ComponentConstructor<IContentRenderer>;
};
frameworkTabComponents?: {
[componentName: string]: any;
};
frameworkComponents?: {
[componentName: string]: any;
};
parentElement: HTMLElement; parentElement: HTMLElement;
defaultTabComponent?: string; defaultTabComponent?: string;
watermarkComponent?: WatermarkConstructor; createRightHeaderActionComponent?: (
watermarkFrameworkComponent?: any; group: DockviewGroupPanel
frameworkComponentFactory?: GroupPanelFrameworkComponentFactory; ) => IHeaderActionsRenderer;
createLeftHeaderActionComponent?: (
group: DockviewGroupPanel
) => IHeaderActionsRenderer;
createPrefixHeaderActionComponent?: (
group: DockviewGroupPanel
) => IHeaderActionsRenderer;
createTabComponent?: (options: {
id: string;
name: string;
}) => ITabRenderer | undefined;
createComponent: (options: {
id: string;
name: string;
}) => IContentRenderer;
createWatermarkComponent?: () => IWatermarkRenderer;
} }
export type DockviewComponentOptions = DockviewOptions & export type DockviewComponentOptions = DockviewOptions &

View File

@ -42,7 +42,7 @@
], ],
"scripts": { "scripts": {
"build-only": "vite build", "build-only": "vite build",
"build": "npm run build:package && npm run build:bundles", "build": "npm run build:package",
"build:bundles": "rollup -c", "build:bundles": "rollup -c",
"build:cjs": "cross-env ../../node_modules/.bin/vue-tsc --build ./tsconfig.json --verbose --extendedDiagnostics", "build:cjs": "cross-env ../../node_modules/.bin/vue-tsc --build ./tsconfig.json --verbose --extendedDiagnostics",
"build:css": "gulp sass", "build:css": "gulp sass",
@ -58,4 +58,4 @@
"dependencies": { "dependencies": {
"dockview-core": "^1.10.1" "dockview-core": "^1.10.1"
} }
} }

View File

@ -30,23 +30,19 @@ import {
VueHeaderActionsRenderer, VueHeaderActionsRenderer,
VueTabRenderer, VueTabRenderer,
VueWatermarkRenderer, VueWatermarkRenderer,
type VueComponent, findComponent,
} from '../utils'; } from '../utils';
interface VueProps { interface VueProps {
components: Record<string, VueComponent<IDockviewPanelProps>>; watermarkComponent?: string;
tabComponents?: Record<string, VueComponent<IDockviewPanelHeaderProps>>; defaultTabComponent?: string;
watermarkComponent?: VueComponent<IWatermarkPanelProps>; rightHeaderActionsComponent?: string;
defaultTabComponent?: VueComponent<IDockviewPanelHeaderProps>; leftHeaderActionsComponent?: string;
rightHeaderActionsComponent?: VueComponent<IGroupPanelBaseProps>; prefixHeaderActionsComponent?: string;
leftHeaderActionsComponent?: VueComponent<IGroupPanelBaseProps>;
prefixHeaderActionsComponent?: VueComponent<IGroupPanelBaseProps>;
} }
const VUE_PROPERTIES = (() => { const VUE_PROPERTIES = (() => {
const _value: Record<keyof VueProps, undefined> = { const _value: Record<keyof VueProps, undefined> = {
components: undefined,
tabComponents: undefined,
watermarkComponent: undefined, watermarkComponent: undefined,
defaultTabComponent: undefined, defaultTabComponent: undefined,
rightHeaderActionsComponent: undefined, rightHeaderActionsComponent: undefined,
@ -61,8 +57,6 @@ type VueEvents = {
ready: [event: DockviewReadyEvent]; ready: [event: DockviewReadyEvent];
}; };
const DEFAULT_REACT_TAB = 'props.defaultTabComponent';
export type IDockviewVueProps = DockviewOptions & VueProps; export type IDockviewVueProps = DockviewOptions & VueProps;
function extractCoreOptions(props: IDockviewVueProps): DockviewOptions { function extractCoreOptions(props: IDockviewVueProps): DockviewOptions {
@ -79,7 +73,6 @@ function extractCoreOptions(props: IDockviewVueProps): DockviewOptions {
const emit = defineEmits<VueEvents>(); const emit = defineEmits<VueEvents>();
/** /**
* Anything here that is a Vue.js component should not be reactive * Anything here that is a Vue.js component should not be reactive
* i.e. markRaw(toRaw(...)) * i.e. markRaw(toRaw(...))
@ -89,7 +82,6 @@ const props = defineProps<IDockviewVueProps>();
const el = ref<HTMLElement | null>(null); const el = ref<HTMLElement | null>(null);
const instance = ref<DockviewComponent | null>(null); const instance = ref<DockviewComponent | null>(null);
PROPERTY_KEYS.forEach((coreOptionKey) => { PROPERTY_KEYS.forEach((coreOptionKey) => {
watch( watch(
() => props[coreOptionKey], () => props[coreOptionKey],
@ -101,180 +93,87 @@ PROPERTY_KEYS.forEach((coreOptionKey) => {
); );
}); });
watch(
() => props.components,
(newValue, oldValue) => {
if (instance.value) {
instance.value.updateOptions({ frameworkComponents: newValue });
}
}
);
watch(
() => [props.tabComponents, props.defaultTabComponent],
([newTabComponents, newDefaultTabComponent], oldValue) => {
if (instance.value) {
const frameworkTabComponents = newTabComponents ?? {};
if (newDefaultTabComponent) {
frameworkTabComponents[DEFAULT_REACT_TAB] =
newDefaultTabComponent;
}
instance.value.updateOptions({
defaultTabComponent: newDefaultTabComponent
? DEFAULT_REACT_TAB
: undefined,
frameworkTabComponents,
});
}
}
);
watch(
() => props.watermarkComponent,
(newValue, oldValue) => {
if (instance.value) {
instance.value.updateOptions({
watermarkFrameworkComponent: newValue,
});
}
}
);
watch(
() => props.leftHeaderActionsComponent,
(newValue, oldValue) => {
if (instance.value) {
instance.value.updateOptions({
headerLeftActionComponent: newValue
? (group) => {
return new VueHeaderActionsRenderer(
newValue as VueComponent,
getCurrentInstance()!,
group
);
}
: undefined,
});
}
}
);
watch(
() => props.rightHeaderActionsComponent,
(newValue, oldValue) => {
if (instance.value) {
instance.value.updateOptions({
headerRightActionComponent: newValue
? (group) => {
return new VueHeaderActionsRenderer(
newValue as VueComponent,
getCurrentInstance()!,
group
);
}
: undefined,
});
}
}
);
watch(
() => props.prefixHeaderActionsComponent,
(newValue, oldValue) => {
if (instance.value) {
instance.value.updateOptions({
headerPrefixActionComponent: newValue
? (group) => {
return new VueHeaderActionsRenderer(
newValue as VueComponent,getCurrentInstance()!,
group
);
}
: undefined,
});
}
}
);
onMounted(() => { onMounted(() => {
if (!el.value) { if (!el.value) {
throw new Error('element is not mounted'); throw new Error('element is not mounted');
} }
const frameworkTabComponents = props.tabComponents ?? {};
if (props.defaultTabComponent) {
frameworkTabComponents[DEFAULT_REACT_TAB] = props.defaultTabComponent;
}
const frameworkOptions: DockviewFrameworkOptions = { const frameworkOptions: DockviewFrameworkOptions = {
parentElement: el.value, parentElement: el.value,
frameworkComponentFactory: { createComponent(options) {
content: { const component = findComponent(
createComponent: ( getCurrentInstance()!,
id: string, options.name
componentId: string, );
component: any return new VueContentRenderer(component!, getCurrentInstance()!);
): IContentRenderer => {
return new VueContentRenderer(component,getCurrentInstance()!);
},
},
tab: {
createComponent: (
id: string,
componentId: string,
component: any
): ITabRenderer => {
return new VueTabRenderer(component,getCurrentInstance()!);
},
},
watermark: {
createComponent: (
id: string,
componentId: string,
component: any
): IWatermarkRenderer => {
return new VueWatermarkRenderer(component,getCurrentInstance()!);
},
},
// action: {
// createComponent: (id: string, componentId: string, component: any): IWatermarkRenderer => {
// return new VueHeaderActionRenderer(component)
// }
// }
}, },
frameworkComponents: props.components, createTabComponent(options) {
frameworkTabComponents, let component = findComponent(getCurrentInstance()!, options.name);
headerLeftActionComponent: props.leftHeaderActionsComponent
if (!component && props.defaultTabComponent) {
component = findComponent(
getCurrentInstance()!,
props.defaultTabComponent
);
}
if (component) {
return new VueTabRenderer(component, getCurrentInstance()!);
}
return undefined;
},
createWatermarkComponent: props.watermarkComponent
? () => {
const component = findComponent(
getCurrentInstance()!,
props.watermarkComponent!
);
return new VueWatermarkRenderer(
component!,
getCurrentInstance()!
);
}
: undefined,
createLeftHeaderActionComponent: props.leftHeaderActionsComponent
? (group) => { ? (group) => {
const component = findComponent(
getCurrentInstance()!,
props.leftHeaderActionsComponent!
);
return new VueHeaderActionsRenderer( return new VueHeaderActionsRenderer(
props.leftHeaderActionsComponent as VueComponent,getCurrentInstance()!, component!,
getCurrentInstance()!,
group group
); );
} }
: undefined, : undefined,
headerPrefixActionComponent: props.prefixHeaderActionsComponent createPrefixHeaderActionComponent: props.prefixHeaderActionsComponent
? (group) => { ? (group) => {
const component = findComponent(
getCurrentInstance()!,
props.prefixHeaderActionsComponent!
);
return new VueHeaderActionsRenderer( return new VueHeaderActionsRenderer(
props.prefixHeaderActionsComponent as VueComponent,getCurrentInstance()!, component!,
getCurrentInstance()!,
group group
); );
} }
: undefined, : undefined,
headerRightActionComponent: props.rightHeaderActionsComponent createRightHeaderActionComponent: props.rightHeaderActionsComponent
? (group) => { ? (group) => {
const component = findComponent(
getCurrentInstance()!,
props.rightHeaderActionsComponent!
);
return new VueHeaderActionsRenderer( return new VueHeaderActionsRenderer(
props.rightHeaderActionsComponent as VueComponent,getCurrentInstance()!, component!,
getCurrentInstance()!,
group group
); );
} }
: undefined, : undefined,
defaultTabComponent: props.defaultTabComponent
? DEFAULT_REACT_TAB
: undefined,
watermarkFrameworkComponent:props.watermarkComponent
}; };
const dockview = new DockviewComponent({ const dockview = new DockviewComponent({
@ -300,6 +199,7 @@ onMounted(() => {
*/ */
instance.value = markRaw(dockview); instance.value = markRaw(dockview);
console.log(getCurrentInstance());
emit('ready', { api: new DockviewApi(dockview) }); emit('ready', { api: new DockviewApi(dockview) });
}); });

View File

@ -2,9 +2,12 @@ import type {
DockviewGroupPanel, DockviewGroupPanel,
GroupPanelPartInitParameters, GroupPanelPartInitParameters,
IContentRenderer, IContentRenderer,
IDockviewPanelHeaderProps,
IDockviewPanelProps,
IGroupHeaderProps, IGroupHeaderProps,
IHeaderActionsRenderer, IHeaderActionsRenderer,
ITabRenderer, ITabRenderer,
IWatermarkPanelProps,
IWatermarkRenderer, IWatermarkRenderer,
PanelUpdateEvent, PanelUpdateEvent,
Parameters, Parameters,
@ -15,7 +18,6 @@ import {
type ComponentOptionsBase, type ComponentOptionsBase,
render, render,
cloneVNode, cloneVNode,
mergeProps,
type DefineComponent, type DefineComponent,
type ComponentInternalInstance, type ComponentInternalInstance,
} from 'vue'; } from 'vue';
@ -33,6 +35,29 @@ export type ComponentInterface = ComponentOptionsBase<
export type VueComponent<T = any> = DefineComponent<T>; export type VueComponent<T = any> = DefineComponent<T>;
export function findComponent(
parent: ComponentInternalInstance,
name: string
): VueComponent | null {
let instance = parent as any;
let component = null;
while (!component && instance) {
component = instance.components?.[name];
instance = instance.parent;
}
if (!component) {
component = parent.appContext.components?.[name];
}
if (!component) {
throw new Error(`Failed to find Vue Component '${name}'`);
}
return component;
}
/** /**
* TODO List * TODO List
* *
@ -90,7 +115,7 @@ export class VueContentRenderer implements IContentRenderer {
} }
init(parameters: GroupPanelPartInitParameters): void { init(parameters: GroupPanelPartInitParameters): void {
const props = { const props: IDockviewPanelProps = {
params: parameters.params, params: parameters.params,
api: parameters.api, api: parameters.api,
containerApi: parameters.containerApi, containerApi: parameters.containerApi,
@ -100,7 +125,7 @@ export class VueContentRenderer implements IContentRenderer {
this._renderDisposable = mountVueComponent( this._renderDisposable = mountVueComponent(
this.component, this.component,
this.parent, this.parent,
props, { params: props },
this.element this.element
); );
} }
@ -141,7 +166,7 @@ export class VueTabRenderer implements ITabRenderer {
} }
init(parameters: GroupPanelPartInitParameters): void { init(parameters: GroupPanelPartInitParameters): void {
const props = { const props: IDockviewPanelHeaderProps = {
params: parameters.params, params: parameters.params,
api: parameters.api, api: parameters.api,
containerApi: parameters.containerApi, containerApi: parameters.containerApi,
@ -151,7 +176,7 @@ export class VueTabRenderer implements ITabRenderer {
this._renderDisposable = mountVueComponent( this._renderDisposable = mountVueComponent(
this.component, this.component,
this.parent, this.parent,
props, { params: props },
this.element this.element
); );
} }
@ -188,7 +213,7 @@ export class VueWatermarkRenderer implements IWatermarkRenderer {
} }
init(parameters: WatermarkRendererInitParameters): void { init(parameters: WatermarkRendererInitParameters): void {
const props = { const props: IWatermarkPanelProps = {
group: parameters.group, group: parameters.group,
containerApi: parameters.containerApi, containerApi: parameters.containerApi,
}; };
@ -197,7 +222,7 @@ export class VueWatermarkRenderer implements IWatermarkRenderer {
this._renderDisposable = mountVueComponent( this._renderDisposable = mountVueComponent(
this.component, this.component,
this.parent, this.parent,
props, { params: props },
this.element this.element
); );
} }
@ -238,13 +263,12 @@ export class VueHeaderActionsRenderer implements IHeaderActionsRenderer {
this._element.style.height = '100%'; this._element.style.height = '100%';
} }
init(params: IGroupHeaderProps): void { init(props: IGroupHeaderProps): void {
console.log(params);
this._renderDisposable?.dispose(); this._renderDisposable?.dispose();
this._renderDisposable = mountVueComponent( this._renderDisposable = mountVueComponent(
this.component, this.component,
this.parent, this.parent,
{ ...params }, { params: props },
this.element this.element
); );
} }

View File

@ -6,6 +6,7 @@ import vue from '@vitejs/plugin-vue';
export default defineConfig({ export default defineConfig({
plugins: [vue()], plugins: [vue()],
build: { build: {
minify: false,
lib: { lib: {
// src/indext.ts is where we have exported the component(s) // src/indext.ts is where we have exported the component(s)
entry: resolve(__dirname, 'src/index.ts'), entry: resolve(__dirname, 'src/index.ts'),

View File

@ -2,7 +2,6 @@ import React from 'react';
import { import {
DockviewComponent, DockviewComponent,
DockviewWillDropEvent, DockviewWillDropEvent,
GroupPanelFrameworkComponentFactory,
DockviewApi, DockviewApi,
IContentRenderer, IContentRenderer,
ITabRenderer, ITabRenderer,
@ -70,7 +69,9 @@ export interface IDockviewReactProps extends DockviewOptions {
function extractCoreOptions(props: IDockviewReactProps): DockviewOptions { function extractCoreOptions(props: IDockviewReactProps): DockviewOptions {
const coreOptions = (PROPERTY_KEYS as (keyof DockviewOptions)[]).reduce( const coreOptions = (PROPERTY_KEYS as (keyof DockviewOptions)[]).reduce(
(obj, key) => { (obj, key) => {
obj[key] = props[key] as any; if (key in props) {
obj[key] = props[key] as any;
}
return obj; return obj;
}, },
{} as Partial<DockviewComponentOptions> {} as Partial<DockviewComponentOptions>
@ -79,46 +80,6 @@ function extractCoreOptions(props: IDockviewReactProps): DockviewOptions {
return coreOptions as DockviewOptions; return coreOptions as DockviewOptions;
} }
function createFrameworkFactory(
addPortal: (portal: React.ReactPortal) => IDockviewDisposable
): GroupPanelFrameworkComponentFactory {
return {
content: {
createComponent: (
_id: string,
componentId: string,
component: React.FunctionComponent<IDockviewPanelProps>
): IContentRenderer => {
return new ReactPanelContentPart(componentId, component, {
addPortal,
});
},
},
tab: {
createComponent: (
_id: string,
componentId: string,
component: React.FunctionComponent<IDockviewPanelHeaderProps>
): ITabRenderer => {
return new ReactPanelHeaderPart(componentId, component, {
addPortal,
});
},
},
watermark: {
createComponent: (
_id: string,
componentId: string,
component: React.FunctionComponent<{}>
) => {
return new ReactWatermarkPart(componentId, component, {
addPortal,
});
},
},
};
}
export const DockviewReact = React.forwardRef( export const DockviewReact = React.forwardRef(
(props: IDockviewReactProps, ref: React.ForwardedRef<HTMLDivElement>) => { (props: IDockviewReactProps, ref: React.ForwardedRef<HTMLDivElement>) => {
const domRef = React.useRef<HTMLDivElement>(null); const domRef = React.useRef<HTMLDivElement>(null);
@ -137,7 +98,7 @@ export const DockviewReact = React.forwardRef(
const key = propKey as keyof DockviewOptions; const key = propKey as keyof DockviewOptions;
const propValue = props[key]; const propValue = props[key];
if (propValue !== prevProps.current[key]) { if (key in props && propValue !== prevProps.current[key]) {
changes[key] = propValue as any; changes[key] = propValue as any;
} }
}); });
@ -166,26 +127,51 @@ export const DockviewReact = React.forwardRef(
} }
const frameworkOptions: DockviewFrameworkOptions = { const frameworkOptions: DockviewFrameworkOptions = {
headerLeftActionComponent: createGroupControlElement( createLeftHeaderActionComponent: createGroupControlElement(
props.leftHeaderActionsComponent, props.leftHeaderActionsComponent,
{ addPortal } { addPortal }
), ),
headerRightActionComponent: createGroupControlElement( createRightHeaderActionComponent: createGroupControlElement(
props.rightHeaderActionsComponent, props.rightHeaderActionsComponent,
{ addPortal } { addPortal }
), ),
headerPrefixActionComponent: createGroupControlElement( createPrefixHeaderActionComponent: createGroupControlElement(
props.prefixHeaderActionsComponent, props.prefixHeaderActionsComponent,
{ addPortal } { addPortal }
), ),
frameworkTabComponents, createComponent: (options) => {
frameworkComponents: props.components, return new ReactPanelContentPart(
frameworkComponentFactory: createFrameworkFactory(addPortal), options.id,
props.components[options.name],
{
addPortal,
}
);
},
createTabComponent(options) {
return new ReactPanelHeaderPart(
options.id,
frameworkTabComponents[options.name],
{
addPortal,
}
);
},
createWatermarkComponent: props.watermarkComponent
? () => {
return new ReactWatermarkPart(
'watermark',
props.watermarkComponent!,
{
addPortal,
}
);
}
: undefined,
parentElement: domRef.current, parentElement: domRef.current,
defaultTabComponent: props.defaultTabComponent defaultTabComponent: props.defaultTabComponent
? DEFAULT_REACT_TAB ? DEFAULT_REACT_TAB
: undefined, : undefined,
watermarkFrameworkComponent: props.watermarkComponent,
}; };
const dockview = new DockviewComponent({ const dockview = new DockviewComponent({
@ -267,20 +253,20 @@ export const DockviewReact = React.forwardRef(
if (!dockviewRef.current) { if (!dockviewRef.current) {
return; return;
} }
dockviewRef.current.updateOptions({ dockviewRef.current.updateOptions({
frameworkComponents: props.components, createComponent: (options) => {
return new ReactPanelContentPart(
options.id,
props.components[options.name],
{
addPortal,
}
);
},
}); });
}, [props.components]); }, [props.components]);
React.useEffect(() => {
if (!dockviewRef.current) {
return;
}
dockviewRef.current.updateOptions({
watermarkFrameworkComponent: props.watermarkComponent,
});
}, [props.watermarkComponent]);
React.useEffect(() => { React.useEffect(() => {
if (!dockviewRef.current) { if (!dockviewRef.current) {
return; return;
@ -297,7 +283,15 @@ export const DockviewReact = React.forwardRef(
defaultTabComponent: props.defaultTabComponent defaultTabComponent: props.defaultTabComponent
? DEFAULT_REACT_TAB ? DEFAULT_REACT_TAB
: undefined, : undefined,
frameworkTabComponents, createTabComponent(options) {
return new ReactPanelHeaderPart(
options.id,
frameworkTabComponents[options.name],
{
addPortal,
}
);
},
}); });
}, [props.tabComponents, props.defaultTabComponent]); }, [props.tabComponents, props.defaultTabComponent]);
@ -305,8 +299,28 @@ export const DockviewReact = React.forwardRef(
if (!dockviewRef.current) { if (!dockviewRef.current) {
return; return;
} }
dockviewRef.current.updateOptions({ dockviewRef.current.updateOptions({
headerRightActionComponent: createGroupControlElement( createWatermarkComponent: props.watermarkComponent
? () => {
return new ReactWatermarkPart(
'watermark',
props.watermarkComponent!,
{
addPortal,
}
);
}
: undefined,
});
}, [props.watermarkComponent]);
React.useEffect(() => {
if (!dockviewRef.current) {
return;
}
dockviewRef.current.updateOptions({
createRightHeaderActionComponent: createGroupControlElement(
props.rightHeaderActionsComponent, props.rightHeaderActionsComponent,
{ addPortal } { addPortal }
), ),
@ -318,7 +332,7 @@ export const DockviewReact = React.forwardRef(
return; return;
} }
dockviewRef.current.updateOptions({ dockviewRef.current.updateOptions({
headerLeftActionComponent: createGroupControlElement( createLeftHeaderActionComponent: createGroupControlElement(
props.leftHeaderActionsComponent, props.leftHeaderActionsComponent,
{ addPortal } { addPortal }
), ),
@ -330,7 +344,7 @@ export const DockviewReact = React.forwardRef(
return; return;
} }
dockviewRef.current.updateOptions({ dockviewRef.current.updateOptions({
headerRightActionComponent: createGroupControlElement( createPrefixHeaderActionComponent: createGroupControlElement(
props.prefixHeaderActionsComponent, props.prefixHeaderActionsComponent,
{ addPortal } { addPortal }
), ),

View File

@ -12,8 +12,12 @@ Please reference docs @ [dockview.dev](https://dockview.dev).
- Add `onDidActivePanelChange` event to group api [#541](https://github.com/mathuo/dockview/pull/541) - Add `onDidActivePanelChange` event to group api [#541](https://github.com/mathuo/dockview/pull/541)
- Add `inactive` property to `addPanel` method to add panels without making them active [#572](https://github.com/mathuo/dockview/issues/572)
## 🛠 Miscs ## 🛠 Miscs
- Bug: width and height set incorrectly on floating groups when resized [#580](https://github.com/mathuo/dockview/issues/580)
- Create framework packages in preperation for multiple framework support [#541](https://github.com/mathuo/dockview/pull/541) - Create framework packages in preperation for multiple framework support [#541](https://github.com/mathuo/dockview/pull/541)
These are still in active development and will be offically support soon. These are still in active development and will be offically support soon.
@ -36,6 +40,9 @@ Please reference docs @ [dockview.dev](https://dockview.dev).
## 🔥 Breaking changes ## 🔥 Breaking changes
- [dockview-core] Replace DockviewComponent `canDisplayOverlay` option with `onUnhandledDragOverEvent` event [#541](https://github.com/mathuo/dockview/pull/541) - [dockview-core] Replace DockviewComponent `canDisplayOverlay` option with `onUnhandledDragOverEvent` event [#541](https://github.com/mathuo/dockview/pull/541)
- [dockview-core] Rename `createRightHeaderActionsElement` to `headerRightActionComponent` [#541](https://github.com/mathuo/dockview/pull/541) - [dockview-core] Rename `createRightHeaderActionsElement` to `createRightHeaderActionElement` [#576](https://github.com/mathuo/dockview/pull/576)
- [dockview-core] Rename `createLeftHeaderActionsElement` to `headerLeftActionComponent` [#541](https://github.com/mathuo/dockview/pull/541) - [dockview-core] Rename `createLeftHeaderActionsElement` to `createLeftHeaderActionElement` [#576](https://github.com/mathuo/dockview/pull/576)
- [dockview-core] Rename `createPrefixHeaderActionsElement` to `headerPrefixActionComponent` [#541](https://github.com/mathuo/dockview/pull/541) - [dockview-core] Rename `createPrefixHeaderActionsElement` to `createPrefixHeaderActionElement` [#576](https://github.com/mathuo/dockview/pull/576)
- [dockview-core] Remove `frameworkTabComponents` and `tabComponents`, replaced by `createTabComponent` [#576](https://github.com/mathuo/dockview/pull/576)
- [dockview-core] Remove `frameworkComponents` and `components`, replaced by `createComponent` [#576](https://github.com/mathuo/dockview/pull/576)
- [dockview-core] Remove `watermarkFrameworkComponent` and `watermarkComponent`, replaced by `createWatermarkComponent` [#576](https://github.com/mathuo/dockview/pull/576)

View File

@ -12,4 +12,6 @@ This section describes how to lock the dock to prevent movement.
You may want to combine this with `disableDnd={true}` to provide a locked grid with no dnd funtionality. See [Disable Dnd](/docs/core/dnd/disable) for more. You may want to combine this with `disableDnd={true}` to provide a locked grid with no dnd funtionality. See [Disable Dnd](/docs/core/dnd/disable) for more.
::: :::
Locking the component prevent the resizing of components using the drag handles between panels.
<CodeRunner id='dockview/locked'/> <CodeRunner id='dockview/locked'/>

View File

@ -22,3 +22,12 @@ npm install dockview
``` ```
</FrameworkSpecific> </FrameworkSpecific>
<FrameworkSpecific framework='Vue'>
Firstly, install the `dockview-vue` library:
```sh
npm install dockview-vue
```
</FrameworkSpecific>

View File

@ -10,8 +10,8 @@
"swizzle": "docusaurus swizzle @docusaurus/theme-classic", "swizzle": "docusaurus swizzle @docusaurus/theme-classic",
"docs:version": "docusaurus docs:version", "docs:version": "docusaurus docs:version",
"typecheck": "tsc", "typecheck": "tsc",
"create-templates": "node scripts/buildTemplates.mjs", "build-templates": "node scripts/buildTemplates.mjs",
"create-templates:local": "node scripts/buildTemplates.mjs --local" "build-templates:local": "node scripts/buildTemplates.mjs --local"
}, },
"browserslist": { "browserslist": {
"production": [ "production": [
@ -50,4 +50,4 @@
"@types/uuid": "^9.0.7", "@types/uuid": "^9.0.7",
"docusaurus-plugin-sass": "^0.2.5" "docusaurus-plugin-sass": "^0.2.5"
} }
} }

View File

@ -188,16 +188,20 @@ const DockviewDemo = (props: { theme?: string }) => {
> >
<div> <div>
<GridActions api={api} /> <GridActions api={api} />
<PanelActions {api && (
api={api} <PanelActions
panels={panels} api={api}
activePanel={activePanel} panels={panels}
/> activePanel={activePanel}
<GroupActions />
api={api} )}
groups={groups} {api && (
activeGroup={activeGroup} <GroupActions
/> api={api}
groups={groups}
activeGroup={activeGroup}
/>
)}
</div> </div>
<div <div
style={{ style={{

View File

@ -3,9 +3,7 @@ import { DockviewApi } from 'dockview';
export const nextId = (() => { export const nextId = (() => {
let counter = 0; let counter = 0;
return () => { return () => counter++;
counter++;
};
})(); })();
export function defaultConfig(api: DockviewApi) { export function defaultConfig(api: DockviewApi) {

View File

@ -34,11 +34,12 @@ export const GridActions = (props: { api?: DockviewApi }) => {
} }
}; };
const onAddPanel = () => { const onAddPanel = (options?: { inactive: boolean }) => {
props.api?.addPanel({ props.api?.addPanel({
id: `id_${Date.now().toString()}`, id: `id_${Date.now().toString()}`,
component: 'default', component: 'default',
title: `Tab ${nextId()}`, title: `Tab ${nextId()}`,
inactive: options?.inactive,
}); });
}; };
@ -48,9 +49,15 @@ export const GridActions = (props: { api?: DockviewApi }) => {
return ( return (
<div className="action-container"> <div className="action-container">
<button className="text-button" onClick={onAddPanel}> <button className="text-button" onClick={() => onAddPanel()}>
Add Panel Add Panel
</button> </button>
<button
className="text-button"
onClick={() => onAddPanel({ inactive: true })}
>
Add Inactive Panel
</button>
<button className="text-button" onClick={onAddGroup}> <button className="text-button" onClick={onAddGroup}>
Add Group Add Group
</button> </button>

View File

@ -1,85 +1,136 @@
import { DockviewApi } from 'dockview'; import { DockviewApi, DockviewGroupLocation } from 'dockview';
import * as React from 'react';
const GroupAction = (props: {
groupId: string;
groups: string[];
api: DockviewApi;
activeGroup?: string;
}) => {
const onClick = () => {
props.api?.getGroup(props.groupId)?.focus();
};
const isActive = props.activeGroup === props.groupId;
const group = React.useMemo(
() => props.api.getGroup(props.groupId),
[props.api, props.groupId]
);
const [location, setLocation] =
React.useState<DockviewGroupLocation | null>(null);
const [isMaximized, setIsMaximized] = React.useState<boolean>(false);
React.useEffect(() => {
if (!group) {
setLocation(null);
return;
}
const disposable = group.api.onDidLocationChange((event) => {
setLocation(event.location);
});
const disposable2 = props.api.onDidMaximizedGroupChange(() => {
setIsMaximized(group.api.isMaximized());
});
setLocation(group.api.location);
setIsMaximized(group.api.isMaximized());
return () => {
disposable.dispose();
disposable2.dispose();
};
}, [group]);
return (
<div className="button-action">
<div style={{ display: 'flex' }}>
<button
onClick={onClick}
className={
isActive ? 'demo-button selected' : 'demo-button'
}
>
{props.groupId}
</button>
</div>
<div style={{ display: 'flex' }}>
<button
className={
location?.type === 'floating'
? 'demo-icon-button selected'
: 'demo-icon-button'
}
onClick={() => {
if (group) {
props.api.addFloatingGroup(group);
}
}}
>
<span className="material-symbols-outlined">ad_group</span>
</button>
<button
className={
location?.type === 'popout'
? 'demo-icon-button selected'
: 'demo-icon-button'
}
onClick={() => {
if (group) {
props.api.addPopoutGroup(group);
}
}}
>
<span className="material-symbols-outlined">
open_in_new
</span>
</button>
<button
className={
isMaximized
? 'demo-icon-button selected'
: 'demo-icon-button'
}
onClick={() => {
if (group) {
if (group.api.isMaximized()) {
group.api.exitMaximized();
} else {
group.api.maximize();
}
}
}}
>
<span className="material-symbols-outlined">
fullscreen
</span>
</button>
<button
className="demo-icon-button"
onClick={() => {
const panel = props.api?.getGroup(props.groupId);
panel?.api.close();
}}
>
<span className="material-symbols-outlined">close</span>
</button>
</div>
</div>
);
};
export const GroupActions = (props: { export const GroupActions = (props: {
groups: string[]; groups: string[];
api?: DockviewApi; api: DockviewApi;
activeGroup?: string; activeGroup?: string;
}) => { }) => {
return ( return (
<div className="action-container"> <div className="action-container">
{props.groups.map((x) => { {props.groups.map((groupId) => {
const onClick = () => {
props.api?.getGroup(x)?.focus();
};
return ( return (
<div className="button-action"> <GroupAction key={groupId} {...props} groupId={groupId} />
<div style={{ display: 'flex' }}>
<button
onClick={onClick}
className={
props.activeGroup === x
? 'demo-button selected'
: 'demo-button'
}
>
{x}
</button>
</div>
<div style={{ display: 'flex' }}>
<button
className="demo-icon-button"
onClick={() => {
const panel = props.api?.getGroup(x);
if (panel) {
props.api?.addFloatingGroup(panel);
}
}}
>
<span className="material-symbols-outlined">
ad_group
</span>
</button>
<button
className="demo-icon-button"
onClick={() => {
const panel = props.api?.getGroup(x);
if (panel) {
props.api?.addPopoutGroup(panel);
}
}}
>
<span className="material-symbols-outlined">
open_in_new
</span>
</button>
<button
className="demo-icon-button"
onClick={() => {
const panel = props.api?.getGroup(x);
if (panel?.api.isMaximized()) {
panel.api.exitMaximized();
} else {
panel?.api.maximize();
}
}}
>
<span className="material-symbols-outlined">
fullscreen
</span>
</button>
<button
className="demo-icon-button"
onClick={() => {
const panel = props.api?.getGroup(x);
panel?.api.close();
}}
>
<span className="material-symbols-outlined">
close
</span>
</button>
</div>
</div>
); );
})} })}
</div> </div>

View File

@ -1,71 +1,76 @@
import { DockviewApi } from 'dockview'; import { DockviewApi } from 'dockview';
const PanelAction = (props: {
panels: string[];
api: DockviewApi;
activePanel?: string;
panelId: string;
}) => {
const onClick = () => {
props.api?.getPanel(props.panelId)?.focus();
};
return (
<div className="button-action">
<div style={{ display: 'flex' }}>
<button
className={
props.activePanel === props.panelId
? 'demo-button selected'
: 'demo-button'
}
onClick={onClick}
>
{props.panelId}
</button>
</div>
<div style={{ display: 'flex' }}>
<button
className="demo-icon-button"
onClick={() => {
const panel = props.api?.getPanel(props.panelId);
if (panel) {
props.api?.addFloatingGroup(panel);
}
}}
>
<span className="material-symbols-outlined">ad_group</span>
</button>
<button
className="demo-icon-button"
onClick={() => {
const panel = props.api?.getPanel(props.panelId);
if (panel) {
props.api?.addPopoutGroup(panel);
}
}}
>
<span className="material-symbols-outlined">
open_in_new
</span>
</button>
<button
className="demo-icon-button"
onClick={() => {
const panel = props.api?.getPanel(props.panelId);
panel?.api.close();
}}
>
<span className="material-symbols-outlined">close</span>
</button>
</div>
</div>
);
};
export const PanelActions = (props: { export const PanelActions = (props: {
panels: string[]; panels: string[];
api?: DockviewApi; api: DockviewApi;
activePanel?: string; activePanel?: string;
}) => { }) => {
return ( return (
<div className="action-container"> <div className="action-container">
{props.panels.map((x) => { {props.panels.map((id) => {
const onClick = () => { return <PanelAction key={id} {...props} panelId={id} />;
props.api?.getPanel(x)?.focus();
};
return (
<div className="button-action">
<div style={{ display: 'flex' }}>
<button
className={
props.activePanel === x
? 'demo-button selected'
: 'demo-button'
}
onClick={onClick}
>
{x}
</button>
</div>
<div style={{ display: 'flex' }}>
<button
className="demo-icon-button"
onClick={() => {
const panel = props.api?.getPanel(x);
if (panel) {
props.api?.addFloatingGroup(panel);
}
}}
>
<span className="material-symbols-outlined">
ad_group
</span>
</button>
<button
className="demo-icon-button"
onClick={() => {
const panel = props.api?.getPanel(x);
if (panel) {
props.api?.addPopoutGroup(panel);
}
}}
>
<span className="material-symbols-outlined">
open_in_new
</span>
</button>
<button
className="demo-icon-button"
onClick={() => {
const panel = props.api?.getPanel(x);
panel?.api.close();
}}
>
<span className="material-symbols-outlined">
close
</span>
</button>
</div>
</div>
);
})} })}
</div> </div>
); );

View File

@ -6,9 +6,15 @@ import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url)); const __dirname = path.dirname(fileURLToPath(import.meta.url));
const { version } = JSON.parse(
fs.readFileSync(
path.join(__dirname, '..', '..', 'dockview', 'package.json')
)
);
const REACT_VERSION = '18.2.0'; const REACT_VERSION = '18.2.0';
const VUE_VERSION = '3.4.21'; const VUE_VERSION = '3.4.21';
const DOCKVIEW_VERSION = '1.11.0'; const DOCKVIEW_VERSION = version;
const USE_LOCAL_CDN = argv.slice(2).includes('--local'); const USE_LOCAL_CDN = argv.slice(2).includes('--local');
const local = 'http://localhost:1111'; const local = 'http://localhost:1111';
@ -107,7 +113,7 @@ for (const component of COMPONENTS) {
path.join(output, component, folder, framework, 'src') path.join(output, component, folder, framework, 'src')
); );
const template = createIndexHTML({ const template = createIndexHTML({
title: 'React App', title: `Dockview | ${folder} ${framework}`,
app: app:
framework === 'react' framework === 'react'
? './src/index.tsx' ? './src/index.tsx'

View File

@ -1,120 +1,95 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<title>{{title}}</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/img/dockview_logo.ico" data-rh="true" />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200"
/>
<style media="only screen">
html,
body,
#app {
height: 100%;
width: 100%;
margin: 0;
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
font-family: ui-sans-serif, system-ui, -apple-system,
BlinkMacSystemFont, Segoe UI, Roboto;
}
<head> html {
<title>{{title}}</title> position: absolute;
<meta charset="UTF-8" /> top: 0;
<meta name="viewport" content="width=device-width, initial-scale=1" /> left: 0;
<link rel="icon" href="/img/dockview_logo.ico" data-rh="true"> padding: 0;
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" /> overflow: auto;
<style media="only screen"> }
html,
body,
#app {
height: 100%;
width: 100%;
margin: 0;
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
font-family: ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto;
}
html { body {
position: absolute; padding: 16px;
top: 0; overflow: auto;
left: 0; }
padding: 0; </style>
overflow: auto; <script type="systemjs-importmap">
} {
"imports": {
{{importPaths}}
}
}
</script>
<script src="https://cdn.jsdelivr.net/npm/systemjs@6.8.0/dist/system.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/systemjs-babel@0.3.2/dist/systemjs-babel.js"></script>
<script>
async function importCSSStyleSheet(uri) {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = uri;
document.head.appendChild(link);
}
body { System.onload = function (err, id, deps, isErrSource) {
padding: 16px; console.log(id);
overflow: auto; if (id.endsWith('.css') && !err) {
} importCSSStyleSheet(id);
</style> }
<script type="systemjs-importmap"> };
{ </script>
"imports": { </head>
{{importPaths}}
}
}
</script>
<script src="https://cdn.jsdelivr.net/npm/systemjs@6.8.0/dist/system.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/systemjs-babel@0.3.2/dist/systemjs-babel.js"></script>
<script>
async function importCSSStyleSheet(uri) {
const link = document.createElement('link'); <body>
link.rel = 'stylesheet'; <div id="app">
link.href = uri; <script type="systemjs-module" src="import:{{app}}"></script>
document.head.appendChild(link); </div>
console.log('add link') <object
id="loading-spinner"
// const styles = (await import(uri)).default; style="
position: absolute;
// const el = document.createElement('style'); top: 50%;
// el.type = 'text/css'; left: 50%;
transform: translate(-50%, -50%) scale(0.75);
// el.innerHTML = Array.from(styles.cssRules) "
// .map((x) => x.cssText) type="image/svg+xml"
// .join(' '); data="https://dockview.dev/img/dockview_logo.svg"
aria-label="loading"
// document.head.appendChild(el); ></object>
} <script id="loading-script">
(function () {
// System.resolve = function (id, parentUrl) { const cleanupLoading = () => {
// console.log(id, parentUrl); if (document.querySelector('.dv-dockview')) {
// return id; document.querySelector('#loading-spinner').remove();
// return '' document.querySelector('#loading-script').remove();
// } } else {
requestAnimationFrame(() => cleanupLoading());
System.onload = function (err, id, deps, isErrSource) { }
console.log(id); };
if (id.endsWith('.css') && !err) {
importCSSStyleSheet(id);
// const module = System.get(id);
// console.log(module);
// const styles = module?.default;
// if (styles) {
// // importCSSStyleSheet(styles);
// document.adoptedStyleSheets = [...document.adoptedStyleSheets, styles];
// }
}
};
</script>
</head>
<body>
<div id="app">
<script type="systemjs-module" src="import:{{app}}"></script>
</div>
<object id="loading-spinner" style="
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0.75);
" type="image/svg+xml" data="https://dockview.dev/img/dockview_logo.svg" aria-label="loading"></object>
<script id="loading-script">
(function () {
const cleanupLoading = () => {
if (
document.querySelector(
'.dv-dockview'
)
) {
document.querySelector('#loading-spinner').remove();
document.querySelector('#loading-script').remove();
} else {
requestAnimationFrame(() => cleanupLoading());
}
};
cleanupLoading();
})();
</script>
</body>
cleanupLoading();
})();
</script>
</body>
</html> </html>

View File

@ -4,9 +4,10 @@ import * as React from 'react';
import { IS_PROD } from '../flags'; import { IS_PROD } from '../flags';
const frameworks = [ const frameworks = [
{ value: 'JavaScript', label: 'JavaScript' }, // { value: 'JavaScript', label: 'JavaScript' },
{ value: 'React', label: 'React' }, { value: 'React', label: 'React' },
{ value: 'Angular', label: 'Angular' }, { value: 'Vue', label: 'Vue' },
// { value: 'Angular', label: 'Angular' },
]; ];
const activeFrameworkGlobal = new DockviewEmitter<string>({ replay: true }); const activeFrameworkGlobal = new DockviewEmitter<string>({ replay: true });
@ -36,7 +37,7 @@ export function useActiveFramework(): [string, (value: string) => void] {
activeFrameworkGlobal.fire(value); activeFrameworkGlobal.fire(value);
}, []); }, []);
return [IS_PROD ? frameworks[1].value : value, setter]; return [IS_PROD ? frameworks[0].value : value, setter];
} }
const FrameworkSelector1 = () => { const FrameworkSelector1 = () => {

View File

@ -22,6 +22,13 @@ export const _CodeRunner = (props: {
/> />
<div style={{ display: 'flex', justifyContent: 'flex-end' }}> <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
<CodeSandbox url={sandboxUrl} /> <CodeSandbox url={sandboxUrl} />
<a
target="#blank"
href={path}
className="material-symbols-outlined"
>
open_in_new
</a>
</div> </div>
</div> </div>
); );

View File

@ -1 +1 @@
export const IS_PROD = true; export const IS_PROD = false;

View File

@ -6,22 +6,14 @@ import { DockviewReadyEvent, IDockviewPanelProps } from 'dockview-core';
const Panel = defineComponent({ const Panel = defineComponent({
name: 'Panel', name: 'Panel',
props: { props: {
api: {
type: Object as PropType<IDockviewPanelProps['api']>,
required: true,
},
containerApi: {
type: Object as PropType<IDockviewPanelProps['containerApi']>,
required: true,
},
params: { params: {
type: Object as PropType<IDockviewPanelProps['params']>, type: Object as PropType<IDockviewPanelProps>,
required: true, required: true,
}, },
}, },
setup(props) { setup(props) {
return { return {
title: props.api.title, title: props.params.api.title,
}; };
}, },
template: ` template: `
@ -34,14 +26,7 @@ const App = defineComponent({
name: 'App', name: 'App',
components: { components: {
'dockview-vue': DockviewVue, 'dockview-vue': DockviewVue,
Panel, panel: Panel,
},
data() {
return {
components: {
panel: Panel,
},
};
}, },
methods: { methods: {
onReady(event: DockviewReadyEvent) { onReady(event: DockviewReadyEvent) {
@ -57,7 +42,6 @@ const App = defineComponent({
style="width:100%; height:100%" style="width:100%; height:100%"
class="dockview-theme-abyss" class="dockview-theme-abyss"
@ready="onReady" @ready="onReady"
:components="components"
> >
</dockview-vue>`, </dockview-vue>`,
}); });

View File

@ -10,16 +10,8 @@ import {
const Panel = defineComponent({ const Panel = defineComponent({
name: 'Panel', name: 'Panel',
props: { props: {
api: {
type: Object as PropType<IDockviewPanelProps['api']>,
required: true,
},
containerApi: {
type: Object as PropType<IDockviewPanelProps['containerApi']>,
required: true,
},
params: { params: {
type: Object as PropType<IDockviewPanelProps['params']>, type: Object as PropType<IDockviewPanelProps>,
required: true, required: true,
}, },
}, },
@ -43,9 +35,9 @@ const Panel = defineComponent({
console.log('interval'); console.log('interval');
const interval = setInterval(() => { const interval = setInterval(() => {
this.api.updateParameters({ myValue: Date.now() }); this.params.api.updateParameters({ myValue: Date.now() });
}, 1000); }, 1000);
this.api.updateParameters({ myValue: Date.now() }); this.parmas.api.updateParameters({ myValue: Date.now() });
return () => { return () => {
clearInterval(interval); clearInterval(interval);
@ -53,10 +45,10 @@ const Panel = defineComponent({
}, },
}, },
mounted() { mounted() {
const disposable = this.api.onDidTitleChange(() => { const disposable = this.params.api.onDidTitleChange(() => {
this.title = this.api.title; this.title = this.params.api.title;
}); });
this.title = this.api.title; this.title = this.params.api.title;
return () => { return () => {
disposable.dispose(); disposable.dispose();
@ -78,28 +70,14 @@ interface CustomParams {
const Tab = defineComponent({ const Tab = defineComponent({
name: 'Tab', name: 'Tab',
props: { props: {
api: {
type: Object as PropType<
IDockviewPanelHeaderProps<CustomParams>['api']
>,
required: true,
},
containerApi: {
type: Object as PropType<
IDockviewPanelHeaderProps<CustomParams>['containerApi']
>,
required: true,
},
params: { params: {
type: Object as PropType< type: Object as PropType<IDockviewPanelHeaderProps<CustomParams>>,
IDockviewPanelHeaderProps<CustomParams>['params']
>,
required: true, required: true,
}, },
}, },
data() { data() {
return { return {
myValue: this.params.myValue, myValue: this.params.params.myValue,
title: '', title: '',
}; };
}, },
@ -118,9 +96,9 @@ const Tab = defineComponent({
} }
const interval = setInterval(() => { const interval = setInterval(() => {
this.api.updateParameters({ myValue: Date.now() }); this.params.api.updateParameters({ myValue: Date.now() });
}, 1000); }, 1000);
this.api.updateParameters({ myValue: Date.now() }); this.params.api.updateParameters({ myValue: Date.now() });
return () => { return () => {
clearInterval(interval); clearInterval(interval);
@ -139,25 +117,15 @@ const App = defineComponent({
name: 'App', name: 'App',
components: { components: {
'dockview-vue': DockviewVue, 'dockview-vue': DockviewVue,
Panel, defaultPanel: Panel,
Tab, defaultTab: Tab,
},
data() {
return {
components: {
default: Panel,
},
tabComponents: {
default: Tab,
},
};
}, },
methods: { methods: {
onReady(event: DockviewReadyEvent) { onReady(event: DockviewReadyEvent) {
event.api.addPanel({ event.api.addPanel({
id: 'panel_1', id: 'panel_1',
component: 'default', component: 'defaultPanel',
tabComponent: 'default', tabComponent: 'defaultTab',
params: { params: {
myValue: Date.now(), myValue: Date.now(),
}, },
@ -165,8 +133,8 @@ const App = defineComponent({
event.api.addPanel({ event.api.addPanel({
id: 'panel_2', id: 'panel_2',
component: 'default', component: 'defaultPanel',
tabComponent: 'default', tabComponent: 'defaultTab',
params: { params: {
myValue: Date.now(), myValue: Date.now(),
}, },
@ -178,8 +146,6 @@ const App = defineComponent({
style="width:100%;height:100%" style="width:100%;height:100%"
class="dockview-theme-abyss" class="dockview-theme-abyss"
@ready="onReady" @ready="onReady"
:components="components"
:tabComponents="tabComponents"
</dockview-vue>`, </dockview-vue>`,
}); });

View File

@ -48,18 +48,8 @@ const MaterialIcon = defineComponent({
const LeftAction = defineComponent({ const LeftAction = defineComponent({
name: 'LeftAction', name: 'LeftAction',
props: { props: {
containerApi: { params: {
type: Object as PropType< type: Object as PropType<IDockviewHeaderActionsProps>,
IDockviewHeaderActionsProps['containerApi']
>,
required: true,
},
api: {
type: Object as PropType<IDockviewHeaderActionsProps['api']>,
required: true,
},
group: {
type: Object as PropType<IDockviewHeaderActionsProps['group']>,
required: true, required: true,
}, },
}, },
@ -68,7 +58,7 @@ const LeftAction = defineComponent({
}, },
methods: { methods: {
onClick() { onClick() {
this.containerApi.addPanel({ this.params.containerApi.addPanel({
id: (++panelCount).toString(), id: (++panelCount).toString(),
title: `Tab ${panelCount}`, title: `Tab ${panelCount}`,
component: 'default', component: 'default',
@ -84,18 +74,8 @@ const LeftAction = defineComponent({
const RightAction = defineComponent({ const RightAction = defineComponent({
name: 'RightAction', name: 'RightAction',
props: { props: {
containerApi: { params: {
type: Object as PropType< type: Object as PropType<IDockviewHeaderActionsProps>,
IDockviewHeaderActionsProps['containerApi']
>,
required: true,
},
api: {
type: Object as PropType<IDockviewHeaderActionsProps['api']>,
required: true,
},
group: {
type: Object as PropType<IDockviewHeaderActionsProps['group']>,
required: true, required: true,
}, },
}, },
@ -104,23 +84,25 @@ const RightAction = defineComponent({
}, },
data() { data() {
return { return {
floating: this.api.location.type === 'floating', floating: this.params.api.location.type === 'floating',
}; };
}, },
methods: { methods: {
onClick() { onClick() {
if (this.floating) { if (this.floating) {
const group = this.containerApi.addGroup(); const group = this.params.containerApi.addGroup();
this.group.api.moveTo({ group }); this.group.api.moveTo({ group });
} else { } else {
this.containerApi.addFloatingGroup(this.group); this.containerApi.addFloatingGroup(this.params.group);
} }
}, },
}, },
mounted() { mounted() {
const disposable = this.group.api.onDidLocationChange((event) => { const disposable = this.params.group.api.onDidLocationChange(
this.floating = event.location.type === 'floating'; (event) => {
}); this.floating = event.location.type === 'floating';
}
);
return () => { return () => {
disposable.dispose(); disposable.dispose();
@ -136,16 +118,8 @@ const RightAction = defineComponent({
const Panel = defineComponent({ const Panel = defineComponent({
name: 'Panel', name: 'Panel',
props: { props: {
api: {
type: Object as PropType<IDockviewPanelProps['api']>,
required: true,
},
containerApi: {
type: Object as PropType<IDockviewPanelProps['containerApi']>,
required: true,
},
params: { params: {
type: Object as PropType<IDockviewPanelProps['params']>, type: Object as PropType<IDockviewPanelProps>,
required: true, required: true,
}, },
}, },
@ -155,10 +129,10 @@ const Panel = defineComponent({
}; };
}, },
mounted() { mounted() {
const disposable = this.api.onDidTitleChange(() => { const disposable = this.params.api.onDidTitleChange(() => {
this.title = this.api.title; this.title = this.params.api.title;
}); });
this.title = this.api.title; this.title = this.params.api.title;
return () => { return () => {
disposable.dispose(); disposable.dispose();
@ -174,17 +148,12 @@ const App = defineComponent({
name: 'App', name: 'App',
components: { components: {
'dockview-vue': DockviewVue, 'dockview-vue': DockviewVue,
Panel, default: Panel,
LeftAction, leftAction: LeftAction,
RightAction, rightAction: RightAction,
}, },
data() { data() {
return { return {
components: {
default: Panel,
},
leftAction: LeftAction,
rightAction: RightAction,
api: null as DockviewApi | null, api: null as DockviewApi | null,
bounds: undefined, bounds: undefined,
disableFloatingGroups: false, disableFloatingGroups: false,
@ -246,11 +215,9 @@ const App = defineComponent({
style="width:100%;height:100%" style="width:100%;height:100%"
class="dockview-theme-abyss" class="dockview-theme-abyss"
@ready="onReady" @ready="onReady"
:components="components"
:floatingGroupBounds="bounds" :floatingGroupBounds="bounds"
:leftHeaderActionsComponent="leftAction" leftHeaderActionsComponent="leftAction"
:rightHeaderActionsComponent="rightAction" rightHeaderActionsComponent="rightAction"
:prefixHeaderActionsComponent="prefixAction"
:disableFloatingGroups="disableFloatingGroups" :disableFloatingGroups="disableFloatingGroups"
</dockview-vue> </dockview-vue>
</div> </div>

View File

@ -2,7 +2,6 @@ import 'dockview-core/dist/styles/dockview.css';
import { PropType, createApp, defineComponent } from 'vue'; import { PropType, createApp, defineComponent } from 'vue';
import { DockviewVue } from 'dockview-vue'; import { DockviewVue } from 'dockview-vue';
import { import {
DockviewGroupPanelApi,
DockviewReadyEvent, DockviewReadyEvent,
IDockviewHeaderActionsProps, IDockviewHeaderActionsProps,
IDockviewPanelProps, IDockviewPanelProps,
@ -12,18 +11,8 @@ import './app.css';
const LeftAction = defineComponent({ const LeftAction = defineComponent({
name: 'LeftAction', name: 'LeftAction',
props: { props: {
containerApi: { params: {
type: Object as PropType< type: Object as PropType<IDockviewHeaderActionsProps>,
IDockviewHeaderActionsProps['containerApi']
>,
required: true,
},
api: {
type: Object as PropType<IDockviewHeaderActionsProps['api']>,
required: true,
},
group: {
type: Object as PropType<IDockviewHeaderActionsProps['group']>,
required: true, required: true,
}, },
}, },
@ -33,11 +22,11 @@ const LeftAction = defineComponent({
}; };
}, },
mounted() { mounted() {
const disposable = this.api.onDidActivePanelChange((event) => { const disposable = this.params.api.onDidActivePanelChange((event) => {
this.activePanel = event.panel.id; this.activePanel = event.panel.id;
}); });
this.activePanel = this.group.activePanel.id; this.activePanel = this.params.group.activePanel.id;
return () => { return () => {
disposable.dispose(); disposable.dispose();
@ -54,18 +43,8 @@ const LeftAction = defineComponent({
const RightAction = defineComponent({ const RightAction = defineComponent({
name: 'RightAction', name: 'RightAction',
props: { props: {
containerApi: { params: {
type: Object as PropType< type: Object as PropType<IDockviewHeaderActionsProps>,
IDockviewHeaderActionsProps['containerApi']
>,
required: true,
},
api: {
type: Object as PropType<IDockviewHeaderActionsProps['api']>,
required: true,
},
group: {
type: Object as PropType<IDockviewHeaderActionsProps['group']>,
required: true, required: true,
}, },
}, },
@ -75,7 +54,7 @@ const RightAction = defineComponent({
}; };
}, },
mounted() { mounted() {
const disposable = this.api.onDidActiveChange((event) => { const disposable = this.params.api.onDidActiveChange((event) => {
this.isGroupActive = event.isActive; this.isGroupActive = event.isActive;
}); });
@ -99,14 +78,8 @@ const RightAction = defineComponent({
const PrefixAction = defineComponent({ const PrefixAction = defineComponent({
name: 'PrefixAction', name: 'PrefixAction',
props: { props: {
containerApi: { params: {
type: Object as PropType< type: Object as PropType<IDockviewHeaderActionsProps>,
IDockviewHeaderActionsProps['containerApi']
>,
required: true,
},
group: {
type: Object as PropType<IDockviewHeaderActionsProps['group']>,
required: true, required: true,
}, },
}, },
@ -116,16 +89,8 @@ const PrefixAction = defineComponent({
const Panel = defineComponent({ const Panel = defineComponent({
name: 'Panel', name: 'Panel',
props: { props: {
api: {
type: Object as PropType<IDockviewPanelProps['api']>,
required: true,
},
containerApi: {
type: Object as PropType<IDockviewPanelProps['containerApi']>,
required: true,
},
params: { params: {
type: Object as PropType<IDockviewPanelProps['params']>, type: Object as PropType<IDockviewPanelProps>,
required: true, required: true,
}, },
}, },
@ -136,10 +101,10 @@ const Panel = defineComponent({
}, },
mounted() { mounted() {
const disposable = this.api.onDidTitleChange(() => { const disposable = this.params.api.onDidTitleChange(() => {
this.title = this.api.title; this.title = this.params.api.title;
}); });
this.title = this.api.title; this.title = this.params.api.title;
return () => { return () => {
disposable.dispose(); disposable.dispose();
@ -155,20 +120,10 @@ const App = defineComponent({
name: 'App', name: 'App',
components: { components: {
'dockview-vue': DockviewVue, 'dockview-vue': DockviewVue,
Panel, default: Panel,
LeftAction, leftAction: LeftAction,
RightAction, rightAction: RightAction,
PrefixAction, prefixAction: PrefixAction,
},
data() {
return {
components: {
default: Panel,
},
leftAction: LeftAction,
rightAction: RightAction,
prefixAction: PrefixAction,
};
}, },
methods: { methods: {
onReady(event: DockviewReadyEvent) { onReady(event: DockviewReadyEvent) {
@ -202,10 +157,9 @@ const App = defineComponent({
style="width:100%;height:100%" style="width:100%;height:100%"
class="dockview-theme-abyss" class="dockview-theme-abyss"
@ready="onReady" @ready="onReady"
:components="components" leftHeaderActionsComponent="leftAction"
:leftHeaderActionsComponent="leftAction" rightHeaderActionsComponent="rightAction"
:rightHeaderActionsComponent="rightAction" prefixHeaderActionsComponent="prefixAction"
:prefixHeaderActionsComponent="prefixAction"
</dockview-vue>`, </dockview-vue>`,
}); });

View File

@ -65,18 +65,8 @@ const MaterialIcon = defineComponent({
const LeftAction = defineComponent({ const LeftAction = defineComponent({
name: 'LeftAction', name: 'LeftAction',
props: { props: {
containerApi: { params: {
type: Object as PropType< type: Object as PropType<IDockviewHeaderActionsProps>,
IDockviewHeaderActionsProps['containerApi']
>,
required: true,
},
api: {
type: Object as PropType<IDockviewHeaderActionsProps['api']>,
required: true,
},
group: {
type: Object as PropType<IDockviewHeaderActionsProps['group']>,
required: true, required: true,
}, },
}, },
@ -85,7 +75,7 @@ const LeftAction = defineComponent({
}, },
methods: { methods: {
onClick() { onClick() {
this.containerApi.addPanel({ this.params.containerApi.addPanel({
id: (++panelCount).toString(), id: (++panelCount).toString(),
title: `Tab ${panelCount}`, title: `Tab ${panelCount}`,
component: 'default', component: 'default',
@ -101,16 +91,8 @@ const LeftAction = defineComponent({
const Panel = defineComponent({ const Panel = defineComponent({
name: 'Panel', name: 'Panel',
props: { props: {
api: {
type: Object as PropType<IDockviewPanelProps['api']>,
required: true,
},
containerApi: {
type: Object as PropType<IDockviewPanelProps['containerApi']>,
required: true,
},
params: { params: {
type: Object as PropType<IDockviewPanelProps['params']>, type: Object as PropType<IDockviewPanelProps>,
required: true, required: true,
}, },
}, },
@ -120,7 +102,7 @@ const Panel = defineComponent({
}; };
}, },
mounted() { mounted() {
const disposable = this.api.onDidTitleChange(() => { const disposable = this.params.api.onDidTitleChange(() => {
this.title = this.api.title; this.title = this.api.title;
}); });
this.title = this.api.title; this.title = this.api.title;
@ -139,15 +121,11 @@ const App = defineComponent({
name: 'App', name: 'App',
components: { components: {
'dockview-vue': DockviewVue, 'dockview-vue': DockviewVue,
Panel, default: Panel,
LeftAction, leftAction: LeftAction,
}, },
data() { data() {
return { return {
components: {
default: Panel,
},
leftAction: LeftAction,
api: null as DockviewApi | null, api: null as DockviewApi | null,
}; };
}, },
@ -219,11 +197,8 @@ const App = defineComponent({
style="width:100%;height:100%" style="width:100%;height:100%"
class="dockview-theme-abyss" class="dockview-theme-abyss"
@ready="onReady" @ready="onReady"
:components="components"
:floatingGroupBounds="bounds" :floatingGroupBounds="bounds"
:leftHeaderActionsComponent="leftAction" leftHeaderActionsComponent="leftAction"
:rightHeaderActionsComponent="rightAction"
:prefixHeaderActionsComponent="prefixAction"
:disableFloatingGroups="disableFloatingGroups" :disableFloatingGroups="disableFloatingGroups"
</dockview-vue> </dockview-vue>
</div> </div>

View File

@ -1,25 +1,13 @@
import 'dockview-core/dist/styles/dockview.css'; import 'dockview-core/dist/styles/dockview.css';
import { PropType, createApp, defineComponent } from 'vue'; import { PropType, createApp, defineComponent } from 'vue';
import { DockviewVue } from 'dockview-vue'; import { DockviewVue } from 'dockview-vue';
import { import { DockviewReadyEvent, IDockviewPanelProps } from 'dockview-core';
DockviewApi,
DockviewReadyEvent,
IDockviewPanelProps,
} from 'dockview-core';
const Panel = defineComponent({ const Panel = defineComponent({
name: 'Panel', name: 'Panel',
props: { props: {
api: {
type: Object as PropType<IDockviewPanelProps['api']>,
required: true,
},
containerApi: {
type: Object as PropType<IDockviewPanelProps['containerApi']>,
required: true,
},
params: { params: {
type: Object as PropType<IDockviewPanelProps['params']>, type: Object as PropType<IDockviewPanelProps>,
required: true, required: true,
}, },
}, },
@ -30,7 +18,7 @@ const Panel = defineComponent({
}, },
mounted() { mounted() {
const disposable = this.api.onDidTitleChange(() => { const disposable = this.params.api.onDidTitleChange(() => {
this.title = this.api.title; this.title = this.api.title;
}); });
this.title = this.api.title; this.title = this.api.title;
@ -50,13 +38,7 @@ const App = defineComponent({
name: 'App', name: 'App',
components: { components: {
'dockview-vue': DockviewVue, 'dockview-vue': DockviewVue,
}, default: Panel,
data() {
return {
components: {
default: Panel,
},
};
}, },
methods: { methods: {
onReady(event: DockviewReadyEvent) { onReady(event: DockviewReadyEvent) {
@ -95,7 +77,6 @@ const App = defineComponent({
style="width:100%;height:100%" style="width:100%;height:100%"
class="dockview-theme-abyss" class="dockview-theme-abyss"
@ready="onReady" @ready="onReady"
:components="components"
:locked=true :locked=true
</dockview-vue>`, </dockview-vue>`,
}); });

View File

@ -47,14 +47,8 @@ const MaterialIcon = defineComponent({
const LeftAction = defineComponent({ const LeftAction = defineComponent({
name: 'LeftAction', name: 'LeftAction',
props: { props: {
containerApi: { params: {
type: Object as PropType< type: Object as PropType<IDockviewHeaderActionsProps>,
IDockviewHeaderActionsProps['containerApi']
>,
required: true,
},
group: {
type: Object as PropType<IDockviewHeaderActionsProps['group']>,
required: true, required: true,
}, },
}, },
@ -63,11 +57,11 @@ const LeftAction = defineComponent({
}, },
methods: { methods: {
onClick() { onClick() {
this.containerApi.addPanel({ this.parmas.containerApi.addPanel({
id: (++panelCount).toString(), id: (++panelCount).toString(),
title: `Tab ${panelCount}`, title: `Tab ${panelCount}`,
component: 'default', component: 'default',
position: { referenceGroup: this.group }, position: { referenceGroup: this.params.group },
}); });
}, },
}, },
@ -80,18 +74,8 @@ const LeftAction = defineComponent({
const RightAction = defineComponent({ const RightAction = defineComponent({
name: 'RightAction', name: 'RightAction',
props: { props: {
containerApi: { params: {
type: Object as PropType< type: Object as PropType<IDockviewHeaderActionsProps>,
IDockviewHeaderActionsProps['containerApi']
>,
required: true,
},
api: {
type: Object as PropType<IDockviewHeaderActionsProps['api']>,
required: true,
},
group: {
type: Object as PropType<IDockviewHeaderActionsProps['group']>,
required: true, required: true,
}, },
}, },
@ -101,9 +85,11 @@ const RightAction = defineComponent({
}; };
}, },
mounted() { mounted() {
const disposable = this.containerApi.onDidMaximizedGroupChange(() => { const disposable = this.params.containerApi.onDidMaximizedGroupChange(
this.maximized = this.api.isMaximized(); () => {
}); this.maximized = this.api.isMaximized();
}
);
this.maximized = this.api.isMaximized(); this.maximized = this.api.isMaximized();
@ -133,16 +119,8 @@ const RightAction = defineComponent({
const Panel = defineComponent({ const Panel = defineComponent({
name: 'Panel', name: 'Panel',
props: { props: {
api: {
type: Object as PropType<IDockviewPanelProps['api']>,
required: true,
},
containerApi: {
type: Object as PropType<IDockviewPanelProps['containerApi']>,
required: true,
},
params: { params: {
type: Object as PropType<IDockviewPanelProps['params']>, type: Object as PropType<IDockviewPanelProps>,
required: true, required: true,
}, },
}, },
@ -153,7 +131,7 @@ const Panel = defineComponent({
}, },
mounted() { mounted() {
const disposable = this.api.onDidTitleChange(() => { const disposable = this.params.api.onDidTitleChange(() => {
this.title = this.api.title; this.title = this.api.title;
}); });
this.title = this.api.title; this.title = this.api.title;
@ -172,18 +150,9 @@ const App = defineComponent({
name: 'App', name: 'App',
components: { components: {
'dockview-vue': DockviewVue, 'dockview-vue': DockviewVue,
Panel, default: Panel,
LeftAction, leftAction: LeftAction,
RightAction, rightAction: RightAction,
},
data() {
return {
components: {
default: Panel,
},
leftAction: LeftAction,
rightAction: RightAction,
};
}, },
methods: { methods: {
onReady(event: DockviewReadyEvent) { onReady(event: DockviewReadyEvent) {
@ -230,9 +199,8 @@ const App = defineComponent({
style="width:100%;height:100%" style="width:100%;height:100%"
class="dockview-theme-abyss" class="dockview-theme-abyss"
@ready="onReady" @ready="onReady"
:components="components" leftHeaderActionsComponent="leftAction"
:leftHeaderActionsComponent="leftAction" rightHeaderActionsComponent="rightAction"
:rightHeaderActionsComponent="rightAction"
</dockview-vue>`, </dockview-vue>`,
}); });

View File

@ -6,16 +6,8 @@ import { DockviewReadyEvent, IDockviewPanelProps } from 'dockview-core';
const Panel = defineComponent({ const Panel = defineComponent({
name: 'Panel', name: 'Panel',
props: { props: {
api: {
type: Object as PropType<IDockviewPanelProps['api']>,
required: true,
},
containerApi: {
type: Object as PropType<IDockviewPanelProps['containerApi']>,
required: true,
},
params: { params: {
type: Object as PropType<IDockviewPanelProps['params']>, type: Object as PropType<IDockviewPanelProps>,
required: true, required: true,
}, },
}, },
@ -25,7 +17,7 @@ const Panel = defineComponent({
}; };
}, },
mounted() { mounted() {
const disposable = this.api.onDidTitleChange(() => { const disposable = this.params.api.onDidTitleChange(() => {
this.title = this.api.title; this.title = this.api.title;
}); });
this.title = this.api.title; this.title = this.api.title;
@ -44,15 +36,7 @@ const InnerDockview = defineComponent({
name: 'App', name: 'App',
components: { components: {
'dockview-vue': DockviewVue, 'dockview-vue': DockviewVue,
Panel, default: Panel,
},
data() {
return {
components: {
default: Panel,
innerDockview: InnerDockview,
},
};
}, },
methods: { methods: {
onReady(event: DockviewReadyEvent) { onReady(event: DockviewReadyEvent) {
@ -76,7 +60,6 @@ const InnerDockview = defineComponent({
<dockview-vue <dockview-vue
style="width:100%;height:100%" style="width:100%;height:100%"
class="dockview-theme-abyss" class="dockview-theme-abyss"
:components="components"
@ready="onReady" @ready="onReady"
</dockview-vue>`, </dockview-vue>`,
}); });
@ -85,16 +68,8 @@ const App = defineComponent({
name: 'App', name: 'App',
components: { components: {
'dockview-vue': DockviewVue, 'dockview-vue': DockviewVue,
Panel, default: Panel,
InnerDockview, innerDockview: InnerDockview,
},
data() {
return {
components: {
default: Panel,
innerDockview: InnerDockview,
},
};
}, },
methods: { methods: {
onReady(event: DockviewReadyEvent) { onReady(event: DockviewReadyEvent) {
@ -119,7 +94,6 @@ const App = defineComponent({
<dockview-vue <dockview-vue
style="width:100%;height:100%" style="width:100%;height:100%"
class="dockview-theme-abyss" class="dockview-theme-abyss"
:components="components"
@ready="onReady" @ready="onReady"
</dockview-vue>`, </dockview-vue>`,
}); });

View File

@ -48,18 +48,8 @@ const MaterialIcon = defineComponent({
const LeftAction = defineComponent({ const LeftAction = defineComponent({
name: 'LeftAction', name: 'LeftAction',
props: { props: {
containerApi: { params: {
type: Object as PropType< type: Object as PropType<IDockviewHeaderActionsProps>,
IDockviewHeaderActionsProps['containerApi']
>,
required: true,
},
api: {
type: Object as PropType<IDockviewHeaderActionsProps['api']>,
required: true,
},
group: {
type: Object as PropType<IDockviewHeaderActionsProps['group']>,
required: true, required: true,
}, },
}, },
@ -68,7 +58,7 @@ const LeftAction = defineComponent({
}, },
methods: { methods: {
onClick() { onClick() {
this.containerApi.addPanel({ this.params.containerApi.addPanel({
id: (++panelCount).toString(), id: (++panelCount).toString(),
title: `Tab ${panelCount}`, title: `Tab ${panelCount}`,
component: 'default', component: 'default',
@ -84,18 +74,8 @@ const LeftAction = defineComponent({
const RightAction = defineComponent({ const RightAction = defineComponent({
name: 'RightAction', name: 'RightAction',
props: { props: {
containerApi: { params: {
type: Object as PropType< type: Object as PropType<IDockviewHeaderActionsProps>,
IDockviewHeaderActionsProps['containerApi']
>,
required: true,
},
api: {
type: Object as PropType<IDockviewHeaderActionsProps['api']>,
required: true,
},
group: {
type: Object as PropType<IDockviewHeaderActionsProps['group']>,
required: true, required: true,
}, },
}, },
@ -104,25 +84,27 @@ const RightAction = defineComponent({
}, },
data() { data() {
return { return {
isPopout: this.api.location.type === 'popout', isPopout: this.params.api.location.type === 'popout',
}; };
}, },
methods: { methods: {
onClick() { onClick() {
if (this.isPopout) { if (this.isPopout) {
const group = this.containerApi.addGroup(); const group = this.params.containerApi.addGroup();
this.group.api.moveTo({ group }); this.group.api.moveTo({ group });
} else { } else {
this.containerApi.addPopoutGroup(this.group, { this.params.containerApi.addPopoutGroup(this.params.group, {
popoutUrl: '/popout/index.html', popoutUrl: '/popout/index.html',
}); });
} }
}, },
}, },
mounted() { mounted() {
const disposable = this.group.api.onDidLocationChange((event) => { const disposable = this.params.group.api.onDidLocationChange(
this.isPopout = event.location.type === 'popout'; (event) => {
}); this.isPopout = event.location.type === 'popout';
}
);
return () => { return () => {
disposable.dispose(); disposable.dispose();
@ -138,16 +120,8 @@ const RightAction = defineComponent({
const Panel = defineComponent({ const Panel = defineComponent({
name: 'Panel', name: 'Panel',
props: { props: {
api: {
type: Object as PropType<IDockviewPanelProps['api']>,
required: true,
},
containerApi: {
type: Object as PropType<IDockviewPanelProps['containerApi']>,
required: true,
},
params: { params: {
type: Object as PropType<IDockviewPanelProps['params']>, type: Object as PropType<IDockviewPanelProps>,
required: true, required: true,
}, },
}, },
@ -157,7 +131,7 @@ const Panel = defineComponent({
}; };
}, },
mounted() { mounted() {
const disposable = this.api.onDidTitleChange(() => { const disposable = this.params.api.onDidTitleChange(() => {
this.title = this.api.title; this.title = this.api.title;
}); });
this.title = this.api.title; this.title = this.api.title;
@ -176,17 +150,12 @@ const App = defineComponent({
name: 'App', name: 'App',
components: { components: {
'dockview-vue': DockviewVue, 'dockview-vue': DockviewVue,
Panel, default: Panel,
LeftAction, leftAction: LeftAction,
RightAction, rightAction: RightAction,
}, },
data() { data() {
return { return {
components: {
default: Panel,
},
leftAction: LeftAction,
rightAction: RightAction,
api: null as DockviewApi | null, api: null as DockviewApi | null,
bounds: undefined, bounds: undefined,
disableFloatingGroups: false, disableFloatingGroups: false,
@ -248,11 +217,10 @@ const App = defineComponent({
style="width:100%;height:100%" style="width:100%;height:100%"
class="dockview-theme-abyss" class="dockview-theme-abyss"
@ready="onReady" @ready="onReady"
:components="components"
:floatingGroupBounds="bounds" :floatingGroupBounds="bounds"
:leftHeaderActionsComponent="leftAction" leftHeaderActionsComponent="leftAction"
:rightHeaderActionsComponent="rightAction" rightHeaderActionsComponent="rightAction"
:prefixHeaderActionsComponent="prefixAction" prefixHeaderActionsComponent="prefixAction"
:disableFloatingGroups="disableFloatingGroups" :disableFloatingGroups="disableFloatingGroups"
</dockview-vue> </dockview-vue>
</div> </div>

View File

@ -6,16 +6,8 @@ import { DockviewReadyEvent, IDockviewPanelProps } from 'dockview-core';
const Panel = defineComponent({ const Panel = defineComponent({
name: 'Panel', name: 'Panel',
props: { props: {
api: {
type: Object as PropType<IDockviewPanelProps['api']>,
required: true,
},
containerApi: {
type: Object as PropType<IDockviewPanelProps['containerApi']>,
required: true,
},
params: { params: {
type: Object as PropType<IDockviewPanelProps['params']>, type: Object as PropType<IDockviewPanelProps>,
required: true, required: true,
}, },
}, },
@ -27,18 +19,18 @@ const Panel = defineComponent({
}, },
methods: { methods: {
onToggleRenderMode() { onToggleRenderMode() {
this.api.setRenderer( this.params.api.setRenderer(
this.api.renderer === 'onlyWhenVisible' this.params.api.renderer === 'onlyWhenVisible'
? 'always' ? 'always'
: 'onlyWhenVisible' : 'onlyWhenVisible'
); );
}, },
}, },
mounted() { mounted() {
const disposable = this.api.onDidTitleChange(() => { const disposable = this.params.api.onDidTitleChange(() => {
this.title = this.api.title; this.title = this.api.title;
}); });
const disposable2 = this.api.onDidRendererChange((event) => { const disposable2 = this.params.api.onDidRendererChange((event) => {
this.renderer = event.renderer; this.renderer = event.renderer;
}); });
@ -61,14 +53,7 @@ const App = defineComponent({
name: 'App', name: 'App',
components: { components: {
'dockview-vue': DockviewVue, 'dockview-vue': DockviewVue,
Panel, default: Panel,
},
data() {
return {
components: {
default: Panel,
},
};
}, },
methods: { methods: {
onReady(event: DockviewReadyEvent) { onReady(event: DockviewReadyEvent) {
@ -104,7 +89,6 @@ const App = defineComponent({
style="width:100%;height:100%" style="width:100%;height:100%"
class="dockview-theme-abyss" class="dockview-theme-abyss"
@ready="onReady" @ready="onReady"
:components="components"
</dockview-vue>`, </dockview-vue>`,
}); });

View File

@ -6,16 +6,8 @@ import { DockviewReadyEvent, IDockviewPanelProps } from 'dockview-core';
const Panel = defineComponent({ const Panel = defineComponent({
name: 'Panel', name: 'Panel',
props: { props: {
api: {
type: Object as PropType<IDockviewPanelProps['api']>,
required: true,
},
containerApi: {
type: Object as PropType<IDockviewPanelProps['containerApi']>,
required: true,
},
params: { params: {
type: Object as PropType<IDockviewPanelProps['params']>, type: Object as PropType<IDockviewPanelProps>,
required: true, required: true,
}, },
}, },
@ -25,7 +17,7 @@ const Panel = defineComponent({
}; };
}, },
mounted() { mounted() {
const disposable = this.api.onDidTitleChange(() => { const disposable = this.params.api.onDidTitleChange(() => {
this.title = this.api.title; this.title = this.api.title;
}); });
this.title = this.api.title; this.title = this.api.title;
@ -44,13 +36,10 @@ const App = defineComponent({
name: 'App', name: 'App',
components: { components: {
'dockview-vue': DockviewVue, 'dockview-vue': DockviewVue,
Panel, default: Panel,
}, },
data() { data() {
return { return {
components: {
default: Panel,
},
value: 50, value: 50,
}; };
}, },
@ -136,7 +125,6 @@ const App = defineComponent({
style="width:100%;height:100%" style="width:100%;height:100%"
class="dockview-theme-abyss" class="dockview-theme-abyss"
@ready="onReady" @ready="onReady"
:components="components"
:disableFloatingGroups=true :disableFloatingGroups=true
</dockview-vue> </dockview-vue>
</div> </div>

View File

@ -7,16 +7,8 @@ import './resize.css';
const Panel = defineComponent({ const Panel = defineComponent({
name: 'Panel', name: 'Panel',
props: { props: {
api: {
type: Object as PropType<IDockviewPanelProps['api']>,
required: true,
},
containerApi: {
type: Object as PropType<IDockviewPanelProps['containerApi']>,
required: true,
},
params: { params: {
type: Object as PropType<IDockviewPanelProps['params']>, type: Object as PropType<IDockviewPanelProps>,
required: true, required: true,
}, },
}, },
@ -29,20 +21,20 @@ const Panel = defineComponent({
}, },
methods: { methods: {
onResizeGroupWidth() { onResizeGroupWidth() {
this.api.group.api.setSize({ width: this.width }); this.params.api.group.api.setSize({ width: this.width });
}, },
onResizePanelWidth() { onResizePanelWidth() {
this.api.setSize({ width: this.width }); this.params.api.setSize({ width: this.width });
}, },
onResizeGroupHeight() { onResizeGroupHeight() {
this.api.group.api.setSize({ height: this.height }); this.params.api.group.api.setSize({ height: this.height });
}, },
onResizePanelHeight() { onResizePanelHeight() {
this.api.setSize({ height: this.height }); this.params.api.setSize({ height: this.height });
}, },
}, },
mounted() { mounted() {
const disposable = this.api.onDidTitleChange(() => { const disposable = this.params.api.onDidTitleChange(() => {
this.title = this.api.title; this.title = this.api.title;
}); });
this.title = this.api.title; this.title = this.api.title;
@ -73,14 +65,7 @@ const App = defineComponent({
name: 'App', name: 'App',
components: { components: {
'dockview-vue': DockviewVue, 'dockview-vue': DockviewVue,
Panel, default: Panel,
},
data() {
return {
components: {
default: Panel,
},
};
}, },
methods: { methods: {
onReady(event: DockviewReadyEvent) { onReady(event: DockviewReadyEvent) {
@ -127,7 +112,6 @@ const App = defineComponent({
style="width:100%;height:100%" style="width:100%;height:100%"
class="dockview-theme-abyss" class="dockview-theme-abyss"
@ready="onReady" @ready="onReady"
:components="components"
</dockview-vue>`, </dockview-vue>`,
}); });

View File

@ -51,15 +51,9 @@ const App = defineComponent({
name: 'App', name: 'App',
components: { components: {
'dockview-vue': DockviewVue, 'dockview-vue': DockviewVue,
}, fixedHeightContainer: FixedHeightContainer,
data() { overflowContainer: OverflowContainer,
return { userDefinedOverflowContainer: UserDefinedOverflowContainer,
components: {
fixedHeightContainer: FixedHeightContainer,
overflowContainer: OverflowContainer,
userDefinedOverflowContainer: UserDefinedOverflowContainer,
},
};
}, },
methods: { methods: {
onReady(event: DockviewReadyEvent) { onReady(event: DockviewReadyEvent) {
@ -89,7 +83,6 @@ const App = defineComponent({
style="width:100%;height:100%" style="width:100%;height:100%"
class="dockview-theme-abyss" class="dockview-theme-abyss"
@ready="onReady" @ready="onReady"
:components="components"
:disableFloatingGroups=true :disableFloatingGroups=true
</dockview-vue>`, </dockview-vue>`,
}); });

View File

@ -10,16 +10,8 @@ import {
const Panel = defineComponent({ const Panel = defineComponent({
name: 'Panel', name: 'Panel',
props: { props: {
api: {
type: Object as PropType<IDockviewPanelProps['api']>,
required: true,
},
containerApi: {
type: Object as PropType<IDockviewPanelProps['containerApi']>,
required: true,
},
params: { params: {
type: Object as PropType<IDockviewPanelProps['params']>, type: Object as PropType<IDockviewPanelProps>,
required: true, required: true,
}, },
}, },
@ -29,7 +21,7 @@ const Panel = defineComponent({
}; };
}, },
mounted() { mounted() {
const disposable = this.api.onDidTitleChange(() => { const disposable = this.params.api.onDidTitleChange(() => {
this.title = this.api.title; this.title = this.api.title;
}); });
this.title = this.api.title; this.title = this.api.title;
@ -48,14 +40,7 @@ const App = defineComponent({
name: 'App', name: 'App',
components: { components: {
'dockview-vue': DockviewVue, 'dockview-vue': DockviewVue,
Panel, default: Panel,
},
setup() {
return {
components: {
default: Panel,
},
};
}, },
data() { data() {
return { api: null as DockviewApi | null }; return { api: null as DockviewApi | null };
@ -107,7 +92,6 @@ const App = defineComponent({
style="width:100%;height:100%" style="width:100%;height:100%"
class="dockview-theme-abyss" class="dockview-theme-abyss"
@ready="onReady" @ready="onReady"
:components="components"
:disableFloatingGroups=true :disableFloatingGroups=true
</dockview-vue>`, </dockview-vue>`,
}); });

View File

@ -10,16 +10,8 @@ import {
const Panel = defineComponent({ const Panel = defineComponent({
name: 'Panel', name: 'Panel',
props: { props: {
api: {
type: Object as PropType<IDockviewPanelProps['api']>,
required: true,
},
containerApi: {
type: Object as PropType<IDockviewPanelProps['containerApi']>,
required: true,
},
params: { params: {
type: Object as PropType<IDockviewPanelProps['params']>, type: Object as PropType<IDockviewPanelProps>,
required: true, required: true,
}, },
}, },
@ -51,9 +43,9 @@ const Panel = defineComponent({
} }
const interval = setInterval(() => { const interval = setInterval(() => {
this.api.updateParameters({ myValue: Date.now() }); this.params.api.updateParameters({ myValue: Date.now() });
}, 1000); }, 1000);
this.api.updateParameters({ myValue: Date.now() }); this.params.api.updateParameters({ myValue: Date.now() });
return () => { return () => {
clearInterval(interval); clearInterval(interval);
@ -71,16 +63,8 @@ const Panel = defineComponent({
const Tab = defineComponent({ const Tab = defineComponent({
name: 'Tab', name: 'Tab',
props: { props: {
api: {
type: Object as PropType<IDockviewPanelHeaderProps['api']>,
required: true,
},
containerApi: {
type: Object as PropType<IDockviewPanelHeaderProps['containerApi']>,
required: true,
},
params: { params: {
type: Object as PropType<IDockviewPanelHeaderProps['params']>, type: Object as PropType<IDockviewPanelHeaderProps>,
required: true, required: true,
}, },
}, },
@ -91,11 +75,11 @@ const Tab = defineComponent({
}; };
}, },
mounted() { mounted() {
const disposable = this.api.onDidTitleChange(() => { const disposable = this.params.api.onDidTitleChange(() => {
this.title = this.api.title; this.title = this.api.title;
}); });
const disposable2 = this.api.onDidParametersChange(() => { const disposable2 = this.params.api.onDidParametersChange(() => {
this.value = this.params.myValue; this.value = this.params.myValue;
}); });
@ -119,23 +103,15 @@ const App = defineComponent({
components: { components: {
'dockview-vue': DockviewVue, 'dockview-vue': DockviewVue,
Panel, Panel,
}, defaultPanel: Panel,
data() { defaultTab: Tab,
return {
components: {
default: Panel,
},
tabComponents: {
default: Tab,
},
};
}, },
methods: { methods: {
onReady(event: DockviewReadyEvent) { onReady(event: DockviewReadyEvent) {
event.api.addPanel({ event.api.addPanel({
id: 'panel_1', id: 'panel_1',
component: 'default', component: 'defaultPanel',
tabComponent: 'default', tabComponent: 'defaultTab',
params: { params: {
myValue: Date.now(), myValue: Date.now(),
}, },
@ -143,8 +119,8 @@ const App = defineComponent({
event.api.addPanel({ event.api.addPanel({
id: 'panel_2', id: 'panel_2',
component: 'default', component: 'defaultPanel',
tabComponent: 'default', tabComponent: 'defaultTab',
params: { params: {
myValue: Date.now(), myValue: Date.now(),
}, },
@ -156,8 +132,6 @@ const App = defineComponent({
style="width:100%;height:100%" style="width:100%;height:100%"
class="dockview-theme-abyss" class="dockview-theme-abyss"
@ready="onReady" @ready="onReady"
:components="components"
:tabComponents="tabComponents"
</dockview-vue>`, </dockview-vue>`,
}); });

View File

@ -1,24 +1,13 @@
import 'dockview-core/dist/styles/dockview.css'; import 'dockview-core/dist/styles/dockview.css';
import { PropType, createApp, defineComponent } from 'vue'; import { PropType, createApp, defineComponent } from 'vue';
import { DockviewVue } from 'dockview-vue'; import { DockviewVue } from 'dockview-vue';
import { import { DockviewReadyEvent, IDockviewPanelProps } from 'dockview-core';
DockviewReadyEvent,
IDockviewPanelProps,
} from 'dockview-core';
const Panel = defineComponent({ const Panel = defineComponent({
name: 'Panel', name: 'Panel',
props: { props: {
api: {
type: Object as PropType<IDockviewPanelProps['api']>,
required: true,
},
containerApi: {
type: Object as PropType<IDockviewPanelProps['containerApi']>,
required: true,
},
params: { params: {
type: Object as PropType<IDockviewPanelProps['params']>, type: Object as PropType<IDockviewPanelProps>,
required: true, required: true,
}, },
}, },
@ -30,7 +19,7 @@ const Panel = defineComponent({
}, },
methods: { methods: {
onChangeTitle() { onChangeTitle() {
this.api.setTitle(this.value); this.params.api.setTitle(this.value);
}, },
updateTitle(title: string) { updateTitle(title: string) {
this.title = title; this.title = title;
@ -62,14 +51,7 @@ const App = defineComponent({
name: 'App', name: 'App',
components: { components: {
'dockview-vue': DockviewVue, 'dockview-vue': DockviewVue,
Panel, default: Panel,
},
data() {
return {
components: {
default: Panel,
},
};
}, },
methods: { methods: {
onReady(event: DockviewReadyEvent) { onReady(event: DockviewReadyEvent) {
@ -107,7 +89,6 @@ const App = defineComponent({
style="width:100%;height:100%" style="width:100%;height:100%"
class="dockview-theme-abyss" class="dockview-theme-abyss"
@ready="onReady" @ready="onReady"
:components="components"
</dockview-vue>`, </dockview-vue>`,
}); });

View File

@ -12,16 +12,8 @@ import {
const Panel = defineComponent({ const Panel = defineComponent({
name: 'Panel', name: 'Panel',
props: { props: {
api: {
type: Object as PropType<IDockviewPanelProps['api']>,
required: true,
},
containerApi: {
type: Object as PropType<IDockviewPanelProps['containerApi']>,
required: true,
},
params: { params: {
type: Object as PropType<IDockviewPanelProps['params']>, type: Object as PropType<IDockviewPanelProps>,
required: true, required: true,
}, },
}, },
@ -37,27 +29,23 @@ const Panel = defineComponent({
const WatermarkPanel = defineComponent({ const WatermarkPanel = defineComponent({
name: 'Panel', name: 'Panel',
props: { props: {
group: { params: {
type: Object as PropType<IWatermarkPanelProps['group']>, type: Object as PropType<IWatermarkPanelProps>,
required: true,
},
containerApi: {
type: Object as PropType<IWatermarkPanelProps['containerApi']>,
required: true, required: true,
}, },
}, },
setup(props) { setup(props) {
return { isGroup: props.containerApi.groups.length > 0 }; return { isGroup: props.params.containerApi.groups.length > 0 };
}, },
methods: { methods: {
onAddNewPanel() { onAddNewPanel() {
this.containerApi.addPanel({ this.params.containerApi.addPanel({
id: Date.now().toString(), id: Date.now().toString(),
component: 'default', component: 'default',
}); });
}, },
onCloseGroup() { onCloseGroup() {
this.group?.api.close(); this.params.group?.api.close();
}, },
}, },
template: ` template: `
@ -80,18 +68,16 @@ const App = defineComponent({
name: 'App', name: 'App',
components: { components: {
'dockview-vue': DockviewVue, 'dockview-vue': DockviewVue,
Panel, default: Panel,
watermarkComponent: WatermarkPanel,
}, },
data() { data() {
return { return {
components: { api: null as DockviewApi | null,
default: Panel,
},
watermarkComponent: WatermarkPanel,
}; };
}, },
methods: { methods: {
onClick(event: MouseEvent) { onClick() {
if (!this.api) { if (!this.api) {
return; return;
} }
@ -99,6 +85,7 @@ const App = defineComponent({
this.api.addGroup(); this.api.addGroup();
}, },
onReady(event: DockviewReadyEvent) { onReady(event: DockviewReadyEvent) {
this.api = event.api;
event.api.fromJSON({ event.api.fromJSON({
grid: { grid: {
orientation: Orientation.HORIZONTAL, orientation: Orientation.HORIZONTAL,
@ -119,8 +106,7 @@ const App = defineComponent({
style="width:100%;height:100%" style="width:100%;height:100%"
class="dockview-theme-abyss" class="dockview-theme-abyss"
@ready="onReady" @ready="onReady"
:components="components" watermarkComponent="watermarkComponent"
:watermarkComponent="watermarkComponent"
> >
</dockview-vue> </dockview-vue>
</div>`, </div>`,

View File

@ -2,6 +2,7 @@
"extends": "./tsconfig.base.json", "extends": "./tsconfig.base.json",
"compilerOptions": { "compilerOptions": {
"jsx": "react-jsx", "jsx": "react-jsx",
"noImplicitAny": false,
"sourceMap": true "sourceMap": true
}, },
"include": ["**/*.spec.ts", "./jest-setup.ts"] "include": ["**/*.spec.ts", "./jest-setup.ts"]