@window-splitter/state 0.3.2 → 0.4.1
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/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-lint.log +4 -5
- package/.turbo/turbo-test.log +1192 -4322
- package/CHANGELOG.md +49 -0
- package/coverage/coverage-final.json +1 -1
- package/coverage/coverage-summary.json +2 -2
- package/coverage/index.html +17 -17
- package/coverage/index.ts.html +1161 -399
- package/dist/commonjs/index.d.ts +21 -14
- package/dist/commonjs/index.d.ts.map +1 -1
- package/dist/commonjs/index.js +219 -45
- package/dist/commonjs/index.js.map +1 -1
- package/dist/esm/index.d.ts +21 -14
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +219 -45
- package/dist/esm/index.js.map +1 -1
- package/package.json +4 -3
- package/src/__snapshots__/machine.test.ts.snap +82 -2
- package/src/index.ts +319 -71
- package/src/machine.test.ts +329 -24
package/src/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import Cookies from "universal-cookie";
|
|
1
2
|
import { raf } from "@react-spring/rafz";
|
|
2
3
|
import {
|
|
3
4
|
createMachine,
|
|
@@ -65,6 +66,13 @@ export interface Constraints<T extends ParsedUnit | Unit = ParsedUnit> {
|
|
|
65
66
|
defaultCollapsed?: boolean;
|
|
66
67
|
/** The size of the panel once collapsed */
|
|
67
68
|
collapsedSize?: T;
|
|
69
|
+
/**
|
|
70
|
+
* By default the layout will be stored in percentage values while at rest.
|
|
71
|
+
* This makes scaling the layout easier when the container is resized.
|
|
72
|
+
* However you might have a panel you want to stay at a static size when
|
|
73
|
+
* the container is resized.
|
|
74
|
+
*/
|
|
75
|
+
isStaticAtRest?: boolean;
|
|
68
76
|
}
|
|
69
77
|
|
|
70
78
|
interface Order {
|
|
@@ -108,6 +116,7 @@ export interface PanelData
|
|
|
108
116
|
collapseAnimation?:
|
|
109
117
|
| CollapseAnimation
|
|
110
118
|
| { duration: number; easing: CollapseAnimation | ((t: number) => number) };
|
|
119
|
+
lastKnownSize?: Rect;
|
|
111
120
|
}
|
|
112
121
|
|
|
113
122
|
function getCollapseAnimation(panel: PanelData) {
|
|
@@ -294,8 +303,17 @@ export interface GroupMachineContextValue {
|
|
|
294
303
|
/** How much the drag has overshot the handle */
|
|
295
304
|
dragOvershoot: Big.Big;
|
|
296
305
|
groupId: string;
|
|
306
|
+
/**
|
|
307
|
+
* How to save the persisted state
|
|
308
|
+
*/
|
|
309
|
+
autosaveStrategy?: "localStorage" | "cookie";
|
|
297
310
|
}
|
|
298
311
|
|
|
312
|
+
export type GroupMachineSnapshot = Snapshot<unknown> & {
|
|
313
|
+
context: GroupMachineContextValue;
|
|
314
|
+
value: string;
|
|
315
|
+
};
|
|
316
|
+
|
|
299
317
|
export type GroupMachineEvent =
|
|
300
318
|
| RegisterPanelEvent
|
|
301
319
|
| RegisterDynamicPanelEvent
|
|
@@ -344,10 +362,8 @@ export function getCursor(
|
|
|
344
362
|
}
|
|
345
363
|
}
|
|
346
364
|
|
|
347
|
-
export function prepareSnapshot(snapshot:
|
|
348
|
-
|
|
349
|
-
const snapshotContext = (snapshot as any)
|
|
350
|
-
.context as unknown as GroupMachineContextValue;
|
|
365
|
+
export function prepareSnapshot(snapshot: GroupMachineSnapshot) {
|
|
366
|
+
const snapshotContext = snapshot.context;
|
|
351
367
|
|
|
352
368
|
snapshotContext.dragOvershoot = new Big(snapshotContext.dragOvershoot);
|
|
353
369
|
|
|
@@ -406,23 +422,24 @@ type OnResizeSize = {
|
|
|
406
422
|
|
|
407
423
|
export type OnResizeCallback = (size: OnResizeSize) => void;
|
|
408
424
|
|
|
409
|
-
|
|
425
|
+
type InitializePanelOptions = {
|
|
410
426
|
min?: Unit;
|
|
411
427
|
max?: Unit;
|
|
412
428
|
default?: Unit;
|
|
413
|
-
collapsible?: boolean;
|
|
414
|
-
collapsed?: boolean;
|
|
415
429
|
collapsedSize?: Unit;
|
|
416
|
-
onCollapseChange?: {
|
|
417
|
-
current: ((isCollapsed: boolean) => void) | null | undefined;
|
|
418
|
-
};
|
|
419
|
-
onResize?: {
|
|
420
|
-
current: OnResizeCallback | null | undefined;
|
|
421
|
-
};
|
|
422
|
-
collapseAnimation?: PanelData["collapseAnimation"];
|
|
423
|
-
defaultCollapsed?: boolean;
|
|
424
430
|
id?: string;
|
|
425
|
-
}
|
|
431
|
+
} & Partial<
|
|
432
|
+
Pick<
|
|
433
|
+
PanelData,
|
|
434
|
+
| "isStaticAtRest"
|
|
435
|
+
| "collapseAnimation"
|
|
436
|
+
| "defaultCollapsed"
|
|
437
|
+
| "onResize"
|
|
438
|
+
| "collapsible"
|
|
439
|
+
| "collapsed"
|
|
440
|
+
| "onCollapseChange"
|
|
441
|
+
>
|
|
442
|
+
>;
|
|
426
443
|
|
|
427
444
|
type InitializePanelOptionsWithId = InitializePanelOptions & { id: string };
|
|
428
445
|
|
|
@@ -468,6 +485,7 @@ export function initializePanel(
|
|
|
468
485
|
id: item.id,
|
|
469
486
|
collapseAnimation: item.collapseAnimation,
|
|
470
487
|
default: item.default ? parseUnit(item.default) : undefined,
|
|
488
|
+
isStaticAtRest: item.isStaticAtRest,
|
|
471
489
|
} satisfies Omit<PanelData, "id" | "currentValue"> & { id?: string };
|
|
472
490
|
|
|
473
491
|
return { ...data, currentValue: makePixelUnit(-1) } satisfies Omit<
|
|
@@ -686,10 +704,7 @@ function panelHasSpace(
|
|
|
686
704
|
);
|
|
687
705
|
}
|
|
688
706
|
|
|
689
|
-
return (
|
|
690
|
-
item.currentValue.value.gt(getUnitPixelValue(context, item.min)) &&
|
|
691
|
-
item.currentValue.value.lte(getUnitPixelValue(context, item.max))
|
|
692
|
-
);
|
|
707
|
+
return item.currentValue.value.gt(getUnitPixelValue(context, item.min));
|
|
693
708
|
}
|
|
694
709
|
|
|
695
710
|
/** Search in a `direction` for a panel that still has space to expand. */
|
|
@@ -726,11 +741,9 @@ function getStaticWidth(context: GroupMachineContextValue) {
|
|
|
726
741
|
for (const item of context.items) {
|
|
727
742
|
if (isPanelHandle(item)) {
|
|
728
743
|
width = width.add(item.size.value);
|
|
729
|
-
} else if (
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
item.currentValue.type === "pixel"
|
|
733
|
-
) {
|
|
744
|
+
} else if (item.collapsed && item.currentValue.type === "pixel") {
|
|
745
|
+
width = width.add(item.currentValue.value);
|
|
746
|
+
} else if (item.isStaticAtRest) {
|
|
734
747
|
width = width.add(item.currentValue.value);
|
|
735
748
|
}
|
|
736
749
|
}
|
|
@@ -795,6 +808,7 @@ export function getPanelPercentageSize(
|
|
|
795
808
|
/** Build the grid template from the item values. */
|
|
796
809
|
export function buildTemplate(context: GroupMachineContextValue) {
|
|
797
810
|
const staticWidth = getStaticWidth(context);
|
|
811
|
+
let hasSeenFillPanel = false;
|
|
798
812
|
|
|
799
813
|
return context.items
|
|
800
814
|
.map((item) => {
|
|
@@ -805,8 +819,22 @@ export function buildTemplate(context: GroupMachineContextValue) {
|
|
|
805
819
|
item.currentValue.type === "pixel" &&
|
|
806
820
|
item.currentValue.value.toNumber() !== -1
|
|
807
821
|
) {
|
|
822
|
+
if (item.isStaticAtRest) {
|
|
823
|
+
const max = item.max === "1fr" ? "100%" : formatUnit(item.max);
|
|
824
|
+
return `clamp(${min}, ${formatUnit(item.currentValue)}, ${max})`;
|
|
825
|
+
}
|
|
826
|
+
|
|
808
827
|
return formatUnit(item.currentValue);
|
|
809
828
|
} else if (item.currentValue.type === "percent") {
|
|
829
|
+
if (
|
|
830
|
+
!hasSeenFillPanel &&
|
|
831
|
+
(item.max === "1fr" ||
|
|
832
|
+
(item.max.type === "percent" && item.max.value.eq(100)))
|
|
833
|
+
) {
|
|
834
|
+
hasSeenFillPanel = true;
|
|
835
|
+
return `minmax(${min}, 1fr)`;
|
|
836
|
+
}
|
|
837
|
+
|
|
810
838
|
const max = item.max === "1fr" ? "100%" : formatUnit(item.max);
|
|
811
839
|
return `minmax(${min}, min(calc(${item.currentValue.value} * (100% - ${staticWidth}px)), ${max}))`;
|
|
812
840
|
} else if (item.collapsible && item.collapsed) {
|
|
@@ -919,18 +947,28 @@ function createUnrestrainedPanel(_: GroupMachineContextValue, data: PanelData) {
|
|
|
919
947
|
*/
|
|
920
948
|
|
|
921
949
|
/** Converts the items to pixels */
|
|
922
|
-
export function prepareItems(context: GroupMachineContextValue) {
|
|
950
|
+
export function prepareItems(context: GroupMachineContextValue): Item[] {
|
|
923
951
|
const staticWidth = getStaticWidth(context);
|
|
924
952
|
const newItems = [];
|
|
925
953
|
|
|
926
954
|
for (const item of context.items) {
|
|
927
955
|
if (!item || !isPanelData(item)) {
|
|
928
|
-
newItems.push(item);
|
|
956
|
+
newItems.push({ ...item });
|
|
957
|
+
continue;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
if (item.lastKnownSize) {
|
|
961
|
+
const lastSize = makePixelUnit(
|
|
962
|
+
context.orientation === "horizontal"
|
|
963
|
+
? item.lastKnownSize.width
|
|
964
|
+
: item.lastKnownSize.height
|
|
965
|
+
);
|
|
966
|
+
newItems.push({ ...item, currentValue: lastSize });
|
|
929
967
|
continue;
|
|
930
968
|
}
|
|
931
969
|
|
|
932
970
|
if (item.currentValue.type === "pixel") {
|
|
933
|
-
newItems.push(item);
|
|
971
|
+
newItems.push({ ...item });
|
|
934
972
|
continue;
|
|
935
973
|
}
|
|
936
974
|
|
|
@@ -1031,6 +1069,10 @@ function updateLayout(
|
|
|
1031
1069
|
|
|
1032
1070
|
const isInDragBugger =
|
|
1033
1071
|
newDragOvershoot.abs().lt(COLLAPSE_THRESHOLD) &&
|
|
1072
|
+
// Let the panel expand at it's min size
|
|
1073
|
+
!panelAfter.currentValue.value
|
|
1074
|
+
.add(newDragOvershoot.abs())
|
|
1075
|
+
.gte(panelAfter.min.value) &&
|
|
1034
1076
|
panelAfter.collapsible &&
|
|
1035
1077
|
panelAfter.collapsed &&
|
|
1036
1078
|
(isInLeftOvershoot || isInRightOvershoot);
|
|
@@ -1048,9 +1090,11 @@ function updateLayout(
|
|
|
1048
1090
|
|
|
1049
1091
|
// Don't let the panel collapse until the threshold is reached
|
|
1050
1092
|
if (
|
|
1093
|
+
!dragEvent.disregardCollapseBuffer &&
|
|
1051
1094
|
panelBefore.collapsible &&
|
|
1052
|
-
panelBefore.currentValue.value
|
|
1095
|
+
panelBefore.currentValue.value.eq(
|
|
1053
1096
|
getUnitPixelValue(context, panelBefore.min)
|
|
1097
|
+
)
|
|
1054
1098
|
) {
|
|
1055
1099
|
const potentialNewValue = panelBefore.currentValue.value.sub(
|
|
1056
1100
|
newDragOvershoot.abs()
|
|
@@ -1116,8 +1160,6 @@ function updateLayout(
|
|
|
1116
1160
|
.add(Math.abs(moveAmount))
|
|
1117
1161
|
);
|
|
1118
1162
|
|
|
1119
|
-
panelAfter.collapsed = false;
|
|
1120
|
-
|
|
1121
1163
|
if (extra.gt(0)) {
|
|
1122
1164
|
panelAfterNewValue = panelAfterNewValue.add(extra);
|
|
1123
1165
|
}
|
|
@@ -1131,6 +1173,13 @@ function updateLayout(
|
|
|
1131
1173
|
.minus(Math.abs(moveAmount))
|
|
1132
1174
|
);
|
|
1133
1175
|
|
|
1176
|
+
if (panelBeforeNewValue.lt(panelBefore.min.value)) {
|
|
1177
|
+
// TODO this should probably distribute the space between the panels?
|
|
1178
|
+
return { dragOvershoot: newDragOvershoot };
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
panelAfter.collapsed = false;
|
|
1182
|
+
|
|
1134
1183
|
if (
|
|
1135
1184
|
panelAfter.onCollapseChange?.current &&
|
|
1136
1185
|
!panelAfter.collapseIsControlled &&
|
|
@@ -1140,9 +1189,9 @@ function updateLayout(
|
|
|
1140
1189
|
}
|
|
1141
1190
|
}
|
|
1142
1191
|
|
|
1143
|
-
const panelBeforeIsAboutToCollapse =
|
|
1144
|
-
panelBefore.
|
|
1145
|
-
|
|
1192
|
+
const panelBeforeIsAboutToCollapse = panelBefore.currentValue.value.eq(
|
|
1193
|
+
getUnitPixelValue(context, panelBefore.min)
|
|
1194
|
+
);
|
|
1146
1195
|
|
|
1147
1196
|
// If the panel was expanded and now is at it's min size, collapse it
|
|
1148
1197
|
if (
|
|
@@ -1187,8 +1236,11 @@ function updateLayout(
|
|
|
1187
1236
|
);
|
|
1188
1237
|
|
|
1189
1238
|
if (!leftoverSpace.eq(0)) {
|
|
1190
|
-
panelBefore.currentValue.value =
|
|
1191
|
-
|
|
1239
|
+
panelBefore.currentValue.value = clampUnit(
|
|
1240
|
+
context,
|
|
1241
|
+
panelBefore,
|
|
1242
|
+
panelBefore.currentValue.value.add(leftoverSpace)
|
|
1243
|
+
);
|
|
1192
1244
|
}
|
|
1193
1245
|
|
|
1194
1246
|
return { items: newItems };
|
|
@@ -1215,7 +1267,7 @@ function commitLayout(context: GroupMachineContextValue) {
|
|
|
1215
1267
|
const staticWidth = getStaticWidth({ ...context, items: newItems });
|
|
1216
1268
|
|
|
1217
1269
|
newItems.forEach((item, index) => {
|
|
1218
|
-
if (item.type !== "panel" || item.collapsed) {
|
|
1270
|
+
if (item.type !== "panel" || item.collapsed || item.isStaticAtRest) {
|
|
1219
1271
|
return;
|
|
1220
1272
|
}
|
|
1221
1273
|
|
|
@@ -1334,6 +1386,85 @@ function applyDeltaInBothDirections(
|
|
|
1334
1386
|
}
|
|
1335
1387
|
}
|
|
1336
1388
|
|
|
1389
|
+
/**
|
|
1390
|
+
* A layout might overflow at small screen sizes.
|
|
1391
|
+
* This function tries to fix that by:
|
|
1392
|
+
*
|
|
1393
|
+
* 1. It will try to collapse a panel if it can.
|
|
1394
|
+
*/
|
|
1395
|
+
function handleOverflow(context: GroupMachineContextValue) {
|
|
1396
|
+
// If we haven't measured yet we can't do anything
|
|
1397
|
+
if (
|
|
1398
|
+
context.items.some((i) => isPanelData(i) && i.currentValue.value.eq(-1))
|
|
1399
|
+
) {
|
|
1400
|
+
return context;
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
const groupSize = new Big(getGroupSize(context));
|
|
1404
|
+
const nonStaticWidth = groupSize.sub(getStaticWidth(context).toNumber());
|
|
1405
|
+
const pixelItems = context.items.map((i) => {
|
|
1406
|
+
if (isPanelHandle(i)) return i.size.value;
|
|
1407
|
+
if (i.collapsed) return getUnitPixelValue(context, i.currentValue);
|
|
1408
|
+
|
|
1409
|
+
const pixel =
|
|
1410
|
+
(i.currentValue.type === "pixel" && i.currentValue.value) ||
|
|
1411
|
+
i.currentValue.value.mul(nonStaticWidth);
|
|
1412
|
+
|
|
1413
|
+
return clampUnit(context, i, pixel);
|
|
1414
|
+
});
|
|
1415
|
+
const totalSize = pixelItems.reduce((acc, i) => acc.add(i), new Big(0));
|
|
1416
|
+
const overflow = totalSize.abs().sub(groupSize);
|
|
1417
|
+
|
|
1418
|
+
if (overflow.eq(0) || groupSize.eq(0)) {
|
|
1419
|
+
return context;
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
let newContext = { ...context, items: prepareItems(context) };
|
|
1423
|
+
|
|
1424
|
+
const collapsiblePanel = newContext.items.find((i): i is PanelData =>
|
|
1425
|
+
Boolean(isPanelData(i) && i.collapsible)
|
|
1426
|
+
);
|
|
1427
|
+
|
|
1428
|
+
if (collapsiblePanel) {
|
|
1429
|
+
const collapsiblePanelIndex = newContext.items.findIndex(
|
|
1430
|
+
(i) => i.id === collapsiblePanel.id
|
|
1431
|
+
);
|
|
1432
|
+
const handleId = getHandleForPanelId(newContext, collapsiblePanel.id);
|
|
1433
|
+
const sizeChange = collapsiblePanel.currentValue.value.sub(
|
|
1434
|
+
getUnitPixelValue(newContext, collapsiblePanel.collapsedSize)
|
|
1435
|
+
);
|
|
1436
|
+
|
|
1437
|
+
// Try to collapse the panel
|
|
1438
|
+
newContext = {
|
|
1439
|
+
...newContext,
|
|
1440
|
+
...iterativelyUpdateLayout({
|
|
1441
|
+
handleId: handleId.item.id,
|
|
1442
|
+
delta: sizeChange,
|
|
1443
|
+
direction: (handleId.direction * -1) as -1 | 1,
|
|
1444
|
+
context: {
|
|
1445
|
+
...newContext,
|
|
1446
|
+
// act like its the old size so the space is distributed correctly
|
|
1447
|
+
size: { width: totalSize.toNumber(), height: totalSize.toNumber() },
|
|
1448
|
+
},
|
|
1449
|
+
}),
|
|
1450
|
+
};
|
|
1451
|
+
|
|
1452
|
+
// Then remove all the overflow
|
|
1453
|
+
applyDeltaInBothDirections(
|
|
1454
|
+
newContext,
|
|
1455
|
+
newContext.items,
|
|
1456
|
+
collapsiblePanelIndex,
|
|
1457
|
+
overflow.neg()
|
|
1458
|
+
);
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
return { ...newContext, items: commitLayout(newContext) };
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
function clearLastKnownSize(items: Item[]) {
|
|
1465
|
+
return items.map((i) => ({ ...i, lastKnownSize: undefined }));
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1337
1468
|
// #endregion
|
|
1338
1469
|
|
|
1339
1470
|
// #region Machine
|
|
@@ -1349,6 +1480,22 @@ interface AnimationActorOutput {
|
|
|
1349
1480
|
action: "expand" | "collapse";
|
|
1350
1481
|
}
|
|
1351
1482
|
|
|
1483
|
+
function getDeltaForEvent(
|
|
1484
|
+
context: GroupMachineContextValue,
|
|
1485
|
+
event: CollapsePanelEvent | ExpandPanelEvent
|
|
1486
|
+
) {
|
|
1487
|
+
const panel = getPanelWithId(context, event.panelId);
|
|
1488
|
+
|
|
1489
|
+
if (event.type === "expandPanel") {
|
|
1490
|
+
return new Big(
|
|
1491
|
+
panel.sizeBeforeCollapse ?? getUnitPixelValue(context, panel.min)
|
|
1492
|
+
).minus(panel.currentValue.value);
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
const collapsedSize = getUnitPixelValue(context, panel.collapsedSize);
|
|
1496
|
+
return panel.currentValue.value.minus(collapsedSize);
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1352
1499
|
const animationActor = fromPromise<
|
|
1353
1500
|
AnimationActorOutput | undefined,
|
|
1354
1501
|
AnimationActorInput
|
|
@@ -1359,18 +1506,11 @@ const animationActor = fromPromise<
|
|
|
1359
1506
|
const handle = getHandleForPanelId(context, event.panelId);
|
|
1360
1507
|
|
|
1361
1508
|
let direction = new Big(handle.direction);
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
if (event.type === "expandPanel") {
|
|
1365
|
-
fullDelta = new Big(
|
|
1366
|
-
panel.sizeBeforeCollapse ?? getUnitPixelValue(context, panel.min)
|
|
1367
|
-
).minus(panel.currentValue.value);
|
|
1368
|
-
} else {
|
|
1369
|
-
const collapsedSize = getUnitPixelValue(context, panel.collapsedSize);
|
|
1509
|
+
const fullDelta = getDeltaForEvent(context, event);
|
|
1370
1510
|
|
|
1511
|
+
if (event.type === "collapsePanel") {
|
|
1371
1512
|
panel.sizeBeforeCollapse = panel.currentValue.value.toNumber();
|
|
1372
1513
|
direction = direction.mul(new Big(-1));
|
|
1373
|
-
fullDelta = panel.currentValue.value.minus(collapsedSize);
|
|
1374
1514
|
}
|
|
1375
1515
|
|
|
1376
1516
|
const fps = 60;
|
|
@@ -1426,6 +1566,7 @@ export const groupMachine = createMachine(
|
|
|
1426
1566
|
orientation?: Orientation;
|
|
1427
1567
|
groupId: string;
|
|
1428
1568
|
initialItems?: Item[];
|
|
1569
|
+
autosaveStrategy?: "localStorage" | "cookie";
|
|
1429
1570
|
},
|
|
1430
1571
|
},
|
|
1431
1572
|
context: ({ input }) => ({
|
|
@@ -1434,15 +1575,17 @@ export const groupMachine = createMachine(
|
|
|
1434
1575
|
orientation: input.orientation || "horizontal",
|
|
1435
1576
|
dragOvershoot: new Big(0),
|
|
1436
1577
|
groupId: input.groupId,
|
|
1578
|
+
autosaveStrategy: input.autosaveStrategy,
|
|
1437
1579
|
}),
|
|
1438
1580
|
states: {
|
|
1439
1581
|
idle: {
|
|
1582
|
+
entry: ["onAutosave"],
|
|
1440
1583
|
on: {
|
|
1441
|
-
setActualItemsSize: { actions: ["recordActualItemSize", "onResize"] },
|
|
1442
1584
|
dragHandleStart: { target: "dragging" },
|
|
1443
1585
|
setPanelPixelSize: {
|
|
1444
1586
|
actions: [
|
|
1445
1587
|
"prepare",
|
|
1588
|
+
"onClearLastKnownSize",
|
|
1446
1589
|
"onSetPanelSize",
|
|
1447
1590
|
"commit",
|
|
1448
1591
|
"onResize",
|
|
@@ -1457,6 +1600,8 @@ export const groupMachine = createMachine(
|
|
|
1457
1600
|
{ target: "togglingCollapse" },
|
|
1458
1601
|
],
|
|
1459
1602
|
expandPanel: [
|
|
1603
|
+
// This will match if we can't expand and the expansion won't happen
|
|
1604
|
+
{ guard: "cannotExpandPanel" },
|
|
1460
1605
|
{
|
|
1461
1606
|
actions: "notifyCollapseToggle",
|
|
1462
1607
|
guard: "shouldNotifyCollapseToggle",
|
|
@@ -1468,7 +1613,9 @@ export const groupMachine = createMachine(
|
|
|
1468
1613
|
dragging: {
|
|
1469
1614
|
entry: ["prepare"],
|
|
1470
1615
|
on: {
|
|
1471
|
-
dragHandle: {
|
|
1616
|
+
dragHandle: {
|
|
1617
|
+
actions: ["onClearLastKnownSize", "onDragHandle", "onResize"],
|
|
1618
|
+
},
|
|
1472
1619
|
dragHandleEnd: { target: "idle" },
|
|
1473
1620
|
collapsePanel: {
|
|
1474
1621
|
guard: "shouldCollapseToggle",
|
|
@@ -1479,16 +1626,16 @@ export const groupMachine = createMachine(
|
|
|
1479
1626
|
actions: "runCollapseToggle",
|
|
1480
1627
|
},
|
|
1481
1628
|
},
|
|
1482
|
-
exit: ["commit"
|
|
1629
|
+
exit: ["commit"],
|
|
1483
1630
|
},
|
|
1484
1631
|
togglingCollapse: {
|
|
1485
|
-
entry: ["prepare"],
|
|
1632
|
+
entry: ["prepare", "onClearLastKnownSize"],
|
|
1486
1633
|
invoke: {
|
|
1487
1634
|
src: "animation",
|
|
1488
1635
|
input: (i) => ({ ...i, send: i.self.send }),
|
|
1489
1636
|
onDone: {
|
|
1490
1637
|
target: "idle",
|
|
1491
|
-
actions: ["onToggleCollapseComplete", "commit"
|
|
1638
|
+
actions: ["onToggleCollapseComplete", "commit"],
|
|
1492
1639
|
},
|
|
1493
1640
|
},
|
|
1494
1641
|
on: {
|
|
@@ -1497,25 +1644,43 @@ export const groupMachine = createMachine(
|
|
|
1497
1644
|
},
|
|
1498
1645
|
},
|
|
1499
1646
|
on: {
|
|
1647
|
+
setActualItemsSize: { actions: ["recordActualItemSize", "onResize"] },
|
|
1500
1648
|
registerPanel: { actions: ["assignPanelData"] },
|
|
1501
1649
|
registerDynamicPanel: {
|
|
1502
1650
|
actions: [
|
|
1503
1651
|
"prepare",
|
|
1504
1652
|
"onRegisterDynamicPanel",
|
|
1653
|
+
"onClearLastKnownSize",
|
|
1505
1654
|
"commit",
|
|
1506
1655
|
"onResize",
|
|
1507
1656
|
"onAutosave",
|
|
1508
1657
|
],
|
|
1509
1658
|
},
|
|
1510
1659
|
unregisterPanel: {
|
|
1511
|
-
actions: [
|
|
1660
|
+
actions: [
|
|
1661
|
+
"prepare",
|
|
1662
|
+
"removeItem",
|
|
1663
|
+
"onClearLastKnownSize",
|
|
1664
|
+
"commit",
|
|
1665
|
+
"onResize",
|
|
1666
|
+
"onAutosave",
|
|
1667
|
+
],
|
|
1512
1668
|
},
|
|
1513
1669
|
registerPanelHandle: { actions: ["assignPanelHandleData"] },
|
|
1514
1670
|
unregisterPanelHandle: {
|
|
1515
|
-
actions: [
|
|
1671
|
+
actions: [
|
|
1672
|
+
"prepare",
|
|
1673
|
+
"removeItem",
|
|
1674
|
+
"onClearLastKnownSize",
|
|
1675
|
+
"commit",
|
|
1676
|
+
"onResize",
|
|
1677
|
+
"onAutosave",
|
|
1678
|
+
],
|
|
1516
1679
|
},
|
|
1517
1680
|
setSize: { actions: ["updateSize", "onResize"] },
|
|
1518
|
-
setOrientation: {
|
|
1681
|
+
setOrientation: {
|
|
1682
|
+
actions: ["updateOrientation", "onClearLastKnownSize", "onResize"],
|
|
1683
|
+
},
|
|
1519
1684
|
},
|
|
1520
1685
|
},
|
|
1521
1686
|
{
|
|
@@ -1530,11 +1695,63 @@ export const groupMachine = createMachine(
|
|
|
1530
1695
|
const panel = getPanelWithId(context, event.panelId);
|
|
1531
1696
|
return panel.collapseIsControlled === true;
|
|
1532
1697
|
},
|
|
1698
|
+
cannotExpandPanel: ({ context, event }) => {
|
|
1699
|
+
isEvent(event, ["expandPanel"]);
|
|
1700
|
+
const delta = getDeltaForEvent(context, event);
|
|
1701
|
+
const handle = getHandleForPanelId(context, event.panelId);
|
|
1702
|
+
const pixelItems = prepareItems(context);
|
|
1703
|
+
|
|
1704
|
+
let interimContext = { ...context, items: pixelItems };
|
|
1705
|
+
interimContext = {
|
|
1706
|
+
...interimContext,
|
|
1707
|
+
...iterativelyUpdateLayout({
|
|
1708
|
+
context: interimContext,
|
|
1709
|
+
handleId: handle.item.id,
|
|
1710
|
+
controlled: event.controlled,
|
|
1711
|
+
delta: delta,
|
|
1712
|
+
direction: handle.direction,
|
|
1713
|
+
}),
|
|
1714
|
+
};
|
|
1715
|
+
const updatedPanel = interimContext.items.find(
|
|
1716
|
+
(i) => i.id === event.panelId
|
|
1717
|
+
);
|
|
1718
|
+
const totalSize = interimContext.items.reduce(
|
|
1719
|
+
(acc, i) =>
|
|
1720
|
+
acc.add(isPanelData(i) ? i.currentValue.value : i.size.value),
|
|
1721
|
+
new Big(0)
|
|
1722
|
+
);
|
|
1723
|
+
const didExpand =
|
|
1724
|
+
updatedPanel &&
|
|
1725
|
+
isPanelData(updatedPanel) &&
|
|
1726
|
+
!updatedPanel.currentValue.value.eq(updatedPanel.collapsedSize.value);
|
|
1727
|
+
|
|
1728
|
+
return totalSize.gt(getGroupSize(context)) || !didExpand;
|
|
1729
|
+
},
|
|
1533
1730
|
},
|
|
1534
1731
|
actors: {
|
|
1535
1732
|
animation: animationActor,
|
|
1536
1733
|
},
|
|
1537
1734
|
actions: {
|
|
1735
|
+
onAutosave: ({ context, self }) => {
|
|
1736
|
+
if (!context.autosaveStrategy || typeof window === "undefined") {
|
|
1737
|
+
return;
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
const snapshot = self.getPersistedSnapshot() as GroupMachineSnapshot;
|
|
1741
|
+
snapshot.context.items = clearLastKnownSize(context.items);
|
|
1742
|
+
snapshot.value = "idle";
|
|
1743
|
+
const data = JSON.stringify(snapshot);
|
|
1744
|
+
|
|
1745
|
+
if (context.autosaveStrategy === "localStorage") {
|
|
1746
|
+
localStorage.setItem(context.groupId, data);
|
|
1747
|
+
} else {
|
|
1748
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1749
|
+
const ActualClass = (Cookies as any).default || Cookies;
|
|
1750
|
+
const cookies = new ActualClass(null, { path: "/" });
|
|
1751
|
+
|
|
1752
|
+
cookies.set(context.groupId, data, { path: "/", maxAge: 31536000 });
|
|
1753
|
+
}
|
|
1754
|
+
},
|
|
1538
1755
|
notifyCollapseToggle: ({ context, event }) => {
|
|
1539
1756
|
isEvent(event, ["collapsePanel", "expandPanel"]);
|
|
1540
1757
|
const panel = getPanelWithId(context, event.panelId);
|
|
@@ -1561,8 +1778,7 @@ export const groupMachine = createMachine(
|
|
|
1561
1778
|
}),
|
|
1562
1779
|
onToggleCollapseComplete: assign({
|
|
1563
1780
|
items: ({ context, event: e }) => {
|
|
1564
|
-
|
|
1565
|
-
const output = (e as any).output as AnimationActorOutput;
|
|
1781
|
+
const { output } = e as unknown as { output: AnimationActorOutput };
|
|
1566
1782
|
invariant(output, "Expected output from animation actor");
|
|
1567
1783
|
|
|
1568
1784
|
const panel = getPanelWithId(context, output.panelId);
|
|
@@ -1585,21 +1801,40 @@ export const groupMachine = createMachine(
|
|
|
1585
1801
|
items: ({ context, event }) => {
|
|
1586
1802
|
isEvent(event, ["setActualItemsSize"]);
|
|
1587
1803
|
|
|
1588
|
-
const
|
|
1804
|
+
const withLastKnownSize = context.items.map((i) => {
|
|
1805
|
+
if (!isPanelData(i)) return i;
|
|
1806
|
+
const lastKnownSize = event.childrenSizes[i.id] || i.lastKnownSize;
|
|
1807
|
+
return { ...i, lastKnownSize };
|
|
1808
|
+
});
|
|
1809
|
+
|
|
1810
|
+
let totalSize = 0;
|
|
1589
1811
|
|
|
1590
|
-
for (const
|
|
1591
|
-
|
|
1812
|
+
for (const item of withLastKnownSize) {
|
|
1813
|
+
if (isPanelData(item)) {
|
|
1814
|
+
const size =
|
|
1815
|
+
item.lastKnownSize?.[
|
|
1816
|
+
context.orientation === "horizontal" ? "width" : "height"
|
|
1817
|
+
];
|
|
1592
1818
|
|
|
1593
|
-
|
|
1594
|
-
|
|
1819
|
+
// If any size is 0 don't handle overflow
|
|
1820
|
+
if (!size) {
|
|
1821
|
+
return withLastKnownSize;
|
|
1822
|
+
}
|
|
1823
|
+
|
|
1824
|
+
totalSize += size;
|
|
1825
|
+
} else {
|
|
1826
|
+
totalSize += item.size.value.toNumber();
|
|
1595
1827
|
}
|
|
1828
|
+
}
|
|
1596
1829
|
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1830
|
+
if (totalSize > getGroupSize(context)) {
|
|
1831
|
+
return handleOverflow({
|
|
1832
|
+
...context,
|
|
1833
|
+
items: prepareItems({ ...context, items: withLastKnownSize }),
|
|
1834
|
+
}).items;
|
|
1600
1835
|
}
|
|
1601
1836
|
|
|
1602
|
-
return
|
|
1837
|
+
return withLastKnownSize;
|
|
1603
1838
|
},
|
|
1604
1839
|
}),
|
|
1605
1840
|
updateOrientation: assign({
|
|
@@ -1608,6 +1843,9 @@ export const groupMachine = createMachine(
|
|
|
1608
1843
|
return event.orientation;
|
|
1609
1844
|
},
|
|
1610
1845
|
}),
|
|
1846
|
+
onClearLastKnownSize: assign({
|
|
1847
|
+
items: ({ context }) => clearLastKnownSize(context.items),
|
|
1848
|
+
}),
|
|
1611
1849
|
assignPanelData: assign({
|
|
1612
1850
|
items: ({ context, event }) => {
|
|
1613
1851
|
isEvent(event, ["registerPanel"]);
|
|
@@ -1758,15 +1996,25 @@ export const groupMachine = createMachine(
|
|
|
1758
1996
|
onResize: ({ context }) => {
|
|
1759
1997
|
for (const item of context.items) {
|
|
1760
1998
|
if (isPanelData(item)) {
|
|
1761
|
-
const pixel =
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1999
|
+
const pixel = item.lastKnownSize
|
|
2000
|
+
? new Big(
|
|
2001
|
+
context.orientation === "horizontal"
|
|
2002
|
+
? item.lastKnownSize.width
|
|
2003
|
+
: item.lastKnownSize.height
|
|
2004
|
+
)
|
|
2005
|
+
: clampUnit(
|
|
2006
|
+
context,
|
|
2007
|
+
item,
|
|
2008
|
+
getUnitPixelValue(context, item.currentValue)
|
|
2009
|
+
);
|
|
2010
|
+
const groupSize = getGroupSize(context);
|
|
1766
2011
|
|
|
1767
2012
|
item.onResize?.current?.({
|
|
1768
2013
|
pixel: pixel.toNumber(),
|
|
1769
|
-
percentage:
|
|
2014
|
+
percentage:
|
|
2015
|
+
groupSize > 0
|
|
2016
|
+
? pixel.div(getGroupSize(context)).toNumber()
|
|
2017
|
+
: -1,
|
|
1770
2018
|
});
|
|
1771
2019
|
}
|
|
1772
2020
|
}
|