dockview-core 6.2.2 → 6.4.0

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 (145) hide show
  1. package/README.md +1 -0
  2. package/dist/cjs/api/dockviewGroupPanelApi.d.ts +10 -1
  3. package/dist/cjs/api/dockviewGroupPanelApi.js +16 -0
  4. package/dist/cjs/dnd/backend.d.ts +70 -0
  5. package/dist/cjs/dnd/backend.js +171 -0
  6. package/dist/cjs/dnd/dropOverlay.d.ts +20 -0
  7. package/dist/cjs/dnd/dropOverlay.js +197 -0
  8. package/dist/cjs/dnd/droptarget.d.ts +20 -6
  9. package/dist/cjs/dnd/droptarget.js +14 -208
  10. package/dist/cjs/dnd/pointer/index.d.ts +11 -0
  11. package/dist/cjs/dnd/pointer/index.js +13 -0
  12. package/dist/cjs/dnd/pointer/longPress.d.ts +32 -0
  13. package/dist/cjs/dnd/pointer/longPress.js +151 -0
  14. package/dist/cjs/dnd/pointer/pointerDragController.d.ts +60 -0
  15. package/dist/cjs/dnd/pointer/pointerDragController.js +241 -0
  16. package/dist/cjs/dnd/pointer/pointerDragSource.d.ts +61 -0
  17. package/dist/cjs/dnd/pointer/pointerDragSource.js +195 -0
  18. package/dist/cjs/dnd/pointer/pointerDropTarget.d.ts +39 -0
  19. package/dist/cjs/dnd/pointer/pointerDropTarget.js +198 -0
  20. package/dist/cjs/dnd/pointer/pointerGhost.d.ts +30 -0
  21. package/dist/cjs/dnd/pointer/pointerGhost.js +44 -0
  22. package/dist/cjs/dnd/pointer/types.d.ts +16 -0
  23. package/dist/cjs/dnd/pointer/types.js +2 -0
  24. package/dist/cjs/dockview/components/panel/content.d.ts +3 -1
  25. package/dist/cjs/dockview/components/panel/content.js +33 -16
  26. package/dist/cjs/dockview/components/popupService.js +34 -0
  27. package/dist/cjs/dockview/components/tab/tab.d.ts +11 -3
  28. package/dist/cjs/dockview/components/tab/tab.js +151 -117
  29. package/dist/cjs/dockview/components/titlebar/tabGroupChip.d.ts +9 -2
  30. package/dist/cjs/dockview/components/titlebar/tabGroupChip.js +15 -6
  31. package/dist/cjs/dockview/components/titlebar/tabGroupIndicator.js +2 -2
  32. package/dist/cjs/dockview/components/titlebar/tabGroups.d.ts +33 -5
  33. package/dist/cjs/dockview/components/titlebar/tabGroups.js +231 -40
  34. package/dist/cjs/dockview/components/titlebar/tabs.d.ts +38 -1
  35. package/dist/cjs/dockview/components/titlebar/tabs.js +381 -253
  36. package/dist/cjs/dockview/components/titlebar/tabsContainer.d.ts +5 -3
  37. package/dist/cjs/dockview/components/titlebar/voidContainer.d.ts +6 -2
  38. package/dist/cjs/dockview/components/titlebar/voidContainer.js +190 -22
  39. package/dist/cjs/dockview/contextMenu.js +19 -4
  40. package/dist/cjs/dockview/dndCapabilities.d.ts +19 -0
  41. package/dist/cjs/dockview/dndCapabilities.js +39 -0
  42. package/dist/cjs/dockview/dockviewComponent.d.ts +2 -0
  43. package/dist/cjs/dockview/dockviewComponent.js +241 -158
  44. package/dist/cjs/dockview/dockviewGroupPanelModel.d.ts +10 -5
  45. package/dist/cjs/dockview/dockviewGroupPanelModel.js +34 -11
  46. package/dist/cjs/dockview/dockviewPanel.js +5 -0
  47. package/dist/cjs/dockview/dockviewPanelModel.d.ts +2 -0
  48. package/dist/cjs/dockview/dockviewPanelModel.js +8 -0
  49. package/dist/cjs/dockview/events.d.ts +2 -1
  50. package/dist/cjs/dockview/events.js +1 -0
  51. package/dist/cjs/dockview/framework.d.ts +8 -0
  52. package/dist/cjs/dockview/options.d.ts +31 -5
  53. package/dist/cjs/dockview/options.js +3 -0
  54. package/dist/cjs/dom.d.ts +5 -1
  55. package/dist/cjs/dom.js +21 -5
  56. package/dist/cjs/index.d.ts +1 -1
  57. package/dist/cjs/overlay/overlay.d.ts +12 -0
  58. package/dist/cjs/overlay/overlay.js +84 -16
  59. package/dist/cjs/paneview/draggablePaneviewPanel.d.ts +3 -1
  60. package/dist/cjs/paneview/draggablePaneviewPanel.js +27 -26
  61. package/dist/cjs/paneview/options.d.ts +4 -3
  62. package/dist/cjs/popoutWindow.d.ts +2 -0
  63. package/dist/cjs/popoutWindow.js +3 -1
  64. package/dist/dockview-core.js +2431 -937
  65. package/dist/dockview-core.min.js +2 -2
  66. package/dist/dockview-core.min.js.map +1 -1
  67. package/dist/dockview-core.min.noStyle.js +2 -2
  68. package/dist/dockview-core.min.noStyle.js.map +1 -1
  69. package/dist/dockview-core.noStyle.js +2430 -936
  70. package/dist/esm/api/dockviewGroupPanelApi.d.ts +10 -1
  71. package/dist/esm/api/dockviewGroupPanelApi.js +12 -0
  72. package/dist/esm/dnd/backend.d.ts +70 -0
  73. package/dist/esm/dnd/backend.js +148 -0
  74. package/dist/esm/dnd/dropOverlay.d.ts +20 -0
  75. package/dist/esm/dnd/dropOverlay.js +192 -0
  76. package/dist/esm/dnd/droptarget.d.ts +20 -6
  77. package/dist/esm/dnd/droptarget.js +16 -210
  78. package/dist/esm/dnd/pointer/index.d.ts +11 -0
  79. package/dist/esm/dnd/pointer/index.js +5 -0
  80. package/dist/esm/dnd/pointer/longPress.d.ts +32 -0
  81. package/dist/esm/dnd/pointer/longPress.js +127 -0
  82. package/dist/esm/dnd/pointer/pointerDragController.d.ts +60 -0
  83. package/dist/esm/dnd/pointer/pointerDragController.js +191 -0
  84. package/dist/esm/dnd/pointer/pointerDragSource.d.ts +61 -0
  85. package/dist/esm/dnd/pointer/pointerDragSource.js +171 -0
  86. package/dist/esm/dnd/pointer/pointerDropTarget.d.ts +39 -0
  87. package/dist/esm/dnd/pointer/pointerDropTarget.js +168 -0
  88. package/dist/esm/dnd/pointer/pointerGhost.d.ts +30 -0
  89. package/dist/esm/dnd/pointer/pointerGhost.js +39 -0
  90. package/dist/esm/dnd/pointer/types.d.ts +16 -0
  91. package/dist/esm/dnd/pointer/types.js +1 -0
  92. package/dist/esm/dockview/components/panel/content.d.ts +3 -1
  93. package/dist/esm/dockview/components/panel/content.js +33 -16
  94. package/dist/esm/dockview/components/popupService.js +34 -0
  95. package/dist/esm/dockview/components/tab/tab.d.ts +11 -3
  96. package/dist/esm/dockview/components/tab/tab.js +139 -114
  97. package/dist/esm/dockview/components/titlebar/tabGroupChip.d.ts +9 -2
  98. package/dist/esm/dockview/components/titlebar/tabGroupChip.js +15 -6
  99. package/dist/esm/dockview/components/titlebar/tabGroupIndicator.js +2 -2
  100. package/dist/esm/dockview/components/titlebar/tabGroups.d.ts +33 -5
  101. package/dist/esm/dockview/components/titlebar/tabGroups.js +177 -12
  102. package/dist/esm/dockview/components/titlebar/tabs.d.ts +38 -1
  103. package/dist/esm/dockview/components/titlebar/tabs.js +360 -229
  104. package/dist/esm/dockview/components/titlebar/tabsContainer.d.ts +5 -3
  105. package/dist/esm/dockview/components/titlebar/voidContainer.d.ts +6 -2
  106. package/dist/esm/dockview/components/titlebar/voidContainer.js +180 -26
  107. package/dist/esm/dockview/contextMenu.js +19 -4
  108. package/dist/esm/dockview/dndCapabilities.d.ts +19 -0
  109. package/dist/esm/dockview/dndCapabilities.js +36 -0
  110. package/dist/esm/dockview/dockviewComponent.d.ts +2 -0
  111. package/dist/esm/dockview/dockviewComponent.js +104 -41
  112. package/dist/esm/dockview/dockviewGroupPanelModel.d.ts +10 -5
  113. package/dist/esm/dockview/dockviewGroupPanelModel.js +33 -11
  114. package/dist/esm/dockview/dockviewPanel.js +5 -0
  115. package/dist/esm/dockview/dockviewPanelModel.d.ts +2 -0
  116. package/dist/esm/dockview/dockviewPanelModel.js +8 -0
  117. package/dist/esm/dockview/events.d.ts +2 -1
  118. package/dist/esm/dockview/events.js +1 -0
  119. package/dist/esm/dockview/framework.d.ts +8 -0
  120. package/dist/esm/dockview/options.d.ts +31 -5
  121. package/dist/esm/dockview/options.js +3 -0
  122. package/dist/esm/dom.d.ts +5 -1
  123. package/dist/esm/dom.js +20 -5
  124. package/dist/esm/index.d.ts +1 -1
  125. package/dist/esm/overlay/overlay.d.ts +12 -0
  126. package/dist/esm/overlay/overlay.js +85 -17
  127. package/dist/esm/paneview/draggablePaneviewPanel.d.ts +3 -1
  128. package/dist/esm/paneview/draggablePaneviewPanel.js +26 -20
  129. package/dist/esm/paneview/options.d.ts +4 -3
  130. package/dist/esm/popoutWindow.d.ts +2 -0
  131. package/dist/esm/popoutWindow.js +3 -1
  132. package/dist/package/main.cjs.js +2430 -936
  133. package/dist/package/main.cjs.min.js +2 -2
  134. package/dist/package/main.esm.min.mjs +2 -2
  135. package/dist/package/main.esm.mjs +2430 -936
  136. package/dist/styles/dockview.css +117 -1
  137. package/package.json +3 -1
  138. package/dist/cjs/dnd/abstractDragHandler.d.ts +0 -14
  139. package/dist/cjs/dnd/abstractDragHandler.js +0 -86
  140. package/dist/cjs/dnd/groupDragHandler.d.ts +0 -12
  141. package/dist/cjs/dnd/groupDragHandler.js +0 -82
  142. package/dist/esm/dnd/abstractDragHandler.d.ts +0 -14
  143. package/dist/esm/dnd/abstractDragHandler.js +0 -63
  144. package/dist/esm/dnd/groupDragHandler.d.ts +0 -12
  145. package/dist/esm/dnd/groupDragHandler.js +0 -59
