@zag-js/splitter 1.4.1 → 1.5.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/index.d.mts +125 -75
- package/dist/index.d.ts +125 -75
- package/dist/index.js +793 -364
- package/dist/index.mjs +795 -367
- package/package.json +6 -6
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createAnatomy } from '@zag-js/anatomy';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { trackPointerMove, queryAll, dataAttr, getEventKey, getEventPoint } from '@zag-js/dom-query';
|
|
3
|
+
import { prev, next, ensure, isEqual, setRafTimeout, ensureProps, createSplitProps } from '@zag-js/utils';
|
|
4
4
|
import { createMachine } from '@zag-js/core';
|
|
5
5
|
import { createProps } from '@zag-js/types';
|
|
6
6
|
|
|
@@ -19,17 +19,17 @@ var getCursor = (state, x) => {
|
|
|
19
19
|
if (state.isAtMax) cursor = x ? "w-resize" : "n-resize";
|
|
20
20
|
return cursor;
|
|
21
21
|
};
|
|
22
|
-
var
|
|
23
|
-
|
|
24
|
-
return { flexBasis: 0, flexGrow, flexShrink: 1, overflow: "hidden" };
|
|
22
|
+
var getResizeTriggerEls = (ctx) => {
|
|
23
|
+
return queryAll(getRootEl(ctx), `[role=separator][data-ownedby='${CSS.escape(getRootId(ctx))}']`);
|
|
25
24
|
};
|
|
26
|
-
var setupGlobalCursor = (ctx, state, x) => {
|
|
25
|
+
var setupGlobalCursor = (ctx, state, x, nonce) => {
|
|
27
26
|
const styleEl = ctx.getById(getGlobalCursorId(ctx));
|
|
28
27
|
const textContent = `* { cursor: ${getCursor(state, x)} !important; }`;
|
|
29
28
|
if (styleEl) {
|
|
30
29
|
styleEl.textContent = textContent;
|
|
31
30
|
} else {
|
|
32
31
|
const style = ctx.getDoc().createElement("style");
|
|
32
|
+
if (nonce) style.nonce = nonce;
|
|
33
33
|
style.id = getGlobalCursorId(ctx);
|
|
34
34
|
style.textContent = textContent;
|
|
35
35
|
ctx.getDoc().head.appendChild(style);
|
|
@@ -39,170 +39,255 @@ var removeGlobalCursor = (ctx) => {
|
|
|
39
39
|
const styleEl = ctx.getById(getGlobalCursorId(ctx));
|
|
40
40
|
styleEl?.remove();
|
|
41
41
|
};
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
function getNormalizedPanels(sizes) {
|
|
50
|
-
let numOfPanelsWithoutSize = 0;
|
|
51
|
-
let totalSize = 0;
|
|
42
|
+
function calculateAriaValues({
|
|
43
|
+
size,
|
|
44
|
+
panels,
|
|
45
|
+
pivotIndices
|
|
46
|
+
}) {
|
|
47
|
+
let currentMinSize = 0;
|
|
48
|
+
let currentMaxSize = 100;
|
|
52
49
|
let totalMinSize = 0;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
50
|
+
let totalMaxSize = 0;
|
|
51
|
+
const firstIndex = pivotIndices[0];
|
|
52
|
+
ensure(firstIndex, "No pivot index found");
|
|
53
|
+
panels.forEach((panel, index) => {
|
|
54
|
+
const { maxSize = 100, minSize = 0 } = panel;
|
|
55
|
+
if (index === firstIndex) {
|
|
56
|
+
currentMinSize = minSize;
|
|
57
|
+
currentMaxSize = maxSize;
|
|
59
58
|
} else {
|
|
60
|
-
|
|
59
|
+
totalMinSize += minSize;
|
|
60
|
+
totalMaxSize += maxSize;
|
|
61
61
|
}
|
|
62
|
-
return {
|
|
63
|
-
...panel,
|
|
64
|
-
minSize,
|
|
65
|
-
maxSize
|
|
66
|
-
};
|
|
67
62
|
});
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
remainingSize = panel.size - panel.minSize;
|
|
77
|
-
return {
|
|
78
|
-
...panel,
|
|
79
|
-
start,
|
|
80
|
-
end,
|
|
81
|
-
remainingSize
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
const size = (100 - totalSize) / numOfPanelsWithoutSize;
|
|
85
|
-
end += size;
|
|
86
|
-
remainingSize = size - panel.minSize;
|
|
87
|
-
return { ...panel, size, start, end, remainingSize };
|
|
88
|
-
});
|
|
89
|
-
return result;
|
|
63
|
+
const valueMax = Math.min(currentMaxSize, 100 - totalMinSize);
|
|
64
|
+
const valueMin = Math.max(currentMinSize, 100 - totalMaxSize);
|
|
65
|
+
const valueNow = size[firstIndex];
|
|
66
|
+
return {
|
|
67
|
+
valueMax,
|
|
68
|
+
valueMin,
|
|
69
|
+
valueNow
|
|
70
|
+
};
|
|
90
71
|
}
|
|
91
|
-
function
|
|
92
|
-
const [beforeId, afterId] =
|
|
93
|
-
if (!beforeId || !afterId) return;
|
|
72
|
+
function getAriaValue(size, panels, handleId) {
|
|
73
|
+
const [beforeId, afterId] = handleId.split(":");
|
|
94
74
|
const beforeIndex = panels.findIndex((panel) => panel.id === beforeId);
|
|
95
75
|
const afterIndex = panels.findIndex((panel) => panel.id === afterId);
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
76
|
+
const { valueMax, valueMin, valueNow } = calculateAriaValues({
|
|
77
|
+
size,
|
|
78
|
+
panels,
|
|
79
|
+
pivotIndices: [beforeIndex, afterIndex]
|
|
80
|
+
});
|
|
99
81
|
return {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
...after,
|
|
106
|
-
index: afterIndex
|
|
107
|
-
}
|
|
82
|
+
beforeId,
|
|
83
|
+
afterId,
|
|
84
|
+
valueMax: Math.round(valueMax),
|
|
85
|
+
valueMin: Math.round(valueMin),
|
|
86
|
+
valueNow: valueNow != null ? Math.round(valueNow) : void 0
|
|
108
87
|
};
|
|
109
88
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
89
|
+
|
|
90
|
+
// src/utils/fuzzy.ts
|
|
91
|
+
var PRECISION = 10;
|
|
92
|
+
function fuzzyCompareNumbers(actual, expected, fractionDigits = PRECISION) {
|
|
93
|
+
if (actual.toFixed(fractionDigits) === expected.toFixed(fractionDigits)) {
|
|
94
|
+
return 0;
|
|
95
|
+
} else {
|
|
96
|
+
return actual > expected ? 1 : -1;
|
|
97
|
+
}
|
|
118
98
|
}
|
|
119
|
-
function
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
max: beforeMax,
|
|
133
|
-
isAtMin: beforeMin === before.size,
|
|
134
|
-
isAtMax: beforeMax === before.size,
|
|
135
|
-
up(step) {
|
|
136
|
-
return Math.min(before.size + step, beforeMax);
|
|
137
|
-
},
|
|
138
|
-
down(step) {
|
|
139
|
-
return Math.max(before.size - step, beforeMin);
|
|
140
|
-
}
|
|
141
|
-
},
|
|
142
|
-
after: {
|
|
143
|
-
index: after.index,
|
|
144
|
-
min: afterMin,
|
|
145
|
-
max: afterMax,
|
|
146
|
-
isAtMin: afterMin === after.size,
|
|
147
|
-
isAtMax: afterMax === after.size,
|
|
148
|
-
up(step) {
|
|
149
|
-
return Math.min(after.size + step, afterMin);
|
|
150
|
-
},
|
|
151
|
-
down(step) {
|
|
152
|
-
return Math.max(after.size - step, afterMax);
|
|
153
|
-
}
|
|
99
|
+
function fuzzyNumbersEqual(actual, expected, fractionDigits = PRECISION) {
|
|
100
|
+
if (actual == null || expected == null) return false;
|
|
101
|
+
return fuzzyCompareNumbers(actual, expected, fractionDigits) === 0;
|
|
102
|
+
}
|
|
103
|
+
function fuzzySizeEqual(actual, expected, fractionDigits) {
|
|
104
|
+
if (actual.length !== expected.length) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
for (let index = 0; index < actual.length; index++) {
|
|
108
|
+
const actualSize = actual[index];
|
|
109
|
+
const expectedSize = expected[index];
|
|
110
|
+
if (!fuzzyNumbersEqual(actualSize, expectedSize, fractionDigits)) {
|
|
111
|
+
return false;
|
|
154
112
|
}
|
|
113
|
+
}
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
function getPanelById(panels, id) {
|
|
117
|
+
const panel = panels.find((panel2) => panel2.id === id);
|
|
118
|
+
ensure(panel, `Panel data not found for id "${id}"`);
|
|
119
|
+
return panel;
|
|
120
|
+
}
|
|
121
|
+
function findPanelDataIndex(panels, panel) {
|
|
122
|
+
return panels.findIndex((prevPanel) => prevPanel === panel || prevPanel.id === panel.id);
|
|
123
|
+
}
|
|
124
|
+
function findPanelIndex(panels, id) {
|
|
125
|
+
return panels.findIndex((panel) => panel.id === id);
|
|
126
|
+
}
|
|
127
|
+
function panelDataHelper(panels, panel, sizes) {
|
|
128
|
+
const index = findPanelIndex(panels, panel.id);
|
|
129
|
+
const pivotIndices = index === panels.length - 1 ? [index - 1, index] : [index, index + 1];
|
|
130
|
+
const panelSize = sizes[index];
|
|
131
|
+
return { ...panel, panelSize, pivotIndices };
|
|
132
|
+
}
|
|
133
|
+
function sortPanels(panels) {
|
|
134
|
+
return panels.sort((panelA, panelB) => {
|
|
135
|
+
const orderA = panelA.order;
|
|
136
|
+
const orderB = panelB.order;
|
|
137
|
+
if (orderA == null && orderB == null) {
|
|
138
|
+
return 0;
|
|
139
|
+
} else if (orderA == null) {
|
|
140
|
+
return -1;
|
|
141
|
+
} else if (orderB == null) {
|
|
142
|
+
return 1;
|
|
143
|
+
} else {
|
|
144
|
+
return orderA - orderB;
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
function getPanelLayout(panels) {
|
|
149
|
+
return panels.map((panel) => panel.id).sort().join(":");
|
|
150
|
+
}
|
|
151
|
+
function serializePanels(panels) {
|
|
152
|
+
const keys = panels.map((panel) => panel.id);
|
|
153
|
+
const sortedKeys = keys.sort();
|
|
154
|
+
const serialized = sortedKeys.map((key) => {
|
|
155
|
+
const panel = panels.find((panel2) => panel2.id === key);
|
|
156
|
+
return JSON.stringify(panel);
|
|
157
|
+
});
|
|
158
|
+
return serialized.join(",");
|
|
159
|
+
}
|
|
160
|
+
function getPanelFlexBoxStyle({
|
|
161
|
+
defaultSize,
|
|
162
|
+
dragState,
|
|
163
|
+
sizes,
|
|
164
|
+
panels,
|
|
165
|
+
panelIndex,
|
|
166
|
+
precision = 3
|
|
167
|
+
}) {
|
|
168
|
+
const size = sizes[panelIndex];
|
|
169
|
+
let flexGrow;
|
|
170
|
+
if (size == null) {
|
|
171
|
+
flexGrow = defaultSize != void 0 ? defaultSize.toPrecision(precision) : "1";
|
|
172
|
+
} else if (panels.length === 1) {
|
|
173
|
+
flexGrow = "1";
|
|
174
|
+
} else {
|
|
175
|
+
flexGrow = size.toPrecision(precision);
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
flexBasis: 0,
|
|
179
|
+
flexGrow,
|
|
180
|
+
flexShrink: 1,
|
|
181
|
+
// Without this, Panel sizes may be unintentionally overridden by their content
|
|
182
|
+
overflow: "hidden",
|
|
183
|
+
// Disable pointer events inside of a panel during resize
|
|
184
|
+
// This avoid edge cases like nested iframes
|
|
185
|
+
pointerEvents: dragState !== null ? "none" : void 0
|
|
155
186
|
};
|
|
156
187
|
}
|
|
157
|
-
function
|
|
158
|
-
|
|
188
|
+
function getUnsafeDefaultSize({ panels, size: sizes }) {
|
|
189
|
+
const finalSizes = Array(panels.length);
|
|
190
|
+
let numPanelsWithSizes = 0;
|
|
191
|
+
let remainingSize = 100;
|
|
192
|
+
for (let index = 0; index < panels.length; index++) {
|
|
193
|
+
const panel = panels[index];
|
|
194
|
+
ensure(panel, `Panel data not found for index ${index}`);
|
|
195
|
+
const defaultSize = sizes[index];
|
|
196
|
+
if (defaultSize != null) {
|
|
197
|
+
numPanelsWithSizes++;
|
|
198
|
+
finalSizes[index] = defaultSize;
|
|
199
|
+
remainingSize -= defaultSize;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
for (let index = 0; index < panels.length; index++) {
|
|
203
|
+
const panel = panels[index];
|
|
204
|
+
ensure(panel, `Panel data not found for index ${index}`);
|
|
205
|
+
const defaultSize = sizes[index];
|
|
206
|
+
if (defaultSize != null) {
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
const numRemainingPanels = panels.length - numPanelsWithSizes;
|
|
210
|
+
const size = remainingSize / numRemainingPanels;
|
|
211
|
+
numPanelsWithSizes++;
|
|
212
|
+
finalSizes[index] = size;
|
|
213
|
+
remainingSize -= size;
|
|
214
|
+
}
|
|
215
|
+
return finalSizes;
|
|
159
216
|
}
|
|
160
217
|
|
|
161
218
|
// src/splitter.connect.ts
|
|
162
219
|
function connect(service, normalize) {
|
|
163
220
|
const { state, send, prop, computed, context, scope } = service;
|
|
164
|
-
const horizontal = computed("
|
|
165
|
-
const focused = state.hasTag("focus");
|
|
221
|
+
const horizontal = computed("horizontal");
|
|
166
222
|
const dragging = state.matches("dragging");
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
const
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
value: 0
|
|
181
|
-
};
|
|
182
|
-
}
|
|
223
|
+
const getPanelStyle = (id) => {
|
|
224
|
+
const panels = prop("panels");
|
|
225
|
+
const panelIndex = panels.findIndex((panel) => panel.id === id);
|
|
226
|
+
const defaultSize = context.initial("size")[panelIndex];
|
|
227
|
+
const dragState = context.get("dragState");
|
|
228
|
+
return getPanelFlexBoxStyle({
|
|
229
|
+
defaultSize,
|
|
230
|
+
dragState,
|
|
231
|
+
sizes: context.get("size"),
|
|
232
|
+
panels,
|
|
233
|
+
panelIndex
|
|
234
|
+
});
|
|
235
|
+
};
|
|
183
236
|
return {
|
|
184
|
-
focused,
|
|
185
237
|
dragging,
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
238
|
+
getItems() {
|
|
239
|
+
return prop("panels").flatMap((panel, index, arr) => {
|
|
240
|
+
const nextPanel = arr[index + 1];
|
|
241
|
+
if (panel && nextPanel) {
|
|
242
|
+
return [
|
|
243
|
+
{ type: "panel", id: panel.id },
|
|
244
|
+
{ type: "handle", id: `${panel.id}:${nextPanel.id}` }
|
|
245
|
+
];
|
|
246
|
+
}
|
|
247
|
+
return [{ type: "panel", id: panel.id }];
|
|
248
|
+
});
|
|
249
|
+
},
|
|
250
|
+
getSizes() {
|
|
251
|
+
return context.get("size");
|
|
191
252
|
},
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
send({ type: "SIZE.SET", id, size: panel?.maxSize, src: "setToMaxSize" });
|
|
253
|
+
setSizes(size) {
|
|
254
|
+
send({ type: "SIZE.SET", size });
|
|
195
255
|
},
|
|
196
|
-
|
|
197
|
-
send({ type: "
|
|
256
|
+
collapsePanel(id) {
|
|
257
|
+
send({ type: "PANEL.COLLAPSE", id });
|
|
198
258
|
},
|
|
199
|
-
|
|
200
|
-
send({ type: "
|
|
259
|
+
expandPanel(id, minSize) {
|
|
260
|
+
send({ type: "PANEL.EXPAND", id, minSize });
|
|
201
261
|
},
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
262
|
+
resizePanel(id, unsafePanelSize) {
|
|
263
|
+
send({ type: "PANEL.RESIZE", id, size: unsafePanelSize });
|
|
264
|
+
},
|
|
265
|
+
getPanelSize(id) {
|
|
266
|
+
const panels = prop("panels");
|
|
267
|
+
const size = context.get("size");
|
|
268
|
+
const panelData = getPanelById(panels, id);
|
|
269
|
+
const { panelSize } = panelDataHelper(panels, panelData, size);
|
|
270
|
+
ensure(panelSize, `Panel size not found for panel "${panelData.id}"`);
|
|
271
|
+
return panelSize;
|
|
272
|
+
},
|
|
273
|
+
isPanelCollapsed(id) {
|
|
274
|
+
const panels = prop("panels");
|
|
275
|
+
const size = context.get("size");
|
|
276
|
+
const panelData = getPanelById(panels, id);
|
|
277
|
+
const { collapsedSize = 0, collapsible, panelSize } = panelDataHelper(panels, panelData, size);
|
|
278
|
+
ensure(panelSize, `Panel size not found for panel "${panelData.id}"`);
|
|
279
|
+
return collapsible === true && fuzzyNumbersEqual(panelSize, collapsedSize);
|
|
280
|
+
},
|
|
281
|
+
isPanelExpanded(id) {
|
|
282
|
+
const panels = prop("panels");
|
|
283
|
+
const size = context.get("size");
|
|
284
|
+
const panelData = getPanelById(panels, id);
|
|
285
|
+
const { collapsedSize = 0, collapsible, panelSize } = panelDataHelper(panels, panelData, size);
|
|
286
|
+
ensure(panelSize, `Panel size not found for panel "${panelData.id}"`);
|
|
287
|
+
return !collapsible || fuzzyCompareNumbers(panelSize, collapsedSize) > 0;
|
|
288
|
+
},
|
|
289
|
+
getLayout() {
|
|
290
|
+
return getPanelLayout(prop("panels"));
|
|
206
291
|
},
|
|
207
292
|
getRootProps() {
|
|
208
293
|
return normalize.element({
|
|
@@ -225,44 +310,51 @@ function connect(service, normalize) {
|
|
|
225
310
|
...parts.panel.attrs,
|
|
226
311
|
"data-orientation": prop("orientation"),
|
|
227
312
|
dir: prop("dir"),
|
|
313
|
+
"data-id": id,
|
|
314
|
+
"data-index": findPanelIndex(prop("panels"), id),
|
|
228
315
|
id: getPanelId(scope, id),
|
|
229
316
|
"data-ownedby": getRootId(scope),
|
|
230
|
-
style: getPanelStyle(
|
|
317
|
+
style: getPanelStyle(id)
|
|
231
318
|
});
|
|
232
319
|
},
|
|
233
320
|
getResizeTriggerProps(props2) {
|
|
234
|
-
const { id, disabled
|
|
235
|
-
const
|
|
321
|
+
const { id, disabled } = props2;
|
|
322
|
+
const aria = getAriaValue(context.get("size"), prop("panels"), id);
|
|
323
|
+
const dragging2 = context.get("dragState")?.resizeTriggerId === id;
|
|
324
|
+
const focused = dragging2 || context.get("keyboardState")?.resizeTriggerId === id;
|
|
236
325
|
return normalize.element({
|
|
237
326
|
...parts.resizeTrigger.attrs,
|
|
238
327
|
dir: prop("dir"),
|
|
239
328
|
id: getResizeTriggerId(scope, id),
|
|
240
329
|
role: "separator",
|
|
330
|
+
"data-id": id,
|
|
241
331
|
"data-ownedby": getRootId(scope),
|
|
242
332
|
tabIndex: disabled ? void 0 : 0,
|
|
243
|
-
"aria-valuenow":
|
|
244
|
-
"aria-valuemin":
|
|
245
|
-
"aria-valuemax":
|
|
333
|
+
"aria-valuenow": aria.valueNow,
|
|
334
|
+
"aria-valuemin": aria.valueMin,
|
|
335
|
+
"aria-valuemax": aria.valueMax,
|
|
246
336
|
"data-orientation": prop("orientation"),
|
|
247
337
|
"aria-orientation": prop("orientation"),
|
|
248
|
-
"aria-controls":
|
|
249
|
-
"data-focus": dataAttr(
|
|
338
|
+
"aria-controls": `${getPanelId(scope, aria.beforeId)} ${getPanelId(scope, aria.afterId)}`,
|
|
339
|
+
"data-focus": dataAttr(focused),
|
|
250
340
|
"data-disabled": dataAttr(disabled),
|
|
251
341
|
style: {
|
|
252
342
|
touchAction: "none",
|
|
253
343
|
userSelect: "none",
|
|
254
344
|
WebkitUserSelect: "none",
|
|
255
345
|
flex: "0 0 auto",
|
|
256
|
-
pointerEvents:
|
|
346
|
+
pointerEvents: dragging2 && !focused ? "none" : void 0,
|
|
257
347
|
cursor: horizontal ? "col-resize" : "row-resize",
|
|
258
348
|
[horizontal ? "minHeight" : "minWidth"]: "0"
|
|
259
349
|
},
|
|
260
350
|
onPointerDown(event) {
|
|
351
|
+
if (event.button !== 0) return;
|
|
261
352
|
if (disabled) {
|
|
262
353
|
event.preventDefault();
|
|
263
354
|
return;
|
|
264
355
|
}
|
|
265
|
-
|
|
356
|
+
const point = getEventPoint(event);
|
|
357
|
+
send({ type: "POINTER_DOWN", id, point });
|
|
266
358
|
event.currentTarget.setPointerCapture(event.pointerId);
|
|
267
359
|
event.preventDefault();
|
|
268
360
|
event.stopPropagation();
|
|
@@ -282,40 +374,49 @@ function connect(service, normalize) {
|
|
|
282
374
|
send({ type: "POINTER_LEAVE", id });
|
|
283
375
|
},
|
|
284
376
|
onBlur() {
|
|
377
|
+
if (disabled) return;
|
|
285
378
|
send({ type: "BLUR" });
|
|
286
379
|
},
|
|
287
380
|
onFocus() {
|
|
288
|
-
send({ type: "FOCUS", id });
|
|
289
|
-
},
|
|
290
|
-
onDoubleClick() {
|
|
291
381
|
if (disabled) return;
|
|
292
|
-
send({ type: "
|
|
382
|
+
send({ type: "FOCUS", id });
|
|
293
383
|
},
|
|
294
384
|
onKeyDown(event) {
|
|
295
385
|
if (event.defaultPrevented) return;
|
|
296
386
|
if (disabled) return;
|
|
297
|
-
const
|
|
387
|
+
const keyboardResizeBy = prop("keyboardResizeBy");
|
|
388
|
+
let delta = 0;
|
|
389
|
+
if (event.shiftKey) {
|
|
390
|
+
delta = 10;
|
|
391
|
+
} else if (keyboardResizeBy != null) {
|
|
392
|
+
delta = keyboardResizeBy;
|
|
393
|
+
} else {
|
|
394
|
+
delta = 1;
|
|
395
|
+
}
|
|
298
396
|
const keyMap = {
|
|
299
397
|
Enter() {
|
|
300
|
-
send({ type: "ENTER" });
|
|
398
|
+
send({ type: "ENTER", id });
|
|
301
399
|
},
|
|
302
400
|
ArrowUp() {
|
|
303
|
-
send({ type: "
|
|
401
|
+
send({ type: "KEYBOARD_MOVE", id, delta: horizontal ? 0 : delta });
|
|
304
402
|
},
|
|
305
403
|
ArrowDown() {
|
|
306
|
-
send({ type: "
|
|
404
|
+
send({ type: "KEYBOARD_MOVE", id, delta: horizontal ? 0 : delta });
|
|
307
405
|
},
|
|
308
406
|
ArrowLeft() {
|
|
309
|
-
send({ type: "
|
|
407
|
+
send({ type: "KEYBOARD_MOVE", id, delta: horizontal ? -delta : 0 });
|
|
310
408
|
},
|
|
311
409
|
ArrowRight() {
|
|
312
|
-
send({ type: "
|
|
410
|
+
send({ type: "KEYBOARD_MOVE", id, delta: horizontal ? delta : 0 });
|
|
313
411
|
},
|
|
314
412
|
Home() {
|
|
315
|
-
send({ type: "
|
|
413
|
+
send({ type: "KEYBOARD_MOVE", id, delta: -100 });
|
|
316
414
|
},
|
|
317
415
|
End() {
|
|
318
|
-
send({ type: "
|
|
416
|
+
send({ type: "KEYBOARD_MOVE", id, delta: 100 });
|
|
417
|
+
},
|
|
418
|
+
F6() {
|
|
419
|
+
send({ type: "FOCUS.CYCLE", id, shiftKey: event.shiftKey });
|
|
319
420
|
}
|
|
320
421
|
};
|
|
321
422
|
const key = getEventKey(event, {
|
|
@@ -332,81 +433,295 @@ function connect(service, normalize) {
|
|
|
332
433
|
}
|
|
333
434
|
};
|
|
334
435
|
}
|
|
436
|
+
function resizePanel({ panels, index, size }) {
|
|
437
|
+
const panel = panels[index];
|
|
438
|
+
ensure(panel, `Panel data not found for index ${index}`);
|
|
439
|
+
let { collapsedSize = 0, collapsible, maxSize = 100, minSize = 0 } = panel;
|
|
440
|
+
if (fuzzyCompareNumbers(size, minSize) < 0) {
|
|
441
|
+
if (collapsible) {
|
|
442
|
+
const halfwayPoint = (collapsedSize + minSize) / 2;
|
|
443
|
+
if (fuzzyCompareNumbers(size, halfwayPoint) < 0) {
|
|
444
|
+
size = collapsedSize;
|
|
445
|
+
} else {
|
|
446
|
+
size = minSize;
|
|
447
|
+
}
|
|
448
|
+
} else {
|
|
449
|
+
size = minSize;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
size = Math.min(maxSize, size);
|
|
453
|
+
size = parseFloat(size.toFixed(PRECISION));
|
|
454
|
+
return size;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// src/utils/resize-by-delta.ts
|
|
458
|
+
function resizeByDelta(props2) {
|
|
459
|
+
let { delta, initialSize, panels, pivotIndices, prevSize, trigger } = props2;
|
|
460
|
+
if (fuzzyNumbersEqual(delta, 0)) {
|
|
461
|
+
return initialSize;
|
|
462
|
+
}
|
|
463
|
+
const nextSize = [...initialSize];
|
|
464
|
+
const [firstPivotIndex, secondPivotIndex] = pivotIndices;
|
|
465
|
+
ensure(firstPivotIndex, "Invalid first pivot index");
|
|
466
|
+
ensure(secondPivotIndex, "Invalid second pivot index");
|
|
467
|
+
let deltaApplied = 0;
|
|
468
|
+
{
|
|
469
|
+
if (trigger === "keyboard") {
|
|
470
|
+
{
|
|
471
|
+
const index = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
472
|
+
const panel = panels[index];
|
|
473
|
+
ensure(panel, `Panel data not found for index ${index}`);
|
|
474
|
+
const { collapsedSize = 0, collapsible, minSize = 0 } = panel;
|
|
475
|
+
if (collapsible) {
|
|
476
|
+
const prevSize2 = initialSize[index];
|
|
477
|
+
ensure(prevSize2, `Previous size not found for panel index ${index}`);
|
|
478
|
+
if (fuzzyNumbersEqual(prevSize2, collapsedSize)) {
|
|
479
|
+
const localDelta = minSize - prevSize2;
|
|
480
|
+
if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
|
|
481
|
+
delta = delta < 0 ? 0 - localDelta : localDelta;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
{
|
|
487
|
+
const index = delta < 0 ? firstPivotIndex : secondPivotIndex;
|
|
488
|
+
const panel = panels[index];
|
|
489
|
+
ensure(panel, `No panel data found for index ${index}`);
|
|
490
|
+
const { collapsedSize = 0, collapsible, minSize = 0 } = panel;
|
|
491
|
+
if (collapsible) {
|
|
492
|
+
const prevSize2 = initialSize[index];
|
|
493
|
+
ensure(prevSize2, `Previous size not found for panel index ${index}`);
|
|
494
|
+
if (fuzzyNumbersEqual(prevSize2, minSize)) {
|
|
495
|
+
const localDelta = prevSize2 - collapsedSize;
|
|
496
|
+
if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
|
|
497
|
+
delta = delta < 0 ? 0 - localDelta : localDelta;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
{
|
|
505
|
+
const increment = delta < 0 ? 1 : -1;
|
|
506
|
+
let index = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
507
|
+
let maxAvailableDelta = 0;
|
|
508
|
+
while (true) {
|
|
509
|
+
const prevSize2 = initialSize[index];
|
|
510
|
+
ensure(prevSize2, `Previous size not found for panel index ${index}`);
|
|
511
|
+
const maxSafeSize = resizePanel({
|
|
512
|
+
panels,
|
|
513
|
+
index,
|
|
514
|
+
size: 100
|
|
515
|
+
});
|
|
516
|
+
const delta2 = maxSafeSize - prevSize2;
|
|
517
|
+
maxAvailableDelta += delta2;
|
|
518
|
+
index += increment;
|
|
519
|
+
if (index < 0 || index >= panels.length) {
|
|
520
|
+
break;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
const minAbsDelta = Math.min(Math.abs(delta), Math.abs(maxAvailableDelta));
|
|
524
|
+
delta = delta < 0 ? 0 - minAbsDelta : minAbsDelta;
|
|
525
|
+
}
|
|
526
|
+
{
|
|
527
|
+
const pivotIndex = delta < 0 ? firstPivotIndex : secondPivotIndex;
|
|
528
|
+
let index = pivotIndex;
|
|
529
|
+
while (index >= 0 && index < panels.length) {
|
|
530
|
+
const deltaRemaining = Math.abs(delta) - Math.abs(deltaApplied);
|
|
531
|
+
const prevSize2 = initialSize[index];
|
|
532
|
+
ensure(prevSize2, `Previous size not found for panel index ${index}`);
|
|
533
|
+
const unsafeSize = prevSize2 - deltaRemaining;
|
|
534
|
+
const safeSize = resizePanel({ panels, index, size: unsafeSize });
|
|
535
|
+
if (!fuzzyNumbersEqual(prevSize2, safeSize)) {
|
|
536
|
+
deltaApplied += prevSize2 - safeSize;
|
|
537
|
+
nextSize[index] = safeSize;
|
|
538
|
+
if (deltaApplied.toPrecision(3).localeCompare(Math.abs(delta).toPrecision(3), void 0, {
|
|
539
|
+
numeric: true
|
|
540
|
+
}) >= 0) {
|
|
541
|
+
break;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
if (delta < 0) {
|
|
545
|
+
index--;
|
|
546
|
+
} else {
|
|
547
|
+
index++;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
if (fuzzySizeEqual(prevSize, nextSize)) {
|
|
552
|
+
return prevSize;
|
|
553
|
+
}
|
|
554
|
+
{
|
|
555
|
+
const pivotIndex = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
556
|
+
const prevSize2 = initialSize[pivotIndex];
|
|
557
|
+
ensure(prevSize2, `Previous size not found for panel index ${pivotIndex}`);
|
|
558
|
+
const unsafeSize = prevSize2 + deltaApplied;
|
|
559
|
+
const safeSize = resizePanel({ panels, index: pivotIndex, size: unsafeSize });
|
|
560
|
+
nextSize[pivotIndex] = safeSize;
|
|
561
|
+
if (!fuzzyNumbersEqual(safeSize, unsafeSize)) {
|
|
562
|
+
let deltaRemaining = unsafeSize - safeSize;
|
|
563
|
+
const pivotIndex2 = delta < 0 ? secondPivotIndex : firstPivotIndex;
|
|
564
|
+
let index = pivotIndex2;
|
|
565
|
+
while (index >= 0 && index < panels.length) {
|
|
566
|
+
const prevSize3 = nextSize[index];
|
|
567
|
+
ensure(prevSize3, `Previous size not found for panel index ${index}`);
|
|
568
|
+
const unsafeSize2 = prevSize3 + deltaRemaining;
|
|
569
|
+
const safeSize2 = resizePanel({ panels, index, size: unsafeSize2 });
|
|
570
|
+
if (!fuzzyNumbersEqual(prevSize3, safeSize2)) {
|
|
571
|
+
deltaRemaining -= safeSize2 - prevSize3;
|
|
572
|
+
nextSize[index] = safeSize2;
|
|
573
|
+
}
|
|
574
|
+
if (fuzzyNumbersEqual(deltaRemaining, 0)) {
|
|
575
|
+
break;
|
|
576
|
+
}
|
|
577
|
+
if (delta > 0) {
|
|
578
|
+
index--;
|
|
579
|
+
} else {
|
|
580
|
+
index++;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
const totalSize = nextSize.reduce((total, size) => size + total, 0);
|
|
586
|
+
if (!fuzzyNumbersEqual(totalSize, 100)) {
|
|
587
|
+
return prevSize;
|
|
588
|
+
}
|
|
589
|
+
return nextSize;
|
|
590
|
+
}
|
|
591
|
+
function validateSizes({ size: prevSize, panels }) {
|
|
592
|
+
const nextSize = [...prevSize];
|
|
593
|
+
const nextSizeTotalSize = nextSize.reduce((accumulated, current) => accumulated + current, 0);
|
|
594
|
+
if (nextSize.length !== panels.length) {
|
|
595
|
+
throw Error(`Invalid ${panels.length} panel size: ${nextSize.map((size) => `${size}%`).join(", ")}`);
|
|
596
|
+
} else if (!fuzzyNumbersEqual(nextSizeTotalSize, 100) && nextSize.length > 0) {
|
|
597
|
+
for (let index = 0; index < panels.length; index++) {
|
|
598
|
+
const unsafeSize = nextSize[index];
|
|
599
|
+
ensure(unsafeSize, `No size data found for index ${index}`);
|
|
600
|
+
const safeSize = 100 / nextSizeTotalSize * unsafeSize;
|
|
601
|
+
nextSize[index] = safeSize;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
let remainingSize = 0;
|
|
605
|
+
for (let index = 0; index < panels.length; index++) {
|
|
606
|
+
const unsafeSize = nextSize[index];
|
|
607
|
+
ensure(unsafeSize, `No size data found for index ${index}`);
|
|
608
|
+
const safeSize = resizePanel({ panels, index, size: unsafeSize });
|
|
609
|
+
if (unsafeSize != safeSize) {
|
|
610
|
+
remainingSize += unsafeSize - safeSize;
|
|
611
|
+
nextSize[index] = safeSize;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
if (!fuzzyNumbersEqual(remainingSize, 0)) {
|
|
615
|
+
for (let index = 0; index < panels.length; index++) {
|
|
616
|
+
const prevSize2 = nextSize[index];
|
|
617
|
+
ensure(prevSize2, `No size data found for index ${index}`);
|
|
618
|
+
const unsafeSize = prevSize2 + remainingSize;
|
|
619
|
+
const safeSize = resizePanel({ panels, index, size: unsafeSize });
|
|
620
|
+
if (prevSize2 !== safeSize) {
|
|
621
|
+
remainingSize -= safeSize - prevSize2;
|
|
622
|
+
nextSize[index] = safeSize;
|
|
623
|
+
if (fuzzyNumbersEqual(remainingSize, 0)) {
|
|
624
|
+
break;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
return nextSize;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// src/splitter.machine.ts
|
|
335
633
|
var machine = createMachine({
|
|
336
634
|
props({ props: props2 }) {
|
|
635
|
+
ensureProps(props2, ["panels"]);
|
|
337
636
|
return {
|
|
338
637
|
orientation: "horizontal",
|
|
339
638
|
defaultSize: [],
|
|
340
|
-
|
|
639
|
+
dir: "ltr",
|
|
640
|
+
...props2,
|
|
641
|
+
panels: sortPanels(props2.panels)
|
|
341
642
|
};
|
|
342
643
|
},
|
|
343
644
|
initialState() {
|
|
344
645
|
return "idle";
|
|
345
646
|
},
|
|
346
|
-
context({ prop, bindable, getContext }) {
|
|
647
|
+
context({ prop, bindable, getContext, getRefs }) {
|
|
347
648
|
return {
|
|
348
|
-
activeResizeId: bindable(() => ({
|
|
349
|
-
defaultValue: null
|
|
350
|
-
})),
|
|
351
649
|
size: bindable(() => ({
|
|
352
|
-
defaultValue: prop("defaultSize"),
|
|
353
650
|
value: prop("size"),
|
|
354
|
-
|
|
355
|
-
|
|
651
|
+
defaultValue: prop("defaultSize"),
|
|
652
|
+
isEqual(a, b) {
|
|
653
|
+
return b != null && fuzzySizeEqual(a, b);
|
|
356
654
|
},
|
|
357
655
|
onChange(value) {
|
|
358
|
-
const
|
|
359
|
-
|
|
656
|
+
const ctx = getContext();
|
|
657
|
+
const refs = getRefs();
|
|
658
|
+
const sizesBeforeCollapse = refs.get("panelSizeBeforeCollapse");
|
|
659
|
+
const expandToSizes = Object.fromEntries(sizesBeforeCollapse.entries());
|
|
660
|
+
const resizeTriggerId = ctx.get("dragState")?.resizeTriggerId ?? null;
|
|
661
|
+
const layout = getPanelLayout(prop("panels"));
|
|
662
|
+
prop("onResize")?.({
|
|
360
663
|
size: value,
|
|
361
|
-
|
|
664
|
+
layout,
|
|
665
|
+
resizeTriggerId,
|
|
666
|
+
expandToSizes
|
|
362
667
|
});
|
|
363
668
|
}
|
|
364
669
|
})),
|
|
365
|
-
|
|
366
|
-
defaultValue:
|
|
670
|
+
dragState: bindable(() => ({
|
|
671
|
+
defaultValue: null
|
|
672
|
+
})),
|
|
673
|
+
keyboardState: bindable(() => ({
|
|
674
|
+
defaultValue: null
|
|
367
675
|
}))
|
|
368
676
|
};
|
|
369
677
|
},
|
|
370
|
-
|
|
678
|
+
watch({ track, action, prop }) {
|
|
679
|
+
track([() => serializePanels(prop("panels"))], () => {
|
|
680
|
+
action(["syncSize"]);
|
|
681
|
+
});
|
|
682
|
+
},
|
|
683
|
+
refs() {
|
|
371
684
|
return {
|
|
372
|
-
|
|
685
|
+
panelSizeBeforeCollapse: /* @__PURE__ */ new Map(),
|
|
686
|
+
prevDelta: 0,
|
|
687
|
+
panelIdToLastNotifiedSizeMap: /* @__PURE__ */ new Map()
|
|
373
688
|
};
|
|
374
689
|
},
|
|
375
|
-
watch({ track, action, context }) {
|
|
376
|
-
track([() => context.hash("size")], () => {
|
|
377
|
-
action(["setActiveResizeState"]);
|
|
378
|
-
});
|
|
379
|
-
},
|
|
380
690
|
computed: {
|
|
381
|
-
|
|
382
|
-
|
|
691
|
+
horizontal({ prop }) {
|
|
692
|
+
return prop("orientation") === "horizontal";
|
|
693
|
+
}
|
|
383
694
|
},
|
|
384
695
|
on: {
|
|
385
696
|
"SIZE.SET": {
|
|
386
|
-
actions: ["
|
|
697
|
+
actions: ["setSize"]
|
|
698
|
+
},
|
|
699
|
+
"PANEL.COLLAPSE": {
|
|
700
|
+
actions: ["collapsePanel"]
|
|
701
|
+
},
|
|
702
|
+
"PANEL.EXPAND": {
|
|
703
|
+
actions: ["expandPanel"]
|
|
387
704
|
},
|
|
388
|
-
"
|
|
389
|
-
actions: ["
|
|
705
|
+
"PANEL.RESIZE": {
|
|
706
|
+
actions: ["resizePanel"]
|
|
390
707
|
}
|
|
391
708
|
},
|
|
709
|
+
entry: ["syncSize"],
|
|
392
710
|
states: {
|
|
393
711
|
idle: {
|
|
394
|
-
entry: ["
|
|
712
|
+
entry: ["clearDraggingState", "clearKeyboardState"],
|
|
395
713
|
on: {
|
|
396
714
|
POINTER_OVER: {
|
|
397
715
|
target: "hover:temp",
|
|
398
|
-
actions: ["
|
|
716
|
+
actions: ["setKeyboardState"]
|
|
399
717
|
},
|
|
400
718
|
FOCUS: {
|
|
401
719
|
target: "focused",
|
|
402
|
-
actions: ["
|
|
720
|
+
actions: ["setKeyboardState"]
|
|
403
721
|
},
|
|
404
722
|
POINTER_DOWN: {
|
|
405
723
|
target: "dragging",
|
|
406
|
-
actions: ["
|
|
407
|
-
},
|
|
408
|
-
DOUBLE_CLICK: {
|
|
409
|
-
actions: ["resetStartPanel", "setPreviousPanels"]
|
|
724
|
+
actions: ["setDraggingState"]
|
|
410
725
|
}
|
|
411
726
|
}
|
|
412
727
|
},
|
|
@@ -418,7 +733,7 @@ var machine = createMachine({
|
|
|
418
733
|
},
|
|
419
734
|
POINTER_DOWN: {
|
|
420
735
|
target: "dragging",
|
|
421
|
-
actions: ["
|
|
736
|
+
actions: ["setDraggingState"]
|
|
422
737
|
},
|
|
423
738
|
POINTER_LEAVE: {
|
|
424
739
|
target: "idle"
|
|
@@ -429,7 +744,8 @@ var machine = createMachine({
|
|
|
429
744
|
tags: ["focus"],
|
|
430
745
|
on: {
|
|
431
746
|
POINTER_DOWN: {
|
|
432
|
-
target: "dragging"
|
|
747
|
+
target: "dragging",
|
|
748
|
+
actions: ["setDraggingState"]
|
|
433
749
|
},
|
|
434
750
|
POINTER_LEAVE: {
|
|
435
751
|
target: "idle"
|
|
@@ -442,52 +758,32 @@ var machine = createMachine({
|
|
|
442
758
|
BLUR: {
|
|
443
759
|
target: "idle"
|
|
444
760
|
},
|
|
761
|
+
ENTER: {
|
|
762
|
+
actions: ["collapseOrExpandPanel"]
|
|
763
|
+
},
|
|
445
764
|
POINTER_DOWN: {
|
|
446
765
|
target: "dragging",
|
|
447
|
-
actions: ["
|
|
448
|
-
},
|
|
449
|
-
ARROW_LEFT: {
|
|
450
|
-
guard: "isHorizontal",
|
|
451
|
-
actions: ["shrinkStartPanel", "setPreviousPanels"]
|
|
452
|
-
},
|
|
453
|
-
ARROW_RIGHT: {
|
|
454
|
-
guard: "isHorizontal",
|
|
455
|
-
actions: ["expandStartPanel", "setPreviousPanels"]
|
|
766
|
+
actions: ["setDraggingState"]
|
|
456
767
|
},
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
actions: ["shrinkStartPanel", "setPreviousPanels"]
|
|
768
|
+
KEYBOARD_MOVE: {
|
|
769
|
+
actions: ["setKeyboardValue"]
|
|
460
770
|
},
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
actions: ["expandStartPanel", "setPreviousPanels"]
|
|
464
|
-
},
|
|
465
|
-
ENTER: [
|
|
466
|
-
{
|
|
467
|
-
guard: "isStartPanelAtMax",
|
|
468
|
-
actions: ["setStartPanelToMin", "setPreviousPanels"]
|
|
469
|
-
},
|
|
470
|
-
{ actions: ["setStartPanelToMax", "setPreviousPanels"] }
|
|
471
|
-
],
|
|
472
|
-
HOME: {
|
|
473
|
-
actions: ["setStartPanelToMin", "setPreviousPanels"]
|
|
474
|
-
},
|
|
475
|
-
END: {
|
|
476
|
-
actions: ["setStartPanelToMax", "setPreviousPanels"]
|
|
771
|
+
"FOCUS.CYCLE": {
|
|
772
|
+
actions: ["focusNextResizeTrigger"]
|
|
477
773
|
}
|
|
478
774
|
}
|
|
479
775
|
},
|
|
480
776
|
dragging: {
|
|
481
777
|
tags: ["focus"],
|
|
482
|
-
entry: ["focusResizeHandle"],
|
|
483
778
|
effects: ["trackPointerMove"],
|
|
779
|
+
entry: ["invokeOnResizeStart"],
|
|
484
780
|
on: {
|
|
485
781
|
POINTER_MOVE: {
|
|
486
|
-
actions: ["setPointerValue", "setGlobalCursor"
|
|
782
|
+
actions: ["setPointerValue", "setGlobalCursor"]
|
|
487
783
|
},
|
|
488
784
|
POINTER_UP: {
|
|
489
|
-
target: "
|
|
490
|
-
actions: ["
|
|
785
|
+
target: "idle",
|
|
786
|
+
actions: ["invokeOnResizeEnd", "clearGlobalCursor"]
|
|
491
787
|
}
|
|
492
788
|
}
|
|
493
789
|
}
|
|
@@ -511,178 +807,310 @@ var machine = createMachine({
|
|
|
511
807
|
});
|
|
512
808
|
}
|
|
513
809
|
},
|
|
514
|
-
guards: {
|
|
515
|
-
isStartPanelAtMin: ({ context }) => context.get("activeResizeState").isAtMin,
|
|
516
|
-
isStartPanelAtMax: ({ context }) => context.get("activeResizeState").isAtMax,
|
|
517
|
-
isHorizontal: ({ prop }) => prop("orientation") === "horizontal",
|
|
518
|
-
isVertical: ({ prop }) => prop("orientation") !== "horizontal"
|
|
519
|
-
},
|
|
520
810
|
actions: {
|
|
521
|
-
|
|
522
|
-
const
|
|
523
|
-
const
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
811
|
+
setSize(params) {
|
|
812
|
+
const { context, event, prop } = params;
|
|
813
|
+
const unsafeSize = event.size;
|
|
814
|
+
const prevSize = context.get("size");
|
|
815
|
+
const panels = prop("panels");
|
|
816
|
+
const safeSize = validateSizes({
|
|
817
|
+
size: unsafeSize,
|
|
818
|
+
panels
|
|
819
|
+
});
|
|
820
|
+
if (!isEqual(prevSize, safeSize)) {
|
|
821
|
+
setSize(params, safeSize);
|
|
822
|
+
}
|
|
528
823
|
},
|
|
529
|
-
|
|
530
|
-
prop("
|
|
531
|
-
|
|
532
|
-
|
|
824
|
+
syncSize({ context, prop }) {
|
|
825
|
+
const panels = prop("panels");
|
|
826
|
+
let prevSize = context.get("size");
|
|
827
|
+
let unsafeSize = null;
|
|
828
|
+
if (prevSize.length === 0) {
|
|
829
|
+
unsafeSize = getUnsafeDefaultSize({
|
|
830
|
+
panels,
|
|
831
|
+
size: context.initial("size")
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
const nextSize = validateSizes({
|
|
835
|
+
size: unsafeSize ?? prevSize,
|
|
836
|
+
panels
|
|
533
837
|
});
|
|
838
|
+
if (!isEqual(prevSize, nextSize)) {
|
|
839
|
+
context.set("size", nextSize);
|
|
840
|
+
}
|
|
534
841
|
},
|
|
535
|
-
|
|
536
|
-
prop("
|
|
537
|
-
|
|
538
|
-
|
|
842
|
+
setDraggingState({ context, event, prop, scope }) {
|
|
843
|
+
const orientation = prop("orientation");
|
|
844
|
+
const size = context.get("size");
|
|
845
|
+
const resizeTriggerId = event.id;
|
|
846
|
+
const panelGroupEl = getRootEl(scope);
|
|
847
|
+
if (!panelGroupEl) return;
|
|
848
|
+
const handleElement = getResizeTriggerEl(scope, resizeTriggerId);
|
|
849
|
+
ensure(handleElement, `Drag handle element not found for id "${resizeTriggerId}"`);
|
|
850
|
+
const initialCursorPosition = orientation === "horizontal" ? event.point.x : event.point.y;
|
|
851
|
+
context.set("dragState", {
|
|
852
|
+
resizeTriggerId: event.id,
|
|
853
|
+
resizeTriggerRect: handleElement.getBoundingClientRect(),
|
|
854
|
+
initialCursorPosition,
|
|
855
|
+
initialSize: size
|
|
539
856
|
});
|
|
540
857
|
},
|
|
541
|
-
|
|
542
|
-
context.set("
|
|
858
|
+
clearDraggingState({ context }) {
|
|
859
|
+
context.set("dragState", null);
|
|
543
860
|
},
|
|
544
|
-
|
|
545
|
-
context.set("
|
|
861
|
+
setKeyboardState({ context, event }) {
|
|
862
|
+
context.set("keyboardState", {
|
|
863
|
+
resizeTriggerId: event.id
|
|
864
|
+
});
|
|
546
865
|
},
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
context.set(
|
|
550
|
-
"size",
|
|
551
|
-
(prev) => prev.map((panel) => {
|
|
552
|
-
const panelSize = clamp(size, panel.minSize ?? 0, panel.maxSize ?? 100);
|
|
553
|
-
return panel.id === id ? { ...panel, size: panelSize } : panel;
|
|
554
|
-
})
|
|
555
|
-
);
|
|
866
|
+
clearKeyboardState({ context }) {
|
|
867
|
+
context.set("keyboardState", null);
|
|
556
868
|
},
|
|
557
|
-
|
|
558
|
-
context
|
|
869
|
+
collapsePanel(params) {
|
|
870
|
+
const { context, prop, event, refs } = params;
|
|
871
|
+
const prevSize = context.get("size");
|
|
872
|
+
const panels = prop("panels");
|
|
873
|
+
const panel = panels.find((panel2) => panel2.id === event.id);
|
|
874
|
+
ensure(panel, `Panel data not found for id "${event.id}"`);
|
|
875
|
+
if (panel.collapsible) {
|
|
876
|
+
const { collapsedSize = 0, panelSize, pivotIndices } = panelDataHelper(panels, panel, prevSize);
|
|
877
|
+
ensure(panelSize, `Panel size not found for panel "${panel.id}"`);
|
|
878
|
+
if (!fuzzyNumbersEqual(panelSize, collapsedSize)) {
|
|
879
|
+
refs.get("panelSizeBeforeCollapse").set(panel.id, panelSize);
|
|
880
|
+
const isLastPanel = findPanelDataIndex(panels, panel) === panels.length - 1;
|
|
881
|
+
const delta = isLastPanel ? panelSize - collapsedSize : collapsedSize - panelSize;
|
|
882
|
+
const nextSize = resizeByDelta({
|
|
883
|
+
delta,
|
|
884
|
+
initialSize: prevSize,
|
|
885
|
+
panels,
|
|
886
|
+
pivotIndices,
|
|
887
|
+
prevSize,
|
|
888
|
+
trigger: "imperative-api"
|
|
889
|
+
});
|
|
890
|
+
if (!isEqual(prevSize, nextSize)) {
|
|
891
|
+
setSize(params, nextSize);
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
}
|
|
559
895
|
},
|
|
560
|
-
|
|
561
|
-
const
|
|
562
|
-
|
|
563
|
-
const
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
896
|
+
expandPanel(params) {
|
|
897
|
+
const { context, prop, event, refs } = params;
|
|
898
|
+
const panels = prop("panels");
|
|
899
|
+
const prevSize = context.get("size");
|
|
900
|
+
const panel = panels.find((panel2) => panel2.id === event.id);
|
|
901
|
+
ensure(panel, `Panel data not found for id "${event.id}"`);
|
|
902
|
+
if (panel.collapsible) {
|
|
903
|
+
const {
|
|
904
|
+
collapsedSize = 0,
|
|
905
|
+
panelSize = 0,
|
|
906
|
+
minSize: minSizeFromProps = 0,
|
|
907
|
+
pivotIndices
|
|
908
|
+
} = panelDataHelper(panels, panel, prevSize);
|
|
909
|
+
const minSize = event.minSize ?? minSizeFromProps;
|
|
910
|
+
if (fuzzyNumbersEqual(panelSize, collapsedSize)) {
|
|
911
|
+
const prevPanelSize = refs.get("panelSizeBeforeCollapse").get(panel.id);
|
|
912
|
+
const baseSize = prevPanelSize != null && prevPanelSize >= minSize ? prevPanelSize : minSize;
|
|
913
|
+
const isLastPanel = findPanelDataIndex(panels, panel) === panels.length - 1;
|
|
914
|
+
const delta = isLastPanel ? panelSize - baseSize : baseSize - panelSize;
|
|
915
|
+
const nextSize = resizeByDelta({
|
|
916
|
+
delta,
|
|
917
|
+
initialSize: prevSize,
|
|
918
|
+
panels,
|
|
919
|
+
pivotIndices,
|
|
920
|
+
prevSize,
|
|
921
|
+
trigger: "imperative-api"
|
|
922
|
+
});
|
|
923
|
+
if (!isEqual(prevSize, nextSize)) {
|
|
924
|
+
setSize(params, nextSize);
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
}
|
|
570
928
|
},
|
|
571
|
-
|
|
572
|
-
const
|
|
573
|
-
|
|
574
|
-
const
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
929
|
+
resizePanel(params) {
|
|
930
|
+
const { context, prop, event } = params;
|
|
931
|
+
const prevSize = context.get("size");
|
|
932
|
+
const panels = prop("panels");
|
|
933
|
+
const panel = getPanelById(panels, event.id);
|
|
934
|
+
const unsafePanelSize = event.size;
|
|
935
|
+
const { panelSize, pivotIndices } = panelDataHelper(panels, panel, prevSize);
|
|
936
|
+
ensure(panelSize, `Panel size not found for panel "${panel.id}"`);
|
|
937
|
+
const isLastPanel = findPanelDataIndex(panels, panel) === panels.length - 1;
|
|
938
|
+
const delta = isLastPanel ? panelSize - unsafePanelSize : unsafePanelSize - panelSize;
|
|
939
|
+
const nextSize = resizeByDelta({
|
|
940
|
+
delta,
|
|
941
|
+
initialSize: prevSize,
|
|
942
|
+
panels,
|
|
943
|
+
pivotIndices,
|
|
944
|
+
prevSize,
|
|
945
|
+
trigger: "imperative-api"
|
|
580
946
|
});
|
|
947
|
+
if (!isEqual(prevSize, nextSize)) {
|
|
948
|
+
setSize(params, nextSize);
|
|
949
|
+
}
|
|
581
950
|
},
|
|
582
|
-
|
|
583
|
-
const
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
951
|
+
setPointerValue(params) {
|
|
952
|
+
const { context, event, prop, scope } = params;
|
|
953
|
+
const dragState = context.get("dragState");
|
|
954
|
+
if (!dragState) return;
|
|
955
|
+
const { resizeTriggerId, initialSize, initialCursorPosition } = dragState;
|
|
956
|
+
const panels = prop("panels");
|
|
957
|
+
const panelGroupElement = getRootEl(scope);
|
|
958
|
+
ensure(panelGroupElement, `Panel group element not found`);
|
|
959
|
+
const pivotIndices = resizeTriggerId.split(":").map((id) => panels.findIndex((panel) => panel.id === id));
|
|
960
|
+
const horizontal = prop("orientation") === "horizontal";
|
|
961
|
+
const cursorPosition = horizontal ? event.point.x : event.point.y;
|
|
962
|
+
const groupRect = panelGroupElement.getBoundingClientRect();
|
|
963
|
+
const groupSizeInPixels = horizontal ? groupRect.width : groupRect.height;
|
|
964
|
+
const offsetPixels = cursorPosition - initialCursorPosition;
|
|
965
|
+
const offsetPercentage = offsetPixels / groupSizeInPixels * 100;
|
|
966
|
+
const prevSize = context.get("size");
|
|
967
|
+
const nextSize = resizeByDelta({
|
|
968
|
+
delta: offsetPercentage,
|
|
969
|
+
initialSize: initialSize ?? prevSize,
|
|
970
|
+
panels,
|
|
971
|
+
pivotIndices,
|
|
972
|
+
prevSize,
|
|
973
|
+
trigger: "mouse-or-touch"
|
|
591
974
|
});
|
|
975
|
+
if (!isEqual(prevSize, nextSize)) {
|
|
976
|
+
setSize(params, nextSize);
|
|
977
|
+
}
|
|
592
978
|
},
|
|
593
|
-
|
|
594
|
-
const
|
|
595
|
-
|
|
596
|
-
const
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
979
|
+
setKeyboardValue(params) {
|
|
980
|
+
const { context, event, prop } = params;
|
|
981
|
+
const panelDataArray = prop("panels");
|
|
982
|
+
const resizeTriggerId = event.id;
|
|
983
|
+
const delta = event.delta;
|
|
984
|
+
const pivotIndices = resizeTriggerId.split(":").map((id) => panelDataArray.findIndex((panelData) => panelData.id === id));
|
|
985
|
+
const prevSize = context.get("size");
|
|
986
|
+
const nextSize = resizeByDelta({
|
|
987
|
+
delta,
|
|
988
|
+
initialSize: prevSize,
|
|
989
|
+
panels: panelDataArray,
|
|
990
|
+
pivotIndices,
|
|
991
|
+
prevSize,
|
|
992
|
+
trigger: "keyboard"
|
|
602
993
|
});
|
|
994
|
+
if (!isEqual(prevSize, nextSize)) {
|
|
995
|
+
setSize(params, nextSize);
|
|
996
|
+
}
|
|
603
997
|
},
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
next[before.index].size = initialSize[before.index].size;
|
|
612
|
-
next[after.index].size = initialSize[after.index].size;
|
|
613
|
-
return next;
|
|
998
|
+
invokeOnResizeEnd({ context, prop }) {
|
|
999
|
+
queueMicrotask(() => {
|
|
1000
|
+
const dragState = context.get("dragState");
|
|
1001
|
+
prop("onResizeEnd")?.({
|
|
1002
|
+
size: context.get("size"),
|
|
1003
|
+
resizeTriggerId: dragState?.resizeTriggerId ?? null
|
|
1004
|
+
});
|
|
614
1005
|
});
|
|
615
1006
|
},
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
if (!activeId) return;
|
|
620
|
-
getResizeTriggerEl(scope, activeId)?.focus({ preventScroll: true });
|
|
1007
|
+
invokeOnResizeStart({ prop }) {
|
|
1008
|
+
queueMicrotask(() => {
|
|
1009
|
+
prop("onResizeStart")?.();
|
|
621
1010
|
});
|
|
622
1011
|
},
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
1012
|
+
collapseOrExpandPanel(params) {
|
|
1013
|
+
const { context, prop } = params;
|
|
1014
|
+
const panelDataArray = prop("panels");
|
|
1015
|
+
const sizes = context.get("size");
|
|
1016
|
+
const resizeTriggerId = context.get("keyboardState")?.resizeTriggerId;
|
|
1017
|
+
const [idBefore, idAfter] = resizeTriggerId?.split(":") ?? [];
|
|
1018
|
+
const index = panelDataArray.findIndex((panelData2) => panelData2.id === idBefore);
|
|
1019
|
+
if (index === -1) return;
|
|
1020
|
+
const panelData = panelDataArray[index];
|
|
1021
|
+
ensure(panelData, `No panel data found for index ${index}`);
|
|
1022
|
+
const size = sizes[index];
|
|
1023
|
+
const { collapsedSize = 0, collapsible, minSize = 0 } = panelData;
|
|
1024
|
+
if (size != null && collapsible) {
|
|
1025
|
+
const pivotIndices = [idBefore, idAfter].map(
|
|
1026
|
+
(id) => panelDataArray.findIndex((panelData2) => panelData2.id === id)
|
|
1027
|
+
);
|
|
1028
|
+
const nextSize = resizeByDelta({
|
|
1029
|
+
delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
|
|
1030
|
+
initialSize: context.initial("size"),
|
|
1031
|
+
panels: panelDataArray,
|
|
1032
|
+
pivotIndices,
|
|
1033
|
+
prevSize: sizes,
|
|
1034
|
+
trigger: "keyboard"
|
|
1035
|
+
});
|
|
1036
|
+
if (!isEqual(sizes, nextSize)) {
|
|
1037
|
+
setSize(params, nextSize);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
629
1040
|
},
|
|
630
|
-
|
|
631
|
-
|
|
1041
|
+
setGlobalCursor({ context, scope, prop }) {
|
|
1042
|
+
const dragState = context.get("dragState");
|
|
1043
|
+
if (!dragState) return;
|
|
1044
|
+
const panels = prop("panels");
|
|
1045
|
+
const horizontal = prop("orientation") === "horizontal";
|
|
1046
|
+
const [idBefore] = dragState.resizeTriggerId.split(":");
|
|
1047
|
+
const indexBefore = panels.findIndex((panel2) => panel2.id === idBefore);
|
|
1048
|
+
const panel = panels[indexBefore];
|
|
1049
|
+
const size = context.get("size");
|
|
1050
|
+
const aria = getAriaValue(size, panels, dragState.resizeTriggerId);
|
|
1051
|
+
const isAtMin = fuzzyNumbersEqual(aria.valueNow, aria.valueMin) || fuzzyNumbersEqual(aria.valueNow, panel.collapsedSize);
|
|
1052
|
+
const isAtMax = fuzzyNumbersEqual(aria.valueNow, aria.valueMax);
|
|
1053
|
+
const cursorState = { isAtMin, isAtMax };
|
|
1054
|
+
setupGlobalCursor(scope, cursorState, horizontal, prop("nonce"));
|
|
632
1055
|
},
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
if (!panels) return;
|
|
636
|
-
const { before } = panels;
|
|
637
|
-
context.set("activeResizeState", {
|
|
638
|
-
isAtMin: before.isAtMin,
|
|
639
|
-
isAtMax: before.isAtMax
|
|
640
|
-
});
|
|
1056
|
+
clearGlobalCursor({ scope }) {
|
|
1057
|
+
removeGlobalCursor(scope);
|
|
641
1058
|
},
|
|
642
|
-
|
|
643
|
-
const
|
|
644
|
-
const
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
if (!rootEl) return;
|
|
648
|
-
const relativePoint = getRelativePoint(event.point, rootEl);
|
|
649
|
-
const percentValue = relativePoint.getPercentValue({
|
|
650
|
-
dir: prop("dir"),
|
|
651
|
-
orientation: prop("orientation")
|
|
652
|
-
});
|
|
653
|
-
let pointValue = percentValue * 100;
|
|
654
|
-
context.set("activeResizeState", {
|
|
655
|
-
isAtMin: pointValue < bounds.min,
|
|
656
|
-
isAtMax: pointValue > bounds.max
|
|
657
|
-
});
|
|
658
|
-
pointValue = clamp(pointValue, bounds.min, bounds.max);
|
|
659
|
-
const { before, after } = panels;
|
|
660
|
-
const offset = pointValue - before.end;
|
|
661
|
-
context.set("size", (prev) => {
|
|
662
|
-
const next = prev.slice();
|
|
663
|
-
next[before.index].size = before.size + offset;
|
|
664
|
-
next[after.index].size = after.size - offset;
|
|
665
|
-
return next;
|
|
666
|
-
});
|
|
1059
|
+
focusNextResizeTrigger({ event, scope }) {
|
|
1060
|
+
const resizeTriggers = getResizeTriggerEls(scope);
|
|
1061
|
+
const index = resizeTriggers.findIndex((el) => el.dataset.id === event.id);
|
|
1062
|
+
const handleEl = event.shiftKey ? prev(resizeTriggers, index) : next(resizeTriggers, index);
|
|
1063
|
+
handleEl?.focus();
|
|
667
1064
|
}
|
|
668
1065
|
}
|
|
669
1066
|
}
|
|
670
1067
|
});
|
|
1068
|
+
function setSize(params, sizes) {
|
|
1069
|
+
const { refs, prop, context } = params;
|
|
1070
|
+
const panelsArray = prop("panels");
|
|
1071
|
+
const onCollapse = prop("onCollapse");
|
|
1072
|
+
const onExpand = prop("onExpand");
|
|
1073
|
+
const panelIdToLastNotifiedSizeMap = refs.get("panelIdToLastNotifiedSizeMap");
|
|
1074
|
+
context.set("size", sizes);
|
|
1075
|
+
sizes.forEach((size, index) => {
|
|
1076
|
+
const panelData = panelsArray[index];
|
|
1077
|
+
ensure(panelData, `Panel data not found for index ${index}`);
|
|
1078
|
+
const { collapsedSize = 0, collapsible, id: panelId } = panelData;
|
|
1079
|
+
const lastNotifiedSize = panelIdToLastNotifiedSizeMap.get(panelId);
|
|
1080
|
+
if (lastNotifiedSize == null || size !== lastNotifiedSize) {
|
|
1081
|
+
panelIdToLastNotifiedSizeMap.set(panelId, size);
|
|
1082
|
+
if (collapsible && (onCollapse || onExpand)) {
|
|
1083
|
+
if ((lastNotifiedSize == null || fuzzyNumbersEqual(lastNotifiedSize, collapsedSize)) && !fuzzyNumbersEqual(size, collapsedSize)) {
|
|
1084
|
+
onExpand?.({ panelId, size });
|
|
1085
|
+
}
|
|
1086
|
+
if (onCollapse && (lastNotifiedSize == null || !fuzzyNumbersEqual(lastNotifiedSize, collapsedSize)) && fuzzyNumbersEqual(size, collapsedSize)) {
|
|
1087
|
+
onCollapse?.({ panelId, size });
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
});
|
|
1092
|
+
}
|
|
671
1093
|
var props = createProps()([
|
|
672
1094
|
"dir",
|
|
673
1095
|
"getRootNode",
|
|
674
1096
|
"id",
|
|
675
1097
|
"ids",
|
|
676
|
-
"
|
|
677
|
-
"
|
|
1098
|
+
"onResize",
|
|
1099
|
+
"onResizeStart",
|
|
1100
|
+
"onResizeEnd",
|
|
1101
|
+
"onCollapse",
|
|
1102
|
+
"onExpand",
|
|
678
1103
|
"orientation",
|
|
679
1104
|
"size",
|
|
680
|
-
"defaultSize"
|
|
1105
|
+
"defaultSize",
|
|
1106
|
+
"panels",
|
|
1107
|
+
"keyboardResizeBy",
|
|
1108
|
+
"nonce"
|
|
681
1109
|
]);
|
|
682
1110
|
var splitProps = createSplitProps(props);
|
|
683
|
-
var panelProps = createProps()(["id"
|
|
1111
|
+
var panelProps = createProps()(["id"]);
|
|
684
1112
|
var splitPanelProps = createSplitProps(panelProps);
|
|
685
|
-
var resizeTriggerProps = createProps()(["disabled", "id"
|
|
1113
|
+
var resizeTriggerProps = createProps()(["disabled", "id"]);
|
|
686
1114
|
var splitResizeTriggerProps = createSplitProps(resizeTriggerProps);
|
|
687
1115
|
|
|
688
|
-
export { anatomy, connect, machine, panelProps, props, resizeTriggerProps, splitPanelProps, splitProps, splitResizeTriggerProps };
|
|
1116
|
+
export { anatomy, connect, getPanelLayout as layout, machine, panelProps, props, resizeTriggerProps, splitPanelProps, splitProps, splitResizeTriggerProps };
|