-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathinsert_child.ts
More file actions
136 lines (123 loc) · 4.88 KB
/
insert_child.ts
File metadata and controls
136 lines (123 loc) · 4.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
// ░░░░░░░░▄▀░█▀▄░█▀▀░█▀▀░█░█░█░░░█▀█░█▀▄░░░░░█░░░█▀█░█░█░█▀█░█░█░▀█▀░▀▄░░░░░░░░
// ░░░░░░░▀▄░░█▀▄░█▀▀░█░█░█░█░█░░░█▀█░█▀▄░▀▀▀░█░░░█▀█░░█░░█░█░█░█░░█░░░▄▀░░░░░░░
// ░░░░░░░░░▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░▀▀▀░▀░▀░▀░▀░░░░░▀▀▀░▀░▀░░▀░░▀▀▀░▀▀▀░░▀░░▀░░░░░░░░░
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ * Copyright (c) 2026, the Regular Layout Authors. This file is part * ┃
// ┃ * of the Regular Layout library, distributed under the terms of the * ┃
// ┃ * [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). * ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
import type { Layout } from "./layout_config.ts";
/**
* Inserts a new child panel into the layout tree at a specified location.
* Creates a split panel if necessary and redistributes sizes equally among all
* children.
*
* @param panel - The root layout tree to insert into
* @param child - Unique identifier for the new child panel
* @param path - Array of indices defining where to insert. Empty array inserts
* at root level.
* @param orientation - Orientation for newly created split panels. Defaults to
* "horizontal".
* @returns A new layout tree with the child inserted (original is not mutated).
*/
export function insert_child(
panel: Layout,
child: string,
path: number[],
orientation: "horizontal" | "vertical" = "horizontal",
is_edge?: boolean,
): Layout {
if (path.length === 0) {
// Insert at root level
if (panel.type === "child-panel") {
// Add to existing child-panel as a tab
return {
type: "child-panel",
child: [child, ...panel.child],
};
} else {
// Append to existing split-panel
const newChildren = [
...panel.children,
{
type: "child-panel",
child: [child],
} as Layout,
];
const numChildren = newChildren.length;
const newSizes = Array(numChildren).fill(1 / numChildren);
return {
...panel,
children: newChildren,
sizes: newSizes,
};
}
}
// Navigate down the path
const [index, ...restPath] = path;
if (panel.type === "child-panel") {
// This shouldn't happen if path.length > 0, but handle it gracefully
// We need to split this child-panel
const newPanel: Layout = {
type: "split-panel",
orientation,
children: [panel],
sizes: [1],
};
return insert_child(newPanel, child, path, orientation, is_edge);
}
if (restPath.length === 0 || index === panel.children.length) {
if (is_edge && panel.children[index]?.type === "child-panel") {
panel.children[index].child.unshift(child);
panel.children[index].selected = 0;
return panel;
}
// Insert at this level at the specified index
const newChildren = [...panel.children];
newChildren.splice(index, 0, {
type: "child-panel",
child: [child],
});
const numChildren = newChildren.length;
const newSizes = Array(numChildren).fill(1 / numChildren);
return {
...panel,
children: newChildren,
sizes: newSizes,
};
}
const targetChild = panel.children[index];
if (targetChild.type === "child-panel" && restPath.length > 0) {
// Need to split this child-panel
const oppositeOrientation =
panel.orientation === "horizontal" ? "vertical" : "horizontal";
const newSplitPanel = insert_child(
targetChild,
child,
restPath,
oppositeOrientation,
is_edge,
);
const newChildren = [...panel.children];
newChildren[index] = newSplitPanel;
return {
...panel,
children: newChildren,
};
}
const updatedChild = insert_child(
targetChild,
child,
restPath,
orientation,
is_edge,
);
const newChildren = [...panel.children];
newChildren[index] = updatedChild;
return {
...panel,
children: newChildren,
};
}