react-resizable-panels 0.0.63 → 1.0.0-rc.2

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.
Files changed (74) hide show
  1. package/.eslintrc.cjs +1 -0
  2. package/CHANGELOG.md +5 -0
  3. package/dist/declarations/src/Panel.d.ts +19 -34
  4. package/dist/declarations/src/PanelGroup.d.ts +9 -13
  5. package/dist/declarations/src/PanelResizeHandle.d.ts +5 -7
  6. package/dist/declarations/src/index.d.ts +2 -2
  7. package/dist/declarations/src/types.d.ts +0 -7
  8. package/dist/declarations/src/utils/assert.d.ts +1 -0
  9. package/dist/declarations/src/vendor/react.d.ts +2 -2
  10. package/dist/react-resizable-panels.browser.cjs.js +253 -518
  11. package/dist/react-resizable-panels.browser.cjs.mjs +2 -1
  12. package/dist/react-resizable-panels.browser.development.cjs.js +279 -574
  13. package/dist/react-resizable-panels.browser.development.cjs.mjs +2 -1
  14. package/dist/react-resizable-panels.browser.development.esm.js +279 -575
  15. package/dist/react-resizable-panels.browser.esm.js +253 -519
  16. package/dist/react-resizable-panels.cjs.d.ts +88 -1
  17. package/dist/react-resizable-panels.cjs.d.ts.map +1 -1
  18. package/dist/react-resizable-panels.cjs.js +1481 -1983
  19. package/dist/react-resizable-panels.cjs.js.map +1 -1
  20. package/dist/react-resizable-panels.cjs.mjs +2 -1
  21. package/dist/react-resizable-panels.development.cjs.js +281 -576
  22. package/dist/react-resizable-panels.development.cjs.mjs +2 -1
  23. package/dist/react-resizable-panels.development.esm.js +281 -577
  24. package/dist/react-resizable-panels.development.node.cjs.js +267 -502
  25. package/dist/react-resizable-panels.development.node.cjs.mjs +2 -1
  26. package/dist/react-resizable-panels.development.node.esm.js +267 -503
  27. package/dist/react-resizable-panels.esm.js +1476 -1959
  28. package/dist/react-resizable-panels.esm.js.map +1 -1
  29. package/dist/react-resizable-panels.node.cjs.js +239 -444
  30. package/dist/react-resizable-panels.node.cjs.mjs +2 -1
  31. package/dist/react-resizable-panels.node.esm.js +239 -445
  32. package/package.json +1 -1
  33. package/src/Panel.test.tsx +74 -73
  34. package/src/Panel.ts +44 -68
  35. package/src/PanelGroup.test.tsx +43 -42
  36. package/src/PanelGroup.ts +221 -411
  37. package/src/PanelGroupContext.ts +2 -3
  38. package/src/PanelResizeHandle.test.tsx +68 -0
  39. package/src/PanelResizeHandle.ts +31 -22
  40. package/src/hooks/useWindowSplitterBehavior.ts +2 -1
  41. package/src/hooks/useWindowSplitterPanelGroupBehavior.ts +22 -33
  42. package/src/index.ts +4 -3
  43. package/src/types.ts +0 -9
  44. package/src/utils/adjustLayoutByDelta.test.ts +206 -336
  45. package/src/utils/adjustLayoutByDelta.ts +59 -51
  46. package/src/utils/assert.ts +1 -1
  47. package/src/utils/calculateAriaValues.test.ts +6 -11
  48. package/src/utils/calculateAriaValues.ts +7 -29
  49. package/src/utils/calculateDeltaPercentage.ts +8 -15
  50. package/src/utils/calculateDragOffsetPercentage.ts +11 -5
  51. package/src/utils/calculateUnsafeDefaultLayout.test.ts +4 -9
  52. package/src/utils/calculateUnsafeDefaultLayout.ts +13 -18
  53. package/src/utils/callPanelCallbacks.ts +11 -46
  54. package/src/utils/getResizeEventCursorPosition.ts +2 -0
  55. package/src/utils/resizePanel.test.ts +6 -52
  56. package/src/utils/resizePanel.ts +24 -46
  57. package/src/utils/test-utils.ts +6 -7
  58. package/src/utils/validatePanelConstraints.test.ts +12 -65
  59. package/src/utils/validatePanelConstraints.ts +26 -67
  60. package/src/utils/validatePanelGroupLayout.test.ts +27 -142
  61. package/src/utils/validatePanelGroupLayout.ts +17 -13
  62. package/src/vendor/react.ts +2 -0
  63. package/src/utils/computePercentagePanelConstraints.test.ts +0 -98
  64. package/src/utils/computePercentagePanelConstraints.ts +0 -56
  65. package/src/utils/convertPercentageToPixels.test.ts +0 -9
  66. package/src/utils/convertPercentageToPixels.ts +0 -6
  67. package/src/utils/convertPixelConstraintsToPercentages.test.ts +0 -47
  68. package/src/utils/convertPixelConstraintsToPercentages.ts +0 -72
  69. package/src/utils/convertPixelsToPercentage.test.ts +0 -9
  70. package/src/utils/convertPixelsToPercentage.ts +0 -6
  71. package/src/utils/getPercentageSizeFromMixedSizes.test.ts +0 -47
  72. package/src/utils/getPercentageSizeFromMixedSizes.ts +0 -15
  73. package/src/utils/shouldMonitorPixelBasedConstraints.test.ts +0 -23
  74. package/src/utils/shouldMonitorPixelBasedConstraints.ts +0 -13
