regular-layout 0.0.2 → 0.2.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.
- package/LICENSE.md +1 -1
- package/README.md +20 -6
- package/dist/extensions.d.ts +10 -11
- package/dist/index.d.ts +3 -3
- package/dist/index.js +15 -10
- package/dist/index.js.map +4 -4
- package/dist/{common/calculate_split.d.ts → layout/calculate_edge.d.ts} +2 -2
- package/dist/{common → layout}/calculate_intersect.d.ts +7 -9
- package/dist/layout/constants.d.ts +43 -0
- package/dist/{common → layout}/flatten.d.ts +1 -1
- package/dist/{common → layout}/generate_grid.d.ts +3 -3
- package/dist/layout/generate_overlay.d.ts +2 -0
- package/dist/{common → layout}/insert_child.d.ts +3 -2
- package/dist/{common → layout}/redistribute_panel_sizes.d.ts +1 -1
- package/dist/{common → layout}/remove_child.d.ts +1 -1
- package/dist/{common/layout_config.d.ts → layout/types.d.ts} +9 -31
- package/dist/regular-layout-frame.d.ts +2 -2
- package/dist/regular-layout-tab.d.ts +26 -0
- package/dist/regular-layout.d.ts +61 -27
- package/package.json +9 -6
- package/src/extensions.ts +25 -15
- package/src/index.ts +3 -7
- package/src/layout/calculate_edge.ts +209 -0
- package/src/{common → layout}/calculate_intersect.ts +61 -100
- package/src/layout/constants.ts +63 -0
- package/src/{common → layout}/flatten.ts +2 -1
- package/src/{common → layout}/generate_grid.ts +77 -106
- package/src/{common → layout}/generate_overlay.ts +27 -12
- package/src/{common → layout}/insert_child.ts +105 -50
- package/src/{common → layout}/redistribute_panel_sizes.ts +2 -4
- package/src/{common → layout}/remove_child.ts +3 -2
- package/src/{common/layout_config.ts → layout/types.ts} +9 -44
- package/src/regular-layout-frame.ts +83 -68
- package/src/regular-layout-tab.ts +103 -0
- package/src/regular-layout.ts +257 -175
- package/themes/chicago.css +89 -0
- package/themes/fluxbox.css +110 -0
- package/themes/gibson.css +264 -0
- package/themes/hotdog.css +88 -0
- package/themes/lorax.css +129 -0
- package/dist/common/generate_overlay.d.ts +0 -2
- package/src/common/calculate_split.ts +0 -185
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
|
|
2
|
+
// ░░░░░░░░▄▀░█▀▄░█▀▀░█▀▀░█░█░█░░░█▀█░█▀▄░░░░░█░░░█▀█░█░█░█▀█░█░█░▀█▀░▀▄░░░░░░░░
|
|
3
|
+
// ░░░░░░░▀▄░░█▀▄░█▀▀░█░█░█░█░█░░░█▀█░█▀▄░▀▀▀░█░░░█▀█░░█░░█░█░█░█░░█░░░▄▀░░░░░░░
|
|
4
|
+
// ░░░░░░░░░▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░▀▀▀░▀░▀░▀░▀░░░░░▀▀▀░▀░▀░░▀░░▀▀▀░▀▀▀░░▀░░▀░░░░░░░░░
|
|
5
|
+
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
|
|
6
|
+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
7
|
+
// ┃ * Copyright (c) 2026, the Regular Layout Authors. This file is part * ┃
|
|
8
|
+
// ┃ * of the Regular Layout library, distributed under the terms of the * ┃
|
|
9
|
+
// ┃ * [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). * ┃
|
|
10
|
+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
11
|
+
|
|
12
|
+
import { SPLIT_EDGE_TOLERANCE, SPLIT_ROOT_EDGE_TOLERANCE } from "./constants";
|
|
13
|
+
import { insert_child } from "./insert_child";
|
|
14
|
+
import type { Layout, LayoutPath, Orientation, ViewWindow } from "./types";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Calculates an insertion point (which may involve splitting a single
|
|
18
|
+
* `"child-panel"` into a new `"split-panel"`), based on the cursor position.
|
|
19
|
+
* *
|
|
20
|
+
* @param col - The cursor column.
|
|
21
|
+
* @param row - The cursor row.
|
|
22
|
+
* @param panel - The `Layout` to insert into.
|
|
23
|
+
* @param slot - The slot identifier where the insert should occur
|
|
24
|
+
* @param drop_target - The `LayoutPath` (from `calculateIntersect`) of the
|
|
25
|
+
* panel to either insert next to, or split by.
|
|
26
|
+
* @returns A new `LayoutPath` reflecting the updated (maybe) `"split-panel"`,
|
|
27
|
+
* which is enough to draw the overlay.
|
|
28
|
+
*/
|
|
29
|
+
export function calculate_edge(
|
|
30
|
+
col: number,
|
|
31
|
+
row: number,
|
|
32
|
+
panel: Layout,
|
|
33
|
+
slot: string,
|
|
34
|
+
drop_target: LayoutPath,
|
|
35
|
+
box?: DOMRect,
|
|
36
|
+
): LayoutPath {
|
|
37
|
+
// Check root edges first
|
|
38
|
+
if (col < SPLIT_ROOT_EDGE_TOLERANCE) {
|
|
39
|
+
return insert_root_edge(panel, slot, drop_target, [0], true, "horizontal");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (col > 1 - SPLIT_ROOT_EDGE_TOLERANCE) {
|
|
43
|
+
return insert_root_edge(
|
|
44
|
+
panel,
|
|
45
|
+
slot,
|
|
46
|
+
drop_target,
|
|
47
|
+
drop_target.path.length > 0 ? drop_target.path : [],
|
|
48
|
+
false,
|
|
49
|
+
"horizontal",
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (row < SPLIT_ROOT_EDGE_TOLERANCE) {
|
|
54
|
+
return insert_root_edge(panel, slot, drop_target, [0], true, "vertical");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (row > 1 - SPLIT_ROOT_EDGE_TOLERANCE) {
|
|
58
|
+
return insert_root_edge(panel, slot, drop_target, [], false, "vertical");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Check panel edges
|
|
62
|
+
const is_column_edge =
|
|
63
|
+
drop_target.column_offset < SPLIT_EDGE_TOLERANCE ||
|
|
64
|
+
drop_target.column_offset > 1 - SPLIT_EDGE_TOLERANCE;
|
|
65
|
+
|
|
66
|
+
const is_row_edge =
|
|
67
|
+
drop_target.row_offset < SPLIT_EDGE_TOLERANCE ||
|
|
68
|
+
drop_target.row_offset > 1 - SPLIT_EDGE_TOLERANCE;
|
|
69
|
+
|
|
70
|
+
// If both edges triggered, choose closer axis
|
|
71
|
+
if (is_column_edge && is_row_edge) {
|
|
72
|
+
const col_distance = Math.abs(drop_target.column_offset - 0.5);
|
|
73
|
+
const row_distance = Math.abs(drop_target.row_offset - 0.5);
|
|
74
|
+
const col_scale =
|
|
75
|
+
(box?.width || 1) *
|
|
76
|
+
(drop_target.view_window.col_end - drop_target.view_window.col_start);
|
|
77
|
+
|
|
78
|
+
const row_scale =
|
|
79
|
+
(box?.height || 1) *
|
|
80
|
+
(drop_target.view_window.row_end - drop_target.view_window.row_start);
|
|
81
|
+
|
|
82
|
+
const use_column = col_distance * col_scale > row_distance * row_scale;
|
|
83
|
+
|
|
84
|
+
return insert_axis(
|
|
85
|
+
panel,
|
|
86
|
+
slot,
|
|
87
|
+
drop_target,
|
|
88
|
+
use_column
|
|
89
|
+
? drop_target.column_offset < SPLIT_EDGE_TOLERANCE
|
|
90
|
+
: drop_target.row_offset < SPLIT_EDGE_TOLERANCE,
|
|
91
|
+
use_column ? "horizontal" : "vertical",
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (is_column_edge) {
|
|
96
|
+
return insert_axis(
|
|
97
|
+
panel,
|
|
98
|
+
slot,
|
|
99
|
+
drop_target,
|
|
100
|
+
drop_target.column_offset < SPLIT_EDGE_TOLERANCE,
|
|
101
|
+
"horizontal",
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (is_row_edge) {
|
|
106
|
+
return insert_axis(
|
|
107
|
+
panel,
|
|
108
|
+
slot,
|
|
109
|
+
drop_target,
|
|
110
|
+
drop_target.row_offset < SPLIT_EDGE_TOLERANCE,
|
|
111
|
+
"vertical",
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Not at an edge - insert as a tab
|
|
116
|
+
return {
|
|
117
|
+
...drop_target,
|
|
118
|
+
path: [...drop_target.path, 0],
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function insert_root_edge(
|
|
123
|
+
panel: Layout,
|
|
124
|
+
slot: string,
|
|
125
|
+
drop_target: LayoutPath,
|
|
126
|
+
path: number[],
|
|
127
|
+
is_before: boolean,
|
|
128
|
+
orientation: Orientation,
|
|
129
|
+
): LayoutPath {
|
|
130
|
+
return insert_axis(
|
|
131
|
+
panel,
|
|
132
|
+
slot,
|
|
133
|
+
{ ...drop_target, path, orientation },
|
|
134
|
+
is_before,
|
|
135
|
+
orientation,
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function insert_axis(
|
|
140
|
+
panel: Layout,
|
|
141
|
+
slot: string,
|
|
142
|
+
drop_target: LayoutPath,
|
|
143
|
+
is_before: boolean,
|
|
144
|
+
axis_orientation: Orientation,
|
|
145
|
+
): LayoutPath {
|
|
146
|
+
let result_path: number[];
|
|
147
|
+
|
|
148
|
+
if (drop_target.orientation === axis_orientation) {
|
|
149
|
+
// Same orientation - insert into existing split
|
|
150
|
+
if (drop_target.path.length === 0) {
|
|
151
|
+
result_path = [is_before ? 0 : 1];
|
|
152
|
+
} else {
|
|
153
|
+
const last_index = drop_target.path[drop_target.path.length - 1];
|
|
154
|
+
result_path = [
|
|
155
|
+
...drop_target.path.slice(0, -1),
|
|
156
|
+
is_before ? last_index : last_index + 1,
|
|
157
|
+
];
|
|
158
|
+
}
|
|
159
|
+
} else {
|
|
160
|
+
// Different orientation - split the child panel
|
|
161
|
+
result_path = [...drop_target.path, is_before ? 0 : 1];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const new_panel = insert_child(panel, slot, result_path, axis_orientation);
|
|
165
|
+
const view_window = calculate_view_window(new_panel, result_path);
|
|
166
|
+
return {
|
|
167
|
+
...drop_target,
|
|
168
|
+
path: result_path,
|
|
169
|
+
slot: drop_target.slot,
|
|
170
|
+
is_edge: true,
|
|
171
|
+
orientation: axis_orientation,
|
|
172
|
+
view_window,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function calculate_view_window(panel: Layout, path: number[]): ViewWindow {
|
|
177
|
+
let view_window: ViewWindow = {
|
|
178
|
+
row_start: 0,
|
|
179
|
+
row_end: 1,
|
|
180
|
+
col_start: 0,
|
|
181
|
+
col_end: 1,
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
let current_panel = panel;
|
|
185
|
+
for (const step of path) {
|
|
186
|
+
if (current_panel.type === "child-panel") {
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const index = Math.min(step, current_panel.children.length - 1);
|
|
191
|
+
const is_vertical = current_panel.orientation === "vertical";
|
|
192
|
+
const start_key = is_vertical ? "row_start" : "col_start";
|
|
193
|
+
const end_key = is_vertical ? "row_end" : "col_end";
|
|
194
|
+
const total_size = view_window[end_key] - view_window[start_key];
|
|
195
|
+
const offset = current_panel.sizes
|
|
196
|
+
.slice(0, index)
|
|
197
|
+
.reduce((sum, size) => sum + size * total_size, view_window[start_key]);
|
|
198
|
+
|
|
199
|
+
view_window = {
|
|
200
|
+
...view_window,
|
|
201
|
+
[start_key]: offset,
|
|
202
|
+
[end_key]: offset + total_size * current_panel.sizes[index],
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
current_panel = current_panel.children[index];
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return view_window;
|
|
209
|
+
}
|
|
@@ -9,24 +9,25 @@
|
|
|
9
9
|
// ┃ * [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). * ┃
|
|
10
10
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
11
11
|
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
import { GRID_DIVIDER_SIZE } from "./constants.ts";
|
|
13
|
+
import type { LayoutPath, LayoutDivider, Layout, ViewWindow } from "./types.ts";
|
|
14
|
+
|
|
15
|
+
const VIEW_WINDOW = {
|
|
16
|
+
row_start: 0,
|
|
17
|
+
row_end: 1,
|
|
18
|
+
col_start: 0,
|
|
19
|
+
col_end: 1,
|
|
20
|
+
};
|
|
18
21
|
|
|
19
22
|
/**
|
|
20
23
|
* Determines which panel or divider is located at a given position in the
|
|
21
24
|
* layout.
|
|
22
25
|
*
|
|
23
|
-
* @param
|
|
24
|
-
* height
|
|
25
|
-
* @param column - Horizontal position as a fraction (0-1) of the
|
|
26
|
-
* container width
|
|
26
|
+
* @param column - Horizontal position as a fraction (0-1) of the container width
|
|
27
|
+
* @param row - Vertical position as a fraction (0-1) of the container height
|
|
27
28
|
* @param layout - The layout tree to search
|
|
28
29
|
* @param check_dividers - Whether `LayoutDivider` intersection should be
|
|
29
|
-
* checked, which
|
|
30
|
+
* checked, which you may not want for e.g. `drop` actions.
|
|
30
31
|
* @returns The panel path if over a panel, a divider if over a resizable
|
|
31
32
|
* boundary, or null if outside all panels
|
|
32
33
|
*/
|
|
@@ -34,44 +35,37 @@ export function calculate_intersection(
|
|
|
34
35
|
column: number,
|
|
35
36
|
row: number,
|
|
36
37
|
layout: Layout,
|
|
37
|
-
check_dividers
|
|
38
|
-
): LayoutPath;
|
|
38
|
+
check_dividers?: null,
|
|
39
|
+
): LayoutPath | null;
|
|
39
40
|
|
|
40
41
|
export function calculate_intersection(
|
|
41
42
|
column: number,
|
|
42
43
|
row: number,
|
|
43
44
|
layout: Layout,
|
|
44
|
-
check_dividers
|
|
45
|
+
check_dividers?: DOMRect,
|
|
45
46
|
): LayoutPath | null | LayoutDivider;
|
|
46
47
|
|
|
47
48
|
export function calculate_intersection(
|
|
48
49
|
column: number,
|
|
49
50
|
row: number,
|
|
50
51
|
layout: Layout,
|
|
51
|
-
check_dividers?:
|
|
52
|
+
check_dividers?: DOMRect | null,
|
|
52
53
|
): LayoutPath | null | LayoutDivider;
|
|
53
54
|
|
|
54
55
|
export function calculate_intersection(
|
|
55
56
|
column: number,
|
|
56
57
|
row: number,
|
|
57
58
|
layout: Layout,
|
|
58
|
-
check_dividers:
|
|
59
|
+
check_dividers: DOMRect | null = null,
|
|
59
60
|
): LayoutPath | null | LayoutDivider {
|
|
60
61
|
return calculate_intersection_recursive(column, row, layout, check_dividers);
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
const VIEW_WINDOW = {
|
|
64
|
-
row_start: 0,
|
|
65
|
-
row_end: 1,
|
|
66
|
-
col_start: 0,
|
|
67
|
-
col_end: 1,
|
|
68
|
-
};
|
|
69
|
-
|
|
70
64
|
function calculate_intersection_recursive(
|
|
71
65
|
column: number,
|
|
72
66
|
row: number,
|
|
73
67
|
panel: Layout,
|
|
74
|
-
check_dividers:
|
|
68
|
+
check_dividers: DOMRect | null,
|
|
75
69
|
parent_orientation: "horizontal" | "vertical" | null = null,
|
|
76
70
|
view_window: ViewWindow = structuredClone(VIEW_WINDOW),
|
|
77
71
|
path: number[] = [],
|
|
@@ -83,101 +77,68 @@ function calculate_intersection_recursive(
|
|
|
83
77
|
// Base case: if this is a child panel, return its name
|
|
84
78
|
if (panel.type === "child-panel") {
|
|
85
79
|
const selected = panel.selected ?? 0;
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
(view_window.col_end - view_window.col_start);
|
|
89
|
-
const row_offset =
|
|
90
|
-
(row - view_window.row_start) /
|
|
91
|
-
(view_window.row_end - view_window.row_start);
|
|
92
|
-
|
|
80
|
+
const col_width = view_window.col_end - view_window.col_start;
|
|
81
|
+
const row_height = view_window.row_end - view_window.row_start;
|
|
93
82
|
return {
|
|
94
83
|
type: "layout-path",
|
|
95
|
-
|
|
84
|
+
layout: undefined,
|
|
96
85
|
slot: panel.child[selected],
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
view_window: view_window,
|
|
86
|
+
path,
|
|
87
|
+
view_window,
|
|
100
88
|
is_edge: false,
|
|
101
|
-
|
|
102
|
-
|
|
89
|
+
column,
|
|
90
|
+
row,
|
|
91
|
+
column_offset: (column - view_window.col_start) / col_width,
|
|
92
|
+
row_offset: (row - view_window.row_start) / row_height,
|
|
103
93
|
orientation: parent_orientation || "horizontal",
|
|
104
94
|
};
|
|
105
95
|
}
|
|
106
96
|
|
|
107
97
|
// For split panels, determine which child was hit
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
type: "vertical",
|
|
118
|
-
view_window: {
|
|
119
|
-
...view_window,
|
|
120
|
-
row_start: current_row,
|
|
121
|
-
row_end: next_row,
|
|
122
|
-
},
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (row >= current_row && row < next_row) {
|
|
127
|
-
return calculate_intersection_recursive(
|
|
128
|
-
column,
|
|
129
|
-
row,
|
|
130
|
-
panel.children[i],
|
|
131
|
-
check_dividers,
|
|
132
|
-
"vertical",
|
|
133
|
-
{
|
|
134
|
-
...view_window,
|
|
135
|
-
row_start: current_row,
|
|
136
|
-
row_end: next_row,
|
|
137
|
-
},
|
|
138
|
-
[...path, i],
|
|
139
|
-
);
|
|
140
|
-
}
|
|
98
|
+
const is_vertical = panel.orientation === "vertical";
|
|
99
|
+
const position = is_vertical ? row : column;
|
|
100
|
+
const start_key = is_vertical ? "row_start" : "col_start";
|
|
101
|
+
const end_key = is_vertical ? "row_end" : "col_end";
|
|
102
|
+
const rect_dim = is_vertical ? check_dividers?.height : check_dividers?.width;
|
|
103
|
+
let current_pos = view_window[start_key];
|
|
104
|
+
const total_size = view_window[end_key] - view_window[start_key];
|
|
105
|
+
for (let i = 0; i < panel.children.length; i++) {
|
|
106
|
+
const next_pos = current_pos + total_size * panel.sizes[i];
|
|
141
107
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
let current_col = view_window.col_start;
|
|
147
|
-
for (let i = 0; i < panel.children.length; i++) {
|
|
148
|
-
const total_size = view_window.col_end - view_window.col_start;
|
|
149
|
-
const next_col = current_col + total_size * panel.sizes[i];
|
|
150
|
-
if (check_dividers && Math.abs(column - next_col) < 0.01) {
|
|
108
|
+
// Check if position is on a divider
|
|
109
|
+
if (check_dividers && rect_dim) {
|
|
110
|
+
const divider_threshold = GRID_DIVIDER_SIZE / rect_dim;
|
|
111
|
+
if (Math.abs(position - next_pos) < divider_threshold) {
|
|
151
112
|
return {
|
|
152
113
|
path: [...path, i],
|
|
153
|
-
type:
|
|
114
|
+
type: panel.orientation,
|
|
154
115
|
view_window: {
|
|
155
116
|
...view_window,
|
|
156
|
-
|
|
157
|
-
|
|
117
|
+
[start_key]: current_pos,
|
|
118
|
+
[end_key]: next_pos,
|
|
158
119
|
},
|
|
159
120
|
};
|
|
160
121
|
}
|
|
122
|
+
}
|
|
161
123
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
current_col = next_col;
|
|
124
|
+
// Check if position falls within this child's bounds
|
|
125
|
+
if (position >= current_pos && position < next_pos) {
|
|
126
|
+
return calculate_intersection_recursive(
|
|
127
|
+
column,
|
|
128
|
+
row,
|
|
129
|
+
panel.children[i],
|
|
130
|
+
check_dividers,
|
|
131
|
+
panel.orientation,
|
|
132
|
+
{
|
|
133
|
+
...view_window,
|
|
134
|
+
[start_key]: current_pos,
|
|
135
|
+
[end_key]: next_pos,
|
|
136
|
+
},
|
|
137
|
+
[...path, i],
|
|
138
|
+
);
|
|
180
139
|
}
|
|
140
|
+
|
|
141
|
+
current_pos = next_pos;
|
|
181
142
|
}
|
|
182
143
|
|
|
183
144
|
// If we get here, the hit was outside all children (possibly in a gap or
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
|
|
2
|
+
// ░░░░░░░░▄▀░█▀▄░█▀▀░█▀▀░█░█░█░░░█▀█░█▀▄░░░░░█░░░█▀█░█░█░█▀█░█░█░▀█▀░▀▄░░░░░░░░
|
|
3
|
+
// ░░░░░░░▀▄░░█▀▄░█▀▀░█░█░█░█░█░░░█▀█░█▀▄░▀▀▀░█░░░█▀█░░█░░█░█░█░█░░█░░░▄▀░░░░░░░
|
|
4
|
+
// ░░░░░░░░░▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░▀▀▀░▀░▀░▀░▀░░░░░▀▀▀░▀░▀░░▀░░▀▀▀░▀▀▀░░▀░░▀░░░░░░░░░
|
|
5
|
+
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
|
|
6
|
+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
7
|
+
// ┃ * Copyright (c) 2026, the Regular Layout Authors. This file is part * ┃
|
|
8
|
+
// ┃ * of the Regular Layout library, distributed under the terms of the * ┃
|
|
9
|
+
// ┃ * [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). * ┃
|
|
10
|
+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
11
|
+
|
|
12
|
+
import type { OverlayMode } from "./types";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The prefix to use for `CustomEvent`s generated by `regular-layout`, e.g.
|
|
16
|
+
* `"regular-layout-before-update"`.
|
|
17
|
+
*/
|
|
18
|
+
export const CUSTOM_EVENT_NAME_PREFIX = "regular-layout";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The minimum number of pixels the mouse must move to be considered a drag.
|
|
22
|
+
*/
|
|
23
|
+
export const MIN_DRAG_DISTANCE = 10;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Class name to use for child elements in overlay position (dragging).
|
|
27
|
+
*/
|
|
28
|
+
export const OVERLAY_CLASSNAME = "overlay";
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The percentage of the maximum resize distance that will be clamped.
|
|
32
|
+
*
|
|
33
|
+
*/
|
|
34
|
+
export const MINIMUM_REDISTRIBUTION_SIZE_THRESHOLD = 0.15;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Threshold from panel edge that is considered a split vs drop action.
|
|
38
|
+
*/
|
|
39
|
+
export const SPLIT_EDGE_TOLERANCE = 0.25;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Threshold from _container_ edge that is considered a split action on the root
|
|
43
|
+
* node.
|
|
44
|
+
*/
|
|
45
|
+
export const SPLIT_ROOT_EDGE_TOLERANCE = 0.01;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Tolerance threshold for considering two grid track positions as identical.
|
|
49
|
+
*
|
|
50
|
+
* When collecting and deduplicating track positions, any positions closer than
|
|
51
|
+
* this value are treated as the same position to avoid redundant grid tracks.
|
|
52
|
+
*/
|
|
53
|
+
export const GRID_TRACK_COLLAPSE_TOLERANCE = 0.001;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The overlay default behavior.
|
|
57
|
+
*/
|
|
58
|
+
export const OVERLAY_DEFAULT: OverlayMode = "absolute";
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Width of split panel dividers in pixels (for hit-test purposes).
|
|
62
|
+
*/
|
|
63
|
+
export const GRID_DIVIDER_SIZE = 6;
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// ┃ * [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). * ┃
|
|
10
10
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
11
11
|
|
|
12
|
-
import type { Layout } from "./
|
|
12
|
+
import type { Layout } from "./types.ts";
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Flattens the layout tree by merging parent and child split panels that have
|
|
@@ -24,6 +24,7 @@ import type { Layout } from "./layout_config.ts";
|
|
|
24
24
|
*/
|
|
25
25
|
export function flatten(layout: Layout): Layout {
|
|
26
26
|
if (layout.type === "child-panel") {
|
|
27
|
+
layout.selected = layout.selected || 0;
|
|
27
28
|
return layout;
|
|
28
29
|
}
|
|
29
30
|
|