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
@@ -67,24 +67,20 @@ function useUniqueId(idFromParams = null) {
67
67
  function PanelWithForwardedRef({
68
68
  children,
69
69
  className: classNameFromProps = "",
70
- collapsedSizePercentage,
71
- collapsedSizePixels,
70
+ collapsedSize,
72
71
  collapsible,
73
- dataAttributes,
74
- defaultSizePercentage,
75
- defaultSizePixels,
72
+ defaultSize,
76
73
  forwardedRef,
77
74
  id: idFromProps,
78
- maxSizePercentage,
79
- maxSizePixels,
80
- minSizePercentage,
81
- minSizePixels,
75
+ maxSize,
76
+ minSize,
82
77
  onCollapse,
83
78
  onExpand,
84
79
  onResize,
85
80
  order,
86
81
  style: styleFromProps,
87
- tagName: Type = "div"
82
+ tagName: Type = "div",
83
+ ...rest
88
84
  }) {
89
85
  const context = useContext(PanelGroupContext);
90
86
  if (context === null) {
@@ -109,15 +105,11 @@ function PanelWithForwardedRef({
109
105
  onResize
110
106
  },
111
107
  constraints: {
112
- collapsedSizePercentage,
113
- collapsedSizePixels,
108
+ collapsedSize,
114
109
  collapsible,
115
- defaultSizePercentage,
116
- defaultSizePixels,
117
- maxSizePercentage,
118
- maxSizePixels,
119
- minSizePercentage,
120
- minSizePixels
110
+ defaultSize,
111
+ maxSize,
112
+ minSize
121
113
  },
122
114
  id: panelId,
123
115
  idIsFromProps: idFromProps !== undefined,
@@ -131,9 +123,9 @@ function PanelWithForwardedRef({
131
123
  // but effects don't run on the server, so we can't do it there
132
124
  {
133
125
  if (!devWarningsRef.current.didLogMissingDefaultSizeWarning) {
134
- if (!isBrowser && defaultSizePercentage == null && defaultSizePixels == null) {
126
+ if (!isBrowser && defaultSize == null) {
135
127
  devWarningsRef.current.didLogMissingDefaultSizeWarning = true;
136
- console.warn(`WARNING: Panel defaultSizePercentage or defaultSizePixels prop recommended to avoid layout shift after server rendering`);
128
+ console.warn(`WARNING: Panel defaultSize prop recommended to avoid layout shift after server rendering`);
137
129
  }
138
130
  }
139
131
  }
@@ -148,15 +140,11 @@ function PanelWithForwardedRef({
148
140
  callbacks.onCollapse = onCollapse;
149
141
  callbacks.onExpand = onExpand;
150
142
  callbacks.onResize = onResize;
151
- constraints.collapsedSizePercentage = collapsedSizePercentage;
152
- constraints.collapsedSizePixels = collapsedSizePixels;
143
+ constraints.collapsedSize = collapsedSize;
153
144
  constraints.collapsible = collapsible;
154
- constraints.defaultSizePercentage = defaultSizePercentage;
155
- constraints.defaultSizePixels = defaultSizePixels;
156
- constraints.maxSizePercentage = maxSizePercentage;
157
- constraints.maxSizePixels = maxSizePixels;
158
- constraints.minSizePercentage = minSizePercentage;
159
- constraints.minSizePixels = minSizePixels;
145
+ constraints.defaultSize = defaultSize;
146
+ constraints.maxSize = maxSize;
147
+ constraints.minSize = minSize;
160
148
  });
161
149
  useIsomorphicLayoutEffect(() => {
162
150
  const panelData = panelDataRef.current;
@@ -184,19 +172,19 @@ function PanelWithForwardedRef({
184
172
  isExpanded() {
185
173
  return !isPanelCollapsed(panelDataRef.current);
186
174
  },
187
- resize: mixedSizes => {
188
- resizePanel(panelDataRef.current, mixedSizes);
175
+ resize: size => {
176
+ resizePanel(panelDataRef.current, size);
189
177
  }
190
178
  }), [collapsePanel, expandPanel, getPanelSize, isPanelCollapsed, panelId, resizePanel]);
191
179
  const style = getPanelStyle(panelDataRef.current);
192
180
  return createElement(Type, {
181
+ ...rest,
193
182
  children,
194
183
  className: classNameFromProps,
195
184
  style: {
196
185
  ...style,
197
186
  ...styleFromProps
198
187
  },
199
- ...dataAttributes,
200
188
  // CSS selectors
201
189
  "data-panel": "",
202
190
  "data-panel-id": panelId,
@@ -213,81 +201,11 @@ const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
213
201
  PanelWithForwardedRef.displayName = "Panel";
214
202
  Panel.displayName = "forwardRef(Panel)";
215
203
 
216
- function convertPixelsToPercentage(pixels, groupSizePixels) {
217
- return pixels / groupSizePixels * 100;
218
- }
219
-
220
- function convertPixelConstraintsToPercentages(panelConstraints, groupSizePixels) {
221
- let {
222
- collapsedSizePercentage = 0,
223
- collapsedSizePixels,
224
- defaultSizePercentage,
225
- defaultSizePixels,
226
- maxSizePercentage = 100,
227
- maxSizePixels,
228
- minSizePercentage = 0,
229
- minSizePixels
230
- } = panelConstraints;
231
- const hasPixelConstraints = collapsedSizePixels != null || defaultSizePixels != null || minSizePixels != null || maxSizePixels != null;
232
- if (hasPixelConstraints && groupSizePixels <= 0) {
233
- console.warn(`WARNING: Invalid group size: ${groupSizePixels}px`);
234
- return {
235
- collapsedSizePercentage: 0,
236
- defaultSizePercentage,
237
- maxSizePercentage: 0,
238
- minSizePercentage: 0
239
- };
240
- }
241
- if (collapsedSizePixels != null) {
242
- collapsedSizePercentage = convertPixelsToPercentage(collapsedSizePixels, groupSizePixels);
243
- }
244
- if (defaultSizePixels != null) {
245
- defaultSizePercentage = convertPixelsToPercentage(defaultSizePixels, groupSizePixels);
246
- }
247
- if (minSizePixels != null) {
248
- minSizePercentage = convertPixelsToPercentage(minSizePixels, groupSizePixels);
249
- }
250
- if (maxSizePixels != null) {
251
- maxSizePercentage = convertPixelsToPercentage(maxSizePixels, groupSizePixels);
252
- }
253
- return {
254
- collapsedSizePercentage,
255
- defaultSizePercentage,
256
- maxSizePercentage,
257
- minSizePercentage
258
- };
259
- }
260
-
261
- function computePercentagePanelConstraints(panelConstraintsArray, panelIndex, groupSizePixels) {
262
- // All panel constraints, excluding the current one
263
- let totalMinConstraints = 0;
264
- let totalMaxConstraints = 0;
265
- for (let index = 0; index < panelConstraintsArray.length; index++) {
266
- if (index !== panelIndex) {
267
- const {
268
- collapsible
269
- } = panelConstraintsArray[index];
270
- const {
271
- collapsedSizePercentage,
272
- maxSizePercentage,
273
- minSizePercentage
274
- } = convertPixelConstraintsToPercentages(panelConstraintsArray[index], groupSizePixels);
275
- totalMaxConstraints += maxSizePercentage;
276
- totalMinConstraints += collapsible ? collapsedSizePercentage : minSizePercentage;
277
- }
204
+ function assert(expectedCondition, message = "Assertion failed!") {
205
+ if (!expectedCondition) {
206
+ console.error(message);
207
+ throw Error(message);
278
208
  }
279
- const {
280
- collapsedSizePercentage,
281
- defaultSizePercentage,
282
- maxSizePercentage,
283
- minSizePercentage
284
- } = convertPixelConstraintsToPercentages(panelConstraintsArray[panelIndex], groupSizePixels);
285
- return {
286
- collapsedSizePercentage,
287
- defaultSizePercentage,
288
- maxSizePercentage: panelConstraintsArray.length > 1 ? Math.min(maxSizePercentage, 100 - totalMinConstraints) : maxSizePercentage,
289
- minSizePercentage: panelConstraintsArray.length > 1 ? Math.max(minSizePercentage, 100 - totalMaxConstraints) : minSizePercentage
290
- };
291
209
  }
292
210
 
293
211
  const PRECISION = 10;
@@ -309,56 +227,41 @@ function fuzzyNumbersEqual(actual, expected, fractionDigits) {
309
227
 
310
228
  // Panel size must be in percentages; pixel values should be pre-converted
311
229
  function resizePanel({
312
- groupSizePixels,
313
- panelConstraints,
230
+ panelConstraints: panelConstraintsArray,
314
231
  panelIndex,
315
232
  size
316
233
  }) {
317
- const hasPixelConstraints = panelConstraints.some(({
318
- collapsedSizePixels,
319
- defaultSizePixels,
320
- minSizePixels,
321
- maxSizePixels
322
- }) => collapsedSizePixels != null || defaultSizePixels != null || minSizePixels != null || maxSizePixels != null);
323
- if (hasPixelConstraints && groupSizePixels <= 0) {
324
- console.warn(`WARNING: Invalid group size: ${groupSizePixels}px`);
325
- return 0;
326
- }
234
+ const panelConstraints = panelConstraintsArray[panelIndex];
235
+ assert(panelConstraints != null);
327
236
  let {
328
- collapsible
329
- } = panelConstraints[panelIndex];
330
- const {
331
- collapsedSizePercentage,
332
- maxSizePercentage,
333
- minSizePercentage
334
- } = computePercentagePanelConstraints(panelConstraints, panelIndex, groupSizePixels);
335
- if (minSizePercentage != null) {
336
- if (fuzzyCompareNumbers(size, minSizePercentage) < 0) {
337
- if (collapsible) {
338
- // Collapsible panels should snap closed or open only once they cross the halfway point between collapsed and min size.
339
- const halfwayPoint = (collapsedSizePercentage + minSizePercentage) / 2;
340
- if (fuzzyCompareNumbers(size, halfwayPoint) < 0) {
341
- size = collapsedSizePercentage;
342
- } else {
343
- size = minSizePercentage;
344
- }
237
+ collapsedSize = 0,
238
+ collapsible,
239
+ maxSize = 100,
240
+ minSize = 0
241
+ } = panelConstraints;
242
+ if (fuzzyCompareNumbers(size, minSize) < 0) {
243
+ if (collapsible) {
244
+ // Collapsible panels should snap closed or open only once they cross the halfway point between collapsed and min size.
245
+ const halfwayPoint = (collapsedSize + minSize) / 2;
246
+ if (fuzzyCompareNumbers(size, halfwayPoint) < 0) {
247
+ size = collapsedSize;
345
248
  } else {
346
- size = minSizePercentage;
249
+ size = minSize;
347
250
  }
251
+ } else {
252
+ size = minSize;
348
253
  }
349
254
  }
350
- if (maxSizePercentage != null) {
351
- size = Math.min(maxSizePercentage, size);
352
- }
255
+ size = Math.min(maxSize, size);
256
+ size = parseFloat(size.toFixed(PRECISION));
353
257
  return size;
354
258
  }
355
259
 
356
260
  // All units must be in percentages; pixel values should be pre-converted
357
261
  function adjustLayoutByDelta({
358
262
  delta,
359
- groupSizePixels,
360
263
  layout: prevLayout,
361
- panelConstraints,
264
+ panelConstraints: panelConstraintsArray,
362
265
  pivotIndices,
363
266
  trigger
364
267
  }) {
@@ -366,6 +269,9 @@ function adjustLayoutByDelta({
366
269
  return prevLayout;
367
270
  }
368
271
  const nextLayout = [...prevLayout];
272
+ const [firstPivotIndex, secondPivotIndex] = pivotIndices;
273
+ assert(firstPivotIndex != null);
274
+ assert(secondPivotIndex != null);
369
275
  let deltaApplied = 0;
370
276
 
371
277
  //const DEBUG = [];
@@ -389,18 +295,23 @@ function adjustLayoutByDelta({
389
295
  if (trigger === "keyboard") {
390
296
  {
391
297
  // Check if we should expand a collapsed panel
392
- const index = delta < 0 ? pivotIndices[1] : pivotIndices[0];
393
- const constraints = panelConstraints[index];
298
+ const index = delta < 0 ? secondPivotIndex : firstPivotIndex;
299
+ const panelConstraints = panelConstraintsArray[index];
300
+ assert(panelConstraints);
301
+
394
302
  //DEBUG.push(`edge case check 1: ${index}`);
395
303
  //DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
396
- if (constraints.collapsible) {
304
+ if (panelConstraints.collapsible) {
397
305
  const prevSize = prevLayout[index];
306
+ assert(prevSize != null);
307
+ const panelConstraints = panelConstraintsArray[index];
308
+ assert(panelConstraints);
398
309
  const {
399
- collapsedSizePercentage,
400
- minSizePercentage
401
- } = computePercentagePanelConstraints(panelConstraints, index, groupSizePixels);
402
- if (fuzzyNumbersEqual(prevSize, collapsedSizePercentage)) {
403
- const localDelta = minSizePercentage - prevSize;
310
+ collapsedSize = 0,
311
+ minSize = 0
312
+ } = panelConstraints;
313
+ if (fuzzyNumbersEqual(prevSize, collapsedSize)) {
314
+ const localDelta = minSize - prevSize;
404
315
  //DEBUG.push(` -> expand delta: ${localDelta}`);
405
316
 
406
317
  if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
@@ -413,18 +324,26 @@ function adjustLayoutByDelta({
413
324
 
414
325
  {
415
326
  // Check if we should collapse a panel at its minimum size
416
- const index = delta < 0 ? pivotIndices[0] : pivotIndices[1];
417
- const constraints = panelConstraints[index];
327
+ const index = delta < 0 ? firstPivotIndex : secondPivotIndex;
328
+ const panelConstraints = panelConstraintsArray[index];
329
+ assert(panelConstraints);
330
+ const {
331
+ collapsible
332
+ } = panelConstraints;
333
+
418
334
  //DEBUG.push(`edge case check 2: ${index}`);
419
- //DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
420
- if (constraints.collapsible) {
335
+ //DEBUG.push(` -> collapsible? ${collapsible}`);
336
+ if (collapsible) {
421
337
  const prevSize = prevLayout[index];
338
+ assert(prevSize != null);
339
+ const panelConstraints = panelConstraintsArray[index];
340
+ assert(panelConstraints);
422
341
  const {
423
- collapsedSizePercentage,
424
- minSizePercentage
425
- } = computePercentagePanelConstraints(panelConstraints, index, groupSizePixels);
426
- if (fuzzyNumbersEqual(prevSize, minSizePercentage)) {
427
- const localDelta = prevSize - collapsedSizePercentage;
342
+ collapsedSize = 0,
343
+ minSize = 0
344
+ } = panelConstraints;
345
+ if (fuzzyNumbersEqual(prevSize, minSize)) {
346
+ const localDelta = prevSize - collapsedSize;
428
347
  //DEBUG.push(` -> expand delta: ${localDelta}`);
429
348
 
430
349
  if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
@@ -446,15 +365,15 @@ function adjustLayoutByDelta({
446
365
  // as an expanding panel might change from collapsed to min size.
447
366
 
448
367
  const increment = delta < 0 ? 1 : -1;
449
- let index = delta < 0 ? pivotIndices[1] : pivotIndices[0];
368
+ let index = delta < 0 ? secondPivotIndex : firstPivotIndex;
450
369
  let maxAvailableDelta = 0;
451
370
 
452
371
  //DEBUG.push("pre calc...");
453
372
  while (true) {
454
373
  const prevSize = prevLayout[index];
374
+ assert(prevSize != null);
455
375
  const maxSafeSize = resizePanel({
456
- groupSizePixels,
457
- panelConstraints,
376
+ panelConstraints: panelConstraintsArray,
458
377
  panelIndex: index,
459
378
  size: 100
460
379
  });
@@ -463,7 +382,7 @@ function adjustLayoutByDelta({
463
382
 
464
383
  maxAvailableDelta += delta;
465
384
  index += increment;
466
- if (index < 0 || index >= panelConstraints.length) {
385
+ if (index < 0 || index >= panelConstraintsArray.length) {
467
386
  break;
468
387
  }
469
388
  }
@@ -478,15 +397,15 @@ function adjustLayoutByDelta({
478
397
  {
479
398
  // Delta added to a panel needs to be subtracted from other panels (within the constraints that those panels allow).
480
399
 
481
- const pivotIndex = delta < 0 ? pivotIndices[0] : pivotIndices[1];
400
+ const pivotIndex = delta < 0 ? firstPivotIndex : secondPivotIndex;
482
401
  let index = pivotIndex;
483
- while (index >= 0 && index < panelConstraints.length) {
402
+ while (index >= 0 && index < panelConstraintsArray.length) {
484
403
  const deltaRemaining = Math.abs(delta) - Math.abs(deltaApplied);
485
404
  const prevSize = prevLayout[index];
405
+ assert(prevSize != null);
486
406
  const unsafeSize = prevSize - deltaRemaining;
487
407
  const safeSize = resizePanel({
488
- groupSizePixels,
489
- panelConstraints,
408
+ panelConstraints: panelConstraintsArray,
490
409
  panelIndex: index,
491
410
  size: unsafeSize
492
411
  });
@@ -518,11 +437,12 @@ function adjustLayoutByDelta({
518
437
  }
519
438
  {
520
439
  // Now distribute the applied delta to the panels in the other direction
521
- const pivotIndex = delta < 0 ? pivotIndices[1] : pivotIndices[0];
522
- const unsafeSize = prevLayout[pivotIndex] + deltaApplied;
440
+ const pivotIndex = delta < 0 ? secondPivotIndex : firstPivotIndex;
441
+ const prevSize = prevLayout[pivotIndex];
442
+ assert(prevSize != null);
443
+ const unsafeSize = prevSize + deltaApplied;
523
444
  const safeSize = resizePanel({
524
- groupSizePixels,
525
- panelConstraints,
445
+ panelConstraints: panelConstraintsArray,
526
446
  panelIndex: pivotIndex,
527
447
  size: unsafeSize
528
448
  });
@@ -533,14 +453,14 @@ function adjustLayoutByDelta({
533
453
  // Edge case where expanding or contracting one panel caused another one to change collapsed state
534
454
  if (!fuzzyNumbersEqual(safeSize, unsafeSize)) {
535
455
  let deltaRemaining = unsafeSize - safeSize;
536
- const pivotIndex = delta < 0 ? pivotIndices[1] : pivotIndices[0];
456
+ const pivotIndex = delta < 0 ? secondPivotIndex : firstPivotIndex;
537
457
  let index = pivotIndex;
538
- while (index >= 0 && index < panelConstraints.length) {
458
+ while (index >= 0 && index < panelConstraintsArray.length) {
539
459
  const prevSize = nextLayout[index];
460
+ assert(prevSize != null);
540
461
  const unsafeSize = prevSize + deltaRemaining;
541
462
  const safeSize = resizePanel({
542
- groupSizePixels,
543
- panelConstraints,
463
+ panelConstraints: panelConstraintsArray,
544
464
  panelIndex: index,
545
465
  size: unsafeSize
546
466
  });
@@ -564,9 +484,7 @@ function adjustLayoutByDelta({
564
484
  //DEBUG.push("");
565
485
 
566
486
  const totalSize = nextLayout.reduce((total, size) => size + total, 0);
567
- deltaApplied = 100 - totalSize;
568
487
  //DEBUG.push(`total size: ${totalSize}`);
569
- //DEBUG.push(` deltaApplied: ${deltaApplied}`);
570
488
  //console.log(DEBUG.join("\n"));
571
489
 
572
490
  if (!fuzzyNumbersEqual(totalSize, 100)) {
@@ -575,27 +493,7 @@ function adjustLayoutByDelta({
575
493
  return nextLayout;
576
494
  }
577
495
 
578
- function assert(expectedCondition, message = "Assertion failed!") {
579
- if (!expectedCondition) {
580
- console.error(message);
581
- throw Error(message);
582
- }
583
- }
584
-
585
- function getPercentageSizeFromMixedSizes({
586
- sizePercentage,
587
- sizePixels
588
- }, groupSizePixels) {
589
- if (sizePercentage != null) {
590
- return sizePercentage;
591
- } else if (sizePixels != null) {
592
- return convertPixelsToPercentage(sizePixels, groupSizePixels);
593
- }
594
- return undefined;
595
- }
596
-
597
496
  function calculateAriaValues({
598
- groupSizePixels,
599
497
  layout,
600
498
  panelsArray,
601
499
  pivotIndices
@@ -604,28 +502,19 @@ function calculateAriaValues({
604
502
  let currentMaxSize = 100;
605
503
  let totalMinSize = 0;
606
504
  let totalMaxSize = 0;
505
+ const firstIndex = pivotIndices[0];
506
+ assert(firstIndex != null);
607
507
 
608
508
  // A panel's effective min/max sizes also need to account for other panel's sizes.
609
509
  panelsArray.forEach((panelData, index) => {
610
- var _getPercentageSizeFro, _getPercentageSizeFro2;
611
510
  const {
612
511
  constraints
613
512
  } = panelData;
614
513
  const {
615
- maxSizePercentage,
616
- maxSizePixels,
617
- minSizePercentage,
618
- minSizePixels
514
+ maxSize = 100,
515
+ minSize = 0
619
516
  } = constraints;
620
- const minSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
621
- sizePercentage: minSizePercentage,
622
- sizePixels: minSizePixels
623
- }, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
624
- const maxSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
625
- sizePercentage: maxSizePercentage,
626
- sizePixels: maxSizePixels
627
- }, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 100;
628
- if (index === pivotIndices[0]) {
517
+ if (index === firstIndex) {
629
518
  currentMinSize = minSize;
630
519
  currentMaxSize = maxSize;
631
520
  } else {
@@ -635,7 +524,7 @@ function calculateAriaValues({
635
524
  });
636
525
  const valueMax = Math.min(currentMaxSize, 100 - totalMinSize);
637
526
  const valueMin = Math.max(currentMinSize, 100 - totalMaxSize);
638
- const valueNow = layout[pivotIndices[0]];
527
+ const valueNow = layout[firstIndex];
639
528
  return {
640
529
  valueMax,
641
530
  valueMin,
@@ -666,42 +555,6 @@ function getPanelGroupElement(id) {
666
555
  return null;
667
556
  }
668
557
 
669
- function calculateAvailablePanelSizeInPixels(groupId) {
670
- const panelGroupElement = getPanelGroupElement(groupId);
671
- if (panelGroupElement == null) {
672
- return NaN;
673
- }
674
- const direction = panelGroupElement.getAttribute("data-panel-group-direction");
675
- const resizeHandles = getResizeHandleElementsForGroup(groupId);
676
- if (direction === "horizontal") {
677
- return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
678
- return accumulated + handle.offsetWidth;
679
- }, 0);
680
- } else {
681
- return panelGroupElement.offsetHeight - resizeHandles.reduce((accumulated, handle) => {
682
- return accumulated + handle.offsetHeight;
683
- }, 0);
684
- }
685
- }
686
-
687
- function getAvailableGroupSizePixels(groupId) {
688
- const panelGroupElement = getPanelGroupElement(groupId);
689
- if (panelGroupElement == null) {
690
- return NaN;
691
- }
692
- const direction = panelGroupElement.getAttribute("data-panel-group-direction");
693
- const resizeHandles = getResizeHandleElementsForGroup(groupId);
694
- if (direction === "horizontal") {
695
- return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
696
- return accumulated + handle.offsetWidth;
697
- }, 0);
698
- } else {
699
- return panelGroupElement.offsetHeight - resizeHandles.reduce((accumulated, handle) => {
700
- return accumulated + handle.offsetHeight;
701
- }, 0);
702
- }
703
- }
704
-
705
558
  function getResizeHandleElement(id) {
706
559
  const element = document.querySelector(`[data-panel-resize-handle-id="${id}"]`);
707
560
  if (element) {
@@ -734,7 +587,6 @@ function useWindowSplitterPanelGroupBehavior({
734
587
  didWarnAboutMissingResizeHandle: false
735
588
  });
736
589
  useIsomorphicLayoutEffect(() => {
737
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
738
590
  const resizeHandleElements = getResizeHandleElementsForGroup(groupId);
739
591
  for (let index = 0; index < panelDataArray.length - 1; index++) {
740
592
  const {
@@ -742,7 +594,6 @@ function useWindowSplitterPanelGroupBehavior({
742
594
  valueMin,
743
595
  valueNow
744
596
  } = calculateAriaValues({
745
- groupSizePixels,
746
597
  layout,
747
598
  panelsArray: panelDataArray,
748
599
  pivotIndices: [index, index + 1]
@@ -759,10 +610,12 @@ function useWindowSplitterPanelGroupBehavior({
759
610
  }
760
611
  }
761
612
  } else {
762
- resizeHandleElement.setAttribute("aria-controls", panelDataArray[index].id);
613
+ const panelData = panelDataArray[index];
614
+ assert(panelData);
615
+ resizeHandleElement.setAttribute("aria-controls", panelData.id);
763
616
  resizeHandleElement.setAttribute("aria-valuemax", "" + Math.round(valueMax));
764
617
  resizeHandleElement.setAttribute("aria-valuemin", "" + Math.round(valueMin));
765
- resizeHandleElement.setAttribute("aria-valuenow", "" + Math.round(valueNow));
618
+ resizeHandleElement.setAttribute("aria-valuenow", valueNow != null ? "" + Math.round(valueNow) : "");
766
619
  }
767
620
  }
768
621
  return () => {
@@ -775,14 +628,18 @@ function useWindowSplitterPanelGroupBehavior({
775
628
  };
776
629
  }, [groupId, layout, panelDataArray]);
777
630
  useEffect(() => {
631
+ const eagerValues = eagerValuesRef.current;
632
+ assert(eagerValues);
778
633
  const {
779
634
  panelDataArray
780
- } = eagerValuesRef.current;
635
+ } = eagerValues;
781
636
  const groupElement = getPanelGroupElement(groupId);
782
637
  assert(groupElement != null, `No group found for id "${groupId}"`);
783
638
  const handles = getResizeHandleElementsForGroup(groupId);
639
+ assert(handles);
784
640
  const cleanupFunctions = handles.map(handle => {
785
641
  const handleId = handle.getAttribute("data-panel-resize-handle-id");
642
+ assert(handleId);
786
643
  const [idBefore, idAfter] = getResizeHandlePanelIds(groupId, handleId, panelDataArray);
787
644
  if (idBefore == null || idAfter == null) {
788
645
  return () => {};
@@ -798,21 +655,16 @@ function useWindowSplitterPanelGroupBehavior({
798
655
  const index = panelDataArray.findIndex(panelData => panelData.id === idBefore);
799
656
  if (index >= 0) {
800
657
  const panelData = panelDataArray[index];
658
+ assert(panelData);
801
659
  const size = layout[index];
802
- if (size != null && panelData.constraints.collapsible) {
803
- var _getPercentageSizeFro, _getPercentageSizeFro2;
804
- const groupSizePixels = getAvailableGroupSizePixels(groupId);
805
- const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
806
- sizePercentage: panelData.constraints.collapsedSizePercentage,
807
- sizePixels: panelData.constraints.collapsedSizePixels
808
- }, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
809
- const minSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
810
- sizePercentage: panelData.constraints.minSizePercentage,
811
- sizePixels: panelData.constraints.minSizePixels
812
- }, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 0;
660
+ const {
661
+ collapsedSize = 0,
662
+ collapsible,
663
+ minSize = 0
664
+ } = panelData.constraints;
665
+ if (size != null && collapsible) {
813
666
  const nextLayout = adjustLayoutByDelta({
814
667
  delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
815
- groupSizePixels,
816
668
  layout,
817
669
  panelConstraints: panelDataArray.map(panelData => panelData.constraints),
818
670
  pivotIndices: determinePivotIndices(groupId, handleId),
@@ -866,6 +718,7 @@ function getResizeEventCursorPosition(direction, event) {
866
718
  return isHorizontal ? event.clientX : event.clientY;
867
719
  } else if (isTouchEvent(event)) {
868
720
  const firstTouch = event.touches[0];
721
+ assert(firstTouch);
869
722
  return isHorizontal ? firstTouch.screenX : firstTouch.screenY;
870
723
  } else {
871
724
  throw Error(`Unsupported event type "${event.type}"`);
@@ -875,12 +728,15 @@ function getResizeEventCursorPosition(direction, event) {
875
728
  function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState) {
876
729
  const isHorizontal = direction === "horizontal";
877
730
  const handleElement = getResizeHandleElement(dragHandleId);
731
+ assert(handleElement);
878
732
  const groupId = handleElement.getAttribute("data-panel-group-id");
733
+ assert(groupId);
879
734
  let {
880
735
  initialCursorPosition
881
736
  } = initialDragState;
882
737
  const cursorPosition = getResizeEventCursorPosition(direction, event);
883
738
  const groupElement = getPanelGroupElement(groupId);
739
+ assert(groupElement);
884
740
  const groupRect = groupElement.getBoundingClientRect();
885
741
  const groupSizeInPixels = isHorizontal ? groupRect.width : groupRect.height;
886
742
  const offsetPixels = cursorPosition - initialCursorPosition;
@@ -889,19 +745,14 @@ function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDr
889
745
  }
890
746
 
891
747
  // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/movementX
892
- function calculateDeltaPercentage(event, groupId, dragHandleId, direction, initialDragState, keyboardResizeByOptions) {
748
+ function calculateDeltaPercentage(event, dragHandleId, direction, initialDragState, keyboardResizeBy) {
893
749
  if (isKeyDown(event)) {
894
750
  const isHorizontal = direction === "horizontal";
895
- const groupElement = getPanelGroupElement(groupId);
896
- const rect = groupElement.getBoundingClientRect();
897
- const groupSizeInPixels = isHorizontal ? rect.width : rect.height;
898
751
  let delta = 0;
899
752
  if (event.shiftKey) {
900
753
  delta = 100;
901
- } else if (keyboardResizeByOptions.percentage != null) {
902
- delta = keyboardResizeByOptions.percentage;
903
- } else if (keyboardResizeByOptions.pixels != null) {
904
- delta = keyboardResizeByOptions.pixels / groupSizeInPixels;
754
+ } else if (keyboardResizeBy != null) {
755
+ delta = keyboardResizeBy;
905
756
  } else {
906
757
  delta = 10;
907
758
  }
@@ -928,37 +779,43 @@ function calculateDeltaPercentage(event, groupId, dragHandleId, direction, initi
928
779
  }
929
780
  return movement;
930
781
  } else {
782
+ if (initialDragState == null) {
783
+ return 0;
784
+ }
931
785
  return calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState);
932
786
  }
933
787
  }
934
788
 
935
789
  function calculateUnsafeDefaultLayout({
936
- groupSizePixels,
937
790
  panelDataArray
938
791
  }) {
939
792
  const layout = Array(panelDataArray.length);
940
- const panelDataConstraints = panelDataArray.map(panelData => panelData.constraints);
793
+ const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
941
794
  let numPanelsWithSizes = 0;
942
795
  let remainingSize = 100;
943
796
 
944
797
  // Distribute default sizes first
945
798
  for (let index = 0; index < panelDataArray.length; index++) {
799
+ const panelConstraints = panelConstraintsArray[index];
800
+ assert(panelConstraints);
946
801
  const {
947
- defaultSizePercentage
948
- } = computePercentagePanelConstraints(panelDataConstraints, index, groupSizePixels);
949
- if (defaultSizePercentage != null) {
802
+ defaultSize
803
+ } = panelConstraints;
804
+ if (defaultSize != null) {
950
805
  numPanelsWithSizes++;
951
- layout[index] = defaultSizePercentage;
952
- remainingSize -= defaultSizePercentage;
806
+ layout[index] = defaultSize;
807
+ remainingSize -= defaultSize;
953
808
  }
954
809
  }
955
810
 
956
811
  // Remaining size should be distributed evenly between panels without default sizes
957
812
  for (let index = 0; index < panelDataArray.length; index++) {
813
+ const panelConstraints = panelConstraintsArray[index];
814
+ assert(panelConstraints);
958
815
  const {
959
- defaultSizePercentage
960
- } = computePercentagePanelConstraints(panelDataConstraints, index, groupSizePixels);
961
- if (defaultSizePercentage != null) {
816
+ defaultSize
817
+ } = panelConstraints;
818
+ if (defaultSize != null) {
962
819
  continue;
963
820
  }
964
821
  const numRemainingPanels = panelDataArray.length - numPanelsWithSizes;
@@ -970,54 +827,36 @@ function calculateUnsafeDefaultLayout({
970
827
  return layout;
971
828
  }
972
829
 
973
- function convertPercentageToPixels(percentage, groupSizePixels) {
974
- return percentage / 100 * groupSizePixels;
975
- }
976
-
977
830
  // Layout should be pre-converted into percentages
978
- function callPanelCallbacks(groupId, panelsArray, layout, panelIdToLastNotifiedMixedSizesMap) {
979
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
980
- layout.forEach((sizePercentage, index) => {
831
+ function callPanelCallbacks(panelsArray, layout, panelIdToLastNotifiedSizeMap) {
832
+ layout.forEach((size, index) => {
981
833
  const panelData = panelsArray[index];
982
- if (!panelData) {
983
- // Handle initial mount (when panels are registered too late to be in the panels array)
984
- // The subsequent render+effects will handle the resize notification
985
- return;
986
- }
834
+ assert(panelData);
987
835
  const {
988
836
  callbacks,
989
837
  constraints,
990
838
  id: panelId
991
839
  } = panelData;
992
840
  const {
841
+ collapsedSize = 0,
993
842
  collapsible
994
843
  } = constraints;
995
- const mixedSizes = {
996
- sizePercentage,
997
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
998
- };
999
- const lastNotifiedMixedSizes = panelIdToLastNotifiedMixedSizesMap[panelId];
1000
- if (lastNotifiedMixedSizes == null || mixedSizes.sizePercentage !== lastNotifiedMixedSizes.sizePercentage || mixedSizes.sizePixels !== lastNotifiedMixedSizes.sizePixels) {
1001
- panelIdToLastNotifiedMixedSizesMap[panelId] = mixedSizes;
844
+ const lastNotifiedSize = panelIdToLastNotifiedSizeMap[panelId];
845
+ if (lastNotifiedSize == null || size !== lastNotifiedSize) {
846
+ panelIdToLastNotifiedSizeMap[panelId] = size;
1002
847
  const {
1003
848
  onCollapse,
1004
849
  onExpand,
1005
850
  onResize
1006
851
  } = callbacks;
1007
852
  if (onResize) {
1008
- onResize(mixedSizes, lastNotifiedMixedSizes);
853
+ onResize(size, lastNotifiedSize);
1009
854
  }
1010
855
  if (collapsible && (onCollapse || onExpand)) {
1011
- var _getPercentageSizeFro;
1012
- const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
1013
- sizePercentage: constraints.collapsedSizePercentage,
1014
- sizePixels: constraints.collapsedSizePixels
1015
- }, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
1016
- const size = getPercentageSizeFromMixedSizes(mixedSizes, groupSizePixels);
1017
- if (onExpand && (lastNotifiedMixedSizes == null || lastNotifiedMixedSizes.sizePercentage === collapsedSize) && size !== collapsedSize) {
856
+ if (onExpand && (lastNotifiedSize == null || lastNotifiedSize === collapsedSize) && size !== collapsedSize) {
1018
857
  onExpand();
1019
858
  }
1020
- if (onCollapse && (lastNotifiedMixedSizes == null || lastNotifiedMixedSizes.sizePercentage !== collapsedSize) && size === collapsedSize) {
859
+ if (onCollapse && (lastNotifiedSize == null || lastNotifiedSize !== collapsedSize) && size === collapsedSize) {
1021
860
  onCollapse();
1022
861
  }
1023
862
  }
@@ -1200,74 +1039,39 @@ function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
1200
1039
  }
1201
1040
  }
1202
1041
 
1203
- function shouldMonitorPixelBasedConstraints(constraints) {
1204
- return constraints.some(constraints => {
1205
- return constraints.collapsedSizePixels !== undefined || constraints.maxSizePixels !== undefined || constraints.minSizePixels !== undefined;
1206
- });
1207
- }
1208
-
1209
1042
  function validatePanelConstraints({
1210
- groupSizePixels,
1211
- panelConstraints,
1043
+ panelConstraints: panelConstraintsArray,
1212
1044
  panelId,
1213
1045
  panelIndex
1214
1046
  }) {
1215
1047
  {
1216
1048
  const warnings = [];
1217
- {
1218
- const {
1219
- collapsedSizePercentage,
1220
- collapsedSizePixels,
1221
- defaultSizePercentage,
1222
- defaultSizePixels,
1223
- maxSizePercentage,
1224
- maxSizePixels,
1225
- minSizePercentage,
1226
- minSizePixels
1227
- } = panelConstraints[panelIndex];
1228
- const conflictingUnits = [];
1229
- if (collapsedSizePercentage != null && collapsedSizePixels != null) {
1230
- conflictingUnits.push("collapsed size");
1231
- }
1232
- if (defaultSizePercentage != null && defaultSizePixels != null) {
1233
- conflictingUnits.push("default size");
1234
- }
1235
- if (maxSizePercentage != null && maxSizePixels != null) {
1236
- conflictingUnits.push("max size");
1237
- }
1238
- if (minSizePercentage != null && minSizePixels != null) {
1239
- conflictingUnits.push("min size");
1240
- }
1241
- if (conflictingUnits.length > 0) {
1242
- warnings.push(`should not specify both percentage and pixel units for: ${conflictingUnits.join(", ")}`);
1243
- }
1049
+ const panelConstraints = panelConstraintsArray[panelIndex];
1050
+ assert(panelConstraints);
1051
+ const {
1052
+ collapsedSize = 0,
1053
+ defaultSize,
1054
+ maxSize = 100,
1055
+ minSize = 0
1056
+ } = panelConstraints;
1057
+ if (minSize > maxSize) {
1058
+ warnings.push(`min size (${minSize}%) should not be greater than max size (${maxSize}%)`);
1244
1059
  }
1245
- {
1246
- const {
1247
- collapsedSizePercentage,
1248
- defaultSizePercentage,
1249
- maxSizePercentage,
1250
- minSizePercentage
1251
- } = computePercentagePanelConstraints(panelConstraints, panelIndex, groupSizePixels);
1252
- if (minSizePercentage > maxSizePercentage) {
1253
- warnings.push(`min size (${minSizePercentage}%) should not be greater than max size (${maxSizePercentage}%)`);
1254
- }
1255
- if (defaultSizePercentage != null) {
1256
- if (defaultSizePercentage < 0) {
1257
- warnings.push("default size should not be less than 0");
1258
- } else if (defaultSizePercentage < minSizePercentage) {
1259
- warnings.push("default size should not be less than min size");
1260
- }
1261
- if (defaultSizePercentage > 100) {
1262
- warnings.push("default size should not be greater than 100");
1263
- } else if (defaultSizePercentage > maxSizePercentage) {
1264
- warnings.push("default size should not be greater than max size");
1265
- }
1060
+ if (defaultSize != null) {
1061
+ if (defaultSize < 0) {
1062
+ warnings.push("default size should not be less than 0");
1063
+ } else if (defaultSize < minSize) {
1064
+ warnings.push("default size should not be less than min size");
1266
1065
  }
1267
- if (collapsedSizePercentage > minSizePercentage) {
1268
- warnings.push("collapsed size should not be greater than min size");
1066
+ if (defaultSize > 100) {
1067
+ warnings.push("default size should not be greater than 100");
1068
+ } else if (defaultSize > maxSize) {
1069
+ warnings.push("default size should not be greater than max size");
1269
1070
  }
1270
1071
  }
1072
+ if (collapsedSize > minSize) {
1073
+ warnings.push("collapsed size should not be greater than min size");
1074
+ }
1271
1075
  if (warnings.length > 0) {
1272
1076
  const name = panelId != null ? `Panel "${panelId}"` : "Panel";
1273
1077
  console.warn(`${name} has an invalid configuration:\n\n${warnings.join("\n")}`);
@@ -1279,20 +1083,26 @@ function validatePanelConstraints({
1279
1083
 
1280
1084
  // All units must be in percentages; pixel values should be pre-converted
1281
1085
  function validatePanelGroupLayout({
1282
- groupSizePixels,
1283
1086
  layout: prevLayout,
1284
1087
  panelConstraints
1285
1088
  }) {
1286
1089
  const nextLayout = [...prevLayout];
1090
+ const nextLayoutTotalSize = nextLayout.reduce((accumulated, current) => accumulated + current, 0);
1287
1091
 
1288
1092
  // Validate layout expectations
1289
1093
  if (nextLayout.length !== panelConstraints.length) {
1290
1094
  throw Error(`Invalid ${panelConstraints.length} panel layout: ${nextLayout.map(size => `${size}%`).join(", ")}`);
1291
- } else if (!fuzzyNumbersEqual(nextLayout.reduce((accumulated, current) => accumulated + current, 0), 100)) {
1095
+ } else if (!fuzzyNumbersEqual(nextLayoutTotalSize, 100)) {
1292
1096
  // This is not ideal so we should warn about it, but it may be recoverable in some cases
1293
1097
  // (especially if the amount is small)
1294
1098
  {
1295
- console.warn(`WARNING: Invalid layout total size: ${nextLayout.map(size => `${size}%`).join(", ")}`);
1099
+ console.warn(`WARNING: Invalid layout total size: ${nextLayout.map(size => `${size}%`).join(", ")}. Layout normalization will be applied.`);
1100
+ }
1101
+ for (let index = 0; index < panelConstraints.length; index++) {
1102
+ const unsafeSize = nextLayout[index];
1103
+ assert(unsafeSize != null);
1104
+ const safeSize = 100 / nextLayoutTotalSize * unsafeSize;
1105
+ nextLayout[index] = safeSize;
1296
1106
  }
1297
1107
  }
1298
1108
  let remainingSize = 0;
@@ -1300,8 +1110,8 @@ function validatePanelGroupLayout({
1300
1110
  // First pass: Validate the proposed layout given each panel's constraints
1301
1111
  for (let index = 0; index < panelConstraints.length; index++) {
1302
1112
  const unsafeSize = nextLayout[index];
1113
+ assert(unsafeSize != null);
1303
1114
  const safeSize = resizePanel({
1304
- groupSizePixels,
1305
1115
  panelConstraints,
1306
1116
  panelIndex: index,
1307
1117
  size: unsafeSize
@@ -1317,9 +1127,9 @@ function validatePanelGroupLayout({
1317
1127
  if (!fuzzyNumbersEqual(remainingSize, 0)) {
1318
1128
  for (let index = 0; index < panelConstraints.length; index++) {
1319
1129
  const prevSize = nextLayout[index];
1130
+ assert(prevSize != null);
1320
1131
  const unsafeSize = prevSize + remainingSize;
1321
1132
  const safeSize = resizePanel({
1322
- groupSizePixels,
1323
1133
  panelConstraints,
1324
1134
  panelIndex: index,
1325
1135
  size: unsafeSize
@@ -1354,21 +1164,20 @@ function PanelGroupWithForwardedRef({
1354
1164
  autoSaveId = null,
1355
1165
  children,
1356
1166
  className: classNameFromProps = "",
1357
- dataAttributes,
1358
1167
  direction,
1359
1168
  forwardedRef,
1360
- id: idFromProps,
1169
+ id: idFromProps = null,
1361
1170
  onLayout = null,
1362
- keyboardResizeByPercentage = null,
1363
- keyboardResizeByPixels = null,
1171
+ keyboardResizeBy = null,
1364
1172
  storage = defaultStorage,
1365
1173
  style: styleFromProps,
1366
- tagName: Type = "div"
1174
+ tagName: Type = "div",
1175
+ ...rest
1367
1176
  }) {
1368
1177
  const groupId = useUniqueId(idFromProps);
1369
1178
  const [dragState, setDragState] = useState(null);
1370
1179
  const [layout, setLayout] = useState([]);
1371
- const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
1180
+ const panelIdToLastNotifiedSizeMapRef = useRef({});
1372
1181
  const panelSizeBeforeCollapseRef = useRef(new Map());
1373
1182
  const prevDeltaRef = useRef(0);
1374
1183
  const committedValuesRef = useRef({
@@ -1376,8 +1185,7 @@ function PanelGroupWithForwardedRef({
1376
1185
  direction,
1377
1186
  dragState,
1378
1187
  id: groupId,
1379
- keyboardResizeByPercentage,
1380
- keyboardResizeByPixels,
1188
+ keyboardResizeBy,
1381
1189
  onLayout,
1382
1190
  storage
1383
1191
  });
@@ -1393,33 +1201,20 @@ function PanelGroupWithForwardedRef({
1393
1201
  useImperativeHandle(forwardedRef, () => ({
1394
1202
  getId: () => committedValuesRef.current.id,
1395
1203
  getLayout: () => {
1396
- const {
1397
- id: groupId
1398
- } = committedValuesRef.current;
1399
1204
  const {
1400
1205
  layout
1401
1206
  } = eagerValuesRef.current;
1402
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1403
- return layout.map(sizePercentage => {
1404
- return {
1405
- sizePercentage,
1406
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1407
- };
1408
- });
1207
+ return layout;
1409
1208
  },
1410
- setLayout: mixedSizes => {
1209
+ setLayout: unsafeLayout => {
1411
1210
  const {
1412
- id: groupId,
1413
1211
  onLayout
1414
1212
  } = committedValuesRef.current;
1415
1213
  const {
1416
1214
  layout: prevLayout,
1417
1215
  panelDataArray
1418
1216
  } = eagerValuesRef.current;
1419
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1420
- const unsafeLayout = mixedSizes.map(mixedSize => getPercentageSizeFromMixedSizes(mixedSize, groupSizePixels));
1421
1217
  const safeLayout = validatePanelGroupLayout({
1422
- groupSizePixels,
1423
1218
  layout: unsafeLayout,
1424
1219
  panelConstraints: panelDataArray.map(panelData => panelData.constraints)
1425
1220
  });
@@ -1427,12 +1222,9 @@ function PanelGroupWithForwardedRef({
1427
1222
  setLayout(safeLayout);
1428
1223
  eagerValuesRef.current.layout = safeLayout;
1429
1224
  if (onLayout) {
1430
- onLayout(safeLayout.map(sizePercentage => ({
1431
- sizePercentage,
1432
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1433
- })));
1225
+ onLayout(safeLayout);
1434
1226
  }
1435
- callPanelCallbacks(groupId, panelDataArray, safeLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1227
+ callPanelCallbacks(panelDataArray, safeLayout, panelIdToLastNotifiedSizeMapRef.current);
1436
1228
  }
1437
1229
  }
1438
1230
  }), []);
@@ -1443,11 +1235,7 @@ function PanelGroupWithForwardedRef({
1443
1235
  committedValuesRef.current.id = groupId;
1444
1236
  committedValuesRef.current.onLayout = onLayout;
1445
1237
  committedValuesRef.current.storage = storage;
1446
-
1447
- // panelDataArray and layout are updated in-sync with scheduled state updates.
1448
- // TODO [217] Move these values into a separate ref
1449
1238
  });
1450
-
1451
1239
  useWindowSplitterPanelGroupBehavior({
1452
1240
  committedValuesRef,
1453
1241
  eagerValuesRef,
@@ -1466,57 +1254,16 @@ function PanelGroupWithForwardedRef({
1466
1254
  if (layout.length === 0 || layout.length !== panelDataArray.length) {
1467
1255
  return;
1468
1256
  }
1257
+ let debouncedSave = debounceMap[autoSaveId];
1469
1258
 
1470
1259
  // Limit the frequency of localStorage updates.
1471
- if (!debounceMap[autoSaveId]) {
1472
- debounceMap[autoSaveId] = debounce(savePanelGroupLayout, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
1260
+ if (debouncedSave == null) {
1261
+ debouncedSave = debounce(savePanelGroupLayout, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
1262
+ debounceMap[autoSaveId] = debouncedSave;
1473
1263
  }
1474
- debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
1264
+ debouncedSave(autoSaveId, panelDataArray, layout, storage);
1475
1265
  }
1476
1266
  }, [autoSaveId, layout, storage]);
1477
- useIsomorphicLayoutEffect(() => {
1478
- const {
1479
- layout: prevLayout,
1480
- panelDataArray
1481
- } = eagerValuesRef.current;
1482
- const constraints = panelDataArray.map(({
1483
- constraints
1484
- }) => constraints);
1485
- if (!shouldMonitorPixelBasedConstraints(constraints)) {
1486
- // Avoid the overhead of ResizeObserver if no pixel constraints require monitoring
1487
- return;
1488
- }
1489
- if (typeof ResizeObserver === "undefined") {
1490
- console.warn(`WARNING: Pixel based constraints require ResizeObserver but it is not supported by the current browser.`);
1491
- } else {
1492
- const resizeObserver = new ResizeObserver(() => {
1493
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1494
- const {
1495
- onLayout
1496
- } = committedValuesRef.current;
1497
- const nextLayout = validatePanelGroupLayout({
1498
- groupSizePixels,
1499
- layout: prevLayout,
1500
- panelConstraints: panelDataArray.map(panelData => panelData.constraints)
1501
- });
1502
- if (!areEqual(prevLayout, nextLayout)) {
1503
- setLayout(nextLayout);
1504
- eagerValuesRef.current.layout = nextLayout;
1505
- if (onLayout) {
1506
- onLayout(nextLayout.map(sizePercentage => ({
1507
- sizePercentage,
1508
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1509
- })));
1510
- }
1511
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1512
- }
1513
- });
1514
- resizeObserver.observe(getPanelGroupElement(groupId));
1515
- return () => {
1516
- resizeObserver.disconnect();
1517
- };
1518
- }
1519
- }, [groupId]);
1520
1267
 
1521
1268
  // DEV warnings
1522
1269
  useEffect(() => {
@@ -1547,12 +1294,12 @@ function PanelGroupWithForwardedRef({
1547
1294
  }
1548
1295
  if (!didLogPanelConstraintsWarning) {
1549
1296
  const panelConstraints = panelDataArray.map(panelData => panelData.constraints);
1550
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1551
1297
  for (let panelIndex = 0; panelIndex < panelConstraints.length; panelIndex++) {
1298
+ const panelData = panelDataArray[panelIndex];
1299
+ assert(panelData);
1552
1300
  const isValid = validatePanelConstraints({
1553
- groupSizePixels,
1554
1301
  panelConstraints,
1555
- panelId: panelDataArray[panelIndex].id,
1302
+ panelId: panelData.id,
1556
1303
  panelIndex
1557
1304
  });
1558
1305
  if (!isValid) {
@@ -1576,20 +1323,19 @@ function PanelGroupWithForwardedRef({
1576
1323
  if (panelData.constraints.collapsible) {
1577
1324
  const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
1578
1325
  const {
1579
- collapsedSizePercentage,
1580
- panelSizePercentage,
1581
- pivotIndices,
1582
- groupSizePixels
1583
- } = panelDataHelper(groupId, panelDataArray, panelData, prevLayout);
1584
- if (panelSizePercentage !== collapsedSizePercentage) {
1326
+ collapsedSize = 0,
1327
+ panelSize,
1328
+ pivotIndices
1329
+ } = panelDataHelper(panelDataArray, panelData, prevLayout);
1330
+ assert(panelSize != null);
1331
+ if (panelSize !== collapsedSize) {
1585
1332
  // Store size before collapse;
1586
1333
  // This is the size that gets restored if the expand() API is used.
1587
- panelSizeBeforeCollapseRef.current.set(panelData.id, panelSizePercentage);
1334
+ panelSizeBeforeCollapseRef.current.set(panelData.id, panelSize);
1588
1335
  const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
1589
- const delta = isLastPanel ? panelSizePercentage - collapsedSizePercentage : collapsedSizePercentage - panelSizePercentage;
1336
+ const delta = isLastPanel ? panelSize - collapsedSize : collapsedSize - panelSize;
1590
1337
  const nextLayout = adjustLayoutByDelta({
1591
1338
  delta,
1592
- groupSizePixels,
1593
1339
  layout: prevLayout,
1594
1340
  panelConstraints: panelConstraintsArray,
1595
1341
  pivotIndices,
@@ -1599,16 +1345,13 @@ function PanelGroupWithForwardedRef({
1599
1345
  setLayout(nextLayout);
1600
1346
  eagerValuesRef.current.layout = nextLayout;
1601
1347
  if (onLayout) {
1602
- onLayout(nextLayout.map(sizePercentage => ({
1603
- sizePercentage,
1604
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1605
- })));
1348
+ onLayout(nextLayout);
1606
1349
  }
1607
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1350
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1608
1351
  }
1609
1352
  }
1610
1353
  }
1611
- }, [groupId]);
1354
+ }, []);
1612
1355
 
1613
1356
  // External APIs are safe to memoize via committed values ref
1614
1357
  const expandPanel = useCallback(panelData => {
@@ -1622,21 +1365,19 @@ function PanelGroupWithForwardedRef({
1622
1365
  if (panelData.constraints.collapsible) {
1623
1366
  const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
1624
1367
  const {
1625
- collapsedSizePercentage,
1626
- panelSizePercentage,
1627
- minSizePercentage,
1628
- pivotIndices,
1629
- groupSizePixels
1630
- } = panelDataHelper(groupId, panelDataArray, panelData, prevLayout);
1631
- if (panelSizePercentage === collapsedSizePercentage) {
1368
+ collapsedSize = 0,
1369
+ panelSize,
1370
+ minSize = 0,
1371
+ pivotIndices
1372
+ } = panelDataHelper(panelDataArray, panelData, prevLayout);
1373
+ if (panelSize === collapsedSize) {
1632
1374
  // Restore this panel to the size it was before it was collapsed, if possible.
1633
- const prevPanelSizePercentage = panelSizeBeforeCollapseRef.current.get(panelData.id);
1634
- const baseSizePercentage = prevPanelSizePercentage != null && prevPanelSizePercentage >= minSizePercentage ? prevPanelSizePercentage : minSizePercentage;
1375
+ const prevPanelSize = panelSizeBeforeCollapseRef.current.get(panelData.id);
1376
+ const baseSize = prevPanelSize != null && prevPanelSize >= minSize ? prevPanelSize : minSize;
1635
1377
  const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
1636
- const delta = isLastPanel ? panelSizePercentage - baseSizePercentage : baseSizePercentage - panelSizePercentage;
1378
+ const delta = isLastPanel ? panelSize - baseSize : baseSize - panelSize;
1637
1379
  const nextLayout = adjustLayoutByDelta({
1638
1380
  delta,
1639
- groupSizePixels,
1640
1381
  layout: prevLayout,
1641
1382
  panelConstraints: panelConstraintsArray,
1642
1383
  pivotIndices,
@@ -1646,16 +1387,13 @@ function PanelGroupWithForwardedRef({
1646
1387
  setLayout(nextLayout);
1647
1388
  eagerValuesRef.current.layout = nextLayout;
1648
1389
  if (onLayout) {
1649
- onLayout(nextLayout.map(sizePercentage => ({
1650
- sizePercentage,
1651
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1652
- })));
1390
+ onLayout(nextLayout);
1653
1391
  }
1654
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1392
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1655
1393
  }
1656
1394
  }
1657
1395
  }
1658
- }, [groupId]);
1396
+ }, []);
1659
1397
 
1660
1398
  // External APIs are safe to memoize via committed values ref
1661
1399
  const getPanelSize = useCallback(panelData => {
@@ -1664,14 +1402,11 @@ function PanelGroupWithForwardedRef({
1664
1402
  panelDataArray
1665
1403
  } = eagerValuesRef.current;
1666
1404
  const {
1667
- panelSizePercentage,
1668
- panelSizePixels
1669
- } = panelDataHelper(groupId, panelDataArray, panelData, layout);
1670
- return {
1671
- sizePercentage: panelSizePercentage,
1672
- sizePixels: panelSizePixels
1673
- };
1674
- }, [groupId]);
1405
+ panelSize
1406
+ } = panelDataHelper(panelDataArray, panelData, layout);
1407
+ assert(panelSize != null);
1408
+ return panelSize;
1409
+ }, []);
1675
1410
 
1676
1411
  // This API should never read from committedValuesRef
1677
1412
  const getPanelStyle = useCallback(panelData => {
@@ -1694,12 +1429,12 @@ function PanelGroupWithForwardedRef({
1694
1429
  panelDataArray
1695
1430
  } = eagerValuesRef.current;
1696
1431
  const {
1697
- collapsedSizePercentage,
1432
+ collapsedSize,
1698
1433
  collapsible,
1699
- panelSizePercentage
1700
- } = panelDataHelper(groupId, panelDataArray, panelData, layout);
1701
- return collapsible === true && panelSizePercentage === collapsedSizePercentage;
1702
- }, [groupId]);
1434
+ panelSize
1435
+ } = panelDataHelper(panelDataArray, panelData, layout);
1436
+ return collapsible === true && panelSize === collapsedSize;
1437
+ }, []);
1703
1438
 
1704
1439
  // External APIs are safe to memoize via committed values ref
1705
1440
  const isPanelExpanded = useCallback(panelData => {
@@ -1708,12 +1443,13 @@ function PanelGroupWithForwardedRef({
1708
1443
  panelDataArray
1709
1444
  } = eagerValuesRef.current;
1710
1445
  const {
1711
- collapsedSizePercentage,
1446
+ collapsedSize = 0,
1712
1447
  collapsible,
1713
- panelSizePercentage
1714
- } = panelDataHelper(groupId, panelDataArray, panelData, layout);
1715
- return !collapsible || panelSizePercentage > collapsedSizePercentage;
1716
- }, [groupId]);
1448
+ panelSize
1449
+ } = panelDataHelper(panelDataArray, panelData, layout);
1450
+ assert(panelSize != null);
1451
+ return !collapsible || panelSize > collapsedSize;
1452
+ }, []);
1717
1453
  const registerPanel = useCallback(panelData => {
1718
1454
  const {
1719
1455
  autoSaveId,
@@ -1753,18 +1489,8 @@ function PanelGroupWithForwardedRef({
1753
1489
  if (autoSaveId) {
1754
1490
  unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
1755
1491
  }
1756
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1757
- if (groupSizePixels <= 0) {
1758
- if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
1759
- constraints
1760
- }) => constraints))) {
1761
- // Wait until the group has rendered a non-zero size before computing layout.
1762
- return;
1763
- }
1764
- }
1765
1492
  if (unsafeLayout == null) {
1766
1493
  unsafeLayout = calculateUnsafeDefaultLayout({
1767
- groupSizePixels,
1768
1494
  panelDataArray
1769
1495
  });
1770
1496
  }
@@ -1772,7 +1498,6 @@ function PanelGroupWithForwardedRef({
1772
1498
  // Validate even saved layouts in case something has changed since last render
1773
1499
  // e.g. for pixel groups, this could be the size of the window
1774
1500
  const nextLayout = validatePanelGroupLayout({
1775
- groupSizePixels,
1776
1501
  layout: unsafeLayout,
1777
1502
  panelConstraints: panelDataArray.map(panelData => panelData.constraints)
1778
1503
  });
@@ -1784,12 +1509,9 @@ function PanelGroupWithForwardedRef({
1784
1509
  eagerValuesRef.current.layout = nextLayout;
1785
1510
  if (!areEqual(prevLayout, nextLayout)) {
1786
1511
  if (onLayout) {
1787
- onLayout(nextLayout.map(sizePercentage => ({
1788
- sizePercentage,
1789
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1790
- })));
1512
+ onLayout(nextLayout);
1791
1513
  }
1792
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1514
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1793
1515
  }
1794
1516
  }, []);
1795
1517
  const registerResizeHandle = useCallback(dragHandleId => {
@@ -1799,8 +1521,7 @@ function PanelGroupWithForwardedRef({
1799
1521
  direction,
1800
1522
  dragState,
1801
1523
  id: groupId,
1802
- keyboardResizeByPercentage,
1803
- keyboardResizeByPixels,
1524
+ keyboardResizeBy,
1804
1525
  onLayout
1805
1526
  } = committedValuesRef.current;
1806
1527
  const {
@@ -1811,10 +1532,7 @@ function PanelGroupWithForwardedRef({
1811
1532
  initialLayout
1812
1533
  } = dragState !== null && dragState !== void 0 ? dragState : {};
1813
1534
  const pivotIndices = determinePivotIndices(groupId, dragHandleId);
1814
- let delta = calculateDeltaPercentage(event, groupId, dragHandleId, direction, dragState, {
1815
- percentage: keyboardResizeByPercentage,
1816
- pixels: keyboardResizeByPixels
1817
- });
1535
+ let delta = calculateDeltaPercentage(event, dragHandleId, direction, dragState, keyboardResizeBy);
1818
1536
  if (delta === 0) {
1819
1537
  return;
1820
1538
  }
@@ -1824,11 +1542,9 @@ function PanelGroupWithForwardedRef({
1824
1542
  if (document.dir === "rtl" && isHorizontal) {
1825
1543
  delta = -delta;
1826
1544
  }
1827
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1828
1545
  const panelConstraints = panelDataArray.map(panelData => panelData.constraints);
1829
1546
  const nextLayout = adjustLayoutByDelta({
1830
1547
  delta,
1831
- groupSizePixels,
1832
1548
  layout: initialLayout !== null && initialLayout !== void 0 ? initialLayout : prevLayout,
1833
1549
  panelConstraints,
1834
1550
  pivotIndices,
@@ -1864,18 +1580,15 @@ function PanelGroupWithForwardedRef({
1864
1580
  setLayout(nextLayout);
1865
1581
  eagerValuesRef.current.layout = nextLayout;
1866
1582
  if (onLayout) {
1867
- onLayout(nextLayout.map(sizePercentage => ({
1868
- sizePercentage,
1869
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1870
- })));
1583
+ onLayout(nextLayout);
1871
1584
  }
1872
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1585
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1873
1586
  }
1874
1587
  };
1875
1588
  }, []);
1876
1589
 
1877
1590
  // External APIs are safe to memoize via committed values ref
1878
- const resizePanel = useCallback((panelData, mixedSizes) => {
1591
+ const resizePanel = useCallback((panelData, unsafePanelSize) => {
1879
1592
  const {
1880
1593
  onLayout
1881
1594
  } = committedValuesRef.current;
@@ -1885,16 +1598,14 @@ function PanelGroupWithForwardedRef({
1885
1598
  } = eagerValuesRef.current;
1886
1599
  const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
1887
1600
  const {
1888
- groupSizePixels,
1889
- panelSizePercentage,
1601
+ panelSize,
1890
1602
  pivotIndices
1891
- } = panelDataHelper(groupId, panelDataArray, panelData, prevLayout);
1892
- const sizePercentage = getPercentageSizeFromMixedSizes(mixedSizes, groupSizePixels);
1603
+ } = panelDataHelper(panelDataArray, panelData, prevLayout);
1604
+ assert(panelSize != null);
1893
1605
  const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
1894
- const delta = isLastPanel ? panelSizePercentage - sizePercentage : sizePercentage - panelSizePercentage;
1606
+ const delta = isLastPanel ? panelSize - unsafePanelSize : unsafePanelSize - panelSize;
1895
1607
  const nextLayout = adjustLayoutByDelta({
1896
1608
  delta,
1897
- groupSizePixels,
1898
1609
  layout: prevLayout,
1899
1610
  panelConstraints: panelConstraintsArray,
1900
1611
  pivotIndices,
@@ -1904,14 +1615,11 @@ function PanelGroupWithForwardedRef({
1904
1615
  setLayout(nextLayout);
1905
1616
  eagerValuesRef.current.layout = nextLayout;
1906
1617
  if (onLayout) {
1907
- onLayout(nextLayout.map(sizePercentage => ({
1908
- sizePercentage,
1909
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1910
- })));
1618
+ onLayout(nextLayout);
1911
1619
  }
1912
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1620
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1913
1621
  }
1914
- }, [groupId]);
1622
+ }, []);
1915
1623
  const startDragging = useCallback((dragHandleId, event) => {
1916
1624
  const {
1917
1625
  direction
@@ -1920,6 +1628,7 @@ function PanelGroupWithForwardedRef({
1920
1628
  layout
1921
1629
  } = eagerValuesRef.current;
1922
1630
  const handleElement = getResizeHandleElement(dragHandleId);
1631
+ assert(handleElement);
1923
1632
  const initialCursorPosition = getResizeEventCursorPosition(direction, event);
1924
1633
  setDragState({
1925
1634
  dragHandleId,
@@ -1938,7 +1647,6 @@ function PanelGroupWithForwardedRef({
1938
1647
  });
1939
1648
  const unregisterPanel = useCallback(panelData => {
1940
1649
  const {
1941
- id: groupId,
1942
1650
  onLayout
1943
1651
  } = committedValuesRef.current;
1944
1652
  const {
@@ -1961,7 +1669,7 @@ function PanelGroupWithForwardedRef({
1961
1669
  const {
1962
1670
  pendingPanelIds
1963
1671
  } = unregisterPanelRef.current;
1964
- const map = panelIdToLastNotifiedMixedSizesMapRef.current;
1672
+ const map = panelIdToLastNotifiedSizeMapRef.current;
1965
1673
 
1966
1674
  // TRICKY
1967
1675
  // Strict effects mode
@@ -1970,7 +1678,7 @@ function PanelGroupWithForwardedRef({
1970
1678
  pendingPanelIds.delete(panelId);
1971
1679
  if (panelDataArray.find(({
1972
1680
  id
1973
- }) => id === panelId) == null) {
1681
+ }) => id === panelId) != null) {
1974
1682
  unmountDueToStrictMode = true;
1975
1683
 
1976
1684
  // TRICKY
@@ -1987,16 +1695,13 @@ function PanelGroupWithForwardedRef({
1987
1695
  // The group is unmounting; skip layout calculation.
1988
1696
  return;
1989
1697
  }
1990
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1991
1698
  let unsafeLayout = calculateUnsafeDefaultLayout({
1992
- groupSizePixels,
1993
1699
  panelDataArray
1994
1700
  });
1995
1701
 
1996
1702
  // Validate even saved layouts in case something has changed since last render
1997
1703
  // e.g. for pixel groups, this could be the size of the window
1998
1704
  const nextLayout = validatePanelGroupLayout({
1999
- groupSizePixels,
2000
1705
  layout: unsafeLayout,
2001
1706
  panelConstraints: panelDataArray.map(panelData => panelData.constraints)
2002
1707
  });
@@ -2004,12 +1709,9 @@ function PanelGroupWithForwardedRef({
2004
1709
  setLayout(nextLayout);
2005
1710
  eagerValuesRef.current.layout = nextLayout;
2006
1711
  if (onLayout) {
2007
- onLayout(nextLayout.map(sizePercentage => ({
2008
- sizePercentage,
2009
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
2010
- })));
1712
+ onLayout(nextLayout);
2011
1713
  }
2012
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1714
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
2013
1715
  }
2014
1716
  }, 0);
2015
1717
  }, []);
@@ -2040,13 +1742,13 @@ function PanelGroupWithForwardedRef({
2040
1742
  return createElement(PanelGroupContext.Provider, {
2041
1743
  value: context
2042
1744
  }, createElement(Type, {
1745
+ ...rest,
2043
1746
  children,
2044
1747
  className: classNameFromProps,
2045
1748
  style: {
2046
1749
  ...style,
2047
1750
  ...styleFromProps
2048
1751
  },
2049
- ...dataAttributes,
2050
1752
  // CSS selectors
2051
1753
  "data-panel-group": "",
2052
1754
  "data-panel-group-direction": direction,
@@ -2059,22 +1761,16 @@ const PanelGroup = forwardRef((props, ref) => createElement(PanelGroupWithForwar
2059
1761
  }));
2060
1762
  PanelGroupWithForwardedRef.displayName = "PanelGroup";
2061
1763
  PanelGroup.displayName = "forwardRef(PanelGroup)";
2062
- function panelDataHelper(groupId, panelDataArray, panelData, layout) {
1764
+ function panelDataHelper(panelDataArray, panelData, layout) {
2063
1765
  const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
2064
1766
  const panelIndex = panelDataArray.indexOf(panelData);
2065
1767
  const panelConstraints = panelConstraintsArray[panelIndex];
2066
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
2067
- const percentagePanelConstraints = computePercentagePanelConstraints(panelConstraintsArray, panelIndex, groupSizePixels);
2068
1768
  const isLastPanel = panelIndex === panelDataArray.length - 1;
2069
1769
  const pivotIndices = isLastPanel ? [panelIndex - 1, panelIndex] : [panelIndex, panelIndex + 1];
2070
- const panelSizePercentage = layout[panelIndex];
2071
- const panelSizePixels = convertPercentageToPixels(panelSizePercentage, groupSizePixels);
1770
+ const panelSize = layout[panelIndex];
2072
1771
  return {
2073
- ...percentagePanelConstraints,
2074
- collapsible: panelConstraints.collapsible,
2075
- panelSizePercentage,
2076
- panelSizePixels,
2077
- groupSizePixels,
1772
+ ...panelConstraints,
1773
+ panelSize,
2078
1774
  pivotIndices
2079
1775
  };
2080
1776
  }
@@ -2114,6 +1810,7 @@ function useWindowSplitterResizeHandlerBehavior({
2114
1810
  {
2115
1811
  event.preventDefault();
2116
1812
  const groupId = handleElement.getAttribute("data-panel-group-id");
1813
+ assert(groupId);
2117
1814
  const handles = getResizeHandleElementsForGroup(groupId);
2118
1815
  const index = getResizeHandleElementIndex(groupId, handleId);
2119
1816
  assert(index !== null);
@@ -2134,12 +1831,13 @@ function useWindowSplitterResizeHandlerBehavior({
2134
1831
  function PanelResizeHandle({
2135
1832
  children = null,
2136
1833
  className: classNameFromProps = "",
2137
- dataAttributes,
2138
1834
  disabled = false,
2139
- id: idFromProps = null,
1835
+ id: idFromProps,
2140
1836
  onDragging,
2141
1837
  style: styleFromProps = {},
2142
- tagName: Type = "div"
1838
+ tabIndex = 0,
1839
+ tagName: Type = "div",
1840
+ ...rest
2143
1841
  }) {
2144
1842
  const divElementRef = useRef(null);
2145
1843
 
@@ -2169,8 +1867,9 @@ function PanelResizeHandle({
2169
1867
  const stopDraggingAndBlur = useCallback(() => {
2170
1868
  // Clicking on the drag handle shouldn't leave it focused;
2171
1869
  // That would cause the PanelGroup to think it was still active.
2172
- const div = divElementRef.current;
2173
- div.blur();
1870
+ const divElement = divElementRef.current;
1871
+ assert(divElement);
1872
+ divElement.blur();
2174
1873
  stopDragging();
2175
1874
  const {
2176
1875
  onDragging
@@ -2198,6 +1897,7 @@ function PanelResizeHandle({
2198
1897
  resizeHandler(event);
2199
1898
  };
2200
1899
  const divElement = divElementRef.current;
1900
+ assert(divElement);
2201
1901
  const targetDocument = divElement.ownerDocument;
2202
1902
  targetDocument.body.addEventListener("contextmenu", stopDraggingAndBlur);
2203
1903
  targetDocument.body.addEventListener("mousemove", onMove);
@@ -2225,15 +1925,18 @@ function PanelResizeHandle({
2225
1925
  userSelect: "none"
2226
1926
  };
2227
1927
  return createElement(Type, {
1928
+ ...rest,
2228
1929
  children,
2229
1930
  className: classNameFromProps,
2230
1931
  onBlur: () => setIsFocused(false),
2231
1932
  onFocus: () => setIsFocused(true),
2232
1933
  onMouseDown: event => {
2233
1934
  startDragging(resizeHandleId, event.nativeEvent);
1935
+ const callbacks = callbacksRef.current;
1936
+ assert(callbacks);
2234
1937
  const {
2235
1938
  onDragging
2236
- } = callbacksRef.current;
1939
+ } = callbacks;
2237
1940
  if (onDragging) {
2238
1941
  onDragging(true);
2239
1942
  }
@@ -2243,9 +1946,11 @@ function PanelResizeHandle({
2243
1946
  onTouchEnd: stopDraggingAndBlur,
2244
1947
  onTouchStart: event => {
2245
1948
  startDragging(resizeHandleId, event.nativeEvent);
1949
+ const callbacks = callbacksRef.current;
1950
+ assert(callbacks);
2246
1951
  const {
2247
1952
  onDragging
2248
- } = callbacksRef.current;
1953
+ } = callbacks;
2249
1954
  if (onDragging) {
2250
1955
  onDragging(true);
2251
1956
  }
@@ -2256,8 +1961,7 @@ function PanelResizeHandle({
2256
1961
  ...style,
2257
1962
  ...styleFromProps
2258
1963
  },
2259
- tabIndex: 0,
2260
- ...dataAttributes,
1964
+ tabIndex,
2261
1965
  // CSS selectors
2262
1966
  "data-panel-group-direction": direction,
2263
1967
  "data-panel-group-id": groupId,
@@ -2272,3 +1976,4 @@ PanelResizeHandle.displayName = "PanelResizeHandle";
2272
1976
  exports.Panel = Panel;
2273
1977
  exports.PanelGroup = PanelGroup;
2274
1978
  exports.PanelResizeHandle = PanelResizeHandle;
1979
+ exports.assert = assert;