dockview-core 7.0.2 → 7.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/dist/cjs/api/dockviewGroupPanelApi.js +1 -1
  2. package/dist/cjs/dnd/dropTargetAnchorContainer.js +1 -2
  3. package/dist/cjs/dnd/pointer/longPress.js +1 -1
  4. package/dist/cjs/dnd/pointer/pointerDragController.js +9 -7
  5. package/dist/cjs/dnd/pointer/pointerDragSource.js +4 -2
  6. package/dist/cjs/dockview/components/panel/content.js +6 -6
  7. package/dist/cjs/dockview/components/popupService.js +1 -1
  8. package/dist/cjs/dockview/components/tab/tab.js +2 -2
  9. package/dist/cjs/dockview/components/titlebar/floatingTitleBar.d.ts +1 -2
  10. package/dist/cjs/dockview/components/titlebar/groupDragSource.d.ts +1 -2
  11. package/dist/cjs/dockview/components/titlebar/groupDragSource.js +1 -1
  12. package/dist/cjs/dockview/components/titlebar/tabGroupIndicator.js +5 -6
  13. package/dist/cjs/dockview/components/titlebar/tabGroups.d.ts +27 -5
  14. package/dist/cjs/dockview/components/titlebar/tabGroups.js +104 -54
  15. package/dist/cjs/dockview/components/titlebar/tabs.js +16 -23
  16. package/dist/cjs/dockview/components/titlebar/voidContainer.js +1 -1
  17. package/dist/cjs/dockview/dndCapabilities.js +3 -3
  18. package/dist/cjs/dockview/dockviewComponent.d.ts +5 -5
  19. package/dist/cjs/dockview/dockviewComponent.js +140 -122
  20. package/dist/cjs/dockview/dockviewGroupPanel.d.ts +1 -1
  21. package/dist/cjs/dockview/dockviewGroupPanelModel.js +19 -25
  22. package/dist/cjs/dockview/dockviewPanel.js +4 -5
  23. package/dist/cjs/dockview/dockviewShell.d.ts +29 -7
  24. package/dist/cjs/dockview/dockviewShell.js +94 -36
  25. package/dist/cjs/dockview/strictEventsSequencing.js +6 -6
  26. package/dist/cjs/dockview/tabGroup.js +3 -3
  27. package/dist/cjs/dockview/tabGroupAccent.js +1 -3
  28. package/dist/cjs/dom.js +1 -1
  29. package/dist/cjs/events.js +1 -1
  30. package/dist/cjs/gridview/baseComponentGridview.js +3 -8
  31. package/dist/cjs/gridview/branchNode.js +13 -17
  32. package/dist/cjs/gridview/gridview.js +8 -8
  33. package/dist/cjs/gridview/gridviewComponent.js +1 -6
  34. package/dist/cjs/overlay/overlay.js +25 -28
  35. package/dist/cjs/overlay/overlayRenderContainer.js +3 -4
  36. package/dist/cjs/paneview/draggablePaneviewPanel.js +1 -1
  37. package/dist/cjs/paneview/paneviewComponent.js +2 -6
  38. package/dist/cjs/popoutWindow.js +4 -4
  39. package/dist/cjs/scrollbar.d.ts +1 -1
  40. package/dist/cjs/scrollbar.js +7 -6
  41. package/dist/cjs/splitview/splitview.d.ts +1 -1
  42. package/dist/cjs/splitview/splitview.js +21 -20
  43. package/dist/cjs/splitview/viewItem.js +1 -1
  44. package/dist/dockview-core.js +413 -330
  45. package/dist/dockview-core.min.js +2 -2
  46. package/dist/dockview-core.min.js.map +1 -1
  47. package/dist/dockview-core.min.noStyle.js +2 -2
  48. package/dist/dockview-core.min.noStyle.js.map +1 -1
  49. package/dist/dockview-core.noStyle.js +412 -329
  50. package/dist/esm/api/dockviewGroupPanelApi.js +1 -1
  51. package/dist/esm/dnd/dropTargetAnchorContainer.js +1 -2
  52. package/dist/esm/dnd/pointer/longPress.js +1 -1
  53. package/dist/esm/dnd/pointer/pointerDragController.js +9 -7
  54. package/dist/esm/dnd/pointer/pointerDragSource.js +4 -2
  55. package/dist/esm/dockview/components/panel/content.js +6 -6
  56. package/dist/esm/dockview/components/popupService.js +1 -1
  57. package/dist/esm/dockview/components/tab/tab.js +2 -2
  58. package/dist/esm/dockview/components/titlebar/floatingTitleBar.d.ts +1 -2
  59. package/dist/esm/dockview/components/titlebar/groupDragSource.d.ts +1 -2
  60. package/dist/esm/dockview/components/titlebar/groupDragSource.js +1 -1
  61. package/dist/esm/dockview/components/titlebar/tabGroupIndicator.js +5 -6
  62. package/dist/esm/dockview/components/titlebar/tabGroups.d.ts +27 -5
  63. package/dist/esm/dockview/components/titlebar/tabGroups.js +91 -42
  64. package/dist/esm/dockview/components/titlebar/tabs.js +17 -24
  65. package/dist/esm/dockview/components/titlebar/voidContainer.js +1 -1
  66. package/dist/esm/dockview/dndCapabilities.js +3 -3
  67. package/dist/esm/dockview/dockviewComponent.d.ts +5 -5
  68. package/dist/esm/dockview/dockviewComponent.js +61 -51
  69. package/dist/esm/dockview/dockviewGroupPanel.d.ts +1 -1
  70. package/dist/esm/dockview/dockviewGroupPanelModel.js +19 -25
  71. package/dist/esm/dockview/dockviewPanel.js +1 -2
  72. package/dist/esm/dockview/dockviewShell.d.ts +29 -7
  73. package/dist/esm/dockview/dockviewShell.js +89 -37
  74. package/dist/esm/dockview/strictEventsSequencing.js +6 -6
  75. package/dist/esm/dockview/tabGroup.js +3 -3
  76. package/dist/esm/dockview/tabGroupAccent.js +1 -3
  77. package/dist/esm/dom.js +1 -1
  78. package/dist/esm/events.js +1 -1
  79. package/dist/esm/gridview/baseComponentGridview.js +3 -8
  80. package/dist/esm/gridview/branchNode.js +13 -15
  81. package/dist/esm/gridview/gridview.js +8 -8
  82. package/dist/esm/gridview/gridviewComponent.js +1 -6
  83. package/dist/esm/overlay/overlay.js +25 -28
  84. package/dist/esm/overlay/overlayRenderContainer.js +3 -4
  85. package/dist/esm/paneview/draggablePaneviewPanel.js +1 -1
  86. package/dist/esm/paneview/paneviewComponent.js +2 -6
  87. package/dist/esm/popoutWindow.js +4 -4
  88. package/dist/esm/scrollbar.d.ts +1 -1
  89. package/dist/esm/scrollbar.js +7 -6
  90. package/dist/esm/splitview/splitview.d.ts +1 -1
  91. package/dist/esm/splitview/splitview.js +21 -20
  92. package/dist/esm/splitview/viewItem.js +1 -1
  93. package/dist/package/main.cjs.js +412 -329
  94. package/dist/package/main.cjs.min.js +2 -2
  95. package/dist/package/main.esm.min.mjs +2 -2
  96. package/dist/package/main.esm.mjs +412 -329
  97. package/dist/styles/dockview.css +8 -8
  98. package/package.json +1 -1
