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