react-resizable-panels 0.0.62 → 1.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/.eslintrc.cjs +1 -0
  2. package/CHANGELOG.md +9 -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 +255 -519
  11. package/dist/react-resizable-panels.browser.cjs.mjs +2 -1
  12. package/dist/react-resizable-panels.browser.development.cjs.js +281 -575
  13. package/dist/react-resizable-panels.browser.development.cjs.mjs +2 -1
  14. package/dist/react-resizable-panels.browser.development.esm.js +281 -576
  15. package/dist/react-resizable-panels.browser.esm.js +255 -520
  16. package/dist/react-resizable-panels.cjs.js +255 -519
  17. package/dist/react-resizable-panels.cjs.js.map +1 -0
  18. package/dist/react-resizable-panels.cjs.mjs +2 -1
  19. package/dist/react-resizable-panels.development.cjs.js +283 -577
  20. package/dist/react-resizable-panels.development.cjs.mjs +2 -1
  21. package/dist/react-resizable-panels.development.esm.js +283 -578
  22. package/dist/react-resizable-panels.development.node.cjs.js +269 -503
  23. package/dist/react-resizable-panels.development.node.cjs.mjs +2 -1
  24. package/dist/react-resizable-panels.development.node.esm.js +269 -504
  25. package/dist/react-resizable-panels.esm.js +255 -520
  26. package/dist/react-resizable-panels.esm.js.map +1 -0
  27. package/dist/react-resizable-panels.node.cjs.js +241 -445
  28. package/dist/react-resizable-panels.node.cjs.mjs +2 -1
  29. package/dist/react-resizable-panels.node.esm.js +241 -446
  30. package/package.json +1 -1
  31. package/src/Panel.test.tsx +74 -73
  32. package/src/Panel.ts +44 -68
  33. package/src/PanelGroup.test.tsx +43 -42
  34. package/src/PanelGroup.ts +189 -403
  35. package/src/PanelGroupContext.ts +2 -3
  36. package/src/PanelResizeHandle.test.tsx +68 -0
  37. package/src/PanelResizeHandle.ts +31 -22
  38. package/src/hooks/useWindowSplitterBehavior.ts +2 -1
  39. package/src/hooks/useWindowSplitterPanelGroupBehavior.ts +22 -33
  40. package/src/index.ts +4 -3
  41. package/src/types.ts +0 -9
  42. package/src/utils/adjustLayoutByDelta.test.ts +206 -336
  43. package/src/utils/adjustLayoutByDelta.ts +59 -51
  44. package/src/utils/assert.ts +1 -1
  45. package/src/utils/calculateAriaValues.test.ts +6 -11
  46. package/src/utils/calculateAriaValues.ts +7 -29
  47. package/src/utils/calculateDeltaPercentage.ts +8 -15
  48. package/src/utils/calculateDragOffsetPercentage.ts +11 -5
  49. package/src/utils/calculateUnsafeDefaultLayout.test.ts +4 -9
  50. package/src/utils/calculateUnsafeDefaultLayout.ts +13 -18
  51. package/src/utils/callPanelCallbacks.ts +11 -46
  52. package/src/utils/computePanelFlexBoxStyle.ts +3 -2
  53. package/src/utils/getResizeEventCursorPosition.ts +2 -0
  54. package/src/utils/resizePanel.test.ts +6 -52
  55. package/src/utils/resizePanel.ts +24 -46
  56. package/src/utils/test-utils.ts +6 -7
  57. package/src/utils/validatePanelConstraints.test.ts +12 -65
  58. package/src/utils/validatePanelConstraints.ts +26 -67
  59. package/src/utils/validatePanelGroupLayout.test.ts +27 -142
  60. package/src/utils/validatePanelGroupLayout.ts +17 -13
  61. package/src/vendor/react.ts +2 -0
  62. package/src/utils/computePercentagePanelConstraints.test.ts +0 -98
  63. package/src/utils/computePercentagePanelConstraints.ts +0 -56
  64. package/src/utils/convertPercentageToPixels.test.ts +0 -9
  65. package/src/utils/convertPercentageToPixels.ts +0 -6
  66. package/src/utils/convertPixelConstraintsToPercentages.test.ts +0 -47
  67. package/src/utils/convertPixelConstraintsToPercentages.ts +0 -72
  68. package/src/utils/convertPixelsToPercentage.test.ts +0 -9
  69. package/src/utils/convertPixelsToPercentage.ts +0 -6
  70. package/src/utils/getPercentageSizeFromMixedSizes.test.ts +0 -47
  71. package/src/utils/getPercentageSizeFromMixedSizes.ts +0 -15
  72. package/src/utils/shouldMonitorPixelBasedConstraints.test.ts +0 -23
  73. 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
  }
@@ -1051,9 +890,10 @@ function computePanelFlexBoxStyle({
1051
890
  const size = layout[panelIndex];
1052
891
  let flexGrow;
1053
892
  if (panelData.length === 1) {
1054
- flexGrow = "100";
893
+ flexGrow = "1";
1055
894
  } else if (size == null) {
1056
- flexGrow = "0";
895
+ // Initial render (before panels have registered themselves)
896
+ flexGrow = "1";
1057
897
  } else {
1058
898
  flexGrow = size.toPrecision(precision);
1059
899
  }
@@ -1199,74 +1039,39 @@ function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
1199
1039
  }
1200
1040
  }