@@ -72,7 +72,7 @@ export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
72
72
  getWindow() {
73
73
  return this.location.type === 'popout'
74
74
  ? this.location.getWindow()
75
- : window;
75
+ : globalThis.window;
76
76
  }
77
77
  setHeaderPosition(position) {
78
78
  if (!this._group) {
@@ -19,9 +19,8 @@ export class DropTargetAnchorContainer extends CompositeDisposable {
19
19
  }
20
20
  return {
21
21
  clear: () => {
22
- var _a;
23
22
  if (this._model) {
24
- (_a = this._model.root.parentElement) === null || _a === void 0 ? void 0 : _a.removeChild(this._model.root);
23
+ this._model.root.remove();
25
24
  }
26
25
  this._model = undefined;
27
26
  },
@@ -33,7 +33,7 @@ export class LongPressDetector extends CompositeDisposable {
33
33
  const delay = (_b = this.options.delay) !== null && _b !== void 0 ? _b : DEFAULT_DELAY;
34
34
  const tolerance = (_c = this.options.tolerance) !== null && _c !== void 0 ? _c : DEFAULT_TOLERANCE;
35
35
  // Source's owning window — popout drags fire on their own window.
36
- const targetWindow = (_e = (_d = this.element.ownerDocument) === null || _d === void 0 ? void 0 : _d.defaultView) !== null && _e !== void 0 ? _e : window;
36
+ const targetWindow = (_e = (_d = this.element.ownerDocument) === null || _d === void 0 ? void 0 : _d.defaultView) !== null && _e !== void 0 ? _e : globalThis.window;
37
37
  this._timer = setTimeout(() => {
38
38
  this._timer = undefined;
39
39
  this._cancelPending();
@@ -14,9 +14,8 @@ import { CompositeDisposable } from '../../lifecycle';
14
14
  */
15
15
  export class PointerDragController extends CompositeDisposable {
16
16
  static getInstance() {
17
- if (!PointerDragController._instance) {
18
- PointerDragController._instance = new PointerDragController();
19
- }
17
+ var _a;
18
+ (_a = PointerDragController._instance) !== null && _a !== void 0 ? _a : (PointerDragController._instance = new PointerDragController());
20
19
  return PointerDragController._instance;
21
20
  }
22
21
  constructor() {
@@ -81,21 +80,24 @@ export class PointerDragController extends CompositeDisposable {
81
80
  this._onDragStart.fire(startEvent);
82
81
  // Source's owning window — popout drags fire on their own window,
83
82
  // not the main one.
84
- const targetWindow = (_c = (_b = source.ownerDocument) === null || _b === void 0 ? void 0 : _b.defaultView) !== null && _c !== void 0 ? _c : window;
83
+ const targetWindow = (_c = (_b = source.ownerDocument) === null || _b === void 0 ? void 0 : _b.defaultView) !== null && _c !== void 0 ? _c : globalThis.window;
85
84
  this._moveListener = addDisposableListener(targetWindow, 'pointermove', (e) => {
86
- if (!this._active || e.pointerId !== this._active.pointerId) {
85
+ var _a;
86
+ if (e.pointerId !== ((_a = this._active) === null || _a === void 0 ? void 0 : _a.pointerId)) {
87
87
  return;
88
88
  }
89
89
  this._handleMove(e);
90
90
  });
91
91
  this._upListener = addDisposableListener(targetWindow, 'pointerup', (e) => {
92
- if (!this._active || e.pointerId !== this._active.pointerId) {
92
+ var _a;
93
+ if (e.pointerId !== ((_a = this._active) === null || _a === void 0 ? void 0 : _a.pointerId)) {
93
94
  return;
94
95
  }
95
96
  this._handleEnd(e, true);
96
97
  });
97
98
  this._cancelListener = addDisposableListener(targetWindow, 'pointercancel', (e) => {
98
- if (!this._active || e.pointerId !== this._active.pointerId) {
99
+ var _a;
100
+ if (e.pointerId !== ((_a = this._active) === null || _a === void 0 ? void 0 : _a.pointerId)) {
99
101
  return;
100
102
  }
101
103
  this._handleEnd(e, false);
@@ -82,7 +82,9 @@ export class PointerDragSource extends CompositeDisposable {
82
82
  ? initiationDelayOpt()
83
83
  : initiationDelayOpt)) !== null && _a !== void 0 ? _a : DEFAULT_TOUCH_INITIATION_DELAY;
84
84
  this._armed = !isTouch || initiationDelay <= 0;
85
- if (isTouch && initiationDelay > 0 && isFinite(initiationDelay)) {
85
+ if (isTouch &&
86
+ initiationDelay > 0 &&
87
+ Number.isFinite(initiationDelay)) {
86
88
  this._armTimer = setTimeout(() => {
87
89
  this._armTimer = undefined;
88
90
  this._armed = true;
@@ -94,7 +96,7 @@ export class PointerDragSource extends CompositeDisposable {
94
96
  ? pressToleranceOpt()
95
97
  : pressToleranceOpt)) !== null && _c !== void 0 ? _c : DEFAULT_PRESS_TOLERANCE;
96
98
  // Source's owning window — popout drags fire on their own window.
97
- const targetWindow = (_e = (_d = this.element.ownerDocument) === null || _d === void 0 ? void 0 : _d.defaultView) !== null && _e !== void 0 ? _e : window;
99
+ const targetWindow = (_e = (_d = this.element.ownerDocument) === null || _d === void 0 ? void 0 : _d.defaultView) !== null && _e !== void 0 ? _e : globalThis.window;
98
100
  this._pendingMoveListener = addDisposableListener(targetWindow, 'pointermove', (moveEvent) => {
99
101
  if (moveEvent.pointerId !== this._pendingPointerId) {
100
102
  return;
@@ -46,7 +46,7 @@ export class ContentContainer extends CompositeDisposable {
46
46
  this.group.location.type !== 'floating') {
47
47
  return false;
48
48
  }
49
- if (data && data.viewId === this.accessor.id) {
49
+ if ((data === null || data === void 0 ? void 0 : data.viewId) === this.accessor.id) {
50
50
  return true;
51
51
  }
52
52
  return this.group.canDisplayOverlay(event, position, 'content');
@@ -113,7 +113,7 @@ export class ContentContainer extends CompositeDisposable {
113
113
  /**
114
114
  * If the currently attached panel is mounted directly to the content then remove it
115
115
  */
116
- this._element.removeChild(this.panel.view.content.element);
116
+ this.panel.view.content.element.remove();
117
117
  (_b = (_a = this.panel.view.content).onHide) === null || _b === void 0 ? void 0 : _b.call(_a);
118
118
  }
119
119
  this.panel = panel;
@@ -131,7 +131,7 @@ export class ContentContainer extends CompositeDisposable {
131
131
  break;
132
132
  case 'always':
133
133
  if (panel.view.content.element.parentElement === this._element) {
134
- this._element.removeChild(panel.view.content.element);
134
+ panel.view.content.element.remove();
135
135
  }
136
136
  container = this.group.renderContainer.attach({
137
137
  panel,
@@ -159,11 +159,11 @@ export class ContentContainer extends CompositeDisposable {
159
159
  // noop
160
160
  }
161
161
  closePanel() {
162
- var _a, _b, _c;
162
+ var _a, _b;
163
163
  if (this.panel) {
164
164
  if (this.panel.api.renderer === 'onlyWhenVisible') {
165
- (_a = this.panel.view.content.element.parentElement) === null || _a === void 0 ? void 0 : _a.removeChild(this.panel.view.content.element);
166
- (_c = (_b = this.panel.view.content).onHide) === null || _c === void 0 ? void 0 : _c.call(_b);
165
+ this.panel.view.content.element.remove();
166
+ (_b = (_a = this.panel.view.content).onHide) === null || _b === void 0 ? void 0 : _b.call(_a);
167
167
  }
168
168
  }
169
169
  this.panel = undefined;
@@ -10,7 +10,7 @@ function isCoarsePrimaryInput(win) {
10
10
  return coarse && !fine;
11
11
  }
12
12
  export class PopupService extends CompositeDisposable {
13
- constructor(root, win = window) {
13
+ constructor(root, win = globalThis.window) {
14
14
  super();
15
15
  this._active = null;
16
16
  this._activeDisposable = new MutableDisposable();
@@ -55,7 +55,7 @@ export class Tab extends CompositeDisposable {
55
55
  return false;
56
56
  }
57
57
  const data = getPanelData();
58
- if (data && this.accessor.id === data.viewId) {
58
+ if (this.accessor.id === (data === null || data === void 0 ? void 0 : data.viewId)) {
59
59
  // Smooth-reorder takes over the in-flight visual when active,
60
60
  // so individual tab overlays are suppressed for internal drags.
61
61
  if (((_a = this.accessor.options.theme) === null || _a === void 0 ? void 0 : _a.tabAnimation) === 'smooth') {
@@ -156,7 +156,7 @@ export class Tab extends CompositeDisposable {
156
156
  }
157
157
  setContent(part) {
158
158
  if (this.content) {
159
- this._element.removeChild(this.content.element);
159
+ this.content.element.remove();
160
160
  }
161
161
  this.content = part;
162
162
  this._element.appendChild(this.content.element);
@@ -1,5 +1,4 @@
1
1
  import { DockviewComponent } from '../../dockviewComponent';
2
- import { Event } from '../../../events';
3
2
  import { CompositeDisposable } from '../../../lifecycle';
4
3
  import { DockviewGroupPanel } from '../../dockviewGroupPanel';
5
4
  /**
@@ -20,7 +19,7 @@ export declare class FloatingTitleBar extends CompositeDisposable {
20
19
  private readonly dragSource;
21
20
  private _group;
22
21
  private readonly _onDragStart;
23
- readonly onDragStart: Event<PointerEvent | DragEvent>;
22
+ readonly onDragStart: import("../../../events").Event<PointerEvent | DragEvent>;
24
23
  get element(): HTMLElement;
25
24
  /** The window's current anchor group — the one this bar drags/activates. */
26
25
  get group(): DockviewGroupPanel;
@@ -1,5 +1,4 @@
1
1
  import { DockviewComponent } from '../../dockviewComponent';
2
- import { Event } from '../../../events';
3
2
  import { CompositeDisposable } from '../../../lifecycle';
4
3
  import { DockviewGroupPanel } from '../../dockviewGroupPanel';
5
4
  declare const FLOATING_REDOCK_INITIATION_DELAY_MS = 500;
@@ -42,7 +41,7 @@ export declare class GroupDragSource extends CompositeDisposable {
42
41
  private readonly pointerDragSource;
43
42
  private readonly panelTransfer;
44
43
  private readonly _onDragStart;
45
- readonly onDragStart: Event<PointerEvent | DragEvent>;
44
+ readonly onDragStart: import("../../../events").Event<PointerEvent | DragEvent>;
46
45
  private readonly isFloatingMoveHandle;
47
46
  private get group();
48
47
  constructor(options: GroupDragSourceOptions);
@@ -42,7 +42,7 @@ export class GroupDragSource extends CompositeDisposable {
42
42
  this.addDisposables(this._onDragStart);
43
43
  const buildMultiPanelsGhost = () => {
44
44
  const ghostEl = document.createElement('div');
45
- const style = window.getComputedStyle(this._element);
45
+ const style = globalThis.getComputedStyle(this._element);
46
46
  const bgColor = style.getPropertyValue('--dv-activegroup-visiblepanel-tab-background-color');
47
47
  const color = style.getPropertyValue('--dv-activegroup-visiblepanel-tab-color');
48
48
  ghostEl.style.backgroundColor = bgColor;
@@ -142,8 +142,7 @@ class BaseTabGroupIndicator {
142
142
  const isAnimating = tg.collapsed ||
143
143
  tg.panelIds.some((pid) => {
144
144
  const te = tabMap.get(pid);
145
- return (te &&
146
- te.value.element.classList.contains('dv-tab--group-expanding'));
145
+ return te === null || te === void 0 ? void 0 : te.value.element.classList.contains('dv-tab--group-expanding');
147
146
  });
148
147
  if (isAnimating && chipEl) {
149
148
  const chipRect = chipEl.getBoundingClientRect();
@@ -240,7 +239,10 @@ export class WrapTabGroupIndicator extends BaseTabGroupIndicator {
240
239
  // Ensure SVG + path child exists (created once, reused)
241
240
  let svg = underline.firstElementChild;
242
241
  let path;
243
- if (!svg || svg.tagName !== 'svg') {
242
+ if ((svg === null || svg === void 0 ? void 0 : svg.tagName) === 'svg') {
243
+ path = svg.firstElementChild;
244
+ }
245
+ else {
244
246
  underline.replaceChildren();
245
247
  svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
246
248
  svg.style.display = 'block';
@@ -249,9 +251,6 @@ export class WrapTabGroupIndicator extends BaseTabGroupIndicator {
249
251
  svg.appendChild(path);
250
252
  underline.appendChild(svg);
251
253
  }
252
- else {
253
- path = svg.firstElementChild;
254
- }
255
254
  path.setAttribute('stroke', color);
256
255
  path.setAttribute('stroke-width', String(t));
257
256
  if (!activeTabEntry) {
@@ -27,9 +27,17 @@ export interface TabGroupManagerCallbacks {
27
27
  }
28
28
  interface ChipRendererEntry {
29
29
  chip: ITabGroupChipRenderer;
30
- /** Created by the manager so it can be toggled live on strategy changes. */
31
- html5DragSource: IDragSource;
32
- pointerDragSource: IDragSource;
30
+ /**
31
+ * Created by the manager so it can be toggled live on strategy changes.
32
+ * Undefined between an in-flight drag being torn down by
33
+ * `disposeChipDrag` and the following `update()` re-arming it — the chip
34
+ * element outlives a within-group move even though its drag sources do
35
+ * not. (#1410)
36
+ */
37
+ html5DragSource: IDragSource | undefined;
38
+ pointerDragSource: IDragSource | undefined;
39
+ /** Disposes the two drag sources + their shared dragend listener. */
40
+ dragSourcesDisposable: IDisposable | undefined;
33
41
  disposable: IDisposable;
34
42
  dropTarget: Droptarget;
35
43
  }
@@ -70,14 +78,28 @@ export declare class TabGroupManager {
70
78
  * iframe shield are released BEFORE the cross-group move detaches
71
79
  * the chip (chip dispose is scheduled on a microtask via
72
80
  * `_scheduleTabGroupUpdate`, which is too late for callers that read
73
- * `getPanelData()` synchronously after the move). Idempotent — the
74
- * subsequent `update()` will also dispose the sources.
81
+ * `getPanelData()` synchronously after the move).
82
+ *
83
+ * A cross-group move dissolves the source chip entirely, but a
84
+ * within-group reorder keeps the same chip element — so the sources are
85
+ * cleared to `undefined` here and the subsequent `update()` re-arms them
86
+ * via `_ensureChipForGroup`. Without that re-arm the chip would fire a
87
+ * native `dragstart` (the element keeps `draggable=true`) but never set
88
+ * a transfer payload, leaving the group permanently undraggable after
89
+ * its first move. (#1410)
75
90
  */
76
91
  disposeChipDrag(tabGroupId: string): void;
77
92
  /** Cloned chip rect used as the pointer follow-finger ghost. */
78
93
  private _buildChipGhostElement;
79
94
  disposeAll(): void;
80
95
  private _ensureIndicator;
96
+ /**
97
+ * Create the HTML5 + pointer drag sources for a chip (and the direct
98
+ * dragend listener that clears the transfer synchronously). Extracted so
99
+ * both the initial chip build and the post-move re-arm in
100
+ * `_ensureChipForGroup` share one wiring path. (#1410)
101
+ */
102
+ private _createChipDragSources;
81
103
  private _ensureChipForGroup;
82
104
  private _positionChipForGroup;
83
105
  private _updateTabGroupClasses;
@@ -1,6 +1,6 @@
1
1
  import { toggleClass } from '../../../dom';
2
2
  import { addDisposableListener } from '../../../events';
3
- import { LocalSelectionTransfer, PanelTransfer, } from '../../../dnd/dataTransfer';
3
+ import { getPanelData, LocalSelectionTransfer, PanelTransfer, } from '../../../dnd/dataTransfer';
4
4
  import { html5Backend, pointerBackend, } from '../../../dnd/backend';
5
5
  import { LongPressDetector } from '../../../dnd/pointer/longPress';
6
6
  import { CompositeDisposable, } from '../../../lifecycle';
@@ -8,7 +8,6 @@ import { resolveDndCapabilities } from '../../dndCapabilities';
8
8
  import { applyTabGroupAccent } from '../../tabGroupAccent';
9
9
  import { TabGroupChip } from './tabGroupChip';
10
10
  import { Droptarget } from '../../../dnd/droptarget';
11
- import { getPanelData } from '../../../dnd/dataTransfer';
12
11
  import { NoneTabGroupIndicator, WrapTabGroupIndicator, } from './tabGroupIndicator';
13
12
  const EMPTY_MAP = new Map();
14
13
  export class TabGroupManager {
@@ -38,6 +37,7 @@ export class TabGroupManager {
38
37
  * in the parent group model. Call after any tab group mutation.
39
38
  */
40
39
  update() {
40
+ var _a;
41
41
  const model = this._ctx.group.model;
42
42
  const tabGroups = model.getTabGroups();
43
43
  // Track which group IDs are still active
@@ -52,6 +52,7 @@ export class TabGroupManager {
52
52
  if (!activeGroupIds.has(groupId)) {
53
53
  entry.chip.element.remove();
54
54
  entry.chip.dispose();
55
+ (_a = entry.dragSourcesDisposable) === null || _a === void 0 ? void 0 : _a.dispose();
55
56
  entry.disposable.dispose();
56
57
  this._chipRenderers.delete(groupId);
57
58
  }
@@ -180,12 +181,13 @@ export class TabGroupManager {
180
181
  this._pendingTransitionCleanups.delete(panelId);
181
182
  }
182
183
  updateDragAndDropState() {
184
+ var _a, _b, _c;
183
185
  const caps = resolveDndCapabilities(this._ctx.accessor.options);
184
186
  for (const entry of this._chipRenderers.values()) {
185
187
  entry.chip.element.draggable = caps.html5;
186
- entry.html5DragSource.setDisabled(!caps.html5);
187
- entry.pointerDragSource.setDisabled(!caps.pointer);
188
- entry.pointerDragSource.setTouchOnly(!caps.pointerHandlesMouse);
188
+ (_a = entry.html5DragSource) === null || _a === void 0 ? void 0 : _a.setDisabled(!caps.html5);
189
+ (_b = entry.pointerDragSource) === null || _b === void 0 ? void 0 : _b.setDisabled(!caps.pointer);
190
+ (_c = entry.pointerDragSource) === null || _c === void 0 ? void 0 : _c.setTouchOnly(!caps.pointerHandlesMouse);
189
191
  }
190
192
  }
191
193
  /**
@@ -194,19 +196,28 @@ export class TabGroupManager {
194
196
  * iframe shield are released BEFORE the cross-group move detaches
195
197
  * the chip (chip dispose is scheduled on a microtask via
196
198
  * `_scheduleTabGroupUpdate`, which is too late for callers that read
197
- * `getPanelData()` synchronously after the move). Idempotent — the
198
- * subsequent `update()` will also dispose the sources.
199
+ * `getPanelData()` synchronously after the move).
200
+ *
201
+ * A cross-group move dissolves the source chip entirely, but a
202
+ * within-group reorder keeps the same chip element — so the sources are
203
+ * cleared to `undefined` here and the subsequent `update()` re-arms them
204
+ * via `_ensureChipForGroup`. Without that re-arm the chip would fire a
205
+ * native `dragstart` (the element keeps `draggable=true`) but never set
206
+ * a transfer payload, leaving the group permanently undraggable after
207
+ * its first move. (#1410)
199
208
  */
200
209
  disposeChipDrag(tabGroupId) {
201
- var _a, _b;
210
+ var _a;
202
211
  const entry = this._chipRenderers.get(tabGroupId);
203
212
  if (!entry) {
204
213
  return;
205
214
  }
206
215
  // Optional-chained because tests may inject minimal entries
207
216
  // that skip the manager's normal `_ensureChipForGroup` flow.
208
- (_a = entry.html5DragSource) === null || _a === void 0 ? void 0 : _a.dispose();
209
- (_b = entry.pointerDragSource) === null || _b === void 0 ? void 0 : _b.dispose();
217
+ (_a = entry.dragSourcesDisposable) === null || _a === void 0 ? void 0 : _a.dispose();
218
+ entry.html5DragSource = undefined;
219
+ entry.pointerDragSource = undefined;
220
+ entry.dragSourcesDisposable = undefined;
210
221
  }
211
222
  /** Cloned chip rect used as the pointer follow-finger ghost. */
212
223
  _buildChipGhostElement(chipEl) {
@@ -219,7 +230,7 @@ export class TabGroupManager {
219
230
  return clone;
220
231
  }
221
232
  disposeAll() {
222
- var _a;
233
+ var _a, _b;
223
234
  (_a = this._indicator) === null || _a === void 0 ? void 0 : _a.dispose();
224
235
  this._indicator = null;
225
236
  for (const [, cleanup] of this._pendingTransitionCleanups) {
@@ -229,12 +240,13 @@ export class TabGroupManager {
229
240
  for (const [, entry] of this._chipRenderers) {
230
241
  entry.chip.element.remove();
231
242
  entry.chip.dispose();
243
+ (_b = entry.dragSourcesDisposable) === null || _b === void 0 ? void 0 : _b.dispose();
232
244
  entry.disposable.dispose();
233
245
  }
234
246
  this._chipRenderers.clear();
235
247
  }
236
248
  _ensureIndicator() {
237
- var _a, _b;
249
+ var _a, _b, _c;
238
250
  const mode = (_b = (_a = this._ctx.accessor.options.theme) === null || _a === void 0 ? void 0 : _a.tabGroupIndicator) !== null && _b !== void 0 ? _b : 'wrap';
239
251
  const Ctor = mode === 'none' ? NoneTabGroupIndicator : WrapTabGroupIndicator;
240
252
  // Re-create if the indicator type changed (e.g. theme switch)
@@ -242,28 +254,24 @@ export class TabGroupManager {
242
254
  this._indicator.dispose();
243
255
  this._indicator = null;
244
256
  }
245
- if (!this._indicator) {
246
- this._indicator = new Ctor({
247
- tabsList: this._ctx.tabsList,
248
- getTabGroups: () => this._ctx.group.model.getTabGroups(),
249
- getActivePanelId: () => { var _a; return (_a = this._ctx.group.activePanel) === null || _a === void 0 ? void 0 : _a.id; },
250
- getTabMap: () => this._ctx.getTabMap(),
251
- getChipElement: (id) => { var _a; return (_a = this._chipRenderers.get(id)) === null || _a === void 0 ? void 0 : _a.chip.element; },
252
- getDirection: () => this._ctx.getDirection(),
253
- getHeaderPosition: () => this._ctx.group.model.headerPosition,
254
- getColorPalette: () => this._ctx.accessor.tabGroupColorPalette,
255
- });
256
- }
257
+ (_c = this._indicator) !== null && _c !== void 0 ? _c : (this._indicator = new Ctor({
258
+ tabsList: this._ctx.tabsList,
259
+ getTabGroups: () => this._ctx.group.model.getTabGroups(),
260
+ getActivePanelId: () => { var _a; return (_a = this._ctx.group.activePanel) === null || _a === void 0 ? void 0 : _a.id; },
261
+ getTabMap: () => this._ctx.getTabMap(),
262
+ getChipElement: (id) => { var _a; return (_a = this._chipRenderers.get(id)) === null || _a === void 0 ? void 0 : _a.chip.element; },
263
+ getDirection: () => this._ctx.getDirection(),
264
+ getHeaderPosition: () => this._ctx.group.model.headerPosition,
265
+ getColorPalette: () => this._ctx.accessor.tabGroupColorPalette,
266
+ }));
257
267
  }
258
- _ensureChipForGroup(tabGroup) {
259
- if (this._chipRenderers.has(tabGroup.id)) {
260
- return;
261
- }
262
- const createChip = this._ctx.accessor.options.createTabGroupChipComponent;
263
- const chip = createChip
264
- ? createChip(tabGroup)
265
- : new TabGroupChip(this._ctx.accessor.tabGroupColorPalette);
266
- chip.init({ tabGroup, api: this._ctx.accessor.api });
268
+ /**
269
+ * Create the HTML5 + pointer drag sources for a chip (and the direct
270
+ * dragend listener that clears the transfer synchronously). Extracted so
271
+ * both the initial chip build and the post-move re-arm in
272
+ * `_ensureChipForGroup` share one wiring path. (#1410)
273
+ */
274
+ _createChipDragSources(chip, tabGroup) {
267
275
  const caps = resolveDndCapabilities(this._ctx.accessor.options);
268
276
  chip.element.draggable = caps.html5;
269
277
  const panelTransfer = LocalSelectionTransfer.getInstance();
@@ -315,9 +323,12 @@ export class TabGroupManager {
315
323
  // the listener survives chip disposal in the detach-then-dragend
316
324
  // cross-group path; `once: true` auto-removes after the single
317
325
  // dragend that we care about. (#1254)
318
- chip.element.addEventListener('dragend', () => {
326
+ const onDragEndClear = () => {
319
327
  panelTransfer.clearData(PanelTransfer.prototype);
320
- }, { once: true });
328
+ };
329
+ chip.element.addEventListener('dragend', onDragEndClear, {
330
+ once: true,
331
+ });
321
332
  const pointerDragSource = pointerBackend.createDragSource(chip.element, {
322
333
  getData,
323
334
  disabled: !caps.pointer,
@@ -332,6 +343,41 @@ export class TabGroupManager {
332
343
  this._callbacks.onChipDragStart(tabGroup, chip, event);
333
344
  },
334
345
  });
346
+ return {
347
+ html5DragSource,
348
+ pointerDragSource,
349
+ disposable: {
350
+ dispose: () => {
351
+ html5DragSource.dispose();
352
+ pointerDragSource.dispose();
353
+ chip.element.removeEventListener('dragend', onDragEndClear);
354
+ },
355
+ },
356
+ };
357
+ }
358
+ _ensureChipForGroup(tabGroup) {
359
+ const existing = this._chipRenderers.get(tabGroup.id);
360
+ if (existing) {
361
+ // A committed group move tears down the chip's drag sources via
362
+ // `disposeChipDrag`, but a within-group reorder keeps the same
363
+ // chip element alive. Re-arm the sources so the group stays
364
+ // draggable; without this the chip is stuck after its first
365
+ // move — `dragstart` still fires (the element keeps
366
+ // `draggable=true`) but no transfer payload is set. (#1410)
367
+ if (!existing.html5DragSource) {
368
+ const sources = this._createChipDragSources(existing.chip, tabGroup);
369
+ existing.html5DragSource = sources.html5DragSource;
370
+ existing.pointerDragSource = sources.pointerDragSource;
371
+ existing.dragSourcesDisposable = sources.disposable;
372
+ }
373
+ return;
374
+ }
375
+ const createChip = this._ctx.accessor.options.createTabGroupChipComponent;
376
+ const chip = createChip
377
+ ? createChip(tabGroup)
378
+ : new TabGroupChip(this._ctx.accessor.tabGroupColorPalette);
379
+ chip.init({ tabGroup, api: this._ctx.accessor.api });
380
+ const dragSources = this._createChipDragSources(chip, tabGroup);
335
381
  const disposables = [
336
382
  tabGroup.onDidChange(() => {
337
383
  var _a;
@@ -345,17 +391,19 @@ export class TabGroupManager {
345
391
  tabGroup.onDidCollapseChange(() => {
346
392
  this._updateTabGroupClasses();
347
393
  }),
348
- html5DragSource,
349
- pointerDragSource,
350
394
  ];
351
395
  // Context menu: built-in TabGroupChip already aggregates right-click
352
396
  // + touch long-press into `onContextMenu`. Custom chip renderers
353
397
  // don't, so attach a long-press detector and contextmenu listener
354
398
  // directly on their element.
355
399
  const onContextMenu = (event) => {
400
+ var _a, _b;
356
401
  // A long-press on a chip should preempt the in-flight pointer
357
- // drag and open the menu instead.
358
- pointerDragSource.cancelPending();
402
+ // drag and open the menu instead. Resolve the source from the
403
+ // entry so a post-move re-armed source is cancelled, not the
404
+ // stale one captured at build time. (#1410)
405
+ (_b = (_a = this._chipRenderers
406
+ .get(tabGroup.id)) === null || _a === void 0 ? void 0 : _a.pointerDragSource) === null || _b === void 0 ? void 0 : _b.cancelPending();
359
407
  this._callbacks.onChipContextMenu(tabGroup, event);
360
408
  };
361
409
  if (chip instanceof TabGroupChip) {
@@ -388,7 +436,7 @@ export class TabGroupManager {
388
436
  return false;
389
437
  }
390
438
  const data = getPanelData();
391
- if (data && this._ctx.accessor.id === data.viewId) {
439
+ if (this._ctx.accessor.id === (data === null || data === void 0 ? void 0 : data.viewId)) {
392
440
  if (((_a = this._ctx.accessor.options.theme) === null || _a === void 0 ? void 0 : _a.tabAnimation) ===
393
441
  'smooth') {
394
442
  return false;
@@ -404,8 +452,9 @@ export class TabGroupManager {
404
452
  const disposable = new CompositeDisposable(...disposables);
405
453
  this._chipRenderers.set(tabGroup.id, {
406
454
  chip,
407
- html5DragSource,
408
- pointerDragSource,
455
+ html5DragSource: dragSources.html5DragSource,
456
+ pointerDragSource: dragSources.pointerDragSource,
457
+ dragSourcesDisposable: dragSources.disposable,
409
458
  disposable,
410
459
  dropTarget,
411
460
  });
@@ -1,4 +1,4 @@
1
- import { getPanelData, } from '../../../dnd/dataTransfer';
1
+ import { getPanelData } from '../../../dnd/dataTransfer';
2
2
  import { addClasses, isChildEntirelyVisibleWithinParent, OverflowObserver, removeClasses, toggleClass, } from '../../../dom';
3
3
  import { addDisposableListener, Emitter } from '../../../events';
4
4
  import { CompositeDisposable, Disposable, MutableDisposable, } from '../../../lifecycle';
@@ -445,12 +445,10 @@ export class Tabs extends CompositeDisposable {
445
445
  parentElement.scrollTop = running;
446
446
  }
447
447
  }
448
- else {
449
- if (running < parentElement.scrollLeft ||
450
- running + element.clientWidth >
451
- parentElement.scrollLeft + parentElement.clientWidth) {
452
- parentElement.scrollLeft = running;
453
- }
448
+ else if (running < parentElement.scrollLeft ||
449
+ running + element.clientWidth >
450
+ parentElement.scrollLeft + parentElement.clientWidth) {
451
+ parentElement.scrollLeft = running;
454
452
  }
455
453
  }
456
454
  running += isVertical
@@ -562,18 +560,13 @@ export class Tabs extends CompositeDisposable {
562
560
  });
563
561
  return;
564
562
  }
565
- switch (event.button) {
566
- case 0:
567
- if (this.group.api.location.type === 'edge') {
568
- // All tab interaction for edge groups is handled by
569
- // onTabClick to avoid race conditions with active panel state
570
- }
571
- else {
572
- if (this.group.activePanel !== panel) {
573
- this.group.model.openPanel(panel);
574
- }
575
- }
576
- break;
563
+ // Edge groups are skipped here: all their tab interaction
564
+ // is handled by onTabClick to avoid race conditions with
565
+ // active panel state.
566
+ if (event.button === 0 &&
567
+ this.group.api.location.type !== 'edge' &&
568
+ this.group.activePanel !== panel) {
569
+ this.group.model.openPanel(panel);
577
570
  }
578
571
  }), tab.onDrop((event) => {
579
572
  var _a, _b, _c, _d;
@@ -596,12 +589,12 @@ export class Tabs extends CompositeDisposable {
596
589
  targetTabGroupId: animState.targetTabGroupId,
597
590
  });
598
591
  if (((_b = this.accessor.options.theme) === null || _b === void 0 ? void 0 : _b.tabAnimation) === 'smooth') {
599
- this.runFlipAnimation(firstPositions, animState.sourceTabId, animState.sourceIndex === -1, animState.sourceIndex !== -1
600
- ? {
592
+ this.runFlipAnimation(firstPositions, animState.sourceTabId, animState.sourceIndex === -1, animState.sourceIndex === -1
593
+ ? undefined
594
+ : {
601
595
  from: Math.min(animState.sourceIndex, dropIndex),
602
596
  to: Math.max(animState.sourceIndex, dropIndex),
603
- }
604
- : undefined);
597
+ });
605
598
  }
606
599
  }
607
600
  else {
@@ -851,7 +844,7 @@ export class Tabs extends CompositeDisposable {
851
844
  return;
852
845
  }
853
846
  const data = getPanelData();
854
- const sourceIndex = data && data.groupId === this.group.id && data.panelId
847
+ const sourceIndex = (data === null || data === void 0 ? void 0 : data.groupId) === this.group.id && (data === null || data === void 0 ? void 0 : data.panelId)
855
848
  ? this._tabs.findIndex((x) => x.value.panel.id === data.panelId)
856
849
  : -1;
857
850
  const adjustedIndex = insertionIndex -
@@ -52,7 +52,7 @@ export class VoidContainer extends CompositeDisposable {
52
52
  return false;
53
53
  }
54
54
  const data = getPanelData();
55
- if (data && this.accessor.id === data.viewId) {
55
+ if (this.accessor.id === (data === null || data === void 0 ? void 0 : data.viewId)) {
56
56
  return true;
57
57
  }
58
58
  return group.model.canDisplayOverlay(event, position, 'header_space');
@@ -24,13 +24,13 @@ export function resolveDndCapabilities(options) {
24
24
  }
25
25
  }
26
26
  function isCoarsePrimaryInput() {
27
- if (typeof window === 'undefined' || !window.matchMedia) {
27
+ if (globalThis.window === undefined || !globalThis.matchMedia) {
28
28
  return false;
29
29
  }
30
30
  // Coarse pointer without any fine pointer = phone-class device. A laptop
31
31
  // touchscreen reports both, and we want HTML5 to remain available there
32
32
  // because a real mouse is also plugged in.
33
- const coarse = window.matchMedia('(pointer: coarse)').matches;
34
- const fine = window.matchMedia('(pointer: fine)').matches;
33
+ const coarse = globalThis.matchMedia('(pointer: coarse)').matches;
34
+ const fine = globalThis.matchMedia('(pointer: fine)').matches;
35
35
  return coarse && !fine;
36
36
  }