@window-splitter/state 0.3.2 → 0.4.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.
- package/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-lint.log +1 -1
- package/CHANGELOG.md +27 -0
- package/coverage/coverage-final.json +1 -1
- package/coverage/coverage-summary.json +2 -2
- package/coverage/index.html +21 -21
- package/coverage/index.ts.html +1367 -893
- package/dist/commonjs/index.d.ts +11 -13
- package/dist/commonjs/index.d.ts.map +1 -1
- package/dist/commonjs/index.js +126 -29
- package/dist/commonjs/index.js.map +1 -1
- package/dist/esm/index.d.ts +11 -13
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +126 -29
- package/dist/esm/index.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +197 -48
- package/src/machine.test.ts +219 -0
package/dist/esm/index.js
CHANGED
|
@@ -138,6 +138,7 @@ export function initializePanel(item) {
|
|
|
138
138
|
id: item.id,
|
|
139
139
|
collapseAnimation: item.collapseAnimation,
|
|
140
140
|
default: item.default ? parseUnit(item.default) : undefined,
|
|
141
|
+
isStaticAtRest: item.isStaticAtRest,
|
|
141
142
|
};
|
|
142
143
|
return { ...data, currentValue: makePixelUnit(-1) };
|
|
143
144
|
}
|
|
@@ -280,8 +281,7 @@ function panelHasSpace(context, item, adjustment) {
|
|
|
280
281
|
return (item.currentValue.value.gte(getUnitPixelValue(context, item.min)) &&
|
|
281
282
|
item.currentValue.value.lt(getUnitPixelValue(context, item.max)));
|
|
282
283
|
}
|
|
283
|
-
return
|
|
284
|
-
item.currentValue.value.lte(getUnitPixelValue(context, item.max)));
|
|
284
|
+
return item.currentValue.value.gt(getUnitPixelValue(context, item.min));
|
|
285
285
|
}
|
|
286
286
|
/** Search in a `direction` for a panel that still has space to expand. */
|
|
287
287
|
function findPanelWithSpace(context, items, start, direction, adjustment, disregardCollapseBuffer) {
|
|
@@ -305,9 +305,10 @@ function getStaticWidth(context) {
|
|
|
305
305
|
if (isPanelHandle(item)) {
|
|
306
306
|
width = width.add(item.size.value);
|
|
307
307
|
}
|
|
308
|
-
else if (
|
|
309
|
-
item.
|
|
310
|
-
|
|
308
|
+
else if (item.collapsed && item.currentValue.type === "pixel") {
|
|
309
|
+
width = width.add(item.currentValue.value);
|
|
310
|
+
}
|
|
311
|
+
else if (item.isStaticAtRest) {
|
|
311
312
|
width = width.add(item.currentValue.value);
|
|
312
313
|
}
|
|
313
314
|
}
|
|
@@ -354,6 +355,10 @@ export function buildTemplate(context) {
|
|
|
354
355
|
const min = formatUnit(item.min);
|
|
355
356
|
if (item.currentValue.type === "pixel" &&
|
|
356
357
|
item.currentValue.value.toNumber() !== -1) {
|
|
358
|
+
if (item.isStaticAtRest) {
|
|
359
|
+
const max = item.max === "1fr" ? "100%" : formatUnit(item.max);
|
|
360
|
+
return `clamp(${min}, ${formatUnit(item.currentValue)}, ${max})`;
|
|
361
|
+
}
|
|
357
362
|
return formatUnit(item.currentValue);
|
|
358
363
|
}
|
|
359
364
|
else if (item.currentValue.type === "percent") {
|
|
@@ -459,11 +464,11 @@ export function prepareItems(context) {
|
|
|
459
464
|
const newItems = [];
|
|
460
465
|
for (const item of context.items) {
|
|
461
466
|
if (!item || !isPanelData(item)) {
|
|
462
|
-
newItems.push(item);
|
|
467
|
+
newItems.push({ ...item });
|
|
463
468
|
continue;
|
|
464
469
|
}
|
|
465
470
|
if (item.currentValue.type === "pixel") {
|
|
466
|
-
newItems.push(item);
|
|
471
|
+
newItems.push({ ...item });
|
|
467
472
|
continue;
|
|
468
473
|
}
|
|
469
474
|
const pixel = new Big(getGroupSize(context))
|
|
@@ -517,6 +522,10 @@ function updateLayout(context, dragEvent) {
|
|
|
517
522
|
const potentialNewValue = panelAfter.currentValue.value.add(new Big(newDragOvershoot).mul(isInRightBuffer ? moveDirection : 1));
|
|
518
523
|
const min = getUnitPixelValue(context, panelAfter.min);
|
|
519
524
|
const isInDragBugger = newDragOvershoot.abs().lt(COLLAPSE_THRESHOLD) &&
|
|
525
|
+
// Let the panel expand at it's min size
|
|
526
|
+
!panelAfter.currentValue.value
|
|
527
|
+
.add(newDragOvershoot.abs())
|
|
528
|
+
.gte(panelAfter.min.value) &&
|
|
520
529
|
panelAfter.collapsible &&
|
|
521
530
|
panelAfter.collapsed &&
|
|
522
531
|
(isInLeftOvershoot || isInRightOvershoot);
|
|
@@ -529,9 +538,9 @@ function updateLayout(context, dragEvent) {
|
|
|
529
538
|
}
|
|
530
539
|
}
|
|
531
540
|
// Don't let the panel collapse until the threshold is reached
|
|
532
|
-
if (
|
|
533
|
-
panelBefore.
|
|
534
|
-
|
|
541
|
+
if (!dragEvent.disregardCollapseBuffer &&
|
|
542
|
+
panelBefore.collapsible &&
|
|
543
|
+
panelBefore.currentValue.value.eq(getUnitPixelValue(context, panelBefore.min))) {
|
|
535
544
|
const potentialNewValue = panelBefore.currentValue.value.sub(newDragOvershoot.abs());
|
|
536
545
|
if (newDragOvershoot.abs().lt(COLLAPSE_THRESHOLD) &&
|
|
537
546
|
potentialNewValue.gt(getUnitPixelValue(context, panelBefore.collapsedSize))) {
|
|
@@ -578,7 +587,6 @@ function updateLayout(context, dragEvent) {
|
|
|
578
587
|
.sub(panelAfterNewValue
|
|
579
588
|
// Then re-add the move amount
|
|
580
589
|
.add(Math.abs(moveAmount)));
|
|
581
|
-
panelAfter.collapsed = false;
|
|
582
590
|
if (extra.gt(0)) {
|
|
583
591
|
panelAfterNewValue = panelAfterNewValue.add(extra);
|
|
584
592
|
}
|
|
@@ -588,14 +596,18 @@ function updateLayout(context, dragEvent) {
|
|
|
588
596
|
.minus(panelAfterPreviousValue)
|
|
589
597
|
// And then re-apply the movement value
|
|
590
598
|
.minus(Math.abs(moveAmount)));
|
|
599
|
+
if (panelBeforeNewValue.lt(panelBefore.min.value)) {
|
|
600
|
+
// TODO this should probably distribute the space between the panels?
|
|
601
|
+
return { dragOvershoot: newDragOvershoot };
|
|
602
|
+
}
|
|
603
|
+
panelAfter.collapsed = false;
|
|
591
604
|
if (panelAfter.onCollapseChange?.current &&
|
|
592
605
|
!panelAfter.collapseIsControlled &&
|
|
593
606
|
!dragEvent.controlled) {
|
|
594
607
|
panelAfter.onCollapseChange.current(false);
|
|
595
608
|
}
|
|
596
609
|
}
|
|
597
|
-
const panelBeforeIsAboutToCollapse = panelBefore.currentValue.value
|
|
598
|
-
getUnitPixelValue(context, panelBefore.min);
|
|
610
|
+
const panelBeforeIsAboutToCollapse = panelBefore.currentValue.value.eq(getUnitPixelValue(context, panelBefore.min));
|
|
599
611
|
// If the panel was expanded and now is at it's min size, collapse it
|
|
600
612
|
if (!dragEvent.disregardCollapseBuffer &&
|
|
601
613
|
panelBefore.collapsible &&
|
|
@@ -621,8 +633,7 @@ function updateLayout(context, dragEvent) {
|
|
|
621
633
|
panelAfter.currentValue = { type: "pixel", value: panelAfterNewValue };
|
|
622
634
|
const leftoverSpace = new Big(getGroupSize(context)).minus(newItems.reduce((acc, b) => acc.add(isPanelData(b) ? b.currentValue.value : b.size.value), new Big(0)));
|
|
623
635
|
if (!leftoverSpace.eq(0)) {
|
|
624
|
-
panelBefore.currentValue.value =
|
|
625
|
-
panelBefore.currentValue.value.add(leftoverSpace);
|
|
636
|
+
panelBefore.currentValue.value = clampUnit(context, panelBefore, panelBefore.currentValue.value.add(leftoverSpace));
|
|
626
637
|
}
|
|
627
638
|
return { items: newItems };
|
|
628
639
|
}
|
|
@@ -643,7 +654,7 @@ function commitLayout(context) {
|
|
|
643
654
|
});
|
|
644
655
|
const staticWidth = getStaticWidth({ ...context, items: newItems });
|
|
645
656
|
newItems.forEach((item, index) => {
|
|
646
|
-
if (item.type !== "panel" || item.collapsed) {
|
|
657
|
+
if (item.type !== "panel" || item.collapsed || item.isStaticAtRest) {
|
|
647
658
|
return;
|
|
648
659
|
}
|
|
649
660
|
newItems[index] = {
|
|
@@ -713,19 +724,74 @@ function applyDeltaInBothDirections(context, newItems, itemIndex, delta) {
|
|
|
713
724
|
direction = direction === 1 ? -1 : 1;
|
|
714
725
|
}
|
|
715
726
|
}
|
|
727
|
+
/**
|
|
728
|
+
* A layout might overflow at small screen sizes.
|
|
729
|
+
* This function tries to fix that by:
|
|
730
|
+
*
|
|
731
|
+
* 1. It will try to collapse a panel if it can.
|
|
732
|
+
*/
|
|
733
|
+
function handleOverflow(context) {
|
|
734
|
+
// If we haven't measured yet we can't do anything
|
|
735
|
+
if (context.items.some((i) => isPanelData(i) && i.currentValue.value.eq(-1))) {
|
|
736
|
+
return context;
|
|
737
|
+
}
|
|
738
|
+
const groupSize = new Big(getGroupSize(context));
|
|
739
|
+
const nonStaticWidth = groupSize.sub(getStaticWidth(context).toNumber());
|
|
740
|
+
const pixelItems = context.items.map((i) => {
|
|
741
|
+
if (isPanelHandle(i))
|
|
742
|
+
return i.size.value;
|
|
743
|
+
if (i.collapsed)
|
|
744
|
+
return getUnitPixelValue(context, i.currentValue);
|
|
745
|
+
const pixel = (i.currentValue.type === "pixel" && i.currentValue.value) ||
|
|
746
|
+
i.currentValue.value.mul(nonStaticWidth);
|
|
747
|
+
return clampUnit(context, i, pixel);
|
|
748
|
+
});
|
|
749
|
+
const totalSize = pixelItems.reduce((acc, i) => acc.add(i), new Big(0));
|
|
750
|
+
const overflow = totalSize.abs().sub(groupSize);
|
|
751
|
+
if (overflow.eq(0) || groupSize.eq(0)) {
|
|
752
|
+
return context;
|
|
753
|
+
}
|
|
754
|
+
let newContext = { ...context, items: prepareItems(context) };
|
|
755
|
+
const collapsiblePanel = newContext.items.find((i) => Boolean(isPanelData(i) && i.collapsible));
|
|
756
|
+
if (collapsiblePanel) {
|
|
757
|
+
const collapsiblePanelIndex = newContext.items.findIndex((i) => i.id === collapsiblePanel.id);
|
|
758
|
+
const handleId = getHandleForPanelId(newContext, collapsiblePanel.id);
|
|
759
|
+
const sizeChange = collapsiblePanel.currentValue.value.sub(getUnitPixelValue(newContext, collapsiblePanel.collapsedSize));
|
|
760
|
+
// Try to collapse the panel
|
|
761
|
+
newContext = {
|
|
762
|
+
...newContext,
|
|
763
|
+
...iterativelyUpdateLayout({
|
|
764
|
+
handleId: handleId.item.id,
|
|
765
|
+
delta: sizeChange,
|
|
766
|
+
direction: (handleId.direction * -1),
|
|
767
|
+
context: {
|
|
768
|
+
...newContext,
|
|
769
|
+
// act like its the old size so the space is distributed correctly
|
|
770
|
+
size: { width: totalSize.toNumber(), height: totalSize.toNumber() },
|
|
771
|
+
},
|
|
772
|
+
}),
|
|
773
|
+
};
|
|
774
|
+
// Then remove all the overflow
|
|
775
|
+
applyDeltaInBothDirections(newContext, newContext.items, collapsiblePanelIndex, overflow.neg());
|
|
776
|
+
}
|
|
777
|
+
return { ...newContext, items: commitLayout(newContext) };
|
|
778
|
+
}
|
|
779
|
+
function getDeltaForEvent(context, event) {
|
|
780
|
+
const panel = getPanelWithId(context, event.panelId);
|
|
781
|
+
if (event.type === "expandPanel") {
|
|
782
|
+
return new Big(panel.sizeBeforeCollapse ?? getUnitPixelValue(context, panel.min)).minus(panel.currentValue.value);
|
|
783
|
+
}
|
|
784
|
+
const collapsedSize = getUnitPixelValue(context, panel.collapsedSize);
|
|
785
|
+
return panel.currentValue.value.minus(collapsedSize);
|
|
786
|
+
}
|
|
716
787
|
const animationActor = fromPromise(({ input: { send, context, event } }) => new Promise((resolve) => {
|
|
717
788
|
const panel = getPanelWithId(context, event.panelId);
|
|
718
789
|
const handle = getHandleForPanelId(context, event.panelId);
|
|
719
790
|
let direction = new Big(handle.direction);
|
|
720
|
-
|
|
721
|
-
if (event.type === "
|
|
722
|
-
fullDelta = new Big(panel.sizeBeforeCollapse ?? getUnitPixelValue(context, panel.min)).minus(panel.currentValue.value);
|
|
723
|
-
}
|
|
724
|
-
else {
|
|
725
|
-
const collapsedSize = getUnitPixelValue(context, panel.collapsedSize);
|
|
791
|
+
const fullDelta = getDeltaForEvent(context, event);
|
|
792
|
+
if (event.type === "collapsePanel") {
|
|
726
793
|
panel.sizeBeforeCollapse = panel.currentValue.value.toNumber();
|
|
727
794
|
direction = direction.mul(new Big(-1));
|
|
728
|
-
fullDelta = panel.currentValue.value.minus(collapsedSize);
|
|
729
795
|
}
|
|
730
796
|
const fps = 60;
|
|
731
797
|
const { duration, ease } = getCollapseAnimation(panel);
|
|
@@ -792,6 +858,8 @@ export const groupMachine = createMachine({
|
|
|
792
858
|
{ target: "togglingCollapse" },
|
|
793
859
|
],
|
|
794
860
|
expandPanel: [
|
|
861
|
+
// This will match if we can't expand and the expansion won't happen
|
|
862
|
+
{ guard: "cannotExpandPanel" },
|
|
795
863
|
{
|
|
796
864
|
actions: "notifyCollapseToggle",
|
|
797
865
|
guard: "shouldNotifyCollapseToggle",
|
|
@@ -864,6 +932,29 @@ export const groupMachine = createMachine({
|
|
|
864
932
|
const panel = getPanelWithId(context, event.panelId);
|
|
865
933
|
return panel.collapseIsControlled === true;
|
|
866
934
|
},
|
|
935
|
+
cannotExpandPanel: ({ context, event }) => {
|
|
936
|
+
isEvent(event, ["expandPanel"]);
|
|
937
|
+
const delta = getDeltaForEvent(context, event);
|
|
938
|
+
const handle = getHandleForPanelId(context, event.panelId);
|
|
939
|
+
const pixelItems = prepareItems(context);
|
|
940
|
+
let interimContext = { ...context, items: pixelItems };
|
|
941
|
+
interimContext = {
|
|
942
|
+
...interimContext,
|
|
943
|
+
...iterativelyUpdateLayout({
|
|
944
|
+
context: interimContext,
|
|
945
|
+
handleId: handle.item.id,
|
|
946
|
+
controlled: event.controlled,
|
|
947
|
+
delta: delta,
|
|
948
|
+
direction: handle.direction,
|
|
949
|
+
}),
|
|
950
|
+
};
|
|
951
|
+
const updatedPanel = interimContext.items.find((i) => i.id === event.panelId);
|
|
952
|
+
const totalSize = interimContext.items.reduce((acc, i) => acc.add(isPanelData(i) ? i.currentValue.value : i.size.value), new Big(0));
|
|
953
|
+
const didExpand = updatedPanel &&
|
|
954
|
+
isPanelData(updatedPanel) &&
|
|
955
|
+
!updatedPanel.currentValue.value.eq(updatedPanel.collapsedSize.value);
|
|
956
|
+
return totalSize.gt(getGroupSize(context)) || !didExpand;
|
|
957
|
+
},
|
|
867
958
|
},
|
|
868
959
|
actors: {
|
|
869
960
|
animation: animationActor,
|
|
@@ -903,11 +994,14 @@ export const groupMachine = createMachine({
|
|
|
903
994
|
return context.items;
|
|
904
995
|
},
|
|
905
996
|
}),
|
|
906
|
-
updateSize:
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
}
|
|
997
|
+
updateSize: enqueueActions(({ context, event, enqueue }) => {
|
|
998
|
+
isEvent(event, ["setSize"]);
|
|
999
|
+
if (event.handleOverflow) {
|
|
1000
|
+
enqueue.assign(handleOverflow({ ...context, size: event.size }));
|
|
1001
|
+
}
|
|
1002
|
+
else {
|
|
1003
|
+
enqueue.assign({ size: event.size });
|
|
1004
|
+
}
|
|
911
1005
|
}),
|
|
912
1006
|
recordActualItemSize: assign({
|
|
913
1007
|
items: ({ context, event }) => {
|
|
@@ -1049,9 +1143,12 @@ export const groupMachine = createMachine({
|
|
|
1049
1143
|
for (const item of context.items) {
|
|
1050
1144
|
if (isPanelData(item)) {
|
|
1051
1145
|
const pixel = clampUnit(context, item, getUnitPixelValue(context, item.currentValue));
|
|
1146
|
+
const groupSize = getGroupSize(context);
|
|
1052
1147
|
item.onResize?.current?.({
|
|
1053
1148
|
pixel: pixel.toNumber(),
|
|
1054
|
-
percentage:
|
|
1149
|
+
percentage: groupSize > 0
|
|
1150
|
+
? pixel.div(getGroupSize(context)).toNumber()
|
|
1151
|
+
: -1,
|
|
1055
1152
|
});
|
|
1056
1153
|
}
|
|
1057
1154
|
}
|