react-resizable-panels 0.0.56 → 0.0.58
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/CHANGELOG.md +11 -0
- package/dist/declarations/src/Panel.d.ts +7 -3
- package/dist/declarations/src/PanelGroup.d.ts +3 -1
- package/dist/declarations/src/PanelResizeHandle.d.ts +3 -1
- package/dist/declarations/src/types.d.ts +3 -0
- package/dist/react-resizable-panels.browser.cjs.js +186 -87
- package/dist/react-resizable-panels.browser.development.cjs.js +186 -87
- package/dist/react-resizable-panels.browser.development.esm.js +186 -87
- package/dist/react-resizable-panels.browser.esm.js +186 -87
- package/dist/react-resizable-panels.cjs.js +186 -87
- package/dist/react-resizable-panels.cjs.js.map +1 -1
- package/dist/react-resizable-panels.development.cjs.js +186 -87
- package/dist/react-resizable-panels.development.esm.js +186 -87
- package/dist/react-resizable-panels.development.node.cjs.js +175 -82
- package/dist/react-resizable-panels.development.node.esm.js +175 -82
- package/dist/react-resizable-panels.esm.js +186 -87
- package/dist/react-resizable-panels.esm.js.map +1 -1
- package/dist/react-resizable-panels.node.cjs.js +175 -82
- package/dist/react-resizable-panels.node.esm.js +175 -82
- package/package.json +3 -1
- package/src/Panel.ts +9 -3
- package/src/PanelGroup.ts +11 -5
- package/src/PanelResizeHandle.ts +17 -13
- package/src/types.ts +4 -0
- package/src/utils/adjustLayoutByDelta.test.ts +238 -8
- package/src/utils/adjustLayoutByDelta.ts +122 -72
- package/src/utils/computePercentagePanelConstraints.test.ts +27 -0
- package/src/utils/convertPixelConstraintsToPercentages.test.ts +47 -0
- package/src/utils/convertPixelConstraintsToPercentages.ts +17 -0
- package/src/utils/dom/getPanelGroupElement.ts +3 -1
- package/src/utils/resizePanel.test.ts +105 -0
- package/src/utils/resizePanel.ts +26 -1
- package/src/utils/validatePanelGroupLayout.test.ts +36 -6
|
@@ -82,7 +82,7 @@ describe("adjustLayoutByDelta", () => {
|
|
|
82
82
|
it("[1++,2]", () => {
|
|
83
83
|
expect(
|
|
84
84
|
adjustLayoutByDelta({
|
|
85
|
-
delta:
|
|
85
|
+
delta: 40,
|
|
86
86
|
groupSizePixels: 100,
|
|
87
87
|
layout: [50, 50],
|
|
88
88
|
panelConstraints: [
|
|
@@ -122,7 +122,7 @@ describe("adjustLayoutByDelta", () => {
|
|
|
122
122
|
});
|
|
123
123
|
|
|
124
124
|
// Edge case
|
|
125
|
-
//
|
|
125
|
+
// Keyboard interactions should always expand a collapsed panel
|
|
126
126
|
it("[1++,2]", () => {
|
|
127
127
|
expect(
|
|
128
128
|
adjustLayoutByDelta({
|
|
@@ -143,6 +143,27 @@ describe("adjustLayoutByDelta", () => {
|
|
|
143
143
|
).toEqual([25, 75]);
|
|
144
144
|
});
|
|
145
145
|
|
|
146
|
+
// Edge case
|
|
147
|
+
// Keyboard interactions should always collapse a collapsible panel once it's at the minimum size
|
|
148
|
+
it("[1++,2]", () => {
|
|
149
|
+
expect(
|
|
150
|
+
adjustLayoutByDelta({
|
|
151
|
+
delta: 5,
|
|
152
|
+
groupSizePixels: NaN,
|
|
153
|
+
layout: [75, 25],
|
|
154
|
+
panelConstraints: [
|
|
155
|
+
{},
|
|
156
|
+
{
|
|
157
|
+
collapsible: true,
|
|
158
|
+
minSizePercentage: 25,
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
pivotIndices: [0, 1],
|
|
162
|
+
trigger: "keyboard",
|
|
163
|
+
})
|
|
164
|
+
).toEqual([100, 0]);
|
|
165
|
+
});
|
|
166
|
+
|
|
146
167
|
// Edge case
|
|
147
168
|
// Expanding from a collapsed state to less than the min size via imperative API should do nothing
|
|
148
169
|
it("[1++,2]", () => {
|
|
@@ -174,6 +195,7 @@ describe("adjustLayoutByDelta", () => {
|
|
|
174
195
|
// Expanding from a collapsed state to less than the min size via keyboard should snap to min size
|
|
175
196
|
it("[1++,2]", () => {
|
|
176
197
|
// collapsed 4%, min size 6%, max size 15%
|
|
198
|
+
|
|
177
199
|
expect(
|
|
178
200
|
adjustLayoutByDelta({
|
|
179
201
|
delta: 1,
|
|
@@ -395,6 +417,24 @@ describe("adjustLayoutByDelta", () => {
|
|
|
395
417
|
pivotIndices: [0, 1],
|
|
396
418
|
trigger: "imperative-api",
|
|
397
419
|
})
|
|
420
|
+
).toEqual([25, 75]);
|
|
421
|
+
|
|
422
|
+
expect(
|
|
423
|
+
adjustLayoutByDelta({
|
|
424
|
+
delta: -36,
|
|
425
|
+
groupSizePixels: 100,
|
|
426
|
+
layout: [50, 50],
|
|
427
|
+
panelConstraints: [
|
|
428
|
+
{
|
|
429
|
+
collapsedSizePercentage: 5,
|
|
430
|
+
collapsible: true,
|
|
431
|
+
minSizePercentage: 25,
|
|
432
|
+
},
|
|
433
|
+
{},
|
|
434
|
+
],
|
|
435
|
+
pivotIndices: [0, 1],
|
|
436
|
+
trigger: "imperative-api",
|
|
437
|
+
})
|
|
398
438
|
).toEqual([5, 95]);
|
|
399
439
|
});
|
|
400
440
|
|
|
@@ -420,6 +460,50 @@ describe("adjustLayoutByDelta", () => {
|
|
|
420
460
|
).toEqual([25, 75]);
|
|
421
461
|
});
|
|
422
462
|
|
|
463
|
+
// Edge case
|
|
464
|
+
// Keyboard interactions should always expand a collapsed panel
|
|
465
|
+
it("[1--,2]", () => {
|
|
466
|
+
expect(
|
|
467
|
+
adjustLayoutByDelta({
|
|
468
|
+
delta: -5,
|
|
469
|
+
groupSizePixels: NaN,
|
|
470
|
+
layout: [90, 10],
|
|
471
|
+
panelConstraints: [
|
|
472
|
+
{},
|
|
473
|
+
{
|
|
474
|
+
collapsedSizePercentage: 10,
|
|
475
|
+
collapsible: true,
|
|
476
|
+
minSizePercentage: 25,
|
|
477
|
+
},
|
|
478
|
+
],
|
|
479
|
+
pivotIndices: [0, 1],
|
|
480
|
+
trigger: "keyboard",
|
|
481
|
+
})
|
|
482
|
+
).toEqual([75, 25]);
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
// Edge case
|
|
486
|
+
// Keyboard interactions should always collapse a collapsible panel once it's at the minimum size
|
|
487
|
+
it("[1++,2]", () => {
|
|
488
|
+
expect(
|
|
489
|
+
adjustLayoutByDelta({
|
|
490
|
+
delta: -5,
|
|
491
|
+
groupSizePixels: NaN,
|
|
492
|
+
layout: [25, 75],
|
|
493
|
+
panelConstraints: [
|
|
494
|
+
{
|
|
495
|
+
collapsedSizePercentage: 10,
|
|
496
|
+
collapsible: true,
|
|
497
|
+
minSizePercentage: 25,
|
|
498
|
+
},
|
|
499
|
+
{},
|
|
500
|
+
],
|
|
501
|
+
pivotIndices: [0, 1],
|
|
502
|
+
trigger: "keyboard",
|
|
503
|
+
})
|
|
504
|
+
).toEqual([10, 90]);
|
|
505
|
+
});
|
|
506
|
+
|
|
423
507
|
it("[1++,2,3]", () => {
|
|
424
508
|
expect(
|
|
425
509
|
adjustLayoutByDelta({
|
|
@@ -722,7 +806,7 @@ describe("adjustLayoutByDelta", () => {
|
|
|
722
806
|
pivotIndices: [0, 1],
|
|
723
807
|
trigger: "imperative-api",
|
|
724
808
|
})
|
|
725
|
-
).toEqual([
|
|
809
|
+
).toEqual([25, 50, 25]);
|
|
726
810
|
});
|
|
727
811
|
|
|
728
812
|
it("[1,2++,3]", () => {
|
|
@@ -834,6 +918,21 @@ describe("adjustLayoutByDelta", () => {
|
|
|
834
918
|
pivotIndices: [1, 2],
|
|
835
919
|
trigger: "imperative-api",
|
|
836
920
|
})
|
|
921
|
+
).toEqual([25, 55, 20]);
|
|
922
|
+
|
|
923
|
+
expect(
|
|
924
|
+
adjustLayoutByDelta({
|
|
925
|
+
delta: 16,
|
|
926
|
+
groupSizePixels: 100,
|
|
927
|
+
layout: [25, 50, 25],
|
|
928
|
+
panelConstraints: [
|
|
929
|
+
{},
|
|
930
|
+
{},
|
|
931
|
+
{ collapsible: true, minSizePercentage: 20 },
|
|
932
|
+
],
|
|
933
|
+
pivotIndices: [1, 2],
|
|
934
|
+
trigger: "imperative-api",
|
|
935
|
+
})
|
|
837
936
|
).toEqual([25, 75, 0]);
|
|
838
937
|
});
|
|
839
938
|
|
|
@@ -907,15 +1006,53 @@ describe("adjustLayoutByDelta", () => {
|
|
|
907
1006
|
pivotIndices: [1, 2],
|
|
908
1007
|
trigger: "imperative-api",
|
|
909
1008
|
})
|
|
1009
|
+
).toEqual([20, 20, 60]);
|
|
1010
|
+
|
|
1011
|
+
expect(
|
|
1012
|
+
adjustLayoutByDelta({
|
|
1013
|
+
delta: -40,
|
|
1014
|
+
groupSizePixels: 100,
|
|
1015
|
+
layout: [25, 50, 25],
|
|
1016
|
+
panelConstraints: [
|
|
1017
|
+
{},
|
|
1018
|
+
{
|
|
1019
|
+
collapsedSizePercentage: 5,
|
|
1020
|
+
collapsible: true,
|
|
1021
|
+
minSizePercentage: 20,
|
|
1022
|
+
},
|
|
1023
|
+
{},
|
|
1024
|
+
],
|
|
1025
|
+
pivotIndices: [1, 2],
|
|
1026
|
+
trigger: "imperative-api",
|
|
1027
|
+
})
|
|
910
1028
|
).toEqual([25, 5, 70]);
|
|
911
1029
|
});
|
|
912
1030
|
|
|
913
1031
|
it("[1,2--,3]", () => {
|
|
914
1032
|
expect(
|
|
915
1033
|
adjustLayoutByDelta({
|
|
916
|
-
delta: -
|
|
1034
|
+
delta: -10,
|
|
917
1035
|
groupSizePixels: 100,
|
|
918
|
-
layout: [25,
|
|
1036
|
+
layout: [25, 0, 75],
|
|
1037
|
+
panelConstraints: [
|
|
1038
|
+
{
|
|
1039
|
+
collapsedSizePercentage: 5,
|
|
1040
|
+
collapsible: true,
|
|
1041
|
+
minSizePercentage: 20,
|
|
1042
|
+
},
|
|
1043
|
+
{},
|
|
1044
|
+
{},
|
|
1045
|
+
],
|
|
1046
|
+
pivotIndices: [1, 2],
|
|
1047
|
+
trigger: "imperative-api",
|
|
1048
|
+
})
|
|
1049
|
+
).toEqual([20, 0, 80]);
|
|
1050
|
+
|
|
1051
|
+
expect(
|
|
1052
|
+
adjustLayoutByDelta({
|
|
1053
|
+
delta: -20,
|
|
1054
|
+
groupSizePixels: 100,
|
|
1055
|
+
layout: [25, 0, 75],
|
|
919
1056
|
panelConstraints: [
|
|
920
1057
|
{
|
|
921
1058
|
collapsedSizePercentage: 5,
|
|
@@ -1041,6 +1178,34 @@ describe("adjustLayoutByDelta", () => {
|
|
|
1041
1178
|
pivotIndices: [0, 1],
|
|
1042
1179
|
trigger: "imperative-api",
|
|
1043
1180
|
})
|
|
1181
|
+
).toEqual([35, 20, 20, 25]);
|
|
1182
|
+
|
|
1183
|
+
expect(
|
|
1184
|
+
adjustLayoutByDelta({
|
|
1185
|
+
delta: 15,
|
|
1186
|
+
groupSizePixels: 100,
|
|
1187
|
+
layout: [25, 25, 25, 25],
|
|
1188
|
+
panelConstraints: [
|
|
1189
|
+
{},
|
|
1190
|
+
{
|
|
1191
|
+
collapsedSizePercentage: 5,
|
|
1192
|
+
collapsible: true,
|
|
1193
|
+
minSizePercentage: 20,
|
|
1194
|
+
},
|
|
1195
|
+
{
|
|
1196
|
+
collapsedSizePercentage: 5,
|
|
1197
|
+
collapsible: true,
|
|
1198
|
+
minSizePercentage: 20,
|
|
1199
|
+
},
|
|
1200
|
+
{
|
|
1201
|
+
collapsedSizePercentage: 5,
|
|
1202
|
+
collapsible: true,
|
|
1203
|
+
minSizePercentage: 20,
|
|
1204
|
+
},
|
|
1205
|
+
],
|
|
1206
|
+
pivotIndices: [0, 1],
|
|
1207
|
+
trigger: "imperative-api",
|
|
1208
|
+
})
|
|
1044
1209
|
).toEqual([45, 5, 25, 25]);
|
|
1045
1210
|
});
|
|
1046
1211
|
|
|
@@ -1153,7 +1318,7 @@ describe("adjustLayoutByDelta", () => {
|
|
|
1153
1318
|
pivotIndices: [0, 1],
|
|
1154
1319
|
trigger: "imperative-api",
|
|
1155
1320
|
})
|
|
1156
|
-
).toEqual([
|
|
1321
|
+
).toEqual([0, 35, 40, 25]);
|
|
1157
1322
|
});
|
|
1158
1323
|
|
|
1159
1324
|
it("[1--,2,3,4]", () => {
|
|
@@ -1175,6 +1340,26 @@ describe("adjustLayoutByDelta", () => {
|
|
|
1175
1340
|
pivotIndices: [0, 1],
|
|
1176
1341
|
trigger: "imperative-api",
|
|
1177
1342
|
})
|
|
1343
|
+
).toEqual([20, 30, 25, 25]);
|
|
1344
|
+
|
|
1345
|
+
expect(
|
|
1346
|
+
adjustLayoutByDelta({
|
|
1347
|
+
delta: -15,
|
|
1348
|
+
groupSizePixels: 100,
|
|
1349
|
+
layout: [25, 25, 25, 25],
|
|
1350
|
+
panelConstraints: [
|
|
1351
|
+
{
|
|
1352
|
+
collapsedSizePercentage: 5,
|
|
1353
|
+
collapsible: true,
|
|
1354
|
+
minSizePercentage: 20,
|
|
1355
|
+
},
|
|
1356
|
+
{},
|
|
1357
|
+
{},
|
|
1358
|
+
{},
|
|
1359
|
+
],
|
|
1360
|
+
pivotIndices: [0, 1],
|
|
1361
|
+
trigger: "imperative-api",
|
|
1362
|
+
})
|
|
1178
1363
|
).toEqual([5, 45, 25, 25]);
|
|
1179
1364
|
});
|
|
1180
1365
|
|
|
@@ -1197,6 +1382,26 @@ describe("adjustLayoutByDelta", () => {
|
|
|
1197
1382
|
pivotIndices: [0, 1],
|
|
1198
1383
|
trigger: "imperative-api",
|
|
1199
1384
|
})
|
|
1385
|
+
).toEqual([20, 30, 25, 25]);
|
|
1386
|
+
|
|
1387
|
+
expect(
|
|
1388
|
+
adjustLayoutByDelta({
|
|
1389
|
+
delta: -15,
|
|
1390
|
+
groupSizePixels: 100,
|
|
1391
|
+
layout: [25, 25, 25, 25],
|
|
1392
|
+
panelConstraints: [
|
|
1393
|
+
{
|
|
1394
|
+
collapsedSizePercentage: 5,
|
|
1395
|
+
collapsible: true,
|
|
1396
|
+
minSizePercentage: 20,
|
|
1397
|
+
},
|
|
1398
|
+
{ maxSizePercentage: 35 },
|
|
1399
|
+
{},
|
|
1400
|
+
{},
|
|
1401
|
+
],
|
|
1402
|
+
pivotIndices: [0, 1],
|
|
1403
|
+
trigger: "imperative-api",
|
|
1404
|
+
})
|
|
1200
1405
|
).toEqual([5, 35, 35, 25]);
|
|
1201
1406
|
});
|
|
1202
1407
|
|
|
@@ -1256,7 +1461,9 @@ describe("adjustLayoutByDelta", () => {
|
|
|
1256
1461
|
).toEqual([20, 30, 25, 25]);
|
|
1257
1462
|
});
|
|
1258
1463
|
|
|
1464
|
+
// Edge case (issues/210)
|
|
1259
1465
|
it("[1--,2,3,4]", () => {
|
|
1466
|
+
// If the size doesn't drop below the halfway point, the panel should not collapse
|
|
1260
1467
|
expect(
|
|
1261
1468
|
adjustLayoutByDelta({
|
|
1262
1469
|
delta: -10,
|
|
@@ -1275,6 +1482,29 @@ describe("adjustLayoutByDelta", () => {
|
|
|
1275
1482
|
pivotIndices: [0, 1],
|
|
1276
1483
|
trigger: "imperative-api",
|
|
1277
1484
|
})
|
|
1485
|
+
).toEqual([20, 30, 25, 25]);
|
|
1486
|
+
|
|
1487
|
+
// If the size drops below the halfway point, the panel should collapse
|
|
1488
|
+
// In this case it needs to add sizes to multiple other panels in order to collapse
|
|
1489
|
+
// because the nearest neighbor panel's max size constraints won't allow it to expand to cover all of the difference
|
|
1490
|
+
expect(
|
|
1491
|
+
adjustLayoutByDelta({
|
|
1492
|
+
delta: -20,
|
|
1493
|
+
groupSizePixels: 100,
|
|
1494
|
+
layout: [25, 25, 25, 25],
|
|
1495
|
+
panelConstraints: [
|
|
1496
|
+
{
|
|
1497
|
+
collapsedSizePercentage: 5,
|
|
1498
|
+
collapsible: true,
|
|
1499
|
+
minSizePercentage: 20,
|
|
1500
|
+
},
|
|
1501
|
+
{ maxSizePercentage: 35 },
|
|
1502
|
+
{ maxSizePercentage: 35 },
|
|
1503
|
+
{ maxSizePercentage: 35 },
|
|
1504
|
+
],
|
|
1505
|
+
pivotIndices: [0, 1],
|
|
1506
|
+
trigger: "imperative-api",
|
|
1507
|
+
})
|
|
1278
1508
|
).toEqual([5, 35, 35, 25]);
|
|
1279
1509
|
});
|
|
1280
1510
|
|
|
@@ -1327,7 +1557,7 @@ describe("adjustLayoutByDelta", () => {
|
|
|
1327
1557
|
pivotIndices: [1, 2],
|
|
1328
1558
|
trigger: "imperative-api",
|
|
1329
1559
|
})
|
|
1330
|
-
).toEqual([
|
|
1560
|
+
).toEqual([65, 35, 0, 0]);
|
|
1331
1561
|
});
|
|
1332
1562
|
|
|
1333
1563
|
it("[1,2++,3,4]", () => {
|
|
@@ -1581,7 +1811,7 @@ describe("adjustLayoutByDelta", () => {
|
|
|
1581
1811
|
pivotIndices: [2, 3],
|
|
1582
1812
|
trigger: "imperative-api",
|
|
1583
1813
|
})
|
|
1584
|
-
).toEqual([25,
|
|
1814
|
+
).toEqual([25, 35, 40, 0]);
|
|
1585
1815
|
});
|
|
1586
1816
|
|
|
1587
1817
|
it("[1,2,3++,4]", () => {
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
+
import { PanelConstraints } from "../Panel";
|
|
1
2
|
import { computePercentagePanelConstraints } from "./computePercentagePanelConstraints";
|
|
3
|
+
import { fuzzyCompareNumbers } from "./numbers/fuzzyCompareNumbers";
|
|
2
4
|
import { fuzzyNumbersEqual } from "./numbers/fuzzyNumbersEqual";
|
|
3
5
|
import { resizePanel } from "./resizePanel";
|
|
4
|
-
import { PanelConstraints } from "../Panel";
|
|
5
|
-
|
|
6
|
-
let isCheckingForInfiniteLoop = false;
|
|
7
6
|
|
|
8
7
|
// All units must be in percentages; pixel values should be pre-converted
|
|
9
8
|
export function adjustLayoutByDelta({
|
|
@@ -29,59 +28,124 @@ export function adjustLayoutByDelta({
|
|
|
29
28
|
|
|
30
29
|
let deltaApplied = 0;
|
|
31
30
|
|
|
31
|
+
//const DEBUG = [];
|
|
32
|
+
//DEBUG.push(`adjustLayoutByDelta() ${prevLayout.join(", ")}`);
|
|
33
|
+
//DEBUG.push(` delta: ${delta}`);
|
|
34
|
+
//DEBUG.push(` pivotIndices: ${pivotIndices.join(", ")}`);
|
|
35
|
+
//DEBUG.push(` trigger: ${trigger}`);
|
|
36
|
+
//DEBUG.push("");
|
|
37
|
+
|
|
32
38
|
// A resizing panel affects the panels before or after it.
|
|
33
39
|
//
|
|
34
|
-
// A negative delta means the panel immediately after the
|
|
40
|
+
// A negative delta means the panel(s) immediately after the resize handle should grow/expand by decreasing its offset.
|
|
35
41
|
// Other panels may also need to shrink/contract (and shift) to make room, depending on the min weights.
|
|
36
42
|
//
|
|
37
|
-
// A positive delta means the panel immediately before the
|
|
38
|
-
// This is accomplished by shrinking/contracting (and shifting) one or more of the panels after the
|
|
43
|
+
// A positive delta means the panel(s) immediately before the resize handle should "expand".
|
|
44
|
+
// This is accomplished by shrinking/contracting (and shifting) one or more of the panels after the resize handle.
|
|
39
45
|
|
|
40
|
-
// First, check the panel we're pivoting around;
|
|
41
|
-
// We should only expand or contract by as much as its constraints allow
|
|
42
46
|
{
|
|
43
|
-
|
|
44
|
-
|
|
47
|
+
// If this is a resize triggered by a keyboard event, our logic for expanding/collapsing is different.
|
|
48
|
+
// We no longer check the halfway threshold because this may prevent the panel from expanding at all.
|
|
49
|
+
if (trigger === "keyboard") {
|
|
50
|
+
{
|
|
51
|
+
// Check if we should expand a collapsed panel
|
|
52
|
+
const index = delta < 0 ? pivotIndices[1]! : pivotIndices[0]!;
|
|
53
|
+
const constraints = panelConstraints[index]!;
|
|
54
|
+
//DEBUG.push(`edge case check 1: ${index}`);
|
|
55
|
+
//DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
|
|
56
|
+
if (constraints.collapsible) {
|
|
57
|
+
const prevSize = prevLayout[index]!;
|
|
58
|
+
const { collapsedSizePercentage, minSizePercentage } =
|
|
59
|
+
computePercentagePanelConstraints(
|
|
60
|
+
panelConstraints,
|
|
61
|
+
index,
|
|
62
|
+
groupSizePixels
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
if (fuzzyNumbersEqual(prevSize, collapsedSizePercentage)) {
|
|
66
|
+
const localDelta = minSizePercentage - prevSize;
|
|
67
|
+
//DEBUG.push(` -> expand delta: ${localDelta}`);
|
|
68
|
+
|
|
69
|
+
if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
|
|
70
|
+
delta = delta < 0 ? 0 - localDelta : localDelta;
|
|
71
|
+
//DEBUG.push(` -> delta: ${delta}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
45
76
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
panelConstraints
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (minSizePercentage
|
|
62
|
-
|
|
77
|
+
{
|
|
78
|
+
// Check if we should collapse a panel at its minimum size
|
|
79
|
+
const index = delta < 0 ? pivotIndices[0]! : pivotIndices[1]!;
|
|
80
|
+
const constraints = panelConstraints[index]!;
|
|
81
|
+
//DEBUG.push(`edge case check 2: ${index}`);
|
|
82
|
+
//DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
|
|
83
|
+
if (constraints.collapsible) {
|
|
84
|
+
const prevSize = prevLayout[index]!;
|
|
85
|
+
const { collapsedSizePercentage, minSizePercentage } =
|
|
86
|
+
computePercentagePanelConstraints(
|
|
87
|
+
panelConstraints,
|
|
88
|
+
index,
|
|
89
|
+
groupSizePixels
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
if (fuzzyNumbersEqual(prevSize, minSizePercentage)) {
|
|
93
|
+
const localDelta = prevSize - collapsedSizePercentage;
|
|
94
|
+
//DEBUG.push(` -> expand delta: ${localDelta}`);
|
|
95
|
+
|
|
96
|
+
if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
|
|
97
|
+
delta = delta < 0 ? 0 - localDelta : localDelta;
|
|
98
|
+
//DEBUG.push(` -> delta: ${delta}`);
|
|
99
|
+
}
|
|
63
100
|
}
|
|
101
|
+
}
|
|
64
102
|
}
|
|
65
103
|
}
|
|
104
|
+
//DEBUG.push("");
|
|
105
|
+
}
|
|
66
106
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
107
|
+
{
|
|
108
|
+
// Pre-calculate max available delta in the opposite direction of our pivot.
|
|
109
|
+
// This will be the maximum amount we're allowed to expand/contract the panels in the primary direction.
|
|
110
|
+
// If this amount is less than the requested delta, adjust the requested delta.
|
|
111
|
+
// If this amount is greater than the requested delta, that's useful information too–
|
|
112
|
+
// as an expanding panel might change from collapsed to min size.
|
|
113
|
+
|
|
114
|
+
const increment = delta < 0 ? 1 : -1;
|
|
115
|
+
|
|
116
|
+
let index = delta < 0 ? pivotIndices[1]! : pivotIndices[0]!;
|
|
117
|
+
let maxAvailableDelta = 0;
|
|
73
118
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
119
|
+
//DEBUG.push("pre calc...");
|
|
120
|
+
while (true) {
|
|
121
|
+
const prevSize = prevLayout[index];
|
|
122
|
+
const maxSafeSize = resizePanel({
|
|
123
|
+
groupSizePixels,
|
|
124
|
+
panelConstraints,
|
|
125
|
+
panelIndex: index,
|
|
126
|
+
size: 100,
|
|
127
|
+
});
|
|
128
|
+
const delta = maxSafeSize - prevSize;
|
|
129
|
+
//DEBUG.push(` ${index}: ${prevSize} -> ${maxSafeSize}`);
|
|
130
|
+
|
|
131
|
+
maxAvailableDelta += delta;
|
|
132
|
+
index += increment;
|
|
133
|
+
|
|
134
|
+
if (index < 0 || index >= panelConstraints.length) {
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
79
137
|
}
|
|
138
|
+
|
|
139
|
+
//DEBUG.push(` -> max available delta: ${maxAvailableDelta}`);
|
|
140
|
+
const minAbsDelta = Math.min(Math.abs(delta), Math.abs(maxAvailableDelta));
|
|
141
|
+
delta = delta < 0 ? 0 - minAbsDelta : minAbsDelta;
|
|
142
|
+
//DEBUG.push(` -> adjusted delta: ${delta}`);
|
|
143
|
+
//DEBUG.push("");
|
|
80
144
|
}
|
|
81
145
|
|
|
82
|
-
// Delta added to a panel needs to be subtracted from other panels
|
|
83
|
-
// within the constraints that those panels allow
|
|
84
146
|
{
|
|
147
|
+
// Delta added to a panel needs to be subtracted from other panels (within the constraints that those panels allow).
|
|
148
|
+
|
|
85
149
|
const pivotIndex = delta < 0 ? pivotIndices[0]! : pivotIndices[1]!;
|
|
86
150
|
let index = pivotIndex;
|
|
87
151
|
while (index >= 0 && index < panelConstraints.length) {
|
|
@@ -89,8 +153,7 @@ export function adjustLayoutByDelta({
|
|
|
89
153
|
|
|
90
154
|
const prevSize = prevLayout[index]!;
|
|
91
155
|
const unsafeSize = prevSize - deltaRemaining;
|
|
92
|
-
|
|
93
|
-
let safeSize = resizePanel({
|
|
156
|
+
const safeSize = resizePanel({
|
|
94
157
|
groupSizePixels,
|
|
95
158
|
panelConstraints,
|
|
96
159
|
panelIndex: index,
|
|
@@ -120,14 +183,19 @@ export function adjustLayoutByDelta({
|
|
|
120
183
|
}
|
|
121
184
|
}
|
|
122
185
|
}
|
|
186
|
+
//DEBUG.push(`after 1: ${nextLayout.join(", ")}`);
|
|
187
|
+
//DEBUG.push(` deltaApplied: ${deltaApplied}`);
|
|
188
|
+
//DEBUG.push("");
|
|
123
189
|
|
|
124
190
|
// If we were unable to resize any of the panels panels, return the previous state.
|
|
125
191
|
// This will essentially bailout and ignore e.g. drags past a panel's boundaries
|
|
126
192
|
if (fuzzyNumbersEqual(deltaApplied, 0)) {
|
|
193
|
+
//console.log(DEBUG.join("\n"));
|
|
127
194
|
return prevLayout;
|
|
128
195
|
}
|
|
129
196
|
|
|
130
197
|
{
|
|
198
|
+
// Now distribute the applied delta to the panels in the other direction
|
|
131
199
|
const pivotIndex = delta < 0 ? pivotIndices[1]! : pivotIndices[0]!;
|
|
132
200
|
|
|
133
201
|
const unsafeSize = prevLayout[pivotIndex]! + deltaApplied;
|
|
@@ -173,38 +241,20 @@ export function adjustLayoutByDelta({
|
|
|
173
241
|
index++;
|
|
174
242
|
}
|
|
175
243
|
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
//DEBUG.push(`after 2: ${nextLayout.join(", ")}`);
|
|
247
|
+
//DEBUG.push(` deltaApplied: ${deltaApplied}`);
|
|
248
|
+
//DEBUG.push("");
|
|
176
249
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
didSetInfiniteLoopCheckCounter = true;
|
|
183
|
-
isCheckingForInfiniteLoop = true;
|
|
184
|
-
}
|
|
250
|
+
const totalSize = nextLayout.reduce((total, size) => size + total, 0);
|
|
251
|
+
deltaApplied = 100 - totalSize;
|
|
252
|
+
//DEBUG.push(`total size: ${totalSize}`);
|
|
253
|
+
//DEBUG.push(` deltaApplied: ${deltaApplied}`);
|
|
254
|
+
//console.log(DEBUG.join("\n"));
|
|
185
255
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
delta: delta < 0 ? delta + 1 : delta - 1,
|
|
189
|
-
groupSizePixels,
|
|
190
|
-
layout: prevLayout,
|
|
191
|
-
panelConstraints,
|
|
192
|
-
pivotIndices,
|
|
193
|
-
trigger,
|
|
194
|
-
});
|
|
195
|
-
} catch (error) {
|
|
196
|
-
if (error instanceof RangeError) {
|
|
197
|
-
console.error(`Could not apply delta ${delta} to layout`);
|
|
198
|
-
|
|
199
|
-
return prevLayout;
|
|
200
|
-
}
|
|
201
|
-
} finally {
|
|
202
|
-
if (didSetInfiniteLoopCheckCounter) {
|
|
203
|
-
isCheckingForInfiniteLoop = false;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
256
|
+
if (!fuzzyNumbersEqual(totalSize, 100)) {
|
|
257
|
+
return prevLayout;
|
|
208
258
|
}
|
|
209
259
|
|
|
210
260
|
return nextLayout;
|
|
@@ -68,4 +68,31 @@ describe("computePercentagePanelConstraints", () => {
|
|
|
68
68
|
}
|
|
69
69
|
`);
|
|
70
70
|
});
|
|
71
|
+
|
|
72
|
+
it("should compute reasonable percentage based constraints from pixels if group size is negative", () => {
|
|
73
|
+
jest.spyOn(console, "warn").mockImplementation(() => {});
|
|
74
|
+
|
|
75
|
+
expect(
|
|
76
|
+
computePercentagePanelConstraints(
|
|
77
|
+
[
|
|
78
|
+
{
|
|
79
|
+
minSizePixels: 25,
|
|
80
|
+
maxSizePixels: 100,
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
|
|
84
|
+
0,
|
|
85
|
+
-100
|
|
86
|
+
)
|
|
87
|
+
).toMatchInlineSnapshot(`
|
|
88
|
+
{
|
|
89
|
+
"collapsedSizePercentage": 0,
|
|
90
|
+
"defaultSizePercentage": undefined,
|
|
91
|
+
"maxSizePercentage": 0,
|
|
92
|
+
"minSizePercentage": 0,
|
|
93
|
+
}
|
|
94
|
+
`);
|
|
95
|
+
|
|
96
|
+
expect(console.warn).toHaveBeenCalledTimes(1);
|
|
97
|
+
});
|
|
71
98
|
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { convertPixelConstraintsToPercentages } from "./convertPixelConstraintsToPercentages";
|
|
2
|
+
|
|
3
|
+
describe("convertPixelConstraintsToPercentages", () => {
|
|
4
|
+
it("should respect percentage panel constraints if group size is negative", () => {
|
|
5
|
+
jest.spyOn(console, "warn").mockImplementation(() => {});
|
|
6
|
+
|
|
7
|
+
expect(
|
|
8
|
+
convertPixelConstraintsToPercentages(
|
|
9
|
+
{
|
|
10
|
+
minSizePercentage: 25,
|
|
11
|
+
defaultSizePercentage: 50,
|
|
12
|
+
maxSizePercentage: 75,
|
|
13
|
+
},
|
|
14
|
+
-100
|
|
15
|
+
)
|
|
16
|
+
).toEqual({
|
|
17
|
+
collapsedSizePercentage: 0,
|
|
18
|
+
defaultSizePercentage: 50,
|
|
19
|
+
maxSizePercentage: 75,
|
|
20
|
+
minSizePercentage: 25,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
expect(console.warn).toHaveBeenCalledTimes(0);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// Edge case test (issues/206)
|
|
27
|
+
it("should ignore pixel panel constraints if group size is negative", () => {
|
|
28
|
+
jest.spyOn(console, "warn").mockImplementation(() => {});
|
|
29
|
+
|
|
30
|
+
expect(
|
|
31
|
+
convertPixelConstraintsToPercentages(
|
|
32
|
+
{
|
|
33
|
+
minSizePixels: 25,
|
|
34
|
+
maxSizePixels: 75,
|
|
35
|
+
},
|
|
36
|
+
-100
|
|
37
|
+
)
|
|
38
|
+
).toEqual({
|
|
39
|
+
collapsedSizePercentage: 0,
|
|
40
|
+
defaultSizePercentage: undefined,
|
|
41
|
+
maxSizePercentage: 0,
|
|
42
|
+
minSizePercentage: 0,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
expect(console.warn).toHaveBeenCalledTimes(1);
|
|
46
|
+
});
|
|
47
|
+
});
|