diff --git a/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts b/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts index d544001fa..8d36f5420 100644 --- a/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts +++ b/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts @@ -5378,6 +5378,101 @@ describe('dockviewComponent', () => { }); describe('addPanel', () => { + test('that can add panel to index with referencePanel', () => { + const container = document.createElement('div'); + + const dockview = new DockviewComponent(container, { + createComponent(options) { + switch (options.name) { + case 'default': + return new PanelContentPartTest( + options.id, + options.name + ); + default: + throw new Error(`unsupported`); + } + }, + }); + const api = new DockviewApi(dockview); + + dockview.layout(1000, 1000); + + const panel1 = api.addPanel({ + id: 'panel_1', + component: 'default', + }); + + const panel2 = api.addPanel({ + id: 'panel_2', + component: 'default', + position: { + referencePanel: panel1, + }, + }); + + const panel3 = api.addPanel({ + id: 'panel_3', + component: 'default', + position: { + referencePanel: panel1, + index: 1, + }, + }); + + expect(panel1.api.group.panels).toEqual([panel1, panel3, panel2]); + }); + + test('that can add panel to index with referenceGroup', () => { + const container = document.createElement('div'); + + const dockview = new DockviewComponent(container, { + createComponent(options) { + switch (options.name) { + case 'default': + return new PanelContentPartTest( + options.id, + options.name + ); + default: + throw new Error(`unsupported`); + } + }, + }); + const api = new DockviewApi(dockview); + + dockview.layout(1000, 1000); + + const panel1 = api.addPanel({ + id: 'panel_1', + component: 'default', + }); + + const panel2 = api.addPanel({ + id: 'panel_2', + component: 'default', + position: { + referencePanel: panel1, + index: 1, + }, + }); + + const panel3 = api.addPanel({ + id: 'panel_3', + component: 'default', + position: { + referenceGroup: panel1.api.group, + index: 1, + }, + }); + + expect(panel1.api.group.panels).toEqual([panel1, panel3, panel2]); + + panel1.api.moveTo({ index: 1 }); + + expect(panel1.api.group.panels).toEqual([panel3, panel1, panel2]); + }); + test('that can add panel', () => { const container = document.createElement('div'); diff --git a/packages/dockview-core/src/api/dockviewGroupPanelApi.ts b/packages/dockview-core/src/api/dockviewGroupPanelApi.ts index b13bd8fd9..12424debb 100644 --- a/packages/dockview-core/src/api/dockviewGroupPanelApi.ts +++ b/packages/dockview-core/src/api/dockviewGroupPanelApi.ts @@ -9,6 +9,15 @@ import { Emitter, Event } from '../events'; import { MutableDisposable } from '../lifecycle'; import { GridviewPanelApi, GridviewPanelApiImpl } from './gridviewPanelApi'; +export interface DockviewGroupMoveParams { + group?: DockviewGroupPanel; + position?: Position; + /** + * The index to place the panel within a group, only applicable if the placement is within an existing group + */ + index?: number; +} + export interface DockviewGroupPanelApi extends GridviewPanelApi { readonly onDidLocationChange: Event; readonly onDidActivePanelChange: Event; @@ -17,7 +26,7 @@ export interface DockviewGroupPanelApi extends GridviewPanelApi { * If you require the Window object */ getWindow(): Window; - moveTo(options: { group?: DockviewGroupPanel; position?: Position }): void; + moveTo(options: DockviewGroupMoveParams): void; maximize(): void; isMaximized(): boolean; exitMaximized(): void; @@ -28,7 +37,8 @@ export interface DockviewGroupPanelFloatingChangeEvent { readonly location: DockviewGroupLocation; } -const NOT_INITIALIZED_MESSAGE = 'dockview: DockviewGroupPanelApiImpl not initialized'; +const NOT_INITIALIZED_MESSAGE = + 'dockview: DockviewGroupPanelApiImpl not initialized'; export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl { private readonly _mutableDisposable = new MutableDisposable(); @@ -74,7 +84,7 @@ export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl { : window; } - moveTo(options: { group?: DockviewGroupPanel; position?: Position }): void { + moveTo(options: DockviewGroupMoveParams): void { if (!this._group) { throw new Error(NOT_INITIALIZED_MESSAGE); } @@ -93,6 +103,7 @@ export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl { position: options.group ? options.position ?? 'center' : 'center', + index: options.index, }, }); } diff --git a/packages/dockview-core/src/api/dockviewPanelApi.ts b/packages/dockview-core/src/api/dockviewPanelApi.ts index 20646b16d..4b33f5eae 100644 --- a/packages/dockview-core/src/api/dockviewPanelApi.ts +++ b/packages/dockview-core/src/api/dockviewPanelApi.ts @@ -4,9 +4,11 @@ import { DockviewGroupPanel } from '../dockview/dockviewGroupPanel'; import { CompositeDisposable, MutableDisposable } from '../lifecycle'; import { DockviewPanel } from '../dockview/dockviewPanel'; import { DockviewComponent } from '../dockview/dockviewComponent'; -import { Position } from '../dnd/droptarget'; import { DockviewPanelRenderer } from '../overlay/overlayRenderContainer'; -import { DockviewGroupPanelFloatingChangeEvent } from './dockviewGroupPanelApi'; +import { + DockviewGroupMoveParams, + DockviewGroupPanelFloatingChangeEvent, +} from './dockviewGroupPanelApi'; import { DockviewGroupLocation } from '../dockview/dockviewGroupPanelModel'; export interface TitleEvent { @@ -25,6 +27,8 @@ export interface GroupChangedEvent { // empty } +export type DockviewPanelMoveParams = DockviewGroupMoveParams; + export interface DockviewPanelApi extends Omit< GridviewPanelApi, @@ -50,11 +54,7 @@ export interface DockviewPanelApi close(): void; setTitle(title: string): void; setRenderer(renderer: DockviewPanelRenderer): void; - moveTo(options: { - group: DockviewGroupPanel; - position?: Position; - index?: number; - }): void; + moveTo(options: DockviewPanelMoveParams): void; maximize(): void; isMaximized(): boolean; exitMaximized(): void; @@ -160,16 +160,14 @@ export class DockviewPanelApiImpl return this.group.api.getWindow(); } - moveTo(options: { - group: DockviewGroupPanel; - position?: Position; - index?: number; - }): void { + moveTo(options: DockviewPanelMoveParams): void { this.accessor.moveGroupOrPanel({ from: { groupId: this._group.id, panelId: this.panel.id }, to: { - group: options.group, - position: options.position ?? 'center', + group: options.group ?? this._group, + position: options.group + ? options.position ?? 'center' + : 'center', index: options.index, }, }); diff --git a/packages/dockview-core/src/dockview/dockviewComponent.ts b/packages/dockview-core/src/dockview/dockviewComponent.ts index a7b71827d..0328b8298 100644 --- a/packages/dockview-core/src/dockview/dockviewComponent.ts +++ b/packages/dockview-core/src/dockview/dockviewComponent.ts @@ -1387,12 +1387,15 @@ export class DockviewComponent height: options.initialHeight, }; + let index: number | undefined; + if (options.position) { if (isPanelOptionsWithPanel(options.position)) { const referencePanel = typeof options.position.referencePanel === 'string' ? this.getGroupPanel(options.position.referencePanel) : options.position.referencePanel; + index = options.position.index; if (!referencePanel) { throw new Error( @@ -1407,6 +1410,7 @@ export class DockviewComponent ? this._groups.get(options.position.referenceGroup) ?.value : options.position.referenceGroup; + index = options.position.index; if (!referenceGroup) { throw new Error( @@ -1422,6 +1426,7 @@ export class DockviewComponent group.model.openPanel(panel, { skipSetActive: options.inactive, skipSetGroupActive: options.inactive, + index, }); if (!options.inactive) { @@ -1468,6 +1473,7 @@ export class DockviewComponent group.model.openPanel(panel, { skipSetActive: options.inactive, skipSetGroupActive: options.inactive, + index, }); } else if ( referenceGroup.api.location.type === 'floating' || @@ -1477,6 +1483,7 @@ export class DockviewComponent referenceGroup.model.openPanel(panel, { skipSetActive: options.inactive, skipSetGroupActive: options.inactive, + index, }); referenceGroup.api.setSize({ @@ -1505,6 +1512,7 @@ export class DockviewComponent group.model.openPanel(panel, { skipSetActive: options.inactive, skipSetGroupActive: options.inactive, + index, }); if (!options.inactive) { @@ -1532,6 +1540,7 @@ export class DockviewComponent group.model.openPanel(panel, { skipSetActive: options.inactive, skipSetGroupActive: options.inactive, + index, }); } else { const group = this.createGroupAtLocation( @@ -1544,6 +1553,7 @@ export class DockviewComponent group.model.openPanel(panel, { skipSetActive: options.inactive, skipSetGroupActive: options.inactive, + index, }); if (!options.inactive) { diff --git a/packages/dockview-core/src/dockview/dockviewGroupPanelModel.ts b/packages/dockview-core/src/dockview/dockviewGroupPanelModel.ts index fb27c42fd..28847b33b 100644 --- a/packages/dockview-core/src/dockview/dockviewGroupPanelModel.ts +++ b/packages/dockview-core/src/dockview/dockviewGroupPanelModel.ts @@ -326,7 +326,7 @@ export class DockviewGroupPanelModel private readonly _api: DockviewApi; get element(): HTMLElement { - throw new Error('not supported'); + throw new Error('dockview: not supported'); } get activePanel(): IDockviewPanel | undefined { diff --git a/packages/dockview-core/src/dockview/options.ts b/packages/dockview-core/src/dockview/options.ts index 9f21344e1..c1a429a08 100644 --- a/packages/dockview-core/src/dockview/options.ts +++ b/packages/dockview-core/src/dockview/options.ts @@ -159,11 +159,19 @@ export interface PanelOptions

{ type RelativePanel = { direction?: Direction; referencePanel: string | IDockviewPanel; + /** + * The index to place the panel within a group, only applicable if the placement is within an existing group + */ + index?: number; }; type RelativeGroup = { direction?: Direction; referenceGroup: string | DockviewGroupPanel; + /** + * The index to place the panel within a group, only applicable if the placement is within an existing group + */ + index?: number; }; type AbsolutePosition = { diff --git a/packages/dockview-core/src/index.ts b/packages/dockview-core/src/index.ts index 02171ae7d..59d4a19e6 100644 --- a/packages/dockview-core/src/index.ts +++ b/packages/dockview-core/src/index.ts @@ -100,6 +100,7 @@ export { TitleEvent, RendererChangedEvent, DockviewPanelApi, + DockviewPanelMoveParams, } from './api/dockviewPanelApi'; export { PanelSizeEvent, @@ -110,6 +111,7 @@ export { ExpansionEvent, PaneviewPanelApi } from './api/paneviewPanelApi'; export { DockviewGroupPanelApi, DockviewGroupPanelFloatingChangeEvent, + DockviewGroupMoveParams, } from './api/dockviewGroupPanelApi'; export { CommonApi,