react-resizable-panels 0.0.57 → 0.0.58

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 (29) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/declarations/src/Panel.d.ts +7 -3
  3. package/dist/declarations/src/PanelGroup.d.ts +3 -1
  4. package/dist/declarations/src/PanelResizeHandle.d.ts +3 -1
  5. package/dist/declarations/src/types.d.ts +3 -0
  6. package/dist/react-resizable-panels.browser.cjs.js +129 -57
  7. package/dist/react-resizable-panels.browser.development.cjs.js +129 -57
  8. package/dist/react-resizable-panels.browser.development.esm.js +129 -57
  9. package/dist/react-resizable-panels.browser.esm.js +129 -57
  10. package/dist/react-resizable-panels.cjs.js +129 -57
  11. package/dist/react-resizable-panels.cjs.js.map +1 -1
  12. package/dist/react-resizable-panels.development.cjs.js +129 -57
  13. package/dist/react-resizable-panels.development.esm.js +129 -57
  14. package/dist/react-resizable-panels.development.node.cjs.js +129 -57
  15. package/dist/react-resizable-panels.development.node.esm.js +129 -57
  16. package/dist/react-resizable-panels.esm.js +129 -57
  17. package/dist/react-resizable-panels.esm.js.map +1 -1
  18. package/dist/react-resizable-panels.node.cjs.js +129 -57
  19. package/dist/react-resizable-panels.node.esm.js +129 -57
  20. package/package.json +1 -1
  21. package/src/Panel.ts +8 -2
  22. package/src/PanelGroup.ts +5 -1
  23. package/src/PanelResizeHandle.ts +5 -0
  24. package/src/types.ts +4 -0
  25. package/src/utils/adjustLayoutByDelta.test.ts +238 -8
  26. package/src/utils/adjustLayoutByDelta.ts +122 -72
  27. package/src/utils/resizePanel.test.ts +61 -1
  28. package/src/utils/resizePanel.ts +7 -1
  29. package/src/utils/validatePanelGroupLayout.test.ts +36 -6
