@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/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 && !item.collapsed) {
808
- return true;
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
- const panelAfter = newItems[handleIndex - moveDirection];
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 (panelBeforeNewValue.lt(panelBefore.min.value)) {
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 = panelAfterNewValue.add(
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 = getHandleForPanelId(context, event.panelId);
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,
@@ -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
+ });