@window-splitter/state 1.1.0 → 1.1.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 +1 -1
- package/.turbo/turbo-test.log +45 -137
- package/CHANGELOG.md +25 -0
- package/dist/commonjs/index.d.ts +3 -0
- package/dist/commonjs/index.d.ts.map +1 -1
- package/dist/commonjs/index.js +86 -11
- package/dist/commonjs/index.js.map +1 -1
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +86 -11
- package/dist/esm/index.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +139 -12
- package/src/machine.test.ts +277 -0
- package/src/utils.test.ts +28 -1
package/src/index.ts
CHANGED
|
@@ -257,6 +257,7 @@ interface ApplyDeltaEvent {
|
|
|
257
257
|
type: "applyDelta";
|
|
258
258
|
delta: number;
|
|
259
259
|
handleId: string;
|
|
260
|
+
panelId: string;
|
|
260
261
|
}
|
|
261
262
|
|
|
262
263
|
interface SetOrientationEvent {
|
|
@@ -278,6 +279,7 @@ interface CollapsePanelEvent extends ControlledCollapseToggle {
|
|
|
278
279
|
type: "collapsePanel";
|
|
279
280
|
/** The panel to collapse */
|
|
280
281
|
panelId: string;
|
|
282
|
+
resolve?: () => void;
|
|
281
283
|
}
|
|
282
284
|
|
|
283
285
|
interface ExpandPanelEvent extends ControlledCollapseToggle {
|
|
@@ -285,6 +287,7 @@ interface ExpandPanelEvent extends ControlledCollapseToggle {
|
|
|
285
287
|
type: "expandPanel";
|
|
286
288
|
/** The panel to expand */
|
|
287
289
|
panelId: string;
|
|
290
|
+
resolve?: () => void;
|
|
288
291
|
}
|
|
289
292
|
|
|
290
293
|
interface SetPanelPixelSizeEvent {
|
|
@@ -402,6 +405,10 @@ export function prepareSnapshot(snapshot: GroupMachineContextValue) {
|
|
|
402
405
|
item.collapsedSize.value = new Big(item.collapsedSize.value);
|
|
403
406
|
item.min.value = new Big(item.min.value);
|
|
404
407
|
|
|
408
|
+
if (item.default) {
|
|
409
|
+
item.default.value = new Big(item.default.value);
|
|
410
|
+
}
|
|
411
|
+
|
|
405
412
|
if (item.max && item.max !== "1fr") {
|
|
406
413
|
item.max.value = new Big(item.max.value);
|
|
407
414
|
}
|
|
@@ -740,6 +747,25 @@ function getHandleForPanelId(
|
|
|
740
747
|
) {
|
|
741
748
|
const panelIndex = context.items.findIndex((item) => item.id === panelId);
|
|
742
749
|
|
|
750
|
+
// When in controlled collapse mode we defer to the controlled state to know if we need to update.
|
|
751
|
+
// The confirmation comes along as an expand/collapse event.
|
|
752
|
+
// The default behavior is to find the closes handle and use that to collapse, if we're dragging some other
|
|
753
|
+
// handle though we want to use that instead. This will results in a smoother visual experience.
|
|
754
|
+
if (context.activeDragHandleId) {
|
|
755
|
+
const handleIndex = getPanelHandleIndex(
|
|
756
|
+
context,
|
|
757
|
+
context.activeDragHandleId
|
|
758
|
+
);
|
|
759
|
+
const item = context.items[handleIndex];
|
|
760
|
+
|
|
761
|
+
if (item && isPanelHandle(item)) {
|
|
762
|
+
return {
|
|
763
|
+
item,
|
|
764
|
+
direction: handleIndex > panelIndex ? (1 as const) : (-1 as const),
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
|
|
743
769
|
invariant(panelIndex !== -1, `Expected panel before: ${panelId}`);
|
|
744
770
|
|
|
745
771
|
let item = context.items[panelIndex + 1];
|
|
@@ -757,6 +783,37 @@ function getHandleForPanelId(
|
|
|
757
783
|
throw new Error(`Cant find handle for panel: ${panelId}`);
|
|
758
784
|
}
|
|
759
785
|
|
|
786
|
+
function getHandleForPanelIdWithAvailableSpace(
|
|
787
|
+
context: GroupMachineContextValue,
|
|
788
|
+
panelId: string
|
|
789
|
+
) {
|
|
790
|
+
const panelIndex = context.items.findIndex((item) => item.id === panelId);
|
|
791
|
+
|
|
792
|
+
invariant(panelIndex !== -1, `Expected panel before: ${panelId}`);
|
|
793
|
+
|
|
794
|
+
let item = context.items[panelIndex + 1];
|
|
795
|
+
|
|
796
|
+
if (
|
|
797
|
+
item &&
|
|
798
|
+
isPanelHandle(item) &&
|
|
799
|
+
findPanelWithSpace(context, context.items, panelIndex + 1, 1, "add")
|
|
800
|
+
) {
|
|
801
|
+
return { item, direction: 1 as const };
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
item = context.items[panelIndex - 1];
|
|
805
|
+
|
|
806
|
+
if (
|
|
807
|
+
item &&
|
|
808
|
+
isPanelHandle(item) &&
|
|
809
|
+
findPanelWithSpace(context, context.items, panelIndex - 1, -1, "add")
|
|
810
|
+
) {
|
|
811
|
+
return { item, direction: -1 as const };
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
return getHandleForPanelId(context, panelId);
|
|
815
|
+
}
|
|
816
|
+
|
|
760
817
|
/** Given the specified order props and default order of the items, order the items */
|
|
761
818
|
function sortWithOrder(items: Array<Item>) {
|
|
762
819
|
const defaultPlacement: Record<string, number> = {};
|
|
@@ -804,8 +861,8 @@ function panelHasSpace(
|
|
|
804
861
|
`panelHasSpace only works with number values: ${item.id} ${item.currentValue}`
|
|
805
862
|
);
|
|
806
863
|
|
|
807
|
-
if (item.collapsible
|
|
808
|
-
return
|
|
864
|
+
if (item.collapsible) {
|
|
865
|
+
return !item.collapsed;
|
|
809
866
|
}
|
|
810
867
|
|
|
811
868
|
if (adjustment === "add") {
|
|
@@ -1103,6 +1160,7 @@ function updateLayout(
|
|
|
1103
1160
|
| (DragHandleEvent & {
|
|
1104
1161
|
controlled?: boolean;
|
|
1105
1162
|
disregardCollapseBuffer?: never;
|
|
1163
|
+
panelId?: string;
|
|
1106
1164
|
isVirtual?: boolean;
|
|
1107
1165
|
})
|
|
1108
1166
|
| {
|
|
@@ -1110,6 +1168,7 @@ function updateLayout(
|
|
|
1110
1168
|
value: MoveMoveEvent;
|
|
1111
1169
|
handleId: string;
|
|
1112
1170
|
controlled?: boolean;
|
|
1171
|
+
panelId: string;
|
|
1113
1172
|
disregardCollapseBuffer?: boolean;
|
|
1114
1173
|
isVirtual?: boolean;
|
|
1115
1174
|
}
|
|
@@ -1152,7 +1211,26 @@ function updateLayout(
|
|
|
1152
1211
|
|
|
1153
1212
|
invariant(isPanelData(panelBefore), `Expected panel before: ${handle.id}`);
|
|
1154
1213
|
|
|
1155
|
-
|
|
1214
|
+
/** The panel that gets bigger */
|
|
1215
|
+
const panelAfter =
|
|
1216
|
+
dragEvent.type === "collapsePanel"
|
|
1217
|
+
? // If we have the panel id just use that
|
|
1218
|
+
newItems.find(
|
|
1219
|
+
(item) =>
|
|
1220
|
+
item.id === dragEvent.panelId &&
|
|
1221
|
+
panelBefore.id !== dragEvent.panelId
|
|
1222
|
+
) ||
|
|
1223
|
+
// otherwise fallback to the next panel with space
|
|
1224
|
+
findPanelWithSpace(
|
|
1225
|
+
context,
|
|
1226
|
+
newItems,
|
|
1227
|
+
handleIndex - moveDirection,
|
|
1228
|
+
moveDirection * -1,
|
|
1229
|
+
"add",
|
|
1230
|
+
dragEvent.disregardCollapseBuffer
|
|
1231
|
+
) ||
|
|
1232
|
+
newItems[handleIndex - moveDirection]
|
|
1233
|
+
: newItems[handleIndex - moveDirection];
|
|
1156
1234
|
|
|
1157
1235
|
invariant(
|
|
1158
1236
|
panelAfter && isPanelData(panelAfter),
|
|
@@ -1170,7 +1248,7 @@ function updateLayout(
|
|
|
1170
1248
|
const newDragOvershoot = context.dragOvershoot.add(moveAmount);
|
|
1171
1249
|
|
|
1172
1250
|
// Don't let the panel expand until the threshold is reached
|
|
1173
|
-
if (!dragEvent.disregardCollapseBuffer) {
|
|
1251
|
+
if (!dragEvent.disregardCollapseBuffer && !dragEvent.controlled) {
|
|
1174
1252
|
const isInLeftBuffer = newDragOvershoot.lt(0) && moveDirection > 0;
|
|
1175
1253
|
const isInLeftOvershoot = newDragOvershoot.gt(0) && moveDirection > 0;
|
|
1176
1254
|
const isInRightBuffer = newDragOvershoot.gt(0) && moveDirection < 0;
|
|
@@ -1204,6 +1282,7 @@ function updateLayout(
|
|
|
1204
1282
|
// Don't let the panel collapse until the threshold is reached
|
|
1205
1283
|
if (
|
|
1206
1284
|
!dragEvent.disregardCollapseBuffer &&
|
|
1285
|
+
!dragEvent.controlled &&
|
|
1207
1286
|
panelBefore.collapsible &&
|
|
1208
1287
|
panelBefore.currentValue.value.eq(
|
|
1209
1288
|
getUnitPixelValue(context, panelBefore.min)
|
|
@@ -1287,7 +1366,10 @@ function updateLayout(
|
|
|
1287
1366
|
.minus(Math.abs(moveAmount))
|
|
1288
1367
|
);
|
|
1289
1368
|
|
|
1290
|
-
if (
|
|
1369
|
+
if (
|
|
1370
|
+
panelBeforeNewValue.lt(panelBefore.min.value) &&
|
|
1371
|
+
!panelBefore.collapsible
|
|
1372
|
+
) {
|
|
1291
1373
|
// TODO this should probably distribute the space between the panels?
|
|
1292
1374
|
return { dragOvershoot: newDragOvershoot };
|
|
1293
1375
|
}
|
|
@@ -1328,7 +1410,7 @@ function updateLayout(
|
|
|
1328
1410
|
panelBefore.collapsed = true;
|
|
1329
1411
|
panelBeforeNewValue = getUnitPixelValue(context, panelBefore.collapsedSize);
|
|
1330
1412
|
// Add the extra space created to the before panel
|
|
1331
|
-
panelAfterNewValue =
|
|
1413
|
+
panelAfterNewValue = panelAfter.currentValue.value.add(
|
|
1332
1414
|
panelBeforePreviousValue.minus(panelBeforeNewValue)
|
|
1333
1415
|
);
|
|
1334
1416
|
|
|
@@ -1432,6 +1514,7 @@ function iterativelyUpdateLayout({
|
|
|
1432
1514
|
controlled,
|
|
1433
1515
|
disregardCollapseBuffer,
|
|
1434
1516
|
isVirtual,
|
|
1517
|
+
panelId,
|
|
1435
1518
|
}: {
|
|
1436
1519
|
context: GroupMachineContextValue;
|
|
1437
1520
|
handleId: string;
|
|
@@ -1444,6 +1527,7 @@ function iterativelyUpdateLayout({
|
|
|
1444
1527
|
* no on* callbacks will be called
|
|
1445
1528
|
*/
|
|
1446
1529
|
isVirtual?: boolean;
|
|
1530
|
+
panelId: string;
|
|
1447
1531
|
}) {
|
|
1448
1532
|
let newContext: Partial<GroupMachineContextValue> = context;
|
|
1449
1533
|
|
|
@@ -1459,6 +1543,7 @@ function iterativelyUpdateLayout({
|
|
|
1459
1543
|
controlled,
|
|
1460
1544
|
disregardCollapseBuffer,
|
|
1461
1545
|
isVirtual,
|
|
1546
|
+
panelId,
|
|
1462
1547
|
value: dragHandlePayload({
|
|
1463
1548
|
delta: direction,
|
|
1464
1549
|
orientation: context.orientation,
|
|
@@ -1565,6 +1650,7 @@ function handleOverflow(context: GroupMachineContextValue) {
|
|
|
1565
1650
|
handleId: handleId.item.id,
|
|
1566
1651
|
delta: sizeChange,
|
|
1567
1652
|
direction: (handleId.direction * -1) as -1 | 1,
|
|
1653
|
+
panelId: collapsiblePanel.id,
|
|
1568
1654
|
context: {
|
|
1569
1655
|
...newContext,
|
|
1570
1656
|
// act like its the old size so the space is distributed correctly
|
|
@@ -1600,6 +1686,7 @@ function setCookie(name: string, jsonData: unknown) {
|
|
|
1600
1686
|
interface AnimationActorOutput {
|
|
1601
1687
|
panelId: string;
|
|
1602
1688
|
action: "expand" | "collapse";
|
|
1689
|
+
resolve?: () => void;
|
|
1603
1690
|
}
|
|
1604
1691
|
|
|
1605
1692
|
function getDeltaForEvent(
|
|
@@ -1625,11 +1712,20 @@ function animationActor(
|
|
|
1625
1712
|
abortController: AbortController
|
|
1626
1713
|
) {
|
|
1627
1714
|
const panel = getPanelWithId(context, event.panelId);
|
|
1628
|
-
const handle =
|
|
1629
|
-
|
|
1715
|
+
const handle = getHandleForPanelIdWithAvailableSpace(context, event.panelId);
|
|
1630
1716
|
let direction = new Big(handle.direction);
|
|
1631
1717
|
const fullDelta = getDeltaForEvent(context, event);
|
|
1632
1718
|
|
|
1719
|
+
const contextCopy = { ...context, items: prepareItems(context) };
|
|
1720
|
+
const finalLayout = iterativelyUpdateLayout({
|
|
1721
|
+
context: contextCopy,
|
|
1722
|
+
panelId: event.panelId,
|
|
1723
|
+
handleId: handle.item.id,
|
|
1724
|
+
delta: fullDelta,
|
|
1725
|
+
direction: handle.direction,
|
|
1726
|
+
isVirtual: true,
|
|
1727
|
+
});
|
|
1728
|
+
|
|
1633
1729
|
return new Promise<AnimationActorOutput | undefined>((resolve, reject) => {
|
|
1634
1730
|
abortController.signal.addEventListener("abort", () => {
|
|
1635
1731
|
reject(new Error("Operation was canceled"));
|
|
@@ -1657,6 +1753,7 @@ function animationActor(
|
|
|
1657
1753
|
type: "applyDelta",
|
|
1658
1754
|
handleId: handle.item.id,
|
|
1659
1755
|
delta: delta.toNumber(),
|
|
1756
|
+
panelId: panel.id,
|
|
1660
1757
|
});
|
|
1661
1758
|
|
|
1662
1759
|
appliedDelta = appliedDelta.add(
|
|
@@ -1670,8 +1767,21 @@ function animationActor(
|
|
|
1670
1767
|
);
|
|
1671
1768
|
|
|
1672
1769
|
if (e.eq(1)) {
|
|
1770
|
+
// If we're controlled expanding to a value that breaks the layout we might get negative values
|
|
1771
|
+
// In this case we need to use a valid layout like `iterativelyUpdateLayout`'s return value
|
|
1772
|
+
// Ideally we figure out some way to not do this but disregardCollapseBuffer is needed for animations
|
|
1773
|
+
if (
|
|
1774
|
+
context.items.find(
|
|
1775
|
+
(i) =>
|
|
1776
|
+
isPanelData(i) &&
|
|
1777
|
+
i.currentValue.value.round(undefined, Big.roundHalfEven).lt(0)
|
|
1778
|
+
)
|
|
1779
|
+
) {
|
|
1780
|
+
assign(context, finalLayout);
|
|
1781
|
+
}
|
|
1782
|
+
|
|
1673
1783
|
const action = event.type === "expandPanel" ? "expand" : "collapse";
|
|
1674
|
-
resolve({ panelId: panel.id, action });
|
|
1784
|
+
resolve({ panelId: panel.id, action, resolve: event.resolve });
|
|
1675
1785
|
return false;
|
|
1676
1786
|
}
|
|
1677
1787
|
|
|
@@ -1806,6 +1916,7 @@ export function groupMachine(
|
|
|
1806
1916
|
: handle.direction;
|
|
1807
1917
|
|
|
1808
1918
|
const newContext = updateLayout(context, {
|
|
1919
|
+
panelId: event.panelId,
|
|
1809
1920
|
handleId: handle.item.id,
|
|
1810
1921
|
type: "dragHandle",
|
|
1811
1922
|
controlled: event.controlled,
|
|
@@ -1850,15 +1961,20 @@ export function groupMachine(
|
|
|
1850
1961
|
},
|
|
1851
1962
|
cannotExpandPanel: (event: GroupMachineEvent) => {
|
|
1852
1963
|
isEvent(event, ["expandPanel"]);
|
|
1853
|
-
const delta = getDeltaForEvent(context, event);
|
|
1854
|
-
const handle = getHandleForPanelId(context, event.panelId);
|
|
1855
1964
|
const pixelItems = prepareItems(context);
|
|
1856
|
-
|
|
1857
1965
|
let interimContext = { ...context, items: pixelItems };
|
|
1966
|
+
|
|
1967
|
+
const delta = getDeltaForEvent(context, event);
|
|
1968
|
+
const handle = getHandleForPanelIdWithAvailableSpace(
|
|
1969
|
+
interimContext,
|
|
1970
|
+
event.panelId
|
|
1971
|
+
);
|
|
1972
|
+
|
|
1858
1973
|
interimContext = {
|
|
1859
1974
|
...interimContext,
|
|
1860
1975
|
...iterativelyUpdateLayout({
|
|
1861
1976
|
context: interimContext,
|
|
1977
|
+
panelId: event.panelId,
|
|
1862
1978
|
handleId: handle.item.id,
|
|
1863
1979
|
controlled: event.controlled,
|
|
1864
1980
|
delta: delta,
|
|
@@ -1907,6 +2023,8 @@ export function groupMachine(
|
|
|
1907
2023
|
}
|
|
1908
2024
|
|
|
1909
2025
|
state.current = to;
|
|
2026
|
+
|
|
2027
|
+
onUpdate?.(context);
|
|
1910
2028
|
}
|
|
1911
2029
|
|
|
1912
2030
|
function send(event: GroupMachineEvent) {
|
|
@@ -2117,11 +2235,13 @@ export function groupMachine(
|
|
|
2117
2235
|
const delta = isBigger
|
|
2118
2236
|
? newSize.minus(current)
|
|
2119
2237
|
: current.minus(newSize);
|
|
2238
|
+
panel.sizeBeforeCollapse = newSize.toNumber();
|
|
2120
2239
|
|
|
2121
2240
|
Object.assign(
|
|
2122
2241
|
context,
|
|
2123
2242
|
iterativelyUpdateLayout({
|
|
2124
2243
|
context,
|
|
2244
|
+
panelId: event.panelId,
|
|
2125
2245
|
direction: (handle.direction * (isBigger ? 1 : -1)) as -1 | 1,
|
|
2126
2246
|
handleId: handle.item.id,
|
|
2127
2247
|
delta,
|
|
@@ -2146,6 +2266,9 @@ export function groupMachine(
|
|
|
2146
2266
|
(output) => {
|
|
2147
2267
|
actions.onAnimationEnd(output);
|
|
2148
2268
|
transition("idle");
|
|
2269
|
+
if (event.resolve) {
|
|
2270
|
+
requestAnimationFrame(event.resolve);
|
|
2271
|
+
}
|
|
2149
2272
|
}
|
|
2150
2273
|
);
|
|
2151
2274
|
}
|
|
@@ -2166,6 +2289,9 @@ export function groupMachine(
|
|
|
2166
2289
|
(output) => {
|
|
2167
2290
|
actions.onAnimationEnd(output);
|
|
2168
2291
|
transition("idle");
|
|
2292
|
+
if (event.resolve) {
|
|
2293
|
+
requestAnimationFrame(event.resolve);
|
|
2294
|
+
}
|
|
2169
2295
|
}
|
|
2170
2296
|
);
|
|
2171
2297
|
}
|
|
@@ -2198,6 +2324,7 @@ export function groupMachine(
|
|
|
2198
2324
|
assign(
|
|
2199
2325
|
context,
|
|
2200
2326
|
updateLayout(context, {
|
|
2327
|
+
panelId: event.panelId,
|
|
2201
2328
|
handleId: event.handleId,
|
|
2202
2329
|
type: "collapsePanel",
|
|
2203
2330
|
disregardCollapseBuffer: true,
|
package/src/machine.test.ts
CHANGED
|
@@ -485,6 +485,283 @@ describe("constraints", () => {
|
|
|
485
485
|
);
|
|
486
486
|
});
|
|
487
487
|
|
|
488
|
+
test("sibling collapsible panels work", async () => {
|
|
489
|
+
const onCollapseChange = (isCollapsed: boolean) => {
|
|
490
|
+
if (isCollapsed) {
|
|
491
|
+
actor.send({
|
|
492
|
+
type: "collapsePanel",
|
|
493
|
+
panelId: "panel-1",
|
|
494
|
+
controlled: true,
|
|
495
|
+
});
|
|
496
|
+
} else {
|
|
497
|
+
actor.send({
|
|
498
|
+
type: "expandPanel",
|
|
499
|
+
panelId: "panel-1",
|
|
500
|
+
controlled: true,
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
const actor = createActor({
|
|
506
|
+
groupId: "group",
|
|
507
|
+
items: [
|
|
508
|
+
initializePanel({
|
|
509
|
+
id: "panel-1",
|
|
510
|
+
default: "200px",
|
|
511
|
+
min: "100px",
|
|
512
|
+
collapsible: true,
|
|
513
|
+
collapsed: false,
|
|
514
|
+
onCollapseChange: { current: onCollapseChange },
|
|
515
|
+
}),
|
|
516
|
+
initializePanelHandleData({ id: "resizer-1", size: "10px" }),
|
|
517
|
+
initializePanel({
|
|
518
|
+
id: "panel-2",
|
|
519
|
+
default: "200px",
|
|
520
|
+
min: "100px",
|
|
521
|
+
collapsible: true,
|
|
522
|
+
}),
|
|
523
|
+
initializePanelHandleData({ id: "resizer-2", size: "10px" }),
|
|
524
|
+
initializePanel({
|
|
525
|
+
id: "panel-3",
|
|
526
|
+
min: "200px",
|
|
527
|
+
collapsible: true,
|
|
528
|
+
collapsedSize: "60px",
|
|
529
|
+
}),
|
|
530
|
+
],
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
initializeSizes(actor, { width: 800, height: 200 });
|
|
534
|
+
|
|
535
|
+
capturePixelValues(actor, () => {
|
|
536
|
+
// First collapse both panels
|
|
537
|
+
expect(buildTemplate(actor.value)).toMatchInlineSnapshot(
|
|
538
|
+
`"200px 10px 200px 10px 380px"`
|
|
539
|
+
);
|
|
540
|
+
dragHandle(actor, { id: "resizer-2", delta: -410 });
|
|
541
|
+
expect(buildTemplate(actor.value)).toMatchInlineSnapshot(
|
|
542
|
+
`"0px 10px 0px 10px 780px"`
|
|
543
|
+
);
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
actor.send({
|
|
547
|
+
type: "expandPanel",
|
|
548
|
+
panelId: "panel-1",
|
|
549
|
+
controlled: true,
|
|
550
|
+
});
|
|
551
|
+
await waitForIdle(actor);
|
|
552
|
+
|
|
553
|
+
capturePixelValues(actor, () => {
|
|
554
|
+
expect(buildTemplate(actor.value)).toMatchInlineSnapshot(
|
|
555
|
+
`"100px 10px 0px 10px 680px"`
|
|
556
|
+
);
|
|
557
|
+
});
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
test("controlled collapse complex drags", async () => {
|
|
561
|
+
const onCollapseChange = (panelId: string) => (isCollapsed: boolean) => {
|
|
562
|
+
if (isCollapsed) {
|
|
563
|
+
actor.send({
|
|
564
|
+
type: "collapsePanel",
|
|
565
|
+
panelId,
|
|
566
|
+
controlled: true,
|
|
567
|
+
});
|
|
568
|
+
} else {
|
|
569
|
+
actor.send({ type: "expandPanel", panelId, controlled: true });
|
|
570
|
+
}
|
|
571
|
+
};
|
|
572
|
+
|
|
573
|
+
const onChange1 = onCollapseChange("panel-1");
|
|
574
|
+
const onChange2 = onCollapseChange("panel-2");
|
|
575
|
+
const onChange3 = onCollapseChange("panel-3");
|
|
576
|
+
|
|
577
|
+
const actor = createActor({
|
|
578
|
+
groupId: "group",
|
|
579
|
+
items: [
|
|
580
|
+
initializePanel({
|
|
581
|
+
id: "panel-1",
|
|
582
|
+
default: "200px",
|
|
583
|
+
min: "100px",
|
|
584
|
+
collapsible: true,
|
|
585
|
+
collapsed: false,
|
|
586
|
+
onCollapseChange: { current: onChange1 },
|
|
587
|
+
}),
|
|
588
|
+
initializePanelHandleData({ id: "resizer-1", size: "10px" }),
|
|
589
|
+
initializePanel({
|
|
590
|
+
id: "panel-2",
|
|
591
|
+
default: "200px",
|
|
592
|
+
min: "100px",
|
|
593
|
+
collapsible: true,
|
|
594
|
+
onCollapseChange: { current: onChange2 },
|
|
595
|
+
}),
|
|
596
|
+
initializePanelHandleData({ id: "resizer-2", size: "10px" }),
|
|
597
|
+
initializePanel({
|
|
598
|
+
id: "panel-3",
|
|
599
|
+
min: "100px",
|
|
600
|
+
collapsible: true,
|
|
601
|
+
onCollapseChange: { current: onChange3 },
|
|
602
|
+
}),
|
|
603
|
+
],
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
initializeSizes(actor, { width: 800, height: 200 });
|
|
607
|
+
|
|
608
|
+
// Collapse middle panel from the left
|
|
609
|
+
capturePixelValues(actor, () => {
|
|
610
|
+
expect(buildTemplate(actor.value)).toMatchInlineSnapshot(
|
|
611
|
+
`"200px 10px 200px 10px 380px"`
|
|
612
|
+
);
|
|
613
|
+
dragHandle(actor, { id: "resizer-1", delta: 200 });
|
|
614
|
+
expect(buildTemplate(actor.value)).toMatchInlineSnapshot(
|
|
615
|
+
`"450px 10px 0px 10px 330px"`
|
|
616
|
+
);
|
|
617
|
+
dragHandle(actor, { id: "resizer-1", delta: -200 });
|
|
618
|
+
expect(buildTemplate(actor.value)).toMatchInlineSnapshot(
|
|
619
|
+
`"249px 10px 201px 10px 330px"`
|
|
620
|
+
);
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
// Collapse middle panel from the right
|
|
624
|
+
capturePixelValues(actor, () => {
|
|
625
|
+
dragHandle(actor, { id: "resizer-2", delta: -200 });
|
|
626
|
+
expect(buildTemplate(actor.value)).toMatchInlineSnapshot(
|
|
627
|
+
`"200px 10px 0px 10px 580px"`
|
|
628
|
+
);
|
|
629
|
+
dragHandle(actor, { id: "resizer-2", delta: 200 });
|
|
630
|
+
expect(buildTemplate(actor.value)).toMatchInlineSnapshot(
|
|
631
|
+
`"200px 10px 201px 10px 379px"`
|
|
632
|
+
);
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
// Collapse the left panel
|
|
636
|
+
capturePixelValues(actor, () => {
|
|
637
|
+
dragHandle(actor, { id: "resizer-1", delta: -200 });
|
|
638
|
+
expect(buildTemplate(actor.value)).toMatchInlineSnapshot(
|
|
639
|
+
`"0px 10px 401px 10px 379px"`
|
|
640
|
+
);
|
|
641
|
+
dragHandle(actor, { id: "resizer-1", delta: 200 });
|
|
642
|
+
expect(buildTemplate(actor.value)).toMatchInlineSnapshot(
|
|
643
|
+
`"150px 10px 251px 10px 379px"`
|
|
644
|
+
);
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
// Collapse the right panel
|
|
648
|
+
capturePixelValues(actor, () => {
|
|
649
|
+
dragHandle(actor, { id: "resizer-2", delta: 600 });
|
|
650
|
+
expect(buildTemplate(actor.value)).toMatchInlineSnapshot(
|
|
651
|
+
`"150px 10px 630px 10px 0px"`
|
|
652
|
+
);
|
|
653
|
+
dragHandle(actor, { id: "resizer-2", delta: -600 });
|
|
654
|
+
expect(buildTemplate(actor.value)).toMatchInlineSnapshot(
|
|
655
|
+
`"150px 10px 300px 10px 330px"`
|
|
656
|
+
);
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
// Sweep the left handle to the right
|
|
660
|
+
capturePixelValues(actor, () => {
|
|
661
|
+
dragHandle(actor, { id: "resizer-1", delta: 1000 });
|
|
662
|
+
expect(buildTemplate(actor.value)).toMatchInlineSnapshot(
|
|
663
|
+
`"780px 10px 0px 10px 0px"`
|
|
664
|
+
);
|
|
665
|
+
});
|
|
666
|
+
|
|
667
|
+
// Sweep the right handle to the left
|
|
668
|
+
capturePixelValues(actor, () => {
|
|
669
|
+
dragHandle(actor, { id: "resizer-2", delta: -1000 });
|
|
670
|
+
expect(buildTemplate(actor.value)).toMatchInlineSnapshot(
|
|
671
|
+
`"0px 10px 0px 10px 780px"`
|
|
672
|
+
);
|
|
673
|
+
});
|
|
674
|
+
});
|
|
675
|
+
|
|
676
|
+
test("controlled collapse events", async () => {
|
|
677
|
+
const onCollapseChange = (panelId: string) => (isCollapsed: boolean) => {
|
|
678
|
+
if (isCollapsed) {
|
|
679
|
+
actor.send({
|
|
680
|
+
type: "collapsePanel",
|
|
681
|
+
panelId,
|
|
682
|
+
controlled: true,
|
|
683
|
+
});
|
|
684
|
+
} else {
|
|
685
|
+
actor.send({ type: "expandPanel", panelId, controlled: true });
|
|
686
|
+
}
|
|
687
|
+
};
|
|
688
|
+
|
|
689
|
+
const onChange1 = onCollapseChange("panel-1");
|
|
690
|
+
const onChange2 = onCollapseChange("panel-2");
|
|
691
|
+
const onChange3 = onCollapseChange("panel-3");
|
|
692
|
+
|
|
693
|
+
const actor = createActor({
|
|
694
|
+
groupId: "group",
|
|
695
|
+
items: [
|
|
696
|
+
initializePanel({
|
|
697
|
+
id: "panel-1",
|
|
698
|
+
default: "200px",
|
|
699
|
+
min: "100px",
|
|
700
|
+
collapsible: true,
|
|
701
|
+
collapsed: false,
|
|
702
|
+
onCollapseChange: { current: onChange1 },
|
|
703
|
+
}),
|
|
704
|
+
initializePanelHandleData({ id: "resizer-1", size: "10px" }),
|
|
705
|
+
initializePanel({
|
|
706
|
+
id: "panel-2",
|
|
707
|
+
default: "200px",
|
|
708
|
+
min: "100px",
|
|
709
|
+
collapsible: true,
|
|
710
|
+
collapsed: false,
|
|
711
|
+
onCollapseChange: { current: onChange2 },
|
|
712
|
+
}),
|
|
713
|
+
initializePanelHandleData({ id: "resizer-2", size: "10px" }),
|
|
714
|
+
initializePanel({
|
|
715
|
+
id: "panel-3",
|
|
716
|
+
min: "100px",
|
|
717
|
+
collapsible: true,
|
|
718
|
+
collapsed: false,
|
|
719
|
+
onCollapseChange: { current: onChange3 },
|
|
720
|
+
}),
|
|
721
|
+
],
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
initializeSizes(actor, { width: 800, height: 200 });
|
|
725
|
+
|
|
726
|
+
capturePixelValues(actor, () => {
|
|
727
|
+
expect(buildTemplate(actor.value)).toMatchInlineSnapshot(
|
|
728
|
+
`"200px 10px 200px 10px 380px"`
|
|
729
|
+
);
|
|
730
|
+
});
|
|
731
|
+
|
|
732
|
+
actor.send({ type: "collapsePanel", panelId: "panel-2", controlled: true });
|
|
733
|
+
await waitForIdle(actor);
|
|
734
|
+
capturePixelValues(actor, () => {
|
|
735
|
+
expect(buildTemplate(actor.value)).toMatchInlineSnapshot(
|
|
736
|
+
`"200px 10px 0px 10px 580px"`
|
|
737
|
+
);
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
actor.send({ type: "collapsePanel", panelId: "panel-3", controlled: true });
|
|
741
|
+
await waitForIdle(actor);
|
|
742
|
+
capturePixelValues(actor, () => {
|
|
743
|
+
expect(buildTemplate(actor.value)).toMatchInlineSnapshot(
|
|
744
|
+
`"780px 10px 0px 10px 0px"`
|
|
745
|
+
);
|
|
746
|
+
});
|
|
747
|
+
|
|
748
|
+
actor.send({ type: "expandPanel", panelId: "panel-2", controlled: true });
|
|
749
|
+
await waitForIdle(actor);
|
|
750
|
+
capturePixelValues(actor, () => {
|
|
751
|
+
expect(buildTemplate(actor.value)).toMatchInlineSnapshot(
|
|
752
|
+
`"580px 10px 200px 10px 0px"`
|
|
753
|
+
);
|
|
754
|
+
});
|
|
755
|
+
|
|
756
|
+
actor.send({ type: "expandPanel", panelId: "panel-3", controlled: true });
|
|
757
|
+
await waitForIdle(actor);
|
|
758
|
+
capturePixelValues(actor, () => {
|
|
759
|
+
expect(buildTemplate(actor.value)).toMatchInlineSnapshot(
|
|
760
|
+
`"100px 10px 0px 10px 680px"`
|
|
761
|
+
);
|
|
762
|
+
});
|
|
763
|
+
});
|
|
764
|
+
|
|
488
765
|
test("panel can have a min", () => {
|
|
489
766
|
const actor = createActor({ groupId: "group" });
|
|
490
767
|
|
package/src/utils.test.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { expect, test, describe } from "vitest";
|
|
1
|
+
import { expect, test, describe, assert } from "vitest";
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
getUnitPercentageValue,
|
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
initializePanel,
|
|
7
7
|
getCursor,
|
|
8
8
|
initializePanelHandleData,
|
|
9
|
+
prepareSnapshot,
|
|
10
|
+
type Item,
|
|
9
11
|
} from "./index.js";
|
|
10
12
|
import Big from "big.js";
|
|
11
13
|
import { createActor } from "./test-utils.js";
|
|
@@ -190,3 +192,28 @@ describe("initializePanelHandleData", () => {
|
|
|
190
192
|
`);
|
|
191
193
|
});
|
|
192
194
|
});
|
|
195
|
+
|
|
196
|
+
describe('prepareSnapshot', () => {
|
|
197
|
+
test('converts sizes to Big', () => {
|
|
198
|
+
const item: Item = initializePanel({ id: 'panel-1', min: '100px', max: '300px', default: '200px' });
|
|
199
|
+
|
|
200
|
+
prepareSnapshot({
|
|
201
|
+
size: { width: 500, height: 300 },
|
|
202
|
+
items: [item, initializePanel({ id: 'panel-2', min: '100px' })],
|
|
203
|
+
groupId: 'group-1',
|
|
204
|
+
orientation: 'horizontal',
|
|
205
|
+
dragOvershoot: new Big(0),
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
expect(item.currentValue.value).toBeInstanceOf(Big);
|
|
209
|
+
expect(item.collapsedSize.value).toBeInstanceOf(Big);
|
|
210
|
+
|
|
211
|
+
expect(item.min.value).toBeInstanceOf(Big);
|
|
212
|
+
|
|
213
|
+
assert(typeof item.max === 'object');
|
|
214
|
+
expect(item.max.value).toBeInstanceOf(Big);
|
|
215
|
+
|
|
216
|
+
assert(typeof item.default === 'object');
|
|
217
|
+
expect(item.default.value).toBeInstanceOf(Big);
|
|
218
|
+
});
|
|
219
|
+
});
|