react-headless-dock-layout 0.1.1 → 0.1.3
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 +1 -894
- package/dist/index.js +1 -894
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -1,894 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3;// src/internal/assertNever.ts
|
|
2
|
-
function assertNever(value) {
|
|
3
|
-
throw new Error(`Unexpected value: ${value}`);
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
// src/internal/findParentNode.ts
|
|
7
|
-
function findParentNode(root, id) {
|
|
8
|
-
if (root === null) {
|
|
9
|
-
return null;
|
|
10
|
-
}
|
|
11
|
-
return findParentNodeInSubTree(id, root);
|
|
12
|
-
}
|
|
13
|
-
function findParentNodeInSubTree(id, node) {
|
|
14
|
-
if (node.type === "panel") {
|
|
15
|
-
return null;
|
|
16
|
-
} else if (node.type === "split") {
|
|
17
|
-
if (node.left.id === id || node.right.id === id) {
|
|
18
|
-
return node;
|
|
19
|
-
}
|
|
20
|
-
return _nullishCoalesce(findParentNodeInSubTree(id, node.left), () => ( findParentNodeInSubTree(id, node.right)));
|
|
21
|
-
} else {
|
|
22
|
-
assertNever(node);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// src/strategies.ts
|
|
27
|
-
var evenlyDividedHorizontalStrategy = {
|
|
28
|
-
getPlacement(root) {
|
|
29
|
-
const horizontalNodeCount = calculateHorizontalSplitCount(root) + 1;
|
|
30
|
-
return {
|
|
31
|
-
targetId: root.id,
|
|
32
|
-
direction: "right",
|
|
33
|
-
ratio: horizontalNodeCount / (horizontalNodeCount + 1)
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
function calculateHorizontalSplitCount(node) {
|
|
38
|
-
if (node.type === "panel") {
|
|
39
|
-
return 0;
|
|
40
|
-
} else if (node.type === "split") {
|
|
41
|
-
if (node.orientation === "horizontal") {
|
|
42
|
-
return 1 + calculateHorizontalSplitCount(node.left) + calculateHorizontalSplitCount(node.right);
|
|
43
|
-
} else if (node.orientation === "vertical") {
|
|
44
|
-
return 0 + calculateHorizontalSplitCount(node.left) + calculateHorizontalSplitCount(node.right);
|
|
45
|
-
} else {
|
|
46
|
-
assertNever(node.orientation);
|
|
47
|
-
}
|
|
48
|
-
} else {
|
|
49
|
-
assertNever(node);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
var bspStrategy = {
|
|
53
|
-
getPlacement(root) {
|
|
54
|
-
const rightMostPanel = findRightMostPanel(root);
|
|
55
|
-
const parentNode = findParentNode(root, rightMostPanel.id);
|
|
56
|
-
return {
|
|
57
|
-
targetId: rightMostPanel.id,
|
|
58
|
-
direction: parentNode === null ? "right" : parentNode.orientation === "horizontal" ? "bottom" : "right",
|
|
59
|
-
ratio: 0.5
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
function findRightMostPanel(node) {
|
|
64
|
-
if (node.type === "panel") {
|
|
65
|
-
return node;
|
|
66
|
-
} else if (node.type === "split") {
|
|
67
|
-
return findRightMostPanel(node.right);
|
|
68
|
-
} else {
|
|
69
|
-
assertNever(node);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// src/useDockLayout.ts
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
var _react = require('react');
|
|
81
|
-
|
|
82
|
-
// src/internal/invariant.tsx
|
|
83
|
-
function invariant(condition, message) {
|
|
84
|
-
if (!condition) {
|
|
85
|
-
throw new Error(_nullishCoalesce(message, () => ( "Invariant failed")));
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// src/internal/clamp.tsx
|
|
90
|
-
function clamp(value, min, max) {
|
|
91
|
-
return Math.max(min, Math.min(max, value));
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// src/internal/EventEmitter.ts
|
|
95
|
-
var EventEmitter = (_class = class {constructor() { _class.prototype.__init.call(this); }
|
|
96
|
-
__init() {this._listeners = /* @__PURE__ */ new Set()}
|
|
97
|
-
subscribe(listener) {
|
|
98
|
-
this._listeners.add(listener);
|
|
99
|
-
return () => {
|
|
100
|
-
this._listeners.delete(listener);
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
emit() {
|
|
104
|
-
this._listeners.forEach((listener) => {
|
|
105
|
-
listener();
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
}, _class);
|
|
109
|
-
|
|
110
|
-
// src/internal/LayoutManager/calculateLayoutRects.ts
|
|
111
|
-
function calculateLayoutRects(root, options) {
|
|
112
|
-
if (root === null) {
|
|
113
|
-
return [];
|
|
114
|
-
}
|
|
115
|
-
const rects = [];
|
|
116
|
-
const traverse = (node, rect) => {
|
|
117
|
-
if (node.type === "split") {
|
|
118
|
-
if (node.orientation === "horizontal") {
|
|
119
|
-
rects.push({
|
|
120
|
-
id: node.id,
|
|
121
|
-
type: "split",
|
|
122
|
-
orientation: node.orientation,
|
|
123
|
-
x: Math.round(rect.x + rect.width * node.ratio - options.gap / 2),
|
|
124
|
-
y: Math.round(rect.y),
|
|
125
|
-
width: Math.round(options.gap),
|
|
126
|
-
height: Math.round(rect.height)
|
|
127
|
-
});
|
|
128
|
-
traverse(node.left, {
|
|
129
|
-
x: rect.x,
|
|
130
|
-
y: rect.y,
|
|
131
|
-
width: rect.width * node.ratio - options.gap / 2,
|
|
132
|
-
height: rect.height
|
|
133
|
-
});
|
|
134
|
-
traverse(node.right, {
|
|
135
|
-
x: rect.x + rect.width * node.ratio + options.gap / 2,
|
|
136
|
-
y: rect.y,
|
|
137
|
-
width: rect.width * (1 - node.ratio) - options.gap / 2,
|
|
138
|
-
height: rect.height
|
|
139
|
-
});
|
|
140
|
-
} else if (node.orientation === "vertical") {
|
|
141
|
-
rects.push({
|
|
142
|
-
id: node.id,
|
|
143
|
-
type: "split",
|
|
144
|
-
orientation: node.orientation,
|
|
145
|
-
x: Math.round(rect.x),
|
|
146
|
-
y: Math.round(rect.y + rect.height * node.ratio - options.gap / 2),
|
|
147
|
-
width: Math.round(rect.width),
|
|
148
|
-
height: Math.round(options.gap)
|
|
149
|
-
});
|
|
150
|
-
traverse(node.left, {
|
|
151
|
-
x: rect.x,
|
|
152
|
-
y: rect.y,
|
|
153
|
-
width: rect.width,
|
|
154
|
-
height: rect.height * node.ratio - options.gap / 2
|
|
155
|
-
});
|
|
156
|
-
traverse(node.right, {
|
|
157
|
-
x: rect.x,
|
|
158
|
-
y: rect.y + rect.height * node.ratio + options.gap / 2,
|
|
159
|
-
width: rect.width,
|
|
160
|
-
height: rect.height * (1 - node.ratio) - options.gap / 2
|
|
161
|
-
});
|
|
162
|
-
} else {
|
|
163
|
-
assertNever(node.orientation);
|
|
164
|
-
}
|
|
165
|
-
} else if (node.type === "panel") {
|
|
166
|
-
rects.push({
|
|
167
|
-
id: node.id,
|
|
168
|
-
type: "panel",
|
|
169
|
-
x: Math.round(rect.x),
|
|
170
|
-
y: Math.round(rect.y),
|
|
171
|
-
width: Math.round(rect.width),
|
|
172
|
-
height: Math.round(rect.height)
|
|
173
|
-
});
|
|
174
|
-
} else {
|
|
175
|
-
assertNever(node);
|
|
176
|
-
}
|
|
177
|
-
};
|
|
178
|
-
traverse(root, {
|
|
179
|
-
x: 0,
|
|
180
|
-
y: 0,
|
|
181
|
-
width: options.size.width,
|
|
182
|
-
height: options.size.height
|
|
183
|
-
});
|
|
184
|
-
return rects;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// src/internal/LayoutManager/calculateMinSize.ts
|
|
188
|
-
function calculateMinSize(node, gap) {
|
|
189
|
-
if (node.type === "panel") {
|
|
190
|
-
return {
|
|
191
|
-
width: _nullishCoalesce(_optionalChain([node, 'access', _ => _.minSize, 'optionalAccess', _2 => _2.width]), () => ( 0)),
|
|
192
|
-
height: _nullishCoalesce(_optionalChain([node, 'access', _3 => _3.minSize, 'optionalAccess', _4 => _4.height]), () => ( 0))
|
|
193
|
-
};
|
|
194
|
-
} else if (node.type === "split") {
|
|
195
|
-
if (node.orientation === "horizontal") {
|
|
196
|
-
return {
|
|
197
|
-
width: calculateMinSize(node.left, gap).width + gap + calculateMinSize(node.right, gap).width,
|
|
198
|
-
height: Math.max(
|
|
199
|
-
calculateMinSize(node.left, gap).height,
|
|
200
|
-
calculateMinSize(node.right, gap).height
|
|
201
|
-
)
|
|
202
|
-
};
|
|
203
|
-
} else if (node.orientation === "vertical") {
|
|
204
|
-
return {
|
|
205
|
-
width: Math.max(
|
|
206
|
-
calculateMinSize(node.left, gap).width,
|
|
207
|
-
calculateMinSize(node.right, gap).width
|
|
208
|
-
),
|
|
209
|
-
height: calculateMinSize(node.left, gap).height + gap + calculateMinSize(node.right, gap).height
|
|
210
|
-
};
|
|
211
|
-
} else {
|
|
212
|
-
assertNever(node.orientation);
|
|
213
|
-
}
|
|
214
|
-
} else {
|
|
215
|
-
assertNever(node);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// src/internal/LayoutManager/findClosestDirection.ts
|
|
220
|
-
function findClosestDirection(rect, point) {
|
|
221
|
-
const centerX = rect.x + rect.width / 2;
|
|
222
|
-
const centerY = rect.y + rect.height / 2;
|
|
223
|
-
const dx = (point.x - centerX) / (rect.width / 2);
|
|
224
|
-
const dy = (point.y - centerY) / (rect.height / 2);
|
|
225
|
-
if (Math.abs(dx) > Math.abs(dy)) {
|
|
226
|
-
return dx > 0 ? "right" : "left";
|
|
227
|
-
} else {
|
|
228
|
-
return dy > 0 ? "bottom" : "top";
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// src/internal/LayoutManager/LayoutTree.ts
|
|
233
|
-
var LayoutTree = (_class2 = class {
|
|
234
|
-
__init2() {this._root = null}
|
|
235
|
-
constructor(root) {;_class2.prototype.__init2.call(this);
|
|
236
|
-
this._root = root;
|
|
237
|
-
}
|
|
238
|
-
get root() {
|
|
239
|
-
return this._root;
|
|
240
|
-
}
|
|
241
|
-
set root(root) {
|
|
242
|
-
this._root = root;
|
|
243
|
-
}
|
|
244
|
-
findNode(id) {
|
|
245
|
-
if (this._root === null) {
|
|
246
|
-
return null;
|
|
247
|
-
}
|
|
248
|
-
return this.findNodeInSubTree(id, this._root);
|
|
249
|
-
}
|
|
250
|
-
findNodeInSubTree(id, node) {
|
|
251
|
-
if (id === node.id) {
|
|
252
|
-
return node;
|
|
253
|
-
}
|
|
254
|
-
if (node.type === "panel") {
|
|
255
|
-
return null;
|
|
256
|
-
} else if (node.type === "split") {
|
|
257
|
-
return _nullishCoalesce(this.findNodeInSubTree(id, node.left), () => ( this.findNodeInSubTree(id, node.right)));
|
|
258
|
-
} else {
|
|
259
|
-
assertNever(node);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
findParentNode(id) {
|
|
263
|
-
return findParentNode(this._root, id);
|
|
264
|
-
}
|
|
265
|
-
replaceChildNode({
|
|
266
|
-
parentId,
|
|
267
|
-
oldChildId,
|
|
268
|
-
newChild
|
|
269
|
-
}) {
|
|
270
|
-
const parentNode = this.findNode(parentId);
|
|
271
|
-
if (parentNode === null) {
|
|
272
|
-
throw new Error(`Parent node with id ${parentId} not found`);
|
|
273
|
-
}
|
|
274
|
-
if (parentNode.type !== "split") {
|
|
275
|
-
throw new Error(`Parent node with id ${parentId} is not a split node`);
|
|
276
|
-
}
|
|
277
|
-
const oldChildNode = this.findNode(oldChildId);
|
|
278
|
-
if (oldChildNode === null) {
|
|
279
|
-
throw new Error(`Child node with id ${oldChildId} not found`);
|
|
280
|
-
}
|
|
281
|
-
if (parentNode.left.id === oldChildId) {
|
|
282
|
-
parentNode.left = newChild;
|
|
283
|
-
} else if (parentNode.right.id === oldChildId) {
|
|
284
|
-
parentNode.right = newChild;
|
|
285
|
-
} else {
|
|
286
|
-
throw new Error(
|
|
287
|
-
`Child node with id ${oldChildId} is not a child of the parent node with id ${parentId}`
|
|
288
|
-
);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
}, _class2);
|
|
292
|
-
|
|
293
|
-
// src/internal/LayoutManager/LayoutManager.ts
|
|
294
|
-
var LayoutManager = (_class3 = class {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
__init3() {this._eventEmitter = new EventEmitter()}
|
|
298
|
-
__init4() {this._layoutRects = []}
|
|
299
|
-
__init5() {this._addPanelStrategy = evenlyDividedHorizontalStrategy}
|
|
300
|
-
constructor(root, options) {;_class3.prototype.__init3.call(this);_class3.prototype.__init4.call(this);_class3.prototype.__init5.call(this);_class3.prototype.__init6.call(this);
|
|
301
|
-
this._tree = new LayoutTree(root);
|
|
302
|
-
this._options = {
|
|
303
|
-
gap: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _5 => _5.gap]), () => ( 10)),
|
|
304
|
-
size: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _6 => _6.size]), () => ( { width: 0, height: 0 }))
|
|
305
|
-
};
|
|
306
|
-
this._layoutRects = calculateLayoutRects(root, this._options);
|
|
307
|
-
}
|
|
308
|
-
get root() {
|
|
309
|
-
return this._tree.root;
|
|
310
|
-
}
|
|
311
|
-
set root(root) {
|
|
312
|
-
this._tree.root = root;
|
|
313
|
-
this.syncLayoutRects();
|
|
314
|
-
}
|
|
315
|
-
get layoutRects() {
|
|
316
|
-
return this._layoutRects;
|
|
317
|
-
}
|
|
318
|
-
__init6() {this.subscribe = (listener) => {
|
|
319
|
-
const unsubscribe = this._eventEmitter.subscribe(listener);
|
|
320
|
-
return unsubscribe;
|
|
321
|
-
}}
|
|
322
|
-
setSize(size) {
|
|
323
|
-
this._options.size = size;
|
|
324
|
-
this.syncLayoutRects();
|
|
325
|
-
}
|
|
326
|
-
removePanel(id) {
|
|
327
|
-
if (this._tree.root === null) {
|
|
328
|
-
throw new Error("Root node is null");
|
|
329
|
-
}
|
|
330
|
-
const node = this._tree.findNode(id);
|
|
331
|
-
if (node === null) {
|
|
332
|
-
throw new Error(`Node with id ${id} not found`);
|
|
333
|
-
}
|
|
334
|
-
if (node.type !== "panel") {
|
|
335
|
-
throw new Error(`Node with id ${id} is not a panel`);
|
|
336
|
-
}
|
|
337
|
-
if (node.id === this._tree.root.id) {
|
|
338
|
-
this._tree.root = null;
|
|
339
|
-
this.syncLayoutRects();
|
|
340
|
-
return;
|
|
341
|
-
}
|
|
342
|
-
const parentNode = this._tree.findParentNode(id);
|
|
343
|
-
invariant(parentNode !== null, "Parent node is not null");
|
|
344
|
-
const siblingNode = parentNode.left.id === node.id ? parentNode.right : parentNode.left;
|
|
345
|
-
if (parentNode.id === this._tree.root.id) {
|
|
346
|
-
this._tree.root = siblingNode;
|
|
347
|
-
this.syncLayoutRects();
|
|
348
|
-
return;
|
|
349
|
-
}
|
|
350
|
-
const grandParentNode = this._tree.findParentNode(parentNode.id);
|
|
351
|
-
invariant(grandParentNode !== null, "Grand parent node is not null");
|
|
352
|
-
this._tree.replaceChildNode({
|
|
353
|
-
parentId: grandParentNode.id,
|
|
354
|
-
oldChildId: parentNode.id,
|
|
355
|
-
newChild: siblingNode
|
|
356
|
-
});
|
|
357
|
-
this.syncLayoutRects();
|
|
358
|
-
}
|
|
359
|
-
movePanel({
|
|
360
|
-
sourceId,
|
|
361
|
-
targetId,
|
|
362
|
-
point
|
|
363
|
-
}) {
|
|
364
|
-
if (this._tree.root === null) {
|
|
365
|
-
throw new Error("Root node is null");
|
|
366
|
-
}
|
|
367
|
-
if (this._tree.root.type !== "split") {
|
|
368
|
-
throw new Error("Root node is not a split node");
|
|
369
|
-
}
|
|
370
|
-
const sourceNode = this._tree.findNode(sourceId);
|
|
371
|
-
if (sourceNode === null) {
|
|
372
|
-
throw new Error(`Node with id ${sourceId} not found`);
|
|
373
|
-
}
|
|
374
|
-
if (sourceNode.type !== "panel") {
|
|
375
|
-
throw new Error(`Node with id ${sourceId} is not a panel node`);
|
|
376
|
-
}
|
|
377
|
-
const sourceNodeParent = this._tree.findParentNode(sourceId);
|
|
378
|
-
invariant(sourceNodeParent !== null);
|
|
379
|
-
const targetNode = this._tree.findNode(targetId);
|
|
380
|
-
if (targetNode === null) {
|
|
381
|
-
throw new Error(`Node with id ${targetId} not found`);
|
|
382
|
-
}
|
|
383
|
-
if (targetNode.type !== "panel") {
|
|
384
|
-
throw new Error(`Node with id ${targetId} is not a panel node`);
|
|
385
|
-
}
|
|
386
|
-
const sourceNodeSibling = sourceNodeParent.left.id === sourceId ? sourceNodeParent.right : sourceNodeParent.left;
|
|
387
|
-
const targetRect = this.findRect(targetId);
|
|
388
|
-
invariant(targetRect !== null);
|
|
389
|
-
invariant(targetRect.type === "panel");
|
|
390
|
-
const direction = findClosestDirection(targetRect, point);
|
|
391
|
-
if (sourceNodeSibling.id === targetId) {
|
|
392
|
-
if (direction === "left") {
|
|
393
|
-
sourceNodeParent.orientation = "horizontal";
|
|
394
|
-
sourceNodeParent.left = sourceNode;
|
|
395
|
-
sourceNodeParent.right = targetNode;
|
|
396
|
-
} else if (direction === "right") {
|
|
397
|
-
sourceNodeParent.orientation = "horizontal";
|
|
398
|
-
sourceNodeParent.left = targetNode;
|
|
399
|
-
sourceNodeParent.right = sourceNode;
|
|
400
|
-
} else if (direction === "top") {
|
|
401
|
-
sourceNodeParent.orientation = "vertical";
|
|
402
|
-
sourceNodeParent.left = sourceNode;
|
|
403
|
-
sourceNodeParent.right = targetNode;
|
|
404
|
-
} else if (direction === "bottom") {
|
|
405
|
-
sourceNodeParent.orientation = "vertical";
|
|
406
|
-
sourceNodeParent.left = targetNode;
|
|
407
|
-
sourceNodeParent.right = sourceNode;
|
|
408
|
-
} else {
|
|
409
|
-
assertNever(direction);
|
|
410
|
-
}
|
|
411
|
-
this.syncLayoutRects();
|
|
412
|
-
return;
|
|
413
|
-
}
|
|
414
|
-
const sourceNodeGrandParent = this._tree.findParentNode(
|
|
415
|
-
sourceNodeParent.id
|
|
416
|
-
);
|
|
417
|
-
if (sourceNodeGrandParent === null) {
|
|
418
|
-
this._tree.root = sourceNodeSibling;
|
|
419
|
-
} else if (sourceNodeGrandParent.right.id === sourceNodeParent.id) {
|
|
420
|
-
sourceNodeGrandParent.right = sourceNodeSibling;
|
|
421
|
-
} else if (sourceNodeGrandParent.left.id === sourceNodeParent.id) {
|
|
422
|
-
sourceNodeGrandParent.left = sourceNodeSibling;
|
|
423
|
-
}
|
|
424
|
-
const targetNodeParent = this._tree.findParentNode(targetId);
|
|
425
|
-
invariant(targetNodeParent !== null);
|
|
426
|
-
const splitNode = this.createSplitNode({
|
|
427
|
-
direction,
|
|
428
|
-
sourceNode,
|
|
429
|
-
targetNode
|
|
430
|
-
});
|
|
431
|
-
if (targetNodeParent.left.id === targetId) {
|
|
432
|
-
targetNodeParent.left = splitNode;
|
|
433
|
-
} else if (targetNodeParent.right.id === targetId) {
|
|
434
|
-
targetNodeParent.right = splitNode;
|
|
435
|
-
} else {
|
|
436
|
-
invariant(false);
|
|
437
|
-
}
|
|
438
|
-
this.syncLayoutRects();
|
|
439
|
-
}
|
|
440
|
-
resizePanel(id, point) {
|
|
441
|
-
if (this._tree.root === null) {
|
|
442
|
-
throw new Error("Root node is null");
|
|
443
|
-
}
|
|
444
|
-
const resizingRect = this.findRect(id);
|
|
445
|
-
if (resizingRect === null) {
|
|
446
|
-
throw new Error(`Rect with id ${id} not found`);
|
|
447
|
-
}
|
|
448
|
-
if (resizingRect.type !== "split") {
|
|
449
|
-
throw new Error(`Rect with id ${id} is not a split node`);
|
|
450
|
-
}
|
|
451
|
-
if (resizingRect.orientation === "horizontal") {
|
|
452
|
-
const { left: leftRect, right: rightRect } = this.getSplitChildRects(
|
|
453
|
-
resizingRect.id
|
|
454
|
-
);
|
|
455
|
-
const leftWidth = point.x - leftRect.x;
|
|
456
|
-
const totalWidth = leftRect.width + resizingRect.width + rightRect.width;
|
|
457
|
-
const ratio = clamp(leftWidth / totalWidth, 0.1, 0.9);
|
|
458
|
-
this.setSplitRatio(resizingRect.id, ratio);
|
|
459
|
-
} else if (resizingRect.orientation === "vertical") {
|
|
460
|
-
const { left: topRect, right: bottomRect } = this.getSplitChildRects(
|
|
461
|
-
resizingRect.id
|
|
462
|
-
);
|
|
463
|
-
const topHeight = point.y - topRect.y;
|
|
464
|
-
const totalHeight = topRect.height + resizingRect.height + bottomRect.height;
|
|
465
|
-
const ratio = clamp(topHeight / totalHeight, 0.1, 0.9);
|
|
466
|
-
this.setSplitRatio(resizingRect.id, ratio);
|
|
467
|
-
} else {
|
|
468
|
-
assertNever(resizingRect.orientation);
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
/**
|
|
472
|
-
/**
|
|
473
|
-
* The addPanelStrategy is used to determine panel placement when the `targetId` is `undefined`.
|
|
474
|
-
*/
|
|
475
|
-
addPanel(options) {
|
|
476
|
-
const id = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _7 => _7.id]), () => ( crypto.randomUUID()));
|
|
477
|
-
if (this._tree.root === null) {
|
|
478
|
-
this._tree.root = {
|
|
479
|
-
id,
|
|
480
|
-
type: "panel"
|
|
481
|
-
};
|
|
482
|
-
this.syncLayoutRects();
|
|
483
|
-
return;
|
|
484
|
-
}
|
|
485
|
-
const shouldUseStrategy = _optionalChain([options, 'optionalAccess', _8 => _8.targetId]) === void 0;
|
|
486
|
-
const {
|
|
487
|
-
targetId,
|
|
488
|
-
direction = "right",
|
|
489
|
-
ratio = 0.5
|
|
490
|
-
} = shouldUseStrategy ? this._addPanelStrategy.getPlacement(this._tree.root) : options;
|
|
491
|
-
invariant(targetId !== void 0, "targetId is not undefined");
|
|
492
|
-
if (targetId === this._tree.root.id) {
|
|
493
|
-
this._tree.root = this.createSplitNode({
|
|
494
|
-
direction,
|
|
495
|
-
ratio,
|
|
496
|
-
sourceNode: {
|
|
497
|
-
id,
|
|
498
|
-
type: "panel"
|
|
499
|
-
},
|
|
500
|
-
targetNode: this._tree.root
|
|
501
|
-
});
|
|
502
|
-
this.syncLayoutRects();
|
|
503
|
-
return;
|
|
504
|
-
}
|
|
505
|
-
const targetNode = this._tree.findNode(targetId);
|
|
506
|
-
if (targetNode === null) {
|
|
507
|
-
throw new Error(`Node with id ${targetId} not found`);
|
|
508
|
-
}
|
|
509
|
-
const targetNodeParent = this._tree.findParentNode(targetId);
|
|
510
|
-
invariant(targetNodeParent !== null, "Target node parent is not null");
|
|
511
|
-
const splitNode = this.createSplitNode({
|
|
512
|
-
direction,
|
|
513
|
-
sourceNode: {
|
|
514
|
-
id,
|
|
515
|
-
type: "panel"
|
|
516
|
-
},
|
|
517
|
-
targetNode,
|
|
518
|
-
ratio
|
|
519
|
-
});
|
|
520
|
-
this._tree.replaceChildNode({
|
|
521
|
-
parentId: targetNodeParent.id,
|
|
522
|
-
oldChildId: targetId,
|
|
523
|
-
newChild: splitNode
|
|
524
|
-
});
|
|
525
|
-
this.syncLayoutRects();
|
|
526
|
-
}
|
|
527
|
-
calculateDropTarget({
|
|
528
|
-
draggedPanelId,
|
|
529
|
-
targetPanelId,
|
|
530
|
-
point
|
|
531
|
-
}) {
|
|
532
|
-
invariant(
|
|
533
|
-
draggedPanelId !== targetPanelId,
|
|
534
|
-
"Dragged panel id is not the same as target panel id"
|
|
535
|
-
);
|
|
536
|
-
const targetRect = this.findRect(targetPanelId);
|
|
537
|
-
invariant(targetRect !== null && targetRect.type === "panel");
|
|
538
|
-
return {
|
|
539
|
-
id: targetPanelId,
|
|
540
|
-
direction: findClosestDirection(targetRect, point)
|
|
541
|
-
};
|
|
542
|
-
}
|
|
543
|
-
serialize() {
|
|
544
|
-
return JSON.stringify({
|
|
545
|
-
root: this._tree.root,
|
|
546
|
-
options: {
|
|
547
|
-
gap: this._options.gap
|
|
548
|
-
}
|
|
549
|
-
});
|
|
550
|
-
}
|
|
551
|
-
emit() {
|
|
552
|
-
this._eventEmitter.emit();
|
|
553
|
-
}
|
|
554
|
-
syncLayoutRects() {
|
|
555
|
-
this._layoutRects = calculateLayoutRects(this._tree.root, this._options);
|
|
556
|
-
this.emit();
|
|
557
|
-
}
|
|
558
|
-
createSplitNode({
|
|
559
|
-
direction,
|
|
560
|
-
sourceNode,
|
|
561
|
-
targetNode,
|
|
562
|
-
ratio = 0.5
|
|
563
|
-
}) {
|
|
564
|
-
switch (direction) {
|
|
565
|
-
case "left": {
|
|
566
|
-
return {
|
|
567
|
-
id: crypto.randomUUID(),
|
|
568
|
-
type: "split",
|
|
569
|
-
orientation: "horizontal",
|
|
570
|
-
ratio,
|
|
571
|
-
left: sourceNode,
|
|
572
|
-
right: targetNode
|
|
573
|
-
};
|
|
574
|
-
}
|
|
575
|
-
case "right": {
|
|
576
|
-
return {
|
|
577
|
-
id: crypto.randomUUID(),
|
|
578
|
-
type: "split",
|
|
579
|
-
orientation: "horizontal",
|
|
580
|
-
ratio,
|
|
581
|
-
left: targetNode,
|
|
582
|
-
right: sourceNode
|
|
583
|
-
};
|
|
584
|
-
}
|
|
585
|
-
case "top": {
|
|
586
|
-
return {
|
|
587
|
-
id: crypto.randomUUID(),
|
|
588
|
-
type: "split",
|
|
589
|
-
orientation: "vertical",
|
|
590
|
-
ratio,
|
|
591
|
-
left: sourceNode,
|
|
592
|
-
right: targetNode
|
|
593
|
-
};
|
|
594
|
-
}
|
|
595
|
-
case "bottom": {
|
|
596
|
-
return {
|
|
597
|
-
id: crypto.randomUUID(),
|
|
598
|
-
type: "split",
|
|
599
|
-
orientation: "vertical",
|
|
600
|
-
ratio,
|
|
601
|
-
left: targetNode,
|
|
602
|
-
right: sourceNode
|
|
603
|
-
};
|
|
604
|
-
}
|
|
605
|
-
default: {
|
|
606
|
-
assertNever(direction);
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
setSplitRatio(id, ratio) {
|
|
611
|
-
const splitNode = this._tree.findNode(id);
|
|
612
|
-
invariant(splitNode !== null, "Node is not null");
|
|
613
|
-
invariant(splitNode.type === "split", "Node is a split");
|
|
614
|
-
if (splitNode.orientation === "horizontal") {
|
|
615
|
-
const totalWidth = this.getSurroundingRect(splitNode.left.id).width + this._options.gap + this.getSurroundingRect(splitNode.right.id).width;
|
|
616
|
-
const minLeftWidth = calculateMinSize(
|
|
617
|
-
splitNode.left,
|
|
618
|
-
this._options.gap
|
|
619
|
-
).width;
|
|
620
|
-
const minRightWidth = calculateMinSize(
|
|
621
|
-
splitNode.right,
|
|
622
|
-
this._options.gap
|
|
623
|
-
).width;
|
|
624
|
-
const minRatio = (minLeftWidth + this._options.gap / 2) / totalWidth;
|
|
625
|
-
const maxRatio = (totalWidth - (minRightWidth + this._options.gap / 2)) / totalWidth;
|
|
626
|
-
splitNode.ratio = clamp(ratio, minRatio, maxRatio);
|
|
627
|
-
} else if (splitNode.orientation === "vertical") {
|
|
628
|
-
const totalHeight = this.getSurroundingRect(splitNode.left.id).height + this._options.gap + this.getSurroundingRect(splitNode.right.id).height;
|
|
629
|
-
const minTopHeight = calculateMinSize(
|
|
630
|
-
splitNode.left,
|
|
631
|
-
this._options.gap
|
|
632
|
-
).height;
|
|
633
|
-
const minBottomHeight = calculateMinSize(
|
|
634
|
-
splitNode.right,
|
|
635
|
-
this._options.gap
|
|
636
|
-
).height;
|
|
637
|
-
const minRatio = (minTopHeight + this._options.gap / 2) / totalHeight;
|
|
638
|
-
const maxRatio = (totalHeight - (minBottomHeight + this._options.gap / 2)) / totalHeight;
|
|
639
|
-
splitNode.ratio = clamp(ratio, minRatio, maxRatio);
|
|
640
|
-
} else {
|
|
641
|
-
assertNever(splitNode.orientation);
|
|
642
|
-
}
|
|
643
|
-
this.syncLayoutRects();
|
|
644
|
-
}
|
|
645
|
-
findRect(id) {
|
|
646
|
-
return _nullishCoalesce(this._layoutRects.find((rect) => rect.id === id), () => ( null));
|
|
647
|
-
}
|
|
648
|
-
getSurroundingRect(id) {
|
|
649
|
-
const node = this._tree.findNode(id);
|
|
650
|
-
invariant(node !== null, "Node is not null");
|
|
651
|
-
if (node.type === "panel") {
|
|
652
|
-
const rect = this.findRect(id);
|
|
653
|
-
invariant(rect !== null, "Rect is not null");
|
|
654
|
-
invariant(rect.type === "panel", "Rect is a panel");
|
|
655
|
-
return {
|
|
656
|
-
x: rect.x,
|
|
657
|
-
y: rect.y,
|
|
658
|
-
width: rect.width,
|
|
659
|
-
height: rect.height
|
|
660
|
-
};
|
|
661
|
-
}
|
|
662
|
-
const leftRect = this.getSurroundingRect(node.left.id);
|
|
663
|
-
const rightRect = this.getSurroundingRect(node.right.id);
|
|
664
|
-
if (node.orientation === "horizontal") {
|
|
665
|
-
return {
|
|
666
|
-
x: leftRect.x,
|
|
667
|
-
y: leftRect.y,
|
|
668
|
-
width: leftRect.width + this._options.gap + rightRect.width,
|
|
669
|
-
height: leftRect.height
|
|
670
|
-
};
|
|
671
|
-
} else if (node.orientation === "vertical") {
|
|
672
|
-
return {
|
|
673
|
-
x: leftRect.x,
|
|
674
|
-
y: leftRect.y,
|
|
675
|
-
width: leftRect.width,
|
|
676
|
-
height: leftRect.height + this._options.gap + rightRect.height
|
|
677
|
-
};
|
|
678
|
-
} else {
|
|
679
|
-
assertNever(node.orientation);
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
getSplitChildRects(splitId) {
|
|
683
|
-
const node = this._tree.findNode(splitId);
|
|
684
|
-
invariant(node !== null && node.type === "split");
|
|
685
|
-
return {
|
|
686
|
-
left: this.getSurroundingRect(node.left.id),
|
|
687
|
-
right: this.getSurroundingRect(node.right.id)
|
|
688
|
-
};
|
|
689
|
-
}
|
|
690
|
-
}, _class3);
|
|
691
|
-
|
|
692
|
-
// src/useDockLayout.ts
|
|
693
|
-
function useDockLayout(initialRoot, options) {
|
|
694
|
-
const [layoutManager] = _react.useState.call(void 0, () => {
|
|
695
|
-
return new LayoutManager(initialRoot, options);
|
|
696
|
-
});
|
|
697
|
-
const containerRef = _react.useRef.call(void 0, null);
|
|
698
|
-
const layoutRects = _react.useSyncExternalStore.call(void 0,
|
|
699
|
-
layoutManager.subscribe,
|
|
700
|
-
() => layoutManager.layoutRects
|
|
701
|
-
);
|
|
702
|
-
const [resizingRect, setResizingRect] = _react.useState.call(void 0,
|
|
703
|
-
null
|
|
704
|
-
);
|
|
705
|
-
const [draggingRect, setDraggingRect] = _react.useState.call(void 0,
|
|
706
|
-
null
|
|
707
|
-
);
|
|
708
|
-
const [dropTarget, setDropTarget] = _react.useState.call(void 0, null);
|
|
709
|
-
_react.useLayoutEffect.call(void 0, () => {
|
|
710
|
-
const container = containerRef.current;
|
|
711
|
-
invariant(container !== null);
|
|
712
|
-
layoutManager.setSize({
|
|
713
|
-
width: container.clientWidth,
|
|
714
|
-
height: container.clientHeight
|
|
715
|
-
});
|
|
716
|
-
const resizeObserver = new ResizeObserver((entries) => {
|
|
717
|
-
for (const entry of entries) {
|
|
718
|
-
layoutManager.setSize({
|
|
719
|
-
width: entry.contentRect.width,
|
|
720
|
-
height: entry.contentRect.height
|
|
721
|
-
});
|
|
722
|
-
}
|
|
723
|
-
});
|
|
724
|
-
resizeObserver.observe(container);
|
|
725
|
-
return () => {
|
|
726
|
-
resizeObserver.disconnect();
|
|
727
|
-
};
|
|
728
|
-
}, [layoutManager]);
|
|
729
|
-
_react.useEffect.call(void 0, () => {
|
|
730
|
-
if (resizingRect === null) {
|
|
731
|
-
return;
|
|
732
|
-
}
|
|
733
|
-
function handleMouseMove(event) {
|
|
734
|
-
invariant(resizingRect !== null);
|
|
735
|
-
layoutManager.resizePanel(resizingRect.id, {
|
|
736
|
-
x: event.clientX,
|
|
737
|
-
y: event.clientY
|
|
738
|
-
});
|
|
739
|
-
}
|
|
740
|
-
function handleMouseUp() {
|
|
741
|
-
setResizingRect(null);
|
|
742
|
-
}
|
|
743
|
-
document.addEventListener("mousemove", handleMouseMove);
|
|
744
|
-
document.addEventListener("mouseup", handleMouseUp);
|
|
745
|
-
return () => {
|
|
746
|
-
document.removeEventListener("mousemove", handleMouseMove);
|
|
747
|
-
document.removeEventListener("mouseup", handleMouseUp);
|
|
748
|
-
};
|
|
749
|
-
}, [resizingRect, layoutManager]);
|
|
750
|
-
_react.useEffect.call(void 0, () => {
|
|
751
|
-
document.body.style.cursor = resizingRect === null ? "default" : CURSORS[resizingRect.orientation];
|
|
752
|
-
}, [resizingRect]);
|
|
753
|
-
return {
|
|
754
|
-
containerRef,
|
|
755
|
-
layoutRects,
|
|
756
|
-
layoutManager,
|
|
757
|
-
getRectProps: (rect) => {
|
|
758
|
-
if (rect.type === "split") {
|
|
759
|
-
return {
|
|
760
|
-
style: {
|
|
761
|
-
position: "absolute",
|
|
762
|
-
left: rect.x,
|
|
763
|
-
top: rect.y,
|
|
764
|
-
width: rect.width,
|
|
765
|
-
height: rect.height,
|
|
766
|
-
cursor: CURSORS[rect.orientation]
|
|
767
|
-
},
|
|
768
|
-
onMouseDown: () => {
|
|
769
|
-
setResizingRect(rect);
|
|
770
|
-
},
|
|
771
|
-
onMouseUp: () => {
|
|
772
|
-
setResizingRect(null);
|
|
773
|
-
}
|
|
774
|
-
};
|
|
775
|
-
} else if (rect.type === "panel") {
|
|
776
|
-
return {
|
|
777
|
-
style: {
|
|
778
|
-
position: "absolute",
|
|
779
|
-
left: rect.x,
|
|
780
|
-
top: rect.y,
|
|
781
|
-
width: rect.width,
|
|
782
|
-
height: rect.height
|
|
783
|
-
},
|
|
784
|
-
onMouseMove: (event) => {
|
|
785
|
-
if (draggingRect === null) {
|
|
786
|
-
return;
|
|
787
|
-
}
|
|
788
|
-
if (draggingRect.id === rect.id) {
|
|
789
|
-
setDropTarget(null);
|
|
790
|
-
return;
|
|
791
|
-
}
|
|
792
|
-
const dropTarget2 = layoutManager.calculateDropTarget({
|
|
793
|
-
draggedPanelId: draggingRect.id,
|
|
794
|
-
targetPanelId: rect.id,
|
|
795
|
-
point: {
|
|
796
|
-
x: event.clientX,
|
|
797
|
-
y: event.clientY
|
|
798
|
-
}
|
|
799
|
-
});
|
|
800
|
-
setDropTarget(dropTarget2);
|
|
801
|
-
},
|
|
802
|
-
onMouseUp: (event) => {
|
|
803
|
-
if (draggingRect === null) {
|
|
804
|
-
return;
|
|
805
|
-
}
|
|
806
|
-
if (draggingRect.id === rect.id) {
|
|
807
|
-
setDraggingRect(null);
|
|
808
|
-
setDropTarget(null);
|
|
809
|
-
return;
|
|
810
|
-
}
|
|
811
|
-
layoutManager.movePanel({
|
|
812
|
-
sourceId: draggingRect.id,
|
|
813
|
-
targetId: rect.id,
|
|
814
|
-
point: {
|
|
815
|
-
x: event.clientX,
|
|
816
|
-
y: event.clientY
|
|
817
|
-
}
|
|
818
|
-
});
|
|
819
|
-
setDraggingRect(null);
|
|
820
|
-
setDropTarget(null);
|
|
821
|
-
}
|
|
822
|
-
};
|
|
823
|
-
} else {
|
|
824
|
-
assertNever(rect);
|
|
825
|
-
}
|
|
826
|
-
},
|
|
827
|
-
getDropZoneProps: (rect) => {
|
|
828
|
-
if (draggingRect === null) {
|
|
829
|
-
return null;
|
|
830
|
-
}
|
|
831
|
-
const isDropTargetRect = rect.id === _optionalChain([dropTarget, 'optionalAccess', _9 => _9.id]);
|
|
832
|
-
if (!isDropTargetRect) {
|
|
833
|
-
return null;
|
|
834
|
-
}
|
|
835
|
-
return {
|
|
836
|
-
style: getDropZoneStyle(dropTarget.direction)
|
|
837
|
-
};
|
|
838
|
-
},
|
|
839
|
-
getDragHandleProps: (rect) => {
|
|
840
|
-
return {
|
|
841
|
-
onMouseDown: () => {
|
|
842
|
-
setDraggingRect(rect);
|
|
843
|
-
}
|
|
844
|
-
};
|
|
845
|
-
},
|
|
846
|
-
draggingRect
|
|
847
|
-
};
|
|
848
|
-
}
|
|
849
|
-
function getDropZoneStyle(direction) {
|
|
850
|
-
if (direction === "top") {
|
|
851
|
-
return {
|
|
852
|
-
position: "absolute",
|
|
853
|
-
left: 0,
|
|
854
|
-
top: 0,
|
|
855
|
-
width: "100%",
|
|
856
|
-
height: "50%"
|
|
857
|
-
};
|
|
858
|
-
} else if (direction === "bottom") {
|
|
859
|
-
return {
|
|
860
|
-
position: "absolute",
|
|
861
|
-
left: 0,
|
|
862
|
-
top: "50%",
|
|
863
|
-
width: "100%",
|
|
864
|
-
height: "50%"
|
|
865
|
-
};
|
|
866
|
-
} else if (direction === "left") {
|
|
867
|
-
return {
|
|
868
|
-
position: "absolute",
|
|
869
|
-
left: 0,
|
|
870
|
-
top: 0,
|
|
871
|
-
width: "50%",
|
|
872
|
-
height: "100%"
|
|
873
|
-
};
|
|
874
|
-
} else if (direction === "right") {
|
|
875
|
-
return {
|
|
876
|
-
position: "absolute",
|
|
877
|
-
left: "50%",
|
|
878
|
-
top: 0,
|
|
879
|
-
width: "50%",
|
|
880
|
-
height: "100%"
|
|
881
|
-
};
|
|
882
|
-
} else {
|
|
883
|
-
assertNever(direction);
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
var CURSORS = {
|
|
887
|
-
horizontal: "col-resize",
|
|
888
|
-
vertical: "row-resize"
|
|
889
|
-
};
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
exports.bspStrategy = bspStrategy; exports.evenlyDividedHorizontalStrategy = evenlyDividedHorizontalStrategy; exports.useDockLayout = useDockLayout;
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3;function a(r){throw new Error(`Unexpected value: ${r}`)}function R(r,t){return r===null?null:S(t,r)}function S(r,t){if(t.type==="panel")return null;if(t.type==="split")return t.left.id===r||t.right.id===r?t:_nullishCoalesce(S(r,t.left), () => (S(r,t.right)));a(t)}var M={getPlacement(r){let t=m(r)+1;return{targetId:r.id,direction:"right",ratio:t/(t+1)}}};function m(r){if(r.type==="panel")return 0;if(r.type==="split"){if(r.orientation==="horizontal")return 1+m(r.left)+m(r.right);if(r.orientation==="vertical")return 0+m(r.left)+m(r.right);a(r.orientation)}else a(r)}var X={getPlacement(r){let t=z(r),e=R(r,t.id);return{targetId:t.id,direction:e===null?"right":e.orientation==="horizontal"?"bottom":"right",ratio:.5}}};function z(r){if(r.type==="panel")return r;if(r.type==="split")return z(r.right);a(r)}var _react = require('react');function u(r,t){if(!r)throw new Error(_nullishCoalesce(t, () => ("Invariant failed")))}function w(r,t,e){return Math.max(t,Math.min(e,r))}var N= (_class =class{constructor() { _class.prototype.__init.call(this); }__init() {this._listeners=new Set}subscribe(t){return this._listeners.add(t),()=>{this._listeners.delete(t)}}emit(){this._listeners.forEach(t=>{t()})}}, _class);function P(r,t){if(r===null)return[];let e=[],n=(o,i)=>{o.type==="split"?o.orientation==="horizontal"?(e.push({id:o.id,type:"split",orientation:o.orientation,x:Math.round(i.x+i.width*o.ratio-t.gap/2),y:Math.round(i.y),width:Math.round(t.gap),height:Math.round(i.height)}),n(o.left,{x:i.x,y:i.y,width:i.width*o.ratio-t.gap/2,height:i.height}),n(o.right,{x:i.x+i.width*o.ratio+t.gap/2,y:i.y,width:i.width*(1-o.ratio)-t.gap/2,height:i.height})):o.orientation==="vertical"?(e.push({id:o.id,type:"split",orientation:o.orientation,x:Math.round(i.x),y:Math.round(i.y+i.height*o.ratio-t.gap/2),width:Math.round(i.width),height:Math.round(t.gap)}),n(o.left,{x:i.x,y:i.y,width:i.width,height:i.height*o.ratio-t.gap/2}),n(o.right,{x:i.x,y:i.y+i.height*o.ratio+t.gap/2,width:i.width,height:i.height*(1-o.ratio)-t.gap/2})):a(o.orientation):o.type==="panel"?e.push({id:o.id,type:"panel",x:Math.round(i.x),y:Math.round(i.y),width:Math.round(i.width),height:Math.round(i.height)}):a(o)};return n(r,{x:0,y:0,width:t.size.width,height:t.size.height}),e}function c(r,t){if(r.type==="panel")return{width:_nullishCoalesce(_optionalChain([r, 'access', _2 => _2.minSize, 'optionalAccess', _3 => _3.width]), () => (0)),height:_nullishCoalesce(_optionalChain([r, 'access', _4 => _4.minSize, 'optionalAccess', _5 => _5.height]), () => (0))};if(r.type==="split"){if(r.orientation==="horizontal")return{width:c(r.left,t).width+t+c(r.right,t).width,height:Math.max(c(r.left,t).height,c(r.right,t).height)};if(r.orientation==="vertical")return{width:Math.max(c(r.left,t).width,c(r.right,t).width),height:c(r.left,t).height+t+c(r.right,t).height};a(r.orientation)}else a(r)}function x(r,t){let e=r.x+r.width/2,n=r.y+r.height/2,o=(t.x-e)/(r.width/2),i=(t.y-n)/(r.height/2);return Math.abs(o)>Math.abs(i)?o>0?"right":"left":i>0?"bottom":"top"}var _= (_class2 =class{__init2() {this._root=null}constructor(t){;_class2.prototype.__init2.call(this);this._root=t}get root(){return this._root}set root(t){this._root=t}findNode(t){return this._root===null?null:this.findNodeInSubTree(t,this._root)}findNodeInSubTree(t,e){if(t===e.id)return e;if(e.type==="panel")return null;if(e.type==="split")return _nullishCoalesce(this.findNodeInSubTree(t,e.left), () => (this.findNodeInSubTree(t,e.right)));a(e)}findParentNode(t){return R(this._root,t)}replaceChildNode({parentId:t,oldChildId:e,newChild:n}){let o=this.findNode(t);if(o===null)throw new Error(`Parent node with id ${t} not found`);if(o.type!=="split")throw new Error(`Parent node with id ${t} is not a split node`);if(this.findNode(e)===null)throw new Error(`Child node with id ${e} not found`);if(o.left.id===e)o.left=n;else if(o.right.id===e)o.right=n;else throw new Error(`Child node with id ${e} is not a child of the parent node with id ${t}`)}}, _class2);var L= (_class3 =class{__init3() {this._eventEmitter=new N}__init4() {this._layoutRects=[]}__init5() {this._addPanelStrategy=M}constructor(t,e){;_class3.prototype.__init3.call(this);_class3.prototype.__init4.call(this);_class3.prototype.__init5.call(this);_class3.prototype.__init6.call(this);this._tree=new _(t),this._options={gap:_nullishCoalesce(_optionalChain([e, 'optionalAccess', _6 => _6.gap]), () => (10)),size:_nullishCoalesce(_optionalChain([e, 'optionalAccess', _7 => _7.size]), () => ({width:0,height:0}))},this._layoutRects=P(t,this._options)}get root(){return this._tree.root}set root(t){this._tree.root=t,this.syncLayoutRects()}get layoutRects(){return this._layoutRects}__init6() {this.subscribe=t=>this._eventEmitter.subscribe(t)}setSize(t){this._options.size=t,this.syncLayoutRects()}removePanel(t){if(this._tree.root===null)throw new Error("Root node is null");let e=this._tree.findNode(t);if(e===null)throw new Error(`Node with id ${t} not found`);if(e.type!=="panel")throw new Error(`Node with id ${t} is not a panel`);if(e.id===this._tree.root.id){this._tree.root=null,this.syncLayoutRects();return}let n=this._tree.findParentNode(t);u(n!==null,"Parent node is not null");let o=n.left.id===e.id?n.right:n.left;if(n.id===this._tree.root.id){this._tree.root=o,this.syncLayoutRects();return}let i=this._tree.findParentNode(n.id);u(i!==null,"Grand parent node is not null"),this._tree.replaceChildNode({parentId:i.id,oldChildId:n.id,newChild:o}),this.syncLayoutRects()}movePanel({sourceId:t,targetId:e,point:n}){if(this._tree.root===null)throw new Error("Root node is null");if(this._tree.root.type!=="split")throw new Error("Root node is not a split node");let o=this._tree.findNode(t);if(o===null)throw new Error(`Node with id ${t} not found`);if(o.type!=="panel")throw new Error(`Node with id ${t} is not a panel node`);let i=this._tree.findParentNode(t);u(i!==null);let h=this._tree.findNode(e);if(h===null)throw new Error(`Node with id ${e} not found`);if(h.type!=="panel")throw new Error(`Node with id ${e} is not a panel node`);let l=i.left.id===t?i.right:i.left,d=this.findRect(e);u(d!==null),u(d.type==="panel");let f=x(d,n);if(l.id===e){f==="left"?(i.orientation="horizontal",i.left=o,i.right=h):f==="right"?(i.orientation="horizontal",i.left=h,i.right=o):f==="top"?(i.orientation="vertical",i.left=o,i.right=h):f==="bottom"?(i.orientation="vertical",i.left=h,i.right=o):a(f),this.syncLayoutRects();return}let g=this._tree.findParentNode(i.id);g===null?this._tree.root=l:g.right.id===i.id?g.right=l:g.left.id===i.id&&(g.left=l);let s=this._tree.findParentNode(e);u(s!==null);let p=this.createSplitNode({direction:f,sourceNode:o,targetNode:h});s.left.id===e?s.left=p:s.right.id===e?s.right=p:u(!1),this.syncLayoutRects()}resizePanel(t,e){if(this._tree.root===null)throw new Error("Root node is null");let n=this.findRect(t);if(n===null)throw new Error(`Rect with id ${t} not found`);if(n.type!=="split")throw new Error(`Rect with id ${t} is not a split node`);if(n.orientation==="horizontal"){let{left:o,right:i}=this.getSplitChildRects(n.id),h=e.x-o.x,l=o.width+n.width+i.width,d=w(h/l,.1,.9);this.setSplitRatio(n.id,d)}else if(n.orientation==="vertical"){let{left:o,right:i}=this.getSplitChildRects(n.id),h=e.y-o.y,l=o.height+n.height+i.height,d=w(h/l,.1,.9);this.setSplitRatio(n.id,d)}else a(n.orientation)}addPanel(t){let e=_nullishCoalesce(_optionalChain([t, 'optionalAccess', _8 => _8.id]), () => (crypto.randomUUID()));if(this._tree.root===null){this._tree.root={id:e,type:"panel"},this.syncLayoutRects();return}let n=_optionalChain([t, 'optionalAccess', _9 => _9.targetId])===void 0,{targetId:o,direction:i="right",ratio:h=.5}=n?this._addPanelStrategy.getPlacement(this._tree.root):t;if(u(o!==void 0,"targetId is not undefined"),o===this._tree.root.id){this._tree.root=this.createSplitNode({direction:i,ratio:h,sourceNode:{id:e,type:"panel"},targetNode:this._tree.root}),this.syncLayoutRects();return}let l=this._tree.findNode(o);if(l===null)throw new Error(`Node with id ${o} not found`);let d=this._tree.findParentNode(o);u(d!==null,"Target node parent is not null");let f=this.createSplitNode({direction:i,sourceNode:{id:e,type:"panel"},targetNode:l,ratio:h});this._tree.replaceChildNode({parentId:d.id,oldChildId:o,newChild:f}),this.syncLayoutRects()}calculateDropTarget({draggedPanelId:t,targetPanelId:e,point:n}){u(t!==e,"Dragged panel id is not the same as target panel id");let o=this.findRect(e);return u(o!==null&&o.type==="panel"),{id:e,direction:x(o,n)}}serialize(){return JSON.stringify({root:this._tree.root,options:{gap:this._options.gap}})}emit(){this._eventEmitter.emit()}syncLayoutRects(){this._layoutRects=P(this._tree.root,this._options),this.emit()}createSplitNode({direction:t,sourceNode:e,targetNode:n,ratio:o=.5}){switch(t){case"left":return{id:crypto.randomUUID(),type:"split",orientation:"horizontal",ratio:o,left:e,right:n};case"right":return{id:crypto.randomUUID(),type:"split",orientation:"horizontal",ratio:o,left:n,right:e};case"top":return{id:crypto.randomUUID(),type:"split",orientation:"vertical",ratio:o,left:e,right:n};case"bottom":return{id:crypto.randomUUID(),type:"split",orientation:"vertical",ratio:o,left:n,right:e};default:a(t)}}setSplitRatio(t,e){let n=this._tree.findNode(t);if(u(n!==null,"Node is not null"),u(n.type==="split","Node is a split"),n.orientation==="horizontal"){let o=this.getSurroundingRect(n.left.id).width+this._options.gap+this.getSurroundingRect(n.right.id).width,i=c(n.left,this._options.gap).width,h=c(n.right,this._options.gap).width,l=(i+this._options.gap/2)/o,d=(o-(h+this._options.gap/2))/o;n.ratio=w(e,l,d)}else if(n.orientation==="vertical"){let o=this.getSurroundingRect(n.left.id).height+this._options.gap+this.getSurroundingRect(n.right.id).height,i=c(n.left,this._options.gap).height,h=c(n.right,this._options.gap).height,l=(i+this._options.gap/2)/o,d=(o-(h+this._options.gap/2))/o;n.ratio=w(e,l,d)}else a(n.orientation);this.syncLayoutRects()}findRect(t){return _nullishCoalesce(this._layoutRects.find(e=>e.id===t), () => (null))}getSurroundingRect(t){let e=this._tree.findNode(t);if(u(e!==null,"Node is not null"),e.type==="panel"){let i=this.findRect(t);return u(i!==null,"Rect is not null"),u(i.type==="panel","Rect is a panel"),{x:i.x,y:i.y,width:i.width,height:i.height}}let n=this.getSurroundingRect(e.left.id),o=this.getSurroundingRect(e.right.id);if(e.orientation==="horizontal")return{x:n.x,y:n.y,width:n.width+this._options.gap+o.width,height:n.height};if(e.orientation==="vertical")return{x:n.x,y:n.y,width:n.width,height:n.height+this._options.gap+o.height};a(e.orientation)}getSplitChildRects(t){let e=this._tree.findNode(t);return u(e!==null&&e.type==="split"),{left:this.getSurroundingRect(e.left.id),right:this.getSurroundingRect(e.right.id)}}}, _class3);function ft(r,t){let[e]=_react.useState.call(void 0, ()=>new L(r,t)),n=_react.useRef.call(void 0, null),o=_react.useSyncExternalStore.call(void 0, e.subscribe,()=>e.layoutRects),[i,h]=_react.useState.call(void 0, null),[l,d]=_react.useState.call(void 0, null),[f,g]=_react.useState.call(void 0, null);return _react.useLayoutEffect.call(void 0, ()=>{let s=n.current;u(s!==null),e.setSize({width:s.clientWidth,height:s.clientHeight});let p=new ResizeObserver(y=>{for(let b of y)e.setSize({width:b.contentRect.width,height:b.contentRect.height})});return p.observe(s),()=>{p.disconnect()}},[e]),_react.useEffect.call(void 0, ()=>{if(i===null)return;function s(y){u(i!==null),e.resizePanel(i.id,{x:y.clientX,y:y.clientY})}function p(){h(null)}return document.addEventListener("mousemove",s),document.addEventListener("mouseup",p),()=>{document.removeEventListener("mousemove",s),document.removeEventListener("mouseup",p)}},[i,e]),_react.useEffect.call(void 0, ()=>{document.body.style.cursor=i===null?"default":D[i.orientation]},[i]),{containerRef:n,layoutRects:o,layoutManager:e,getRectProps:s=>{if(s.type==="split")return{style:{position:"absolute",left:s.x,top:s.y,width:s.width,height:s.height,cursor:D[s.orientation]},onMouseDown:()=>{h(s)},onMouseUp:()=>{h(null)}};if(s.type==="panel")return{style:{position:"absolute",left:s.x,top:s.y,width:s.width,height:s.height},onMouseMove:p=>{if(l===null)return;if(l.id===s.id){g(null);return}let y=e.calculateDropTarget({draggedPanelId:l.id,targetPanelId:s.id,point:{x:p.clientX,y:p.clientY}});g(y)},onMouseUp:p=>{if(l!==null){if(l.id===s.id){d(null),g(null);return}e.movePanel({sourceId:l.id,targetId:s.id,point:{x:p.clientX,y:p.clientY}}),d(null),g(null)}}};a(s)},getDropZoneProps:s=>l===null||!(s.id===_optionalChain([f, 'optionalAccess', _10 => _10.id]))?null:{style:$(f.direction)},getDragHandleProps:s=>({onMouseDown:()=>{d(s)}}),draggingRect:l}}function $(r){if(r==="top")return{position:"absolute",left:0,top:0,width:"100%",height:"50%"};if(r==="bottom")return{position:"absolute",left:0,top:"50%",width:"100%",height:"50%"};if(r==="left")return{position:"absolute",left:0,top:0,width:"50%",height:"100%"};if(r==="right")return{position:"absolute",left:"50%",top:0,width:"50%",height:"100%"};a(r)}var D={horizontal:"col-resize",vertical:"row-resize"};exports.bspStrategy = X; exports.evenlyDividedHorizontalStrategy = M; exports.useDockLayout = ft;
|