@@ -43,24 +43,20 @@ function useUniqueId(idFromParams = null) {
43
43
  function PanelWithForwardedRef({
44
44
  children,
45
45
  className: classNameFromProps = "",
46
- collapsedSizePercentage,
47
- collapsedSizePixels,
46
+ collapsedSize,
48
47
  collapsible,
49
- dataAttributes,
50
- defaultSizePercentage,
51
- defaultSizePixels,
48
+ defaultSize,
52
49
  forwardedRef,
53
50
  id: idFromProps,
54
- maxSizePercentage,
55
- maxSizePixels,
56
- minSizePercentage,
57
- minSizePixels,
51
+ maxSize,
52
+ minSize,
58
53
  onCollapse,
59
54
  onExpand,
60
55
  onResize,
61
56
  order,
62
57
  style: styleFromProps,
63
- tagName: Type = "div"
58
+ tagName: Type = "div",
59
+ ...rest
64
60
  }) {
65
61
  const context = useContext(PanelGroupContext);
66
62
  if (context === null) {
@@ -85,15 +81,11 @@ function PanelWithForwardedRef({
85
81
  onResize
86
82
  },
87
83
  constraints: {
88
- collapsedSizePercentage,
89
- collapsedSizePixels,
84
+ collapsedSize,
90
85
  collapsible,
91
- defaultSizePercentage,
92
- defaultSizePixels,
93
- maxSizePercentage,
94
- maxSizePixels,
95
- minSizePercentage,
96
- minSizePixels
86
+ defaultSize,
87
+ maxSize,
88
+ minSize
97
89
  },
98
90
  id: panelId,
99
91
  idIsFromProps: idFromProps !== undefined,
@@ -107,9 +99,9 @@ function PanelWithForwardedRef({
107
99
  // but effects don't run on the server, so we can't do it there
108
100
  {
109
101
  if (!devWarningsRef.current.didLogMissingDefaultSizeWarning) {
110
- if (!isBrowser && defaultSizePercentage == null && defaultSizePixels == null) {
102
+ if (!isBrowser && defaultSize == null) {
111
103
  devWarningsRef.current.didLogMissingDefaultSizeWarning = true;
112
- console.warn(`WARNING: Panel defaultSizePercentage or defaultSizePixels prop recommended to avoid layout shift after server rendering`);
104
+ console.warn(`WARNING: Panel defaultSize prop recommended to avoid layout shift after server rendering`);
113
105
  }
114
106
  }
115
107
  }
@@ -124,15 +116,11 @@ function PanelWithForwardedRef({
124
116
  callbacks.onCollapse = onCollapse;
125
117
  callbacks.onExpand = onExpand;
126
118
  callbacks.onResize = onResize;
127
- constraints.collapsedSizePercentage = collapsedSizePercentage;
128
- constraints.collapsedSizePixels = collapsedSizePixels;
119
+ constraints.collapsedSize = collapsedSize;
129
120
  constraints.collapsible = collapsible;
130
- constraints.defaultSizePercentage = defaultSizePercentage;
131
- constraints.defaultSizePixels = defaultSizePixels;
132
- constraints.maxSizePercentage = maxSizePercentage;
133
- constraints.maxSizePixels = maxSizePixels;
134
- constraints.minSizePercentage = minSizePercentage;
135
- constraints.minSizePixels = minSizePixels;
121
+ constraints.defaultSize = defaultSize;
122
+ constraints.maxSize = maxSize;
123
+ constraints.minSize = minSize;
136
124
  });
137
125
  useIsomorphicLayoutEffect(() => {
138
126
  const panelData = panelDataRef.current;
@@ -160,19 +148,19 @@ function PanelWithForwardedRef({
160
148
  isExpanded() {
161
149
  return !isPanelCollapsed(panelDataRef.current);
162
150
  },
163
- resize: mixedSizes => {
164
- resizePanel(panelDataRef.current, mixedSizes);
151
+ resize: size => {
152
+ resizePanel(panelDataRef.current, size);
165
153
  }
166
154
  }), [collapsePanel, expandPanel, getPanelSize, isPanelCollapsed, panelId, resizePanel]);
167
155
  const style = getPanelStyle(panelDataRef.current);
168
156
  return createElement(Type, {
157
+ ...rest,
169
158
  children,
170
159
  className: classNameFromProps,
171
160
  style: {
172
161
  ...style,
173
162
  ...styleFromProps
174
163
  },
175
- ...dataAttributes,
176
164
  // CSS selectors
177
165
  "data-panel": "",
178
166
  "data-panel-id": panelId,
@@ -189,81 +177,11 @@ const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
189
177
  PanelWithForwardedRef.displayName = "Panel";
190
178
  Panel.displayName = "forwardRef(Panel)";
191
179
 
192
- function convertPixelsToPercentage(pixels, groupSizePixels) {
193
- return pixels / groupSizePixels * 100;
194
- }
195
-
196
- function convertPixelConstraintsToPercentages(panelConstraints, groupSizePixels) {
197
- let {
198
- collapsedSizePercentage = 0,
199
- collapsedSizePixels,
200
- defaultSizePercentage,
201
- defaultSizePixels,
202
- maxSizePercentage = 100,
203
- maxSizePixels,
204
- minSizePercentage = 0,
205
- minSizePixels
206
- } = panelConstraints;
207
- const hasPixelConstraints = collapsedSizePixels != null || defaultSizePixels != null || minSizePixels != null || maxSizePixels != null;
208
- if (hasPixelConstraints && groupSizePixels <= 0) {
209
- console.warn(`WARNING: Invalid group size: ${groupSizePixels}px`);
210
- return {
211
- collapsedSizePercentage: 0,
212
- defaultSizePercentage,
213
- maxSizePercentage: 0,
214
- minSizePercentage: 0
215
- };
216
- }
217
- if (collapsedSizePixels != null) {
218
- collapsedSizePercentage = convertPixelsToPercentage(collapsedSizePixels, groupSizePixels);
219
- }
220
- if (defaultSizePixels != null) {
221
- defaultSizePercentage = convertPixelsToPercentage(defaultSizePixels, groupSizePixels);
222
- }
223
- if (minSizePixels != null) {
224
- minSizePercentage = convertPixelsToPercentage(minSizePixels, groupSizePixels);
225
- }
226
- if (maxSizePixels != null) {
227
- maxSizePercentage = convertPixelsToPercentage(maxSizePixels, groupSizePixels);
228
- }
229
- return {
230
- collapsedSizePercentage,
231
- defaultSizePercentage,
232
- maxSizePercentage,
233
- minSizePercentage
234
- };
235
- }
236
-
237
- function computePercentagePanelConstraints(panelConstraintsArray, panelIndex, groupSizePixels) {
238
- // All panel constraints, excluding the current one
239
- let totalMinConstraints = 0;
240
- let totalMaxConstraints = 0;
241
- for (let index = 0; index < panelConstraintsArray.length; index++) {
242
- if (index !== panelIndex) {
243
- const {
244
- collapsible
245
- } = panelConstraintsArray[index];
246
- const {
247
- collapsedSizePercentage,
248
- maxSizePercentage,
249
- minSizePercentage
250
- } = convertPixelConstraintsToPercentages(panelConstraintsArray[index], groupSizePixels);
251
- totalMaxConstraints += maxSizePercentage;
252
- totalMinConstraints += collapsible ? collapsedSizePercentage : minSizePercentage;
253
- }
180
+ function assert(expectedCondition, message = "Assertion failed!") {
181
+ if (!expectedCondition) {
182
+ console.error(message);
183
+ throw Error(message);
254
184
  }
255
- const {
256
- collapsedSizePercentage,
257
- defaultSizePercentage,
258
- maxSizePercentage,
259
- minSizePercentage
260
- } = convertPixelConstraintsToPercentages(panelConstraintsArray[panelIndex], groupSizePixels);
261
- return {
262
- collapsedSizePercentage,
263
- defaultSizePercentage,
264
- maxSizePercentage: panelConstraintsArray.length > 1 ? Math.min(maxSizePercentage, 100 - totalMinConstraints) : maxSizePercentage,
265
- minSizePercentage: panelConstraintsArray.length > 1 ? Math.max(minSizePercentage, 100 - totalMaxConstraints) : minSizePercentage
266
- };
267
185
  }
268
186
 
269
187
  const PRECISION = 10;
@@ -285,56 +203,41 @@ function fuzzyNumbersEqual(actual, expected, fractionDigits) {
285
203
 
286
204
  // Panel size must be in percentages; pixel values should be pre-converted
287
205
  function resizePanel({
288
- groupSizePixels,
289
- panelConstraints,
206
+ panelConstraints: panelConstraintsArray,
290
207
  panelIndex,
291
208
  size
292
209
  }) {
293
- const hasPixelConstraints = panelConstraints.some(({
294
- collapsedSizePixels,
295
- defaultSizePixels,
296
- minSizePixels,
297
- maxSizePixels
298
- }) => collapsedSizePixels != null || defaultSizePixels != null || minSizePixels != null || maxSizePixels != null);
299
- if (hasPixelConstraints && groupSizePixels <= 0) {
300
- console.warn(`WARNING: Invalid group size: ${groupSizePixels}px`);
301
- return 0;
302
- }
210
+ const panelConstraints = panelConstraintsArray[panelIndex];
211
+ assert(panelConstraints != null);
303
212
  let {
304
- collapsible
305
- } = panelConstraints[panelIndex];
306
- const {
307
- collapsedSizePercentage,
308
- maxSizePercentage,
309
- minSizePercentage
310
- } = computePercentagePanelConstraints(panelConstraints, panelIndex, groupSizePixels);
311
- if (minSizePercentage != null) {
312
- if (fuzzyCompareNumbers(size, minSizePercentage) < 0) {
313
- if (collapsible) {
314
- // Collapsible panels should snap closed or open only once they cross the halfway point between collapsed and min size.
315
- const halfwayPoint = (collapsedSizePercentage + minSizePercentage) / 2;
316
- if (fuzzyCompareNumbers(size, halfwayPoint) < 0) {
317
- size = collapsedSizePercentage;
318
- } else {
319
- size = minSizePercentage;
320
- }
213
+ collapsedSize = 0,
214
+ collapsible,
215
+ maxSize = 100,
216
+ minSize = 0
217
+ } = panelConstraints;
218
+ if (fuzzyCompareNumbers(size, minSize) < 0) {
219
+ if (collapsible) {
220
+ // Collapsible panels should snap closed or open only once they cross the halfway point between collapsed and min size.
221
+ const halfwayPoint = (collapsedSize + minSize) / 2;
222
+ if (fuzzyCompareNumbers(size, halfwayPoint) < 0) {
223
+ size = collapsedSize;
321
224
  } else {
322
- size = minSizePercentage;
225
+ size = minSize;
323
226
  }
227
+ } else {
228
+ size = minSize;
324
229
  }
325
230
  }
326
- if (maxSizePercentage != null) {
327
- size = Math.min(maxSizePercentage, size);
328
- }
231
+ size = Math.min(maxSize, size);
232
+ size = parseFloat(size.toFixed(PRECISION));
329
233
  return size;
330
234
  }
331
235
 
332
236
  // All units must be in percentages; pixel values should be pre-converted
333
237
  function adjustLayoutByDelta({
334
238
  delta,
335
- groupSizePixels,
336
239
  layout: prevLayout,
337
- panelConstraints,
240
+ panelConstraints: panelConstraintsArray,
338
241
  pivotIndices,
339
242
  trigger
340
243
  }) {
@@ -342,6 +245,9 @@ function adjustLayoutByDelta({
342
245
  return prevLayout;
343
246
  }
344
247
  const nextLayout = [...prevLayout];
248
+ const [firstPivotIndex, secondPivotIndex] = pivotIndices;
249
+ assert(firstPivotIndex != null);
250
+ assert(secondPivotIndex != null);
345
251
  let deltaApplied = 0;
346
252
 
347
253
  //const DEBUG = [];
@@ -365,18 +271,23 @@ function adjustLayoutByDelta({
365
271
  if (trigger === "keyboard") {
366
272
  {
367
273
  // Check if we should expand a collapsed panel
368
- const index = delta < 0 ? pivotIndices[1] : pivotIndices[0];
369
- const constraints = panelConstraints[index];
274
+ const index = delta < 0 ? secondPivotIndex : firstPivotIndex;
275
+ const panelConstraints = panelConstraintsArray[index];
276
+ assert(panelConstraints);
277
+
370
278
  //DEBUG.push(`edge case check 1: ${index}`);
371
279
  //DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
372
- if (constraints.collapsible) {
280
+ if (panelConstraints.collapsible) {
373
281
  const prevSize = prevLayout[index];
282
+ assert(prevSize != null);
283
+ const panelConstraints = panelConstraintsArray[index];
284
+ assert(panelConstraints);
374
285
  const {
375
- collapsedSizePercentage,
376
- minSizePercentage
377
- } = computePercentagePanelConstraints(panelConstraints, index, groupSizePixels);
378
- if (fuzzyNumbersEqual(prevSize, collapsedSizePercentage)) {
379
- const localDelta = minSizePercentage - prevSize;
286
+ collapsedSize = 0,
287
+ minSize = 0
288
+ } = panelConstraints;
289
+ if (fuzzyNumbersEqual(prevSize, collapsedSize)) {
290
+ const localDelta = minSize - prevSize;
380
291
  //DEBUG.push(` -> expand delta: ${localDelta}`);
381
292
 
382
293
  if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
@@ -389,18 +300,26 @@ function adjustLayoutByDelta({
389
300
 
390
301
  {
391
302
  // Check if we should collapse a panel at its minimum size
392
- const index = delta < 0 ? pivotIndices[0] : pivotIndices[1];
393
- const constraints = panelConstraints[index];
303
+ const index = delta < 0 ? firstPivotIndex : secondPivotIndex;
304
+ const panelConstraints = panelConstraintsArray[index];
305
+ assert(panelConstraints);
306
+ const {
307
+ collapsible
308
+ } = panelConstraints;
309
+
394
310
  //DEBUG.push(`edge case check 2: ${index}`);
395
- //DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
396
- if (constraints.collapsible) {
311
+ //DEBUG.push(` -> collapsible? ${collapsible}`);
312
+ if (collapsible) {
397
313
  const prevSize = prevLayout[index];
314
+ assert(prevSize != null);
315
+ const panelConstraints = panelConstraintsArray[index];
316
+ assert(panelConstraints);
398
317
  const {
399
- collapsedSizePercentage,
400
- minSizePercentage
401
- } = computePercentagePanelConstraints(panelConstraints, index, groupSizePixels);
402
- if (fuzzyNumbersEqual(prevSize, minSizePercentage)) {
403
- const localDelta = prevSize - collapsedSizePercentage;
318
+ collapsedSize = 0,
319
+ minSize = 0
320
+ } = panelConstraints;
321
+ if (fuzzyNumbersEqual(prevSize, minSize)) {
322
+ const localDelta = prevSize - collapsedSize;
404
323
  //DEBUG.push(` -> expand delta: ${localDelta}`);
405
324
 
406
325
  if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
@@ -422,15 +341,15 @@ function adjustLayoutByDelta({
422
341
  // as an expanding panel might change from collapsed to min size.
423
342
 
424
343
  const increment = delta < 0 ? 1 : -1;
425
- let index = delta < 0 ? pivotIndices[1] : pivotIndices[0];
344
+ let index = delta < 0 ? secondPivotIndex : firstPivotIndex;
426
345
  let maxAvailableDelta = 0;
427
346
 
428
347
  //DEBUG.push("pre calc...");
429
348
  while (true) {
430
349
  const prevSize = prevLayout[index];
350
+ assert(prevSize != null);
431
351
  const maxSafeSize = resizePanel({
432
- groupSizePixels,
433
- panelConstraints,
352
+ panelConstraints: panelConstraintsArray,
434
353
  panelIndex: index,
435
354
  size: 100
436
355
  });
@@ -439,7 +358,7 @@ function adjustLayoutByDelta({
439
358
 
440
359
  maxAvailableDelta += delta;
441
360
  index += increment;
442
- if (index < 0 || index >= panelConstraints.length) {
361
+ if (index < 0 || index >= panelConstraintsArray.length) {
443
362
  break;
444
363
  }
445
364
  }
@@ -454,15 +373,15 @@ function adjustLayoutByDelta({
454
373
  {
455
374
  // Delta added to a panel needs to be subtracted from other panels (within the constraints that those panels allow).
456
375
 
457
- const pivotIndex = delta < 0 ? pivotIndices[0] : pivotIndices[1];
376
+ const pivotIndex = delta < 0 ? firstPivotIndex : secondPivotIndex;
458
377
  let index = pivotIndex;
459
- while (index >= 0 && index < panelConstraints.length) {
378
+ while (index >= 0 && index < panelConstraintsArray.length) {
460
379
  const deltaRemaining = Math.abs(delta) - Math.abs(deltaApplied);
461
380
  const prevSize = prevLayout[index];
381
+ assert(prevSize != null);
462
382
  const unsafeSize = prevSize - deltaRemaining;
463
383
  const safeSize = resizePanel({
464
- groupSizePixels,
465
- panelConstraints,
384
+ panelConstraints: panelConstraintsArray,
466
385
  panelIndex: index,
467
386
  size: unsafeSize
468
387
  });
@@ -494,11 +413,12 @@ function adjustLayoutByDelta({
494
413
  }
495
414
  {
496
415
  // Now distribute the applied delta to the panels in the other direction
497
- const pivotIndex = delta < 0 ? pivotIndices[1] : pivotIndices[0];
498
- const unsafeSize = prevLayout[pivotIndex] + deltaApplied;
416
+ const pivotIndex = delta < 0 ? secondPivotIndex : firstPivotIndex;
417
+ const prevSize = prevLayout[pivotIndex];
418
+ assert(prevSize != null);
419
+ const unsafeSize = prevSize + deltaApplied;
499
420
  const safeSize = resizePanel({
500
- groupSizePixels,
501
- panelConstraints,
421
+ panelConstraints: panelConstraintsArray,
502
422
  panelIndex: pivotIndex,
503
423
  size: unsafeSize
504
424
  });
@@ -509,14 +429,14 @@ function adjustLayoutByDelta({
509
429
  // Edge case where expanding or contracting one panel caused another one to change collapsed state
510
430
  if (!fuzzyNumbersEqual(safeSize, unsafeSize)) {
511
431
  let deltaRemaining = unsafeSize - safeSize;
512
- const pivotIndex = delta < 0 ? pivotIndices[1] : pivotIndices[0];
432
+ const pivotIndex = delta < 0 ? secondPivotIndex : firstPivotIndex;
513
433
  let index = pivotIndex;
514
- while (index >= 0 && index < panelConstraints.length) {
434
+ while (index >= 0 && index < panelConstraintsArray.length) {
515
435
  const prevSize = nextLayout[index];
436
+ assert(prevSize != null);
516
437
  const unsafeSize = prevSize + deltaRemaining;
517
438
  const safeSize = resizePanel({
518
- groupSizePixels,
519
- panelConstraints,
439
+ panelConstraints: panelConstraintsArray,
520
440
  panelIndex: index,
521
441
  size: unsafeSize
522
442
  });
@@ -540,9 +460,7 @@ function adjustLayoutByDelta({
540
460
  //DEBUG.push("");
541
461
 
542
462
  const totalSize = nextLayout.reduce((total, size) => size + total, 0);
543
- deltaApplied = 100 - totalSize;
544
463
  //DEBUG.push(`total size: ${totalSize}`);
545
- //DEBUG.push(` deltaApplied: ${deltaApplied}`);
546
464
  //console.log(DEBUG.join("\n"));
547
465
 
548
466
  if (!fuzzyNumbersEqual(totalSize, 100)) {
@@ -551,27 +469,7 @@ function adjustLayoutByDelta({
551
469
  return nextLayout;
552
470
  }
553
471
 
554
- function assert(expectedCondition, message = "Assertion failed!") {
555
- if (!expectedCondition) {
556
- console.error(message);
557
- throw Error(message);
558
- }
559
- }
560
-
561
- function getPercentageSizeFromMixedSizes({
562
- sizePercentage,
563
- sizePixels
564
- }, groupSizePixels) {
565
- if (sizePercentage != null) {
566
- return sizePercentage;
567
- } else if (sizePixels != null) {
568
- return convertPixelsToPercentage(sizePixels, groupSizePixels);
569
- }
570
- return undefined;
571
- }
572
-
573
472
  function calculateAriaValues({
574
- groupSizePixels,
575
473
  layout,
576
474
  panelsArray,
577
475
  pivotIndices
@@ -580,28 +478,19 @@ function calculateAriaValues({
580
478
  let currentMaxSize = 100;
581
479
  let totalMinSize = 0;
582
480
  let totalMaxSize = 0;
481
+ const firstIndex = pivotIndices[0];
482
+ assert(firstIndex != null);
583
483
 
584
484
  // A panel's effective min/max sizes also need to account for other panel's sizes.
585
485
  panelsArray.forEach((panelData, index) => {
586
- var _getPercentageSizeFro, _getPercentageSizeFro2;
587
486
  const {
588
487
  constraints
589
488
  } = panelData;
590
489
  const {
591
- maxSizePercentage,
592
- maxSizePixels,
593
- minSizePercentage,
594
- minSizePixels
490
+ maxSize = 100,
491
+ minSize = 0
595
492
  } = constraints;
596
- const minSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
597
- sizePercentage: minSizePercentage,
598
- sizePixels: minSizePixels
599
- }, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
600
- const maxSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
601
- sizePercentage: maxSizePercentage,
602
- sizePixels: maxSizePixels
603
- }, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 100;
604
- if (index === pivotIndices[0]) {
493
+ if (index === firstIndex) {
605
494
  currentMinSize = minSize;
606
495
  currentMaxSize = maxSize;
607
496
  } else {
@@ -611,7 +500,7 @@ function calculateAriaValues({
611
500
  });
612
501
  const valueMax = Math.min(currentMaxSize, 100 - totalMinSize);
613
502
  const valueMin = Math.max(currentMinSize, 100 - totalMaxSize);
614
- const valueNow = layout[pivotIndices[0]];
503
+ const valueNow = layout[firstIndex];
615
504
  return {
616
505
  valueMax,
617
506
  valueMin,
@@ -642,42 +531,6 @@ function getPanelGroupElement(id) {
642
531
  return null;
643
532
  }
644
533
 
645
- function calculateAvailablePanelSizeInPixels(groupId) {
646
- const panelGroupElement = getPanelGroupElement(groupId);
647
- if (panelGroupElement == null) {
648
- return NaN;
649
- }
650
- const direction = panelGroupElement.getAttribute("data-panel-group-direction");
651
- const resizeHandles = getResizeHandleElementsForGroup(groupId);
652
- if (direction === "horizontal") {
653
- return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
654
- return accumulated + handle.offsetWidth;
655
- }, 0);
656
- } else {
657
- return panelGroupElement.offsetHeight - resizeHandles.reduce((accumulated, handle) => {
658
- return accumulated + handle.offsetHeight;
659
- }, 0);
660
- }
661
- }
662
-
663
- function getAvailableGroupSizePixels(groupId) {
664
- const panelGroupElement = getPanelGroupElement(groupId);
665
- if (panelGroupElement == null) {
666
- return NaN;
667
- }
668
- const direction = panelGroupElement.getAttribute("data-panel-group-direction");
669
- const resizeHandles = getResizeHandleElementsForGroup(groupId);
670
- if (direction === "horizontal") {
671
- return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
672
- return accumulated + handle.offsetWidth;
673
- }, 0);
674
- } else {
675
- return panelGroupElement.offsetHeight - resizeHandles.reduce((accumulated, handle) => {
676
- return accumulated + handle.offsetHeight;
677
- }, 0);
678
- }
679
- }
680
-
681
534
  function getResizeHandleElement(id) {
682
535
  const element = document.querySelector(`[data-panel-resize-handle-id="${id}"]`);
683
536
  if (element) {
@@ -710,7 +563,6 @@ function useWindowSplitterPanelGroupBehavior({
710
563
  didWarnAboutMissingResizeHandle: false
711
564
  });
712
565
  useIsomorphicLayoutEffect(() => {
713
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
714
566
  const resizeHandleElements = getResizeHandleElementsForGroup(groupId);
715
567
  for (let index = 0; index < panelDataArray.length - 1; index++) {
716
568
  const {
@@ -718,7 +570,6 @@ function useWindowSplitterPanelGroupBehavior({
718
570
  valueMin,
719
571
  valueNow
720
572
  } = calculateAriaValues({
721
- groupSizePixels,
722
573
  layout,
723
574
  panelsArray: panelDataArray,
724
575
  pivotIndices: [index, index + 1]
@@ -735,10 +586,12 @@ function useWindowSplitterPanelGroupBehavior({
735
586
  }
736
587
  }
737
588
  } else {
738
- resizeHandleElement.setAttribute("aria-controls", panelDataArray[index].id);
589
+ const panelData = panelDataArray[index];
590
+ assert(panelData);
591
+ resizeHandleElement.setAttribute("aria-controls", panelData.id);
739
592
  resizeHandleElement.setAttribute("aria-valuemax", "" + Math.round(valueMax));
740
593
  resizeHandleElement.setAttribute("aria-valuemin", "" + Math.round(valueMin));
741
- resizeHandleElement.setAttribute("aria-valuenow", "" + Math.round(valueNow));
594
+ resizeHandleElement.setAttribute("aria-valuenow", valueNow != null ? "" + Math.round(valueNow) : "");
742
595
  }
743
596
  }
744
597
  return () => {
@@ -751,14 +604,18 @@ function useWindowSplitterPanelGroupBehavior({
751
604
  };
752
605
  }, [groupId, layout, panelDataArray]);
753
606
  useEffect(() => {
607
+ const eagerValues = eagerValuesRef.current;
608
+ assert(eagerValues);
754
609
  const {
755
610
  panelDataArray
756
- } = eagerValuesRef.current;
611
+ } = eagerValues;
757
612
  const groupElement = getPanelGroupElement(groupId);
758
613
  assert(groupElement != null, `No group found for id "${groupId}"`);
759
614
  const handles = getResizeHandleElementsForGroup(groupId);
615
+ assert(handles);
760
616
  const cleanupFunctions = handles.map(handle => {
761
617
  const handleId = handle.getAttribute("data-panel-resize-handle-id");
618
+ assert(handleId);
762
619
  const [idBefore, idAfter] = getResizeHandlePanelIds(groupId, handleId, panelDataArray);
763
620
  if (idBefore == null || idAfter == null) {
764
621
  return () => {};
@@ -774,21 +631,16 @@ function useWindowSplitterPanelGroupBehavior({
774
631
  const index = panelDataArray.findIndex(panelData => panelData.id === idBefore);
775
632
  if (index >= 0) {
776
633
  const panelData = panelDataArray[index];
634
+ assert(panelData);
777
635
  const size = layout[index];
778
- if (size != null && panelData.constraints.collapsible) {
779
- var _getPercentageSizeFro, _getPercentageSizeFro2;
780
- const groupSizePixels = getAvailableGroupSizePixels(groupId);
781
- const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
782
- sizePercentage: panelData.constraints.collapsedSizePercentage,
783
- sizePixels: panelData.constraints.collapsedSizePixels
784
- }, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
785
- const minSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
786
- sizePercentage: panelData.constraints.minSizePercentage,
787
- sizePixels: panelData.constraints.minSizePixels
788
- }, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 0;
636
+ const {
637
+ collapsedSize = 0,
638
+ collapsible,
639
+ minSize = 0
640
+ } = panelData.constraints;
641
+ if (size != null && collapsible) {
789
642
  const nextLayout = adjustLayoutByDelta({
790
643
  delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
791
- groupSizePixels,
792
644
  layout,
793
645
  panelConstraints: panelDataArray.map(panelData => panelData.constraints),
794
646
  pivotIndices: determinePivotIndices(groupId, handleId),
@@ -842,6 +694,7 @@ function getResizeEventCursorPosition(direction, event) {
842
694
  return isHorizontal ? event.clientX : event.clientY;
843
695
  } else if (isTouchEvent(event)) {
844
696
  const firstTouch = event.touches[0];
697
+ assert(firstTouch);
845
698
  return isHorizontal ? firstTouch.screenX : firstTouch.screenY;
846
699
  } else {
847
700
  throw Error(`Unsupported event type "${event.type}"`);
@@ -851,12 +704,15 @@ function getResizeEventCursorPosition(direction, event) {
851
704
  function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState) {
852
705
  const isHorizontal = direction === "horizontal";
853
706
  const handleElement = getResizeHandleElement(dragHandleId);
707
+ assert(handleElement);
854
708
  const groupId = handleElement.getAttribute("data-panel-group-id");
709
+ assert(groupId);
855
710
  let {
856
711
  initialCursorPosition
857
712
  } = initialDragState;
858
713
  const cursorPosition = getResizeEventCursorPosition(direction, event);
859
714
  const groupElement = getPanelGroupElement(groupId);
715
+ assert(groupElement);
860
716
  const groupRect = groupElement.getBoundingClientRect();
861
717
  const groupSizeInPixels = isHorizontal ? groupRect.width : groupRect.height;
862
718
  const offsetPixels = cursorPosition - initialCursorPosition;
@@ -865,19 +721,14 @@ function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDr
865
721
  }
866
722
 
867
723
  // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/movementX
868
- function calculateDeltaPercentage(event, groupId, dragHandleId, direction, initialDragState, keyboardResizeByOptions) {
724
+ function calculateDeltaPercentage(event, dragHandleId, direction, initialDragState, keyboardResizeBy) {
869
725
  if (isKeyDown(event)) {
870
726
  const isHorizontal = direction === "horizontal";
871
- const groupElement = getPanelGroupElement(groupId);
872
- const rect = groupElement.getBoundingClientRect();
873
- const groupSizeInPixels = isHorizontal ? rect.width : rect.height;
874
727
  let delta = 0;
875
728
  if (event.shiftKey) {
876
729
  delta = 100;
877
- } else if (keyboardResizeByOptions.percentage != null) {
878
- delta = keyboardResizeByOptions.percentage;
879
- } else if (keyboardResizeByOptions.pixels != null) {
880
- delta = keyboardResizeByOptions.pixels / groupSizeInPixels;
730
+ } else if (keyboardResizeBy != null) {
731
+ delta = keyboardResizeBy;
881
732
  } else {
882
733
  delta = 10;
883
734
  }
@@ -904,37 +755,43 @@ function calculateDeltaPercentage(event, groupId, dragHandleId, direction, initi
904
755
  }
905
756
  return movement;
906
757
  } else {
758
+ if (initialDragState == null) {
759
+ return 0;
760
+ }
907
761
  return calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState);
908
762
  }
909
763
  }
910
764
 
911
765
  function calculateUnsafeDefaultLayout({
912
- groupSizePixels,
913
766
  panelDataArray
914
767
  }) {
915
768
  const layout = Array(panelDataArray.length);
916
- const panelDataConstraints = panelDataArray.map(panelData => panelData.constraints);
769
+ const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
917
770
  let numPanelsWithSizes = 0;
918
771
  let remainingSize = 100;
919
772
 
920
773
  // Distribute default sizes first
921
774
  for (let index = 0; index < panelDataArray.length; index++) {
775
+ const panelConstraints = panelConstraintsArray[index];
776
+ assert(panelConstraints);
922
777
  const {
923
- defaultSizePercentage
924
- } = computePercentagePanelConstraints(panelDataConstraints, index, groupSizePixels);
925
- if (defaultSizePercentage != null) {
778
+ defaultSize
779
+ } = panelConstraints;
780
+ if (defaultSize != null) {
926
781
  numPanelsWithSizes++;
927
- layout[index] = defaultSizePercentage;
928
- remainingSize -= defaultSizePercentage;
782
+ layout[index] = defaultSize;
783
+ remainingSize -= defaultSize;
929
784
  }
930
785
  }
931
786
 
932
787
  // Remaining size should be distributed evenly between panels without default sizes
933
788
  for (let index = 0; index < panelDataArray.length; index++) {
789
+ const panelConstraints = panelConstraintsArray[index];
790
+ assert(panelConstraints);
934
791
  const {
935
- defaultSizePercentage
936
- } = computePercentagePanelConstraints(panelDataConstraints, index, groupSizePixels);
937
- if (defaultSizePercentage != null) {
792
+ defaultSize
793
+ } = panelConstraints;
794
+ if (defaultSize != null) {
938
795
  continue;
939
796
  }
940
797
  const numRemainingPanels = panelDataArray.length - numPanelsWithSizes;
@@ -946,54 +803,36 @@ function calculateUnsafeDefaultLayout({
946
803
  return layout;
947
804
  }
948
805
 
949
- function convertPercentageToPixels(percentage, groupSizePixels) {
950
- return percentage / 100 * groupSizePixels;
951
- }
952
-
953
806
  // Layout should be pre-converted into percentages
954
- function callPanelCallbacks(groupId, panelsArray, layout, panelIdToLastNotifiedMixedSizesMap) {
955
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
956
- layout.forEach((sizePercentage, index) => {
807
+ function callPanelCallbacks(panelsArray, layout, panelIdToLastNotifiedSizeMap) {
808
+ layout.forEach((size, index) => {
957
809
  const panelData = panelsArray[index];
958
- if (!panelData) {
959
- // Handle initial mount (when panels are registered too late to be in the panels array)
960
- // The subsequent render+effects will handle the resize notification
961
- return;
962
- }
810
+ assert(panelData);
963
811
  const {
964
812
  callbacks,
965
813
  constraints,
966
814
  id: panelId
967
815
  } = panelData;
968
816
  const {
817
+ collapsedSize = 0,
969
818
  collapsible
970
819
  } = constraints;
971
- const mixedSizes = {
972
- sizePercentage,
973
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
974
- };
975
- const lastNotifiedMixedSizes = panelIdToLastNotifiedMixedSizesMap[panelId];
976
- if (lastNotifiedMixedSizes == null || mixedSizes.sizePercentage !== lastNotifiedMixedSizes.sizePercentage || mixedSizes.sizePixels !== lastNotifiedMixedSizes.sizePixels) {
977
- panelIdToLastNotifiedMixedSizesMap[panelId] = mixedSizes;
820
+ const lastNotifiedSize = panelIdToLastNotifiedSizeMap[panelId];
821
+ if (lastNotifiedSize == null || size !== lastNotifiedSize) {
822
+ panelIdToLastNotifiedSizeMap[panelId] = size;
978
823
  const {
979
824
  onCollapse,
980
825
  onExpand,
981
826
  onResize
982
827
  } = callbacks;
983
828
  if (onResize) {
984
- onResize(mixedSizes, lastNotifiedMixedSizes);
829
+ onResize(size, lastNotifiedSize);
985
830
  }
986
831
  if (collapsible && (onCollapse || onExpand)) {
987
- var _getPercentageSizeFro;
988
- const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
989
- sizePercentage: constraints.collapsedSizePercentage,
990
- sizePixels: constraints.collapsedSizePixels
991
- }, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
992
- const size = getPercentageSizeFromMixedSizes(mixedSizes, groupSizePixels);
993
- if (onExpand && (lastNotifiedMixedSizes == null || lastNotifiedMixedSizes.sizePercentage === collapsedSize) && size !== collapsedSize) {
832
+ if (onExpand && (lastNotifiedSize == null || lastNotifiedSize === collapsedSize) && size !== collapsedSize) {
994
833
  onExpand();
995
834
  }
996
- if (onCollapse && (lastNotifiedMixedSizes == null || lastNotifiedMixedSizes.sizePercentage !== collapsedSize) && size === collapsedSize) {
835
+ if (onCollapse && (lastNotifiedSize == null || lastNotifiedSize !== collapsedSize) && size === collapsedSize) {
997
836
  onCollapse();
998
837
  }
999
838
  }
@@ -1176,74 +1015,39 @@ function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
1176
1015
  }
1177
1016
  }
1178
1017
 
1179
- function shouldMonitorPixelBasedConstraints(constraints) {
1180
- return constraints.some(constraints => {
1181
- return constraints.collapsedSizePixels !== undefined || constraints.maxSizePixels !== undefined || constraints.minSizePixels !== undefined;
1182
- });
1183
- }
1184
-
1185
1018
  function validatePanelConstraints({
1186
- groupSizePixels,
1187
- panelConstraints,
1019
+ panelConstraints: panelConstraintsArray,
1188
1020
  panelId,
1189
1021
  panelIndex
1190
1022
  }) {
1191
1023
  {
1192
1024
  const warnings = [];
1193
- {
1194
- const {
1195
- collapsedSizePercentage,
1196
- collapsedSizePixels,
1197
- defaultSizePercentage,
1198
- defaultSizePixels,
1199
- maxSizePercentage,
1200
- maxSizePixels,
1201
- minSizePercentage,
1202
- minSizePixels
1203
- } = panelConstraints[panelIndex];
1204
- const conflictingUnits = [];
1205
- if (collapsedSizePercentage != null && collapsedSizePixels != null) {
1206
- conflictingUnits.push("collapsed size");
1207
- }
1208
- if (defaultSizePercentage != null && defaultSizePixels != null) {
1209
- conflictingUnits.push("default size");
1210
- }
1211
- if (maxSizePercentage != null && maxSizePixels != null) {
1212
- conflictingUnits.push("max size");
1213
- }
1214
- if (minSizePercentage != null && minSizePixels != null) {
1215
- conflictingUnits.push("min size");
1216
- }
1217
- if (conflictingUnits.length > 0) {
1218
- warnings.push(`should not specify both percentage and pixel units for: ${conflictingUnits.join(", ")}`);
1219
- }
1025
+ const panelConstraints = panelConstraintsArray[panelIndex];
1026
+ assert(panelConstraints);
1027
+ const {
1028
+ collapsedSize = 0,
1029
+ defaultSize,
1030
+ maxSize = 100,
1031
+ minSize = 0
1032
+ } = panelConstraints;
1033
+ if (minSize > maxSize) {
1034
+ warnings.push(`min size (${minSize}%) should not be greater than max size (${maxSize}%)`);
1220
1035
  }
1221
- {
1222
- const {
1223
- collapsedSizePercentage,
1224
- defaultSizePercentage,
1225
- maxSizePercentage,
1226
- minSizePercentage
1227
- } = computePercentagePanelConstraints(panelConstraints, panelIndex, groupSizePixels);
1228
- if (minSizePercentage > maxSizePercentage) {
1229
- warnings.push(`min size (${minSizePercentage}%) should not be greater than max size (${maxSizePercentage}%)`);
1230
- }
1231
- if (defaultSizePercentage != null) {
1232
- if (defaultSizePercentage < 0) {
1233
- warnings.push("default size should not be less than 0");
1234
- } else if (defaultSizePercentage < minSizePercentage) {
1235
- warnings.push("default size should not be less than min size");
1236
- }
1237
- if (defaultSizePercentage > 100) {
1238
- warnings.push("default size should not be greater than 100");
1239
- } else if (defaultSizePercentage > maxSizePercentage) {
1240
- warnings.push("default size should not be greater than max size");
1241
- }
1036
+ if (defaultSize != null) {
1037
+ if (defaultSize < 0) {
1038
+ warnings.push("default size should not be less than 0");
1039
+ } else if (defaultSize < minSize) {
1040
+ warnings.push("default size should not be less than min size");
1242
1041
  }
1243
- if (collapsedSizePercentage > minSizePercentage) {
1244
- warnings.push("collapsed size should not be greater than min size");
1042
+ if (defaultSize > 100) {
1043
+ warnings.push("default size should not be greater than 100");
1044
+ } else if (defaultSize > maxSize) {
1045
+ warnings.push("default size should not be greater than max size");
1245
1046
  }
1246
1047
  }
1048
+ if (collapsedSize > minSize) {
1049
+ warnings.push("collapsed size should not be greater than min size");
1050
+ }
1247
1051
  if (warnings.length > 0) {
1248
1052
  const name = panelId != null ? `Panel "${panelId}"` : "Panel";
1249
1053
  console.warn(`${name} has an invalid configuration:\n\n${warnings.join("\n")}`);
@@ -1255,20 +1059,26 @@ function validatePanelConstraints({
1255
1059
 
1256
1060
  // All units must be in percentages; pixel values should be pre-converted
1257
1061
  function validatePanelGroupLayout({
1258
- groupSizePixels,
1259
1062
  layout: prevLayout,
1260
1063
  panelConstraints
1261
1064
  }) {
1262
1065
  const nextLayout = [...prevLayout];
1066
+ const nextLayoutTotalSize = nextLayout.reduce((accumulated, current) => accumulated + current, 0);
1263
1067
 
1264
1068
  // Validate layout expectations
1265
1069
  if (nextLayout.length !== panelConstraints.length) {
1266
1070
  throw Error(`Invalid ${panelConstraints.length} panel layout: ${nextLayout.map(size => `${size}%`).join(", ")}`);
1267
- } else if (!fuzzyNumbersEqual(nextLayout.reduce((accumulated, current) => accumulated + current, 0), 100)) {
1071
+ } else if (!fuzzyNumbersEqual(nextLayoutTotalSize, 100)) {
1268
1072
  // This is not ideal so we should warn about it, but it may be recoverable in some cases
1269
1073
  // (especially if the amount is small)
1270
1074
  {
1271
- console.warn(`WARNING: Invalid layout total size: ${nextLayout.map(size => `${size}%`).join(", ")}`);
1075
+ console.warn(`WARNING: Invalid layout total size: ${nextLayout.map(size => `${size}%`).join(", ")}. Layout normalization will be applied.`);
1076
+ }
1077
+ for (let index = 0; index < panelConstraints.length; index++) {
1078
+ const unsafeSize = nextLayout[index];
1079
+ assert(unsafeSize != null);
1080
+ const safeSize = 100 / nextLayoutTotalSize * unsafeSize;
1081
+ nextLayout[index] = safeSize;
1272
1082
  }
1273
1083
  }
1274
1084
  let remainingSize = 0;
@@ -1276,8 +1086,8 @@ function validatePanelGroupLayout({
1276
1086
  // First pass: Validate the proposed layout given each panel's constraints
1277
1087
  for (let index = 0; index < panelConstraints.length; index++) {
1278
1088
  const unsafeSize = nextLayout[index];
1089
+ assert(unsafeSize != null);
1279
1090
  const safeSize = resizePanel({
1280
- groupSizePixels,
1281
1091
  panelConstraints,
1282
1092
  panelIndex: index,
1283
1093
  size: unsafeSize
@@ -1293,9 +1103,9 @@ function validatePanelGroupLayout({
1293
1103
  if (!fuzzyNumbersEqual(remainingSize, 0)) {
1294
1104
  for (let index = 0; index < panelConstraints.length; index++) {
1295
1105
  const prevSize = nextLayout[index];
1106
+ assert(prevSize != null);
1296
1107
  const unsafeSize = prevSize + remainingSize;
1297
1108
  const safeSize = resizePanel({
1298
- groupSizePixels,
1299
1109
  panelConstraints,
1300
1110
  panelIndex: index,
1301
1111
  size: unsafeSize
@@ -1330,21 +1140,20 @@ function PanelGroupWithForwardedRef({
1330
1140
  autoSaveId = null,
1331
1141
  children,
1332
1142
  className: classNameFromProps = "",
1333
- dataAttributes,
1334
1143
  direction,
1335
1144
  forwardedRef,
1336
- id: idFromProps,
1145
+ id: idFromProps = null,
1337
1146
  onLayout = null,
1338
- keyboardResizeByPercentage = null,
1339
- keyboardResizeByPixels = null,
1147
+ keyboardResizeBy = null,
1340
1148
  storage = defaultStorage,
1341
1149
  style: styleFromProps,
1342
- tagName: Type = "div"
1150
+ tagName: Type = "div",
1151
+ ...rest
1343
1152
  }) {
1344
1153
  const groupId = useUniqueId(idFromProps);
1345
1154
  const [dragState, setDragState] = useState(null);
1346
1155
  const [layout, setLayout] = useState([]);
1347
- const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
1156
+ const panelIdToLastNotifiedSizeMapRef = useRef({});
1348
1157
  const panelSizeBeforeCollapseRef = useRef(new Map());
1349
1158
  const prevDeltaRef = useRef(0);
1350
1159
  const committedValuesRef = useRef({
@@ -1352,8 +1161,7 @@ function PanelGroupWithForwardedRef({
1352
1161
  direction,
1353
1162
  dragState,
1354
1163
  id: groupId,
1355
- keyboardResizeByPercentage,
1356
- keyboardResizeByPixels,
1164
+ keyboardResizeBy,
1357
1165
  onLayout,
1358
1166
  storage
1359
1167
  });
@@ -1369,33 +1177,20 @@ function PanelGroupWithForwardedRef({
1369
1177
  useImperativeHandle(forwardedRef, () => ({
1370
1178
  getId: () => committedValuesRef.current.id,
1371
1179
  getLayout: () => {
1372
- const {
1373
- id: groupId
1374
- } = committedValuesRef.current;
1375
1180
  const {
1376
1181
  layout
1377
1182
  } = eagerValuesRef.current;
1378
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1379
- return layout.map(sizePercentage => {
1380
- return {
1381
- sizePercentage,
1382
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1383
- };
1384
- });
1183
+ return layout;
1385
1184
  },
1386
- setLayout: mixedSizes => {
1185
+ setLayout: unsafeLayout => {
1387
1186
  const {
1388
- id: groupId,
1389
1187
  onLayout
1390
1188
  } = committedValuesRef.current;
1391
1189
  const {
1392
1190
  layout: prevLayout,
1393
1191
  panelDataArray
1394
1192
  } = eagerValuesRef.current;
1395
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1396
- const unsafeLayout = mixedSizes.map(mixedSize => getPercentageSizeFromMixedSizes(mixedSize, groupSizePixels));
1397
1193
  const safeLayout = validatePanelGroupLayout({
1398
- groupSizePixels,
1399
1194
  layout: unsafeLayout,
1400
1195
  panelConstraints: panelDataArray.map(panelData => panelData.constraints)
1401
1196
  });
@@ -1403,12 +1198,9 @@ function PanelGroupWithForwardedRef({
1403
1198
  setLayout(safeLayout);
1404
1199
  eagerValuesRef.current.layout = safeLayout;
1405
1200
  if (onLayout) {
1406
- onLayout(safeLayout.map(sizePercentage => ({
1407
- sizePercentage,
1408
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1409
- })));
1201
+ onLayout(safeLayout);
1410
1202
  }
1411
- callPanelCallbacks(groupId, panelDataArray, safeLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1203
+ callPanelCallbacks(panelDataArray, safeLayout, panelIdToLastNotifiedSizeMapRef.current);
1412
1204
  }
1413
1205
  }
1414
1206
  }), []);
@@ -1419,11 +1211,7 @@ function PanelGroupWithForwardedRef({
1419
1211
  committedValuesRef.current.id = groupId;
1420
1212
  committedValuesRef.current.onLayout = onLayout;
1421
1213
  committedValuesRef.current.storage = storage;
1422
-
1423
- // panelDataArray and layout are updated in-sync with scheduled state updates.
1424
- // TODO [217] Move these values into a separate ref
1425
1214
  });
1426
-
1427
1215
  useWindowSplitterPanelGroupBehavior({
1428
1216
  committedValuesRef,
1429
1217
  eagerValuesRef,
@@ -1442,57 +1230,16 @@ function PanelGroupWithForwardedRef({
1442
1230
  if (layout.length === 0 || layout.length !== panelDataArray.length) {
1443
1231
  return;
1444
1232
  }
1233
+ let debouncedSave = debounceMap[autoSaveId];
1445
1234
 
1446
1235
  // Limit the frequency of localStorage updates.
1447
- if (!debounceMap[autoSaveId]) {
1448
- debounceMap[autoSaveId] = debounce(savePanelGroupLayout, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
1236
+ if (debouncedSave == null) {
1237
+ debouncedSave = debounce(savePanelGroupLayout, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
1238
+ debounceMap[autoSaveId] = debouncedSave;
1449
1239
  }
1450
- debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
1240
+ debouncedSave(autoSaveId, panelDataArray, layout, storage);
1451
1241
  }
1452
1242
  }, [autoSaveId, layout, storage]);
1453
- useIsomorphicLayoutEffect(() => {
1454
- const {
1455
- layout: prevLayout,
1456
- panelDataArray
1457
- } = eagerValuesRef.current;
1458
- const constraints = panelDataArray.map(({
1459
- constraints
1460
- }) => constraints);
1461
- if (!shouldMonitorPixelBasedConstraints(constraints)) {
1462
- // Avoid the overhead of ResizeObserver if no pixel constraints require monitoring
1463
- return;
1464
- }
1465
- if (typeof ResizeObserver === "undefined") {
1466
- console.warn(`WARNING: Pixel based constraints require ResizeObserver but it is not supported by the current browser.`);
1467
- } else {
1468
- const resizeObserver = new ResizeObserver(() => {
1469
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1470
- const {
1471
- onLayout
1472
- } = committedValuesRef.current;
1473
- const nextLayout = validatePanelGroupLayout({
1474
- groupSizePixels,
1475
- layout: prevLayout,
1476
- panelConstraints: panelDataArray.map(panelData => panelData.constraints)
1477
- });
1478
- if (!areEqual(prevLayout, nextLayout)) {
1479
- setLayout(nextLayout);
1480
- eagerValuesRef.current.layout = nextLayout;
1481
- if (onLayout) {
1482
- onLayout(nextLayout.map(sizePercentage => ({
1483
- sizePercentage,
1484
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1485
- })));
1486
- }
1487
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1488
- }
1489
- });
1490
- resizeObserver.observe(getPanelGroupElement(groupId));
1491
- return () => {
1492
- resizeObserver.disconnect();
1493
- };
1494
- }
1495
- }, [groupId]);
1496
1243
 
1497
1244
  // DEV warnings
1498
1245
  useEffect(() => {
@@ -1523,12 +1270,12 @@ function PanelGroupWithForwardedRef({
1523
1270
  }
1524
1271
  if (!didLogPanelConstraintsWarning) {
1525
1272
  const panelConstraints = panelDataArray.map(panelData => panelData.constraints);
1526
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1527
1273
  for (let panelIndex = 0; panelIndex < panelConstraints.length; panelIndex++) {
1274
+ const panelData = panelDataArray[panelIndex];
1275
+ assert(panelData);
1528
1276
  const isValid = validatePanelConstraints({
1529
- groupSizePixels,
1530
1277
  panelConstraints,
1531
- panelId: panelDataArray[panelIndex].id,
1278
+ panelId: panelData.id,
1532
1279
  panelIndex
1533
1280
  });
1534
1281
  if (!isValid) {
@@ -1552,20 +1299,19 @@ function PanelGroupWithForwardedRef({
1552
1299
  if (panelData.constraints.collapsible) {
1553
1300
  const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
1554
1301
  const {
1555
- collapsedSizePercentage,
1556
- panelSizePercentage,
1557
- pivotIndices,
1558
- groupSizePixels
1559
- } = panelDataHelper(groupId, panelDataArray, panelData, prevLayout);
1560
- if (panelSizePercentage !== collapsedSizePercentage) {
1302
+ collapsedSize = 0,
1303
+ panelSize,
1304
+ pivotIndices
1305
+ } = panelDataHelper(panelDataArray, panelData, prevLayout);
1306
+ assert(panelSize != null);
1307
+ if (panelSize !== collapsedSize) {
1561
1308
  // Store size before collapse;
1562
1309
  // This is the size that gets restored if the expand() API is used.
1563
- panelSizeBeforeCollapseRef.current.set(panelData.id, panelSizePercentage);
1310
+ panelSizeBeforeCollapseRef.current.set(panelData.id, panelSize);
1564
1311
  const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
1565
- const delta = isLastPanel ? panelSizePercentage - collapsedSizePercentage : collapsedSizePercentage - panelSizePercentage;
1312
+ const delta = isLastPanel ? panelSize - collapsedSize : collapsedSize - panelSize;
1566
1313
  const nextLayout = adjustLayoutByDelta({
1567
1314
  delta,
1568
- groupSizePixels,
1569
1315
  layout: prevLayout,
1570
1316
  panelConstraints: panelConstraintsArray,
1571
1317
  pivotIndices,
@@ -1575,16 +1321,13 @@ function PanelGroupWithForwardedRef({
1575
1321
  setLayout(nextLayout);
1576
1322
  eagerValuesRef.current.layout = nextLayout;
1577
1323
  if (onLayout) {
1578
- onLayout(nextLayout.map(sizePercentage => ({
1579
- sizePercentage,
1580
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1581
- })));
1324
+ onLayout(nextLayout);
1582
1325
  }
1583
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1326
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1584
1327
  }
1585
1328
  }
1586
1329
  }
1587
- }, [groupId]);
1330
+ }, []);
1588
1331
 
1589
1332
  // External APIs are safe to memoize via committed values ref
1590
1333
  const expandPanel = useCallback(panelData => {
@@ -1598,21 +1341,19 @@ function PanelGroupWithForwardedRef({
1598
1341
  if (panelData.constraints.collapsible) {
1599
1342
  const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
1600
1343
  const {
1601
- collapsedSizePercentage,
1602
- panelSizePercentage,
1603
- minSizePercentage,
1604
- pivotIndices,
1605
- groupSizePixels
1606
- } = panelDataHelper(groupId, panelDataArray, panelData, prevLayout);
1607
- if (panelSizePercentage === collapsedSizePercentage) {
1344
+ collapsedSize = 0,
1345
+ panelSize,
1346
+ minSize = 0,
1347
+ pivotIndices
1348
+ } = panelDataHelper(panelDataArray, panelData, prevLayout);
1349
+ if (panelSize === collapsedSize) {
1608
1350
  // Restore this panel to the size it was before it was collapsed, if possible.
1609
- const prevPanelSizePercentage = panelSizeBeforeCollapseRef.current.get(panelData.id);
1610
- const baseSizePercentage = prevPanelSizePercentage != null && prevPanelSizePercentage >= minSizePercentage ? prevPanelSizePercentage : minSizePercentage;
1351
+ const prevPanelSize = panelSizeBeforeCollapseRef.current.get(panelData.id);
1352
+ const baseSize = prevPanelSize != null && prevPanelSize >= minSize ? prevPanelSize : minSize;
1611
1353
  const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
1612
- const delta = isLastPanel ? panelSizePercentage - baseSizePercentage : baseSizePercentage - panelSizePercentage;
1354
+ const delta = isLastPanel ? panelSize - baseSize : baseSize - panelSize;
1613
1355
  const nextLayout = adjustLayoutByDelta({
1614
1356
  delta,
1615
- groupSizePixels,
1616
1357
  layout: prevLayout,
1617
1358
  panelConstraints: panelConstraintsArray,
1618
1359
  pivotIndices,
@@ -1622,16 +1363,13 @@ function PanelGroupWithForwardedRef({
1622
1363
  setLayout(nextLayout);
1623
1364
  eagerValuesRef.current.layout = nextLayout;
1624
1365
  if (onLayout) {
1625
- onLayout(nextLayout.map(sizePercentage => ({
1626
- sizePercentage,
1627
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1628
- })));
1366
+ onLayout(nextLayout);
1629
1367
  }
1630
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1368
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1631
1369
  }
1632
1370
  }
1633
1371
  }
1634
- }, [groupId]);
1372
+ }, []);
1635
1373
 
1636
1374
  // External APIs are safe to memoize via committed values ref
1637
1375
  const getPanelSize = useCallback(panelData => {
@@ -1640,14 +1378,11 @@ function PanelGroupWithForwardedRef({
1640
1378
  panelDataArray
1641
1379
  } = eagerValuesRef.current;
1642
1380
  const {
1643
- panelSizePercentage,
1644
- panelSizePixels
1645
- } = panelDataHelper(groupId, panelDataArray, panelData, layout);
1646
- return {
1647
- sizePercentage: panelSizePercentage,
1648
- sizePixels: panelSizePixels
1649
- };
1650
- }, [groupId]);
1381
+ panelSize
1382
+ } = panelDataHelper(panelDataArray, panelData, layout);
1383
+ assert(panelSize != null);
1384
+ return panelSize;
1385
+ }, []);
1651
1386
 
1652
1387
  // This API should never read from committedValuesRef
1653
1388
  const getPanelStyle = useCallback(panelData => {
@@ -1670,12 +1405,12 @@ function PanelGroupWithForwardedRef({
1670
1405
  panelDataArray
1671
1406
  } = eagerValuesRef.current;
1672
1407
  const {
1673
- collapsedSizePercentage,
1408
+ collapsedSize,
1674
1409
  collapsible,
1675
- panelSizePercentage
1676
- } = panelDataHelper(groupId, panelDataArray, panelData, layout);
1677
- return collapsible === true && panelSizePercentage === collapsedSizePercentage;
1678
- }, [groupId]);
1410
+ panelSize
1411
+ } = panelDataHelper(panelDataArray, panelData, layout);
1412
+ return collapsible === true && panelSize === collapsedSize;
1413
+ }, []);
1679
1414
 
1680
1415
  // External APIs are safe to memoize via committed values ref
1681
1416
  const isPanelExpanded = useCallback(panelData => {
@@ -1684,12 +1419,13 @@ function PanelGroupWithForwardedRef({
1684
1419
  panelDataArray
1685
1420
  } = eagerValuesRef.current;
1686
1421
  const {
1687
- collapsedSizePercentage,
1422
+ collapsedSize = 0,
1688
1423
  collapsible,
1689
- panelSizePercentage
1690
- } = panelDataHelper(groupId, panelDataArray, panelData, layout);
1691
- return !collapsible || panelSizePercentage > collapsedSizePercentage;
1692
- }, [groupId]);
1424
+ panelSize
1425
+ } = panelDataHelper(panelDataArray, panelData, layout);
1426
+ assert(panelSize != null);
1427
+ return !collapsible || panelSize > collapsedSize;
1428
+ }, []);
1693
1429
  const registerPanel = useCallback(panelData => {
1694
1430
  const {
1695
1431
  autoSaveId,
@@ -1729,18 +1465,8 @@ function PanelGroupWithForwardedRef({
1729
1465
  if (autoSaveId) {
1730
1466
  unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
1731
1467
  }
1732
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1733
- if (groupSizePixels <= 0) {
1734
- if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
1735
- constraints
1736
- }) => constraints))) {
1737
- // Wait until the group has rendered a non-zero size before computing layout.
1738
- return;
1739
- }
1740
- }
1741
1468
  if (unsafeLayout == null) {
1742
1469
  unsafeLayout = calculateUnsafeDefaultLayout({
1743
- groupSizePixels,
1744
1470
  panelDataArray
1745
1471
  });
1746
1472
  }
@@ -1748,7 +1474,6 @@ function PanelGroupWithForwardedRef({
1748
1474
  // Validate even saved layouts in case something has changed since last render
1749
1475
  // e.g. for pixel groups, this could be the size of the window
1750
1476
  const nextLayout = validatePanelGroupLayout({
1751
- groupSizePixels,
1752
1477
  layout: unsafeLayout,
1753
1478
  panelConstraints: panelDataArray.map(panelData => panelData.constraints)
1754
1479
  });
@@ -1760,12 +1485,9 @@ function PanelGroupWithForwardedRef({
1760
1485
  eagerValuesRef.current.layout = nextLayout;
1761
1486
  if (!areEqual(prevLayout, nextLayout)) {
1762
1487
  if (onLayout) {
1763
- onLayout(nextLayout.map(sizePercentage => ({
1764
- sizePercentage,
1765
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1766
- })));
1488
+ onLayout(nextLayout);
1767
1489
  }
1768
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1490
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1769
1491
  }
1770
1492
  }, []);
1771
1493
  const registerResizeHandle = useCallback(dragHandleId => {
@@ -1775,8 +1497,7 @@ function PanelGroupWithForwardedRef({
1775
1497
  direction,
1776
1498
  dragState,
1777
1499
  id: groupId,
1778
- keyboardResizeByPercentage,
1779
- keyboardResizeByPixels,
1500
+ keyboardResizeBy,
1780
1501
  onLayout
1781
1502
  } = committedValuesRef.current;
1782
1503
  const {
@@ -1787,10 +1508,7 @@ function PanelGroupWithForwardedRef({
1787
1508
  initialLayout
1788
1509
  } = dragState !== null && dragState !== void 0 ? dragState : {};
1789
1510
  const pivotIndices = determinePivotIndices(groupId, dragHandleId);
1790
- let delta = calculateDeltaPercentage(event, groupId, dragHandleId, direction, dragState, {
1791
- percentage: keyboardResizeByPercentage,
1792
- pixels: keyboardResizeByPixels
1793
- });
1511
+ let delta = calculateDeltaPercentage(event, dragHandleId, direction, dragState, keyboardResizeBy);
1794
1512
  if (delta === 0) {
1795
1513
  return;
1796
1514
  }
@@ -1800,11 +1518,9 @@ function PanelGroupWithForwardedRef({
1800
1518
  if (document.dir === "rtl" && isHorizontal) {
1801
1519
  delta = -delta;
1802
1520
  }
1803
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1804
1521
  const panelConstraints = panelDataArray.map(panelData => panelData.constraints);
1805
1522
  const nextLayout = adjustLayoutByDelta({
1806
1523
  delta,
1807
- groupSizePixels,
1808
1524
  layout: initialLayout !== null && initialLayout !== void 0 ? initialLayout : prevLayout,
1809
1525
  panelConstraints,
1810
1526
  pivotIndices,
@@ -1840,18 +1556,15 @@ function PanelGroupWithForwardedRef({
1840
1556
  setLayout(nextLayout);
1841
1557
  eagerValuesRef.current.layout = nextLayout;
1842
1558
  if (onLayout) {
1843
- onLayout(nextLayout.map(sizePercentage => ({
1844
- sizePercentage,
1845
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1846
- })));
1559
+ onLayout(nextLayout);
1847
1560
  }
1848
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1561
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1849
1562
  }
1850
1563
  };
1851
1564
  }, []);
1852
1565
 
1853
1566
  // External APIs are safe to memoize via committed values ref
1854
- const resizePanel = useCallback((panelData, mixedSizes) => {
1567
+ const resizePanel = useCallback((panelData, unsafePanelSize) => {
1855
1568
  const {
1856
1569
  onLayout
1857
1570
  } = committedValuesRef.current;
@@ -1861,16 +1574,14 @@ function PanelGroupWithForwardedRef({
1861
1574
  } = eagerValuesRef.current;
1862
1575
  const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
1863
1576
  const {
1864
- groupSizePixels,
1865
- panelSizePercentage,
1577
+ panelSize,
1866
1578
  pivotIndices
1867
- } = panelDataHelper(groupId, panelDataArray, panelData, prevLayout);
1868
- const sizePercentage = getPercentageSizeFromMixedSizes(mixedSizes, groupSizePixels);
1579
+ } = panelDataHelper(panelDataArray, panelData, prevLayout);
1580
+ assert(panelSize != null);
1869
1581
  const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
1870
- const delta = isLastPanel ? panelSizePercentage - sizePercentage : sizePercentage - panelSizePercentage;
1582
+ const delta = isLastPanel ? panelSize - unsafePanelSize : unsafePanelSize - panelSize;
1871
1583
  const nextLayout = adjustLayoutByDelta({
1872
1584
  delta,
1873
- groupSizePixels,
1874
1585
  layout: prevLayout,
1875
1586
  panelConstraints: panelConstraintsArray,
1876
1587
  pivotIndices,
@@ -1880,14 +1591,11 @@ function PanelGroupWithForwardedRef({
1880
1591
  setLayout(nextLayout);
1881
1592
  eagerValuesRef.current.layout = nextLayout;
1882
1593
  if (onLayout) {
1883
- onLayout(nextLayout.map(sizePercentage => ({
1884
- sizePercentage,
1885
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1886
- })));
1594
+ onLayout(nextLayout);
1887
1595
  }
1888
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1596
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1889
1597
  }
1890
- }, [groupId]);
1598
+ }, []);
1891
1599
  const startDragging = useCallback((dragHandleId, event) => {
1892
1600
  const {
1893
1601
  direction
@@ -1896,6 +1604,7 @@ function PanelGroupWithForwardedRef({
1896
1604
  layout
1897
1605
  } = eagerValuesRef.current;
1898
1606
  const handleElement = getResizeHandleElement(dragHandleId);
1607
+ assert(handleElement);
1899
1608
  const initialCursorPosition = getResizeEventCursorPosition(direction, event);
1900
1609
  setDragState({
1901
1610
  dragHandleId,
@@ -1914,7 +1623,6 @@ function PanelGroupWithForwardedRef({
1914
1623
  });
1915
1624
  const unregisterPanel = useCallback(panelData => {
1916
1625
  const {
1917
- id: groupId,
1918
1626
  onLayout
1919
1627
  } = committedValuesRef.current;
1920
1628
  const {
@@ -1937,7 +1645,7 @@ function PanelGroupWithForwardedRef({
1937
1645
  const {
1938
1646
  pendingPanelIds
1939
1647
  } = unregisterPanelRef.current;
1940
- const map = panelIdToLastNotifiedMixedSizesMapRef.current;
1648
+ const map = panelIdToLastNotifiedSizeMapRef.current;
1941
1649
 
1942
1650
  // TRICKY
1943
1651
  // Strict effects mode
@@ -1946,7 +1654,7 @@ function PanelGroupWithForwardedRef({
1946
1654
  pendingPanelIds.delete(panelId);
1947
1655
  if (panelDataArray.find(({
1948
1656
  id
1949
- }) => id === panelId) == null) {
1657
+ }) => id === panelId) != null) {
1950
1658
  unmountDueToStrictMode = true;
1951
1659
 
1952
1660
  // TRICKY
@@ -1963,16 +1671,13 @@ function PanelGroupWithForwardedRef({
1963
1671
  // The group is unmounting; skip layout calculation.
1964
1672
  return;
1965
1673
  }
1966
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1967
1674
  let unsafeLayout = calculateUnsafeDefaultLayout({
1968
- groupSizePixels,
1969
1675
  panelDataArray
1970
1676
  });
1971
1677
 
1972
1678
  // Validate even saved layouts in case something has changed since last render
1973
1679
  // e.g. for pixel groups, this could be the size of the window
1974
1680
  const nextLayout = validatePanelGroupLayout({
1975
- groupSizePixels,
1976
1681
  layout: unsafeLayout,
1977
1682
  panelConstraints: panelDataArray.map(panelData => panelData.constraints)
1978
1683
  });
@@ -1980,12 +1685,9 @@ function PanelGroupWithForwardedRef({
1980
1685
  setLayout(nextLayout);
1981
1686
  eagerValuesRef.current.layout = nextLayout;
1982
1687
  if (onLayout) {
1983
- onLayout(nextLayout.map(sizePercentage => ({
1984
- sizePercentage,
1985
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1986
- })));
1688
+ onLayout(nextLayout);
1987
1689
  }
1988
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1690
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1989
1691
  }
1990
1692
  }, 0);
1991
1693
  }, []);
@@ -2016,13 +1718,13 @@ function PanelGroupWithForwardedRef({
2016
1718
  return createElement(PanelGroupContext.Provider, {
2017
1719
  value: context
2018
1720
  }, createElement(Type, {
1721
+ ...rest,
2019
1722
  children,
2020
1723
  className: classNameFromProps,
2021
1724
  style: {
2022
1725
  ...style,
2023
1726
  ...styleFromProps
2024
1727
  },
2025
- ...dataAttributes,
2026
1728
  // CSS selectors
2027
1729
  "data-panel-group": "",
2028
1730
  "data-panel-group-direction": direction,
@@ -2035,22 +1737,16 @@ const PanelGroup = forwardRef((props, ref) => createElement(PanelGroupWithForwar
2035
1737
  }));
2036
1738
  PanelGroupWithForwardedRef.displayName = "PanelGroup";
2037
1739
  PanelGroup.displayName = "forwardRef(PanelGroup)";
2038
- function panelDataHelper(groupId, panelDataArray, panelData, layout) {
1740
+ function panelDataHelper(panelDataArray, panelData, layout) {
2039
1741
  const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
2040
1742
  const panelIndex = panelDataArray.indexOf(panelData);
2041
1743
  const panelConstraints = panelConstraintsArray[panelIndex];
2042
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
2043
- const percentagePanelConstraints = computePercentagePanelConstraints(panelConstraintsArray, panelIndex, groupSizePixels);
2044
1744
  const isLastPanel = panelIndex === panelDataArray.length - 1;
2045
1745
  const pivotIndices = isLastPanel ? [panelIndex - 1, panelIndex] : [panelIndex, panelIndex + 1];
2046
- const panelSizePercentage = layout[panelIndex];
2047
- const panelSizePixels = convertPercentageToPixels(panelSizePercentage, groupSizePixels);
1746
+ const panelSize = layout[panelIndex];
2048
1747
  return {
2049
- ...percentagePanelConstraints,
2050
- collapsible: panelConstraints.collapsible,
2051
- panelSizePercentage,
2052
- panelSizePixels,
2053
- groupSizePixels,
1748
+ ...panelConstraints,
1749
+ panelSize,
2054
1750
  pivotIndices
2055
1751
  };
2056
1752
  }
@@ -2090,6 +1786,7 @@ function useWindowSplitterResizeHandlerBehavior({
2090
1786
  {
2091
1787
  event.preventDefault();
2092
1788
  const groupId = handleElement.getAttribute("data-panel-group-id");
1789
+ assert(groupId);
2093
1790
  const handles = getResizeHandleElementsForGroup(groupId);
2094
1791
  const index = getResizeHandleElementIndex(groupId, handleId);
2095
1792
  assert(index !== null);
@@ -2110,12 +1807,13 @@ function useWindowSplitterResizeHandlerBehavior({
2110
1807
  function PanelResizeHandle({
2111
1808
  children = null,
2112
1809
  className: classNameFromProps = "",
2113
- dataAttributes,
2114
1810
  disabled = false,
2115
- id: idFromProps = null,
1811
+ id: idFromProps,
2116
1812
  onDragging,
2117
1813
  style: styleFromProps = {},
2118
- tagName: Type = "div"
1814
+ tabIndex = 0,
1815
+ tagName: Type = "div",
1816
+ ...rest
2119
1817
  }) {
2120
1818
  const divElementRef = useRef(null);
2121
1819
 
@@ -2145,8 +1843,9 @@ function PanelResizeHandle({
2145
1843
  const stopDraggingAndBlur = useCallback(() => {
2146
1844
  // Clicking on the drag handle shouldn't leave it focused;
2147
1845
  // That would cause the PanelGroup to think it was still active.
2148
- const div = divElementRef.current;
2149
- div.blur();
1846
+ const divElement = divElementRef.current;
1847
+ assert(divElement);
1848
+ divElement.blur();
2150
1849
  stopDragging();
2151
1850
  const {
2152
1851
  onDragging
@@ -2174,6 +1873,7 @@ function PanelResizeHandle({
2174
1873
  resizeHandler(event);
2175
1874
  };
2176
1875
  const divElement = divElementRef.current;
1876
+ assert(divElement);
2177
1877
  const targetDocument = divElement.ownerDocument;
2178
1878
  targetDocument.body.addEventListener("contextmenu", stopDraggingAndBlur);
2179
1879
  targetDocument.body.addEventListener("mousemove", onMove);
@@ -2201,15 +1901,18 @@ function PanelResizeHandle({
2201
1901
  userSelect: "none"
2202
1902
  };
2203
1903
  return createElement(Type, {
1904
+ ...rest,
2204
1905
  children,
2205
1906
  className: classNameFromProps,
2206
1907
  onBlur: () => setIsFocused(false),
2207
1908
  onFocus: () => setIsFocused(true),
2208
1909
  onMouseDown: event => {
2209
1910
  startDragging(resizeHandleId, event.nativeEvent);
1911
+ const callbacks = callbacksRef.current;
1912
+ assert(callbacks);
2210
1913
  const {
2211
1914
  onDragging
2212
- } = callbacksRef.current;
1915
+ } = callbacks;
2213
1916
  if (onDragging) {
2214
1917
  onDragging(true);
2215
1918
  }
@@ -2219,9 +1922,11 @@ function PanelResizeHandle({
2219
1922
  onTouchEnd: stopDraggingAndBlur,
2220
1923
  onTouchStart: event => {
2221
1924
  startDragging(resizeHandleId, event.nativeEvent);
1925
+ const callbacks = callbacksRef.current;
1926
+ assert(callbacks);
2222
1927
  const {
2223
1928
  onDragging
2224
- } = callbacksRef.current;
1929
+ } = callbacks;
2225
1930
  if (onDragging) {
2226
1931
  onDragging(true);
2227
1932
  }
@@ -2232,8 +1937,7 @@ function PanelResizeHandle({
2232
1937
  ...style,
2233
1938
  ...styleFromProps
2234
1939
  },
2235
- tabIndex: 0,
2236
- ...dataAttributes,
1940
+ tabIndex,
2237
1941
  // CSS selectors
2238
1942
  "data-panel-group-direction": direction,
2239
1943
  "data-panel-group-id": groupId,
@@ -2245,4 +1949,4 @@ function PanelResizeHandle({
2245
1949
  }
2246
1950
  PanelResizeHandle.displayName = "PanelResizeHandle";
2247
1951
 
2248
- export { Panel, PanelGroup, PanelResizeHandle };
1952
+ export { Panel, PanelGroup, PanelResizeHandle, assert };