@window-splitter/state 0.2.2 → 0.2.3--canary.823a479.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.
Files changed (43) hide show
  1. package/.tshy/commonjs.json +1 -0
  2. package/.tshy/esm.json +1 -0
  3. package/.tshy-build/esm/index.d.ts +327 -0
  4. package/.tshy-build/esm/index.d.ts.map +1 -0
  5. package/.tshy-build/esm/index.js +964 -0
  6. package/.tshy-build/esm/index.js.map +1 -0
  7. package/.tshy-build/esm/package.json +3 -0
  8. package/.turbo/turbo-build.log +1 -1
  9. package/.turbo/turbo-lint.log +1 -1
  10. package/.turbo/turbo-test.log +1023 -129
  11. package/coverage/clover.xml +358 -345
  12. package/coverage/coverage-final.json +1 -1
  13. package/coverage/index.html +18 -18
  14. package/coverage/index.ts.html +624 -402
  15. package/dist/commonjs/index.d.ts +22 -9
  16. package/dist/commonjs/index.d.ts.map +1 -1
  17. package/dist/commonjs/index.js +189 -134
  18. package/dist/commonjs/index.js.map +1 -1
  19. package/dist/esm/index.d.ts +22 -9
  20. package/dist/esm/index.d.ts.map +1 -1
  21. package/dist/esm/index.js +188 -114
  22. package/dist/esm/index.js.map +1 -1
  23. package/package.json +6 -6
  24. package/src/index.ts +279 -153
  25. package/src/machine.test.ts +174 -85
  26. package/src/package.json +3 -0
  27. package/src/utils.test.ts +22 -9
  28. package/dist/commonjs/machine.test.d.ts +0 -5
  29. package/dist/commonjs/machine.test.d.ts.map +0 -1
  30. package/dist/commonjs/machine.test.js +0 -1038
  31. package/dist/commonjs/machine.test.js.map +0 -1
  32. package/dist/commonjs/utils.test.d.ts +0 -2
  33. package/dist/commonjs/utils.test.d.ts.map +0 -1
  34. package/dist/commonjs/utils.test.js +0 -79
  35. package/dist/commonjs/utils.test.js.map +0 -1
  36. package/dist/esm/machine.test.d.ts +0 -5
  37. package/dist/esm/machine.test.d.ts.map +0 -1
  38. package/dist/esm/machine.test.js +0 -1036
  39. package/dist/esm/machine.test.js.map +0 -1
  40. package/dist/esm/utils.test.d.ts +0 -2
  41. package/dist/esm/utils.test.d.ts.map +0 -1
  42. package/dist/esm/utils.test.js +0 -77
  43. package/dist/esm/utils.test.js.map +0 -1
package/src/index.ts CHANGED
@@ -1,7 +1,13 @@
1
1
  import { raf } from "@react-spring/rafz";
2
- import { createMachine, assign, enqueueActions, fromPromise } from "xstate";
2
+ import {
3
+ createMachine,
4
+ assign,
5
+ enqueueActions,
6
+ fromPromise,
7
+ Snapshot,
8
+ } from "xstate";
3
9
  import invariant from "invariant";
4
- import * as easings from "d3-ease";
10
+ import Big from "big.js";
5
11
 
6
12
  // #region Constants
7
13
 
@@ -19,22 +25,22 @@ type Orientation = "horizontal" | "vertical";
19
25
 
20
26
  interface ParsedPercentUnit {
21
27
  type: "percent";
22
- value: number;
28
+ value: Big.Big;
23
29
  }
24
30
 
25
31
  interface ParsedPixelUnit {
26
32
  type: "pixel";
27
- value: number;
33
+ value: Big.Big;
28
34
  }
29
35
 
30
36
  type ParsedUnit = ParsedPercentUnit | ParsedPixelUnit;
31
37
 
