dock-spawn-ts 3.18.0 → 3.20.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.
@@ -16,12 +16,13 @@ export class DraggableContainer implements IDockContainer {
16
16
  dockManager: DockManager;
17
17
  topLevelElement: HTMLElement;
18
18
  containerType: ContainerType;
19
- mouseDownHandler: EventHandler;
20
- touchDownHandler: EventHandler;
21
- minimumAllowedChildNodes: number;
22
- previousMousePosition: { x: any; y: any; };
23
- mouseMoveHandler: EventHandler;
24
- mouseUpHandler: EventHandler;
19
+ mouseDownHandler: EventHandler;
20
+ touchDownHandler: EventHandler;
21
+ minimumAllowedChildNodes: number;
22
+ previousMousePosition: { x: any; y: any; };
23
+ dragOffset: Point;
24
+ mouseMoveHandler: EventHandler;
25
+ mouseUpHandler: EventHandler;
25
26
  private iframeEventHandlers: EventHandler[];
26
27
 
27
28
  constructor(dialog: Dialog, delegate: PanelContainer, topLevelElement: HTMLElement, dragHandle: HTMLElement) {
@@ -95,12 +96,13 @@ export class DraggableContainer implements IDockContainer {
95
96
  return;
96
97
  if (event.preventDefault)
97
98
  event.preventDefault();
98
-
99
- this._startDragging(event);
100
- this.previousMousePosition = { x: event.clientX, y: event.clientY };
101
- if (this.mouseMoveHandler) {
102
- this.mouseMoveHandler.cancel();
103
- delete this.mouseMoveHandler;
99
+
100
+ this._startDragging(event);
101
+ this.previousMousePosition = { x: event.clientX, y: event.clientY };
102
+ this.setDragOffset(event.clientX, event.clientY);
103
+ if (this.mouseMoveHandler) {
104
+ this.mouseMoveHandler.cancel();
105
+ delete this.mouseMoveHandler;
104
106
  }
105
107
  if (this.mouseUpHandler) {
106
108
  this.mouseUpHandler.cancel();
@@ -157,21 +159,54 @@ export class DraggableContainer implements IDockContainer {
157
159
  event.preventDefault();
158
160
 
159
161
  let currentMousePosition = new Point(event.clientX, event.clientY);
160
- if (iframeOffset)
161
- currentMousePosition = new Point(event.clientX + iframeOffset.x, event.clientY + iframeOffset.y);
162
-
163
- let dx = this.dockManager.checkXBounds(this.topLevelElement, currentMousePosition, this.previousMousePosition, false, false);
164
- let dy = this.dockManager.checkYBounds(this.topLevelElement, currentMousePosition, this.previousMousePosition, false, false);
165
- this._performDrag(dx, dy);
166
- this.previousMousePosition = currentMousePosition;
167
- }
168
-
169
- _performDrag(dx: number, dy: number) {
170
- let left = dx + Utils.getPixels(this.topLevelElement.style.left);
171
- let top = dy + Utils.getPixels(this.topLevelElement.style.top);
172
- this.topLevelElement.style.left = left + 'px';
173
- this.topLevelElement.style.top = top + 'px';
174
-
162
+ if (iframeOffset)
163
+ currentMousePosition = new Point(event.clientX + iframeOffset.x, event.clientY + iframeOffset.y);
164
+
165
+ this._performDragToMouse(currentMousePosition);
166
+ this.previousMousePosition = currentMousePosition;
167
+ }
168
+
169
+ setDragOffset(clientX: number, clientY: number) {
170
+ const rect = this.topLevelElement.getBoundingClientRect();
171
+ this.dragOffset = new Point(clientX - rect.left, clientY - rect.top);
172
+ }
173
+
174
+ _performDragToMouse(mousePosition: Point) {
175
+ const rootRect = this.dockManager.config.dialogRootElement.getBoundingClientRect();
176
+ let left = mousePosition.x - rootRect.left - this.dragOffset.x;
177
+ let top = mousePosition.y - rootRect.top - this.dragOffset.y;
178
+ const constrained = this.constrainDragPosition(left, top);
179
+ this._setPosition(constrained.x, constrained.y);
180
+ }
181
+
182
+ private constrainDragPosition(left: number, top: number) {
183
+ if (this.dockManager.config.moveOnlyWithinDockConatiner) {
184
+ const rootRect = this.dockManager.config.dialogRootElement.getBoundingClientRect();
185
+ left = Math.min(Math.max(left, 0), Math.max(0, rootRect.width - this.topLevelElement.offsetWidth));
186
+ top = Math.min(Math.max(top, 0), Math.max(0, rootRect.height - this.topLevelElement.offsetHeight));
187
+ return new Point(left, top);
188
+ }
189
+
190
+ const rootRect = this.dockManager.config.dialogRootElement.getBoundingClientRect();
191
+ const minLeft = 40 - this.topLevelElement.offsetWidth - rootRect.left;
192
+ const maxLeft = window.innerWidth - 40 - rootRect.left;
193
+ const minTop = -rootRect.top;
194
+ const maxTop = window.innerHeight - 16 - rootRect.top;
195
+ left = Math.min(Math.max(left, minLeft), maxLeft);
196
+ top = Math.min(Math.max(top, minTop), maxTop);
197
+ return new Point(left, top);
198
+ }
199
+
200
+ _performDrag(dx: number, dy: number) {
201
+ let left = dx + Utils.getPixels(this.topLevelElement.style.left);
202
+ let top = dy + Utils.getPixels(this.topLevelElement.style.top);
203
+ this._setPosition(left, top);
204
+ }
205
+
206
+ private _setPosition(left: number, top: number) {
207
+ this.topLevelElement.style.left = left + 'px';
208
+ this.topLevelElement.style.top = top + 'px';
209
+
175
210
  this.dialog.panel.setDialogPosition(left, top);
176
211
  }
177
- }
212
+ }
@@ -76,11 +76,11 @@ export class SplitterBar {
76
76
  dockManager.resumeLayout(this.nextContainer);
77
77
  }
78
78
 
79
- _performDrag(dx: number, dy: number) {
80
- let previousWidth = this.previousContainer.containerElement.clientWidth;
81
- let previousHeight = this.previousContainer.containerElement.clientHeight;
82
- let nextWidth = this.nextContainer.containerElement.clientWidth;
83
- let nextHeight = this.nextContainer.containerElement.clientHeight;
79
+ _performDrag(dx: number, dy: number) {
80
+ let previousWidth = this.getContainerWidth(this.previousContainer);
81
+ let previousHeight = this.getContainerHeight(this.previousContainer);
82
+ let nextWidth = this.getContainerWidth(this.nextContainer);
83
+ let nextHeight = this.getContainerHeight(this.nextContainer);
84
84
 
85
85
  let previousPanelSize = this.stackedVertical ? previousHeight : previousWidth;
86
86
  let nextPanelSize = this.stackedVertical ? nextHeight : nextWidth;
@@ -112,11 +112,19 @@ export class SplitterBar {
112
112
  this.nextContainer.resize(newNextPanelSize, nextHeight);
113
113
  }
114
114
  }
115
-
116
- document.dispatchEvent(this.dockSpawnResizedEvent);
117
- }
118
-
119
- _startDragging(e: IMouseOrTouchEvent) {
115
+
116
+ document.dispatchEvent(this.dockSpawnResizedEvent);
117
+ }
118
+
119
+ private getContainerWidth(container: IDockContainer) {
120
+ return container.width || container.containerElement.getBoundingClientRect().width;
121
+ }
122
+
123
+ private getContainerHeight(container: IDockContainer) {
124
+ return container.height || container.containerElement.getBoundingClientRect().height;
125
+ }
126
+
127
+ _startDragging(e: IMouseOrTouchEvent) {
120
128
  Utils.disableGlobalTextSelection(this.previousContainer.dockManager.config.dialogRootElement);
121
129
  if (this.pointerMovedHandler) {
122
130
  this.pointerMovedHandler.cancel();
@@ -155,4 +163,4 @@ export class SplitterBar {
155
163
  }
156
164
  this.iframeEventHandlers = [];
157
165
  }
158
- }
166
+ }
@@ -1,6 +1,7 @@
1
- import { SplitterBar } from "./SplitterBar.js";
2
- import { Utils } from "./Utils.js";
3
- import { IDockContainer } from "./interfaces/IDockContainer.js";
1
+ import { SplitterBar } from "./SplitterBar.js";
2
+ import { Utils } from "./Utils.js";
3
+ import { ContainerType } from "./ContainerType.js";
4
+ import { IDockContainer } from "./interfaces/IDockContainer.js";
4
5
 
5
6
  /**
6
7
  * A splitter panel manages the child containers inside it with splitter bars.
@@ -160,73 +161,76 @@ export class SplitterPanel {
160
161
  }
161
162
  }
162
163
 
163
- resize(width: number, height: number) {
164
- if (this.childContainers.length <= 1)
165
- return;
166
-
167
- this.panelElement.style.width = width + 'px';
168
- this.panelElement.style.height = height + 'px';
169
-
170
- let i;
171
-
172
- // Adjust the fixed dimension that is common to all (i.e. width, if stacked vertical; height, if stacked horizontally)
173
- for (i = 0; i < this.childContainers.length; i++) {
174
- let childContainer = this.childContainers[i];
175
- if (this.stackedVertical)
176
- childContainer.resize(width, !childContainer.height ? height : childContainer.height);
177
- else
178
- childContainer.resize(!childContainer.width ? width : childContainer.width, height);
179
-
180
- if (i < this.spiltterBars.length) {
181
- let splitBar = this.spiltterBars[i];
182
- if (this.stackedVertical)
183
- splitBar.barElement.style.width = width + 'px';
184
- else
185
- splitBar.barElement.style.height = height + 'px';
186
- }
187
- }
188
-
189
- // Adjust the varying dimension
190
- let totalChildPanelSize = 0;
191
- // Find out how much space existing child containers take up (excluding the splitter bars)
192
- this.childContainers.forEach((container) => {
193
- let size = this.stackedVertical ?
194
- container.height :
195
- container.width;
196
- totalChildPanelSize += size;
197
- });
198
-
199
- // Get the thickness of the bar
200
- let barSize = this.stackedVertical ? this.spiltterBars[0].barElement.clientHeight : this.spiltterBars[0].barElement.clientWidth;
201
-
202
- // Find out how much space existing child containers will take after being resized (excluding the splitter bars)
203
- let targetTotalChildPanelSize = this.stackedVertical ? height : width;
204
- targetTotalChildPanelSize -= barSize * this.spiltterBars.length;
205
-
206
- // Get the scale multiplier
207
- totalChildPanelSize = Math.max(totalChildPanelSize, 1);
208
- let scaleMultiplier = targetTotalChildPanelSize / totalChildPanelSize;
209
-
210
-
211
- // Update the size with this multiplier
212
- let updatedTotalChildPanelSize = 0;
213
- for (i = 0; i < this.childContainers.length; i++) {
214
- let child = this.childContainers[i];
215
- if (child.containerElement.style.display == 'none')
216
- child.containerElement.style.display = 'block';
217
- let original = this.stackedVertical ? child.containerElement.clientHeight : child.containerElement.clientWidth;
218
- let newSize = Math.floor(original * scaleMultiplier);
219
- updatedTotalChildPanelSize += newSize;
220
-
221
- // If this is the last node, add any extra pixels to fix the rounding off errors and match the requested size
222
- if (i === this.childContainers.length - 1)
223
- newSize += targetTotalChildPanelSize - updatedTotalChildPanelSize;
224
-
225
- // Set the size of the panel
226
- if (this.stackedVertical)
227
- child.resize(child.width, newSize);
228
- else
229
- child.resize(newSize, child.height);
230
- }
231
- }
232
- }
164
+ resize(width: number, height: number) {
165
+ if (this.childContainers.length <= 1)
166
+ return;
167
+
168
+ this.panelElement.style.width = width + 'px';
169
+ this.panelElement.style.height = height + 'px';
170
+
171
+ for (let i = 0; i < this.childContainers.length; i++) {
172
+ if (i < this.spiltterBars.length) {
173
+ let splitBar = this.spiltterBars[i];
174
+ if (this.stackedVertical)
175
+ splitBar.barElement.style.width = width + 'px';
176
+ else
177
+ splitBar.barElement.style.height = height + 'px';
178
+ }
179
+ }
180
+
181
+ let barSize = this.stackedVertical ? this.spiltterBars[0].barElement.clientHeight : this.spiltterBars[0].barElement.clientWidth;
182
+ let targetTotalChildPanelSize = this.stackedVertical ? height : width;
183
+ targetTotalChildPanelSize -= barSize * this.spiltterBars.length;
184
+
185
+ let childSizes = this.childContainers.map((container) => this.stackedVertical ? container.height : container.width);
186
+ let totalChildPanelSize = childSizes.reduce((sum, size) => sum + size, 0);
187
+ if (totalChildPanelSize <= 0) {
188
+ let size = targetTotalChildPanelSize / this.childContainers.length;
189
+ childSizes = this.childContainers.map(() => size);
190
+ totalChildPanelSize = targetTotalChildPanelSize;
191
+ }
192
+
193
+ let resizeIndex = this.getElasticChildIndex();
194
+ let sizeDelta = targetTotalChildPanelSize - totalChildPanelSize;
195
+ childSizes[resizeIndex] += sizeDelta;
196
+ if (childSizes[resizeIndex] < 0) {
197
+ let deficit = -childSizes[resizeIndex];
198
+ childSizes[resizeIndex] = 0;
199
+ for (let i = this.childContainers.length - 1; i >= 0 && deficit > 0; i--) {
200
+ if (i === resizeIndex)
201
+ continue;
202
+ let reduction = Math.min(childSizes[i], deficit);
203
+ childSizes[i] -= reduction;
204
+ deficit -= reduction;
205
+ }
206
+ }
207
+
208
+ childSizes = childSizes.map((size) => Math.floor(size));
209
+ childSizes[resizeIndex] += targetTotalChildPanelSize - childSizes.reduce((sum, size) => sum + size, 0);
210
+
211
+ for (let i = 0; i < this.childContainers.length; i++) {
212
+ let child = this.childContainers[i];
213
+ if (child.containerElement.style.display == 'none')
214
+ child.containerElement.style.display = 'block';
215
+ let newSize = childSizes[i];
216
+
217
+ if (this.stackedVertical)
218
+ child.resize(width, newSize);
219
+ else
220
+ child.resize(newSize, height);
221
+ }
222
+ }
223
+
224
+ private getElasticChildIndex(): number {
225
+ let fillIndex = this.childContainers.findIndex((container) => container.containerType === ContainerType.fill);
226
+ if (fillIndex >= 0)
227
+ return fillIndex;
228
+
229
+ let compositeIndex = this.childContainers.findIndex((container) =>
230
+ container.containerType === ContainerType.horizontal || container.containerType === ContainerType.vertical);
231
+ if (compositeIndex >= 0)
232
+ return compositeIndex;
233
+
234
+ return this.childContainers.length - 1;
235
+ }
236
+ }
package/src/TabHandle.ts CHANGED
@@ -212,11 +212,15 @@ export class TabHandle {
212
212
  this.touchUpHandler = new EventHandler(window, 'touchend', this.onMouseUp.bind(this));
213
213
  }
214
214
 
215
- onMouseUp() {
216
- if (this.elementBase) {
217
- this.elementBase.classList.remove('dockspan-tab-handle-dragged');
218
- }
219
- this.dragged = false;
215
+ onMouseUp() {
216
+ this.cancelTabDrag();
217
+ }
218
+
219
+ private cancelTabDrag() {
220
+ if (this.elementBase) {
221
+ this.elementBase.classList.remove('dockspan-tab-handle-dragged');
222
+ }
223
+ this.dragged = false;
220
224
  if (this.mouseMoveHandler)
221
225
  this.mouseMoveHandler.cancel();
222
226
  if (this.touchMoveHandler)
@@ -225,11 +229,11 @@ export class TabHandle {
225
229
  this.mouseUpHandler.cancel();
226
230
  if (this.touchUpHandler)
227
231
  this.touchUpHandler.cancel();
228
- delete this.mouseMoveHandler;
229
- delete this.touchMoveHandler;
230
- delete this.mouseUpHandler;
231
- delete this.touchUpHandler;
232
- }
232
+ delete this.mouseMoveHandler;
233
+ delete this.touchMoveHandler;
234
+ delete this.mouseUpHandler;
235
+ delete this.touchUpHandler;
236
+ }
233
237
 
234
238
  moveTabEvent(that, state) {
235
239
  that.eventListeners.forEach((listener) => {
@@ -312,12 +316,13 @@ export class TabHandle {
312
316
  }
313
317
  }
314
318
 
315
- _performUndock(e, dragOffset) {
316
- if (this.parent.container.containerType === 'panel') {
317
- this.undockInitiator.enabled = false;
318
- let panel = this.parent.container as PanelContainer;
319
- return panel.performUndockToDialog(e, dragOffset);
320
- }
319
+ _performUndock(e, dragOffset) {
320
+ if (this.parent.container.containerType === 'panel') {
321
+ this.undockInitiator.enabled = false;
322
+ this.cancelTabDrag();
323
+ let panel = this.parent.container as PanelContainer;
324
+ return panel.performUndockToDialog(e, dragOffset);
325
+ }
321
326
  else
322
327
  return null;
323
328
  }
@@ -351,4 +356,4 @@ export class TabHandle {
351
356
  this.elementBase.classList.remove('dockspan-tab-handle-active');
352
357
  }
353
358
  }
354
- }
359
+ }