react-resizable-panels 2.1.6 → 2.1.8
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/README.md +4 -0
- package/dist/declarations/src/Panel.d.ts +1 -1
- package/dist/declarations/src/PanelGroup.d.ts +1 -1
- package/dist/declarations/src/PanelResizeHandle.d.ts +6 -3
- package/dist/react-resizable-panels.browser.cjs.js +90 -94
- package/dist/react-resizable-panels.browser.development.cjs.js +90 -94
- package/dist/react-resizable-panels.browser.development.esm.js +38 -41
- package/dist/react-resizable-panels.browser.esm.js +38 -41
- package/dist/react-resizable-panels.cjs.js +90 -94
- package/dist/react-resizable-panels.development.cjs.js +90 -94
- package/dist/react-resizable-panels.development.esm.js +38 -41
- package/dist/react-resizable-panels.development.node.cjs.js +89 -92
- package/dist/react-resizable-panels.development.node.esm.js +37 -39
- package/dist/react-resizable-panels.esm.js +38 -41
- package/dist/react-resizable-panels.node.cjs.js +89 -92
- package/dist/react-resizable-panels.node.esm.js +37 -39
- package/package.json +7 -2
- package/.eslintrc.cjs +0 -27
- package/CHANGELOG.md +0 -574
- package/dist/declarations/src/vendor/react.d.ts +0 -7
- package/jest.config.js +0 -10
- package/src/Panel.test.tsx +0 -1084
- package/src/Panel.ts +0 -259
- package/src/PanelGroup.test.tsx +0 -443
- package/src/PanelGroup.ts +0 -999
- package/src/PanelGroupContext.ts +0 -42
- package/src/PanelResizeHandle.test.tsx +0 -367
- package/src/PanelResizeHandle.ts +0 -246
- package/src/PanelResizeHandleRegistry.ts +0 -336
- package/src/constants.ts +0 -1
- package/src/env-conditions/browser.ts +0 -1
- package/src/env-conditions/development.ts +0 -1
- package/src/env-conditions/node.ts +0 -1
- package/src/env-conditions/production.ts +0 -1
- package/src/env-conditions/unknown.ts +0 -1
- package/src/hooks/useForceUpdate.ts +0 -7
- package/src/hooks/useIsomorphicEffect.ts +0 -8
- package/src/hooks/useUniqueId.ts +0 -19
- package/src/hooks/useWindowSplitterBehavior.ts +0 -90
- package/src/hooks/useWindowSplitterPanelGroupBehavior.ts +0 -201
- package/src/index.ts +0 -77
- package/src/types.ts +0 -5
- package/src/utils/adjustLayoutByDelta.test.ts +0 -2061
- package/src/utils/adjustLayoutByDelta.ts +0 -308
- package/src/utils/arrays.ts +0 -13
- package/src/utils/assert.ts +0 -10
- package/src/utils/calculateAriaValues.test.ts +0 -106
- package/src/utils/calculateAriaValues.ts +0 -45
- package/src/utils/calculateDeltaPercentage.ts +0 -63
- package/src/utils/calculateDragOffsetPercentage.ts +0 -40
- package/src/utils/calculateUnsafeDefaultLayout.test.ts +0 -87
- package/src/utils/calculateUnsafeDefaultLayout.ts +0 -50
- package/src/utils/callPanelCallbacks.ts +0 -49
- package/src/utils/compareLayouts.test.ts +0 -9
- package/src/utils/compareLayouts.ts +0 -12
- package/src/utils/computePanelFlexBoxStyle.test.ts +0 -123
- package/src/utils/computePanelFlexBoxStyle.ts +0 -50
- package/src/utils/csp.ts +0 -9
- package/src/utils/cursor.ts +0 -103
- package/src/utils/debounce.ts +0 -18
- package/src/utils/determinePivotIndices.ts +0 -15
- package/src/utils/dom/getPanelElement.ts +0 -10
- package/src/utils/dom/getPanelElementsForGroup.ts +0 -8
- package/src/utils/dom/getPanelGroupElement.ts +0 -21
- package/src/utils/dom/getResizeHandleElement.ts +0 -10
- package/src/utils/dom/getResizeHandleElementIndex.ts +0 -13
- package/src/utils/dom/getResizeHandleElementsForGroup.ts +0 -10
- package/src/utils/dom/getResizeHandlePanelIds.ts +0 -19
- package/src/utils/events/getResizeEventCoordinates.ts +0 -23
- package/src/utils/events/getResizeEventCursorPosition.ts +0 -14
- package/src/utils/events/index.ts +0 -13
- package/src/utils/getInputType.ts +0 -5
- package/src/utils/initializeDefaultStorage.ts +0 -26
- package/src/utils/numbers/fuzzyCompareNumbers.test.ts +0 -16
- package/src/utils/numbers/fuzzyCompareNumbers.ts +0 -21
- package/src/utils/numbers/fuzzyLayoutsEqual.ts +0 -22
- package/src/utils/numbers/fuzzyNumbersEqual.ts +0 -9
- package/src/utils/rects/getIntersectingRectangle.test.ts +0 -198
- package/src/utils/rects/getIntersectingRectangle.ts +0 -28
- package/src/utils/rects/intersects.test.ts +0 -197
- package/src/utils/rects/intersects.ts +0 -23
- package/src/utils/rects/types.ts +0 -6
- package/src/utils/resizePanel.test.ts +0 -59
- package/src/utils/resizePanel.ts +0 -47
- package/src/utils/serialization.ts +0 -87
- package/src/utils/test-utils.ts +0 -205
- package/src/utils/validatePanelConstraints.test.ts +0 -143
- package/src/utils/validatePanelConstraints.ts +0 -69
- package/src/utils/validatePanelGroupLayout.test.ts +0 -148
- package/src/utils/validatePanelGroupLayout.ts +0 -95
- package/src/vendor/react.ts +0 -73
- package/src/vendor/stacking-order.ts +0 -139
package/src/utils/test-utils.ts
DELETED
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
import { assert } from "./assert";
|
|
2
|
-
|
|
3
|
-
const util = require("util");
|
|
4
|
-
|
|
5
|
-
export function dispatchPointerEvent(type: string, target: HTMLElement) {
|
|
6
|
-
const rect = target.getBoundingClientRect();
|
|
7
|
-
|
|
8
|
-
const clientX = rect.left + rect.width / 2;
|
|
9
|
-
const clientY = rect.top + rect.height / 2;
|
|
10
|
-
|
|
11
|
-
const event = new MouseEvent(type, {
|
|
12
|
-
bubbles: true,
|
|
13
|
-
clientX,
|
|
14
|
-
clientY,
|
|
15
|
-
buttons: 1,
|
|
16
|
-
});
|
|
17
|
-
Object.defineProperties(event, {
|
|
18
|
-
pageX: {
|
|
19
|
-
get() {
|
|
20
|
-
return clientX;
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
pageY: {
|
|
24
|
-
get() {
|
|
25
|
-
return clientY;
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
isPrimary: {
|
|
29
|
-
value: true,
|
|
30
|
-
},
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
target.dispatchEvent(event);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function expectToBeCloseToArray(
|
|
37
|
-
actualNumbers: number[],
|
|
38
|
-
expectedNumbers: number[]
|
|
39
|
-
) {
|
|
40
|
-
expect(actualNumbers.length).toBe(expectedNumbers.length);
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
actualNumbers.forEach((actualNumber, index) => {
|
|
44
|
-
const expectedNumber = expectedNumbers[index];
|
|
45
|
-
assert(expectedNumber != null, `Expected number not found`);
|
|
46
|
-
|
|
47
|
-
expect(actualNumber).toBeCloseTo(expectedNumber, 1);
|
|
48
|
-
});
|
|
49
|
-
} catch (error) {
|
|
50
|
-
expect(actualNumbers).toEqual(expectedNumbers);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function mockBoundingClientRect(
|
|
55
|
-
element: HTMLElement,
|
|
56
|
-
rect: {
|
|
57
|
-
height: number;
|
|
58
|
-
width: number;
|
|
59
|
-
x: number;
|
|
60
|
-
y: number;
|
|
61
|
-
}
|
|
62
|
-
) {
|
|
63
|
-
const { height, width, x, y } = rect;
|
|
64
|
-
|
|
65
|
-
Object.defineProperty(element, "getBoundingClientRect", {
|
|
66
|
-
configurable: true,
|
|
67
|
-
value: () =>
|
|
68
|
-
({
|
|
69
|
-
bottom: y + height,
|
|
70
|
-
height,
|
|
71
|
-
left: x,
|
|
72
|
-
right: x + width,
|
|
73
|
-
toJSON() {
|
|
74
|
-
return "";
|
|
75
|
-
},
|
|
76
|
-
top: y,
|
|
77
|
-
width,
|
|
78
|
-
x,
|
|
79
|
-
y,
|
|
80
|
-
}) satisfies DOMRect,
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export function mockPanelGroupOffsetWidthAndHeight(
|
|
85
|
-
mockWidth = 1_000,
|
|
86
|
-
mockHeight = 1_000
|
|
87
|
-
) {
|
|
88
|
-
const offsetHeightPropertyDescriptor = Object.getOwnPropertyDescriptor(
|
|
89
|
-
HTMLElement.prototype,
|
|
90
|
-
"offsetHeight"
|
|
91
|
-
);
|
|
92
|
-
|
|
93
|
-
const offsetWidthPropertyDescriptor = Object.getOwnPropertyDescriptor(
|
|
94
|
-
HTMLElement.prototype,
|
|
95
|
-
"offsetWidth"
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
Object.defineProperty(HTMLElement.prototype, "offsetHeight", {
|
|
99
|
-
configurable: true,
|
|
100
|
-
get: function () {
|
|
101
|
-
if (this.hasAttribute("data-resize-handle")) {
|
|
102
|
-
return 0;
|
|
103
|
-
} else if (this.hasAttribute("data-panel-group")) {
|
|
104
|
-
return mockHeight;
|
|
105
|
-
}
|
|
106
|
-
},
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
Object.defineProperty(HTMLElement.prototype, "offsetWidth", {
|
|
110
|
-
configurable: true,
|
|
111
|
-
get: function () {
|
|
112
|
-
if (this.hasAttribute("data-resize-handle")) {
|
|
113
|
-
return 0;
|
|
114
|
-
} else if (this.hasAttribute("data-panel-group")) {
|
|
115
|
-
return mockWidth;
|
|
116
|
-
}
|
|
117
|
-
},
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
return function uninstallMocks() {
|
|
121
|
-
if (offsetHeightPropertyDescriptor) {
|
|
122
|
-
Object.defineProperty(
|
|
123
|
-
HTMLElement.prototype,
|
|
124
|
-
"offsetHeight",
|
|
125
|
-
offsetHeightPropertyDescriptor
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
if (offsetWidthPropertyDescriptor) {
|
|
130
|
-
Object.defineProperty(
|
|
131
|
-
HTMLElement.prototype,
|
|
132
|
-
"offsetWidth",
|
|
133
|
-
offsetWidthPropertyDescriptor
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
export function verifyAttribute(
|
|
140
|
-
element: HTMLElement,
|
|
141
|
-
attributeName: string,
|
|
142
|
-
expectedValue: string | null
|
|
143
|
-
) {
|
|
144
|
-
const actualValue = element.getAttribute(attributeName);
|
|
145
|
-
expect(actualValue).toBe(expectedValue);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export function verifyExpandedPanelGroupLayout(
|
|
149
|
-
actualLayout: number[],
|
|
150
|
-
expectedLayout: number[]
|
|
151
|
-
) {
|
|
152
|
-
expect(actualLayout).toEqual(expectedLayout);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
export function verifyExpectedWarnings(
|
|
156
|
-
callback: Function,
|
|
157
|
-
...expectedMessages: string[]
|
|
158
|
-
) {
|
|
159
|
-
const consoleSpy = (format: any, ...args: any[]) => {
|
|
160
|
-
const message = util.format(format, ...args);
|
|
161
|
-
|
|
162
|
-
for (let index = 0; index < expectedMessages.length; index++) {
|
|
163
|
-
const expectedMessage = expectedMessages[index];
|
|
164
|
-
if (message.includes(expectedMessage)) {
|
|
165
|
-
expectedMessages.splice(index, 1);
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (expectedMessages.length === 0) {
|
|
171
|
-
throw new Error(`Unexpected message recorded:\n\n${message}`);
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
const originalError = console.error;
|
|
176
|
-
const originalWarn = console.warn;
|
|
177
|
-
|
|
178
|
-
console.error = consoleSpy;
|
|
179
|
-
console.warn = consoleSpy;
|
|
180
|
-
|
|
181
|
-
let caughtError;
|
|
182
|
-
let didCatch = false;
|
|
183
|
-
try {
|
|
184
|
-
callback();
|
|
185
|
-
} catch (error) {
|
|
186
|
-
caughtError = error;
|
|
187
|
-
didCatch = true;
|
|
188
|
-
} finally {
|
|
189
|
-
console.error = originalError;
|
|
190
|
-
console.warn = originalWarn;
|
|
191
|
-
|
|
192
|
-
if (didCatch) {
|
|
193
|
-
throw caughtError;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// Any remaining messages indicate a failed expectations.
|
|
197
|
-
if (expectedMessages.length > 0) {
|
|
198
|
-
throw Error(
|
|
199
|
-
`Expected message(s) not recorded:\n\n${expectedMessages.join("\n")}`
|
|
200
|
-
);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
return { pass: true };
|
|
204
|
-
}
|
|
205
|
-
}
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import { verifyExpectedWarnings } from "./test-utils";
|
|
2
|
-
import { validatePanelConstraints } from "./validatePanelConstraints";
|
|
3
|
-
|
|
4
|
-
describe("validatePanelConstraints", () => {
|
|
5
|
-
it("should not warn if there are no validation errors", () => {
|
|
6
|
-
verifyExpectedWarnings(() => {
|
|
7
|
-
validatePanelConstraints({
|
|
8
|
-
panelConstraints: [{}],
|
|
9
|
-
panelIndex: 0,
|
|
10
|
-
panelId: "test",
|
|
11
|
-
});
|
|
12
|
-
});
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it("should warn about conflicting min/max sizes", () => {
|
|
16
|
-
verifyExpectedWarnings(() => {
|
|
17
|
-
validatePanelConstraints({
|
|
18
|
-
panelConstraints: [
|
|
19
|
-
{
|
|
20
|
-
maxSize: 5,
|
|
21
|
-
minSize: 10,
|
|
22
|
-
},
|
|
23
|
-
],
|
|
24
|
-
panelIndex: 0,
|
|
25
|
-
panelId: "test",
|
|
26
|
-
});
|
|
27
|
-
}, "min size (10%) should not be greater than max size (5%)");
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it("should warn about conflicting collapsed and min sizes", () => {
|
|
31
|
-
verifyExpectedWarnings(() => {
|
|
32
|
-
validatePanelConstraints({
|
|
33
|
-
panelConstraints: [
|
|
34
|
-
{
|
|
35
|
-
collapsedSize: 15,
|
|
36
|
-
minSize: 10,
|
|
37
|
-
},
|
|
38
|
-
],
|
|
39
|
-
panelIndex: 0,
|
|
40
|
-
panelId: "test",
|
|
41
|
-
});
|
|
42
|
-
}, "collapsed size should not be greater than min size");
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it("should warn about conflicting default and min/max sizes", () => {
|
|
46
|
-
verifyExpectedWarnings(() => {
|
|
47
|
-
validatePanelConstraints({
|
|
48
|
-
panelConstraints: [
|
|
49
|
-
{
|
|
50
|
-
defaultSize: -1,
|
|
51
|
-
minSize: 10,
|
|
52
|
-
},
|
|
53
|
-
],
|
|
54
|
-
panelIndex: 0,
|
|
55
|
-
panelId: "test",
|
|
56
|
-
});
|
|
57
|
-
}, "default size should not be less than 0");
|
|
58
|
-
|
|
59
|
-
verifyExpectedWarnings(() => {
|
|
60
|
-
validatePanelConstraints({
|
|
61
|
-
panelConstraints: [
|
|
62
|
-
{
|
|
63
|
-
defaultSize: 5,
|
|
64
|
-
minSize: 10,
|
|
65
|
-
},
|
|
66
|
-
],
|
|
67
|
-
panelIndex: 0,
|
|
68
|
-
panelId: "test",
|
|
69
|
-
});
|
|
70
|
-
}, "default size should not be less than min size");
|
|
71
|
-
|
|
72
|
-
verifyExpectedWarnings(() => {
|
|
73
|
-
validatePanelConstraints({
|
|
74
|
-
panelConstraints: [
|
|
75
|
-
{
|
|
76
|
-
collapsedSize: 5,
|
|
77
|
-
collapsible: true,
|
|
78
|
-
defaultSize: 5,
|
|
79
|
-
minSize: 10,
|
|
80
|
-
},
|
|
81
|
-
],
|
|
82
|
-
panelIndex: 0,
|
|
83
|
-
panelId: "test",
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
verifyExpectedWarnings(() => {
|
|
88
|
-
validatePanelConstraints({
|
|
89
|
-
panelConstraints: [
|
|
90
|
-
{
|
|
91
|
-
collapsedSize: 7,
|
|
92
|
-
collapsible: true,
|
|
93
|
-
defaultSize: 5,
|
|
94
|
-
minSize: 10,
|
|
95
|
-
},
|
|
96
|
-
],
|
|
97
|
-
panelIndex: 0,
|
|
98
|
-
panelId: "test",
|
|
99
|
-
});
|
|
100
|
-
}, "default size should not be less than min size");
|
|
101
|
-
|
|
102
|
-
verifyExpectedWarnings(() => {
|
|
103
|
-
validatePanelConstraints({
|
|
104
|
-
panelConstraints: [
|
|
105
|
-
{
|
|
106
|
-
collapsedSize: 5,
|
|
107
|
-
collapsible: false,
|
|
108
|
-
defaultSize: 5,
|
|
109
|
-
minSize: 10,
|
|
110
|
-
},
|
|
111
|
-
],
|
|
112
|
-
panelIndex: 0,
|
|
113
|
-
panelId: "test",
|
|
114
|
-
});
|
|
115
|
-
}, "default size should not be less than min size");
|
|
116
|
-
|
|
117
|
-
verifyExpectedWarnings(() => {
|
|
118
|
-
validatePanelConstraints({
|
|
119
|
-
panelConstraints: [
|
|
120
|
-
{
|
|
121
|
-
defaultSize: 101,
|
|
122
|
-
maxSize: 10,
|
|
123
|
-
},
|
|
124
|
-
],
|
|
125
|
-
panelIndex: 0,
|
|
126
|
-
panelId: "test",
|
|
127
|
-
});
|
|
128
|
-
}, "default size should not be greater than 100");
|
|
129
|
-
|
|
130
|
-
verifyExpectedWarnings(() => {
|
|
131
|
-
validatePanelConstraints({
|
|
132
|
-
panelConstraints: [
|
|
133
|
-
{
|
|
134
|
-
defaultSize: 15,
|
|
135
|
-
maxSize: 10,
|
|
136
|
-
},
|
|
137
|
-
],
|
|
138
|
-
panelIndex: 0,
|
|
139
|
-
panelId: "test",
|
|
140
|
-
});
|
|
141
|
-
}, "default size should not be greater than max size");
|
|
142
|
-
});
|
|
143
|
-
});
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { isDevelopment } from "#is-development";
|
|
2
|
-
import { PanelConstraints } from "../Panel";
|
|
3
|
-
import { assert } from "./assert";
|
|
4
|
-
|
|
5
|
-
export function validatePanelConstraints({
|
|
6
|
-
panelConstraints: panelConstraintsArray,
|
|
7
|
-
panelId,
|
|
8
|
-
panelIndex,
|
|
9
|
-
}: {
|
|
10
|
-
panelConstraints: PanelConstraints[];
|
|
11
|
-
panelId: string | undefined;
|
|
12
|
-
panelIndex: number;
|
|
13
|
-
}): boolean {
|
|
14
|
-
if (isDevelopment) {
|
|
15
|
-
const warnings = [];
|
|
16
|
-
|
|
17
|
-
const panelConstraints = panelConstraintsArray[panelIndex];
|
|
18
|
-
assert(
|
|
19
|
-
panelConstraints,
|
|
20
|
-
`No panel constraints found for index ${panelIndex}`
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
const {
|
|
24
|
-
collapsedSize = 0,
|
|
25
|
-
collapsible = false,
|
|
26
|
-
defaultSize,
|
|
27
|
-
maxSize = 100,
|
|
28
|
-
minSize = 0,
|
|
29
|
-
} = panelConstraints;
|
|
30
|
-
|
|
31
|
-
if (minSize > maxSize) {
|
|
32
|
-
warnings.push(
|
|
33
|
-
`min size (${minSize}%) should not be greater than max size (${maxSize}%)`
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (defaultSize != null) {
|
|
38
|
-
if (defaultSize < 0) {
|
|
39
|
-
warnings.push("default size should not be less than 0");
|
|
40
|
-
} else if (
|
|
41
|
-
defaultSize < minSize &&
|
|
42
|
-
(!collapsible || defaultSize !== collapsedSize)
|
|
43
|
-
) {
|
|
44
|
-
warnings.push("default size should not be less than min size");
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (defaultSize > 100) {
|
|
48
|
-
warnings.push("default size should not be greater than 100");
|
|
49
|
-
} else if (defaultSize > maxSize) {
|
|
50
|
-
warnings.push("default size should not be greater than max size");
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (collapsedSize > minSize) {
|
|
55
|
-
warnings.push("collapsed size should not be greater than min size");
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (warnings.length > 0) {
|
|
59
|
-
const name = panelId != null ? `Panel "${panelId}"` : "Panel";
|
|
60
|
-
console.warn(
|
|
61
|
-
`${name} has an invalid configuration:\n\n${warnings.join("\n")}`
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return true;
|
|
69
|
-
}
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import { verifyExpectedWarnings } from "./test-utils";
|
|
2
|
-
import { validatePanelGroupLayout } from "./validatePanelGroupLayout";
|
|
3
|
-
|
|
4
|
-
describe("validatePanelGroupLayout", () => {
|
|
5
|
-
it("should accept requested layout if there are no constraints provided", () => {
|
|
6
|
-
expect(
|
|
7
|
-
validatePanelGroupLayout({
|
|
8
|
-
layout: [10, 60, 30],
|
|
9
|
-
panelConstraints: [{}, {}, {}],
|
|
10
|
-
})
|
|
11
|
-
).toEqual([10, 60, 30]);
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it("should normalize layouts that do not total 100%", () => {
|
|
15
|
-
let layout;
|
|
16
|
-
verifyExpectedWarnings(() => {
|
|
17
|
-
layout = validatePanelGroupLayout({
|
|
18
|
-
layout: [10, 20, 20],
|
|
19
|
-
panelConstraints: [{}, {}, {}],
|
|
20
|
-
});
|
|
21
|
-
}, "Invalid layout total size");
|
|
22
|
-
expect(layout).toEqual([20, 40, 40]);
|
|
23
|
-
|
|
24
|
-
verifyExpectedWarnings(() => {
|
|
25
|
-
layout = validatePanelGroupLayout({
|
|
26
|
-
layout: [50, 100, 50],
|
|
27
|
-
panelConstraints: [{}, {}, {}],
|
|
28
|
-
});
|
|
29
|
-
}, "Invalid layout total size");
|
|
30
|
-
expect(layout).toEqual([25, 50, 25]);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it("should reject layouts that do not match the number of panels", () => {
|
|
34
|
-
expect(() =>
|
|
35
|
-
validatePanelGroupLayout({
|
|
36
|
-
layout: [10, 20, 30],
|
|
37
|
-
panelConstraints: [{}, {}],
|
|
38
|
-
})
|
|
39
|
-
).toThrow("Invalid 2 panel layout");
|
|
40
|
-
|
|
41
|
-
expect(() =>
|
|
42
|
-
validatePanelGroupLayout({
|
|
43
|
-
layout: [50, 50],
|
|
44
|
-
panelConstraints: [{}, {}, {}],
|
|
45
|
-
})
|
|
46
|
-
).toThrow("Invalid 3 panel layout");
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
describe("minimum size constraints", () => {
|
|
50
|
-
it("should adjust the layout to account for minimum percentage sizes", () => {
|
|
51
|
-
expect(
|
|
52
|
-
validatePanelGroupLayout({
|
|
53
|
-
layout: [25, 75],
|
|
54
|
-
panelConstraints: [
|
|
55
|
-
{
|
|
56
|
-
minSize: 35,
|
|
57
|
-
},
|
|
58
|
-
{},
|
|
59
|
-
],
|
|
60
|
-
})
|
|
61
|
-
).toEqual([35, 65]);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it("should account for multiple panels with minimum size constraints", () => {
|
|
65
|
-
expect(
|
|
66
|
-
validatePanelGroupLayout({
|
|
67
|
-
layout: [20, 60, 20],
|
|
68
|
-
panelConstraints: [
|
|
69
|
-
{
|
|
70
|
-
minSize: 25,
|
|
71
|
-
},
|
|
72
|
-
{},
|
|
73
|
-
{
|
|
74
|
-
minSize: 25,
|
|
75
|
-
},
|
|
76
|
-
],
|
|
77
|
-
})
|
|
78
|
-
).toEqual([25, 50, 25]);
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
describe("maximum size constraints", () => {
|
|
83
|
-
it("should adjust the layout to account for maximum percentage sizes", () => {
|
|
84
|
-
expect(
|
|
85
|
-
validatePanelGroupLayout({
|
|
86
|
-
layout: [25, 75],
|
|
87
|
-
panelConstraints: [{}, { maxSize: 65 }],
|
|
88
|
-
})
|
|
89
|
-
).toEqual([35, 65]);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it("should account for multiple panels with maximum size constraints", () => {
|
|
93
|
-
expect(
|
|
94
|
-
validatePanelGroupLayout({
|
|
95
|
-
layout: [20, 60, 20],
|
|
96
|
-
panelConstraints: [
|
|
97
|
-
{
|
|
98
|
-
maxSize: 15,
|
|
99
|
-
},
|
|
100
|
-
{ maxSize: 50 },
|
|
101
|
-
{},
|
|
102
|
-
],
|
|
103
|
-
})
|
|
104
|
-
).toEqual([15, 50, 35]);
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
describe("collapsible panels", () => {
|
|
109
|
-
it("should not collapse a panel that's at or above the minimum size", () => {
|
|
110
|
-
expect(
|
|
111
|
-
validatePanelGroupLayout({
|
|
112
|
-
layout: [25, 75],
|
|
113
|
-
panelConstraints: [{ collapsible: true, minSize: 25 }, {}],
|
|
114
|
-
})
|
|
115
|
-
).toEqual([25, 75]);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it("should collapse a panel once it drops below the halfway point between collapsed and minimum percentage sizes", () => {
|
|
119
|
-
expect(
|
|
120
|
-
validatePanelGroupLayout({
|
|
121
|
-
layout: [15, 85],
|
|
122
|
-
panelConstraints: [
|
|
123
|
-
{
|
|
124
|
-
collapsible: true,
|
|
125
|
-
collapsedSize: 10,
|
|
126
|
-
minSize: 20,
|
|
127
|
-
},
|
|
128
|
-
{},
|
|
129
|
-
],
|
|
130
|
-
})
|
|
131
|
-
).toEqual([20, 80]);
|
|
132
|
-
|
|
133
|
-
expect(
|
|
134
|
-
validatePanelGroupLayout({
|
|
135
|
-
layout: [14, 86],
|
|
136
|
-
panelConstraints: [
|
|
137
|
-
{
|
|
138
|
-
collapsible: true,
|
|
139
|
-
collapsedSize: 10,
|
|
140
|
-
minSize: 20,
|
|
141
|
-
},
|
|
142
|
-
{},
|
|
143
|
-
],
|
|
144
|
-
})
|
|
145
|
-
).toEqual([10, 90]);
|
|
146
|
-
});
|
|
147
|
-
});
|
|
148
|
-
});
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { isDevelopment } from "#is-development";
|
|
2
|
-
import { PanelConstraints } from "../Panel";
|
|
3
|
-
import { assert } from "./assert";
|
|
4
|
-
import { fuzzyNumbersEqual } from "./numbers/fuzzyNumbersEqual";
|
|
5
|
-
import { resizePanel } from "./resizePanel";
|
|
6
|
-
|
|
7
|
-
// All units must be in percentages; pixel values should be pre-converted
|
|
8
|
-
export function validatePanelGroupLayout({
|
|
9
|
-
layout: prevLayout,
|
|
10
|
-
panelConstraints,
|
|
11
|
-
}: {
|
|
12
|
-
layout: number[];
|
|
13
|
-
panelConstraints: PanelConstraints[];
|
|
14
|
-
}): number[] {
|
|
15
|
-
const nextLayout = [...prevLayout];
|
|
16
|
-
const nextLayoutTotalSize = nextLayout.reduce(
|
|
17
|
-
(accumulated, current) => accumulated + current,
|
|
18
|
-
0
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
// Validate layout expectations
|
|
22
|
-
if (nextLayout.length !== panelConstraints.length) {
|
|
23
|
-
throw Error(
|
|
24
|
-
`Invalid ${panelConstraints.length} panel layout: ${nextLayout
|
|
25
|
-
.map((size) => `${size}%`)
|
|
26
|
-
.join(", ")}`
|
|
27
|
-
);
|
|
28
|
-
} else if (
|
|
29
|
-
!fuzzyNumbersEqual(nextLayoutTotalSize, 100) &&
|
|
30
|
-
nextLayout.length > 0
|
|
31
|
-
) {
|
|
32
|
-
// This is not ideal so we should warn about it, but it may be recoverable in some cases
|
|
33
|
-
// (especially if the amount is small)
|
|
34
|
-
if (isDevelopment) {
|
|
35
|
-
console.warn(
|
|
36
|
-
`WARNING: Invalid layout total size: ${nextLayout
|
|
37
|
-
.map((size) => `${size}%`)
|
|
38
|
-
.join(", ")}. Layout normalization will be applied.`
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
for (let index = 0; index < panelConstraints.length; index++) {
|
|
42
|
-
const unsafeSize = nextLayout[index];
|
|
43
|
-
assert(unsafeSize != null, `No layout data found for index ${index}`);
|
|
44
|
-
const safeSize = (100 / nextLayoutTotalSize) * unsafeSize;
|
|
45
|
-
nextLayout[index] = safeSize;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
let remainingSize = 0;
|
|
50
|
-
|
|
51
|
-
// First pass: Validate the proposed layout given each panel's constraints
|
|
52
|
-
for (let index = 0; index < panelConstraints.length; index++) {
|
|
53
|
-
const unsafeSize = nextLayout[index];
|
|
54
|
-
assert(unsafeSize != null, `No layout data found for index ${index}`);
|
|
55
|
-
|
|
56
|
-
const safeSize = resizePanel({
|
|
57
|
-
panelConstraints,
|
|
58
|
-
panelIndex: index,
|
|
59
|
-
size: unsafeSize,
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
if (unsafeSize != safeSize) {
|
|
63
|
-
remainingSize += unsafeSize - safeSize;
|
|
64
|
-
|
|
65
|
-
nextLayout[index] = safeSize;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// If there is additional, left over space, assign it to any panel(s) that permits it
|
|
70
|
-
// (It's not worth taking multiple additional passes to evenly distribute)
|
|
71
|
-
if (!fuzzyNumbersEqual(remainingSize, 0)) {
|
|
72
|
-
for (let index = 0; index < panelConstraints.length; index++) {
|
|
73
|
-
const prevSize = nextLayout[index];
|
|
74
|
-
assert(prevSize != null, `No layout data found for index ${index}`);
|
|
75
|
-
const unsafeSize = prevSize + remainingSize;
|
|
76
|
-
const safeSize = resizePanel({
|
|
77
|
-
panelConstraints,
|
|
78
|
-
panelIndex: index,
|
|
79
|
-
size: unsafeSize,
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
if (prevSize !== safeSize) {
|
|
83
|
-
remainingSize -= safeSize - prevSize;
|
|
84
|
-
nextLayout[index] = safeSize;
|
|
85
|
-
|
|
86
|
-
// Once we've used up the remainder, bail
|
|
87
|
-
if (fuzzyNumbersEqual(remainingSize, 0)) {
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return nextLayout;
|
|
95
|
-
}
|