@adecore/ui 0.31.12 → 0.32.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/dist/AccentSwatches.js +290 -13
- package/dist/Banner.js +90 -9
- package/dist/Button.js +114 -22
- package/dist/ButtonGroup.js +62 -8
- package/dist/Checkbox.js +73 -4
- package/dist/ChoiceCards.js +205 -11
- package/dist/CloseButton.js +87 -7
- package/dist/ColorSwatch.js +132 -15
- package/dist/ColorWheelPicker.js +305 -71
- package/dist/ColumnResizeHandle.js +43 -8
- package/dist/DisabledReason.js +27 -8
- package/dist/DockShell.js +144 -37
- package/dist/EmptyState.js +95 -6
- package/dist/ErrorBoundary.js +254 -31
- package/dist/Field.js +349 -31
- package/dist/FileIcon.js +67 -6
- package/dist/Icon.js +38 -6
- package/dist/IconButton.js +176 -20
- package/dist/IconPicker.js +344 -73
- package/dist/Input.js +233 -14
- package/dist/Kbd.js +150 -10
- package/dist/LazyBoundary.js +14 -5
- package/dist/ListRow.js +75 -15
- package/dist/Meter.js +108 -5
- package/dist/MiddleTruncate.js +126 -45
- package/dist/PanelEmpty.js +64 -5
- package/dist/PanelHeader.js +95 -13
- package/dist/Pill.js +114 -19
- package/dist/ProjectSwitcher.js +225 -12
- package/dist/PromptDialog.js +352 -37
- package/dist/SectionLabel.js +62 -8
- package/dist/SegmentBar.js +197 -36
- package/dist/Segmented.js +130 -23
- package/dist/Select.js +310 -19
- package/dist/SelectSearch.js +344 -29
- package/dist/Separator.js +35 -4
- package/dist/ShortcutHints.js +146 -76
- package/dist/Skeleton.js +31 -4
- package/dist/Slider.js +172 -10
- package/dist/SlidingColumn.js +194 -34
- package/dist/Spinner.js +100 -3
- package/dist/Stepper.js +232 -11
- package/dist/Surface.js +62 -8
- package/dist/Switch.js +60 -6
- package/dist/TextMenu.js +212 -17
- package/dist/Tile.js +149 -5
- package/dist/Toasts.js +391 -33
- package/dist/Tooltip.js +153 -16
- package/dist/UIProvider.js +62 -15
- package/dist/Waveform.js +362 -93
- package/dist/Wipe.js +259 -34
- package/dist/ZoomControls.js +356 -14
- package/dist/class-name.js +1 -1
- package/dist/clipboard.js +15 -17
- package/dist/context-menu/index.parts.js +1 -1
- package/dist/dialog/index.parts.js +1 -1
- package/dist/dialog/parts.js +378 -29
- package/dist/dialog-layer.js +51 -18
- package/dist/error-boundary.js +19 -19
- package/dist/error-message.js +1 -1
- package/dist/field-context.js +7 -5
- package/dist/file-icon.js +23 -21
- package/dist/file-tree/helpers.js +133 -119
- package/dist/file-tree/index.parts.js +3 -3
- package/dist/file-tree/parts.js +418 -127
- package/dist/file-tree/style.js +1 -1
- package/dist/file-tree/use-file-tree-shift.js +43 -30
- package/dist/file-tree/use-file-tree.js +60 -18
- package/dist/file-tree/use-slots.js +220 -192
- package/dist/floating.js +2 -2
- package/dist/format/datetime.js +88 -38
- package/dist/format/duration.js +59 -53
- package/dist/format/index.js +1 -1
- package/dist/format/locale.js +76 -56
- package/dist/format/number.js +77 -61
- package/dist/format/regions.js +4 -2
- package/dist/format/time-zone.js +1 -1
- package/dist/icon-button-size.js +12 -2
- package/dist/icon-picker.js +70 -61
- package/dist/index.js +57 -57
- package/dist/key-value-list/index.parts.js +1 -1
- package/dist/key-value-list/parts.js +256 -22
- package/dist/lazy-landings.js +10 -10
- package/dist/lazy.js +84 -71
- package/dist/locales/en.js +80 -80
- package/dist/locales/nl.js +80 -80
- package/dist/locales.js +10 -7
- package/dist/menu/index.parts.js +1 -1
- package/dist/menu/parts.js +882 -44
- package/dist/merge-refs.js +8 -9
- package/dist/middle-truncate.js +24 -25
- package/dist/modality.js +27 -19
- package/dist/placement.js +11 -20
- package/dist/platform.js +6 -6
- package/dist/popover/index.parts.js +1 -1
- package/dist/popover/parts.js +173 -11
- package/dist/popup-layer.js +38 -17
- package/dist/prefetch.js +78 -79
- package/dist/preview-card/index.parts.js +1 -1
- package/dist/project-switcher-row.js +153 -12
- package/dist/select-row.js +69 -5
- package/dist/select-shared.js +6 -6
- package/dist/selection.js +16 -16
- package/dist/seti-icons.js +413 -413
- package/dist/settings/ConfirmDialog.js +55 -8
- package/dist/settings/DetailHeader.js +72 -4
- package/dist/settings/MasterDetail.js +119 -7
- package/dist/settings/SettingsDialog.js +820 -80
- package/dist/settings/SettingsRow.js +205 -18
- package/dist/settings/SettingsSection.js +96 -6
- package/dist/settings/index.js +7 -7
- package/dist/settings/target.js +7 -2
- package/dist/shortcut-hints.js +73 -55
- package/dist/shortcut.js +140 -104
- package/dist/step-places.js +1 -1
- package/dist/tabs/index.parts.js +1 -1
- package/dist/tabs/overflow.js +18 -18
- package/dist/tabs/parts.js +780 -166
- package/dist/testing/dedupe.js +82 -75
- package/dist/testing/fake-source.js +12 -12
- package/dist/testing/index.js +1 -1
- package/dist/toast-store.js +65 -46
- package/dist/tree/index.parts.js +1 -1
- package/dist/tree/parts.js +721 -94
- package/dist/tree/shift.js +28 -22
- package/dist/tree/style.js +2 -2
- package/dist/tree/use-tree-shift.js +178 -117
- package/dist/useAsyncAction.js +23 -19
- package/dist/useColumnResize.js +36 -34
- package/dist/useContentSize.js +62 -18
- package/dist/useMeasuredWidth.js +14 -3
- package/dist/useNow.js +73 -30
- package/dist/wipe-split.js +14 -14
- package/dist/workspace/DropPreview.js +60 -7
- package/dist/workspace/SplitView.js +1025 -441
- package/dist/workspace/TabStrip.js +810 -191
- package/dist/workspace/Workspace.js +276 -26
- package/dist/workspace/context.js +8 -3
- package/dist/workspace/geometry.js +173 -150
- package/dist/workspace/model.js +313 -250
- package/dist/workspace/preview.js +61 -61
- package/dist/zoom.js +2 -2
- package/package.json +1 -1
- package/src/ErrorBoundary.tsx +1 -1
- package/src/Field.tsx +4 -3
- package/src/IconPicker.tsx +3 -3
- package/src/LazyBoundary.tsx +2 -0
- package/src/MiddleTruncate.tsx +2 -2
- package/src/SegmentBar.tsx +2 -2
- package/src/Toasts.tsx +3 -1
- package/src/Tooltip.tsx +7 -10
- package/src/Waveform.tsx +3 -3
- package/src/file-tree/parts.tsx +6 -9
- package/src/file-tree/use-file-tree-shift.tsx +6 -9
- package/src/lazy.tsx +4 -0
- package/src/locales/en.ts +4 -4
- package/src/locales/nl.ts +5 -5
- package/src/settings/SettingsDialog.tsx +1 -1
- package/src/tree/parts.tsx +5 -8
- package/src/useContentSize.ts +3 -3
- package/src/workspace/SplitView.tsx +2 -2
- package/src/workspace/TabStrip.tsx +2 -3
- package/src/workspace/Workspace.tsx +2 -5
package/dist/workspace/model.js
CHANGED
|
@@ -1,292 +1,355 @@
|
|
|
1
1
|
export function createSplitLayout(views = [], paneId = 'main') {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
const unique = [...new Set(views)];
|
|
3
|
+
return {
|
|
4
|
+
root: {
|
|
5
|
+
type: 'pane',
|
|
6
|
+
id: paneId,
|
|
7
|
+
views: unique,
|
|
8
|
+
active: unique[0] ?? null
|
|
9
|
+
},
|
|
10
|
+
focused: paneId,
|
|
11
|
+
maximized: null
|
|
12
|
+
};
|
|
4
13
|
}
|
|
5
14
|
export function splitPanes(node) {
|
|
6
|
-
|
|
15
|
+
return node.type === 'pane' ? [node] : node.children.flatMap(splitPanes);
|
|
7
16
|
}
|
|
8
17
|
export function findSplitNode(node, id) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
18
|
+
if (node.id === id) {
|
|
19
|
+
return node;
|
|
20
|
+
}
|
|
21
|
+
return node.type === 'split' ? node.children.map(child => findSplitNode(child, id)).find(Boolean) : undefined;
|
|
13
22
|
}
|
|
14
23
|
function shares(values, length) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
24
|
+
const safe = Array.from({
|
|
25
|
+
length
|
|
26
|
+
}, (_, i) => Number.isFinite(values[i]) && values[i] > 0 ? values[i] : 1);
|
|
27
|
+
const largest = Math.max(...safe, 1);
|
|
28
|
+
const total = safe.reduce((sum, value) => sum + value / largest, 0);
|
|
29
|
+
return safe.map(value => value / largest / total);
|
|
19
30
|
}
|
|
20
31
|
function flattenSplits(node) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
sizes.push(node.sizes[i]);
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
if (children.length === node.children.length && children.every((child, i) => child === node.children[i])) {
|
|
39
|
-
return node;
|
|
32
|
+
if (node.type === 'pane') {
|
|
33
|
+
return node;
|
|
34
|
+
}
|
|
35
|
+
const children = [];
|
|
36
|
+
const sizes = [];
|
|
37
|
+
node.children.forEach((child, i) => {
|
|
38
|
+
const next = flattenSplits(child);
|
|
39
|
+
// A divider balances neighboring tracks, not a pane against a hidden group on the same axis.
|
|
40
|
+
if (next.type === 'split' && next.axis === node.axis) {
|
|
41
|
+
children.push(...next.children);
|
|
42
|
+
sizes.push(...next.sizes.map(size => size * node.sizes[i]));
|
|
43
|
+
} else {
|
|
44
|
+
children.push(next);
|
|
45
|
+
sizes.push(node.sizes[i]);
|
|
40
46
|
}
|
|
41
|
-
|
|
47
|
+
});
|
|
48
|
+
if (children.length === node.children.length && children.every((child, i) => child === node.children[i])) {
|
|
49
|
+
return node;
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
...node,
|
|
53
|
+
children,
|
|
54
|
+
sizes: shares(sizes, children.length)
|
|
55
|
+
};
|
|
42
56
|
}
|
|
43
57
|
function replace(node, id, transform) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
if (children.every((child, i) => child === node.children[i]) && children.length === node.children.length) {
|
|
60
|
-
return node;
|
|
61
|
-
}
|
|
62
|
-
if (children.length < 2) {
|
|
63
|
-
return children[0] ?? null;
|
|
58
|
+
if (node.id === id) {
|
|
59
|
+
return transform(node);
|
|
60
|
+
}
|
|
61
|
+
if (node.type === 'pane') {
|
|
62
|
+
return node;
|
|
63
|
+
}
|
|
64
|
+
const children = [];
|
|
65
|
+
const sizes = [];
|
|
66
|
+
node.children.forEach((child, i) => {
|
|
67
|
+
const next = replace(child, id, transform);
|
|
68
|
+
if (next) {
|
|
69
|
+
children.push(next);
|
|
70
|
+
sizes.push(node.sizes[i]);
|
|
64
71
|
}
|
|
65
|
-
|
|
72
|
+
});
|
|
73
|
+
if (children.every((child, i) => child === node.children[i]) && children.length === node.children.length) {
|
|
74
|
+
return node;
|
|
75
|
+
}
|
|
76
|
+
if (children.length < 2) {
|
|
77
|
+
return children[0] ?? null;
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
...node,
|
|
81
|
+
children,
|
|
82
|
+
sizes: shares(sizes, children.length)
|
|
83
|
+
};
|
|
66
84
|
}
|
|
67
85
|
function finish(layout, root, focus = layout.focused) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
86
|
+
const next = flattenSplits(root ?? createSplitLayout([], layout.focused).root);
|
|
87
|
+
const panes = splitPanes(next);
|
|
88
|
+
return {
|
|
89
|
+
root: next,
|
|
90
|
+
focused: panes.some(pane => pane.id === focus) ? focus : panes[0].id,
|
|
91
|
+
maximized: panes.some(pane => pane.id === layout.maximized) ? layout.maximized : null
|
|
92
|
+
};
|
|
75
93
|
}
|
|
76
94
|
function without(pane, views) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
95
|
+
const remaining = pane.views.filter(view => !views.includes(view));
|
|
96
|
+
const position = Math.max(0, pane.views.indexOf(pane.active ?? ''));
|
|
97
|
+
return {
|
|
98
|
+
...pane,
|
|
99
|
+
views: remaining,
|
|
100
|
+
active: remaining.includes(pane.active ?? '') ? pane.active : remaining[Math.min(position, remaining.length - 1)] ?? null
|
|
101
|
+
};
|
|
84
102
|
}
|
|
85
103
|
function beside(target, pane, side, id) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
104
|
+
return {
|
|
105
|
+
type: 'split',
|
|
106
|
+
id,
|
|
107
|
+
axis: side === 'left' || side === 'right' ? 'horizontal' : 'vertical',
|
|
108
|
+
children: side === 'left' || side === 'top' ? [pane, target] : [target, pane],
|
|
109
|
+
sizes: [0.5, 0.5]
|
|
110
|
+
};
|
|
93
111
|
}
|
|
94
112
|
function equalizeAxis(root, axis, length, gap) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
if (node.axis !== axis) {
|
|
108
|
-
return { ...node, children: node.children.map((child) => distribute(child, extent)) };
|
|
109
|
-
}
|
|
110
|
-
const count = tracks.get(node.id);
|
|
111
|
-
const spacing = Math.min(gap, extent / (count - 1));
|
|
112
|
-
const unit = Math.max(0, extent - spacing * (count - 1)) / count;
|
|
113
|
-
// Spanning panels also occupy the gaps between their tracks.
|
|
114
|
-
const lengths = node.children.map((child) => {
|
|
115
|
-
const span = tracks.get(child.id);
|
|
116
|
-
return Math.max(Number.EPSILON, unit * span + spacing * (span - 1));
|
|
117
|
-
});
|
|
118
|
-
return { ...node, sizes: shares(lengths, lengths.length), children: node.children.map((child, i) => distribute(child, lengths[i])) };
|
|
119
|
-
};
|
|
120
|
-
return distribute(root, length);
|
|
121
|
-
}
|
|
122
|
-
function addPane(layout, panes, pane, command) {
|
|
123
|
-
if (!pane || findSplitNode(layout.root, command.newPane.id) || findSplitNode(layout.root, command.splitId) || command.newPane.id === command.splitId) {
|
|
124
|
-
return layout;
|
|
113
|
+
const tracks = new Map();
|
|
114
|
+
const measure = node => {
|
|
115
|
+
const children = node.type === 'split' ? node.children.map(measure) : [];
|
|
116
|
+
const count = node.type === 'pane' ? 1 : node.axis === axis ? children.reduce((sum, value) => sum + value, 0) : Math.max(...children);
|
|
117
|
+
tracks.set(node.id, count);
|
|
118
|
+
return count;
|
|
119
|
+
};
|
|
120
|
+
measure(root);
|
|
121
|
+
const distribute = (node, extent) => {
|
|
122
|
+
if (node.type === 'pane') {
|
|
123
|
+
return node;
|
|
125
124
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
125
|
+
if (node.axis !== axis) {
|
|
126
|
+
return {
|
|
127
|
+
...node,
|
|
128
|
+
children: node.children.map(child => distribute(child, extent))
|
|
129
|
+
};
|
|
129
130
|
}
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
131
|
+
const count = tracks.get(node.id);
|
|
132
|
+
const spacing = Math.min(gap, extent / (count - 1));
|
|
133
|
+
const unit = Math.max(0, extent - spacing * (count - 1)) / count;
|
|
134
|
+
// Spanning panels also occupy the gaps between their tracks.
|
|
135
|
+
const lengths = node.children.map(child => {
|
|
136
|
+
const span = tracks.get(child.id);
|
|
137
|
+
return Math.max(Number.EPSILON, unit * span + spacing * (span - 1));
|
|
138
|
+
});
|
|
139
|
+
return {
|
|
140
|
+
...node,
|
|
141
|
+
sizes: shares(lengths, lengths.length),
|
|
142
|
+
children: node.children.map((child, i) => distribute(child, lengths[i]))
|
|
133
143
|
};
|
|
134
|
-
|
|
144
|
+
};
|
|
145
|
+
return distribute(root, length);
|
|
146
|
+
}
|
|
147
|
+
function addPane(layout, panes, pane, command) {
|
|
148
|
+
if (!pane || findSplitNode(layout.root, command.newPane.id) || findSplitNode(layout.root, command.splitId) || command.newPane.id === command.splitId) {
|
|
149
|
+
return layout;
|
|
150
|
+
}
|
|
151
|
+
const allViews = new Set(panes.flatMap(item => item.views));
|
|
152
|
+
if (command.newPane.views.some(view => allViews.has(view)) || new Set(command.newPane.views).size !== command.newPane.views.length) {
|
|
153
|
+
return layout;
|
|
154
|
+
}
|
|
155
|
+
const added = {
|
|
156
|
+
...command.newPane,
|
|
157
|
+
active: command.newPane.views.includes(command.newPane.active ?? '') ? command.newPane.active : command.newPane.views[0] ?? null
|
|
158
|
+
};
|
|
159
|
+
return finish({
|
|
160
|
+
...layout,
|
|
161
|
+
maximized: null
|
|
162
|
+
}, replace(layout.root, pane.id, () => beside(pane, added, command.side, command.splitId)), added.id);
|
|
135
163
|
}
|
|
136
164
|
function swapPanes(layout, panes, command) {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const moving = command.viewId;
|
|
155
|
-
const displaced = target.active;
|
|
156
|
-
const sourceNext = displaced === null
|
|
157
|
-
? without(source, [moving])
|
|
158
|
-
: {
|
|
159
|
-
...source,
|
|
160
|
-
views: source.views.map((view) => (view === moving ? displaced : view)),
|
|
161
|
-
active: source.active === moving ? displaced : source.active
|
|
162
|
-
};
|
|
163
|
-
const targetNext = {
|
|
164
|
-
...target,
|
|
165
|
-
views: displaced === null ? [moving] : target.views.map((view) => (view === displaced ? moving : view)),
|
|
166
|
-
active: moving
|
|
165
|
+
const source = panes.find(item => item.id === command.sourceId);
|
|
166
|
+
const target = panes.find(item => item.id === command.targetId);
|
|
167
|
+
if (!source || !target || source === target || source.views.length === 0 || command.viewId !== undefined && !source.views.includes(command.viewId)) {
|
|
168
|
+
return layout;
|
|
169
|
+
}
|
|
170
|
+
if (command.viewId === undefined || source.views.length === 1) {
|
|
171
|
+
const exchange = node => {
|
|
172
|
+
if (node.id === source.id) {
|
|
173
|
+
return target;
|
|
174
|
+
}
|
|
175
|
+
if (node.id === target.id) {
|
|
176
|
+
return source;
|
|
177
|
+
}
|
|
178
|
+
return node.type === 'pane' ? node : {
|
|
179
|
+
...node,
|
|
180
|
+
children: node.children.map(exchange)
|
|
181
|
+
};
|
|
167
182
|
};
|
|
168
|
-
|
|
169
|
-
|
|
183
|
+
return finish({
|
|
184
|
+
...layout,
|
|
185
|
+
maximized: null
|
|
186
|
+
}, exchange(layout.root), source.id);
|
|
187
|
+
}
|
|
188
|
+
const moving = command.viewId;
|
|
189
|
+
const displaced = target.active;
|
|
190
|
+
const sourceNext = displaced === null ? without(source, [moving]) : {
|
|
191
|
+
...source,
|
|
192
|
+
views: source.views.map(view => view === moving ? displaced : view),
|
|
193
|
+
active: source.active === moving ? displaced : source.active
|
|
194
|
+
};
|
|
195
|
+
const targetNext = {
|
|
196
|
+
...target,
|
|
197
|
+
views: displaced === null ? [moving] : target.views.map(view => view === displaced ? moving : view),
|
|
198
|
+
active: moving
|
|
199
|
+
};
|
|
200
|
+
const root = replace(layout.root, source.id, () => sourceNext);
|
|
201
|
+
return finish({
|
|
202
|
+
...layout,
|
|
203
|
+
maximized: null
|
|
204
|
+
}, replace(root, target.id, () => targetNext), target.id);
|
|
170
205
|
}
|
|
171
206
|
function moveViews(layout, panes, command) {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
207
|
+
const source = panes.find(item => item.id === command.sourceId);
|
|
208
|
+
const target = panes.find(item => item.id === command.targetId);
|
|
209
|
+
if (!source || !target || command.viewId !== undefined && !source.views.includes(command.viewId)) {
|
|
210
|
+
return layout;
|
|
211
|
+
}
|
|
212
|
+
const moving = command.viewId === undefined ? source.views : [command.viewId];
|
|
213
|
+
if (!moving.length || source === target && (command.viewId === undefined || command.side !== undefined && source.views.length === 1)) {
|
|
214
|
+
return layout;
|
|
215
|
+
}
|
|
216
|
+
let added;
|
|
217
|
+
if (command.side) {
|
|
218
|
+
const id = command.viewId === undefined ? source.id : command.newPaneId;
|
|
219
|
+
if (!id || !command.splitId || id === command.splitId || findSplitNode(layout.root, command.splitId) || findSplitNode(layout.root, id) && !(id === source.id && command.viewId === undefined)) {
|
|
220
|
+
return layout;
|
|
180
221
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
222
|
+
added = {
|
|
223
|
+
type: 'pane',
|
|
224
|
+
id,
|
|
225
|
+
views: moving,
|
|
226
|
+
active: command.viewId ?? source.active
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
const remaining = without(source, moving);
|
|
230
|
+
const root = replace(layout.root, source.id, () => remaining.views.length || source === target ? remaining : null);
|
|
231
|
+
if (!root) {
|
|
232
|
+
return layout;
|
|
233
|
+
}
|
|
234
|
+
const next = replace(root, target.id, node => {
|
|
235
|
+
if (node.type !== 'pane') {
|
|
236
|
+
return node;
|
|
192
237
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
if (!root) {
|
|
196
|
-
return layout;
|
|
238
|
+
if (added && command.side && command.splitId) {
|
|
239
|
+
return beside(node, added, command.side, command.splitId);
|
|
197
240
|
}
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
241
|
+
const gap = Math.max(0, Math.min(target.views.length, command.index ?? target.views.length));
|
|
242
|
+
const lifted = source === target ? target.views.slice(0, gap).filter(view => moving.includes(view)).length : 0;
|
|
243
|
+
const views = [...node.views];
|
|
244
|
+
views.splice(gap - lifted, 0, ...moving);
|
|
245
|
+
return {
|
|
246
|
+
...node,
|
|
247
|
+
views,
|
|
248
|
+
active: command.viewId ?? source.active ?? views[0] ?? null
|
|
249
|
+
};
|
|
250
|
+
});
|
|
251
|
+
return finish({
|
|
252
|
+
...layout,
|
|
253
|
+
maximized: null
|
|
254
|
+
}, next, added?.id ?? target.id);
|
|
212
255
|
}
|
|
213
256
|
function resizeBranch(layout, command) {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
223
|
-
sizes = shares(command.sizes, node.children.length);
|
|
257
|
+
const node = findSplitNode(layout.root, command.splitId);
|
|
258
|
+
if (!node || node.type !== 'split') {
|
|
259
|
+
return layout;
|
|
260
|
+
}
|
|
261
|
+
let sizes = [...node.sizes];
|
|
262
|
+
if (command.type === 'resize') {
|
|
263
|
+
if (command.sizes.length !== node.children.length || command.sizes.some(size => !Number.isFinite(size) || size <= 0)) {
|
|
264
|
+
return layout;
|
|
224
265
|
}
|
|
225
|
-
|
|
226
|
-
|
|
266
|
+
sizes = shares(command.sizes, node.children.length);
|
|
267
|
+
} else if (command.index === undefined) {
|
|
268
|
+
sizes = node.children.map(() => 1 / node.children.length);
|
|
269
|
+
} else {
|
|
270
|
+
const index = command.index;
|
|
271
|
+
if (index < 0 || index >= sizes.length - 1) {
|
|
272
|
+
return layout;
|
|
227
273
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
}
|
|
235
|
-
return finish(layout, replace(layout.root, node.id, () => ({ ...node, sizes })));
|
|
274
|
+
sizes[index] = sizes[index + 1] = (sizes[index] + sizes[index + 1]) / 2;
|
|
275
|
+
}
|
|
276
|
+
return finish(layout, replace(layout.root, node.id, () => ({
|
|
277
|
+
...node,
|
|
278
|
+
sizes
|
|
279
|
+
})));
|
|
236
280
|
}
|
|
237
281
|
/** Invalid or stale commands are no-ops. IDs for new nodes come from the caller. */
|
|
238
282
|
export function updateSplitLayout(layout, command) {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
283
|
+
const panes = splitPanes(layout.root);
|
|
284
|
+
const pane = 'paneId' in command ? panes.find(item => item.id === command.paneId) : undefined;
|
|
285
|
+
switch (command.type) {
|
|
286
|
+
case 'focus':
|
|
287
|
+
return pane && layout.focused !== pane.id ? {
|
|
288
|
+
...layout,
|
|
289
|
+
focused: pane.id
|
|
290
|
+
} : layout;
|
|
291
|
+
case 'maximize':
|
|
292
|
+
return command.paneId === null || pane ? {
|
|
293
|
+
...layout,
|
|
294
|
+
maximized: command.paneId,
|
|
295
|
+
focused: pane?.id ?? layout.focused
|
|
296
|
+
} : layout;
|
|
297
|
+
case 'activate':
|
|
298
|
+
return pane?.views.includes(command.viewId) ? finish(layout, replace(layout.root, pane.id, () => ({
|
|
299
|
+
...pane,
|
|
300
|
+
active: command.viewId
|
|
301
|
+
})), pane.id) : layout;
|
|
302
|
+
case 'close':
|
|
303
|
+
{
|
|
304
|
+
const source = panes.find(item => item.views.includes(command.viewId));
|
|
305
|
+
if (!source) {
|
|
306
|
+
return layout;
|
|
257
307
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
if (source) {
|
|
268
|
-
return updateSplitLayout(layout, { type: 'move', sourceId: source.id, targetId: pane.id, viewId: command.viewId, index: command.index });
|
|
269
|
-
}
|
|
270
|
-
const views = [...pane.views];
|
|
271
|
-
views.splice(Math.max(0, Math.min(views.length, command.index ?? views.length)), 0, command.viewId);
|
|
272
|
-
return finish(layout, replace(layout.root, pane.id, () => ({ ...pane, views, active: command.viewId })), pane.id);
|
|
308
|
+
const next = without(source, [command.viewId]);
|
|
309
|
+
return finish(layout, replace(layout.root, source.id, () => next.views.length || panes.length === 1 ? next : null));
|
|
310
|
+
}
|
|
311
|
+
case 'closePane':
|
|
312
|
+
return pane ? finish(layout, replace(layout.root, pane.id, () => null)) : layout;
|
|
313
|
+
case 'insert':
|
|
314
|
+
{
|
|
315
|
+
if (!pane) {
|
|
316
|
+
return layout;
|
|
273
317
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
if (layout.root.type === 'pane' || !Number.isFinite(length) || length <= 0 || !Number.isFinite(gap) || gap < 0) {
|
|
284
|
-
return layout;
|
|
285
|
-
}
|
|
286
|
-
return finish(layout, equalizeAxis(layout.root, command.axis, length, gap));
|
|
318
|
+
const source = panes.find(item => item.views.includes(command.viewId));
|
|
319
|
+
if (source) {
|
|
320
|
+
return updateSplitLayout(layout, {
|
|
321
|
+
type: 'move',
|
|
322
|
+
sourceId: source.id,
|
|
323
|
+
targetId: pane.id,
|
|
324
|
+
viewId: command.viewId,
|
|
325
|
+
index: command.index
|
|
326
|
+
});
|
|
287
327
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
328
|
+
const views = [...pane.views];
|
|
329
|
+
views.splice(Math.max(0, Math.min(views.length, command.index ?? views.length)), 0, command.viewId);
|
|
330
|
+
return finish(layout, replace(layout.root, pane.id, () => ({
|
|
331
|
+
...pane,
|
|
332
|
+
views,
|
|
333
|
+
active: command.viewId
|
|
334
|
+
})), pane.id);
|
|
335
|
+
}
|
|
336
|
+
case 'split':
|
|
337
|
+
return addPane(layout, panes, pane, command);
|
|
338
|
+
case 'swap':
|
|
339
|
+
return swapPanes(layout, panes, command);
|
|
340
|
+
case 'move':
|
|
341
|
+
return moveViews(layout, panes, command);
|
|
342
|
+
case 'equalizeAxis':
|
|
343
|
+
{
|
|
344
|
+
const length = command.length ?? 1;
|
|
345
|
+
const gap = command.gap ?? 0;
|
|
346
|
+
if (layout.root.type === 'pane' || !Number.isFinite(length) || length <= 0 || !Number.isFinite(gap) || gap < 0) {
|
|
347
|
+
return layout;
|
|
348
|
+
}
|
|
349
|
+
return finish(layout, equalizeAxis(layout.root, command.axis, length, gap));
|
|
350
|
+
}
|
|
351
|
+
case 'resize':
|
|
352
|
+
case 'equalize':
|
|
353
|
+
return resizeBranch(layout, command);
|
|
354
|
+
}
|
|
355
|
+
}
|