react-headless-dock-layout 0.1.0 → 0.1.1
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.
- package/dist/index.cjs +894 -0
- package/dist/index.d.cts +164 -0
- package/dist/index.d.ts +164 -0
- package/dist/index.js +894 -0
- package/package.json +4 -1
- package/.vscode/settings.json +0 -7
- package/biome.json +0 -34
- package/index.html +0 -12
- package/src/App.tsx +0 -119
- package/src/global.css +0 -5
- package/src/index.ts +0 -3
- package/src/index.tsx +0 -8
- package/src/internal/EventEmitter.ts +0 -17
- package/src/internal/LayoutManager/LayoutManager.test.ts +0 -948
- package/src/internal/LayoutManager/LayoutManager.ts +0 -515
- package/src/internal/LayoutManager/LayoutTree.test.ts +0 -341
- package/src/internal/LayoutManager/LayoutTree.ts +0 -82
- package/src/internal/LayoutManager/calculateLayoutRects.test.ts +0 -211
- package/src/internal/LayoutManager/calculateLayoutRects.ts +0 -88
- package/src/internal/LayoutManager/calculateMinSize.test.ts +0 -77
- package/src/internal/LayoutManager/calculateMinSize.ts +0 -40
- package/src/internal/LayoutManager/findClosestDirection.test.ts +0 -95
- package/src/internal/LayoutManager/findClosestDirection.ts +0 -15
- package/src/internal/LayoutManager/types.ts +0 -20
- package/src/internal/assertNever.ts +0 -3
- package/src/internal/clamp.tsx +0 -3
- package/src/internal/findParentNode.ts +0 -30
- package/src/internal/invariant.tsx +0 -6
- package/src/strategies.ts +0 -76
- package/src/types.ts +0 -31
- package/src/useDockLayout.ts +0 -249
- package/tsconfig.json +0 -7
- package/tsup.config.ts +0 -9
|
@@ -1,515 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type AddPanelStrategy,
|
|
3
|
-
evenlyDividedHorizontalStrategy,
|
|
4
|
-
} from "../../strategies";
|
|
5
|
-
import type {
|
|
6
|
-
LayoutManagerOptions,
|
|
7
|
-
LayoutNode,
|
|
8
|
-
LayoutRect,
|
|
9
|
-
SplitNode,
|
|
10
|
-
} from "../../types";
|
|
11
|
-
import { assertNever } from "../assertNever";
|
|
12
|
-
import { clamp } from "../clamp";
|
|
13
|
-
import { EventEmitter } from "../EventEmitter";
|
|
14
|
-
import { invariant } from "../invariant";
|
|
15
|
-
|
|
16
|
-
import { calculateLayoutRects } from "./calculateLayoutRects";
|
|
17
|
-
import { calculateMinSize } from "./calculateMinSize";
|
|
18
|
-
import { findClosestDirection } from "./findClosestDirection";
|
|
19
|
-
import { LayoutTree } from "./LayoutTree";
|
|
20
|
-
import type { Direction, Point, Rect, Size } from "./types";
|
|
21
|
-
|
|
22
|
-
export class LayoutManager {
|
|
23
|
-
private _tree: LayoutTree;
|
|
24
|
-
private _options: Required<LayoutManagerOptions>;
|
|
25
|
-
private _eventEmitter = new EventEmitter();
|
|
26
|
-
private _layoutRects: LayoutRect[] = [];
|
|
27
|
-
private _addPanelStrategy: AddPanelStrategy = evenlyDividedHorizontalStrategy;
|
|
28
|
-
|
|
29
|
-
constructor(root: LayoutNode | null, options?: LayoutManagerOptions) {
|
|
30
|
-
this._tree = new LayoutTree(root);
|
|
31
|
-
this._options = {
|
|
32
|
-
gap: options?.gap ?? 10,
|
|
33
|
-
size: options?.size ?? { width: 0, height: 0 },
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
this._layoutRects = calculateLayoutRects(root, this._options);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
get root() {
|
|
40
|
-
return this._tree.root;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
set root(root: LayoutNode | null) {
|
|
44
|
-
this._tree.root = root;
|
|
45
|
-
this.syncLayoutRects();
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
get layoutRects() {
|
|
49
|
-
return this._layoutRects;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
subscribe = (listener: () => void) => {
|
|
53
|
-
const unsubscribe = this._eventEmitter.subscribe(listener);
|
|
54
|
-
|
|
55
|
-
return unsubscribe;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
setSize(size: Size) {
|
|
59
|
-
this._options.size = size;
|
|
60
|
-
this.syncLayoutRects();
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
removePanel(id: string) {
|
|
64
|
-
if (this._tree.root === null) {
|
|
65
|
-
throw new Error("Root node is null");
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const node = this._tree.findNode(id);
|
|
69
|
-
|
|
70
|
-
if (node === null) {
|
|
71
|
-
throw new Error(`Node with id ${id} not found`);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (node.type !== "panel") {
|
|
75
|
-
throw new Error(`Node with id ${id} is not a panel`);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (node.id === this._tree.root.id) {
|
|
79
|
-
this._tree.root = null;
|
|
80
|
-
this.syncLayoutRects();
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const parentNode = this._tree.findParentNode(id);
|
|
85
|
-
invariant(parentNode !== null, "Parent node is not null");
|
|
86
|
-
|
|
87
|
-
const siblingNode =
|
|
88
|
-
parentNode.left.id === node.id ? parentNode.right : parentNode.left;
|
|
89
|
-
|
|
90
|
-
if (parentNode.id === this._tree.root.id) {
|
|
91
|
-
this._tree.root = siblingNode;
|
|
92
|
-
this.syncLayoutRects();
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const grandParentNode = this._tree.findParentNode(parentNode.id);
|
|
97
|
-
invariant(grandParentNode !== null, "Grand parent node is not null");
|
|
98
|
-
|
|
99
|
-
this._tree.replaceChildNode({
|
|
100
|
-
parentId: grandParentNode.id,
|
|
101
|
-
oldChildId: parentNode.id,
|
|
102
|
-
newChild: siblingNode,
|
|
103
|
-
});
|
|
104
|
-
this.syncLayoutRects();
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
movePanel({
|
|
108
|
-
sourceId,
|
|
109
|
-
targetId,
|
|
110
|
-
point,
|
|
111
|
-
}: {
|
|
112
|
-
sourceId: string;
|
|
113
|
-
targetId: string;
|
|
114
|
-
point: Point;
|
|
115
|
-
}) {
|
|
116
|
-
if (this._tree.root === null) {
|
|
117
|
-
throw new Error("Root node is null");
|
|
118
|
-
}
|
|
119
|
-
if (this._tree.root.type !== "split") {
|
|
120
|
-
throw new Error("Root node is not a split node");
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const sourceNode = this._tree.findNode(sourceId);
|
|
124
|
-
|
|
125
|
-
if (sourceNode === null) {
|
|
126
|
-
throw new Error(`Node with id ${sourceId} not found`);
|
|
127
|
-
}
|
|
128
|
-
if (sourceNode.type !== "panel") {
|
|
129
|
-
throw new Error(`Node with id ${sourceId} is not a panel node`);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const sourceNodeParent = this._tree.findParentNode(sourceId);
|
|
133
|
-
invariant(sourceNodeParent !== null);
|
|
134
|
-
|
|
135
|
-
const targetNode = this._tree.findNode(targetId);
|
|
136
|
-
|
|
137
|
-
if (targetNode === null) {
|
|
138
|
-
throw new Error(`Node with id ${targetId} not found`);
|
|
139
|
-
}
|
|
140
|
-
if (targetNode.type !== "panel") {
|
|
141
|
-
throw new Error(`Node with id ${targetId} is not a panel node`);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const sourceNodeSibling =
|
|
145
|
-
sourceNodeParent.left.id === sourceId
|
|
146
|
-
? sourceNodeParent.right
|
|
147
|
-
: sourceNodeParent.left;
|
|
148
|
-
|
|
149
|
-
const targetRect = this.findRect(targetId);
|
|
150
|
-
invariant(targetRect !== null);
|
|
151
|
-
invariant(targetRect.type === "panel");
|
|
152
|
-
const direction = findClosestDirection(targetRect, point);
|
|
153
|
-
|
|
154
|
-
if (sourceNodeSibling.id === targetId) {
|
|
155
|
-
if (direction === "left") {
|
|
156
|
-
sourceNodeParent.orientation = "horizontal";
|
|
157
|
-
sourceNodeParent.left = sourceNode;
|
|
158
|
-
sourceNodeParent.right = targetNode;
|
|
159
|
-
} else if (direction === "right") {
|
|
160
|
-
sourceNodeParent.orientation = "horizontal";
|
|
161
|
-
sourceNodeParent.left = targetNode;
|
|
162
|
-
sourceNodeParent.right = sourceNode;
|
|
163
|
-
} else if (direction === "top") {
|
|
164
|
-
sourceNodeParent.orientation = "vertical";
|
|
165
|
-
sourceNodeParent.left = sourceNode;
|
|
166
|
-
sourceNodeParent.right = targetNode;
|
|
167
|
-
} else if (direction === "bottom") {
|
|
168
|
-
sourceNodeParent.orientation = "vertical";
|
|
169
|
-
sourceNodeParent.left = targetNode;
|
|
170
|
-
sourceNodeParent.right = sourceNode;
|
|
171
|
-
} else {
|
|
172
|
-
assertNever(direction);
|
|
173
|
-
}
|
|
174
|
-
this.syncLayoutRects();
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const sourceNodeGrandParent = this._tree.findParentNode(
|
|
179
|
-
sourceNodeParent.id,
|
|
180
|
-
);
|
|
181
|
-
if (sourceNodeGrandParent === null) {
|
|
182
|
-
this._tree.root = sourceNodeSibling;
|
|
183
|
-
} else if (sourceNodeGrandParent.right.id === sourceNodeParent.id) {
|
|
184
|
-
sourceNodeGrandParent.right = sourceNodeSibling;
|
|
185
|
-
} else if (sourceNodeGrandParent.left.id === sourceNodeParent.id) {
|
|
186
|
-
sourceNodeGrandParent.left = sourceNodeSibling;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
const targetNodeParent = this._tree.findParentNode(targetId);
|
|
190
|
-
invariant(targetNodeParent !== null);
|
|
191
|
-
const splitNode = this.createSplitNode({
|
|
192
|
-
direction,
|
|
193
|
-
sourceNode,
|
|
194
|
-
targetNode,
|
|
195
|
-
});
|
|
196
|
-
if (targetNodeParent.left.id === targetId) {
|
|
197
|
-
targetNodeParent.left = splitNode;
|
|
198
|
-
} else if (targetNodeParent.right.id === targetId) {
|
|
199
|
-
targetNodeParent.right = splitNode;
|
|
200
|
-
} else {
|
|
201
|
-
invariant(false);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
this.syncLayoutRects();
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
resizePanel(id: string, point: Point) {
|
|
208
|
-
if (this._tree.root === null) {
|
|
209
|
-
throw new Error("Root node is null");
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
const resizingRect = this.findRect(id);
|
|
213
|
-
|
|
214
|
-
if (resizingRect === null) {
|
|
215
|
-
throw new Error(`Rect with id ${id} not found`);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
if (resizingRect.type !== "split") {
|
|
219
|
-
throw new Error(`Rect with id ${id} is not a split node`);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
if (resizingRect.orientation === "horizontal") {
|
|
223
|
-
const { left: leftRect, right: rightRect } = this.getSplitChildRects(
|
|
224
|
-
resizingRect.id,
|
|
225
|
-
);
|
|
226
|
-
const leftWidth = point.x - leftRect.x;
|
|
227
|
-
const totalWidth = leftRect.width + resizingRect.width + rightRect.width;
|
|
228
|
-
const ratio = clamp(leftWidth / totalWidth, 0.1, 0.9);
|
|
229
|
-
this.setSplitRatio(resizingRect.id, ratio);
|
|
230
|
-
} else if (resizingRect.orientation === "vertical") {
|
|
231
|
-
const { left: topRect, right: bottomRect } = this.getSplitChildRects(
|
|
232
|
-
resizingRect.id,
|
|
233
|
-
);
|
|
234
|
-
const topHeight = point.y - topRect.y;
|
|
235
|
-
const totalHeight =
|
|
236
|
-
topRect.height + resizingRect.height + bottomRect.height;
|
|
237
|
-
const ratio = clamp(topHeight / totalHeight, 0.1, 0.9);
|
|
238
|
-
this.setSplitRatio(resizingRect.id, ratio);
|
|
239
|
-
} else {
|
|
240
|
-
assertNever(resizingRect.orientation);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
/**
|
|
246
|
-
* The addPanelStrategy is used to determine panel placement when the `targetId` is `undefined`.
|
|
247
|
-
*/
|
|
248
|
-
addPanel(options?: {
|
|
249
|
-
id?: string;
|
|
250
|
-
targetId?: string;
|
|
251
|
-
direction?: Direction;
|
|
252
|
-
ratio?: number;
|
|
253
|
-
}) {
|
|
254
|
-
const id = options?.id ?? crypto.randomUUID();
|
|
255
|
-
|
|
256
|
-
if (this._tree.root === null) {
|
|
257
|
-
this._tree.root = {
|
|
258
|
-
id,
|
|
259
|
-
type: "panel",
|
|
260
|
-
};
|
|
261
|
-
this.syncLayoutRects();
|
|
262
|
-
return;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
const shouldUseStrategy = options?.targetId === undefined;
|
|
266
|
-
const {
|
|
267
|
-
targetId,
|
|
268
|
-
direction = "right",
|
|
269
|
-
ratio = 0.5,
|
|
270
|
-
} = shouldUseStrategy
|
|
271
|
-
? this._addPanelStrategy.getPlacement(this._tree.root)
|
|
272
|
-
: options;
|
|
273
|
-
|
|
274
|
-
invariant(targetId !== undefined, "targetId is not undefined");
|
|
275
|
-
|
|
276
|
-
if (targetId === this._tree.root.id) {
|
|
277
|
-
this._tree.root = this.createSplitNode({
|
|
278
|
-
direction,
|
|
279
|
-
ratio,
|
|
280
|
-
sourceNode: {
|
|
281
|
-
id,
|
|
282
|
-
type: "panel",
|
|
283
|
-
},
|
|
284
|
-
targetNode: this._tree.root,
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
this.syncLayoutRects();
|
|
288
|
-
return;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
const targetNode = this._tree.findNode(targetId);
|
|
292
|
-
|
|
293
|
-
if (targetNode === null) {
|
|
294
|
-
throw new Error(`Node with id ${targetId} not found`);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
const targetNodeParent = this._tree.findParentNode(targetId);
|
|
298
|
-
invariant(targetNodeParent !== null, "Target node parent is not null");
|
|
299
|
-
|
|
300
|
-
const splitNode = this.createSplitNode({
|
|
301
|
-
direction,
|
|
302
|
-
sourceNode: {
|
|
303
|
-
id,
|
|
304
|
-
type: "panel",
|
|
305
|
-
},
|
|
306
|
-
targetNode,
|
|
307
|
-
ratio,
|
|
308
|
-
});
|
|
309
|
-
this._tree.replaceChildNode({
|
|
310
|
-
parentId: targetNodeParent.id,
|
|
311
|
-
oldChildId: targetId,
|
|
312
|
-
newChild: splitNode,
|
|
313
|
-
});
|
|
314
|
-
this.syncLayoutRects();
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
calculateDropTarget({
|
|
318
|
-
draggedPanelId,
|
|
319
|
-
targetPanelId,
|
|
320
|
-
point,
|
|
321
|
-
}: {
|
|
322
|
-
draggedPanelId: string;
|
|
323
|
-
targetPanelId: string;
|
|
324
|
-
point: Point;
|
|
325
|
-
}) {
|
|
326
|
-
invariant(
|
|
327
|
-
draggedPanelId !== targetPanelId,
|
|
328
|
-
"Dragged panel id is not the same as target panel id",
|
|
329
|
-
);
|
|
330
|
-
|
|
331
|
-
const targetRect = this.findRect(targetPanelId);
|
|
332
|
-
invariant(targetRect !== null && targetRect.type === "panel");
|
|
333
|
-
|
|
334
|
-
return {
|
|
335
|
-
id: targetPanelId,
|
|
336
|
-
direction: findClosestDirection(targetRect, point),
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
serialize() {
|
|
341
|
-
return JSON.stringify({
|
|
342
|
-
root: this._tree.root,
|
|
343
|
-
options: {
|
|
344
|
-
gap: this._options.gap,
|
|
345
|
-
},
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
private emit() {
|
|
350
|
-
this._eventEmitter.emit();
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
private syncLayoutRects() {
|
|
354
|
-
this._layoutRects = calculateLayoutRects(this._tree.root, this._options);
|
|
355
|
-
this.emit();
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
private createSplitNode({
|
|
359
|
-
direction,
|
|
360
|
-
sourceNode,
|
|
361
|
-
targetNode,
|
|
362
|
-
ratio = 0.5,
|
|
363
|
-
}: {
|
|
364
|
-
direction: Direction;
|
|
365
|
-
sourceNode: LayoutNode;
|
|
366
|
-
targetNode: LayoutNode;
|
|
367
|
-
ratio?: number;
|
|
368
|
-
}): SplitNode {
|
|
369
|
-
switch (direction) {
|
|
370
|
-
case "left": {
|
|
371
|
-
return {
|
|
372
|
-
id: crypto.randomUUID(),
|
|
373
|
-
type: "split",
|
|
374
|
-
orientation: "horizontal",
|
|
375
|
-
ratio,
|
|
376
|
-
left: sourceNode,
|
|
377
|
-
right: targetNode,
|
|
378
|
-
};
|
|
379
|
-
}
|
|
380
|
-
case "right": {
|
|
381
|
-
return {
|
|
382
|
-
id: crypto.randomUUID(),
|
|
383
|
-
type: "split",
|
|
384
|
-
orientation: "horizontal",
|
|
385
|
-
ratio,
|
|
386
|
-
left: targetNode,
|
|
387
|
-
right: sourceNode,
|
|
388
|
-
};
|
|
389
|
-
}
|
|
390
|
-
case "top": {
|
|
391
|
-
return {
|
|
392
|
-
id: crypto.randomUUID(),
|
|
393
|
-
type: "split",
|
|
394
|
-
orientation: "vertical",
|
|
395
|
-
ratio,
|
|
396
|
-
left: sourceNode,
|
|
397
|
-
right: targetNode,
|
|
398
|
-
};
|
|
399
|
-
}
|
|
400
|
-
case "bottom": {
|
|
401
|
-
return {
|
|
402
|
-
id: crypto.randomUUID(),
|
|
403
|
-
type: "split",
|
|
404
|
-
orientation: "vertical",
|
|
405
|
-
ratio,
|
|
406
|
-
left: targetNode,
|
|
407
|
-
right: sourceNode,
|
|
408
|
-
};
|
|
409
|
-
}
|
|
410
|
-
default: {
|
|
411
|
-
assertNever(direction);
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
private setSplitRatio(id: string, ratio: number) {
|
|
417
|
-
const splitNode = this._tree.findNode(id);
|
|
418
|
-
|
|
419
|
-
invariant(splitNode !== null, "Node is not null");
|
|
420
|
-
invariant(splitNode.type === "split", "Node is a split");
|
|
421
|
-
|
|
422
|
-
if (splitNode.orientation === "horizontal") {
|
|
423
|
-
const totalWidth =
|
|
424
|
-
this.getSurroundingRect(splitNode.left.id).width +
|
|
425
|
-
this._options.gap +
|
|
426
|
-
this.getSurroundingRect(splitNode.right.id).width;
|
|
427
|
-
const minLeftWidth = calculateMinSize(
|
|
428
|
-
splitNode.left,
|
|
429
|
-
this._options.gap,
|
|
430
|
-
).width;
|
|
431
|
-
const minRightWidth = calculateMinSize(
|
|
432
|
-
splitNode.right,
|
|
433
|
-
this._options.gap,
|
|
434
|
-
).width;
|
|
435
|
-
const minRatio = (minLeftWidth + this._options.gap / 2) / totalWidth;
|
|
436
|
-
const maxRatio =
|
|
437
|
-
(totalWidth - (minRightWidth + this._options.gap / 2)) / totalWidth;
|
|
438
|
-
splitNode.ratio = clamp(ratio, minRatio, maxRatio);
|
|
439
|
-
} else if (splitNode.orientation === "vertical") {
|
|
440
|
-
const totalHeight =
|
|
441
|
-
this.getSurroundingRect(splitNode.left.id).height +
|
|
442
|
-
this._options.gap +
|
|
443
|
-
this.getSurroundingRect(splitNode.right.id).height;
|
|
444
|
-
const minTopHeight = calculateMinSize(
|
|
445
|
-
splitNode.left,
|
|
446
|
-
this._options.gap,
|
|
447
|
-
).height;
|
|
448
|
-
const minBottomHeight = calculateMinSize(
|
|
449
|
-
splitNode.right,
|
|
450
|
-
this._options.gap,
|
|
451
|
-
).height;
|
|
452
|
-
const minRatio = (minTopHeight + this._options.gap / 2) / totalHeight;
|
|
453
|
-
const maxRatio =
|
|
454
|
-
(totalHeight - (minBottomHeight + this._options.gap / 2)) / totalHeight;
|
|
455
|
-
splitNode.ratio = clamp(ratio, minRatio, maxRatio);
|
|
456
|
-
} else {
|
|
457
|
-
assertNever(splitNode.orientation);
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
this.syncLayoutRects();
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
private findRect(id: string) {
|
|
464
|
-
return this._layoutRects.find((rect) => rect.id === id) ?? null;
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
private getSurroundingRect(id: string): Rect {
|
|
468
|
-
const node = this._tree.findNode(id);
|
|
469
|
-
invariant(node !== null, "Node is not null");
|
|
470
|
-
|
|
471
|
-
if (node.type === "panel") {
|
|
472
|
-
const rect = this.findRect(id);
|
|
473
|
-
invariant(rect !== null, "Rect is not null");
|
|
474
|
-
invariant(rect.type === "panel", "Rect is a panel");
|
|
475
|
-
|
|
476
|
-
return {
|
|
477
|
-
x: rect.x,
|
|
478
|
-
y: rect.y,
|
|
479
|
-
width: rect.width,
|
|
480
|
-
height: rect.height,
|
|
481
|
-
};
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
const leftRect = this.getSurroundingRect(node.left.id);
|
|
485
|
-
const rightRect = this.getSurroundingRect(node.right.id);
|
|
486
|
-
|
|
487
|
-
if (node.orientation === "horizontal") {
|
|
488
|
-
return {
|
|
489
|
-
x: leftRect.x,
|
|
490
|
-
y: leftRect.y,
|
|
491
|
-
width: leftRect.width + this._options.gap + rightRect.width,
|
|
492
|
-
height: leftRect.height,
|
|
493
|
-
};
|
|
494
|
-
} else if (node.orientation === "vertical") {
|
|
495
|
-
return {
|
|
496
|
-
x: leftRect.x,
|
|
497
|
-
y: leftRect.y,
|
|
498
|
-
width: leftRect.width,
|
|
499
|
-
height: leftRect.height + this._options.gap + rightRect.height,
|
|
500
|
-
};
|
|
501
|
-
} else {
|
|
502
|
-
assertNever(node.orientation);
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
private getSplitChildRects(splitId: string) {
|
|
507
|
-
const node = this._tree.findNode(splitId);
|
|
508
|
-
invariant(node !== null && node.type === "split");
|
|
509
|
-
|
|
510
|
-
return {
|
|
511
|
-
left: this.getSurroundingRect(node.left.id),
|
|
512
|
-
right: this.getSurroundingRect(node.right.id),
|
|
513
|
-
};
|
|
514
|
-
}
|
|
515
|
-
}
|