react-resizable-panels 0.0.55 → 0.0.56
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/.eslintrc.cjs +26 -0
- package/CHANGELOG.md +234 -90
- package/README.md +55 -49
- package/dist/declarations/src/Panel.d.ts +75 -20
- package/dist/declarations/src/PanelGroup.d.ts +29 -25
- package/dist/declarations/src/PanelResizeHandle.d.ts +1 -1
- package/dist/declarations/src/index.d.ts +5 -6
- package/dist/declarations/src/types.d.ts +3 -26
- package/dist/declarations/src/vendor/react.d.ts +4 -4
- package/dist/react-resizable-panels.browser.cjs.js +1241 -1035
- package/dist/react-resizable-panels.browser.cjs.mjs +1 -2
- package/dist/react-resizable-panels.browser.development.cjs.js +1367 -1081
- package/dist/react-resizable-panels.browser.development.cjs.mjs +1 -2
- package/dist/react-resizable-panels.browser.development.esm.js +1368 -1081
- package/dist/react-resizable-panels.browser.esm.js +1242 -1035
- package/dist/react-resizable-panels.cjs.js +1241 -1035
- package/dist/react-resizable-panels.cjs.js.map +1 -1
- package/dist/react-resizable-panels.cjs.mjs +1 -2
- package/dist/react-resizable-panels.development.cjs.js +1370 -1084
- package/dist/react-resizable-panels.development.cjs.mjs +1 -2
- package/dist/react-resizable-panels.development.esm.js +1371 -1084
- package/dist/react-resizable-panels.development.node.cjs.js +1151 -940
- package/dist/react-resizable-panels.development.node.cjs.mjs +1 -2
- package/dist/react-resizable-panels.development.node.esm.js +1152 -940
- package/dist/react-resizable-panels.esm.js +1242 -1035
- package/dist/react-resizable-panels.esm.js.map +1 -1
- package/dist/react-resizable-panels.node.cjs.js +1049 -912
- package/dist/react-resizable-panels.node.cjs.mjs +1 -2
- package/dist/react-resizable-panels.node.esm.js +1050 -912
- package/jest.config.js +10 -0
- package/package.json +3 -1
- package/src/Panel.test.tsx +308 -0
- package/src/Panel.ts +175 -123
- package/src/PanelGroup.test.tsx +210 -0
- package/src/PanelGroup.ts +730 -669
- package/src/PanelGroupContext.ts +33 -0
- package/src/PanelResizeHandle.ts +13 -8
- package/src/hooks/useUniqueId.ts +1 -1
- package/src/hooks/useWindowSplitterBehavior.ts +9 -164
- package/src/hooks/useWindowSplitterPanelGroupBehavior.ts +185 -0
- package/src/index.ts +19 -14
- package/src/types.ts +3 -30
- package/src/utils/adjustLayoutByDelta.test.ts +1808 -0
- package/src/utils/adjustLayoutByDelta.ts +211 -0
- package/src/utils/calculateAriaValues.test.ts +111 -0
- package/src/utils/calculateAriaValues.ts +67 -0
- package/src/utils/calculateDeltaPercentage.ts +68 -0
- package/src/utils/calculateDragOffsetPercentage.ts +30 -0
- package/src/utils/calculateUnsafeDefaultLayout.test.ts +92 -0
- package/src/utils/calculateUnsafeDefaultLayout.ts +55 -0
- package/src/utils/callPanelCallbacks.ts +81 -0
- package/src/utils/compareLayouts.test.ts +9 -0
- package/src/utils/compareLayouts.ts +12 -0
- package/src/utils/computePanelFlexBoxStyle.ts +44 -0
- package/src/utils/computePercentagePanelConstraints.test.ts +71 -0
- package/src/utils/computePercentagePanelConstraints.ts +56 -0
- package/src/utils/convertPercentageToPixels.test.ts +9 -0
- package/src/utils/convertPercentageToPixels.ts +6 -0
- package/src/utils/convertPixelConstraintsToPercentages.ts +55 -0
- package/src/utils/convertPixelsToPercentage.test.ts +9 -0
- package/src/utils/convertPixelsToPercentage.ts +6 -0
- package/src/utils/determinePivotIndices.ts +10 -0
- package/src/utils/dom/calculateAvailablePanelSizeInPixels.ts +29 -0
- package/src/utils/dom/getAvailableGroupSizePixels.ts +29 -0
- package/src/utils/dom/getPanelElement.ts +7 -0
- package/src/utils/dom/getPanelGroupElement.ts +7 -0
- package/src/utils/dom/getResizeHandleElement.ts +9 -0
- package/src/utils/dom/getResizeHandleElementIndex.ts +12 -0
- package/src/utils/dom/getResizeHandleElementsForGroup.ts +9 -0
- package/src/utils/dom/getResizeHandlePanelIds.ts +18 -0
- package/src/utils/events.ts +13 -0
- package/src/utils/getPercentageSizeFromMixedSizes.test.ts +47 -0
- package/src/utils/getPercentageSizeFromMixedSizes.ts +15 -0
- package/src/utils/getResizeEventCursorPosition.ts +19 -0
- package/src/utils/initializeDefaultStorage.ts +26 -0
- package/src/utils/numbers/fuzzyCompareNumbers.test.ts +16 -0
- package/src/utils/numbers/fuzzyCompareNumbers.ts +17 -0
- package/src/utils/numbers/fuzzyNumbersEqual.ts +9 -0
- package/src/utils/resizePanel.ts +41 -0
- package/src/utils/serialization.ts +9 -4
- package/src/utils/shouldMonitorPixelBasedConstraints.test.ts +23 -0
- package/src/utils/shouldMonitorPixelBasedConstraints.ts +13 -0
- package/src/utils/test-utils.ts +136 -0
- package/src/utils/validatePanelConstraints.test.ts +151 -0
- package/src/utils/validatePanelConstraints.ts +103 -0
- package/src/utils/validatePanelGroupLayout.test.ts +233 -0
- package/src/utils/validatePanelGroupLayout.ts +88 -0
- package/src/vendor/react.ts +4 -0
- package/.eslintrc.json +0 -22
- package/dist/declarations/src/utils/group.d.ts +0 -29
- package/src/PanelContexts.ts +0 -22
- package/src/utils/coordinates.ts +0 -149
- package/src/utils/group.ts +0 -614
package/src/Panel.ts
CHANGED
|
@@ -1,67 +1,100 @@
|
|
|
1
|
+
import { isBrowser } from "#is-browser";
|
|
2
|
+
import { isDevelopment } from "#is-development";
|
|
3
|
+
import { PanelGroupContext } from "./PanelGroupContext";
|
|
1
4
|
import useIsomorphicLayoutEffect from "./hooks/useIsomorphicEffect";
|
|
2
5
|
import useUniqueId from "./hooks/useUniqueId";
|
|
6
|
+
import { MixedSizes } from "./types";
|
|
3
7
|
import {
|
|
4
|
-
createElement,
|
|
5
|
-
CSSProperties,
|
|
6
8
|
ElementType,
|
|
7
9
|
ForwardedRef,
|
|
10
|
+
PropsWithChildren,
|
|
11
|
+
createElement,
|
|
8
12
|
forwardRef,
|
|
9
|
-
ReactNode,
|
|
10
13
|
useContext,
|
|
11
|
-
useEffect,
|
|
12
14
|
useImperativeHandle,
|
|
13
15
|
useRef,
|
|
14
16
|
} from "./vendor/react";
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
18
|
+
export type PanelOnCollapse = () => void;
|
|
19
|
+
export type PanelOnExpand = () => void;
|
|
20
|
+
export type PanelOnResize = (
|
|
21
|
+
mixedSizes: MixedSizes,
|
|
22
|
+
prevMixedSizes: MixedSizes
|
|
23
|
+
) => void;
|
|
24
|
+
|
|
25
|
+
export type PanelCallbacks = {
|
|
26
|
+
onCollapse?: PanelOnCollapse;
|
|
27
|
+
onExpand?: PanelOnExpand;
|
|
28
|
+
onResize?: PanelOnResize;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export type PanelConstraints = {
|
|
32
|
+
collapsedSizePercentage?: number | undefined;
|
|
33
|
+
collapsedSizePixels?: number | undefined;
|
|
34
|
+
collapsible?: boolean | undefined;
|
|
35
|
+
defaultSizePercentage?: number | undefined;
|
|
36
|
+
defaultSizePixels?: number | undefined;
|
|
37
|
+
maxSizePercentage?: number | undefined;
|
|
38
|
+
maxSizePixels?: number | undefined;
|
|
39
|
+
minSizePercentage?: number | undefined;
|
|
40
|
+
minSizePixels?: number | undefined;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export type PanelData = {
|
|
44
|
+
callbacks: PanelCallbacks;
|
|
45
|
+
constraints: PanelConstraints;
|
|
46
|
+
id: string;
|
|
47
|
+
idIsFromProps: boolean;
|
|
48
|
+
order: number | undefined;
|
|
40
49
|
};
|
|
41
50
|
|
|
42
51
|
export type ImperativePanelHandle = {
|
|
43
52
|
collapse: () => void;
|
|
44
53
|
expand: () => void;
|
|
45
|
-
getCollapsed(): boolean;
|
|
46
54
|
getId(): string;
|
|
47
|
-
getSize(
|
|
48
|
-
resize: (
|
|
55
|
+
getSize(): MixedSizes;
|
|
56
|
+
resize: (size: Partial<MixedSizes>) => void;
|
|
49
57
|
};
|
|
50
58
|
|
|
51
|
-
|
|
52
|
-
|
|
59
|
+
export type PanelProps = PropsWithChildren<{
|
|
60
|
+
className?: string;
|
|
61
|
+
collapsedSizePercentage?: number | undefined;
|
|
62
|
+
collapsedSizePixels?: number | undefined;
|
|
63
|
+
collapsible?: boolean | undefined;
|
|
64
|
+
defaultSizePercentage?: number | undefined;
|
|
65
|
+
defaultSizePixels?: number | undefined;
|
|
66
|
+
id?: string;
|
|
67
|
+
maxSizePercentage?: number | undefined;
|
|
68
|
+
maxSizePixels?: number | undefined;
|
|
69
|
+
minSizePercentage?: number | undefined;
|
|
70
|
+
minSizePixels?: number | undefined;
|
|
71
|
+
onCollapse?: PanelOnCollapse;
|
|
72
|
+
onExpand?: PanelOnExpand;
|
|
73
|
+
onResize?: PanelOnResize;
|
|
74
|
+
order?: number;
|
|
75
|
+
style?: object;
|
|
76
|
+
tagName?: ElementType;
|
|
77
|
+
}>;
|
|
78
|
+
|
|
79
|
+
export function PanelWithForwardedRef({
|
|
80
|
+
children,
|
|
53
81
|
className: classNameFromProps = "",
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
82
|
+
collapsedSizePercentage,
|
|
83
|
+
collapsedSizePixels,
|
|
84
|
+
collapsible,
|
|
85
|
+
defaultSizePercentage,
|
|
86
|
+
defaultSizePixels,
|
|
57
87
|
forwardedRef,
|
|
58
|
-
id: idFromProps
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
88
|
+
id: idFromProps,
|
|
89
|
+
maxSizePercentage,
|
|
90
|
+
maxSizePixels,
|
|
91
|
+
minSizePercentage,
|
|
92
|
+
minSizePixels,
|
|
93
|
+
onCollapse,
|
|
94
|
+
onExpand,
|
|
95
|
+
onResize,
|
|
96
|
+
order,
|
|
97
|
+
style: styleFromProps,
|
|
65
98
|
tagName: Type = "div",
|
|
66
99
|
}: PanelProps & {
|
|
67
100
|
forwardedRef: ForwardedRef<ImperativePanelHandle>;
|
|
@@ -73,123 +106,152 @@ function PanelWithForwardedRef({
|
|
|
73
106
|
);
|
|
74
107
|
}
|
|
75
108
|
|
|
76
|
-
const panelId = useUniqueId(idFromProps);
|
|
77
|
-
|
|
78
109
|
const {
|
|
79
110
|
collapsePanel,
|
|
80
111
|
expandPanel,
|
|
81
112
|
getPanelSize,
|
|
82
113
|
getPanelStyle,
|
|
114
|
+
isPanelCollapsed,
|
|
83
115
|
registerPanel,
|
|
84
116
|
resizePanel,
|
|
85
|
-
units,
|
|
86
117
|
unregisterPanel,
|
|
87
118
|
} = context;
|
|
88
119
|
|
|
89
|
-
|
|
90
|
-
if (units === "percentages") {
|
|
91
|
-
// Mimics legacy default value for percentage based panel groups
|
|
92
|
-
minSize = 10;
|
|
93
|
-
} else {
|
|
94
|
-
// There is no meaningful minimum pixel default we can provide
|
|
95
|
-
minSize = 0;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
120
|
+
const panelId = useUniqueId(idFromProps);
|
|
98
121
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
122
|
+
const panelDataRef = useRef<PanelData>({
|
|
123
|
+
callbacks: {
|
|
124
|
+
onCollapse,
|
|
125
|
+
onExpand,
|
|
126
|
+
onResize,
|
|
127
|
+
},
|
|
128
|
+
constraints: {
|
|
129
|
+
collapsedSizePercentage,
|
|
130
|
+
collapsedSizePixels,
|
|
131
|
+
collapsible,
|
|
132
|
+
defaultSizePercentage,
|
|
133
|
+
defaultSizePixels,
|
|
134
|
+
maxSizePercentage,
|
|
135
|
+
maxSizePixels,
|
|
136
|
+
minSizePercentage,
|
|
137
|
+
minSizePixels,
|
|
138
|
+
},
|
|
139
|
+
id: panelId,
|
|
140
|
+
idIsFromProps: idFromProps !== undefined,
|
|
141
|
+
order,
|
|
107
142
|
});
|
|
108
143
|
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
const committedValuesRef = useRef<{
|
|
112
|
-
size: number;
|
|
144
|
+
const devWarningsRef = useRef<{
|
|
145
|
+
didLogMissingDefaultSizeWarning: boolean;
|
|
113
146
|
}>({
|
|
114
|
-
|
|
147
|
+
didLogMissingDefaultSizeWarning: false,
|
|
115
148
|
});
|
|
116
149
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
idWasAutoGenerated: idFromProps == null,
|
|
134
|
-
maxSize,
|
|
135
|
-
minSize,
|
|
136
|
-
order,
|
|
137
|
-
});
|
|
150
|
+
// Normally we wouldn't log a warning during render,
|
|
151
|
+
// but effects don't run on the server, so we can't do it there
|
|
152
|
+
if (isDevelopment) {
|
|
153
|
+
if (!devWarningsRef.current.didLogMissingDefaultSizeWarning) {
|
|
154
|
+
if (
|
|
155
|
+
!isBrowser &&
|
|
156
|
+
defaultSizePercentage == null &&
|
|
157
|
+
defaultSizePixels == null
|
|
158
|
+
) {
|
|
159
|
+
devWarningsRef.current.didLogMissingDefaultSizeWarning = true;
|
|
160
|
+
console.warn(
|
|
161
|
+
`WARNING: Panel defaultSizePercentage or defaultSizePixels prop recommended to avoid layout shift after server rendering`
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
138
166
|
|
|
139
167
|
useIsomorphicLayoutEffect(() => {
|
|
140
|
-
|
|
168
|
+
const { callbacks, constraints } = panelDataRef.current;
|
|
141
169
|
|
|
142
|
-
panelDataRef.current.callbacksRef = callbacksRef;
|
|
143
|
-
panelDataRef.current.collapsedSize = collapsedSize;
|
|
144
|
-
panelDataRef.current.collapsible = collapsible;
|
|
145
|
-
panelDataRef.current.defaultSize = defaultSize;
|
|
146
170
|
panelDataRef.current.id = panelId;
|
|
147
|
-
panelDataRef.current.
|
|
148
|
-
panelDataRef.current.maxSize = maxSize;
|
|
149
|
-
panelDataRef.current.minSize = minSize as number;
|
|
171
|
+
panelDataRef.current.idIsFromProps = idFromProps !== undefined;
|
|
150
172
|
panelDataRef.current.order = order;
|
|
173
|
+
|
|
174
|
+
callbacks.onCollapse = onCollapse;
|
|
175
|
+
callbacks.onExpand = onExpand;
|
|
176
|
+
callbacks.onResize = onResize;
|
|
177
|
+
|
|
178
|
+
constraints.collapsedSizePercentage = collapsedSizePercentage;
|
|
179
|
+
constraints.collapsedSizePixels = collapsedSizePixels;
|
|
180
|
+
constraints.collapsible = collapsible;
|
|
181
|
+
constraints.defaultSizePercentage = defaultSizePercentage;
|
|
182
|
+
constraints.defaultSizePixels = defaultSizePixels;
|
|
183
|
+
constraints.maxSizePercentage = maxSizePercentage;
|
|
184
|
+
constraints.maxSizePixels = maxSizePixels;
|
|
185
|
+
constraints.minSizePercentage = minSizePercentage;
|
|
186
|
+
constraints.minSizePixels = minSizePixels;
|
|
151
187
|
});
|
|
152
188
|
|
|
153
189
|
useIsomorphicLayoutEffect(() => {
|
|
154
|
-
|
|
190
|
+
const panelData = panelDataRef.current;
|
|
191
|
+
|
|
192
|
+
registerPanel(panelData);
|
|
155
193
|
|
|
156
194
|
return () => {
|
|
157
|
-
unregisterPanel(
|
|
195
|
+
unregisterPanel(panelData);
|
|
158
196
|
};
|
|
159
197
|
}, [order, panelId, registerPanel, unregisterPanel]);
|
|
160
198
|
|
|
161
199
|
useImperativeHandle(
|
|
162
200
|
forwardedRef,
|
|
163
201
|
() => ({
|
|
164
|
-
collapse: () =>
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
202
|
+
collapse: () => {
|
|
203
|
+
collapsePanel(panelDataRef.current);
|
|
204
|
+
},
|
|
205
|
+
expand: () => {
|
|
206
|
+
expandPanel(panelDataRef.current);
|
|
168
207
|
},
|
|
169
208
|
getId() {
|
|
170
209
|
return panelId;
|
|
171
210
|
},
|
|
172
|
-
getSize(
|
|
173
|
-
return getPanelSize(
|
|
211
|
+
getSize() {
|
|
212
|
+
return getPanelSize(panelDataRef.current);
|
|
213
|
+
},
|
|
214
|
+
isCollapsed() {
|
|
215
|
+
return isPanelCollapsed(panelDataRef.current);
|
|
216
|
+
},
|
|
217
|
+
isExpanded() {
|
|
218
|
+
return !isPanelCollapsed(panelDataRef.current);
|
|
219
|
+
},
|
|
220
|
+
resize: (mixedSizes: Partial<MixedSizes>) => {
|
|
221
|
+
resizePanel(panelDataRef.current, mixedSizes);
|
|
174
222
|
},
|
|
175
|
-
resize: (percentage: number, units) =>
|
|
176
|
-
resizePanel(panelId, percentage, units),
|
|
177
223
|
}),
|
|
178
|
-
[
|
|
224
|
+
[
|
|
225
|
+
collapsePanel,
|
|
226
|
+
expandPanel,
|
|
227
|
+
getPanelSize,
|
|
228
|
+
isPanelCollapsed,
|
|
229
|
+
panelId,
|
|
230
|
+
resizePanel,
|
|
231
|
+
]
|
|
179
232
|
);
|
|
180
233
|
|
|
234
|
+
const style = getPanelStyle(panelDataRef.current);
|
|
235
|
+
|
|
181
236
|
return createElement(Type, {
|
|
182
237
|
children,
|
|
183
238
|
className: classNameFromProps,
|
|
184
|
-
"data-panel": "",
|
|
185
|
-
"data-panel-collapsible": collapsible || undefined,
|
|
186
|
-
"data-panel-id": panelId,
|
|
187
|
-
"data-panel-size": parseFloat("" + style.flexGrow).toFixed(1),
|
|
188
|
-
id: `data-panel-id-${panelId}`,
|
|
189
239
|
style: {
|
|
190
240
|
...style,
|
|
191
241
|
...styleFromProps,
|
|
192
242
|
},
|
|
243
|
+
|
|
244
|
+
// CSS selectors
|
|
245
|
+
"data-panel": "",
|
|
246
|
+
|
|
247
|
+
// e2e test attributes
|
|
248
|
+
"data-panel-collapsible": isDevelopment
|
|
249
|
+
? collapsible || undefined
|
|
250
|
+
: undefined,
|
|
251
|
+
"data-panel-id": isDevelopment ? panelId : undefined,
|
|
252
|
+
"data-panel-size": isDevelopment
|
|
253
|
+
? parseFloat("" + style.flexGrow).toFixed(1)
|
|
254
|
+
: undefined,
|
|
193
255
|
});
|
|
194
256
|
}
|
|
195
257
|
|
|
@@ -200,13 +262,3 @@ export const Panel = forwardRef<ImperativePanelHandle, PanelProps>(
|
|
|
200
262
|
|
|
201
263
|
PanelWithForwardedRef.displayName = "Panel";
|
|
202
264
|
Panel.displayName = "forwardRef(Panel)";
|
|
203
|
-
|
|
204
|
-
// HACK
|
|
205
|
-
function parseSizeFromStyle(style: CSSProperties): number {
|
|
206
|
-
const { flexGrow } = style;
|
|
207
|
-
if (typeof flexGrow === "string") {
|
|
208
|
-
return parseFloat(flexGrow);
|
|
209
|
-
} else {
|
|
210
|
-
return flexGrow as number;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { Root, createRoot } from "react-dom/client";
|
|
2
|
+
import { act } from "react-dom/test-utils";
|
|
3
|
+
import {
|
|
4
|
+
ImperativePanelGroupHandle,
|
|
5
|
+
MixedSizes,
|
|
6
|
+
Panel,
|
|
7
|
+
PanelGroup,
|
|
8
|
+
PanelResizeHandle,
|
|
9
|
+
} from ".";
|
|
10
|
+
import { mockPanelGroupOffsetWidthAndHeight } from "./utils/test-utils";
|
|
11
|
+
import { createRef } from "./vendor/react";
|
|
12
|
+
|
|
13
|
+
describe("PanelGroup", () => {
|
|
14
|
+
let expectedWarnings: string[] = [];
|
|
15
|
+
let root: Root;
|
|
16
|
+
let uninstallMockOffsetWidthAndHeight: () => void;
|
|
17
|
+
|
|
18
|
+
function expectWarning(expectedMessage: string) {
|
|
19
|
+
expectedWarnings.push(expectedMessage);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
// @ts-expect-error
|
|
24
|
+
global.IS_REACT_ACT_ENVIRONMENT = true;
|
|
25
|
+
|
|
26
|
+
// JSDom doesn't support element sizes
|
|
27
|
+
uninstallMockOffsetWidthAndHeight = mockPanelGroupOffsetWidthAndHeight();
|
|
28
|
+
|
|
29
|
+
const container = document.createElement("div");
|
|
30
|
+
document.body.appendChild(container);
|
|
31
|
+
|
|
32
|
+
expectedWarnings = [];
|
|
33
|
+
root = createRoot(container);
|
|
34
|
+
|
|
35
|
+
jest.spyOn(console, "warn").mockImplementation((actualMessage: string) => {
|
|
36
|
+
const match = expectedWarnings.findIndex((expectedMessage) => {
|
|
37
|
+
return actualMessage.includes(expectedMessage);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
if (match >= 0) {
|
|
41
|
+
expectedWarnings.splice(match, 1);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
throw Error(`Unexpected warning: ${actualMessage}`);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
afterEach(() => {
|
|
50
|
+
uninstallMockOffsetWidthAndHeight();
|
|
51
|
+
|
|
52
|
+
jest.clearAllMocks();
|
|
53
|
+
jest.resetModules();
|
|
54
|
+
|
|
55
|
+
act(() => {
|
|
56
|
+
root.unmount();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
expect(expectedWarnings).toHaveLength(0);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe("imperative handle API", () => {
|
|
63
|
+
it("should report the most recently rendered group id", () => {
|
|
64
|
+
const ref = createRef<ImperativePanelGroupHandle>();
|
|
65
|
+
|
|
66
|
+
act(() => {
|
|
67
|
+
root.render(<PanelGroup direction="horizontal" id="one" ref={ref} />);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
expect(ref.current!.getId()).toBe("one");
|
|
71
|
+
|
|
72
|
+
act(() => {
|
|
73
|
+
root.render(<PanelGroup direction="horizontal" id="two" ref={ref} />);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
expect(ref.current!.getId()).toBe("two");
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("should get and set layouts", () => {
|
|
80
|
+
const ref = createRef<ImperativePanelGroupHandle>();
|
|
81
|
+
|
|
82
|
+
let mostRecentLayout: MixedSizes[] | null = null;
|
|
83
|
+
|
|
84
|
+
const onLayout = (layout: MixedSizes[]) => {
|
|
85
|
+
mostRecentLayout = layout;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
act(() => {
|
|
89
|
+
root.render(
|
|
90
|
+
<PanelGroup direction="horizontal" onLayout={onLayout} ref={ref}>
|
|
91
|
+
<Panel defaultSizePercentage={50} id="a" />
|
|
92
|
+
<PanelResizeHandle />
|
|
93
|
+
<Panel defaultSizePercentage={50} id="b" />
|
|
94
|
+
</PanelGroup>
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
expect(mostRecentLayout).toEqual([
|
|
99
|
+
{
|
|
100
|
+
sizePercentage: 50,
|
|
101
|
+
sizePixels: 500,
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
sizePercentage: 50,
|
|
105
|
+
sizePixels: 500,
|
|
106
|
+
},
|
|
107
|
+
]);
|
|
108
|
+
|
|
109
|
+
act(() => {
|
|
110
|
+
ref.current!.setLayout([
|
|
111
|
+
{ sizePercentage: 25 },
|
|
112
|
+
{ sizePercentage: 75 },
|
|
113
|
+
]);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
expect(mostRecentLayout).toEqual([
|
|
117
|
+
{
|
|
118
|
+
sizePercentage: 25,
|
|
119
|
+
sizePixels: 250,
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
sizePercentage: 75,
|
|
123
|
+
sizePixels: 750,
|
|
124
|
+
},
|
|
125
|
+
]);
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
describe("DEV warnings", () => {
|
|
130
|
+
it("should warn about unstable layouts without id and order props", () => {
|
|
131
|
+
act(() => {
|
|
132
|
+
root.render(
|
|
133
|
+
<PanelGroup direction="horizontal">
|
|
134
|
+
<Panel defaultSizePercentage={100} id="a" />
|
|
135
|
+
</PanelGroup>
|
|
136
|
+
);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
expectWarning(
|
|
140
|
+
"Panel id and order props recommended when panels are dynamically rendered"
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
act(() => {
|
|
144
|
+
root.render(
|
|
145
|
+
<PanelGroup direction="horizontal">
|
|
146
|
+
<Panel defaultSizePercentage={50} id="a" />
|
|
147
|
+
<PanelResizeHandle />
|
|
148
|
+
<Panel defaultSizePercentage={50} id="b" />
|
|
149
|
+
</PanelGroup>
|
|
150
|
+
);
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it("should warn about missing resize handles", () => {
|
|
155
|
+
expectWarning(
|
|
156
|
+
'Missing resize handle for PanelGroup "group-without-handle"'
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
act(() => {
|
|
160
|
+
root.render(
|
|
161
|
+
<PanelGroup direction="horizontal" id="group-without-handle">
|
|
162
|
+
<Panel />
|
|
163
|
+
<Panel />
|
|
164
|
+
</PanelGroup>
|
|
165
|
+
);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("should warn about an invalid declarative layout", () => {
|
|
170
|
+
expectWarning("Invalid layout total size: 60%, 80%");
|
|
171
|
+
|
|
172
|
+
act(() => {
|
|
173
|
+
root.render(
|
|
174
|
+
<PanelGroup direction="horizontal" id="group-without-handle">
|
|
175
|
+
<Panel defaultSizePercentage={60} />
|
|
176
|
+
<PanelResizeHandle />
|
|
177
|
+
<Panel defaultSizePercentage={80} />
|
|
178
|
+
</PanelGroup>
|
|
179
|
+
);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it("should warn about an invalid layout set via the imperative api", () => {
|
|
184
|
+
const ref = createRef<ImperativePanelGroupHandle>();
|
|
185
|
+
|
|
186
|
+
act(() => {
|
|
187
|
+
root.render(
|
|
188
|
+
<PanelGroup
|
|
189
|
+
direction="horizontal"
|
|
190
|
+
id="group-without-handle"
|
|
191
|
+
ref={ref}
|
|
192
|
+
>
|
|
193
|
+
<Panel defaultSizePercentage={30} />
|
|
194
|
+
<PanelResizeHandle />
|
|
195
|
+
<Panel defaultSizePercentage={70} />
|
|
196
|
+
</PanelGroup>
|
|
197
|
+
);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
expectWarning("Invalid layout total size: 60%, 80%");
|
|
201
|
+
|
|
202
|
+
act(() => {
|
|
203
|
+
ref.current!.setLayout([
|
|
204
|
+
{ sizePercentage: 60 },
|
|
205
|
+
{ sizePercentage: 80 },
|
|
206
|
+
]);
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
});
|