32
- function makePercentUnit(value: number): ParsedPercentUnit {
33
- return { type: "percent", value };
38
+ export function makePercentUnit(value: number): ParsedPercentUnit {
39
+ return { type: "percent", value: new Big(value) };
34
40
  }
35
41
 
36
- function makePixelUnit(value: number): ParsedPixelUnit {
37
- return { type: "pixel", value };
42
+ export function makePixelUnit(value: number): ParsedPixelUnit {
43
+ return { type: "pixel", value: new Big(value) };
38
44
  }
39
45
 
40
46
  interface MoveMoveEvent {
@@ -119,10 +125,22 @@ function getCollapseAnimation(panel: PanelData) {
119
125
  return { ease: easeFn, duration };
120
126
  }
121
127
 
128
+ /** Copied from https://github.com/d3/d3-ease */
122
129
  const collapseAnimations = {
123
- "ease-in-out": easings.easeQuadInOut,
124
- bounce: easings.easeBackInOut,
125
- linear: easings.easeLinear,
130
+ "ease-in-out": function quadInOut(t: number) {
131
+ return ((t *= 2) <= 1 ? t * t : --t * (2 - t) + 1) / 2;
132
+ },
133
+ bounce: function backInOut(t: number) {
134
+ const s = 1.70158;
135
+ return (
136
+ ((t *= 2) < 1
137
+ ? t * t * ((s + 1) * t - s)
138
+ : (t -= 2) * t * ((s + 1) * t + s) + 2) / 2
139
+ );
140
+ },
141
+ linear: function linear(t: number) {
142
+ return +t;
143
+ },
126
144
  };
127
145
 
128
146
  type CollapseAnimation = keyof typeof collapseAnimations;
@@ -156,7 +174,12 @@ interface UnregisterPanelEvent {
156
174
  id: string;
157
175
  }
158
176
 
159
- export type InitializePanelHandleData = Omit<PanelHandleData, "type">;
177
+ export type InitializePanelHandleData = Omit<
178
+ PanelHandleData,
179
+ "type" | "size"
180
+ > & {
181
+ size: PixelUnit;
182
+ };
160
183
 
161
184
  interface RegisterPanelHandleEvent {
162
185
  /** Register a new panel handle with the state machine */
@@ -265,7 +288,7 @@ export interface GroupMachineContextValue {
265
288
  /** The orientation of the grid */
266
289
  orientation: Orientation;
267
290
  /** How much the drag has overshot the handle */
268
- dragOvershoot: number;
291
+ dragOvershoot: Big.Big;
269
292
  /** An id to use for autosaving the layout */
270
293
  autosaveId?: string;
271
294
  groupId: string;
@@ -297,6 +320,36 @@ type EventForType<T extends GroupMachineEvent["type"]> = Extract<
297
320
 
298
321
  // #region Helpers
299
322
 
323
+ export function prepareSnapshot(snapshot: Snapshot<unknown>) {
324
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
325
+ const snapshotContext = (snapshot as any)
326
+ .context as unknown as GroupMachineContextValue;
327
+
328
+ snapshotContext.dragOvershoot = new Big(snapshotContext.dragOvershoot);
329
+
330
+ for (const item of snapshotContext.items) {
331
+ if (isPanelData(item)) {
332
+ item.currentValue.value = new Big(item.currentValue.value);
333
+
334
+ if (item.collapsedSize) {
335
+ item.collapsedSize.value = new Big(item.collapsedSize.value);
336
+ }
337
+
338
+ if (item.min) {
339
+ item.min.value = new Big(item.min.value);
340
+ }
341
+
342
+ if (item.max && item.max !== "1fr") {
343
+ item.max.value = new Big(item.max.value);
344
+ }
345
+ } else {
346
+ item.size.value = new Big(item.size.value);
347
+ }
348
+ }
349
+
350
+ return snapshot;
351
+ }
352
+
300
353
  /** Assert that the provided event is one of the accepted types */
301
354
  function isEvent<T extends GroupMachineEvent["type"]>(
302
355
  event: GroupMachineEvent,
@@ -375,6 +428,14 @@ export function initializePanel(
375
428
  >;
376
429
  }
377
430
 
431
+ export function initializePanelHandleData(item: InitializePanelHandleData) {
432
+ return {
433
+ type: "handle" as const,
434
+ ...item,
435
+ size: parseUnit(item.size) as ParsedPixelUnit,
436
+ };
437
+ }
438
+
378
439
  /** Parse a `Unit` string or `clamp` value */
379
440
  export function parseUnit(unit: Unit | "1fr"): ParsedUnit {
380
441
  if (unit === "1fr") {
@@ -395,10 +456,10 @@ export function parseUnit(unit: Unit | "1fr"): ParsedUnit {
395
456
  /** Convert a `Unit` to a percentage of the group size */
396
457
  export function getUnitPercentageValue(groupsSize: number, unit: ParsedUnit) {
397
458
  if (unit.type === "pixel") {
398
- return unit.value / groupsSize;
459
+ return groupsSize === 0 ? 0 : unit.value.div(groupsSize).toNumber();
399
460
  }
400
461
 
401
- return unit.value;
462
+ return unit.value.toNumber();
402
463
  }
403
464
 
404
465
  export function getGroupSize(context: GroupMachineContextValue) {
@@ -415,19 +476,23 @@ export function getUnitPixelValue(
415
476
  const parsed = unit === "1fr" ? parseUnit(unit) : unit;
416
477
  return parsed.type === "pixel"
417
478
  ? parsed.value
418
- : (parsed.value / 100) * getGroupSize(context);
479
+ : new Big(parsed.value).div(100).mul(getGroupSize(context));
419
480
  }
420
481
 
421
482
  /** Clamp a new `currentValue` given the panel's constraints. */
422
483
  function clampUnit(
423
484
  context: GroupMachineContextValue,
424
485
  item: PanelData,
425
- value: number
486
+ value: Big.Big
426
487
  ) {
427
- return Math.min(
428
- Math.max(value, getUnitPixelValue(context, item.min)),
429
- getUnitPixelValue(context, item.max)
430
- );
488
+ const min = getUnitPixelValue(context, item.min);
489
+ const max = getUnitPixelValue(context, item.max);
490
+
491
+ if (value.gte(min) && value.lte(max)) {
492
+ return value;
493
+ }
494
+
495
+ return value.lt(min) ? min : max;
431
496
  }
432
497
 
433
498
  /** Get a panel with a particular ID. */
@@ -549,7 +614,11 @@ function sortWithOrder(items: Array<Item>) {
549
614
  }
550
615
 
551
616
  /** Check if the panel has space available to add to */
552
- function panelHasSpace(context: GroupMachineContextValue, item: PanelData) {
617
+ function panelHasSpace(
618
+ context: GroupMachineContextValue,
619
+ item: PanelData,
620
+ adjustment: "add" | "subtract"
621
+ ) {
553
622
  invariant(
554
623
  item.currentValue.type === "pixel",
555
624
  `panelHasSpace only works with number values: ${item.id} ${item.currentValue}`
@@ -559,7 +628,17 @@ function panelHasSpace(context: GroupMachineContextValue, item: PanelData) {
559
628
  return true;
560
629
  }
561
630
 
562
- return item.currentValue.value > getUnitPixelValue(context, item.min);
631
+ if (adjustment === "add") {
632
+ return (
633
+ item.currentValue.value.gte(getUnitPixelValue(context, item.min)) &&
634
+ item.currentValue.value.lt(getUnitPixelValue(context, item.max))
635
+ );
636
+ }
637
+
638
+ return (
639
+ item.currentValue.value.gt(getUnitPixelValue(context, item.min)) &&
640
+ item.currentValue.value.lte(getUnitPixelValue(context, item.max))
641
+ );
563
642
  }
564
643
 
565
644
  /** Search in a `direction` for a panel that still has space to expand. */
@@ -568,6 +647,7 @@ function findPanelWithSpace(
568
647
  items: Array<Item>,
569
648
  start: number,
570
649
  direction: number,
650
+ adjustment: "add" | "subtract",
571
651
  disregardCollapseBuffer?: boolean
572
652
  ) {
573
653
  const slice =
@@ -582,7 +662,7 @@ function findPanelWithSpace(
582
662
  ? createUnrestrainedPanel(context, panel)
583
663
  : panel;
584
664
 
585
- if (panelHasSpace(context, targetPanel)) {
665
+ if (panelHasSpace(context, targetPanel, adjustment)) {
586
666
  return panel;
587
667
  }
588
668
  }
@@ -590,23 +670,23 @@ function findPanelWithSpace(
590
670
 
591
671
  /** Add up all the static values in the layout */
592
672
  function getStaticWidth(context: GroupMachineContextValue) {
593
- let width = 0;
673
+ let width = new Big(0);
594
674
 
595
675
  for (const item of context.items) {
596
676
  if (isPanelHandle(item)) {
597
- width += item.size.value;
677
+ width = width.add(item.size.value);
598
678
  } else if (
599
679
  isPanelData(item) &&
600
680
  item.collapsed &&
601
681
  item.currentValue.type === "pixel"
602
682
  ) {
603
- width += item.currentValue.value;
683
+ width = width.add(item.currentValue.value);
604
684
  } else if (
605
685
  isPanelData(item) &&
606
686
  item.default &&
607
687
  item.default.type === "pixel"
608
688
  ) {
609
- width += item.default.value;
689
+ width = width.add(item.default.value);
610
690
  }
611
691
  }
612
692
 
@@ -615,10 +695,10 @@ function getStaticWidth(context: GroupMachineContextValue) {
615
695
 
616
696
  function formatUnit(unit: ParsedUnit): Unit {
617
697
  if (unit.type === "pixel") {
618
- return `${unit.value}px`;
698
+ return `${unit.value.toNumber()}px`;
619
699
  }
620
700
 
621
- return `${unit.value}%`;
701
+ return `${unit.value.toNumber()}%`;
622
702
  }
623
703
 
624
704
  /** Build the grid template from the item values. */
@@ -632,8 +712,12 @@ export function buildTemplate(context: GroupMachineContextValue) {
632
712
 
633
713
  if (
634
714
  item.currentValue.type === "pixel" &&
635
- item.currentValue.value !== -1
715
+ item.currentValue.value.toNumber() !== -1
636
716
  ) {
717
+ if (item.currentValue.value.toNumber() < 0) {
718
+ return "0px";
719
+ }
720
+
637
721
  return formatUnit(item.currentValue);
638
722
  } else if (item.currentValue.type === "percent") {
639
723
  const max = item.max === "1fr" ? "100%" : formatUnit(item.max);
@@ -669,14 +753,11 @@ function addDeDuplicatedItems(items: Array<Item>, newItem: Item) {
669
753
  return sortWithOrder([...restItems, newItem]);
670
754
  }
671
755
 
672
- function createUnrestrainedPanel(
673
- context: GroupMachineContextValue,
674
- data: PanelData
675
- ) {
756
+ function createUnrestrainedPanel(_: GroupMachineContextValue, data: PanelData) {
676
757
  return {
677
758
  ...data,
678
- min: makePixelUnit(0),
679
- max: makePixelUnit(getGroupSize(context)),
759
+ min: makePixelUnit(-100000),
760
+ max: makePixelUnit(100000),
680
761
  };
681
762
  }
682
763
 
@@ -747,12 +828,11 @@ export function prepareItems(context: GroupMachineContextValue) {
747
828
  continue;
748
829
  }
749
830
 
750
- // TODO: Decimal proposal
751
- item.currentValue = makePixelUnit(
752
- Math.round(
753
- (getGroupSize(context) - staticWidth) * item.currentValue.value
754
- )
755
- );
831
+ const pixel = new Big(getGroupSize(context))
832
+ .minus(staticWidth)
833
+ .mul(item.currentValue.value);
834
+
835
+ item.currentValue = makePixelUnit(pixel.toNumber());
756
836
  }
757
837
 
758
838
  return newItems;
@@ -799,13 +879,14 @@ function updateLayout(
799
879
  newItems,
800
880
  handleIndex + moveDirection,
801
881
  moveDirection,
882
+ "subtract",
802
883
  dragEvent.disregardCollapseBuffer
803
884
  );
804
885
 
805
886
  // No panel with space, just record the drag overshoot
806
887
  if (!panelBefore) {
807
888
  return {
808
- dragOvershoot: context.dragOvershoot + moveAmount,
889
+ dragOvershoot: context.dragOvershoot.add(moveAmount),
809
890
  };
810
891
  }
811
892
 
@@ -818,55 +899,70 @@ function updateLayout(
818
899
  `Expected panel after: ${handle.id}`
819
900
  );
820
901
 
821
- const newDragOvershoot = context.dragOvershoot + moveAmount;
902
+ if (
903
+ panelAfter.currentValue.value.eq(getUnitPixelValue(context, panelAfter.max))
904
+ ) {
905
+ return {
906
+ dragOvershoot: context.dragOvershoot.add(moveAmount),
907
+ };
908
+ }
909
+
910
+ const newDragOvershoot = context.dragOvershoot.add(moveAmount);
822
911
 
823
912
  // Don't let the panel expand until the threshold is reached
824
913
  if (!dragEvent.disregardCollapseBuffer) {
825
- if (panelAfter.collapsible && panelAfter.collapsed) {
826
- const isInLeftBuffer = newDragOvershoot < 0 && moveDirection > 0;
827
- const isInLeftOvershoot = newDragOvershoot > 0 && moveDirection > 0;
828
- const isInRightBuffer = newDragOvershoot > 0 && moveDirection < 0;
829
- const isInRightOvershoot = newDragOvershoot < 0 && moveDirection < 0;
830
- const potentialNewValue =
831
- panelAfter.currentValue.value +
832
- newDragOvershoot * (isInRightBuffer ? moveDirection : 1);
833
- const min = getUnitPixelValue(context, panelAfter.min);
834
-
835
- if (
836
- (newDragOvershoot === 0 ||
837
- isInRightBuffer ||
838
- isInLeftBuffer ||
839
- ((isInLeftOvershoot || isInRightOvershoot) &&
840
- Math.abs(newDragOvershoot) < COLLAPSE_THRESHOLD)) &&
841
- potentialNewValue < min
842
- ) {
843
- return { dragOvershoot: newDragOvershoot };
844
- }
845
- }
846
- // Don't let the panel collapse until the threshold is reached
847
- else if (
848
- panelBefore.collapsible &&
849
- panelBefore.currentValue.value ===
850
- getUnitPixelValue(context, panelBefore.min)
914
+ const isInLeftBuffer = newDragOvershoot.lt(0) && moveDirection > 0;
915
+ const isInLeftOvershoot = newDragOvershoot.gt(0) && moveDirection > 0;
916
+ const isInRightBuffer = newDragOvershoot.gt(0) && moveDirection < 0;
917
+ const isInRightOvershoot = newDragOvershoot.lt(0) && moveDirection < 0;
918
+ const potentialNewValue = panelAfter.currentValue.value.add(
919
+ new Big(newDragOvershoot).mul(isInRightBuffer ? moveDirection : 1)
920
+ );
921
+ const min = getUnitPixelValue(context, panelAfter.min);
922
+
923
+ const isInDragBugger =
924
+ newDragOvershoot.abs().lt(COLLAPSE_THRESHOLD) &&
925
+ panelAfter.collapsible &&
926
+ panelAfter.collapsed &&
927
+ (isInLeftOvershoot || isInRightOvershoot);
928
+
929
+ if (
930
+ potentialNewValue.lte(min) &&
931
+ (newDragOvershoot.eq(0) ||
932
+ isInRightBuffer ||
933
+ isInLeftBuffer ||
934
+ isInDragBugger)
851
935
  ) {
852
- const potentialNewValue =
853
- panelBefore.currentValue.value - Math.abs(newDragOvershoot);
936
+ return { dragOvershoot: newDragOvershoot };
937
+ }
938
+ }
854
939
 
855
- if (
856
- Math.abs(newDragOvershoot) < COLLAPSE_THRESHOLD &&
857
- potentialNewValue >
858
- getUnitPixelValue(context, panelBefore.collapsedSize)
859
- ) {
860
- return { dragOvershoot: newDragOvershoot };
861
- }
940
+ // Don't let the panel collapse until the threshold is reached
941
+ if (
942
+ panelBefore.collapsible &&
943
+ panelBefore.currentValue.value ===
944
+ getUnitPixelValue(context, panelBefore.min)
945
+ ) {
946
+ const potentialNewValue = panelBefore.currentValue.value.sub(
947
+ newDragOvershoot.abs()
948
+ );
949
+
950
+ if (
951
+ newDragOvershoot.abs().lt(COLLAPSE_THRESHOLD) &&
952
+ potentialNewValue.gt(
953
+ getUnitPixelValue(context, panelBefore.collapsedSize)
954
+ )
955
+ ) {
956
+ return { dragOvershoot: newDragOvershoot };
862
957
  }
863
958
  }
864
959
 
865
960
  // Apply the move amount to the panel before the slider
866
961
  const unrestrainedPanelBefore = createUnrestrainedPanel(context, panelBefore);
867
962
  const panelBeforePreviousValue = panelBefore.currentValue.value;
868
- const panelBeforeNewValueRaw =
869
- panelBefore.currentValue.value - moveAmount * moveDirection;
963
+ const panelBeforeNewValueRaw = panelBefore.currentValue.value.minus(
964
+ new Big(moveAmount).mul(moveDirection)
965
+ );
870
966
  let panelBeforeNewValue = dragEvent.disregardCollapseBuffer
871
967
  ? clampUnit(context, unrestrainedPanelBefore, panelBeforeNewValueRaw)
872
968
  : clampUnit(context, panelBefore, panelBeforeNewValueRaw);
@@ -874,8 +970,8 @@ function updateLayout(
874
970
  // Also apply the move amount the panel after the slider
875
971
  const unrestrainedPanelAfter = createUnrestrainedPanel(context, panelAfter);
876
972
  const panelAfterPreviousValue = panelAfter.currentValue.value;
877
- const applied = panelBeforePreviousValue - panelBeforeNewValue;
878
- const panelAfterNewValueRaw = panelAfter.currentValue.value + applied;
973
+ const applied = panelBeforePreviousValue.minus(panelBeforeNewValue);
974
+ const panelAfterNewValueRaw = panelAfter.currentValue.value.add(applied);
879
975
  let panelAfterNewValue = dragEvent.disregardCollapseBuffer
880
976
  ? clampUnit(context, unrestrainedPanelAfter, panelAfterNewValueRaw)
881
977
  : clampUnit(context, panelAfter, panelAfterNewValueRaw);
@@ -901,24 +997,30 @@ function updateLayout(
901
997
  // Calculate the amount "extra" after the minSize the panel should grow
902
998
  const extra =
903
999
  // Take the size it was at
904
- getUnitPixelValue(context, panelAfter.collapsedSize) +
905
- // Add in the full overshoot so the cursor is near the slider
906
- Math.abs(context.dragOvershoot) -
907
- // Subtract the min size of the panel
908
- panelAfterNewValue +
909
- // Then re-add the move amount
910
- Math.abs(moveAmount);
1000
+ getUnitPixelValue(context, panelAfter.collapsedSize)
1001
+ // Add in the full overshoot so the cursor is near the slider
1002
+ .add(context.dragOvershoot.abs())
1003
+ // Subtract the min size of the panel
1004
+ .sub(
1005
+ panelAfterNewValue
1006
+ // Then re-add the move amount
1007
+ .add(Math.abs(moveAmount))
1008
+ );
911
1009
 
912
1010
  panelAfter.collapsed = false;
913
- if (extra > 0) {
914
- panelAfterNewValue += extra;
1011
+
1012
+ if (extra.gt(0)) {
1013
+ panelAfterNewValue = panelAfterNewValue.add(extra);
915
1014
  }
916
- panelBeforeNewValue -=
1015
+
1016
+ panelBeforeNewValue = panelBeforeNewValue
917
1017
  // Subtract the delta of the after panel's size
918
- panelAfterNewValue -
919
- panelAfterPreviousValue -
920
- // And then re-apply the movement value
921
- Math.abs(moveAmount);
1018
+ .minus(
1019
+ panelAfterNewValue
1020
+ .minus(panelAfterPreviousValue)
1021
+ // And then re-apply the movement value
1022
+ .minus(Math.abs(moveAmount))
1023
+ );
922
1024
 
923
1025
  if (
924
1026
  panelAfter.onCollapseChange?.current &&
@@ -952,7 +1054,9 @@ function updateLayout(
952
1054
  panelBefore.collapsed = true;
953
1055
  panelBeforeNewValue = getUnitPixelValue(context, panelBefore.collapsedSize);
954
1056
  // Add the extra space created to the before panel
955
- panelAfterNewValue += panelBeforePreviousValue - panelBeforeNewValue;
1057
+ panelAfterNewValue = panelAfterNewValue.add(
1058
+ panelBeforePreviousValue.minus(panelBeforeNewValue)
1059
+ );
956
1060
 
957
1061
  if (
958
1062
  panelBefore.onCollapseChange?.current &&
@@ -963,23 +1067,22 @@ function updateLayout(
963
1067
  }
964
1068
  }
965
1069
 
966
- panelBefore.currentValue = makePixelUnit(panelBeforeNewValue);
967
- panelAfter.currentValue = makePixelUnit(panelAfterNewValue);
1070
+ panelBefore.currentValue = { type: "pixel", value: panelBeforeNewValue };
1071
+ panelAfter.currentValue = { type: "pixel", value: panelAfterNewValue };
968
1072
 
969
- const leftoverSpace =
970
- getGroupSize(context) -
1073
+ const leftoverSpace = new Big(getGroupSize(context)).minus(
971
1074
  newItems.reduce(
972
- (acc, b) =>
973
- acc +
974
- // in updateLayout the panel units will always be numbers
975
- (isPanelData(b) ? b.currentValue.value : b.size.value),
976
- 0
977
- );
1075
+ (acc, b) => acc.add(isPanelData(b) ? b.currentValue.value : b.size.value),
1076
+ new Big(0)
1077
+ )
1078
+ );
978
1079
 
979
- // TODO: this is wrong?
980
- panelBefore.currentValue.value += leftoverSpace;
1080
+ if (leftoverSpace.gt(0)) {
1081
+ panelBefore.currentValue.value =
1082
+ panelBefore.currentValue.value.add(leftoverSpace);
1083
+ }
981
1084
 
982
- return { items: newItems, dragOvershoot: 0 };
1085
+ return { items: newItems };
983
1086
  }
984
1087
 
985
1088
  /** Converts the items to percentages */
@@ -1009,9 +1112,12 @@ export function commitLayout(context: GroupMachineContextValue) {
1009
1112
 
1010
1113
  newItems[index] = {
1011
1114
  ...item,
1012
- currentValue: makePercentUnit(
1013
- item.currentValue.value / (getGroupSize(context) - staticWidth)
1014
- ),
1115
+ currentValue: {
1116
+ type: "percent",
1117
+ value: item.currentValue.value.div(
1118
+ new Big(getGroupSize(context)).sub(staticWidth)
1119
+ ),
1120
+ },
1015
1121
  };
1016
1122
  });
1017
1123
 
@@ -1050,14 +1156,14 @@ function iterativelyUpdateLayout({
1050
1156
  }: {
1051
1157
  context: GroupMachineContextValue;
1052
1158
  handleId: string;
1053
- delta: number;
1159
+ delta: Big.Big;
1054
1160
  direction: -1 | 1;
1055
1161
  controlled?: boolean;
1056
1162
  disregardCollapseBuffer?: boolean;
1057
1163
  }) {
1058
1164
  let newContext: Partial<GroupMachineContextValue> = context;
1059
1165
 
1060
- for (let i = 0; i < Math.abs(delta); i++) {
1166
+ for (let i = 0; i < delta.abs().toNumber(); i++) {
1061
1167
  newContext = updateLayout(
1062
1168
  {
1063
1169
  ...context,
@@ -1083,19 +1189,21 @@ function applyDeltaInBothDirections(
1083
1189
  context: GroupMachineContextValue,
1084
1190
  newItems: Array<Item>,
1085
1191
  itemIndex: number,
1086
- delta: number
1192
+ delta: Big.Big
1087
1193
  ) {
1088
1194
  let hasTriedBothDirections = false;
1089
1195
  let direction = 1;
1196
+ let deltaLeft = new Big(delta);
1090
1197
 
1091
1198
  // Starting from where the items was removed add space to the panels around it.
1092
1199
  // This is only needed for conditional rendering.
1093
- while (delta !== 0) {
1200
+ while (deltaLeft.toNumber() !== 0) {
1094
1201
  const targetPanel = findPanelWithSpace(
1095
1202
  context,
1096
1203
  newItems,
1097
1204
  itemIndex + direction,
1098
- direction
1205
+ direction,
1206
+ delta.gt(0) ? "add" : "subtract"
1099
1207
  );
1100
1208
 
1101
1209
  if (!targetPanel) {
@@ -1109,10 +1217,10 @@ function applyDeltaInBothDirections(
1109
1217
  }
1110
1218
 
1111
1219
  const oldValue = targetPanel.currentValue.value;
1112
- const newValue = clampUnit(context, targetPanel, oldValue + delta);
1220
+ const newValue = clampUnit(context, targetPanel, oldValue.add(deltaLeft));
1113
1221
 
1114
1222
  targetPanel.currentValue.value = newValue;
1115
- delta -= newValue - oldValue;
1223
+ deltaLeft = deltaLeft.sub(newValue.sub(oldValue));
1116
1224
  direction = direction === 1 ? -1 : 1;
1117
1225
  }
1118
1226
  }
@@ -1141,19 +1249,19 @@ const animationActor = fromPromise<
1141
1249
  const panel = getPanelWithId(context, event.panelId);
1142
1250
  const handle = getHandleForPanelId(context, event.panelId);
1143
1251
 
1144
- let direction = handle.direction;
1145
- let fullDelta = 0;
1252
+ let direction = new Big(handle.direction);
1253
+ let fullDelta = new Big(0);
1146
1254
 
1147
1255
  if (event.type === "expandPanel") {
1148
- fullDelta =
1149
- (panel.sizeBeforeCollapse ?? getUnitPixelValue(context, panel.min)) -
1150
- panel.currentValue.value;
1256
+ fullDelta = new Big(
1257
+ panel.sizeBeforeCollapse ?? getUnitPixelValue(context, panel.min)
1258
+ ).minus(panel.currentValue.value);
1151
1259
  } else {
1152
1260
  const collapsedSize = getUnitPixelValue(context, panel.collapsedSize);
1153
1261
 
1154
- panel.sizeBeforeCollapse = panel.currentValue.value;
1155
- direction *= -1 as -1 | 1;
1156
- fullDelta = panel.currentValue.value - collapsedSize;
1262
+ panel.sizeBeforeCollapse = panel.currentValue.value.toNumber();
1263
+ direction = direction.mul(new Big(-1));
1264
+ fullDelta = panel.currentValue.value.minus(collapsedSize);
1157
1265
  }
1158
1266
 
1159
1267
  const fps = 60;
@@ -1162,21 +1270,31 @@ const animationActor = fromPromise<
1162
1270
  panel.collapseAnimation ? duration / (1000 / fps) : 1
1163
1271
  );
1164
1272
  let frame = 0;
1165
- let appliedDelta = 0;
1273
+ let appliedDelta = new Big(0);
1166
1274
 
1167
1275
  function renderFrame() {
1168
- const progress = (frame++ + 1) / totalFrames;
1169
- const e = panel.collapseAnimation ? ease(progress) : 1;
1170
- const delta = (e * fullDelta - appliedDelta) * direction;
1171
-
1172
- send({ type: "applyDelta", handleId: handle.item.id, delta });
1173
- appliedDelta +=
1174
- Math.abs(delta) *
1175
- ((delta > 0 && direction === -1) || (delta < 0 && direction === 1)
1176
- ? -1
1177
- : 1);
1178
-
1179
- if (e === 1) {
1276
+ const progress = ++frame / totalFrames;
1277
+ const e = new Big(panel.collapseAnimation ? ease(progress) : 1);
1278
+ const delta = e.mul(fullDelta).sub(appliedDelta).mul(direction);
1279
+
1280
+ send({
1281
+ type: "applyDelta",
1282
+ handleId: handle.item.id,
1283
+ delta: delta.toNumber(),
1284
+ });
1285
+
1286
+ appliedDelta = appliedDelta.add(
1287
+ delta
1288
+ .abs()
1289
+ .mul(
1290
+ (delta.gt(0) && direction.lt(0)) ||
1291
+ (delta.lt(0) && direction.gt(0))
1292
+ ? -1
1293
+ : 1
1294
+ )
1295
+ );
1296
+
1297
+ if (e.eq(1)) {
1180
1298
  const action = event.type === "expandPanel" ? "expand" : "collapse";
1181
1299
  resolve({ panelId: panel.id, action });
1182
1300
  return false;
@@ -1206,7 +1324,7 @@ export const groupMachine = createMachine(
1206
1324
  size: { width: 0, height: 0 },
1207
1325
  items: input.initialItems || [],
1208
1326
  orientation: input.orientation || "horizontal",
1209
- dragOvershoot: 0,
1327
+ dragOvershoot: new Big(0),
1210
1328
  autosaveId: input.autosaveId,
1211
1329
  groupId: input.groupId,
1212
1330
  }),
@@ -1409,20 +1527,21 @@ export const groupMachine = createMachine(
1409
1527
  (item) => item.id === event.data.id
1410
1528
  );
1411
1529
  const newContext = { ...context, items: newItems };
1412
- const overflowDueToHandles =
1413
- context.items.reduce((acc, i) => {
1530
+ const overflowDueToHandles = context.items
1531
+ .reduce((acc, i) => {
1414
1532
  if (isPanelHandle(i)) {
1415
- return acc + getUnitPixelValue(context, i.size);
1533
+ return acc.add(getUnitPixelValue(context, i.size));
1416
1534
  }
1417
1535
 
1418
- return acc + i.currentValue.value;
1419
- }, 0) - getGroupSize(context);
1536
+ return acc.add(i.currentValue.value);
1537
+ }, new Big(0))
1538
+ .minus(getGroupSize(context));
1420
1539
 
1421
1540
  applyDeltaInBothDirections(
1422
1541
  newContext,
1423
1542
  newItems,
1424
1543
  itemIndex,
1425
- -1 * (currentValue.value + overflowDueToHandles)
1544
+ currentValue.value.add(overflowDueToHandles).neg()
1426
1545
  );
1427
1546
 
1428
1547
  return newItems;
@@ -1432,10 +1551,15 @@ export const groupMachine = createMachine(
1432
1551
  items: ({ context, event }) => {
1433
1552
  isEvent(event, ["registerPanelHandle"]);
1434
1553
 
1554
+ const unit = parseUnit(event.data.size);
1555
+
1435
1556
  return addDeDuplicatedItems(context.items, {
1436
1557
  type: "handle",
1437
1558
  ...event.data,
1438
- size: event.data.size as ParsedPixelUnit,
1559
+ size: {
1560
+ type: "pixel",
1561
+ value: new Big(unit.value),
1562
+ },
1439
1563
  });
1440
1564
  },
1441
1565
  }),
@@ -1469,7 +1593,7 @@ export const groupMachine = createMachine(
1469
1593
  enqueue.assign(updateLayout(context, event));
1470
1594
  }),
1471
1595
  commit: assign({
1472
- dragOvershoot: 0,
1596
+ dragOvershoot: new Big(0),
1473
1597
  items: ({ context }) => commitLayout(context),
1474
1598
  }),
1475
1599
  onApplyDelta: assign(({ context, event }) => {
@@ -1496,7 +1620,9 @@ export const groupMachine = createMachine(
1496
1620
  getUnitPixelValue(context, parseUnit(event.size))
1497
1621
  );
1498
1622
  const isBigger = newSize > current;
1499
- const delta = isBigger ? newSize - current : current - newSize;
1623
+ const delta = isBigger
1624
+ ? newSize.minus(current)
1625
+ : current.minus(newSize);
1500
1626
 
1501
1627
  enqueue.assign(
1502
1628
  iterativelyUpdateLayout({