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
@@ -63,24 +63,20 @@ function useUniqueId(idFromParams = null) {
63
63
  function PanelWithForwardedRef({
64
64
  children,
65
65
  className: classNameFromProps = "",
66
- collapsedSizePercentage,
67
- collapsedSizePixels,
66
+ collapsedSize,
68
67
  collapsible,
69
- dataAttributes,
70
- defaultSizePercentage,
71
- defaultSizePixels,
68
+ defaultSize,
72
69
  forwardedRef,
73
70
  id: idFromProps,
74
- maxSizePercentage,
75
- maxSizePixels,
76
- minSizePercentage,
77
- minSizePixels,
71
+ maxSize,
72
+ minSize,
78
73
  onCollapse,
79
74
  onExpand,
80
75
  onResize,
81
76
  order,
82
77
  style: styleFromProps,
83
- tagName: Type = "div"
78
+ tagName: Type = "div",
79
+ ...rest
84
80
  }) {
85
81
  const context = useContext(PanelGroupContext);
86
82
  if (context === null) {
@@ -105,15 +101,11 @@ function PanelWithForwardedRef({
105
101
  onResize
106
102
  },
107
103
  constraints: {
108
- collapsedSizePercentage,
109
- collapsedSizePixels,
104
+ collapsedSize,
110
105
  collapsible,
111
- defaultSizePercentage,
112
- defaultSizePixels,
113
- maxSizePercentage,
114
- maxSizePixels,
115
- minSizePercentage,
116
- minSizePixels
106
+ defaultSize,
107
+ maxSize,
108
+ minSize
117
109
  },
118
110
  id: panelId,
119
111
  idIsFromProps: idFromProps !== undefined,
@@ -127,9 +119,9 @@ function PanelWithForwardedRef({
127
119
  // but effects don't run on the server, so we can't do it there
128
120
  {
129
121
  if (!devWarningsRef.current.didLogMissingDefaultSizeWarning) {
130
- if (defaultSizePercentage == null && defaultSizePixels == null) {
122
+ if (defaultSize == null) {
131
123
  devWarningsRef.current.didLogMissingDefaultSizeWarning = true;
132
- console.warn(`WARNING: Panel defaultSizePercentage or defaultSizePixels prop recommended to avoid layout shift after server rendering`);
124
+ console.warn(`WARNING: Panel defaultSize prop recommended to avoid layout shift after server rendering`);
133
125
  }
134
126
  }
135
127
  }
@@ -152,19 +144,19 @@ function PanelWithForwardedRef({
152
144
  isExpanded() {
153
145
  return !isPanelCollapsed(panelDataRef.current);
154
146
  },
155
- resize: mixedSizes => {
156
- resizePanel(panelDataRef.current, mixedSizes);
147
+ resize: size => {
148
+ resizePanel(panelDataRef.current, size);
157
149
  }
158
150
  }), [collapsePanel, expandPanel, getPanelSize, isPanelCollapsed, panelId, resizePanel]);
159
151
  const style = getPanelStyle(panelDataRef.current);
160
152
  return createElement(Type, {
153
+ ...rest,
161
154
  children,
162
155
  className: classNameFromProps,
163
156
  style: {
164
157
  ...style,
165
158
  ...styleFromProps
166
159
  },
167
- ...dataAttributes,
168
160
  // CSS selectors
169
161
  "data-panel": "",
170
162
  "data-panel-id": panelId,
@@ -181,81 +173,11 @@ const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
181
173
  PanelWithForwardedRef.displayName = "Panel";
182
174
  Panel.displayName = "forwardRef(Panel)";
183
175
 
184
- function convertPixelsToPercentage(pixels, groupSizePixels) {
185
- return pixels / groupSizePixels * 100;
186
- }
187
-
188
- function convertPixelConstraintsToPercentages(panelConstraints, groupSizePixels) {
189
- let {
190
- collapsedSizePercentage = 0,
191
- collapsedSizePixels,
192
- defaultSizePercentage,
193
- defaultSizePixels,
194
- maxSizePercentage = 100,
195
- maxSizePixels,
196
- minSizePercentage = 0,
197
- minSizePixels
198
- } = panelConstraints;
199
- const hasPixelConstraints = collapsedSizePixels != null || defaultSizePixels != null || minSizePixels != null || maxSizePixels != null;
200
- if (hasPixelConstraints && groupSizePixels <= 0) {
201
- console.warn(`WARNING: Invalid group size: ${groupSizePixels}px`);
202
- return {
203
- collapsedSizePercentage: 0,
204
- defaultSizePercentage,
205
- maxSizePercentage: 0,
206
- minSizePercentage: 0
207
- };
208
- }
209
- if (collapsedSizePixels != null) {
210
- collapsedSizePercentage = convertPixelsToPercentage(collapsedSizePixels, groupSizePixels);
211
- }
212
- if (defaultSizePixels != null) {
213
- defaultSizePercentage = convertPixelsToPercentage(defaultSizePixels, groupSizePixels);
214
- }
215
- if (minSizePixels != null) {
216
- minSizePercentage = convertPixelsToPercentage(minSizePixels, groupSizePixels);
217
- }
218
- if (maxSizePixels != null) {
219
- maxSizePercentage = convertPixelsToPercentage(maxSizePixels, groupSizePixels);
220
- }
221
- return {
222
- collapsedSizePercentage,
223
- defaultSizePercentage,
224
- maxSizePercentage,
225
- minSizePercentage
226
- };
227
- }
228
-
229
- function computePercentagePanelConstraints(panelConstraintsArray, panelIndex, groupSizePixels) {
230
- // All panel constraints, excluding the current one
231
- let totalMinConstraints = 0;
232
- let totalMaxConstraints = 0;
233
- for (let index = 0; index < panelConstraintsArray.length; index++) {
234
- if (index !== panelIndex) {
235
- const {
236
- collapsible
237
- } = panelConstraintsArray[index];
238
- const {
239
- collapsedSizePercentage,
240
- maxSizePercentage,
241
- minSizePercentage
242
- } = convertPixelConstraintsToPercentages(panelConstraintsArray[index], groupSizePixels);
243
- totalMaxConstraints += maxSizePercentage;
244
- totalMinConstraints += collapsible ? collapsedSizePercentage : minSizePercentage;
245
- }
176
+ function assert(expectedCondition, message = "Assertion failed!") {
177
+ if (!expectedCondition) {
178
+ console.error(message);
179
+ throw Error(message);
246
180
  }
247
- const {
248
- collapsedSizePercentage,
249
- defaultSizePercentage,
250
- maxSizePercentage,
251
- minSizePercentage
252
- } = convertPixelConstraintsToPercentages(panelConstraintsArray[panelIndex], groupSizePixels);
253
- return {
254
- collapsedSizePercentage,
255
- defaultSizePercentage,
256
- maxSizePercentage: panelConstraintsArray.length > 1 ? Math.min(maxSizePercentage, 100 - totalMinConstraints) : maxSizePercentage,
257
- minSizePercentage: panelConstraintsArray.length > 1 ? Math.max(minSizePercentage, 100 - totalMaxConstraints) : minSizePercentage
258
- };
259
181
  }
260
182
 
261
183
  const PRECISION = 10;
@@ -277,56 +199,41 @@ function fuzzyNumbersEqual(actual, expected, fractionDigits) {
277
199
 
278
200
  // Panel size must be in percentages; pixel values should be pre-converted
279
201
  function resizePanel({
280
- groupSizePixels,
281
- panelConstraints,
202
+ panelConstraints: panelConstraintsArray,
282
203
  panelIndex,
283
204
  size
284
205
  }) {
285
- const hasPixelConstraints = panelConstraints.some(({
286
- collapsedSizePixels,
287
- defaultSizePixels,
288
- minSizePixels,
289
- maxSizePixels
290
- }) => collapsedSizePixels != null || defaultSizePixels != null || minSizePixels != null || maxSizePixels != null);
291
- if (hasPixelConstraints && groupSizePixels <= 0) {
292
- console.warn(`WARNING: Invalid group size: ${groupSizePixels}px`);
293
- return 0;
294
- }
206
+ const panelConstraints = panelConstraintsArray[panelIndex];
207
+ assert(panelConstraints != null);
295
208
  let {
296
- collapsible
297
- } = panelConstraints[panelIndex];
298
- const {
299
- collapsedSizePercentage,
300
- maxSizePercentage,
301
- minSizePercentage
302
- } = computePercentagePanelConstraints(panelConstraints, panelIndex, groupSizePixels);
303
- if (minSizePercentage != null) {
304
- if (fuzzyCompareNumbers(size, minSizePercentage) < 0) {
305
- if (collapsible) {
306
- // Collapsible panels should snap closed or open only once they cross the halfway point between collapsed and min size.
307
- const halfwayPoint = (collapsedSizePercentage + minSizePercentage) / 2;
308
- if (fuzzyCompareNumbers(size, halfwayPoint) < 0) {
309
- size = collapsedSizePercentage;
310
- } else {
311
- size = minSizePercentage;
312
- }
209
+ collapsedSize = 0,
210
+ collapsible,
211
+ maxSize = 100,
212
+ minSize = 0
213
+ } = panelConstraints;
214
+ if (fuzzyCompareNumbers(size, minSize) < 0) {
215
+ if (collapsible) {
216
+ // Collapsible panels should snap closed or open only once they cross the halfway point between collapsed and min size.
217
+ const halfwayPoint = (collapsedSize + minSize) / 2;
218
+ if (fuzzyCompareNumbers(size, halfwayPoint) < 0) {
219
+ size = collapsedSize;
313
220
  } else {
314
- size = minSizePercentage;
221
+ size = minSize;
315
222
  }
223
+ } else {
224
+ size = minSize;
316
225
  }
317
226
  }
318
- if (maxSizePercentage != null) {
319
- size = Math.min(maxSizePercentage, size);
320
- }
227
+ size = Math.min(maxSize, size);
228
+ size = parseFloat(size.toFixed(PRECISION));
321
229
  return size;
322
230
  }
323
231
 
324
232
  // All units must be in percentages; pixel values should be pre-converted
325
233
  function adjustLayoutByDelta({
326
234
  delta,
327
- groupSizePixels,
328
235
  layout: prevLayout,
329
- panelConstraints,
236
+ panelConstraints: panelConstraintsArray,
330
237
  pivotIndices,
331
238
  trigger
332
239
  }) {
@@ -334,6 +241,9 @@ function adjustLayoutByDelta({
334
241
  return prevLayout;
335
242
  }
336
243
  const nextLayout = [...prevLayout];
244
+ const [firstPivotIndex, secondPivotIndex] = pivotIndices;
245
+ assert(firstPivotIndex != null);
246
+ assert(secondPivotIndex != null);
337
247
  let deltaApplied = 0;
338
248
 
339
249
  //const DEBUG = [];
@@ -357,18 +267,23 @@ function adjustLayoutByDelta({
357
267
  if (trigger === "keyboard") {
358
268
  {
359
269
  // Check if we should expand a collapsed panel
360
- const index = delta < 0 ? pivotIndices[1] : pivotIndices[0];
361
- const constraints = panelConstraints[index];
270
+ const index = delta < 0 ? secondPivotIndex : firstPivotIndex;
271
+ const panelConstraints = panelConstraintsArray[index];
272
+ assert(panelConstraints);
273
+
362
274
  //DEBUG.push(`edge case check 1: ${index}`);
363
275
  //DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
364
- if (constraints.collapsible) {
276
+ if (panelConstraints.collapsible) {
365
277
  const prevSize = prevLayout[index];
278
+ assert(prevSize != null);
279
+ const panelConstraints = panelConstraintsArray[index];
280
+ assert(panelConstraints);
366
281
  const {
367
- collapsedSizePercentage,
368
- minSizePercentage
369
- } = computePercentagePanelConstraints(panelConstraints, index, groupSizePixels);
370
- if (fuzzyNumbersEqual(prevSize, collapsedSizePercentage)) {
371
- const localDelta = minSizePercentage - prevSize;
282
+ collapsedSize = 0,
283
+ minSize = 0
284
+ } = panelConstraints;
285
+ if (fuzzyNumbersEqual(prevSize, collapsedSize)) {
286
+ const localDelta = minSize - prevSize;
372
287
  //DEBUG.push(` -> expand delta: ${localDelta}`);
373
288
 
374
289
  if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
@@ -381,18 +296,26 @@ function adjustLayoutByDelta({
381
296
 
382
297
  {
383
298
  // Check if we should collapse a panel at its minimum size
384
- const index = delta < 0 ? pivotIndices[0] : pivotIndices[1];
385
- const constraints = panelConstraints[index];
299
+ const index = delta < 0 ? firstPivotIndex : secondPivotIndex;
300
+ const panelConstraints = panelConstraintsArray[index];
301
+ assert(panelConstraints);
302
+ const {
303
+ collapsible
304
+ } = panelConstraints;
305
+
386
306
  //DEBUG.push(`edge case check 2: ${index}`);
387
- //DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
388
- if (constraints.collapsible) {
307
+ //DEBUG.push(` -> collapsible? ${collapsible}`);
308
+ if (collapsible) {
389
309
  const prevSize = prevLayout[index];
310
+ assert(prevSize != null);
311
+ const panelConstraints = panelConstraintsArray[index];
312
+ assert(panelConstraints);
390
313
  const {
391
- collapsedSizePercentage,
392
- minSizePercentage
393
- } = computePercentagePanelConstraints(panelConstraints, index, groupSizePixels);
394
- if (fuzzyNumbersEqual(prevSize, minSizePercentage)) {
395
- const localDelta = prevSize - collapsedSizePercentage;
314
+ collapsedSize = 0,
315
+ minSize = 0
316
+ } = panelConstraints;
317
+ if (fuzzyNumbersEqual(prevSize, minSize)) {
318
+ const localDelta = prevSize - collapsedSize;
396
319
  //DEBUG.push(` -> expand delta: ${localDelta}`);
397
320
 
398
321
  if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
@@ -414,15 +337,15 @@ function adjustLayoutByDelta({
414
337
  // as an expanding panel might change from collapsed to min size.
415
338
 
416
339
  const increment = delta < 0 ? 1 : -1;
417
- let index = delta < 0 ? pivotIndices[1] : pivotIndices[0];
340
+ let index = delta < 0 ? secondPivotIndex : firstPivotIndex;
418
341
  let maxAvailableDelta = 0;
419
342
 
420
343
  //DEBUG.push("pre calc...");
421
344
  while (true) {
422
345
  const prevSize = prevLayout[index];
346
+ assert(prevSize != null);
423
347
  const maxSafeSize = resizePanel({
424
- groupSizePixels,
425
- panelConstraints,
348
+ panelConstraints: panelConstraintsArray,
426
349
  panelIndex: index,
427
350
  size: 100
428
351
  });
@@ -431,7 +354,7 @@ function adjustLayoutByDelta({
431
354
 
432
355
  maxAvailableDelta += delta;
433
356
  index += increment;
434
- if (index < 0 || index >= panelConstraints.length) {
357
+ if (index < 0 || index >= panelConstraintsArray.length) {
435
358
  break;
436
359
  }
437
360
  }
@@ -446,15 +369,15 @@ function adjustLayoutByDelta({
446
369
  {
447
370
  // Delta added to a panel needs to be subtracted from other panels (within the constraints that those panels allow).
448
371
 
449
- const pivotIndex = delta < 0 ? pivotIndices[0] : pivotIndices[1];
372
+ const pivotIndex = delta < 0 ? firstPivotIndex : secondPivotIndex;
450
373
  let index = pivotIndex;
451
- while (index >= 0 && index < panelConstraints.length) {
374
+ while (index >= 0 && index < panelConstraintsArray.length) {
452
375
  const deltaRemaining = Math.abs(delta) - Math.abs(deltaApplied);
453
376
  const prevSize = prevLayout[index];
377
+ assert(prevSize != null);
454
378
  const unsafeSize = prevSize - deltaRemaining;
455
379
  const safeSize = resizePanel({
456
- groupSizePixels,
457
- panelConstraints,
380
+ panelConstraints: panelConstraintsArray,
458
381
  panelIndex: index,
459
382
  size: unsafeSize
460
383
  });
@@ -486,11 +409,12 @@ function adjustLayoutByDelta({
486
409
  }
487
410
  {
488
411
  // Now distribute the applied delta to the panels in the other direction
489
- const pivotIndex = delta < 0 ? pivotIndices[1] : pivotIndices[0];
490
- const unsafeSize = prevLayout[pivotIndex] + deltaApplied;
412
+ const pivotIndex = delta < 0 ? secondPivotIndex : firstPivotIndex;
413
+ const prevSize = prevLayout[pivotIndex];
414
+ assert(prevSize != null);
415
+ const unsafeSize = prevSize + deltaApplied;
491
416
  const safeSize = resizePanel({
492
- groupSizePixels,
493
- panelConstraints,
417
+ panelConstraints: panelConstraintsArray,
494
418
  panelIndex: pivotIndex,
495
419
  size: unsafeSize
496
420
  });
@@ -501,14 +425,14 @@ function adjustLayoutByDelta({
501
425
  // Edge case where expanding or contracting one panel caused another one to change collapsed state
502
426
  if (!fuzzyNumbersEqual(safeSize, unsafeSize)) {
503
427
  let deltaRemaining = unsafeSize - safeSize;
504
- const pivotIndex = delta < 0 ? pivotIndices[1] : pivotIndices[0];
428
+ const pivotIndex = delta < 0 ? secondPivotIndex : firstPivotIndex;
505
429
  let index = pivotIndex;
506
- while (index >= 0 && index < panelConstraints.length) {
430
+ while (index >= 0 && index < panelConstraintsArray.length) {
507
431
  const prevSize = nextLayout[index];
432
+ assert(prevSize != null);
508
433
  const unsafeSize = prevSize + deltaRemaining;
509
434
  const safeSize = resizePanel({
510
- groupSizePixels,
511
- panelConstraints,
435
+ panelConstraints: panelConstraintsArray,
512
436
  panelIndex: index,
513
437
  size: unsafeSize
514
438
  });
@@ -532,9 +456,7 @@ function adjustLayoutByDelta({
532
456
  //DEBUG.push("");
533
457
 
534
458
  const totalSize = nextLayout.reduce((total, size) => size + total, 0);
535
- deltaApplied = 100 - totalSize;
536
459
  //DEBUG.push(`total size: ${totalSize}`);
537
- //DEBUG.push(` deltaApplied: ${deltaApplied}`);
538
460
  //console.log(DEBUG.join("\n"));
539
461
 
540
462
  if (!fuzzyNumbersEqual(totalSize, 100)) {
@@ -543,25 +465,6 @@ function adjustLayoutByDelta({
543
465
  return nextLayout;
544
466
  }
545
467
 
546
- function assert(expectedCondition, message = "Assertion failed!") {
547
- if (!expectedCondition) {
548
- console.error(message);
549
- throw Error(message);
550
- }
551
- }
552
-
553
- function getPercentageSizeFromMixedSizes({
554
- sizePercentage,
555
- sizePixels
556
- }, groupSizePixels) {
557
- if (sizePercentage != null) {
558
- return sizePercentage;
559
- } else if (sizePixels != null) {
560
- return convertPixelsToPercentage(sizePixels, groupSizePixels);
561
- }
562
- return undefined;
563
- }
564
-
565
468
  function getResizeHandleElementsForGroup(groupId) {
566
469
  return Array.from(document.querySelectorAll(`[data-panel-resize-handle-id][data-panel-group-id="${groupId}"]`));
567
470
  }
@@ -585,42 +488,6 @@ function getPanelGroupElement(id) {
585
488
  return null;
586
489
  }
587
490
 
588
- function calculateAvailablePanelSizeInPixels(groupId) {
589
- const panelGroupElement = getPanelGroupElement(groupId);
590
- if (panelGroupElement == null) {
591
- return NaN;
592
- }
593
- const direction = panelGroupElement.getAttribute("data-panel-group-direction");
594
- const resizeHandles = getResizeHandleElementsForGroup(groupId);
595
- if (direction === "horizontal") {
596
- return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
597
- return accumulated + handle.offsetWidth;
598
- }, 0);
599
- } else {
600
- return panelGroupElement.offsetHeight - resizeHandles.reduce((accumulated, handle) => {
601
- return accumulated + handle.offsetHeight;
602
- }, 0);
603
- }
604
- }
605
-
606
- function getAvailableGroupSizePixels(groupId) {
607
- const panelGroupElement = getPanelGroupElement(groupId);
608
- if (panelGroupElement == null) {
609
- return NaN;
610
- }
611
- const direction = panelGroupElement.getAttribute("data-panel-group-direction");
612
- const resizeHandles = getResizeHandleElementsForGroup(groupId);
613
- if (direction === "horizontal") {
614
- return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
615
- return accumulated + handle.offsetWidth;
616
- }, 0);
617
- } else {
618
- return panelGroupElement.offsetHeight - resizeHandles.reduce((accumulated, handle) => {
619
- return accumulated + handle.offsetHeight;
620
- }, 0);
621
- }
622
- }
623
-
624
491
  function getResizeHandleElement(id) {
625
492
  const element = document.querySelector(`[data-panel-resize-handle-id="${id}"]`);
626
493
  if (element) {
@@ -653,14 +520,18 @@ function useWindowSplitterPanelGroupBehavior({
653
520
  didWarnAboutMissingResizeHandle: false
654
521
  });
655
522
  useEffect(() => {
523
+ const eagerValues = eagerValuesRef.current;
524
+ assert(eagerValues);
656
525
  const {
657
526
  panelDataArray
658
- } = eagerValuesRef.current;
527
+ } = eagerValues;
659
528
  const groupElement = getPanelGroupElement(groupId);
660
529
  assert(groupElement != null, `No group found for id "${groupId}"`);
661
530
  const handles = getResizeHandleElementsForGroup(groupId);
531
+ assert(handles);
662
532
  const cleanupFunctions = handles.map(handle => {
663
533
  const handleId = handle.getAttribute("data-panel-resize-handle-id");
534
+ assert(handleId);
664
535
  const [idBefore, idAfter] = getResizeHandlePanelIds(groupId, handleId, panelDataArray);
665
536
  if (idBefore == null || idAfter == null) {
666
537
  return () => {};
@@ -676,21 +547,16 @@ function useWindowSplitterPanelGroupBehavior({
676
547
  const index = panelDataArray.findIndex(panelData => panelData.id === idBefore);
677
548
  if (index >= 0) {
678
549
  const panelData = panelDataArray[index];
550
+ assert(panelData);
679
551
  const size = layout[index];
680
- if (size != null && panelData.constraints.collapsible) {
681
- var _getPercentageSizeFro, _getPercentageSizeFro2;
682
- const groupSizePixels = getAvailableGroupSizePixels(groupId);
683
- const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
684
- sizePercentage: panelData.constraints.collapsedSizePercentage,
685
- sizePixels: panelData.constraints.collapsedSizePixels
686
- }, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
687
- const minSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
688
- sizePercentage: panelData.constraints.minSizePercentage,
689
- sizePixels: panelData.constraints.minSizePixels
690
- }, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 0;
552
+ const {
553
+ collapsedSize = 0,
554
+ collapsible,
555
+ minSize = 0
556
+ } = panelData.constraints;
557
+ if (size != null && collapsible) {
691
558
  const nextLayout = adjustLayoutByDelta({
692
559
  delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
693
- groupSizePixels,
694
560
  layout,
695
561
  panelConstraints: panelDataArray.map(panelData => panelData.constraints),
696
562
  pivotIndices: determinePivotIndices(groupId, handleId),
@@ -744,6 +610,7 @@ function getResizeEventCursorPosition(direction, event) {
744
610
  return isHorizontal ? event.clientX : event.clientY;
745
611
  } else if (isTouchEvent(event)) {
746
612
  const firstTouch = event.touches[0];
613
+ assert(firstTouch);
747
614
  return isHorizontal ? firstTouch.screenX : firstTouch.screenY;
748
615
  } else {
749
616
  throw Error(`Unsupported event type "${event.type}"`);
@@ -753,12 +620,15 @@ function getResizeEventCursorPosition(direction, event) {
753
620
  function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState) {
754
621
  const isHorizontal = direction === "horizontal";
755
622
  const handleElement = getResizeHandleElement(dragHandleId);
623
+ assert(handleElement);
756
624
  const groupId = handleElement.getAttribute("data-panel-group-id");
625
+ assert(groupId);
757
626
  let {
758
627
  initialCursorPosition
759
628
  } = initialDragState;
760
629
  const cursorPosition = getResizeEventCursorPosition(direction, event);
761
630
  const groupElement = getPanelGroupElement(groupId);
631
+ assert(groupElement);
762
632
  const groupRect = groupElement.getBoundingClientRect();
763
633
  const groupSizeInPixels = isHorizontal ? groupRect.width : groupRect.height;
764
634
  const offsetPixels = cursorPosition - initialCursorPosition;
@@ -767,19 +637,14 @@ function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDr
767
637
  }
768
638
 
769
639
  // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/movementX
770
- function calculateDeltaPercentage(event, groupId, dragHandleId, direction, initialDragState, keyboardResizeByOptions) {
640
+ function calculateDeltaPercentage(event, dragHandleId, direction, initialDragState, keyboardResizeBy) {
771
641
  if (isKeyDown(event)) {
772
642
  const isHorizontal = direction === "horizontal";
773
- const groupElement = getPanelGroupElement(groupId);
774
- const rect = groupElement.getBoundingClientRect();
775
- const groupSizeInPixels = isHorizontal ? rect.width : rect.height;
776
643
  let delta = 0;
777
644
  if (event.shiftKey) {
778
645
  delta = 100;
779
- } else if (keyboardResizeByOptions.percentage != null) {
780
- delta = keyboardResizeByOptions.percentage;
781
- } else if (keyboardResizeByOptions.pixels != null) {
782
- delta = keyboardResizeByOptions.pixels / groupSizeInPixels;
646
+ } else if (keyboardResizeBy != null) {
647
+ delta = keyboardResizeBy;
783
648
  } else {
784
649
  delta = 10;
785
650
  }
@@ -806,37 +671,43 @@ function calculateDeltaPercentage(event, groupId, dragHandleId, direction, initi
806
671
  }
807
672
  return movement;
808
673
  } else {
674
+ if (initialDragState == null) {
675
+ return 0;
676
+ }
809
677
  return calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState);
810
678
  }
811
679
  }
812
680
 
813
681
  function calculateUnsafeDefaultLayout({
814
- groupSizePixels,
815
682
  panelDataArray
816
683
  }) {
817
684
  const layout = Array(panelDataArray.length);
818
- const panelDataConstraints = panelDataArray.map(panelData => panelData.constraints);
685
+ const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
819
686
  let numPanelsWithSizes = 0;
820
687
  let remainingSize = 100;
821
688
 
822
689
  // Distribute default sizes first
823
690
  for (let index = 0; index < panelDataArray.length; index++) {
691
+ const panelConstraints = panelConstraintsArray[index];
692
+ assert(panelConstraints);
824
693
  const {
825
- defaultSizePercentage
826
- } = computePercentagePanelConstraints(panelDataConstraints, index, groupSizePixels);
827
- if (defaultSizePercentage != null) {
694
+ defaultSize
695
+ } = panelConstraints;
696
+ if (defaultSize != null) {
828
697
  numPanelsWithSizes++;
829
- layout[index] = defaultSizePercentage;
830
- remainingSize -= defaultSizePercentage;
698
+ layout[index] = defaultSize;
699
+ remainingSize -= defaultSize;
831
700
  }
832
701
  }
833
702
 
834
703
  // Remaining size should be distributed evenly between panels without default sizes
835
704
  for (let index = 0; index < panelDataArray.length; index++) {
705
+ const panelConstraints = panelConstraintsArray[index];
706
+ assert(panelConstraints);
836
707
  const {
837
- defaultSizePercentage
838
- } = computePercentagePanelConstraints(panelDataConstraints, index, groupSizePixels);
839
- if (defaultSizePercentage != null) {
708
+ defaultSize
709
+ } = panelConstraints;
710
+ if (defaultSize != null) {
840
711
  continue;
841
712
  }
842
713
  const numRemainingPanels = panelDataArray.length - numPanelsWithSizes;
@@ -848,54 +719,36 @@ function calculateUnsafeDefaultLayout({
848
719
  return layout;
849
720
  }
850
721
 
851
- function convertPercentageToPixels(percentage, groupSizePixels) {
852
- return percentage / 100 * groupSizePixels;
853
- }
854
-
855
722
  // Layout should be pre-converted into percentages
856
- function callPanelCallbacks(groupId, panelsArray, layout, panelIdToLastNotifiedMixedSizesMap) {
857
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
858
- layout.forEach((sizePercentage, index) => {
723
+ function callPanelCallbacks(panelsArray, layout, panelIdToLastNotifiedSizeMap) {
724
+ layout.forEach((size, index) => {
859
725
  const panelData = panelsArray[index];
860
- if (!panelData) {
861
- // Handle initial mount (when panels are registered too late to be in the panels array)
862
- // The subsequent render+effects will handle the resize notification
863
- return;
864
- }
726
+ assert(panelData);
865
727
  const {
866
728
  callbacks,
867
729
  constraints,
868
730
  id: panelId
869
731
  } = panelData;
870
732
  const {
733
+ collapsedSize = 0,
871
734
  collapsible
872
735
  } = constraints;
873
- const mixedSizes = {
874
- sizePercentage,
875
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
876
- };
877
- const lastNotifiedMixedSizes = panelIdToLastNotifiedMixedSizesMap[panelId];
878
- if (lastNotifiedMixedSizes == null || mixedSizes.sizePercentage !== lastNotifiedMixedSizes.sizePercentage || mixedSizes.sizePixels !== lastNotifiedMixedSizes.sizePixels) {
879
- panelIdToLastNotifiedMixedSizesMap[panelId] = mixedSizes;
736
+ const lastNotifiedSize = panelIdToLastNotifiedSizeMap[panelId];
737
+ if (lastNotifiedSize == null || size !== lastNotifiedSize) {
738
+ panelIdToLastNotifiedSizeMap[panelId] = size;
880
739
  const {
881
740
  onCollapse,
882
741
  onExpand,
883
742
  onResize
884
743
  } = callbacks;
885
744
  if (onResize) {
886
- onResize(mixedSizes, lastNotifiedMixedSizes);
745
+ onResize(size, lastNotifiedSize);
887
746
  }
888
747
  if (collapsible && (onCollapse || onExpand)) {
889
- var _getPercentageSizeFro;
890
- const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
891
- sizePercentage: constraints.collapsedSizePercentage,
892
- sizePixels: constraints.collapsedSizePixels
893
- }, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
894
- const size = getPercentageSizeFromMixedSizes(mixedSizes, groupSizePixels);
895
- if (onExpand && (lastNotifiedMixedSizes == null || lastNotifiedMixedSizes.sizePercentage === collapsedSize) && size !== collapsedSize) {
748
+ if (onExpand && (lastNotifiedSize == null || lastNotifiedSize === collapsedSize) && size !== collapsedSize) {
896
749
  onExpand();
897
750
  }
898
- if (onCollapse && (lastNotifiedMixedSizes == null || lastNotifiedMixedSizes.sizePercentage !== collapsedSize) && size === collapsedSize) {
751
+ if (onCollapse && (lastNotifiedSize == null || lastNotifiedSize !== collapsedSize) && size === collapsedSize) {
899
752
  onCollapse();
900
753
  }
901
754
  }
@@ -1078,74 +931,39 @@ function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
1078
931
  }
1079
932
  }
1080
933
 
1081
- function shouldMonitorPixelBasedConstraints(constraints) {
1082
- return constraints.some(constraints => {
1083
- return constraints.collapsedSizePixels !== undefined || constraints.maxSizePixels !== undefined || constraints.minSizePixels !== undefined;
1084
- });
1085
- }
1086
-
1087
934
  function validatePanelConstraints({
1088
- groupSizePixels,
1089
- panelConstraints,
935
+ panelConstraints: panelConstraintsArray,
1090
936
  panelId,
1091
937
  panelIndex
1092
938
  }) {
1093
939
  {
1094
940
  const warnings = [];
1095
- {
1096
- const {
1097
- collapsedSizePercentage,
1098
- collapsedSizePixels,
1099
- defaultSizePercentage,
1100
- defaultSizePixels,
1101
- maxSizePercentage,
1102
- maxSizePixels,
1103
- minSizePercentage,
1104
- minSizePixels
1105
- } = panelConstraints[panelIndex];
1106
- const conflictingUnits = [];
1107
- if (collapsedSizePercentage != null && collapsedSizePixels != null) {
1108
- conflictingUnits.push("collapsed size");
1109
- }
1110
- if (defaultSizePercentage != null && defaultSizePixels != null) {
1111
- conflictingUnits.push("default size");
1112
- }
1113
- if (maxSizePercentage != null && maxSizePixels != null) {
1114
- conflictingUnits.push("max size");
1115
- }
1116
- if (minSizePercentage != null && minSizePixels != null) {
1117
- conflictingUnits.push("min size");
1118
- }
1119
- if (conflictingUnits.length > 0) {
1120
- warnings.push(`should not specify both percentage and pixel units for: ${conflictingUnits.join(", ")}`);
1121
- }
941
+ const panelConstraints = panelConstraintsArray[panelIndex];
942
+ assert(panelConstraints);
943
+ const {
944
+ collapsedSize = 0,
945
+ defaultSize,
946
+ maxSize = 100,
947
+ minSize = 0
948
+ } = panelConstraints;
949
+ if (minSize > maxSize) {
950
+ warnings.push(`min size (${minSize}%) should not be greater than max size (${maxSize}%)`);
1122
951
  }
1123
- {
1124
- const {
1125
- collapsedSizePercentage,
1126
- defaultSizePercentage,
1127
- maxSizePercentage,
1128
- minSizePercentage
1129
- } = computePercentagePanelConstraints(panelConstraints, panelIndex, groupSizePixels);
1130
- if (minSizePercentage > maxSizePercentage) {
1131
- warnings.push(`min size (${minSizePercentage}%) should not be greater than max size (${maxSizePercentage}%)`);
1132
- }
1133
- if (defaultSizePercentage != null) {
1134
- if (defaultSizePercentage < 0) {
1135
- warnings.push("default size should not be less than 0");
1136
- } else if (defaultSizePercentage < minSizePercentage) {
1137
- warnings.push("default size should not be less than min size");
1138
- }
1139
- if (defaultSizePercentage > 100) {
1140
- warnings.push("default size should not be greater than 100");
1141
- } else if (defaultSizePercentage > maxSizePercentage) {
1142
- warnings.push("default size should not be greater than max size");
1143
- }
952
+ if (defaultSize != null) {
953
+ if (defaultSize < 0) {
954
+ warnings.push("default size should not be less than 0");
955
+ } else if (defaultSize < minSize) {
956
+ warnings.push("default size should not be less than min size");
1144
957
  }
1145
- if (collapsedSizePercentage > minSizePercentage) {
1146
- warnings.push("collapsed size should not be greater than min size");
958
+ if (defaultSize > 100) {
959
+ warnings.push("default size should not be greater than 100");
960
+ } else if (defaultSize > maxSize) {
961
+ warnings.push("default size should not be greater than max size");
1147
962
  }
1148
963
  }
964
+ if (collapsedSize > minSize) {
965
+ warnings.push("collapsed size should not be greater than min size");
966
+ }
1149
967
  if (warnings.length > 0) {
1150
968
  const name = panelId != null ? `Panel "${panelId}"` : "Panel";
1151
969
  console.warn(`${name} has an invalid configuration:\n\n${warnings.join("\n")}`);
@@ -1157,20 +975,26 @@ function validatePanelConstraints({
1157
975
 
1158
976
  // All units must be in percentages; pixel values should be pre-converted
1159
977
  function validatePanelGroupLayout({
1160
- groupSizePixels,
1161
978
  layout: prevLayout,
1162
979
  panelConstraints
1163
980
  }) {
1164
981
  const nextLayout = [...prevLayout];
982
+ const nextLayoutTotalSize = nextLayout.reduce((accumulated, current) => accumulated + current, 0);
1165
983
 
1166
984
  // Validate layout expectations
1167
985
  if (nextLayout.length !== panelConstraints.length) {
1168
986
  throw Error(`Invalid ${panelConstraints.length} panel layout: ${nextLayout.map(size => `${size}%`).join(", ")}`);
1169
- } else if (!fuzzyNumbersEqual(nextLayout.reduce((accumulated, current) => accumulated + current, 0), 100)) {
987
+ } else if (!fuzzyNumbersEqual(nextLayoutTotalSize, 100)) {
1170
988
  // This is not ideal so we should warn about it, but it may be recoverable in some cases
1171
989
  // (especially if the amount is small)
1172
990
  {
1173
- console.warn(`WARNING: Invalid layout total size: ${nextLayout.map(size => `${size}%`).join(", ")}`);
991
+ console.warn(`WARNING: Invalid layout total size: ${nextLayout.map(size => `${size}%`).join(", ")}. Layout normalization will be applied.`);
992
+ }
993
+ for (let index = 0; index < panelConstraints.length; index++) {
994
+ const unsafeSize = nextLayout[index];
995
+ assert(unsafeSize != null);
996
+ const safeSize = 100 / nextLayoutTotalSize * unsafeSize;
997
+ nextLayout[index] = safeSize;
1174
998
  }
1175
999
  }
1176
1000
  let remainingSize = 0;
@@ -1178,8 +1002,8 @@ function validatePanelGroupLayout({
1178
1002
  // First pass: Validate the proposed layout given each panel's constraints
1179
1003
  for (let index = 0; index < panelConstraints.length; index++) {
1180
1004
  const unsafeSize = nextLayout[index];
1005
+ assert(unsafeSize != null);
1181
1006
  const safeSize = resizePanel({
1182
- groupSizePixels,
1183
1007
  panelConstraints,
1184
1008
  panelIndex: index,
1185
1009
  size: unsafeSize
@@ -1195,9 +1019,9 @@ function validatePanelGroupLayout({
1195
1019
  if (!fuzzyNumbersEqual(remainingSize, 0)) {
1196
1020
  for (let index = 0; index < panelConstraints.length; index++) {
1197
1021
  const prevSize = nextLayout[index];
1022
+ assert(prevSize != null);
1198
1023
  const unsafeSize = prevSize + remainingSize;
1199
1024
  const safeSize = resizePanel({
1200
- groupSizePixels,
1201
1025
  panelConstraints,
1202
1026
  panelIndex: index,
1203
1027
  size: unsafeSize
@@ -1232,21 +1056,20 @@ function PanelGroupWithForwardedRef({
1232
1056
  autoSaveId = null,
1233
1057
  children,
1234
1058
  className: classNameFromProps = "",
1235
- dataAttributes,
1236
1059
  direction,
1237
1060
  forwardedRef,
1238
- id: idFromProps,
1061
+ id: idFromProps = null,
1239
1062
  onLayout = null,
1240
- keyboardResizeByPercentage = null,
1241
- keyboardResizeByPixels = null,
1063
+ keyboardResizeBy = null,
1242
1064
  storage = defaultStorage,
1243
1065
  style: styleFromProps,
1244
- tagName: Type = "div"
1066
+ tagName: Type = "div",
1067
+ ...rest
1245
1068
  }) {
1246
1069
  const groupId = useUniqueId(idFromProps);
1247
1070
  const [dragState, setDragState] = useState(null);
1248
1071
  const [layout, setLayout] = useState([]);
1249
- const panelIdToLastNotifiedMixedSizesMapRef = useRef({});
1072
+ const panelIdToLastNotifiedSizeMapRef = useRef({});
1250
1073
  const panelSizeBeforeCollapseRef = useRef(new Map());
1251
1074
  const prevDeltaRef = useRef(0);
1252
1075
  const committedValuesRef = useRef({
@@ -1254,8 +1077,7 @@ function PanelGroupWithForwardedRef({
1254
1077
  direction,
1255
1078
  dragState,
1256
1079
  id: groupId,
1257
- keyboardResizeByPercentage,
1258
- keyboardResizeByPixels,
1080
+ keyboardResizeBy,
1259
1081
  onLayout,
1260
1082
  storage
1261
1083
  });
@@ -1271,33 +1093,20 @@ function PanelGroupWithForwardedRef({
1271
1093
  useImperativeHandle(forwardedRef, () => ({
1272
1094
  getId: () => committedValuesRef.current.id,
1273
1095
  getLayout: () => {
1274
- const {
1275
- id: groupId
1276
- } = committedValuesRef.current;
1277
1096
  const {
1278
1097
  layout
1279
1098
  } = eagerValuesRef.current;
1280
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1281
- return layout.map(sizePercentage => {
1282
- return {
1283
- sizePercentage,
1284
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1285
- };
1286
- });
1099
+ return layout;
1287
1100
  },
1288
- setLayout: mixedSizes => {
1101
+ setLayout: unsafeLayout => {
1289
1102
  const {
1290
- id: groupId,
1291
1103
  onLayout
1292
1104
  } = committedValuesRef.current;
1293
1105
  const {
1294
1106
  layout: prevLayout,
1295
1107
  panelDataArray
1296
1108
  } = eagerValuesRef.current;
1297
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1298
- const unsafeLayout = mixedSizes.map(mixedSize => getPercentageSizeFromMixedSizes(mixedSize, groupSizePixels));
1299
1109
  const safeLayout = validatePanelGroupLayout({
1300
- groupSizePixels,
1301
1110
  layout: unsafeLayout,
1302
1111
  panelConstraints: panelDataArray.map(panelData => panelData.constraints)
1303
1112
  });
@@ -1305,16 +1114,12 @@ function PanelGroupWithForwardedRef({
1305
1114
  setLayout(safeLayout);
1306
1115
  eagerValuesRef.current.layout = safeLayout;
1307
1116
  if (onLayout) {
1308
- onLayout(safeLayout.map(sizePercentage => ({
1309
- sizePercentage,
1310
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1311
- })));
1117
+ onLayout(safeLayout);
1312
1118
  }
1313
- callPanelCallbacks(groupId, panelDataArray, safeLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1119
+ callPanelCallbacks(panelDataArray, safeLayout, panelIdToLastNotifiedSizeMapRef.current);
1314
1120
  }
1315
1121
  }
1316
1122
  }), []);
1317
-
1318
1123
  useWindowSplitterPanelGroupBehavior({
1319
1124
  committedValuesRef,
1320
1125
  eagerValuesRef,
@@ -1333,12 +1138,14 @@ function PanelGroupWithForwardedRef({
1333
1138
  if (layout.length === 0 || layout.length !== panelDataArray.length) {
1334
1139
  return;
1335
1140
  }
1141
+ let debouncedSave = debounceMap[autoSaveId];
1336
1142
 
1337
1143
  // Limit the frequency of localStorage updates.
1338
- if (!debounceMap[autoSaveId]) {
1339
- debounceMap[autoSaveId] = debounce(savePanelGroupLayout, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
1144
+ if (debouncedSave == null) {
1145
+ debouncedSave = debounce(savePanelGroupLayout, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
1146
+ debounceMap[autoSaveId] = debouncedSave;
1340
1147
  }
1341
- debounceMap[autoSaveId](autoSaveId, panelDataArray, layout, storage);
1148
+ debouncedSave(autoSaveId, panelDataArray, layout, storage);
1342
1149
  }
1343
1150
  }, [autoSaveId, layout, storage]);
1344
1151
 
@@ -1371,12 +1178,12 @@ function PanelGroupWithForwardedRef({
1371
1178
  }
1372
1179
  if (!didLogPanelConstraintsWarning) {
1373
1180
  const panelConstraints = panelDataArray.map(panelData => panelData.constraints);
1374
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1375
1181
  for (let panelIndex = 0; panelIndex < panelConstraints.length; panelIndex++) {
1182
+ const panelData = panelDataArray[panelIndex];
1183
+ assert(panelData);
1376
1184
  const isValid = validatePanelConstraints({
1377
- groupSizePixels,
1378
1185
  panelConstraints,
1379
- panelId: panelDataArray[panelIndex].id,
1186
+ panelId: panelData.id,
1380
1187
  panelIndex
1381
1188
  });
1382
1189
  if (!isValid) {
@@ -1400,20 +1207,19 @@ function PanelGroupWithForwardedRef({
1400
1207
  if (panelData.constraints.collapsible) {
1401
1208
  const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
1402
1209
  const {
1403
- collapsedSizePercentage,
1404
- panelSizePercentage,
1405
- pivotIndices,
1406
- groupSizePixels
1407
- } = panelDataHelper(groupId, panelDataArray, panelData, prevLayout);
1408
- if (panelSizePercentage !== collapsedSizePercentage) {
1210
+ collapsedSize = 0,
1211
+ panelSize,
1212
+ pivotIndices
1213
+ } = panelDataHelper(panelDataArray, panelData, prevLayout);
1214
+ assert(panelSize != null);
1215
+ if (panelSize !== collapsedSize) {
1409
1216
  // Store size before collapse;
1410
1217
  // This is the size that gets restored if the expand() API is used.
1411
- panelSizeBeforeCollapseRef.current.set(panelData.id, panelSizePercentage);
1218
+ panelSizeBeforeCollapseRef.current.set(panelData.id, panelSize);
1412
1219
  const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
1413
- const delta = isLastPanel ? panelSizePercentage - collapsedSizePercentage : collapsedSizePercentage - panelSizePercentage;
1220
+ const delta = isLastPanel ? panelSize - collapsedSize : collapsedSize - panelSize;
1414
1221
  const nextLayout = adjustLayoutByDelta({
1415
1222
  delta,
1416
- groupSizePixels,
1417
1223
  layout: prevLayout,
1418
1224
  panelConstraints: panelConstraintsArray,
1419
1225
  pivotIndices,
@@ -1423,16 +1229,13 @@ function PanelGroupWithForwardedRef({
1423
1229
  setLayout(nextLayout);
1424
1230
  eagerValuesRef.current.layout = nextLayout;
1425
1231
  if (onLayout) {
1426
- onLayout(nextLayout.map(sizePercentage => ({
1427
- sizePercentage,
1428
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1429
- })));
1232
+ onLayout(nextLayout);
1430
1233
  }
1431
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1234
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1432
1235
  }
1433
1236
  }
1434
1237
  }
1435
- }, [groupId]);
1238
+ }, []);
1436
1239
 
1437
1240
  // External APIs are safe to memoize via committed values ref
1438
1241
  const expandPanel = useCallback(panelData => {
@@ -1446,21 +1249,19 @@ function PanelGroupWithForwardedRef({
1446
1249
  if (panelData.constraints.collapsible) {
1447
1250
  const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
1448
1251
  const {
1449
- collapsedSizePercentage,
1450
- panelSizePercentage,
1451
- minSizePercentage,
1452
- pivotIndices,
1453
- groupSizePixels
1454
- } = panelDataHelper(groupId, panelDataArray, panelData, prevLayout);
1455
- if (panelSizePercentage === collapsedSizePercentage) {
1252
+ collapsedSize = 0,
1253
+ panelSize,
1254
+ minSize = 0,
1255
+ pivotIndices
1256
+ } = panelDataHelper(panelDataArray, panelData, prevLayout);
1257
+ if (panelSize === collapsedSize) {
1456
1258
  // Restore this panel to the size it was before it was collapsed, if possible.
1457
- const prevPanelSizePercentage = panelSizeBeforeCollapseRef.current.get(panelData.id);
1458
- const baseSizePercentage = prevPanelSizePercentage != null && prevPanelSizePercentage >= minSizePercentage ? prevPanelSizePercentage : minSizePercentage;
1259
+ const prevPanelSize = panelSizeBeforeCollapseRef.current.get(panelData.id);
1260
+ const baseSize = prevPanelSize != null && prevPanelSize >= minSize ? prevPanelSize : minSize;
1459
1261
  const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
1460
- const delta = isLastPanel ? panelSizePercentage - baseSizePercentage : baseSizePercentage - panelSizePercentage;
1262
+ const delta = isLastPanel ? panelSize - baseSize : baseSize - panelSize;
1461
1263
  const nextLayout = adjustLayoutByDelta({
1462
1264
  delta,
1463
- groupSizePixels,
1464
1265
  layout: prevLayout,
1465
1266
  panelConstraints: panelConstraintsArray,
1466
1267
  pivotIndices,
@@ -1470,16 +1271,13 @@ function PanelGroupWithForwardedRef({
1470
1271
  setLayout(nextLayout);
1471
1272
  eagerValuesRef.current.layout = nextLayout;
1472
1273
  if (onLayout) {
1473
- onLayout(nextLayout.map(sizePercentage => ({
1474
- sizePercentage,
1475
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1476
- })));
1274
+ onLayout(nextLayout);
1477
1275
  }
1478
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1276
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1479
1277
  }
1480
1278
  }
1481
1279
  }
1482
- }, [groupId]);
1280
+ }, []);
1483
1281
 
1484
1282
  // External APIs are safe to memoize via committed values ref
1485
1283
  const getPanelSize = useCallback(panelData => {
@@ -1488,14 +1286,11 @@ function PanelGroupWithForwardedRef({
1488
1286
  panelDataArray
1489
1287
  } = eagerValuesRef.current;
1490
1288
  const {
1491
- panelSizePercentage,
1492
- panelSizePixels
1493
- } = panelDataHelper(groupId, panelDataArray, panelData, layout);
1494
- return {
1495
- sizePercentage: panelSizePercentage,
1496
- sizePixels: panelSizePixels
1497
- };
1498
- }, [groupId]);
1289
+ panelSize
1290
+ } = panelDataHelper(panelDataArray, panelData, layout);
1291
+ assert(panelSize != null);
1292
+ return panelSize;
1293
+ }, []);
1499
1294
 
1500
1295
  // This API should never read from committedValuesRef
1501
1296
  const getPanelStyle = useCallback(panelData => {
@@ -1518,12 +1313,12 @@ function PanelGroupWithForwardedRef({
1518
1313
  panelDataArray
1519
1314
  } = eagerValuesRef.current;
1520
1315
  const {
1521
- collapsedSizePercentage,
1316
+ collapsedSize,
1522
1317
  collapsible,
1523
- panelSizePercentage
1524
- } = panelDataHelper(groupId, panelDataArray, panelData, layout);
1525
- return collapsible === true && panelSizePercentage === collapsedSizePercentage;
1526
- }, [groupId]);
1318
+ panelSize
1319
+ } = panelDataHelper(panelDataArray, panelData, layout);
1320
+ return collapsible === true && panelSize === collapsedSize;
1321
+ }, []);
1527
1322
 
1528
1323
  // External APIs are safe to memoize via committed values ref
1529
1324
  const isPanelExpanded = useCallback(panelData => {
@@ -1532,12 +1327,13 @@ function PanelGroupWithForwardedRef({
1532
1327
  panelDataArray
1533
1328
  } = eagerValuesRef.current;
1534
1329
  const {
1535
- collapsedSizePercentage,
1330
+ collapsedSize = 0,
1536
1331
  collapsible,
1537
- panelSizePercentage
1538
- } = panelDataHelper(groupId, panelDataArray, panelData, layout);
1539
- return !collapsible || panelSizePercentage > collapsedSizePercentage;
1540
- }, [groupId]);
1332
+ panelSize
1333
+ } = panelDataHelper(panelDataArray, panelData, layout);
1334
+ assert(panelSize != null);
1335
+ return !collapsible || panelSize > collapsedSize;
1336
+ }, []);
1541
1337
  const registerPanel = useCallback(panelData => {
1542
1338
  const {
1543
1339
  autoSaveId,
@@ -1577,18 +1373,8 @@ function PanelGroupWithForwardedRef({
1577
1373
  if (autoSaveId) {
1578
1374
  unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
1579
1375
  }
1580
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1581
- if (groupSizePixels <= 0) {
1582
- if (shouldMonitorPixelBasedConstraints(panelDataArray.map(({
1583
- constraints
1584
- }) => constraints))) {
1585
- // Wait until the group has rendered a non-zero size before computing layout.
1586
- return;
1587
- }
1588
- }
1589
1376
  if (unsafeLayout == null) {
1590
1377
  unsafeLayout = calculateUnsafeDefaultLayout({
1591
- groupSizePixels,
1592
1378
  panelDataArray
1593
1379
  });
1594
1380
  }
@@ -1596,7 +1382,6 @@ function PanelGroupWithForwardedRef({
1596
1382
  // Validate even saved layouts in case something has changed since last render
1597
1383
  // e.g. for pixel groups, this could be the size of the window
1598
1384
  const nextLayout = validatePanelGroupLayout({
1599
- groupSizePixels,
1600
1385
  layout: unsafeLayout,
1601
1386
  panelConstraints: panelDataArray.map(panelData => panelData.constraints)
1602
1387
  });
@@ -1608,12 +1393,9 @@ function PanelGroupWithForwardedRef({
1608
1393
  eagerValuesRef.current.layout = nextLayout;
1609
1394
  if (!areEqual(prevLayout, nextLayout)) {
1610
1395
  if (onLayout) {
1611
- onLayout(nextLayout.map(sizePercentage => ({
1612
- sizePercentage,
1613
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1614
- })));
1396
+ onLayout(nextLayout);
1615
1397
  }
1616
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1398
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1617
1399
  }
1618
1400
  }, []);
1619
1401
  const registerResizeHandle = useCallback(dragHandleId => {
@@ -1623,8 +1405,7 @@ function PanelGroupWithForwardedRef({
1623
1405
  direction,
1624
1406
  dragState,
1625
1407
  id: groupId,
1626
- keyboardResizeByPercentage,
1627
- keyboardResizeByPixels,
1408
+ keyboardResizeBy,
1628
1409
  onLayout
1629
1410
  } = committedValuesRef.current;
1630
1411
  const {
@@ -1635,10 +1416,7 @@ function PanelGroupWithForwardedRef({
1635
1416
  initialLayout
1636
1417
  } = dragState !== null && dragState !== void 0 ? dragState : {};
1637
1418
  const pivotIndices = determinePivotIndices(groupId, dragHandleId);
1638
- let delta = calculateDeltaPercentage(event, groupId, dragHandleId, direction, dragState, {
1639
- percentage: keyboardResizeByPercentage,
1640
- pixels: keyboardResizeByPixels
1641
- });
1419
+ let delta = calculateDeltaPercentage(event, dragHandleId, direction, dragState, keyboardResizeBy);
1642
1420
  if (delta === 0) {
1643
1421
  return;
1644
1422
  }
@@ -1648,11 +1426,9 @@ function PanelGroupWithForwardedRef({
1648
1426
  if (document.dir === "rtl" && isHorizontal) {
1649
1427
  delta = -delta;
1650
1428
  }
1651
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1652
1429
  const panelConstraints = panelDataArray.map(panelData => panelData.constraints);
1653
1430
  const nextLayout = adjustLayoutByDelta({
1654
1431
  delta,
1655
- groupSizePixels,
1656
1432
  layout: initialLayout !== null && initialLayout !== void 0 ? initialLayout : prevLayout,
1657
1433
  panelConstraints,
1658
1434
  pivotIndices,
@@ -1688,18 +1464,15 @@ function PanelGroupWithForwardedRef({
1688
1464
  setLayout(nextLayout);
1689
1465
  eagerValuesRef.current.layout = nextLayout;
1690
1466
  if (onLayout) {
1691
- onLayout(nextLayout.map(sizePercentage => ({
1692
- sizePercentage,
1693
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1694
- })));
1467
+ onLayout(nextLayout);
1695
1468
  }
1696
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1469
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1697
1470
  }
1698
1471
  };
1699
1472
  }, []);
1700
1473
 
1701
1474
  // External APIs are safe to memoize via committed values ref
1702
- const resizePanel = useCallback((panelData, mixedSizes) => {
1475
+ const resizePanel = useCallback((panelData, unsafePanelSize) => {
1703
1476
  const {
1704
1477
  onLayout
1705
1478
  } = committedValuesRef.current;
@@ -1709,16 +1482,14 @@ function PanelGroupWithForwardedRef({
1709
1482
  } = eagerValuesRef.current;
1710
1483
  const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
1711
1484
  const {
1712
- groupSizePixels,
1713
- panelSizePercentage,
1485
+ panelSize,
1714
1486
  pivotIndices
1715
- } = panelDataHelper(groupId, panelDataArray, panelData, prevLayout);
1716
- const sizePercentage = getPercentageSizeFromMixedSizes(mixedSizes, groupSizePixels);
1487
+ } = panelDataHelper(panelDataArray, panelData, prevLayout);
1488
+ assert(panelSize != null);
1717
1489
  const isLastPanel = panelDataArray.indexOf(panelData) === panelDataArray.length - 1;
1718
- const delta = isLastPanel ? panelSizePercentage - sizePercentage : sizePercentage - panelSizePercentage;
1490
+ const delta = isLastPanel ? panelSize - unsafePanelSize : unsafePanelSize - panelSize;
1719
1491
  const nextLayout = adjustLayoutByDelta({
1720
1492
  delta,
1721
- groupSizePixels,
1722
1493
  layout: prevLayout,
1723
1494
  panelConstraints: panelConstraintsArray,
1724
1495
  pivotIndices,
@@ -1728,14 +1499,11 @@ function PanelGroupWithForwardedRef({
1728
1499
  setLayout(nextLayout);
1729
1500
  eagerValuesRef.current.layout = nextLayout;
1730
1501
  if (onLayout) {
1731
- onLayout(nextLayout.map(sizePercentage => ({
1732
- sizePercentage,
1733
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1734
- })));
1502
+ onLayout(nextLayout);
1735
1503
  }
1736
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1504
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1737
1505
  }
1738
- }, [groupId]);
1506
+ }, []);
1739
1507
  const startDragging = useCallback((dragHandleId, event) => {
1740
1508
  const {
1741
1509
  direction
@@ -1744,6 +1512,7 @@ function PanelGroupWithForwardedRef({
1744
1512
  layout
1745
1513
  } = eagerValuesRef.current;
1746
1514
  const handleElement = getResizeHandleElement(dragHandleId);
1515
+ assert(handleElement);
1747
1516
  const initialCursorPosition = getResizeEventCursorPosition(direction, event);
1748
1517
  setDragState({
1749
1518
  dragHandleId,
@@ -1762,7 +1531,6 @@ function PanelGroupWithForwardedRef({
1762
1531
  });
1763
1532
  const unregisterPanel = useCallback(panelData => {
1764
1533
  const {
1765
- id: groupId,
1766
1534
  onLayout
1767
1535
  } = committedValuesRef.current;
1768
1536
  const {
@@ -1785,7 +1553,7 @@ function PanelGroupWithForwardedRef({
1785
1553
  const {
1786
1554
  pendingPanelIds
1787
1555
  } = unregisterPanelRef.current;
1788
- const map = panelIdToLastNotifiedMixedSizesMapRef.current;
1556
+ const map = panelIdToLastNotifiedSizeMapRef.current;
1789
1557
 
1790
1558
  // TRICKY
1791
1559
  // Strict effects mode
@@ -1794,7 +1562,7 @@ function PanelGroupWithForwardedRef({
1794
1562
  pendingPanelIds.delete(panelId);
1795
1563
  if (panelDataArray.find(({
1796
1564
  id
1797
- }) => id === panelId) == null) {
1565
+ }) => id === panelId) != null) {
1798
1566
  unmountDueToStrictMode = true;
1799
1567
 
1800
1568
  // TRICKY
@@ -1811,16 +1579,13 @@ function PanelGroupWithForwardedRef({
1811
1579
  // The group is unmounting; skip layout calculation.
1812
1580
  return;
1813
1581
  }
1814
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1815
1582
  let unsafeLayout = calculateUnsafeDefaultLayout({
1816
- groupSizePixels,
1817
1583
  panelDataArray
1818
1584
  });
1819
1585
 
1820
1586
  // Validate even saved layouts in case something has changed since last render
1821
1587
  // e.g. for pixel groups, this could be the size of the window
1822
1588
  const nextLayout = validatePanelGroupLayout({
1823
- groupSizePixels,
1824
1589
  layout: unsafeLayout,
1825
1590
  panelConstraints: panelDataArray.map(panelData => panelData.constraints)
1826
1591
  });
@@ -1828,12 +1593,9 @@ function PanelGroupWithForwardedRef({
1828
1593
  setLayout(nextLayout);
1829
1594
  eagerValuesRef.current.layout = nextLayout;
1830
1595
  if (onLayout) {
1831
- onLayout(nextLayout.map(sizePercentage => ({
1832
- sizePercentage,
1833
- sizePixels: convertPercentageToPixels(sizePercentage, groupSizePixels)
1834
- })));
1596
+ onLayout(nextLayout);
1835
1597
  }
1836
- callPanelCallbacks(groupId, panelDataArray, nextLayout, panelIdToLastNotifiedMixedSizesMapRef.current);
1598
+ callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1837
1599
  }
1838
1600
  }, 0);
1839
1601
  }, []);
@@ -1864,13 +1626,13 @@ function PanelGroupWithForwardedRef({
1864
1626
  return createElement(PanelGroupContext.Provider, {
1865
1627
  value: context
1866
1628
  }, createElement(Type, {
1629
+ ...rest,
1867
1630
  children,
1868
1631
  className: classNameFromProps,
1869
1632
  style: {
1870
1633
  ...style,
1871
1634
  ...styleFromProps
1872
1635
  },
1873
- ...dataAttributes,
1874
1636
  // CSS selectors
1875
1637
  "data-panel-group": "",
1876
1638
  "data-panel-group-direction": direction,
@@ -1883,22 +1645,16 @@ const PanelGroup = forwardRef((props, ref) => createElement(PanelGroupWithForwar
1883
1645
  }));
1884
1646
  PanelGroupWithForwardedRef.displayName = "PanelGroup";
1885
1647
  PanelGroup.displayName = "forwardRef(PanelGroup)";
1886
- function panelDataHelper(groupId, panelDataArray, panelData, layout) {
1648
+ function panelDataHelper(panelDataArray, panelData, layout) {
1887
1649
  const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
1888
1650
  const panelIndex = panelDataArray.indexOf(panelData);
1889
1651
  const panelConstraints = panelConstraintsArray[panelIndex];
1890
- const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1891
- const percentagePanelConstraints = computePercentagePanelConstraints(panelConstraintsArray, panelIndex, groupSizePixels);
1892
1652
  const isLastPanel = panelIndex === panelDataArray.length - 1;
1893
1653
  const pivotIndices = isLastPanel ? [panelIndex - 1, panelIndex] : [panelIndex, panelIndex + 1];
1894
- const panelSizePercentage = layout[panelIndex];
1895
- const panelSizePixels = convertPercentageToPixels(panelSizePercentage, groupSizePixels);
1654
+ const panelSize = layout[panelIndex];
1896
1655
  return {
1897
- ...percentagePanelConstraints,
1898
- collapsible: panelConstraints.collapsible,
1899
- panelSizePercentage,
1900
- panelSizePixels,
1901
- groupSizePixels,
1656
+ ...panelConstraints,
1657
+ panelSize,
1902
1658
  pivotIndices
1903
1659
  };
1904
1660
  }
@@ -1938,6 +1694,7 @@ function useWindowSplitterResizeHandlerBehavior({
1938
1694
  {
1939
1695
  event.preventDefault();
1940
1696
  const groupId = handleElement.getAttribute("data-panel-group-id");
1697
+ assert(groupId);
1941
1698
  const handles = getResizeHandleElementsForGroup(groupId);
1942
1699
  const index = getResizeHandleElementIndex(groupId, handleId);
1943
1700
  assert(index !== null);
@@ -1958,12 +1715,13 @@ function useWindowSplitterResizeHandlerBehavior({
1958
1715
  function PanelResizeHandle({
1959
1716
  children = null,
1960
1717
  className: classNameFromProps = "",
1961
- dataAttributes,
1962
1718
  disabled = false,
1963
- id: idFromProps = null,
1719
+ id: idFromProps,
1964
1720
  onDragging,
1965
1721
  style: styleFromProps = {},
1966
- tagName: Type = "div"
1722
+ tabIndex = 0,
1723
+ tagName: Type = "div",
1724
+ ...rest
1967
1725
  }) {
1968
1726
  const divElementRef = useRef(null);
1969
1727
 
@@ -1993,8 +1751,9 @@ function PanelResizeHandle({
1993
1751
  const stopDraggingAndBlur = useCallback(() => {
1994
1752
  // Clicking on the drag handle shouldn't leave it focused;
1995
1753
  // That would cause the PanelGroup to think it was still active.
1996
- const div = divElementRef.current;
1997
- div.blur();
1754
+ const divElement = divElementRef.current;
1755
+ assert(divElement);
1756
+ divElement.blur();
1998
1757
  stopDragging();
1999
1758
  const {
2000
1759
  onDragging
@@ -2022,6 +1781,7 @@ function PanelResizeHandle({
2022
1781
  resizeHandler(event);
2023
1782
  };
2024
1783
  const divElement = divElementRef.current;
1784
+ assert(divElement);
2025
1785
  const targetDocument = divElement.ownerDocument;
2026
1786
  targetDocument.body.addEventListener("contextmenu", stopDraggingAndBlur);
2027
1787
  targetDocument.body.addEventListener("mousemove", onMove);
@@ -2049,15 +1809,18 @@ function PanelResizeHandle({
2049
1809
  userSelect: "none"
2050
1810
  };
2051
1811
  return createElement(Type, {
1812
+ ...rest,
2052
1813
  children,
2053
1814
  className: classNameFromProps,
2054
1815
  onBlur: () => setIsFocused(false),
2055
1816
  onFocus: () => setIsFocused(true),
2056
1817
  onMouseDown: event => {
2057
1818
  startDragging(resizeHandleId, event.nativeEvent);
1819
+ const callbacks = callbacksRef.current;
1820
+ assert(callbacks);
2058
1821
  const {
2059
1822
  onDragging
2060
- } = callbacksRef.current;
1823
+ } = callbacks;
2061
1824
  if (onDragging) {
2062
1825
  onDragging(true);
2063
1826
  }
@@ -2067,9 +1830,11 @@ function PanelResizeHandle({
2067
1830
  onTouchEnd: stopDraggingAndBlur,
2068
1831
  onTouchStart: event => {
2069
1832
  startDragging(resizeHandleId, event.nativeEvent);
1833
+ const callbacks = callbacksRef.current;
1834
+ assert(callbacks);
2070
1835
  const {
2071
1836
  onDragging
2072
- } = callbacksRef.current;
1837
+ } = callbacks;
2073
1838
  if (onDragging) {
2074
1839
  onDragging(true);
2075
1840
  }
@@ -2080,8 +1845,7 @@ function PanelResizeHandle({
2080
1845
  ...style,
2081
1846
  ...styleFromProps
2082
1847
  },
2083
- tabIndex: 0,
2084
- ...dataAttributes,
1848
+ tabIndex,
2085
1849
  // CSS selectors
2086
1850
  "data-panel-group-direction": direction,
2087
1851
  "data-panel-group-id": groupId,
@@ -2096,3 +1860,4 @@ PanelResizeHandle.displayName = "PanelResizeHandle";
2096
1860
  exports.Panel = Panel;
2097
1861
  exports.PanelGroup = PanelGroup;
2098
1862
  exports.PanelResizeHandle = PanelResizeHandle;
1863
+ exports.assert = assert;