1201
1041
 
1202
- function shouldMonitorPixelBasedConstraints(constraints) {
1203
- return constraints.some(constraints => {
1204
- return constraints.collapsedSizePixels !== undefined || constraints.maxSizePixels !== undefined || constraints.minSizePixels !== undefined;
1205
- });
1206
- }
1207
-
1208
1042
  function validatePanelConstraints({
1209
- groupSizePixels,
1210
- panelConstraints,
1043
+ panelConstraints: panelConstraintsArray,
1211
1044
  panelId,
1212
1045
  panelIndex
1213
1046
  }) {
1214
1047
  {
1215
1048
  const warnings = [];
1216
- {
1217
- const {
1218
- collapsedSizePercentage,
1219
- collapsedSizePixels,
1220
- defaultSizePercentage,
1221
- defaultSizePixels,
1222
- maxSizePercentage,
1223
- maxSizePixels,
1224
- minSizePercentage,
1225
- minSizePixels
1226
- } = panelConstraints[panelIndex];
1227
- const conflictingUnits = [];
1228
- if (collapsedSizePercentage != null && collapsedSizePixels != null) {
1229
- conflictingUnits.push("collapsed size");
1230
- }
1231
- if (defaultSizePercentage != null && defaultSizePixels != null) {
1232
- conflictingUnits.push("default size");
1233
- }
1234
- if (maxSizePercentage != null && maxSizePixels != null) {
1235
- conflictingUnits.push("max size");
1236
- }
1237
- if (minSizePercentage != null && minSizePixels != null) {
1238
- conflictingUnits.push("min size");
1239
- }
1240
- if (conflictingUnits.length > 0) {
1241
- warnings.push(`should not specify both percentage and pixel units for: ${conflictingUnits.join(", ")}`);
1242
- }
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}%)`);
1243
1059
  }
1244
- {
1245
- const {
1246
- collapsedSizePercentage,
1247
- defaultSizePercentage,
1248
- maxSizePercentage,
1249
- minSizePercentage
1250
- } = computePercentagePanelConstraints(panelConstraints, panelIndex, groupSizePixels);
1251
- if (minSizePercentage > maxSizePercentage) {
1252
- warnings.push(`min size (${minSizePercentage}%) should not be greater than max size (${maxSizePercentage}%)`);
1253
- }
1254
- if (defaultSizePercentage != null) {
1255
- if (defaultSizePercentage < 0) {
1256
- warnings.push("default size should not be less than 0");
1257
- } else if (defaultSizePercentage < minSizePercentage) {
1258
- warnings.push("default size should not be less than min size");
1259
- }
1260
- if (defaultSizePercentage > 100) {
1261
- warnings.push("default size should not be greater than 100");
1262
- } else if (defaultSizePercentage > maxSizePercentage) {
1263
- warnings.push("default size should not be greater than max size");
1264
- }
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");
1265
1065
  }
1266
- if (collapsedSizePercentage > minSizePercentage) {
1267
- 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");
1268
1070
  }
1269
1071
  }
1072
+ if (collapsedSize > minSize) {
1073
+ warnings.push("collapsed size should not be greater than min size");
1074
+ }
1270
1075
  if (warnings.length > 0) {
1271
1076
  const name = panelId != null ? `Panel "${panelId}"` : "Panel";
1272
1077
  console.warn(`${name} has an invalid configuration:\n\n${warnings.join("\n")}`);
@@ -1278,20 +1083,26 @@ function validatePanelConstraints({
1278
1083
 
1279
1084
  // All units must be in percentages; pixel values should be pre-converted
1280
1085
  function validatePanelGroupLayout({
1281
- groupSizePixels,
1282
1086
  layout: prevLayout,
1283
1087
  panelConstraints
1284
1088
  }) {
1285
1089
  const nextLayout = [...prevLayout];
1090
+ const nextLayoutTotalSize = nextLayout.reduce((accumulated, current) => accumulated + current, 0);
1286
1091
 
1287
1092
  // Validate layout expectations
1288
1093
  if (nextLayout.length !== panelConstraints.length) {
1289
1094
  throw Error(`Invalid ${panelConstraints.length} panel layout: ${nextLayout.map(size => `${size}%`).join(", ")}`);
1290
- } else if (!fuzzyNumbersEqual(nextLayout.reduce((accumulated, current) => accumulated + current, 0), 100)) {
1095
+ } else if (!fuzzyNumbersEqual(nextLayoutTotalSize, 100)) {
1291
1096
  // This is not ideal so we should warn about it, but it may be recoverable in some cases
1292
1097
  // (especially if the amount is small)
1293
1098
  {
1294
- 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;
1295
1106
  }
1296
1107
  }
1297
1108
  let remainingSize = 0;
@@ -1299,8 +1110,8 @@ function validatePanelGroupLayout({
1299
1110
  // First pass: Validate the proposed layout given each panel's constraints
1300
1111
  for (let index = 0; index < panelConstraints.length; index++) {
1301
1112
  const unsafeSize = nextLayout[index];
1113
+ assert(unsafeSize != null);
1302
1114
  const safeSize = resizePanel({
1303
- groupSizePixels,
1304
1115
  panelConstraints,
1305
1116
  panelIndex: index,
1306
1117
  size: unsafeSize
@@ -1316,9 +1127,9 @@ function validatePanelGroupLayout({
1316
1127
  if (!fuzzyNumbersEqual(remainingSize, 0)) {
1317
1128
  for (let index = 0; index < panelConstraints.length; index++) {
1318
1129
  const prevSize = nextLayout[index];
1130
+ assert(prevSize != null);
1319
1131
  const unsafeSize = prevSize + remainingSize;
1320
1132
  const safeSize = resizePanel({
1321
- groupSizePixels,
1322
1133
  panelConstraints,
1323
1134
  panelIndex: index,
1324
1135
  size: unsafeSize
@@ -1353,21 +1164,20 @@ function PanelGroupWithForwardedRef({
1353
1164
  autoSaveId = null,
1354
1165
  children,
1355
1166
  className: classNameFromProps = "",
1356
- dataAttributes,
1357
1167
  direction,
1358
1168
  forwardedRef,
1359
- id: idFromProps,
1169
+ id: idFromProps = null,
1360
1170
  onLayout = null,
1361
- keyboardResizeByPercentage = null,
1362
- keyboardResizeByPixels = null,
1171
+ keyboardResizeBy = null,
1363
1172
  storage = defaultStorage,
1364
1173
  style: styleFromProps,
1365
- tagName: Type = "div"
1174
+ tagName: Type = "div",
1175
+ ...rest
1366
1176
  }) {
1367
1177
  const groupId = useUniqueId(idFromProps);
1368
1178
  const [dragState, setDragState] = useState(null);
1369
1179
  const [layout, setLayout] = useState([]);
1370
- const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
1180
+ const panelIdToLastNotifiedSizeMapRef = useRef({});
1371
1181
  const panelSizeBeforeCollapseRef = useRef(new Map());
1372
1182
  const prevDeltaRef = useRef(0);
1373
1183
  const committedValuesRef = useRef({
@@ -1375,8 +1185,7 @@ function PanelGroupWithForwardedRef({
1375
1185
  direction,
1376
1186
  dragState,
1377
1187
  id: groupId,
1378
- keyboardResizeByPercentage,
1379
- keyboardResizeByPixels,
1188
+ keyboardResizeBy,
1380
1189
  onLayout,
1381
1190
  storage
1382
1191
  });
@@ -1392,33 +1201,20 @@ function PanelGroupWithForwardedRef({
1392
1201
  useImperativeHandle(forwardedRef, () => ({
1393
1202
  getId: () => committedValuesRef.current.id,
1394
1203
  getLayout: () => {
1395
- const {
1396
- id: groupId
1397
- } = committedValuesRef.current;
1398
1204
  const {
1399
1205
  layout
1400
1206
  } = eagerValuesRef.current;
1401
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1402
- return layout.map(sizePercentage => {
1403
- return {
1404
- sizePercentage,
1405
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1406
- };
1407
- });
1207
+ return layout;
1408
1208
  },
1409
- setLayout: mixedSizes => {
1209
+ setLayout: unsafeLayout => {
1410
1210
  const {
1411
- id: groupId,
1412
1211
  onLayout
1413
1212
  } = committedValuesRef.current;
1414
1213
  const {
1415
1214
  layout: prevLayout,
1416
1215
  panelDataArray
1417
1216
  } = eagerValuesRef.current;
1418
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1419
- const unsafeLayout = mixedSizes.map(mixedSize => getPercentageSizeFromMixedSizes(mixedSize, groupSizePixels));
1420
1217
  const safeLayout = validatePanelGroupLayout({
1421
- groupSizePixels,
1422
1218
  layout: unsafeLayout,
1423
1219
  panelConstraints: panelDataArray.map(panelData => panelData.constraints)
1424
1220
  });
@@ -1426,12 +1222,9 @@ function PanelGroupWithForwardedRef({
1426
1222
  setLayout(safeLayout);
1427
1223
  eagerValuesRef.current.layout = safeLayout;
1428
1224
  if (onLayout) {
1429
- onLayout(safeLayout.map(sizePercentage => ({
1430
- sizePercentage,
1431
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1432
- })));
1225
+ onLayout(safeLayout);
1433
1226
  }
1434
- callPanelCallbacks(groupId, panelDataArray, safeLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1227
+ callPanelCallbacks(panelDataArray, safeLayout, panelIdToLastNotifiedSizeMapRef.current);
1435
1228
  }
1436
1229
  }
1437
1230
  }), []);
@@ -1442,11 +1235,7 @@ function PanelGroupWithForwardedRef({
1442
1235
  committedValuesRef.current.id = groupId;
1443
1236
  committedValuesRef.current.onLayout = onLayout;
1444
1237
  committedValuesRef.current.storage = storage;
1445
-
1446
- // panelDataArray and layout are updated in-sync with scheduled state updates.
1447
- // TODO [217] Move these values into a separate ref
1448
1238
  });
1449
-
1450
1239
  useWindowSplitterPanelGroupBehavior({
1451
1240
  committedValuesRef,
1452
1241
  eagerValuesRef,
@@ -1465,57 +1254,16 @@ function PanelGroupWithForwardedRef({
1465
1254
  if (layout.length === 0 || layout.length !== panelDataArray.length) {
1466
1255
  return;
1467
1256
  }
1257
+ let debouncedSave = debounceMap[autoSaveId];
1468
1258
 
1469
1259
  // Limit the frequency of localStorage updates.
1470
- if (!debounceMap[autoSaveId]) {
1471
- debounceMap[autoSaveId] = debounce(savePanelGroupLayout, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
1260
+ if (debouncedSave == null) {
1261
+ debouncedSave = debounce(savePanelGroupLayout, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
1262
+ debounceMap[autoSaveId] = debouncedSave;
1472
1263
  }
1473
- debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
1264
+ debouncedSave(autoSaveId, panelDataArray, layout, storage);
1474
1265
  }
1475
1266
  }, [autoSaveId, layout, storage]);
1476
- useIsomorphicLayoutEffect(() => {
1477
- const {
1478
- layout: prevLayout,
1479
- panelDataArray
1480
- } = eagerValuesRef.current;
1481
- const constraints = panelDataArray.map(({
1482
- constraints
1483
- }) => constraints);
1484
- if (!shouldMonitorPixelBasedConstraints(constraints)) {
1485
- // Avoid the overhead of ResizeObserver if no pixel constraints require monitoring
1486
- return;
1487
- }
1488
- if (typeof ResizeObserver === "undefined") {
1489
- console.warn(`WARNING: Pixel based constraints require ResizeObserver but it is not supported by the current browser.`);
1490
- } else {
1491
- const resizeObserver = new ResizeObserver(() => {
1492
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1493
- const {
1494
- onLayout
1495
- } = committedValuesRef.current;
1496
- const nextLayout = validatePanelGroupLayout({
1497
- groupSizePixels,
1498
- layout: prevLayout,
1499
- panelConstraints: panelDataArray.map(panelData => panelData.constraints)
1500
- });
1501
- if (!areEqual(prevLayout, nextLayout)) {
1502
- setLayout(nextLayout);
1503
- eagerValuesRef.current.layout = nextLayout;
1504
- if (onLayout) {
1505
- onLayout(nextLayout.map(sizePercentage => ({
1506
- sizePercentage,
1507
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1508
- })));
1509
- }
1510
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1511
- }
1512
- });
1513
- resizeObserver.observe(getPanelGroupElement(groupId));
1514
- return () => {
1515
- resizeObserver.disconnect();
1516
- };
1517
- }
1518
- }, [groupId]);
1519
1267
 
1520
1268
  // DEV warnings
1521
1269
  useEffect(() => {
@@ -1546,12 +1294,12 @@ function PanelGroupWithForwardedRef({
1546
1294
  }
1547
1295
  if (!didLogPanelConstraintsWarning) {
1548
1296
  const panelConstraints = panelDataArray.map(panelData => panelData.constraints);
1549
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1550
1297
  for (let panelIndex = 0; panelIndex < panelConstraints.length; panelIndex++) {
1298
+ const panelData = panelDataArray[panelIndex];
1299
+ assert(panelData);
1551
1300
  const isValid = validatePanelConstraints({
1552
- groupSizePixels,
1553
1301
  panelConstraints,
1554
- panelId: panelDataArray[panelIndex].id,
1302
+ panelId: panelData.id,
1555
1303
  panelIndex
1556
1304
  });
1557
1305
  if (!isValid) {
@@ -1575,20 +1323,19 @@ function PanelGroupWithForwardedRef({
1575
1323
  if (panelData.constraints.collapsible) {
1576
1324
  const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
1577
1325
  const {
1578
- collapsedSizePercentage,
1579
- panelSizePercentage,
1580
- pivotIndices,
1581
- groupSizePixels
1582
- } = panelDataHelper(groupId, panelDataArray, panelData, prevLayout);
1583
- if (panelSizePercentage !== collapsedSizePercentage) {
1326
+ collapsedSize = 0,
1327
+ panelSize,
1328
+ pivotIndices
1329
+ } = panelDataHelper(panelDataArray, panelData, prevLayout);
1330
+ assert(panelSize != null);
1331
+ if (panelSize !== collapsedSize) {
1584
1332
  // Store size before collapse;
1585
1333
  // This is the size that gets restored if the expand() API is used.
1586
- panelSizeBeforeCollapseRef.current.set(panelData.id, panelSizePercentage);
1334
+ panelSizeBeforeCollapseRef.current.set(panelData.id, panelSize);
1587
1335
  const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
1588
- const delta = isLastPanel ? panelSizePercentage - collapsedSizePercentage : collapsedSizePercentage - panelSizePercentage;
1336
+ const delta = isLastPanel ? panelSize - collapsedSize : collapsedSize - panelSize;
1589
1337
  const nextLayout = adjustLayoutByDelta({
1590
1338
  delta,
1591
- groupSizePixels,
1592
1339
  layout: prevLayout,
1593
1340
  panelConstraints: panelConstraintsArray,
1594
1341
  pivotIndices,
@@ -1598,16 +1345,13 @@ function PanelGroupWithForwardedRef({
1598
1345
  setLayout(nextLayout);
1599
1346
  eagerValuesRef.current.layout = nextLayout;
1600
1347
  if (onLayout) {
1601
- onLayout(nextLayout.map(sizePercentage => ({
1602
- sizePercentage,
1603
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1604
- })));
1348
+ onLayout(nextLayout);
1605
1349
  }
1606
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1350
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1607
1351
  }
1608
1352
  }
1609
1353
  }
1610
- }, [groupId]);
1354
+ }, []);
1611
1355
 
1612
1356
  // External APIs are safe to memoize via committed values ref
1613
1357
  const expandPanel = useCallback(panelData => {
@@ -1621,21 +1365,19 @@ function PanelGroupWithForwardedRef({
1621
1365
  if (panelData.constraints.collapsible) {
1622
1366
  const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
1623
1367
  const {
1624
- collapsedSizePercentage,
1625
- panelSizePercentage,
1626
- minSizePercentage,
1627
- pivotIndices,
1628
- groupSizePixels
1629
- } = panelDataHelper(groupId, panelDataArray, panelData, prevLayout);
1630
- if (panelSizePercentage === collapsedSizePercentage) {
1368
+ collapsedSize = 0,
1369
+ panelSize,
1370
+ minSize = 0,
1371
+ pivotIndices
1372
+ } = panelDataHelper(panelDataArray, panelData, prevLayout);
1373
+ if (panelSize === collapsedSize) {
1631
1374
  // Restore this panel to the size it was before it was collapsed, if possible.
1632
- const prevPanelSizePercentage = panelSizeBeforeCollapseRef.current.get(panelData.id);
1633
- 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;
1634
1377
  const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
1635
- const delta = isLastPanel ? panelSizePercentage - baseSizePercentage : baseSizePercentage - panelSizePercentage;
1378
+ const delta = isLastPanel ? panelSize - baseSize : baseSize - panelSize;
1636
1379
  const nextLayout = adjustLayoutByDelta({
1637
1380
  delta,
1638
- groupSizePixels,
1639
1381
  layout: prevLayout,
1640
1382
  panelConstraints: panelConstraintsArray,
1641
1383
  pivotIndices,
@@ -1645,16 +1387,13 @@ function PanelGroupWithForwardedRef({
1645
1387
  setLayout(nextLayout);
1646
1388
  eagerValuesRef.current.layout = nextLayout;
1647
1389
  if (onLayout) {
1648
- onLayout(nextLayout.map(sizePercentage => ({
1649
- sizePercentage,
1650
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1651
- })));
1390
+ onLayout(nextLayout);
1652
1391
  }
1653
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1392
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1654
1393
  }
1655
1394
  }
1656
1395
  }
1657
- }, [groupId]);
1396
+ }, []);
1658
1397
 
1659
1398
  // External APIs are safe to memoize via committed values ref
1660
1399
  const getPanelSize = useCallback(panelData => {
@@ -1663,14 +1402,11 @@ function PanelGroupWithForwardedRef({
1663
1402
  panelDataArray
1664
1403
  } = eagerValuesRef.current;
1665
1404
  const {
1666
- panelSizePercentage,
1667
- panelSizePixels
1668
- } = panelDataHelper(groupId, panelDataArray, panelData, layout);
1669
- return {
1670
- sizePercentage: panelSizePercentage,
1671
- sizePixels: panelSizePixels
1672
- };
1673
- }, [groupId]);
1405
+ panelSize
1406
+ } = panelDataHelper(panelDataArray, panelData, layout);
1407
+ assert(panelSize != null);
1408
+ return panelSize;
1409
+ }, []);
1674
1410
 
1675
1411
  // This API should never read from committedValuesRef
1676
1412
  const getPanelStyle = useCallback(panelData => {
@@ -1693,12 +1429,12 @@ function PanelGroupWithForwardedRef({
1693
1429
  panelDataArray
1694
1430
  } = eagerValuesRef.current;
1695
1431
  const {
1696
- collapsedSizePercentage,
1432
+ collapsedSize,
1697
1433
  collapsible,
1698
- panelSizePercentage
1699
- } = panelDataHelper(groupId, panelDataArray, panelData, layout);
1700
- return collapsible === true && panelSizePercentage === collapsedSizePercentage;
1701
- }, [groupId]);
1434
+ panelSize
1435
+ } = panelDataHelper(panelDataArray, panelData, layout);
1436
+ return collapsible === true && panelSize === collapsedSize;
1437
+ }, []);
1702
1438
 
1703
1439
  // External APIs are safe to memoize via committed values ref
1704
1440
  const isPanelExpanded = useCallback(panelData => {
@@ -1707,12 +1443,13 @@ function PanelGroupWithForwardedRef({
1707
1443
  panelDataArray
1708
1444
  } = eagerValuesRef.current;
1709
1445
  const {
1710
- collapsedSizePercentage,
1446
+ collapsedSize = 0,
1711
1447
  collapsible,
1712
- panelSizePercentage
1713
- } = panelDataHelper(groupId, panelDataArray, panelData, layout);
1714
- return !collapsible || panelSizePercentage > collapsedSizePercentage;
1715
- }, [groupId]);
1448
+ panelSize
1449
+ } = panelDataHelper(panelDataArray, panelData, layout);
1450
+ assert(panelSize != null);
1451
+ return !collapsible || panelSize > collapsedSize;
1452
+ }, []);
1716
1453
  const registerPanel = useCallback(panelData => {
1717
1454
  const {
1718
1455
  autoSaveId,
@@ -1752,18 +1489,8 @@ function PanelGroupWithForwardedRef({
1752
1489
  if (autoSaveId) {
1753
1490
  unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
1754
1491
  }
1755
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1756
- if (groupSizePixels <= 0) {
1757
- if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
1758
- constraints
1759
- }) => constraints))) {
1760
- // Wait until the group has rendered a non-zero size before computing layout.
1761
- return;
1762
- }
1763
- }
1764
1492
  if (unsafeLayout == null) {
1765
1493
  unsafeLayout = calculateUnsafeDefaultLayout({
1766
- groupSizePixels,
1767
1494
  panelDataArray
1768
1495
  });
1769
1496
  }
@@ -1771,7 +1498,6 @@ function PanelGroupWithForwardedRef({
1771
1498
  // Validate even saved layouts in case something has changed since last render
1772
1499
  // e.g. for pixel groups, this could be the size of the window
1773
1500
  const nextLayout = validatePanelGroupLayout({
1774
- groupSizePixels,
1775
1501
  layout: unsafeLayout,
1776
1502
  panelConstraints: panelDataArray.map(panelData => panelData.constraints)
1777
1503
  });
@@ -1783,12 +1509,9 @@ function PanelGroupWithForwardedRef({
1783
1509
  eagerValuesRef.current.layout = nextLayout;
1784
1510
  if (!areEqual(prevLayout, nextLayout)) {
1785
1511
  if (onLayout) {
1786
- onLayout(nextLayout.map(sizePercentage => ({
1787
- sizePercentage,
1788
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1789
- })));
1512
+ onLayout(nextLayout);
1790
1513
  }
1791
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1514
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1792
1515
  }
1793
1516
  }, []);
1794
1517
  const registerResizeHandle = useCallback(dragHandleId => {
@@ -1798,8 +1521,7 @@ function PanelGroupWithForwardedRef({
1798
1521
  direction,
1799
1522
  dragState,
1800
1523
  id: groupId,
1801
- keyboardResizeByPercentage,
1802
- keyboardResizeByPixels,
1524
+ keyboardResizeBy,
1803
1525
  onLayout
1804
1526
  } = committedValuesRef.current;
1805
1527
  const {
@@ -1810,10 +1532,7 @@ function PanelGroupWithForwardedRef({
1810
1532
  initialLayout
1811
1533
  } = dragState !== null && dragState !== void 0 ? dragState : {};
1812
1534
  const pivotIndices = determinePivotIndices(groupId, dragHandleId);
1813
- let delta = calculateDeltaPercentage(event, groupId, dragHandleId, direction, dragState, {
1814
- percentage: keyboardResizeByPercentage,
1815
- pixels: keyboardResizeByPixels
1816
- });
1535
+ let delta = calculateDeltaPercentage(event, dragHandleId, direction, dragState, keyboardResizeBy);
1817
1536
  if (delta === 0) {
1818
1537
  return;
1819
1538
  }
@@ -1823,11 +1542,9 @@ function PanelGroupWithForwardedRef({
1823
1542
  if (document.dir === "rtl" && isHorizontal) {
1824
1543
  delta = -delta;
1825
1544
  }
1826
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1827
1545
  const panelConstraints = panelDataArray.map(panelData => panelData.constraints);
1828
1546
  const nextLayout = adjustLayoutByDelta({
1829
1547
  delta,
1830
- groupSizePixels,
1831
1548
  layout: initialLayout !== null && initialLayout !== void 0 ? initialLayout : prevLayout,
1832
1549
  panelConstraints,
1833
1550
  pivotIndices,
@@ -1863,18 +1580,15 @@ function PanelGroupWithForwardedRef({
1863
1580
  setLayout(nextLayout);
1864
1581
  eagerValuesRef.current.layout = nextLayout;
1865
1582
  if (onLayout) {
1866
- onLayout(nextLayout.map(sizePercentage => ({
1867
- sizePercentage,
1868
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1869
- })));
1583
+ onLayout(nextLayout);
1870
1584
  }
1871
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1585
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1872
1586
  }
1873
1587
  };
1874
1588
  }, []);
1875
1589
 
1876
1590
  // External APIs are safe to memoize via committed values ref
1877
- const resizePanel = useCallback((panelData, mixedSizes) => {
1591
+ const resizePanel = useCallback((panelData, unsafePanelSize) => {
1878
1592
  const {
1879
1593
  onLayout
1880
1594
  } = committedValuesRef.current;
@@ -1884,16 +1598,14 @@ function PanelGroupWithForwardedRef({
1884
1598
  } = eagerValuesRef.current;
1885
1599
  const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
1886
1600
  const {
1887
- groupSizePixels,
1888
- panelSizePercentage,
1601
+ panelSize,
1889
1602
  pivotIndices
1890
- } = panelDataHelper(groupId, panelDataArray, panelData, prevLayout);
1891
- const sizePercentage = getPercentageSizeFromMixedSizes(mixedSizes, groupSizePixels);
1603
+ } = panelDataHelper(panelDataArray, panelData, prevLayout);
1604
+ assert(panelSize != null);
1892
1605
  const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
1893
- const delta = isLastPanel ? panelSizePercentage - sizePercentage : sizePercentage - panelSizePercentage;
1606
+ const delta = isLastPanel ? panelSize - unsafePanelSize : unsafePanelSize - panelSize;
1894
1607
  const nextLayout = adjustLayoutByDelta({
1895
1608
  delta,
1896
- groupSizePixels,
1897
1609
  layout: prevLayout,
1898
1610
  panelConstraints: panelConstraintsArray,
1899
1611
  pivotIndices,
@@ -1903,14 +1615,11 @@ function PanelGroupWithForwardedRef({
1903
1615
  setLayout(nextLayout);
1904
1616
  eagerValuesRef.current.layout = nextLayout;
1905
1617
  if (onLayout) {
1906
- onLayout(nextLayout.map(sizePercentage => ({
1907
- sizePercentage,
1908
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1909
- })));
1618
+ onLayout(nextLayout);
1910
1619
  }
1911
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1620
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1912
1621
  }
1913
- }, [groupId]);
1622
+ }, []);
1914
1623
  const startDragging = useCallback((dragHandleId, event) => {
1915
1624
  const {
1916
1625
  direction
@@ -1919,6 +1628,7 @@ function PanelGroupWithForwardedRef({
1919
1628
  layout
1920
1629
  } = eagerValuesRef.current;
1921
1630
  const handleElement = getResizeHandleElement(dragHandleId);
1631
+ assert(handleElement);
1922
1632
  const initialCursorPosition = getResizeEventCursorPosition(direction, event);
1923
1633
  setDragState({
1924
1634
  dragHandleId,
@@ -1937,7 +1647,6 @@ function PanelGroupWithForwardedRef({
1937
1647
  });
1938
1648
  const unregisterPanel = useCallback(panelData => {
1939
1649
  const {
1940
- id: groupId,
1941
1650
  onLayout
1942
1651
  } = committedValuesRef.current;
1943
1652
  const {
@@ -1960,7 +1669,7 @@ function PanelGroupWithForwardedRef({
1960
1669
  const {
1961
1670
  pendingPanelIds
1962
1671
  } = unregisterPanelRef.current;
1963
- const map = panelIdToLastNotifiedMixedSizesMapRef.current;
1672
+ const map = panelIdToLastNotifiedSizeMapRef.current;
1964
1673
 
1965
1674
  // TRICKY
1966
1675
  // Strict effects mode
@@ -1986,16 +1695,13 @@ function PanelGroupWithForwardedRef({
1986
1695
  // The group is unmounting; skip layout calculation.
1987
1696
  return;
1988
1697
  }
1989
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1990
1698
  let unsafeLayout = calculateUnsafeDefaultLayout({
1991
- groupSizePixels,
1992
1699
  panelDataArray
1993
1700
  });
1994
1701
 
1995
1702
  // Validate even saved layouts in case something has changed since last render
1996
1703
  // e.g. for pixel groups, this could be the size of the window
1997
1704
  const nextLayout = validatePanelGroupLayout({
1998
- groupSizePixels,
1999
1705
  layout: unsafeLayout,
2000
1706
  panelConstraints: panelDataArray.map(panelData => panelData.constraints)
2001
1707
  });
@@ -2003,12 +1709,9 @@ function PanelGroupWithForwardedRef({
2003
1709
  setLayout(nextLayout);
2004
1710
  eagerValuesRef.current.layout = nextLayout;
2005
1711
  if (onLayout) {
2006
- onLayout(nextLayout.map(sizePercentage => ({
2007
- sizePercentage,
2008
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
2009
- })));
1712
+ onLayout(nextLayout);
2010
1713
  }
2011
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1714
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
2012
1715
  }
2013
1716
  }, 0);
2014
1717
  }, []);
@@ -2039,13 +1742,13 @@ function PanelGroupWithForwardedRef({
2039
1742
  return createElement(PanelGroupContext.Provider, {
2040
1743
  value: context
2041
1744
  }, createElement(Type, {
1745
+ ...rest,
2042
1746
  children,
2043
1747
  className: classNameFromProps,
2044
1748
  style: {
2045
1749
  ...style,
2046
1750
  ...styleFromProps
2047
1751
  },
2048
- ...dataAttributes,
2049
1752
  // CSS selectors
2050
1753
  "data-panel-group": "",
2051
1754
  "data-panel-group-direction": direction,
@@ -2058,22 +1761,16 @@ const PanelGroup = forwardRef((props, ref) => createElement(PanelGroupWithForwar
2058
1761
  }));
2059
1762
  PanelGroupWithForwardedRef.displayName = "PanelGroup";
2060
1763
  PanelGroup.displayName = "forwardRef(PanelGroup)";
2061
- function panelDataHelper(groupId, panelDataArray, panelData, layout) {
1764
+ function panelDataHelper(panelDataArray, panelData, layout) {
2062
1765
  const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
2063
1766
  const panelIndex = panelDataArray.indexOf(panelData);
2064
1767
  const panelConstraints = panelConstraintsArray[panelIndex];
2065
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
2066
- const percentagePanelConstraints = computePercentagePanelConstraints(panelConstraintsArray, panelIndex, groupSizePixels);
2067
1768
  const isLastPanel = panelIndex === panelDataArray.length - 1;
2068
1769
  const pivotIndices = isLastPanel ? [panelIndex - 1, panelIndex] : [panelIndex, panelIndex + 1];
2069
- const panelSizePercentage = layout[panelIndex];
2070
- const panelSizePixels = convertPercentageToPixels(panelSizePercentage, groupSizePixels);
1770
+ const panelSize = layout[panelIndex];
2071
1771
  return {
2072
- ...percentagePanelConstraints,
2073
- collapsible: panelConstraints.collapsible,
2074
- panelSizePercentage,
2075
- panelSizePixels,
2076
- groupSizePixels,
1772
+ ...panelConstraints,
1773
+ panelSize,
2077
1774
  pivotIndices
2078
1775
  };
2079
1776
  }
@@ -2113,6 +1810,7 @@ function useWindowSplitterResizeHandlerBehavior({
2113
1810
  {
2114
1811
  event.preventDefault();
2115
1812
  const groupId = handleElement.getAttribute("data-panel-group-id");
1813
+ assert(groupId);
2116
1814
  const handles = getResizeHandleElementsForGroup(groupId);
2117
1815
  const index = getResizeHandleElementIndex(groupId, handleId);
2118
1816
  assert(index !== null);
@@ -2133,12 +1831,13 @@ function useWindowSplitterResizeHandlerBehavior({
2133
1831
  function PanelResizeHandle({
2134
1832
  children = null,
2135
1833
  className: classNameFromProps = "",
2136
- dataAttributes,
2137
1834
  disabled = false,
2138
- id: idFromProps = null,
1835
+ id: idFromProps,
2139
1836
  onDragging,
2140
1837
  style: styleFromProps = {},
2141
- tagName: Type = "div"
1838
+ tabIndex = 0,
1839
+ tagName: Type = "div",
1840
+ ...rest
2142
1841
  }) {
2143
1842
  const divElementRef = useRef(null);
2144
1843
 
@@ -2168,8 +1867,9 @@ function PanelResizeHandle({
2168
1867
  const stopDraggingAndBlur = useCallback(() => {
2169
1868
  // Clicking on the drag handle shouldn't leave it focused;
2170
1869
  // That would cause the PanelGroup to think it was still active.
2171
- const div = divElementRef.current;
2172
- div.blur();
1870
+ const divElement = divElementRef.current;
1871
+ assert(divElement);
1872
+ divElement.blur();
2173
1873
  stopDragging();
2174
1874
  const {
2175
1875
  onDragging
@@ -2197,6 +1897,7 @@ function PanelResizeHandle({
2197
1897
  resizeHandler(event);
2198
1898
  };
2199
1899
  const divElement = divElementRef.current;
1900
+ assert(divElement);
2200
1901
  const targetDocument = divElement.ownerDocument;
2201
1902
  targetDocument.body.addEventListener("contextmenu", stopDraggingAndBlur);
2202
1903
  targetDocument.body.addEventListener("mousemove", onMove);
@@ -2224,15 +1925,18 @@ function PanelResizeHandle({
2224
1925
  userSelect: "none"
2225
1926
  };
2226
1927
  return createElement(Type, {
1928
+ ...rest,
2227
1929
  children,
2228
1930
  className: classNameFromProps,
2229
1931
  onBlur: () => setIsFocused(false),
2230
1932
  onFocus: () => setIsFocused(true),
2231
1933
  onMouseDown: event => {
2232
1934
  startDragging(resizeHandleId, event.nativeEvent);
1935
+ const callbacks = callbacksRef.current;
1936
+ assert(callbacks);
2233
1937
  const {
2234
1938
  onDragging
2235
- } = callbacksRef.current;
1939
+ } = callbacks;
2236
1940
  if (onDragging) {
2237
1941
  onDragging(true);
2238
1942
  }
@@ -2242,9 +1946,11 @@ function PanelResizeHandle({
2242
1946
  onTouchEnd: stopDraggingAndBlur,
2243
1947
  onTouchStart: event => {
2244
1948
  startDragging(resizeHandleId, event.nativeEvent);
1949
+ const callbacks = callbacksRef.current;
1950
+ assert(callbacks);
2245
1951
  const {
2246
1952
  onDragging
2247
- } = callbacksRef.current;
1953
+ } = callbacks;
2248
1954
  if (onDragging) {
2249
1955
  onDragging(true);
2250
1956
  }
@@ -2255,8 +1961,7 @@ function PanelResizeHandle({
2255
1961
  ...style,
2256
1962
  ...styleFromProps
2257
1963
  },
2258
- tabIndex: 0,
2259
- ...dataAttributes,
1964
+ tabIndex,
2260
1965
  // CSS selectors
2261
1966
  "data-panel-group-direction": direction,
2262
1967
  "data-panel-group-id": groupId,
@@ -2271,3 +1976,4 @@ PanelResizeHandle.displayName = "PanelResizeHandle";
2271
1976
  exports.Panel = Panel;
2272
1977
  exports.PanelGroup = PanelGroup;
2273
1978
  exports.PanelResizeHandle = PanelResizeHandle;
1979
+ exports.assert = assert;