Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -263,9 +263,10 @@ export class Tabs extends CompositeDisposable {
tab: IValueDisposable<Tab>,
index: number = this._tabs.length
): void {
if (index < 0 || index > this._tabs.length) {
throw new Error('invalid location');
}
// Clamp index to valid range to prevent IndexOutOfBounds errors
// This can happen when dragging panels from popouts where the original
// position calculations become stale after the source panel is removed
index = Math.max(0, Math.min(index, this._tabs.length));

this._tabsList.insertBefore(
tab.value.element,
Expand Down
11 changes: 10 additions & 1 deletion packages/dockview-core/src/dockview/dockviewComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2193,9 +2193,18 @@ export class DockviewComponent
// Check if destination group is empty - if so, force render the component
const isDestinationGroupEmpty = destinationGroup.model.size === 0;

// Fix for GitHub issue #1004: When dragging from popout windows,
// the destination index might be incorrect due to stale position calculations.
// For popout sources, we should validate and potentially adjust the index.
let adjustedIndex = destinationIndex;
if (sourceGroup.api.location.type === 'popout' && typeof destinationIndex === 'number') {
// Ensure the index is within valid bounds for the destination group
adjustedIndex = Math.max(0, Math.min(destinationIndex, destinationGroup.model.size));
}

this.movingLock(() =>
destinationGroup.model.openPanel(removedPanel, {
index: destinationIndex,
index: adjustedIndex,
skipSetActive: (options.skipSetActive ?? false) && !isDestinationGroupEmpty,
skipSetGroupActive: true,
})
Expand Down