react-resizable-panels 2.0.6 → 2.0.8-rc.1

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 CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.7
4
+
5
+ - Group default layouts use `toPrecision` to avoid small layout shifts due to floating point precision differences between initial server rendering and client hydration (#295)
6
+
3
7
  ## 2.0.6
4
8
 
5
9
  - Replace `useLayoutEffect` usage with SSR-safe wrapper hook (#294)
@@ -186,11 +186,10 @@ function PanelWithForwardedRef({
186
186
  },
187
187
  // CSS selectors
188
188
  "data-panel": "",
189
- "data-panel-id": panelId,
189
+ "data-panel-collapsible": collapsible || undefined,
190
190
  "data-panel-group-id": groupId,
191
- // e2e test attributes
192
- "data-panel-collapsible": undefined,
193
- "data-panel-size": undefined
191
+ "data-panel-id": panelId,
192
+ "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
194
193
  });
195
194
  }
196
195
  const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
@@ -1245,7 +1244,7 @@ function computePanelFlexBoxStyle({
1245
1244
  if (size == null) {
1246
1245
  // Initial render (before panels have registered themselves)
1247
1246
  // In order to support server rendering, fall back to default size if provided
1248
- flexGrow = defaultSize !== null && defaultSize !== void 0 ? defaultSize : "1";
1247
+ flexGrow = defaultSize != undefined ? defaultSize.toPrecision(precision) : "1";
1249
1248
  } else if (panelData.length === 1) {
1250
1249
  // Special case: Single panel group should always fill full width/height
1251
1250
  flexGrow = "1";
@@ -192,11 +192,10 @@ function PanelWithForwardedRef({
192
192
  },
193
193
  // CSS selectors
194
194
  "data-panel": "",
195
- "data-panel-id": panelId,
195
+ "data-panel-collapsible": collapsible || undefined,
196
196
  "data-panel-group-id": groupId,
197
- // e2e test attributes
198
- "data-panel-collapsible": collapsible || undefined ,
199
- "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
197
+ "data-panel-id": panelId,
198
+ "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
200
199
  });
201
200
  }
202
201
  const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
@@ -1261,7 +1260,7 @@ function computePanelFlexBoxStyle({
1261
1260
  if (size == null) {
1262
1261
  // Initial render (before panels have registered themselves)
1263
1262
  // In order to support server rendering, fall back to default size if provided
1264
- flexGrow = defaultSize !== null && defaultSize !== void 0 ? defaultSize : "1";
1263
+ flexGrow = defaultSize != undefined ? defaultSize.toPrecision(precision) : "1";
1265
1264
  } else if (panelData.length === 1) {
1266
1265
  // Special case: Single panel group should always fill full width/height
1267
1266
  flexGrow = "1";
@@ -168,11 +168,10 @@ function PanelWithForwardedRef({
168
168
  },
169
169
  // CSS selectors
170
170
  "data-panel": "",
171
- "data-panel-id": panelId,
171
+ "data-panel-collapsible": collapsible || undefined,
172
172
  "data-panel-group-id": groupId,
173
- // e2e test attributes
174
- "data-panel-collapsible": collapsible || undefined ,
175
- "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
173
+ "data-panel-id": panelId,
174
+ "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
176
175
  });
177
176
  }
178
177
  const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
@@ -1237,7 +1236,7 @@ function computePanelFlexBoxStyle({
1237
1236
  if (size == null) {
1238
1237
  // Initial render (before panels have registered themselves)
1239
1238
  // In order to support server rendering, fall back to default size if provided
1240
- flexGrow = defaultSize !== null && defaultSize !== void 0 ? defaultSize : "1";
1239
+ flexGrow = defaultSize != undefined ? defaultSize.toPrecision(precision) : "1";
1241
1240
  } else if (panelData.length === 1) {
1242
1241
  // Special case: Single panel group should always fill full width/height
1243
1242
  flexGrow = "1";
@@ -162,11 +162,10 @@ function PanelWithForwardedRef({
162
162
  },
163
163
  // CSS selectors
164
164
  "data-panel": "",
165
- "data-panel-id": panelId,
165
+ "data-panel-collapsible": collapsible || undefined,
166
166
  "data-panel-group-id": groupId,
167
- // e2e test attributes
168
- "data-panel-collapsible": undefined,
169
- "data-panel-size": undefined
167
+ "data-panel-id": panelId,
168
+ "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
170
169
  });
171
170
  }
172
171
  const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
@@ -1221,7 +1220,7 @@ function computePanelFlexBoxStyle({
1221
1220
  if (size == null) {
1222
1221
  // Initial render (before panels have registered themselves)
1223
1222
  // In order to support server rendering, fall back to default size if provided
1224
- flexGrow = defaultSize !== null && defaultSize !== void 0 ? defaultSize : "1";
1223
+ flexGrow = defaultSize != undefined ? defaultSize.toPrecision(precision) : "1";
1225
1224
  } else if (panelData.length === 1) {
1226
1225
  // Special case: Single panel group should always fill full width/height
1227
1226
  flexGrow = "1";
@@ -188,11 +188,10 @@ function PanelWithForwardedRef({
188
188
  },
189
189
  // CSS selectors
190
190
  "data-panel": "",
191
- "data-panel-id": panelId,
191
+ "data-panel-collapsible": collapsible || undefined,
192
192
  "data-panel-group-id": groupId,
193
- // e2e test attributes
194
- "data-panel-collapsible": undefined,
195
- "data-panel-size": undefined
193
+ "data-panel-id": panelId,
194
+ "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
196
195
  });
197
196
  }
198
197
  const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
@@ -1247,7 +1246,7 @@ function computePanelFlexBoxStyle({
1247
1246
  if (size == null) {
1248
1247
  // Initial render (before panels have registered themselves)
1249
1248
  // In order to support server rendering, fall back to default size if provided
1250
- flexGrow = defaultSize !== null && defaultSize !== void 0 ? defaultSize : "1";
1249
+ flexGrow = defaultSize != undefined ? defaultSize.toPrecision(precision) : "1";
1251
1250
  } else if (panelData.length === 1) {
1252
1251
  // Special case: Single panel group should always fill full width/height
1253
1252
  flexGrow = "1";
@@ -199,11 +199,10 @@ function PanelWithForwardedRef({
199
199
  },
200
200
  // CSS selectors
201
201
  "data-panel": "",
202
- "data-panel-id": panelId,
202
+ "data-panel-collapsible": collapsible || undefined,
203
203
  "data-panel-group-id": groupId,
204
- // e2e test attributes
205
- "data-panel-collapsible": collapsible || undefined ,
206
- "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
204
+ "data-panel-id": panelId,
205
+ "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
207
206
  });
208
207
  }
209
208
  const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
@@ -1268,7 +1267,7 @@ function computePanelFlexBoxStyle({
1268
1267
  if (size == null) {
1269
1268
  // Initial render (before panels have registered themselves)
1270
1269
  // In order to support server rendering, fall back to default size if provided
1271
- flexGrow = defaultSize !== null && defaultSize !== void 0 ? defaultSize : "1";
1270
+ flexGrow = defaultSize != undefined ? defaultSize.toPrecision(precision) : "1";
1272
1271
  } else if (panelData.length === 1) {
1273
1272
  // Special case: Single panel group should always fill full width/height
1274
1273
  flexGrow = "1";
@@ -175,11 +175,10 @@ function PanelWithForwardedRef({
175
175
  },
176
176
  // CSS selectors
177
177
  "data-panel": "",
178
- "data-panel-id": panelId,
178
+ "data-panel-collapsible": collapsible || undefined,
179
179
  "data-panel-group-id": groupId,
180
- // e2e test attributes
181
- "data-panel-collapsible": collapsible || undefined ,
182
- "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
180
+ "data-panel-id": panelId,
181
+ "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
183
182
  });
184
183
  }
185
184
  const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
@@ -1244,7 +1243,7 @@ function computePanelFlexBoxStyle({
1244
1243
  if (size == null) {
1245
1244
  // Initial render (before panels have registered themselves)
1246
1245
  // In order to support server rendering, fall back to default size if provided
1247
- flexGrow = defaultSize !== null && defaultSize !== void 0 ? defaultSize : "1";
1246
+ flexGrow = defaultSize != undefined ? defaultSize.toPrecision(precision) : "1";
1248
1247
  } else if (panelData.length === 1) {
1249
1248
  // Special case: Single panel group should always fill full width/height
1250
1249
  flexGrow = "1";
@@ -161,11 +161,10 @@ function PanelWithForwardedRef({
161
161
  },
162
162
  // CSS selectors
163
163
  "data-panel": "",
164
- "data-panel-id": panelId,
164
+ "data-panel-collapsible": collapsible || undefined,
165
165
  "data-panel-group-id": groupId,
166
- // e2e test attributes
167
- "data-panel-collapsible": collapsible || undefined ,
168
- "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
166
+ "data-panel-id": panelId,
167
+ "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
169
168
  });
170
169
  }
171
170
  const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
@@ -1106,7 +1105,7 @@ function computePanelFlexBoxStyle({
1106
1105
  if (size == null) {
1107
1106
  // Initial render (before panels have registered themselves)
1108
1107
  // In order to support server rendering, fall back to default size if provided
1109
- flexGrow = defaultSize !== null && defaultSize !== void 0 ? defaultSize : "1";
1108
+ flexGrow = defaultSize != undefined ? defaultSize.toPrecision(precision) : "1";
1110
1109
  } else if (panelData.length === 1) {
1111
1110
  // Special case: Single panel group should always fill full width/height
1112
1111
  flexGrow = "1";
@@ -137,11 +137,10 @@ function PanelWithForwardedRef({
137
137
  },
138
138
  // CSS selectors
139
139
  "data-panel": "",
140
- "data-panel-id": panelId,
140
+ "data-panel-collapsible": collapsible || undefined,
141
141
  "data-panel-group-id": groupId,
142
- // e2e test attributes
143
- "data-panel-collapsible": collapsible || undefined ,
144
- "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
142
+ "data-panel-id": panelId,
143
+ "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
145
144
  });
146
145
  }
147
146
  const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
@@ -1082,7 +1081,7 @@ function computePanelFlexBoxStyle({
1082
1081
  if (size == null) {
1083
1082
  // Initial render (before panels have registered themselves)
1084
1083
  // In order to support server rendering, fall back to default size if provided
1085
- flexGrow = defaultSize !== null && defaultSize !== void 0 ? defaultSize : "1";
1084
+ flexGrow = defaultSize != undefined ? defaultSize.toPrecision(precision) : "1";
1086
1085
  } else if (panelData.length === 1) {
1087
1086
  // Special case: Single panel group should always fill full width/height
1088
1087
  flexGrow = "1";
@@ -164,11 +164,10 @@ function PanelWithForwardedRef({
164
164
  },
165
165
  // CSS selectors
166
166
  "data-panel": "",
167
- "data-panel-id": panelId,
167
+ "data-panel-collapsible": collapsible || undefined,
168
168
  "data-panel-group-id": groupId,
169
- // e2e test attributes
170
- "data-panel-collapsible": undefined,
171
- "data-panel-size": undefined
169
+ "data-panel-id": panelId,
170
+ "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
172
171
  });
173
172
  }
174
173
  const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
@@ -1223,7 +1222,7 @@ function computePanelFlexBoxStyle({
1223
1222
  if (size == null) {
1224
1223
  // Initial render (before panels have registered themselves)
1225
1224
  // In order to support server rendering, fall back to default size if provided
1226
- flexGrow = defaultSize !== null && defaultSize !== void 0 ? defaultSize : "1";
1225
+ flexGrow = defaultSize != undefined ? defaultSize.toPrecision(precision) : "1";
1227
1226
  } else if (panelData.length === 1) {
1228
1227
  // Special case: Single panel group should always fill full width/height
1229
1228
  flexGrow = "1";
@@ -150,11 +150,10 @@ function PanelWithForwardedRef({
150
150
  },
151
151
  // CSS selectors
152
152
  "data-panel": "",
153
- "data-panel-id": panelId,
153
+ "data-panel-collapsible": collapsible || undefined,
154
154
  "data-panel-group-id": groupId,
155
- // e2e test attributes
156
- "data-panel-collapsible": undefined,
157
- "data-panel-size": undefined
155
+ "data-panel-id": panelId,
156
+ "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
158
157
  });
159
158
  }
160
159
  const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
@@ -1095,7 +1094,7 @@ function computePanelFlexBoxStyle({
1095
1094
  if (size == null) {
1096
1095
  // Initial render (before panels have registered themselves)
1097
1096
  // In order to support server rendering, fall back to default size if provided
1098
- flexGrow = defaultSize !== null && defaultSize !== void 0 ? defaultSize : "1";
1097
+ flexGrow = defaultSize != undefined ? defaultSize.toPrecision(precision) : "1";
1099
1098
  } else if (panelData.length === 1) {
1100
1099
  // Special case: Single panel group should always fill full width/height
1101
1100
  flexGrow = "1";
@@ -126,11 +126,10 @@ function PanelWithForwardedRef({
126
126
  },
127
127
  // CSS selectors
128
128
  "data-panel": "",
129
- "data-panel-id": panelId,
129
+ "data-panel-collapsible": collapsible || undefined,
130
130
  "data-panel-group-id": groupId,
131
- // e2e test attributes
132
- "data-panel-collapsible": undefined,
133
- "data-panel-size": undefined
131
+ "data-panel-id": panelId,
132
+ "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
134
133
  });
135
134
  }
136
135
  const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
@@ -1071,7 +1070,7 @@ function computePanelFlexBoxStyle({
1071
1070
  if (size == null) {
1072
1071
  // Initial render (before panels have registered themselves)
1073
1072
  // In order to support server rendering, fall back to default size if provided
1074
- flexGrow = defaultSize !== null && defaultSize !== void 0 ? defaultSize : "1";
1073
+ flexGrow = defaultSize != undefined ? defaultSize.toPrecision(precision) : "1";
1075
1074
  } else if (panelData.length === 1) {
1076
1075
  // Special case: Single panel group should always fill full width/height
1077
1076
  flexGrow = "1";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-resizable-panels",
3
- "version": "2.0.6",
3
+ "version": "2.0.8-rc.1",
4
4
  "description": "React components for resizable panel groups/layouts",
5
5
  "author": "Brian Vaughn <brian.david.vaughn@gmail.com>",
6
6
  "license": "MIT",
package/src/Panel.ts CHANGED
@@ -243,16 +243,10 @@ export function PanelWithForwardedRef({
243
243
 
244
244
  // CSS selectors
245
245
  "data-panel": "",
246
- "data-panel-id": panelId,
246
+ "data-panel-collapsible": collapsible || undefined,
247
247
  "data-panel-group-id": groupId,
248
-
249
- // e2e test attributes
250
- "data-panel-collapsible": isDevelopment
251
- ? collapsible || undefined
252
- : undefined,
253
- "data-panel-size": isDevelopment
254
- ? parseFloat("" + style.flexGrow).toFixed(1)
255
- : undefined,
248
+ "data-panel-id": panelId,
249
+ "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1),
256
250
  });
257
251
  }
258
252
 
@@ -0,0 +1,123 @@
1
+ import { PanelConstraints, PanelData } from "../Panel";
2
+ import { computePanelFlexBoxStyle } from "./computePanelFlexBoxStyle";
3
+
4
+ describe("computePanelFlexBoxStyle", () => {
5
+ function createPanelData(constraints: PanelConstraints = {}): PanelData {
6
+ return {
7
+ callbacks: {},
8
+ constraints,
9
+ id: "fake",
10
+ idIsFromProps: false,
11
+ order: undefined,
12
+ };
13
+ }
14
+
15
+ it("should observe a panel's default size if group layout has not yet been computed", () => {
16
+ expect(
17
+ computePanelFlexBoxStyle({
18
+ defaultSize: 0.1233456789,
19
+ dragState: null,
20
+ layout: [],
21
+ panelData: [
22
+ createPanelData({
23
+ defaultSize: 0.1233456789,
24
+ }),
25
+ createPanelData(),
26
+ ],
27
+ panelIndex: 0,
28
+ precision: 2,
29
+ })
30
+ ).toMatchInlineSnapshot(`
31
+ {
32
+ "flexBasis": 0,
33
+ "flexGrow": "0.12",
34
+ "flexShrink": 1,
35
+ "overflow": "hidden",
36
+ "pointerEvents": undefined,
37
+ }
38
+ `);
39
+ });
40
+
41
+ it("should always fill the full width for single-panel groups", () => {
42
+ expect(
43
+ computePanelFlexBoxStyle({
44
+ defaultSize: undefined,
45
+ dragState: null,
46
+ layout: [],
47
+ panelData: [createPanelData()],
48
+ panelIndex: 0,
49
+ precision: 2,
50
+ })
51
+ ).toMatchInlineSnapshot(`
52
+ {
53
+ "flexBasis": 0,
54
+ "flexGrow": "1",
55
+ "flexShrink": 1,
56
+ "overflow": "hidden",
57
+ "pointerEvents": undefined,
58
+ }
59
+ `);
60
+ });
61
+
62
+ it("should round sizes to avoid floating point precision errors", () => {
63
+ const layout = [0.25435, 0.5758, 0.1698];
64
+ const panelData = [createPanelData(), createPanelData(), createPanelData()];
65
+
66
+ expect(
67
+ computePanelFlexBoxStyle({
68
+ defaultSize: undefined,
69
+ dragState: null,
70
+ layout,
71
+ panelData,
72
+ panelIndex: 0,
73
+ precision: 2,
74
+ })
75
+ ).toMatchInlineSnapshot(`
76
+ {
77
+ "flexBasis": 0,
78
+ "flexGrow": "0.25",
79
+ "flexShrink": 1,
80
+ "overflow": "hidden",
81
+ "pointerEvents": undefined,
82
+ }
83
+ `);
84
+
85
+ expect(
86
+ computePanelFlexBoxStyle({
87
+ defaultSize: undefined,
88
+ dragState: null,
89
+ layout,
90
+ panelData,
91
+ panelIndex: 1,
92
+ precision: 2,
93
+ })
94
+ ).toMatchInlineSnapshot(`
95
+ {
96
+ "flexBasis": 0,
97
+ "flexGrow": "0.58",
98
+ "flexShrink": 1,
99
+ "overflow": "hidden",
100
+ "pointerEvents": undefined,
101
+ }
102
+ `);
103
+
104
+ expect(
105
+ computePanelFlexBoxStyle({
106
+ defaultSize: undefined,
107
+ dragState: null,
108
+ layout,
109
+ panelData,
110
+ panelIndex: 2,
111
+ precision: 2,
112
+ })
113
+ ).toMatchInlineSnapshot(`
114
+ {
115
+ "flexBasis": 0,
116
+ "flexGrow": "0.17",
117
+ "flexShrink": 1,
118
+ "overflow": "hidden",
119
+ "pointerEvents": undefined,
120
+ }
121
+ `);
122
+ });
123
+ });
@@ -26,7 +26,8 @@ export function computePanelFlexBoxStyle({
26
26
  if (size == null) {
27
27
  // Initial render (before panels have registered themselves)
28
28
  // In order to support server rendering, fall back to default size if provided
29
- flexGrow = defaultSize ?? "1";
29
+ flexGrow =
30
+ defaultSize != undefined ? defaultSize.toPrecision(precision) : "1";
30
31
  } else if (panelData.length === 1) {
31
32
  // Special case: Single panel group should always fill full width/height
32
33
  flexGrow = "1";