@@ -66,6 +66,7 @@ function PanelWithForwardedRef({
66
66
  collapsedSizePercentage,
67
67
  collapsedSizePixels,
68
68
  collapsible,
69
+ dataAttributes,
69
70
  defaultSizePercentage,
70
71
  defaultSizePixels,
71
72
  forwardedRef,
@@ -151,6 +152,7 @@ function PanelWithForwardedRef({
151
152
  ...style,
152
153
  ...styleFromProps
153
154
  },
155
+ ...dataAttributes,
154
156
  // CSS selectors
155
157
  "data-panel": "",
156
158
  "data-panel-id": panelId,
@@ -288,7 +290,13 @@ function resizePanel({
288
290
  if (minSizePercentage != null) {
289
291
  if (fuzzyCompareNumbers(size, minSizePercentage) < 0) {
290
292
  if (collapsible) {
291
- size = collapsedSizePercentage;
293
+ // Collapsible panels should snap closed or open only once they cross the halfway point between collapsed and min size.
294
+ const halfwayPoint = (collapsedSizePercentage + minSizePercentage) / 2;
295
+ if (fuzzyCompareNumbers(size, halfwayPoint) < 0) {
296
+ size = collapsedSizePercentage;
297
+ } else {
298
+ size = minSizePercentage;
299
+ }
292
300
  } else {
293
301
  size = minSizePercentage;
294
302
  }
@@ -315,60 +323,123 @@ function adjustLayoutByDelta({
315
323
  const nextLayout = [...prevLayout];
316
324
  let deltaApplied = 0;
317
325
 
326
+ //const DEBUG = [];
327
+ //DEBUG.push(`adjustLayoutByDelta() ${prevLayout.join(", ")}`);
328
+ //DEBUG.push(` delta: ${delta}`);
329
+ //DEBUG.push(` pivotIndices: ${pivotIndices.join(", ")}`);
330
+ //DEBUG.push(` trigger: ${trigger}`);
331
+ //DEBUG.push("");
332
+
318
333
  // A resizing panel affects the panels before or after it.
319
334
  //
320
- // A negative delta means the panel immediately after the resizer should grow/expand by decreasing its offset.
335
+ // A negative delta means the panel(s) immediately after the resize handle should grow/expand by decreasing its offset.
321
336
  // Other panels may also need to shrink/contract (and shift) to make room, depending on the min weights.
322
337
  //
323
- // A positive delta means the panel immediately before the resizer should "expand".
324
- // This is accomplished by shrinking/contracting (and shifting) one or more of the panels after the resizer.
338
+ // A positive delta means the panel(s) immediately before the resize handle should "expand".
339
+ // This is accomplished by shrinking/contracting (and shifting) one or more of the panels after the resize handle.
325
340
 
326
- // First, check the panel we're pivoting around;
327
- // We should only expand or contract by as much as its constraints allow
328
341
  {
329
- const pivotIndex = delta < 0 ? pivotIndices[1] : pivotIndices[0];
330
- const initialSize = nextLayout[pivotIndex];
331
- const {
332
- collapsible
333
- } = panelConstraints[pivotIndex];
334
- const {
335
- collapsedSizePercentage,
336
- minSizePercentage
337
- } = computePercentagePanelConstraints(panelConstraints, pivotIndex, groupSizePixels);
338
- const isCollapsed = collapsible && fuzzyNumbersEqual(initialSize, collapsedSizePercentage);
339
- let unsafeSize = initialSize + Math.abs(delta);
340
- if (isCollapsed) {
341
- switch (trigger) {
342
- case "keyboard":
343
- if (minSizePercentage > unsafeSize) {
344
- unsafeSize = minSizePercentage;
342
+ // If this is a resize triggered by a keyboard event, our logic for expanding/collapsing is different.
343
+ // We no longer check the halfway threshold because this may prevent the panel from expanding at all.
344
+ if (trigger === "keyboard") {
345
+ {
346
+ // Check if we should expand a collapsed panel
347
+ const index = delta < 0 ? pivotIndices[1] : pivotIndices[0];
348
+ const constraints = panelConstraints[index];
349
+ //DEBUG.push(`edge case check 1: ${index}`);
350
+ //DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
351
+ if (constraints.collapsible) {
352
+ const prevSize = prevLayout[index];
353
+ const {
354
+ collapsedSizePercentage,
355
+ minSizePercentage
356
+ } = computePercentagePanelConstraints(panelConstraints, index, groupSizePixels);
357
+ if (fuzzyNumbersEqual(prevSize, collapsedSizePercentage)) {
358
+ const localDelta = minSizePercentage - prevSize;
359
+ //DEBUG.push(` -> expand delta: ${localDelta}`);
360
+
361
+ if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
362
+ delta = delta < 0 ? 0 - localDelta : localDelta;
363
+ //DEBUG.push(` -> delta: ${delta}`);
364
+ }
365
+ }
366
+ }
367
+ }
368
+
369
+ {
370
+ // Check if we should collapse a panel at its minimum size
371
+ const index = delta < 0 ? pivotIndices[0] : pivotIndices[1];
372
+ const constraints = panelConstraints[index];
373
+ //DEBUG.push(`edge case check 2: ${index}`);
374
+ //DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
375
+ if (constraints.collapsible) {
376
+ const prevSize = prevLayout[index];
377
+ const {
378
+ collapsedSizePercentage,
379
+ minSizePercentage
380
+ } = computePercentagePanelConstraints(panelConstraints, index, groupSizePixels);
381
+ if (fuzzyNumbersEqual(prevSize, minSizePercentage)) {
382
+ const localDelta = prevSize - collapsedSizePercentage;
383
+ //DEBUG.push(` -> expand delta: ${localDelta}`);
384
+
385
+ if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
386
+ delta = delta < 0 ? 0 - localDelta : localDelta;
387
+ //DEBUG.push(` -> delta: ${delta}`);
388
+ }
345
389
  }
390
+ }
346
391
  }
347
392
  }
348
- const safeSize = resizePanel({
349
- groupSizePixels,
350
- panelConstraints,
351
- panelIndex: pivotIndex,
352
- size: unsafeSize
353
- });
354
- if (fuzzyNumbersEqual(initialSize, safeSize)) {
355
- // If there's no room for the pivot panel to grow, we should ignore this change
356
- return nextLayout;
357
- } else {
358
- delta = delta < 0 ? initialSize - safeSize : safeSize - initialSize;
393
+ //DEBUG.push("");
394
+ }
395
+
396
+ {
397
+ // Pre-calculate max available delta in the opposite direction of our pivot.
398
+ // This will be the maximum amount we're allowed to expand/contract the panels in the primary direction.
399
+ // If this amount is less than the requested delta, adjust the requested delta.
400
+ // If this amount is greater than the requested delta, that's useful information too–
401
+ // as an expanding panel might change from collapsed to min size.
402
+
403
+ const increment = delta < 0 ? 1 : -1;
404
+ let index = delta < 0 ? pivotIndices[1] : pivotIndices[0];
405
+ let maxAvailableDelta = 0;
406
+
407
+ //DEBUG.push("pre calc...");
408
+ while (true) {
409
+ const prevSize = prevLayout[index];
410
+ const maxSafeSize = resizePanel({
411
+ groupSizePixels,
412
+ panelConstraints,
413
+ panelIndex: index,
414
+ size: 100
415
+ });
416
+ const delta = maxSafeSize - prevSize;
417
+ //DEBUG.push(` ${index}: ${prevSize} -> ${maxSafeSize}`);
418
+
419
+ maxAvailableDelta += delta;
420
+ index += increment;
421
+ if (index < 0 || index >= panelConstraints.length) {
422
+ break;
423
+ }
359
424
  }
425
+
426
+ //DEBUG.push(` -> max available delta: ${maxAvailableDelta}`);
427
+ const minAbsDelta = Math.min(Math.abs(delta), Math.abs(maxAvailableDelta));
428
+ delta = delta < 0 ? 0 - minAbsDelta : minAbsDelta;
429
+ //DEBUG.push(` -> adjusted delta: ${delta}`);
430
+ //DEBUG.push("");
360
431
  }
361
432
 
362
- // Delta added to a panel needs to be subtracted from other panels
363
- // within the constraints that those panels allow
364
433
  {
434
+ // Delta added to a panel needs to be subtracted from other panels (within the constraints that those panels allow).
435
+
365
436
  const pivotIndex = delta < 0 ? pivotIndices[0] : pivotIndices[1];
366
437
  let index = pivotIndex;
367
438
  while (index >= 0 && index < panelConstraints.length) {
368
439
  const deltaRemaining = Math.abs(delta) - Math.abs(deltaApplied);
369
440
  const prevSize = prevLayout[index];
370
441
  const unsafeSize = prevSize - deltaRemaining;
371
- let safeSize = resizePanel({
442
+ const safeSize = resizePanel({
372
443
  groupSizePixels,
373
444
  panelConstraints,
374
445
  panelIndex: index,
@@ -390,13 +461,18 @@ function adjustLayoutByDelta({
390
461
  }
391
462
  }
392
463
  }
464
+ //DEBUG.push(`after 1: ${nextLayout.join(", ")}`);
465
+ //DEBUG.push(` deltaApplied: ${deltaApplied}`);
466
+ //DEBUG.push("");
393
467
 
394
468
  // If we were unable to resize any of the panels panels, return the previous state.
395
469
  // This will essentially bailout and ignore e.g. drags past a panel's boundaries
396
470
  if (fuzzyNumbersEqual(deltaApplied, 0)) {
471
+ //console.log(DEBUG.join("\n"));
397
472
  return prevLayout;
398
473
  }
399
474
  {
475
+ // Now distribute the applied delta to the panels in the other direction
400
476
  const pivotIndex = delta < 0 ? pivotIndices[1] : pivotIndices[0];
401
477
  const unsafeSize = prevLayout[pivotIndex] + deltaApplied;
402
478
  const safeSize = resizePanel({
@@ -436,29 +512,21 @@ function adjustLayoutByDelta({
436
512
  index++;
437
513
  }
438
514
  }
439
-
440
- // If we can't redistribute, this layout is invalid;
441
- // There may be an incremental layout that is valid though
442
- if (!fuzzyNumbersEqual(deltaRemaining, 0)) {
443
- try {
444
- return adjustLayoutByDelta({
445
- delta: delta < 0 ? delta + 1 : delta - 1,
446
- groupSizePixels,
447
- layout: prevLayout,
448
- panelConstraints,
449
- pivotIndices,
450
- trigger
451
- });
452
- } catch (error) {
453
- if (error instanceof RangeError) {
454
- console.error(`Could not apply delta ${delta} to layout`);
455
- return prevLayout;
456
- }
457
- } finally {
458
- }
459
- }
460
515
  }
461
516
  }
517
+ //DEBUG.push(`after 2: ${nextLayout.join(", ")}`);
518
+ //DEBUG.push(` deltaApplied: ${deltaApplied}`);
519
+ //DEBUG.push("");
520
+
521
+ const totalSize = nextLayout.reduce((total, size) => size + total, 0);
522
+ deltaApplied = 100 - totalSize;
523
+ //DEBUG.push(`total size: ${totalSize}`);
524
+ //DEBUG.push(` deltaApplied: ${deltaApplied}`);
525
+ //console.log(DEBUG.join("\n"));
526
+
527
+ if (!fuzzyNumbersEqual(totalSize, 100)) {
528
+ return prevLayout;
529
+ }
462
530
  return nextLayout;
463
531
  }
464
532
 
@@ -1022,6 +1090,7 @@ function PanelGroupWithForwardedRef({
1022
1090
  autoSaveId,
1023
1091
  children,
1024
1092
  className: classNameFromProps = "",
1093
+ dataAttributes,
1025
1094
  direction,
1026
1095
  forwardedRef,
1027
1096
  id: idFromProps,
@@ -1456,6 +1525,7 @@ function PanelGroupWithForwardedRef({
1456
1525
  ...style,
1457
1526
  ...styleFromProps
1458
1527
  },
1528
+ ...dataAttributes,
1459
1529
  // CSS selectors
1460
1530
  "data-panel-group": "",
1461
1531
  "data-panel-group-direction": direction,
@@ -1543,6 +1613,7 @@ function useWindowSplitterResizeHandlerBehavior({
1543
1613
  function PanelResizeHandle({
1544
1614
  children = null,
1545
1615
  className: classNameFromProps = "",
1616
+ dataAttributes,
1546
1617
  disabled = false,
1547
1618
  id: idFromProps = null,
1548
1619
  onDragging,
@@ -1665,6 +1736,7 @@ function PanelResizeHandle({
1665
1736
  ...styleFromProps
1666
1737
  },
1667
1738
  tabIndex: 0,
1739
+ ...dataAttributes,
1668
1740
  // CSS selectors
1669
1741
  "data-panel-group-direction": direction,
1670
1742
  "data-panel-group-id": groupId,
@@ -42,6 +42,7 @@ function PanelWithForwardedRef({
42
42
  collapsedSizePercentage,
43
43
  collapsedSizePixels,
44
44
  collapsible,
45
+ dataAttributes,
45
46
  defaultSizePercentage,
46
47
  defaultSizePixels,
47
48
  forwardedRef,
@@ -127,6 +128,7 @@ function PanelWithForwardedRef({
127
128
  ...style,
128
129
  ...styleFromProps
129
130
  },
131
+ ...dataAttributes,
130
132
  // CSS selectors
131
133
  "data-panel": "",
132
134
  "data-panel-id": panelId,
@@ -264,7 +266,13 @@ function resizePanel({
264
266
  if (minSizePercentage != null) {
265
267
  if (fuzzyCompareNumbers(size, minSizePercentage) < 0) {
266
268
  if (collapsible) {
267
- size = collapsedSizePercentage;
269
+ // Collapsible panels should snap closed or open only once they cross the halfway point between collapsed and min size.
270
+ const halfwayPoint = (collapsedSizePercentage + minSizePercentage) / 2;
271
+ if (fuzzyCompareNumbers(size, halfwayPoint) < 0) {
272
+ size = collapsedSizePercentage;
273
+ } else {
274
+ size = minSizePercentage;
275
+ }
268
276
  } else {
269
277
  size = minSizePercentage;
270
278
  }
@@ -291,60 +299,123 @@ function adjustLayoutByDelta({
291
299
  const nextLayout = [...prevLayout];
292
300
  let deltaApplied = 0;
293
301
 
302
+ //const DEBUG = [];
303
+ //DEBUG.push(`adjustLayoutByDelta() ${prevLayout.join(", ")}`);
304
+ //DEBUG.push(` delta: ${delta}`);
305
+ //DEBUG.push(` pivotIndices: ${pivotIndices.join(", ")}`);
306
+ //DEBUG.push(` trigger: ${trigger}`);
307
+ //DEBUG.push("");
308
+
294
309
  // A resizing panel affects the panels before or after it.
295
310
  //
296
- // A negative delta means the panel immediately after the resizer should grow/expand by decreasing its offset.
311
+ // A negative delta means the panel(s) immediately after the resize handle should grow/expand by decreasing its offset.
297
312
  // Other panels may also need to shrink/contract (and shift) to make room, depending on the min weights.
298
313
  //
299
- // A positive delta means the panel immediately before the resizer should "expand".
300
- // This is accomplished by shrinking/contracting (and shifting) one or more of the panels after the resizer.
314
+ // A positive delta means the panel(s) immediately before the resize handle should "expand".
315
+ // This is accomplished by shrinking/contracting (and shifting) one or more of the panels after the resize handle.
301
316
 
302
- // First, check the panel we're pivoting around;
303
- // We should only expand or contract by as much as its constraints allow
304
317
  {
305
- const pivotIndex = delta < 0 ? pivotIndices[1] : pivotIndices[0];
306
- const initialSize = nextLayout[pivotIndex];
307
- const {
308
- collapsible
309
- } = panelConstraints[pivotIndex];
310
- const {
311
- collapsedSizePercentage,
312
- minSizePercentage
313
- } = computePercentagePanelConstraints(panelConstraints, pivotIndex, groupSizePixels);
314
- const isCollapsed = collapsible && fuzzyNumbersEqual(initialSize, collapsedSizePercentage);
315
- let unsafeSize = initialSize + Math.abs(delta);
316
- if (isCollapsed) {
317
- switch (trigger) {
318
- case "keyboard":
319
- if (minSizePercentage > unsafeSize) {
320
- unsafeSize = minSizePercentage;
318
+ // If this is a resize triggered by a keyboard event, our logic for expanding/collapsing is different.
319
+ // We no longer check the halfway threshold because this may prevent the panel from expanding at all.
320
+ if (trigger === "keyboard") {
321
+ {
322
+ // Check if we should expand a collapsed panel
323
+ const index = delta < 0 ? pivotIndices[1] : pivotIndices[0];
324
+ const constraints = panelConstraints[index];
325
+ //DEBUG.push(`edge case check 1: ${index}`);
326
+ //DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
327
+ if (constraints.collapsible) {
328
+ const prevSize = prevLayout[index];
329
+ const {
330
+ collapsedSizePercentage,
331
+ minSizePercentage
332
+ } = computePercentagePanelConstraints(panelConstraints, index, groupSizePixels);
333
+ if (fuzzyNumbersEqual(prevSize, collapsedSizePercentage)) {
334
+ const localDelta = minSizePercentage - prevSize;
335
+ //DEBUG.push(` -> expand delta: ${localDelta}`);
336
+
337
+ if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
338
+ delta = delta < 0 ? 0 - localDelta : localDelta;
339
+ //DEBUG.push(` -> delta: ${delta}`);
340
+ }
341
+ }
342
+ }
343
+ }
344
+
345
+ {
346
+ // Check if we should collapse a panel at its minimum size
347
+ const index = delta < 0 ? pivotIndices[0] : pivotIndices[1];
348
+ const constraints = panelConstraints[index];
349
+ //DEBUG.push(`edge case check 2: ${index}`);
350
+ //DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
351
+ if (constraints.collapsible) {
352
+ const prevSize = prevLayout[index];
353
+ const {
354
+ collapsedSizePercentage,
355
+ minSizePercentage
356
+ } = computePercentagePanelConstraints(panelConstraints, index, groupSizePixels);
357
+ if (fuzzyNumbersEqual(prevSize, minSizePercentage)) {
358
+ const localDelta = prevSize - collapsedSizePercentage;
359
+ //DEBUG.push(` -> expand delta: ${localDelta}`);
360
+
361
+ if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
362
+ delta = delta < 0 ? 0 - localDelta : localDelta;
363
+ //DEBUG.push(` -> delta: ${delta}`);
364
+ }
321
365
  }
366
+ }
322
367
  }
323
368
  }
324
- const safeSize = resizePanel({
325
- groupSizePixels,
326
- panelConstraints,
327
- panelIndex: pivotIndex,
328
- size: unsafeSize
329
- });
330
- if (fuzzyNumbersEqual(initialSize, safeSize)) {
331
- // If there's no room for the pivot panel to grow, we should ignore this change
332
- return nextLayout;
333
- } else {
334
- delta = delta < 0 ? initialSize - safeSize : safeSize - initialSize;
369
+ //DEBUG.push("");
370
+ }
371
+
372
+ {
373
+ // Pre-calculate max available delta in the opposite direction of our pivot.
374
+ // This will be the maximum amount we're allowed to expand/contract the panels in the primary direction.
375
+ // If this amount is less than the requested delta, adjust the requested delta.
376
+ // If this amount is greater than the requested delta, that's useful information too–
377
+ // as an expanding panel might change from collapsed to min size.
378
+
379
+ const increment = delta < 0 ? 1 : -1;
380
+ let index = delta < 0 ? pivotIndices[1] : pivotIndices[0];
381
+ let maxAvailableDelta = 0;
382
+
383
+ //DEBUG.push("pre calc...");
384
+ while (true) {
385
+ const prevSize = prevLayout[index];
386
+ const maxSafeSize = resizePanel({
387
+ groupSizePixels,
388
+ panelConstraints,
389
+ panelIndex: index,
390
+ size: 100
391
+ });
392
+ const delta = maxSafeSize - prevSize;
393
+ //DEBUG.push(` ${index}: ${prevSize} -> ${maxSafeSize}`);
394
+
395
+ maxAvailableDelta += delta;
396
+ index += increment;
397
+ if (index < 0 || index >= panelConstraints.length) {
398
+ break;
399
+ }
335
400
  }
401
+
402
+ //DEBUG.push(` -> max available delta: ${maxAvailableDelta}`);
403
+ const minAbsDelta = Math.min(Math.abs(delta), Math.abs(maxAvailableDelta));
404
+ delta = delta < 0 ? 0 - minAbsDelta : minAbsDelta;
405
+ //DEBUG.push(` -> adjusted delta: ${delta}`);
406
+ //DEBUG.push("");
336
407
  }
337
408
 
338
- // Delta added to a panel needs to be subtracted from other panels
339
- // within the constraints that those panels allow
340
409
  {
410
+ // Delta added to a panel needs to be subtracted from other panels (within the constraints that those panels allow).
411
+
341
412
  const pivotIndex = delta < 0 ? pivotIndices[0] : pivotIndices[1];
342
413
  let index = pivotIndex;
343
414
  while (index >= 0 && index < panelConstraints.length) {
344
415
  const deltaRemaining = Math.abs(delta) - Math.abs(deltaApplied);
345
416
  const prevSize = prevLayout[index];
346
417
  const unsafeSize = prevSize - deltaRemaining;
347
- let safeSize = resizePanel({
418
+ const safeSize = resizePanel({
348
419
  groupSizePixels,
349
420
  panelConstraints,
350
421
  panelIndex: index,
@@ -366,13 +437,18 @@ function adjustLayoutByDelta({
366
437
  }
367
438
  }
368
439
  }
440
+ //DEBUG.push(`after 1: ${nextLayout.join(", ")}`);
441
+ //DEBUG.push(` deltaApplied: ${deltaApplied}`);
442
+ //DEBUG.push("");
369
443
 
370
444
  // If we were unable to resize any of the panels panels, return the previous state.
371
445
  // This will essentially bailout and ignore e.g. drags past a panel's boundaries
372
446
  if (fuzzyNumbersEqual(deltaApplied, 0)) {
447
+ //console.log(DEBUG.join("\n"));
373
448
  return prevLayout;
374
449
  }
375
450
  {
451
+ // Now distribute the applied delta to the panels in the other direction
376
452
  const pivotIndex = delta < 0 ? pivotIndices[1] : pivotIndices[0];
377
453
  const unsafeSize = prevLayout[pivotIndex] + deltaApplied;
378
454
  const safeSize = resizePanel({
@@ -412,29 +488,21 @@ function adjustLayoutByDelta({
412
488
  index++;
413
489
  }
414
490
  }
415
-
416
- // If we can't redistribute, this layout is invalid;
417
- // There may be an incremental layout that is valid though
418
- if (!fuzzyNumbersEqual(deltaRemaining, 0)) {
419
- try {
420
- return adjustLayoutByDelta({
421
- delta: delta < 0 ? delta + 1 : delta - 1,
422
- groupSizePixels,
423
- layout: prevLayout,
424
- panelConstraints,
425
- pivotIndices,
426
- trigger
427
- });
428
- } catch (error) {
429
- if (error instanceof RangeError) {
430
- console.error(`Could not apply delta ${delta} to layout`);
431
- return prevLayout;
432
- }
433
- } finally {
434
- }
435
- }
436
491
  }
437
492
  }
493
+ //DEBUG.push(`after 2: ${nextLayout.join(", ")}`);
494
+ //DEBUG.push(` deltaApplied: ${deltaApplied}`);
495
+ //DEBUG.push("");
496
+
497
+ const totalSize = nextLayout.reduce((total, size) => size + total, 0);
498
+ deltaApplied = 100 - totalSize;
499
+ //DEBUG.push(`total size: ${totalSize}`);
500
+ //DEBUG.push(` deltaApplied: ${deltaApplied}`);
501
+ //console.log(DEBUG.join("\n"));
502
+
503
+ if (!fuzzyNumbersEqual(totalSize, 100)) {
504
+ return prevLayout;
505
+ }
438
506
  return nextLayout;
439
507
  }
440
508
 
@@ -998,6 +1066,7 @@ function PanelGroupWithForwardedRef({
998
1066
  autoSaveId,
999
1067
  children,
1000
1068
  className: classNameFromProps = "",
1069
+ dataAttributes,
1001
1070
  direction,
1002
1071
  forwardedRef,
1003
1072
  id: idFromProps,
@@ -1432,6 +1501,7 @@ function PanelGroupWithForwardedRef({
1432
1501
  ...style,
1433
1502
  ...styleFromProps
1434
1503
  },
1504
+ ...dataAttributes,
1435
1505
  // CSS selectors
1436
1506
  "data-panel-group": "",
1437
1507
  "data-panel-group-direction": direction,
@@ -1519,6 +1589,7 @@ function useWindowSplitterResizeHandlerBehavior({
1519
1589
  function PanelResizeHandle({
1520
1590
  children = null,
1521
1591
  className: classNameFromProps = "",
1592
+ dataAttributes,
1522
1593
  disabled = false,
1523
1594
  id: idFromProps = null,
1524
1595
  onDragging,
@@ -1641,6 +1712,7 @@ function PanelResizeHandle({
1641
1712
  ...styleFromProps
1642
1713
  },
1643
1714
  tabIndex: 0,
1715
+ ...dataAttributes,
1644
1716
  // CSS selectors
1645
1717
  "data-panel-group-direction": direction,
1646
1718
  "data-panel-group-id": groupId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-resizable-panels",
3
- "version": "0.0.57",
3
+ "version": "0.0.58",
4
4
  "description": "React components for resizable panel groups/layouts",
5
5
  "author": "Brian Vaughn <brian.david.vaughn@gmail.com>",
6
6
  "license": "MIT",
package/src/Panel.ts CHANGED
@@ -3,7 +3,7 @@ import { isDevelopment } from "#is-development";
3
3
  import { PanelGroupContext } from "./PanelGroupContext";
4
4
  import useIsomorphicLayoutEffect from "./hooks/useIsomorphicEffect";
5
5
  import useUniqueId from "./hooks/useUniqueId";
6
- import { MixedSizes } from "./types";
6
+ import { DataAttributes, MixedSizes } from "./types";
7
7
  import {
8
8
  ElementType,
9
9
  ForwardedRef,
@@ -19,7 +19,7 @@ export type PanelOnCollapse = () => void;
19
19
  export type PanelOnExpand = () => void;
20
20
  export type PanelOnResize = (
21
21
  mixedSizes: MixedSizes,
22
- prevMixedSizes: MixedSizes
22
+ prevMixedSizes: MixedSizes | undefined
23
23
  ) => void;
24
24
 
25
25
  export type PanelCallbacks = {
@@ -53,6 +53,8 @@ export type ImperativePanelHandle = {
53
53
  expand: () => void;
54
54
  getId(): string;
55
55
  getSize(): MixedSizes;
56
+ isCollapsed: () => boolean;
57
+ isExpanded: () => boolean;
56
58
  resize: (size: Partial<MixedSizes>) => void;
57
59
  };
58
60
 
@@ -61,6 +63,7 @@ export type PanelProps = PropsWithChildren<{
61
63
  collapsedSizePercentage?: number | undefined;
62
64
  collapsedSizePixels?: number | undefined;
63
65
  collapsible?: boolean | undefined;
66
+ dataAttributes?: DataAttributes;
64
67
  defaultSizePercentage?: number | undefined;
65
68
  defaultSizePixels?: number | undefined;
66
69
  id?: string;
@@ -82,6 +85,7 @@ export function PanelWithForwardedRef({
82
85
  collapsedSizePercentage,
83
86
  collapsedSizePixels,
84
87
  collapsible,
88
+ dataAttributes,
85
89
  defaultSizePercentage,
86
90
  defaultSizePixels,
87
91
  forwardedRef,
@@ -241,6 +245,8 @@ export function PanelWithForwardedRef({
241
245
  ...styleFromProps,
242
246
  },
243
247
 
248
+ ...dataAttributes,
249
+
244
250
  // CSS selectors
245
251
  "data-panel": "",
246
252
  "data-panel-id": panelId,
package/src/PanelGroup.ts CHANGED
@@ -4,7 +4,7 @@ import { DragState, PanelGroupContext, ResizeEvent } from "./PanelGroupContext";
4
4
  import useIsomorphicLayoutEffect from "./hooks/useIsomorphicEffect";
5
5
  import useUniqueId from "./hooks/useUniqueId";
6
6
  import { useWindowSplitterPanelGroupBehavior } from "./hooks/useWindowSplitterPanelGroupBehavior";
7
- import { Direction, MixedSizes } from "./types";
7
+ import { DataAttributes, Direction, MixedSizes } from "./types";
8
8
  import { adjustLayoutByDelta } from "./utils/adjustLayoutByDelta";
9
9
  import { areEqual } from "./utils/arrays";
10
10
  import { calculateDeltaPercentage } from "./utils/calculateDeltaPercentage";
@@ -72,6 +72,7 @@ const defaultStorage: PanelGroupStorage = {
72
72
  export type PanelGroupProps = PropsWithChildren<{
73
73
  autoSaveId?: string;
74
74
  className?: string;
75
+ dataAttributes?: DataAttributes;
75
76
  direction: Direction;
76
77
  id?: string | null;
77
78
  keyboardResizeByPercentage?: number | null;
@@ -90,6 +91,7 @@ function PanelGroupWithForwardedRef({
90
91
  autoSaveId,
91
92
  children,
92
93
  className: classNameFromProps = "",
94
+ dataAttributes,
93
95
  direction,
94
96
  forwardedRef,
95
97
  id: idFromProps,
@@ -927,6 +929,8 @@ function PanelGroupWithForwardedRef({
927
929
  ...styleFromProps,
928
930
  },
929
931
 
932
+ ...dataAttributes,
933
+
930
934
  // CSS selectors
931
935
  "data-panel-group": "",
932
936
  "data-panel-group-direction": direction,