@window-splitter/state 0.2.2 → 0.2.3
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/.tshy/commonjs.json +1 -0
- package/.tshy/esm.json +1 -0
- package/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-lint.log +1 -1
- package/.turbo/turbo-test.log +1023 -129
- package/CHANGELOG.md +21 -0
- package/coverage/clover.xml +358 -345
- package/coverage/coverage-final.json +1 -1
- package/coverage/index.html +18 -18
- package/coverage/index.ts.html +624 -402
- package/dist/commonjs/index.d.ts +22 -9
- package/dist/commonjs/index.d.ts.map +1 -1
- package/dist/commonjs/index.js +189 -134
- package/dist/commonjs/index.js.map +1 -1
- package/dist/esm/index.d.ts +22 -9
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +188 -114
- package/dist/esm/index.js.map +1 -1
- package/package.json +6 -5
- package/src/index.ts +279 -153
- package/src/machine.test.ts +174 -85
- package/src/utils.test.ts +22 -9
- package/dist/commonjs/machine.test.d.ts +0 -5
- package/dist/commonjs/machine.test.d.ts.map +0 -1
- package/dist/commonjs/machine.test.js +0 -1038
- package/dist/commonjs/machine.test.js.map +0 -1
- package/dist/commonjs/utils.test.d.ts +0 -2
- package/dist/commonjs/utils.test.d.ts.map +0 -1
- package/dist/commonjs/utils.test.js +0 -79
- package/dist/commonjs/utils.test.js.map +0 -1
- package/dist/esm/machine.test.d.ts +0 -5
- package/dist/esm/machine.test.d.ts.map +0 -1
- package/dist/esm/machine.test.js +0 -1036
- package/dist/esm/machine.test.js.map +0 -1
- package/dist/esm/utils.test.d.ts +0 -2
- package/dist/esm/utils.test.d.ts.map +0 -1
- package/dist/esm/utils.test.js +0 -77
- 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 {
|
|
2
|
+
import {
|
|
3
|
+
createMachine,
|
|
4
|
+
assign,
|
|
5
|
+
enqueueActions,
|
|
6
|
+
fromPromise,
|
|
7
|
+
Snapshot,
|
|
8
|
+
} from "xstate";
|
|
3
9
|
import invariant from "invariant";
|
|
4
|
-
import
|
|
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:
|
|
28
|
+
value: Big.Big;
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
interface ParsedPixelUnit {
|
|
26
32
|
type: "pixel";
|
|
27
|
-
value:
|
|
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":
|
|
124
|
-
|
|
125
|
-
|
|
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<
|
|
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:
|
|
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
|
|
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
|
|
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:
|
|
486
|
+
value: Big.Big
|
|
426
487
|
) {
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
679
|
-
max: makePixelUnit(
|
|
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
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
)
|
|
843
|
-
|
|
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
|
-
|
|
853
|
-
|
|
936
|
+
return { dragOvershoot: newDragOvershoot };
|
|
937
|
+
}
|
|
938
|
+
}
|
|
854
939
|
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
)
|
|
860
|
-
|
|
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
|
-
|
|
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
|
|
878
|
-
const panelAfterNewValueRaw = panelAfter.currentValue.value
|
|
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
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
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
|
-
|
|
914
|
-
|
|
1011
|
+
|
|
1012
|
+
if (extra.gt(0)) {
|
|
1013
|
+
panelAfterNewValue = panelAfterNewValue.add(extra);
|
|
915
1014
|
}
|
|
916
|
-
|
|
1015
|
+
|
|
1016
|
+
panelBeforeNewValue = panelBeforeNewValue
|
|
917
1017
|
// Subtract the delta of the after panel's size
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
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
|
|
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 =
|
|
967
|
-
panelAfter.currentValue =
|
|
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
|
-
|
|
974
|
-
|
|
975
|
-
|
|
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
|
-
|
|
980
|
-
|
|
1080
|
+
if (leftoverSpace.gt(0)) {
|
|
1081
|
+
panelBefore.currentValue.value =
|
|
1082
|
+
panelBefore.currentValue.value.add(leftoverSpace);
|
|
1083
|
+
}
|
|
981
1084
|
|
|
982
|
-
return { items: newItems
|
|
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:
|
|
1013
|
-
|
|
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:
|
|
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 <
|
|
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:
|
|
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 (
|
|
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
|
|
1220
|
+
const newValue = clampUnit(context, targetPanel, oldValue.add(deltaLeft));
|
|
1113
1221
|
|
|
1114
1222
|
targetPanel.currentValue.value = newValue;
|
|
1115
|
-
|
|
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
|
-
|
|
1150
|
-
|
|
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
|
|
1156
|
-
fullDelta = panel.currentValue.value
|
|
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 =
|
|
1169
|
-
const e = panel.collapseAnimation ? ease(progress) : 1;
|
|
1170
|
-
const delta = (
|
|
1171
|
-
|
|
1172
|
-
send({
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
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
|
-
|
|
1530
|
+
const overflowDueToHandles = context.items
|
|
1531
|
+
.reduce((acc, i) => {
|
|
1414
1532
|
if (isPanelHandle(i)) {
|
|
1415
|
-
return acc
|
|
1533
|
+
return acc.add(getUnitPixelValue(context, i.size));
|
|
1416
1534
|
}
|
|
1417
1535
|
|
|
1418
|
-
return acc
|
|
1419
|
-
},
|
|
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
|
-
|
|
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:
|
|
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
|
|
1623
|
+
const delta = isBigger
|
|
1624
|
+
? newSize.minus(current)
|
|
1625
|
+
: current.minus(newSize);
|
|
1500
1626
|
|
|
1501
1627
|
enqueue.assign(
|
|
1502
1628
|
iterativelyUpdateLayout({
|