@@ -57,6 +57,7 @@ var dom_1 = require("../../../dom");
57
57
  var events_1 = require("../../../events");
58
58
  var lifecycle_1 = require("../../../lifecycle");
59
59
  var scrollbar_1 = require("../../../scrollbar");
60
+ var pointerDragController_1 = require("../../../dnd/pointer/pointerDragController");
60
61
  var events_2 = require("../../events");
61
62
  var tab_1 = require("../tab/tab");
62
63
  var tabGroups_1 = require("./tabGroups");
@@ -80,7 +81,7 @@ var Tabs = /** @class */ (function (_super) {
80
81
  _this._voidContainer = null;
81
82
  _this._voidContainerListeners = null;
82
83
  _this._extendedDropZone = null;
83
- _this._chipDragCleanup = null;
84
+ _this._pointerInsideTabsList = false;
84
85
  _this._onTabDragStart = new events_1.Emitter();
85
86
  _this.onTabDragStart = _this._onTabDragStart.event;
86
87
  _this._onDrop = new events_1.Emitter();
@@ -115,13 +116,40 @@ var Tabs = /** @class */ (function (_super) {
115
116
  onChipDragStart: function (tabGroup, chip, event) {
116
117
  _this._handleChipDragStart(tabGroup, chip, event);
117
118
  },
119
+ onChipDragEnd: function () {
120
+ // HTML5 chip dragend (incl. cancels). The Html5DragSource
121
+ // owns the listener on the chip element, so this fires
122
+ // even if the chip was detached cross-group — the
123
+ // element keeps its listeners until the source is
124
+ // disposed. resetDragAnimation is a no-op after a
125
+ // successful drop (anim state already null) thanks to
126
+ // the gating inside it.
127
+ _this.resetDragAnimation();
128
+ },
129
+ onChipDrop: function (tabGroup, event) {
130
+ _this._handleChipDrop(tabGroup, event);
131
+ },
118
132
  });
119
133
  _this.addDisposables(_this._onOverflowTabsChange, _this._observerDisposable, _this._onWillShowOverlay, _this._onDrop, _this._onTabDragStart, {
120
134
  dispose: function () {
121
135
  var _a;
122
136
  (_a = _this._flipTransitionCleanup) === null || _a === void 0 ? void 0 : _a.call(_this);
123
137
  },
124
- }, (0, events_1.addDisposableListener)(_this.element, 'pointerdown', function (event) {
138
+ },
139
+ // Pointer-side cleanup: when any pointer drag ends, tear
140
+ // down smooth-reorder anim state the dragover bridge may
141
+ // have installed. The chip's pointer drag source handles
142
+ // its own transfer payload + iframe-shield cleanup.
143
+ pointerDragController_1.PointerDragController.getInstance().onDragEnd(function () {
144
+ _this._pointerInsideTabsList = false;
145
+ _this.resetDragAnimation();
146
+ }),
147
+ // Pointer-event mirror of the HTML5 dragover / dragleave handlers
148
+ // below. Drives smooth-reorder for `dndStrategy: 'pointer'` and
149
+ // for touch drags in `'auto'`.
150
+ pointerDragController_1.PointerDragController.getInstance().onDragMove(function (e) {
151
+ _this._handlePointerDragMove(e.clientX, e.clientY);
152
+ }), (0, events_1.addDisposableListener)(_this.element, 'pointerdown', function (event) {
125
153
  if (event.defaultPrevented) {
126
154
  return;
127
155
  }
@@ -129,135 +157,60 @@ var Tabs = /** @class */ (function (_super) {
129
157
  if (isLeftClick) {
130
158
  _this.accessor.doSetGroupActive(_this.group);
131
159
  }
132
- }), (0, events_1.addDisposableListener)(_this._tabsList, 'dragover', function (event) {
133
- var _a, _b, _c, _d;
134
- if (_this.accessor.options.disableDnd) {
160
+ }),
161
+ // Trackpad / wheel forwarding. The strip scrolls along its own
162
+ // axis (x for horizontal headers, y for vertical), so deltaY
163
+ // from a plain mouse wheel maps onto the strip's axis too —
164
+ // this gives the VS Code-style "scroll over tab bar to page
165
+ // through tabs" feel. We only consume the event when the strip
166
+ // is actually overflowing in the direction the user wheeled in,
167
+ // so a wheel at the edge of a non-overflowing strip still
168
+ // bubbles up and scrolls the page. `{ passive: false }` is
169
+ // required because we call preventDefault().
170
+ (0, events_1.addDisposableListener)(_this._tabsList, 'wheel', function (event) {
171
+ var isVertical = _this._direction === 'vertical';
172
+ var primary = isVertical
173
+ ? event.deltaY || event.deltaX
174
+ : event.deltaX || event.deltaY;
175
+ if (primary === 0) {
135
176
  return;
136
177
  }
137
- // If _animState exists but belongs to a different
138
- // drag (stale from a previous operation), replace it
139
- // so the current drag is handled correctly.
140
- if (_this._animState) {
141
- var data = (0, dataTransfer_1.getPanelData)();
142
- if ((data === null || data === void 0 ? void 0 : data.tabGroupId) &&
143
- data.groupId !== _this.group.id &&
144
- _this._animState.sourceTabGroupId !== data.tabGroupId) {
145
- _this._animState = null;
146
- }
147
- }
148
- if (!_this._animState) {
149
- var data_1 = (0, dataTransfer_1.getPanelData)();
150
- // In default animation mode, individual tab drops
151
- // are handled by per-tab Droptargets. But tab group
152
- // chip drags still need tab-list-level handling so
153
- // that drops on gaps / void space work.
154
- if (((_a = _this.accessor.options.theme) === null || _a === void 0 ? void 0 : _a.tabAnimation) ===
155
- 'default' &&
156
- !(data_1 === null || data_1 === void 0 ? void 0 : data_1.tabGroupId)) {
157
- return;
158
- }
159
- if (data_1 &&
160
- (data_1.panelId || data_1.tabGroupId) &&
161
- data_1.groupId !== _this.group.id) {
162
- var avgWidth = _this.getAverageTabWidth();
163
- if (data_1.tabGroupId) {
164
- // External group drag — look up the
165
- // source tab group to size the gap
166
- var sourceGroup = _this.accessor.getPanel(data_1.groupId);
167
- var sourceTg = sourceGroup === null || sourceGroup === void 0 ? void 0 : sourceGroup.model.getTabGroups().find(function (tg) { return tg.id === data_1.tabGroupId; });
168
- var panelCount = (_b = sourceTg === null || sourceTg === void 0 ? void 0 : sourceTg.panelIds.length) !== null && _b !== void 0 ? _b : 1;
169
- var groupGapWidth = avgWidth * panelCount + avgWidth;
170
- _this._animState = {
171
- sourceTabId: '',
172
- sourceIndex: -1,
173
- tabPositions: _this.snapshotTabPositions(),
174
- chipPositions: _this._tabGroupManager.snapshotChipWidths(),
175
- currentInsertionIndex: null,
176
- targetTabGroupId: null,
177
- sourceTabGroupId: data_1.tabGroupId,
178
- sourceGroupPanelIds: sourceTg
179
- ? new Set(sourceTg.panelIds)
180
- : new Set(),
181
- sourceChipWidth: avgWidth,
182
- cursorOffsetFromDragLeft: groupGapWidth / 2,
183
- sourceGapWidth: groupGapWidth,
184
- containerLeft: _this._tabsList.getBoundingClientRect()
185
- .left,
186
- };
187
- }
188
- else {
189
- _this._animState = {
190
- sourceTabId: data_1.panelId,
191
- sourceIndex: -1,
192
- tabPositions: _this.snapshotTabPositions(),
193
- chipPositions: _this._tabGroupManager.snapshotChipWidths(),
194
- currentInsertionIndex: null,
195
- targetTabGroupId: null,
196
- sourceTabGroupId: null,
197
- sourceGroupPanelIds: null,
198
- sourceChipWidth: 0,
199
- cursorOffsetFromDragLeft: avgWidth / 2,
200
- sourceGapWidth: avgWidth,
201
- containerLeft: _this._tabsList.getBoundingClientRect()
202
- .left,
203
- };
204
- }
205
- }
206
- else {
207
- return;
208
- }
209
- }
210
- event.preventDefault(); // allow drop to fire on the container
211
- // For intra-group drag (sourceIndex >= 0) the gap
212
- // animation is the sole visual indicator — clear any
213
- // stale anchor overlay that may have been set while the
214
- // cursor was over the panel content area or another zone.
215
- // External drags (sourceIndex === -1) leave the overlay
216
- // to the individual tab Droptargets so cross-group
217
- // animation is not disrupted.
218
- if (_this._animState.sourceIndex !== -1) {
219
- (_d = (_c = _this.group.model.dropTargetContainer) === null || _c === void 0 ? void 0 : _c.model) === null || _d === void 0 ? void 0 : _d.clear();
220
- }
221
- _this.handleDragOver(event);
222
- }, true), (0, events_1.addDisposableListener)(_this._tabsList, 'dragleave', function (event) {
223
- var _a, _b, _c;
224
- if (!_this._animState) {
178
+ var max = isVertical
179
+ ? _this._tabsList.scrollHeight -
180
+ _this._tabsList.clientHeight
181
+ : _this._tabsList.scrollWidth -
182
+ _this._tabsList.clientWidth;
183
+ if (max <= 0) {
225
184
  return;
226
185
  }
227
- var related = event.relatedTarget;
228
- // Ignore moves between children of the tabs list
229
- if (related && _this._tabsList.contains(related)) {
186
+ var current = isVertical
187
+ ? _this._tabsList.scrollTop
188
+ : _this._tabsList.scrollLeft;
189
+ // At the edge in the wheel direction: let the page
190
+ // scroll instead of trapping the gesture.
191
+ if ((primary < 0 && current <= 0) ||
192
+ (primary > 0 && current >= max)) {
230
193
  return;
231
194
  }
232
- // If moving into the broader drop zone (e.g. void container,
233
- // left actions), keep _animState alive so the external
234
- // dragover listeners can continue the gap animation.
235
- if (related && ((_a = _this._extendedDropZone) === null || _a === void 0 ? void 0 : _a.contains(related))) {
236
- _this.resetTabTransforms();
237
- _this._animState.currentInsertionIndex = null;
238
- return;
195
+ event.preventDefault();
196
+ // Custom-scrollbar mode wraps the tabs list and installs
197
+ // its own wheel listener that rewrites scrollLeft from a
198
+ // deltaY-only tracker. Without stopPropagation that
199
+ // handler would clobber our deltaX-aware update.
200
+ event.stopPropagation();
201
+ if (isVertical) {
202
+ _this._tabsList.scrollTop = current + primary;
239
203
  }
240
- // When leaving toward the void container (empty header space
241
- // to the right), keep the animation state so the drop can
242
- // still land at the end position.
243
- var rt = event.relatedTarget;
244
- var isVoid = _this._voidContainer &&
245
- rt &&
246
- (rt === _this._voidContainer ||
247
- _this._voidContainer.contains(rt));
248
- if (isVoid) {
249
- return;
204
+ else {
205
+ _this._tabsList.scrollLeft = current + primary;
250
206
  }
251
- _this.resetTabTransforms();
252
- if (_this._animState) {
253
- if (_this._animState.sourceIndex === -1) {
254
- (_c = (_b = _this.group.model.dropTargetContainer) === null || _b === void 0 ? void 0 : _b.model) === null || _c === void 0 ? void 0 : _c.clear();
255
- _this._animState = null;
256
- }
257
- else {
258
- _this._animState.currentInsertionIndex = null;
259
- }
207
+ }, { passive: false }), (0, events_1.addDisposableListener)(_this._tabsList, 'dragover', function (event) {
208
+ if (_this._processDragOver(event.clientX)) {
209
+ // Allow `drop` to fire on the tabs list container.
210
+ event.preventDefault();
260
211
  }
212
+ }, true), (0, events_1.addDisposableListener)(_this._tabsList, 'dragleave', function (event) {
213
+ _this._processDragLeave(event.relatedTarget);
261
214
  }, true), (0, events_1.addDisposableListener)(_this._tabsList, 'dragend', function () {
262
215
  _this.resetDragAnimation();
263
216
  }), (0, events_1.addDisposableListener)(_this._tabsList, 'drop', function (event) {
@@ -472,6 +425,7 @@ var Tabs = /** @class */ (function (_super) {
472
425
  }
473
426
  finally { if (e_2) throw e_2.error; }
474
427
  }
428
+ this._tabGroupManager.updateDirection();
475
429
  },
476
430
  enumerable: false,
477
431
  configurable: true
@@ -541,6 +495,9 @@ var Tabs = /** @class */ (function (_super) {
541
495
  var disposable = new lifecycle_1.CompositeDisposable(tab.onDragStart(function (event) {
542
496
  var _a;
543
497
  _this._onTabDragStart.fire({ nativeEvent: event, panel: panel });
498
+ // Both HTML5 and pointer drags initialize _animState. Cleanup
499
+ // is wired in both paths: HTML5 via dragend/drop on _tabsList,
500
+ // pointer via PointerDragController.onDragEnd subscriptions.
544
501
  if (((_a = _this.accessor.options.theme) === null || _a === void 0 ? void 0 : _a.tabAnimation) === 'smooth') {
545
502
  var tabWidth = tab.element.getBoundingClientRect().width;
546
503
  var sourceIndex_1 = _this._tabs.findIndex(function (x) { return x.value === tab; });
@@ -677,9 +634,9 @@ var Tabs = /** @class */ (function (_super) {
677
634
  var insertionIndex = event.position === afterPosition
678
635
  ? tabIndex + 1
679
636
  : tabIndex;
680
- var data_2 = (0, dataTransfer_1.getPanelData)();
681
- var sourceIndex = data_2
682
- ? _this._tabs.findIndex(function (x) { return x.value.panel.id === data_2.panelId; })
637
+ var data_1 = (0, dataTransfer_1.getPanelData)();
638
+ var sourceIndex = data_1
639
+ ? _this._tabs.findIndex(function (x) { return x.value.panel.id === data_1.panelId; })
683
640
  : -1;
684
641
  var adjustedIndex = insertionIndex -
685
642
  (sourceIndex !== -1 && sourceIndex < insertionIndex
@@ -837,6 +794,7 @@ var Tabs = /** @class */ (function (_super) {
837
794
  }
838
795
  finally { if (e_6) throw e_6.error; }
839
796
  }
797
+ this._tabGroupManager.updateDragAndDropState();
840
798
  };
841
799
  /**
842
800
  * Synchronize chip elements and CSS classes for all tab groups
@@ -848,6 +806,13 @@ var Tabs = /** @class */ (function (_super) {
848
806
  Tabs.prototype.refreshTabGroupAccent = function () {
849
807
  this._tabGroupManager.refreshAccents();
850
808
  };
809
+ /**
810
+ * Tabs-list-specific side effects of a chip drag start. The chip's
811
+ * drag sources (constructed by `TabGroupManager`) own the transfer
812
+ * payload, iframe shielding, dataTransfer setup, and the HTML5 drag
813
+ * image. This method just sets up the smooth-reorder anim state and
814
+ * collapses the source-group tabs in the tabs list.
815
+ */
851
816
  Tabs.prototype._handleChipDragStart = function (tabGroup, chip, event) {
852
817
  var e_7, _a;
853
818
  var _this = this;
@@ -890,110 +855,100 @@ var Tabs = /** @class */ (function (_super) {
890
855
  sourceGapWidth: groupGapWidth,
891
856
  containerLeft: this._tabsList.getBoundingClientRect().left,
892
857
  };
893
- // Set LocalSelectionTransfer so drop targets recognise this as
894
- // an internal dockview drag. panelId is null (group-level),
895
- // tabGroupId identifies which tab group is being dragged.
896
- var panelTransfer = dataTransfer_1.LocalSelectionTransfer.getInstance();
897
- panelTransfer.setData([
898
- new dataTransfer_1.PanelTransfer(this.accessor.id, this.group.id, null, tabGroup.id),
899
- ], dataTransfer_1.PanelTransfer.prototype);
900
- var iframes = (0, dom_1.disableIframePointEvents)();
901
- // The dragend listener on `_tabsList` is unreachable for chip
902
- // drags because cross-group drops detach the chip from the DOM
903
- // before dragend fires (the source tab group becomes empty, so
904
- // `_positionChipForGroup` removes the chip element). Without
905
- // bubbling, the tabsList listener never runs and `_animState`,
906
- // `_chipDragCleanup`, and the dragging CSS classes leak. Listen
907
- // directly on the chip element so cleanup happens regardless of
908
- // whether it's still attached. (Issue #1254.)
909
- var chipElement = chip.element;
910
- var onChipDragEnd = function () {
911
- chipElement.removeEventListener('dragend', onChipDragEnd);
912
- _this.resetDragAnimation();
913
- };
914
- chipElement.addEventListener('dragend', onChipDragEnd);
915
- this._chipDragCleanup = {
916
- dispose: function () {
917
- chipElement.removeEventListener('dragend', onChipDragEnd);
918
- panelTransfer.clearData(dataTransfer_1.PanelTransfer.prototype);
919
- iframes.release();
920
- },
921
- };
922
- if (event.dataTransfer) {
923
- event.dataTransfer.effectAllowed = 'move';
924
- if (event.dataTransfer.items.length === 0) {
925
- event.dataTransfer.setData('text/plain', '');
926
- }
927
- }
928
- if (((_b = this.accessor.options.theme) === null || _b === void 0 ? void 0 : _b.tabAnimation) === 'smooth') {
929
- // Collapse group tabs + chip after the browser
930
- // captures the drag image, then open the gap at the
931
- // source position — all instant (no transitions).
932
- var groupPanelIds_1 = new Set(tabGroup.panelIds);
933
- this._pendingCollapse = true;
934
- requestAnimationFrame(function () {
935
- var e_8, _a, e_9, _b;
936
- var _c;
937
- var _d;
938
- _this._pendingCollapse = false;
939
- if (!_this._animState) {
940
- return;
941
- }
942
- try {
943
- // Collapse all group tabs instantly
944
- for (var _e = __values(_this._tabs), _f = _e.next(); !_f.done; _f = _e.next()) {
945
- var t = _f.value;
946
- if (groupPanelIds_1.has(t.value.panel.id)) {
947
- t.value.element.style.transition = 'none';
948
- (0, dom_1.toggleClass)(t.value.element, 'dv-tab--dragging', true);
949
- }
950
- }
951
- }
952
- catch (e_8_1) { e_8 = { error: e_8_1 }; }
953
- finally {
954
- try {
955
- if (_f && !_f.done && (_a = _e.return)) _a.call(_e);
858
+ if (((_b = this.accessor.options.theme) === null || _b === void 0 ? void 0 : _b.tabAnimation) !== 'smooth') {
859
+ return;
860
+ }
861
+ // Collapse group tabs + chip after the browser captures the drag
862
+ // image, then open the gap at the source position — all instant
863
+ // (no transitions).
864
+ var groupPanelIds = new Set(tabGroup.panelIds);
865
+ this._pendingCollapse = true;
866
+ requestAnimationFrame(function () {
867
+ var e_8, _a, e_9, _b;
868
+ var _c;
869
+ var _d;
870
+ _this._pendingCollapse = false;
871
+ if (!_this._animState) {
872
+ return;
873
+ }
874
+ try {
875
+ // Collapse all group tabs instantly
876
+ for (var _e = __values(_this._tabs), _f = _e.next(); !_f.done; _f = _e.next()) {
877
+ var t = _f.value;
878
+ if (groupPanelIds.has(t.value.panel.id)) {
879
+ t.value.element.style.transition = 'none';
880
+ (0, dom_1.toggleClass)(t.value.element, 'dv-tab--dragging', true);
956
881
  }
957
- finally { if (e_8) throw e_8.error; }
958
- }
959
- // Collapse the group chip instantly
960
- var chipEntry = _this._tabGroupManager.chipRenderers.get(tabGroup.id);
961
- if (chipEntry) {
962
- chipEntry.chip.element.style.transition = 'none';
963
- (0, dom_1.toggleClass)(chipEntry.chip.element, 'dv-tab-group-chip--dragging', true);
964
- }
965
- // Single reflow for the entire batch
966
- void _this._tabsList.offsetHeight;
967
- var underline = _this._tabGroupManager.groupUnderlines.get(tabGroup.id);
968
- if (underline) {
969
- underline.style.display = 'none';
970
882
  }
971
- (_c = (_d = _this._animState).currentInsertionIndex) !== null && _c !== void 0 ? _c : (_d.currentInsertionIndex = firstIdx);
972
- // Apply gap with transitions disabled
973
- _this.applyDragOverTransforms(true);
883
+ }
884
+ catch (e_8_1) { e_8 = { error: e_8_1 }; }
885
+ finally {
974
886
  try {
975
- // Re-enable transitions for subsequent moves
976
- for (var _g = __values(_this._tabs), _h = _g.next(); !_h.done; _h = _g.next()) {
977
- var t = _h.value;
978
- if (groupPanelIds_1.has(t.value.panel.id)) {
979
- t.value.element.style.removeProperty('transition');
980
- }
981
- }
887
+ if (_f && !_f.done && (_a = _e.return)) _a.call(_e);
982
888
  }
983
- catch (e_9_1) { e_9 = { error: e_9_1 }; }
984
- finally {
985
- try {
986
- if (_h && !_h.done && (_b = _g.return)) _b.call(_g);
889
+ finally { if (e_8) throw e_8.error; }
890
+ }
891
+ // Collapse the group chip instantly
892
+ var chipEntry = _this._tabGroupManager.chipRenderers.get(tabGroup.id);
893
+ if (chipEntry) {
894
+ chipEntry.chip.element.style.transition = 'none';
895
+ (0, dom_1.toggleClass)(chipEntry.chip.element, 'dv-tab-group-chip--dragging', true);
896
+ }
897
+ // Single reflow for the entire batch
898
+ void _this._tabsList.offsetHeight;
899
+ var underline = _this._tabGroupManager.groupUnderlines.get(tabGroup.id);
900
+ if (underline) {
901
+ underline.style.display = 'none';
902
+ }
903
+ (_c = (_d = _this._animState).currentInsertionIndex) !== null && _c !== void 0 ? _c : (_d.currentInsertionIndex = firstIdx);
904
+ _this.applyDragOverTransforms(true);
905
+ try {
906
+ for (var _g = __values(_this._tabs), _h = _g.next(); !_h.done; _h = _g.next()) {
907
+ var t = _h.value;
908
+ if (groupPanelIds.has(t.value.panel.id)) {
909
+ t.value.element.style.removeProperty('transition');
987
910
  }
988
- finally { if (e_9) throw e_9.error; }
989
911
  }
990
- if (chipEntry) {
991
- chipEntry.chip.element.style.removeProperty('transition');
912
+ }
913
+ catch (e_9_1) { e_9 = { error: e_9_1 }; }
914
+ finally {
915
+ try {
916
+ if (_h && !_h.done && (_b = _g.return)) _b.call(_g);
992
917
  }
993
- });
918
+ finally { if (e_9) throw e_9.error; }
919
+ }
920
+ if (chipEntry) {
921
+ chipEntry.chip.element.style.removeProperty('transition');
922
+ }
923
+ });
924
+ };
925
+ /**
926
+ * A drop on a tab group chip means "insert before this group". Resolve to
927
+ * the index of the group's first tab, adjusting for same-group removal
928
+ * (when the source tab is currently to the left of the target slot, its
929
+ * removal shifts the insertion index down by one). Always clears
930
+ * `targetTabGroupId` so the dropped tab lands outside the group.
931
+ */
932
+ Tabs.prototype._handleChipDrop = function (tabGroup, event) {
933
+ var firstPanelId = tabGroup.panelIds[0];
934
+ if (!firstPanelId) {
935
+ return;
994
936
  }
995
- // Build a composite drag image showing chip + group tabs
996
- this._tabGroupManager.setGroupDragImage(event, tabGroup, chip.element);
937
+ var insertionIndex = this._tabs.findIndex(function (x) { return x.value.panel.id === firstPanelId; });
938
+ if (insertionIndex === -1) {
939
+ return;
940
+ }
941
+ var data = (0, dataTransfer_1.getPanelData)();
942
+ var sourceIndex = data && data.groupId === this.group.id && data.panelId
943
+ ? this._tabs.findIndex(function (x) { return x.value.panel.id === data.panelId; })
944
+ : -1;
945
+ var adjustedIndex = insertionIndex -
946
+ (sourceIndex !== -1 && sourceIndex < insertionIndex ? 1 : 0);
947
+ this._onDrop.fire({
948
+ event: event.nativeEvent,
949
+ index: adjustedIndex,
950
+ targetTabGroupId: null,
951
+ });
997
952
  };
998
953
  /**
999
954
  * Sets the broader container that is part of the same logical drop surface
@@ -1077,6 +1032,164 @@ var Tabs = /** @class */ (function (_super) {
1077
1032
  }
1078
1033
  return total / this._tabs.length;
1079
1034
  };
1035
+ /**
1036
+ * Pointer-event entry point. The HTML5 path enters via the per-element
1037
+ * `dragover` listener; this one hit-tests the global pointer-drag
1038
+ * position against the tabs list and routes through the same shared
1039
+ * `_processDragOver` / `_processDragLeave` helpers.
1040
+ */
1041
+ Tabs.prototype._handlePointerDragMove = function (clientX, clientY) {
1042
+ var _a;
1043
+ var sourceDoc = (_a = this._tabsList.ownerDocument) !== null && _a !== void 0 ? _a : document;
1044
+ var elAtPoint = sourceDoc.elementFromPoint(clientX, clientY);
1045
+ var inside = !!elAtPoint &&
1046
+ (this._tabsList.contains(elAtPoint) ||
1047
+ (!!this._extendedDropZone &&
1048
+ this._extendedDropZone.contains(elAtPoint)));
1049
+ if (!inside) {
1050
+ if (this._pointerInsideTabsList) {
1051
+ this._pointerInsideTabsList = false;
1052
+ this._processDragLeave(elAtPoint);
1053
+ }
1054
+ return;
1055
+ }
1056
+ this._pointerInsideTabsList = true;
1057
+ this._processDragOver(clientX);
1058
+ };
1059
+ /**
1060
+ * Shared body of the dragover entry point. Refreshes stale anim state
1061
+ * for a changed drag identity, initializes anim state for incoming
1062
+ * cross-group drags, and dispatches to the gap-following math in
1063
+ * `handleDragOver`. Returns true when this tabs list has taken
1064
+ * ownership of the drag — HTML5 callers use this to gate
1065
+ * `event.preventDefault()`.
1066
+ */
1067
+ Tabs.prototype._processDragOver = function (clientX) {
1068
+ var _a, _b, _c, _d;
1069
+ if (this.accessor.options.disableDnd) {
1070
+ return false;
1071
+ }
1072
+ // Stale-state guard: if a previous drag's anim state is still here
1073
+ // but the current drag is a different identity, drop the stale one
1074
+ // so the new drag starts from a clean slate.
1075
+ if (this._animState) {
1076
+ var data = (0, dataTransfer_1.getPanelData)();
1077
+ if ((data === null || data === void 0 ? void 0 : data.tabGroupId) &&
1078
+ data.groupId !== this.group.id &&
1079
+ this._animState.sourceTabGroupId !== data.tabGroupId) {
1080
+ this._animState = null;
1081
+ }
1082
+ }
1083
+ if (!this._animState) {
1084
+ var data_2 = (0, dataTransfer_1.getPanelData)();
1085
+ // In default animation mode, individual tab drops are handled
1086
+ // by per-tab Droptargets; only chip drags need tabs-list-level
1087
+ // handling so drops on void space still work.
1088
+ if (((_a = this.accessor.options.theme) === null || _a === void 0 ? void 0 : _a.tabAnimation) === 'default' &&
1089
+ !(data_2 === null || data_2 === void 0 ? void 0 : data_2.tabGroupId)) {
1090
+ return false;
1091
+ }
1092
+ if (data_2 &&
1093
+ (data_2.panelId || data_2.tabGroupId) &&
1094
+ data_2.groupId !== this.group.id) {
1095
+ var avgWidth = this.getAverageTabWidth();
1096
+ if (data_2.tabGroupId) {
1097
+ // External group drag — look up the source group to
1098
+ // size the gap.
1099
+ var sourceGroup = this.accessor.getPanel(data_2.groupId);
1100
+ var sourceTg = sourceGroup === null || sourceGroup === void 0 ? void 0 : sourceGroup.model.getTabGroups().find(function (tg) { return tg.id === data_2.tabGroupId; });
1101
+ var panelCount = (_b = sourceTg === null || sourceTg === void 0 ? void 0 : sourceTg.panelIds.length) !== null && _b !== void 0 ? _b : 1;
1102
+ var groupGapWidth = avgWidth * panelCount + avgWidth;
1103
+ this._animState = {
1104
+ sourceTabId: '',
1105
+ sourceIndex: -1,
1106
+ tabPositions: this.snapshotTabPositions(),
1107
+ chipPositions: this._tabGroupManager.snapshotChipWidths(),
1108
+ currentInsertionIndex: null,
1109
+ targetTabGroupId: null,
1110
+ sourceTabGroupId: data_2.tabGroupId,
1111
+ sourceGroupPanelIds: sourceTg
1112
+ ? new Set(sourceTg.panelIds)
1113
+ : new Set(),
1114
+ sourceChipWidth: avgWidth,
1115
+ cursorOffsetFromDragLeft: groupGapWidth / 2,
1116
+ sourceGapWidth: groupGapWidth,
1117
+ containerLeft: this._tabsList.getBoundingClientRect().left,
1118
+ };
1119
+ }
1120
+ else {
1121
+ this._animState = {
1122
+ sourceTabId: data_2.panelId,
1123
+ sourceIndex: -1,
1124
+ tabPositions: this.snapshotTabPositions(),
1125
+ chipPositions: this._tabGroupManager.snapshotChipWidths(),
1126
+ currentInsertionIndex: null,
1127
+ targetTabGroupId: null,
1128
+ sourceTabGroupId: null,
1129
+ sourceGroupPanelIds: null,
1130
+ sourceChipWidth: 0,
1131
+ cursorOffsetFromDragLeft: avgWidth / 2,
1132
+ sourceGapWidth: avgWidth,
1133
+ containerLeft: this._tabsList.getBoundingClientRect().left,
1134
+ };
1135
+ }
1136
+ }
1137
+ else {
1138
+ return false;
1139
+ }
1140
+ }
1141
+ // For intra-group drag (sourceIndex >= 0) the gap animation is the
1142
+ // sole visual indicator — clear any stale anchor overlay that may
1143
+ // have been set while the cursor was over the panel content area or
1144
+ // another zone. External drags (sourceIndex === -1) leave the
1145
+ // overlay to the individual tab Droptargets so cross-group
1146
+ // animation is not disrupted.
1147
+ if (this._animState.sourceIndex !== -1) {
1148
+ (_d = (_c = this.group.model.dropTargetContainer) === null || _c === void 0 ? void 0 : _c.model) === null || _d === void 0 ? void 0 : _d.clear();
1149
+ }
1150
+ this.handleDragOver({ clientX: clientX });
1151
+ return true;
1152
+ };
1153
+ /**
1154
+ * Shared body of the dragleave entry point. Preserves anim state when
1155
+ * the drag moves between tabs-list children, into the extended drop
1156
+ * zone, or into the void container; tears it down otherwise.
1157
+ */
1158
+ Tabs.prototype._processDragLeave = function (related) {
1159
+ var _a, _b, _c;
1160
+ if (!this._animState) {
1161
+ return;
1162
+ }
1163
+ // Moves between children of the tabs list aren't real leaves.
1164
+ if (related && this._tabsList.contains(related)) {
1165
+ return;
1166
+ }
1167
+ // Moving into the broader drop zone (e.g. void container, left
1168
+ // actions) — keep anim state alive so external listeners can
1169
+ // continue the gap animation.
1170
+ if (related && ((_a = this._extendedDropZone) === null || _a === void 0 ? void 0 : _a.contains(related))) {
1171
+ this.resetTabTransforms();
1172
+ this._animState.currentInsertionIndex = null;
1173
+ return;
1174
+ }
1175
+ // Leaving toward the void container (empty header space to the
1176
+ // right): keep anim state so a drop can still land at the end.
1177
+ var isVoid = this._voidContainer &&
1178
+ related &&
1179
+ (related === this._voidContainer ||
1180
+ this._voidContainer.contains(related));
1181
+ if (isVoid) {
1182
+ return;
1183
+ }
1184
+ this.resetTabTransforms();
1185
+ if (this._animState.sourceIndex === -1) {
1186
+ (_c = (_b = this.group.model.dropTargetContainer) === null || _b === void 0 ? void 0 : _b.model) === null || _c === void 0 ? void 0 : _c.clear();
1187
+ this._animState = null;
1188
+ }
1189
+ else {
1190
+ this._animState.currentInsertionIndex = null;
1191
+ }
1192
+ };
1080
1193
  Tabs.prototype.handleDragOver = function (event) {
1081
1194
  var e_12, _a, e_13, _b;
1082
1195
  var _this = this;
@@ -1213,11 +1326,15 @@ var Tabs = /** @class */ (function (_super) {
1213
1326
  if (!isInsideRange && !isJustBeforeGroup) {
1214
1327
  return "continue";
1215
1328
  }
1216
- if (isGroupDrag) {
1329
+ if (isGroupDrag && isInsideRange) {
1217
1330
  // A group cannot be dropped inside another group.
1218
1331
  // Snap the insertion index to just before or just
1219
1332
  // after this group based on cursor position relative
1220
- // to the group's midpoint.
1333
+ // to the group's midpoint. Only applies when the
1334
+ // insertion would land *inside* the group — for
1335
+ // `isJustBeforeGroup`, the index is already outside
1336
+ // (immediately left of the group) and is a valid
1337
+ // drop position, so leave it untouched (issue #1264).
1221
1338
  var groupMid = (firstIdx + lastIdx + 1) / 2;
1222
1339
  if (insertionIndex < groupMid) {
1223
1340
  insertionIndex = firstIdx;
@@ -1227,6 +1344,9 @@ var Tabs = /** @class */ (function (_super) {
1227
1344
  }
1228
1345
  return "break";
1229
1346
  }
1347
+ if (isGroupDrag && isJustBeforeGroup) {
1348
+ return "break";
1349
+ }
1230
1350
  if (isJustBeforeGroup) {
1231
1351
  // Check whether only the source tab (or source group
1232
1352
  // tabs) sits between insertionIndex and firstIdx.
@@ -1592,20 +1712,23 @@ var Tabs = /** @class */ (function (_super) {
1592
1712
  * in the model, and run a FLIP animation.
1593
1713
  */
1594
1714
  Tabs.prototype._commitGroupMove = function (sourceTabGroupId, insertionIndex) {
1595
- var _a, _b, _c;
1596
- // Read transfer data BEFORE disposing cleanup — disposing
1597
- // _chipDragCleanup clears the global LocalSelectionTransfer
1598
- // singleton which getPanelData() reads from.
1715
+ var _a, _b;
1716
+ // Read transfer data first.
1599
1717
  var data = (0, dataTransfer_1.getPanelData)();
1600
- (_a = this._chipDragCleanup) === null || _a === void 0 ? void 0 : _a.dispose();
1601
- this._chipDragCleanup = null;
1718
+ // Synchronously dispose the source chip's drag sources, which
1719
+ // clears the panelTransfer payload + iframe shield. Cross-group
1720
+ // moves dissolve the source chip on a microtask, which is too
1721
+ // late: a synchronous `getPanelData()` after this method (or any
1722
+ // sibling dragover handler firing in the same tick) would
1723
+ // otherwise see stale data still referencing the old tabGroupId.
1724
+ this._tabGroupManager.disposeChipDrag(sourceTabGroupId);
1602
1725
  // Check if the tab group exists in this group (within-group reorder)
1603
1726
  // or in another group (cross-group move).
1604
1727
  var isLocal = this.group.model
1605
1728
  .getTabGroups()
1606
1729
  .some(function (tg) { return tg.id === sourceTabGroupId; });
1607
1730
  if (isLocal) {
1608
- if (((_b = this.accessor.options.theme) === null || _b === void 0 ? void 0 : _b.tabAnimation) === 'smooth') {
1731
+ if (((_a = this.accessor.options.theme) === null || _a === void 0 ? void 0 : _a.tabAnimation) === 'smooth') {
1609
1732
  this._clearGroupDragClasses(sourceTabGroupId);
1610
1733
  var firstPositions = this.snapshotTabPositions();
1611
1734
  this.resetTabTransforms();
@@ -1633,7 +1756,7 @@ var Tabs = /** @class */ (function (_super) {
1633
1756
  this.accessor.moveGroupOrPanel({
1634
1757
  from: {
1635
1758
  groupId: data.groupId,
1636
- tabGroupId: (_c = data.tabGroupId) !== null && _c !== void 0 ? _c : sourceTabGroupId,
1759
+ tabGroupId: (_b = data.tabGroupId) !== null && _b !== void 0 ? _b : sourceTabGroupId,
1637
1760
  },
1638
1761
  to: {
1639
1762
  group: this.group,
@@ -1662,32 +1785,37 @@ var Tabs = /** @class */ (function (_super) {
1662
1785
  };
1663
1786
  Tabs.prototype.resetDragAnimation = function () {
1664
1787
  var e_21, _a;
1665
- var _b, _c;
1666
1788
  this._pendingCollapse = false;
1667
- this.resetTabTransforms();
1668
- // Clear drag-collapse classes instantly (no transition)
1669
- if ((_b = this._animState) === null || _b === void 0 ? void 0 : _b.sourceTabGroupId) {
1670
- this._clearGroupDragClasses(this._animState.sourceTabGroupId);
1671
- }
1672
- else {
1673
- this._removeClassInstantlyBatch(this._tabs.map(function (t) { return t.value.element; }), 'dv-tab--dragging');
1674
- }
1675
- this._animState = null;
1676
- (_c = this._chipDragCleanup) === null || _c === void 0 ? void 0 : _c.dispose();
1677
- this._chipDragCleanup = null;
1678
- try {
1679
- // Restore any hidden underlines from group drags
1680
- for (var _d = __values(this._tabGroupManager.groupUnderlines), _e = _d.next(); !_e.done; _e = _d.next()) {
1681
- var _f = __read(_e.value, 2), el = _f[1];
1682
- el.style.removeProperty('display');
1789
+ // After a drop, `tab.onDrop` consumes _animState (sets it to null)
1790
+ // and immediately calls `runFlipAnimation`, which sets transforms
1791
+ // and queues an rAF to trigger the CSS transition. dragend fires
1792
+ // synchronously on the source element BEFORE that rAF runs — if
1793
+ // we cleared transforms here we'd clobber the in-flight FLIP, so
1794
+ // gate the cleanup on _animState still being set (i.e. drag was
1795
+ // cancelled rather than dropped).
1796
+ if (this._animState) {
1797
+ this.resetTabTransforms();
1798
+ if (this._animState.sourceTabGroupId) {
1799
+ this._clearGroupDragClasses(this._animState.sourceTabGroupId);
1683
1800
  }
1684
- }
1685
- catch (e_21_1) { e_21 = { error: e_21_1 }; }
1686
- finally {
1801
+ else {
1802
+ this._removeClassInstantlyBatch(this._tabs.map(function (t) { return t.value.element; }), 'dv-tab--dragging');
1803
+ }
1804
+ this._animState = null;
1687
1805
  try {
1688
- if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
1806
+ // Restore any hidden underlines from group drags.
1807
+ for (var _b = __values(this._tabGroupManager.groupUnderlines), _c = _b.next(); !_c.done; _c = _b.next()) {
1808
+ var _d = __read(_c.value, 2), el = _d[1];
1809
+ el.style.removeProperty('display');
1810
+ }
1811
+ }
1812
+ catch (e_21_1) { e_21 = { error: e_21_1 }; }
1813
+ finally {
1814
+ try {
1815
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1816
+ }
1817
+ finally { if (e_21) throw e_21.error; }
1689
1818
  }
1690
- finally { if (e_21) throw e_21.error; }
1691
1819
  }
1692
1820
  };
1693
1821
  Tabs.prototype.runFlipAnimation = function (firstPositions, sourceTabId, isCrossGroup, animRange) {