react-resizable-panels 2.0.9 → 2.0.11

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 (34) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/declarations/src/utils/assert.d.ts +1 -1
  3. package/dist/react-resizable-panels.browser.cjs.js +55 -57
  4. package/dist/react-resizable-panels.browser.development.cjs.js +57 -59
  5. package/dist/react-resizable-panels.browser.development.esm.js +57 -59
  6. package/dist/react-resizable-panels.browser.esm.js +55 -57
  7. package/dist/react-resizable-panels.cjs.js +55 -57
  8. package/dist/react-resizable-panels.development.cjs.js +57 -59
  9. package/dist/react-resizable-panels.development.esm.js +57 -59
  10. package/dist/react-resizable-panels.development.node.cjs.js +53 -55
  11. package/dist/react-resizable-panels.development.node.esm.js +53 -55
  12. package/dist/react-resizable-panels.esm.js +55 -57
  13. package/dist/react-resizable-panels.node.cjs.js +51 -53
  14. package/dist/react-resizable-panels.node.esm.js +51 -53
  15. package/package.json +1 -1
  16. package/src/Panel.test.tsx +23 -23
  17. package/src/PanelGroup.test.tsx +32 -3
  18. package/src/PanelGroup.ts +25 -7
  19. package/src/PanelResizeHandle.test.tsx +3 -3
  20. package/src/PanelResizeHandle.ts +1 -1
  21. package/src/hooks/useWindowSplitterBehavior.ts +5 -2
  22. package/src/hooks/useWindowSplitterPanelGroupBehavior.ts +5 -5
  23. package/src/utils/adjustLayoutByDelta.ts +47 -20
  24. package/src/utils/assert.ts +1 -1
  25. package/src/utils/calculateAriaValues.ts +1 -1
  26. package/src/utils/calculateDragOffsetPercentage.ts +6 -3
  27. package/src/utils/calculateUnsafeDefaultLayout.ts +2 -2
  28. package/src/utils/callPanelCallbacks.ts +1 -1
  29. package/src/utils/events/getResizeEventCoordinates.ts +5 -5
  30. package/src/utils/resizePanel.ts +4 -1
  31. package/src/utils/test-utils.ts +1 -1
  32. package/src/utils/validatePanelConstraints.ts +4 -1
  33. package/src/utils/validatePanelGroupLayout.ts +3 -3
  34. package/src/vendor/stacking-order.ts +5 -2
@@ -211,15 +211,15 @@ function isTouchEvent(event) {
211
211
  function getResizeEventCoordinates(event) {
212
212
  if (isMouseEvent(event)) {
213
213
  return {
214
- x: event.pageX,
215
- y: event.pageY
214
+ x: event.clientX,
215
+ y: event.clientY
216
216
  };
217
217
  } else if (isTouchEvent(event)) {
218
218
  const touch = event.touches[0];
219
- if (touch && touch.pageX && touch.pageY) {
219
+ if (touch && touch.clientX && touch.clientY) {
220
220
  return {
221
- x: touch.pageX,
222
- y: touch.pageY
221
+ x: touch.clientX,
222
+ y: touch.clientY
223
223
  };
224
224
  }
225
225
  }
@@ -265,7 +265,7 @@ function compare(a, b) {
265
265
  b = ancestors.b.pop();
266
266
  common_ancestor = a;
267
267
  }
268
- assert(common_ancestor);
268
+ assert(common_ancestor, "Stacking order can only be calculated for elements with a common ancestor");
269
269
  const z_indexes = {
270
270
  a: get_z_index(find_stacking_context(ancestors.a)),
271
271
  b: get_z_index(find_stacking_context(ancestors.b))
@@ -323,7 +323,7 @@ function find_stacking_context(nodes) {
323
323
  let i = nodes.length;
324
324
  while (i--) {
325
325
  const node = nodes[i];
326
- assert(node);
326
+ assert(node, "Missing node");
327
327
  if (creates_stacking_context(node)) return node;
328
328
  }
329
329
  return null;
@@ -610,7 +610,7 @@ function updateResizeHandlerStates(action, event) {
610
610
  });
611
611
  }
612
612
 
613
- function assert(expectedCondition, message = "Assertion failed!") {
613
+ function assert(expectedCondition, message) {
614
614
  if (!expectedCondition) {
615
615
  console.error(message);
616
616
  throw Error(message);
@@ -641,7 +641,7 @@ function resizePanel({
641
641
  size
642
642
  }) {
643
643
  const panelConstraints = panelConstraintsArray[panelIndex];
644
- assert(panelConstraints != null);
644
+ assert(panelConstraints != null, `Panel constraints not found for index ${panelIndex}`);
645
645
  let {
646
646
  collapsedSize = 0,
647
647
  collapsible,
@@ -679,8 +679,8 @@ function adjustLayoutByDelta({
679
679
  }
680
680
  const nextLayout = [...prevLayout];
681
681
  const [firstPivotIndex, secondPivotIndex] = pivotIndices;
682
- assert(firstPivotIndex != null);
683
- assert(secondPivotIndex != null);
682
+ assert(firstPivotIndex != null, "Invalid first pivot index");
683
+ assert(secondPivotIndex != null, "Invalid second pivot index");
684
684
  let deltaApplied = 0;
685
685
 
686
686
  //const DEBUG = [];
@@ -706,19 +706,18 @@ function adjustLayoutByDelta({
706
706
  // Check if we should expand a collapsed panel
707
707
  const index = delta < 0 ? secondPivotIndex : firstPivotIndex;
708
708
  const panelConstraints = panelConstraintsArray[index];
709
- assert(panelConstraints);
709
+ assert(panelConstraints, `Panel constraints not found for index ${index}`);
710
+ const {
711
+ collapsedSize = 0,
712
+ collapsible,
713
+ minSize = 0
714
+ } = panelConstraints;
710
715
 
711
716
  //DEBUG.push(`edge case check 1: ${index}`);
712
717
  //DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
713
- if (panelConstraints.collapsible) {
718
+ if (collapsible) {
714
719
  const prevSize = prevLayout[index];
715
- assert(prevSize != null);
716
- const panelConstraints = panelConstraintsArray[index];
717
- assert(panelConstraints);
718
- const {
719
- collapsedSize = 0,
720
- minSize = 0
721
- } = panelConstraints;
720
+ assert(prevSize != null, `Previous layout not found for panel index ${index}`);
722
721
  if (fuzzyNumbersEqual(prevSize, collapsedSize)) {
723
722
  const localDelta = minSize - prevSize;
724
723
  //DEBUG.push(` -> expand delta: ${localDelta}`);
@@ -735,22 +734,18 @@ function adjustLayoutByDelta({
735
734
  // Check if we should collapse a panel at its minimum size
736
735
  const index = delta < 0 ? firstPivotIndex : secondPivotIndex;
737
736
  const panelConstraints = panelConstraintsArray[index];
738
- assert(panelConstraints);
737
+ assert(panelConstraints, `No panel constraints found for index ${index}`);
739
738
  const {
740
- collapsible
739
+ collapsedSize = 0,
740
+ collapsible,
741
+ minSize = 0
741
742
  } = panelConstraints;
742
743
 
743
744
  //DEBUG.push(`edge case check 2: ${index}`);
744
745
  //DEBUG.push(` -> collapsible? ${collapsible}`);
745
746
  if (collapsible) {
746
747
  const prevSize = prevLayout[index];
747
- assert(prevSize != null);
748
- const panelConstraints = panelConstraintsArray[index];
749
- assert(panelConstraints);
750
- const {
751
- collapsedSize = 0,
752
- minSize = 0
753
- } = panelConstraints;
748
+ assert(prevSize != null, `Previous layout not found for panel index ${index}`);
754
749
  if (fuzzyNumbersEqual(prevSize, minSize)) {
755
750
  const localDelta = prevSize - collapsedSize;
756
751
  //DEBUG.push(` -> expand delta: ${localDelta}`);
@@ -780,7 +775,7 @@ function adjustLayoutByDelta({
780
775
  //DEBUG.push("pre calc...");
781
776
  while (true) {
782
777
  const prevSize = prevLayout[index];
783
- assert(prevSize != null);
778
+ assert(prevSize != null, `Previous layout not found for panel index ${index}`);
784
779
  const maxSafeSize = resizePanel({
785
780
  panelConstraints: panelConstraintsArray,
786
781
  panelIndex: index,
@@ -811,7 +806,7 @@ function adjustLayoutByDelta({
811
806
  while (index >= 0 && index < panelConstraintsArray.length) {
812
807
  const deltaRemaining = Math.abs(delta) - Math.abs(deltaApplied);
813
808
  const prevSize = prevLayout[index];
814
- assert(prevSize != null);
809
+ assert(prevSize != null, `Previous layout not found for panel index ${index}`);
815
810
  const unsafeSize = prevSize - deltaRemaining;
816
811
  const safeSize = resizePanel({
817
812
  panelConstraints: panelConstraintsArray,
@@ -848,7 +843,7 @@ function adjustLayoutByDelta({
848
843
  // Now distribute the applied delta to the panels in the other direction
849
844
  const pivotIndex = delta < 0 ? secondPivotIndex : firstPivotIndex;
850
845
  const prevSize = prevLayout[pivotIndex];
851
- assert(prevSize != null);
846
+ assert(prevSize != null, `Previous layout not found for panel index ${pivotIndex}`);
852
847
  const unsafeSize = prevSize + deltaApplied;
853
848
  const safeSize = resizePanel({
854
849
  panelConstraints: panelConstraintsArray,
@@ -866,7 +861,7 @@ function adjustLayoutByDelta({
866
861
  let index = pivotIndex;
867
862
  while (index >= 0 && index < panelConstraintsArray.length) {
868
863
  const prevSize = nextLayout[index];
869
- assert(prevSize != null);
864
+ assert(prevSize != null, `Previous layout not found for panel index ${index}`);
870
865
  const unsafeSize = prevSize + deltaRemaining;
871
866
  const safeSize = resizePanel({
872
867
  panelConstraints: panelConstraintsArray,
@@ -969,17 +964,17 @@ function useWindowSplitterPanelGroupBehavior({
969
964
  return;
970
965
  }
971
966
  const eagerValues = eagerValuesRef.current;
972
- assert(eagerValues);
967
+ assert(eagerValues, `Eager values not found`);
973
968
  const {
974
969
  panelDataArray
975
970
  } = eagerValues;
976
971
  const groupElement = getPanelGroupElement(groupId, panelGroupElement);
977
972
  assert(groupElement != null, `No group found for id "${groupId}"`);
978
973
  const handles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
979
- assert(handles);
974
+ assert(handles, `No resize handles found for group id "${groupId}"`);
980
975
  const cleanupFunctions = handles.map(handle => {
981
976
  const handleId = handle.getAttribute("data-panel-resize-handle-id");
982
- assert(handleId);
977
+ assert(handleId, `Resize handle element has no handle id attribute`);
983
978
  const [idBefore, idAfter] = getResizeHandlePanelIds(groupId, handleId, panelDataArray, panelGroupElement);
984
979
  if (idBefore == null || idAfter == null) {
985
980
  return () => {};
@@ -995,7 +990,7 @@ function useWindowSplitterPanelGroupBehavior({
995
990
  const index = panelDataArray.findIndex(panelData => panelData.id === idBefore);
996
991
  if (index >= 0) {
997
992
  const panelData = panelDataArray[index];
998
- assert(panelData);
993
+ assert(panelData, `No panel data found for index ${index}`);
999
994
  const size = layout[index];
1000
995
  const {
1001
996
  collapsedSize = 0,
@@ -1054,15 +1049,15 @@ function getResizeEventCursorPosition(direction, event) {
1054
1049
  function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState, panelGroupElement) {
1055
1050
  const isHorizontal = direction === "horizontal";
1056
1051
  const handleElement = getResizeHandleElement(dragHandleId, panelGroupElement);
1057
- assert(handleElement);
1052
+ assert(handleElement, `No resize handle element found for id "${dragHandleId}"`);
1058
1053
  const groupId = handleElement.getAttribute("data-panel-group-id");
1059
- assert(groupId);
1054
+ assert(groupId, `Resize handle element has no group id attribute`);
1060
1055
  let {
1061
1056
  initialCursorPosition
1062
1057
  } = initialDragState;
1063
1058
  const cursorPosition = getResizeEventCursorPosition(direction, event);
1064
1059
  const groupElement = getPanelGroupElement(groupId, panelGroupElement);
1065
- assert(groupElement);
1060
+ assert(groupElement, `No group element found for id "${groupId}"`);
1066
1061
  const groupRect = groupElement.getBoundingClientRect();
1067
1062
  const groupSizeInPixels = isHorizontal ? groupRect.width : groupRect.height;
1068
1063
  const offsetPixels = cursorPosition - initialCursorPosition;
@@ -1116,7 +1111,7 @@ function calculateDeltaPercentage(event, dragHandleId, direction, initialDragSta
1116
1111
  function callPanelCallbacks(panelsArray, layout, panelIdToLastNotifiedSizeMap) {
1117
1112
  layout.forEach((size, index) => {
1118
1113
  const panelData = panelsArray[index];
1119
- assert(panelData);
1114
+ assert(panelData, `Panel data not found for index ${index}`);
1120
1115
  const {
1121
1116
  callbacks,
1122
1117
  constraints,
@@ -1300,7 +1295,7 @@ function validatePanelGroupLayout({
1300
1295
  } else if (!fuzzyNumbersEqual(nextLayoutTotalSize, 100)) {
1301
1296
  for (let index = 0; index < panelConstraints.length; index++) {
1302
1297
  const unsafeSize = nextLayout[index];
1303
- assert(unsafeSize != null);
1298
+ assert(unsafeSize != null, `No layout data found for index ${index}`);
1304
1299
  const safeSize = 100 / nextLayoutTotalSize * unsafeSize;
1305
1300
  nextLayout[index] = safeSize;
1306
1301
  }
@@ -1310,7 +1305,7 @@ function validatePanelGroupLayout({
1310
1305
  // First pass: Validate the proposed layout given each panel's constraints
1311
1306
  for (let index = 0; index < panelConstraints.length; index++) {
1312
1307
  const unsafeSize = nextLayout[index];
1313
- assert(unsafeSize != null);
1308
+ assert(unsafeSize != null, `No layout data found for index ${index}`);
1314
1309
  const safeSize = resizePanel({
1315
1310
  panelConstraints,
1316
1311
  panelIndex: index,
@@ -1327,7 +1322,7 @@ function validatePanelGroupLayout({
1327
1322
  if (!fuzzyNumbersEqual(remainingSize, 0)) {
1328
1323
  for (let index = 0; index < panelConstraints.length; index++) {
1329
1324
  const prevSize = nextLayout[index];
1330
- assert(prevSize != null);
1325
+ assert(prevSize != null, `No layout data found for index ${index}`);
1331
1326
  const unsafeSize = prevSize + remainingSize;
1332
1327
  const safeSize = resizePanel({
1333
1328
  panelConstraints,
@@ -1485,7 +1480,7 @@ function PanelGroupWithForwardedRef({
1485
1480
  panelSize,
1486
1481
  pivotIndices
1487
1482
  } = panelDataHelper(panelDataArray, panelData, prevLayout);
1488
- assert(panelSize != null);
1483
+ assert(panelSize != null, `Panel size not found for panel "${panelData.id}"`);
1489
1484
  if (panelSize !== collapsedSize) {
1490
1485
  // Store size before collapse;
1491
1486
  // This is the size that gets restored if the expand() API is used.
@@ -1562,7 +1557,7 @@ function PanelGroupWithForwardedRef({
1562
1557
  const {
1563
1558
  panelSize
1564
1559
  } = panelDataHelper(panelDataArray, panelData, layout);
1565
- assert(panelSize != null);
1560
+ assert(panelSize != null, `Panel size not found for panel "${panelData.id}"`);
1566
1561
  return panelSize;
1567
1562
  }, []);
1568
1563
 
@@ -1606,7 +1601,7 @@ function PanelGroupWithForwardedRef({
1606
1601
  collapsible,
1607
1602
  panelSize
1608
1603
  } = panelDataHelper(panelDataArray, panelData, layout);
1609
- assert(panelSize != null);
1604
+ assert(panelSize != null, `Panel size not found for panel "${panelData.id}"`);
1610
1605
  return !collapsible || panelSize > collapsedSize;
1611
1606
  }, []);
1612
1607
  const registerPanel = useCallback(panelData => {
@@ -1717,7 +1712,7 @@ function PanelGroupWithForwardedRef({
1717
1712
  panelSize,
1718
1713
  pivotIndices
1719
1714
  } = panelDataHelper(panelDataArray, panelData, prevLayout);
1720
- assert(panelSize != null);
1715
+ assert(panelSize != null, `Panel size not found for panel "${panelData.id}"`);
1721
1716
  const isLastPanel = findPanelDataIndex(panelDataArray, panelData) === panelDataArray.length - 1;
1722
1717
  const delta = isLastPanel ? panelSize - unsafePanelSize : unsafePanelSize - panelSize;
1723
1718
  const nextLayout = adjustLayoutByDelta({
@@ -1754,7 +1749,10 @@ function PanelGroupWithForwardedRef({
1754
1749
  const {
1755
1750
  panelSize: prevPanelSize
1756
1751
  } = panelDataHelper(panelDataArray, panelData, layout);
1757
- assert(prevPanelSize != null);
1752
+ if (prevPanelSize == null) {
1753
+ // It's possible that the panels in this group have changed since the last render
1754
+ return;
1755
+ }
1758
1756
  if (prevCollapsible && nextCollapsible && prevPanelSize === prevCollapsedSize) {
1759
1757
  if (prevCollapsedSize !== nextCollapsedSize) {
1760
1758
  resizePanel(panelData, nextCollapsedSize);
@@ -1776,7 +1774,7 @@ function PanelGroupWithForwardedRef({
1776
1774
  return;
1777
1775
  }
1778
1776
  const handleElement = getResizeHandleElement(dragHandleId, panelGroupElementRef.current);
1779
- assert(handleElement);
1777
+ assert(handleElement, `Drag handle element not found for id "${dragHandleId}"`);
1780
1778
  const initialCursorPosition = getResizeEventCursorPosition(direction, event);
1781
1779
  setDragState({
1782
1780
  dragHandleId,
@@ -1905,10 +1903,10 @@ function useWindowSplitterResizeHandlerBehavior({
1905
1903
  {
1906
1904
  event.preventDefault();
1907
1905
  const groupId = handleElement.getAttribute("data-panel-group-id");
1908
- assert(groupId);
1906
+ assert(groupId, `No group element found for id "${groupId}"`);
1909
1907
  const handles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
1910
1908
  const index = getResizeHandleElementIndex(groupId, handleId, panelGroupElement);
1911
- assert(index !== null);
1909
+ assert(index !== null, `No resize element found for id "${handleId}"`);
1912
1910
  const nextIndex = event.shiftKey ? index > 0 ? index - 1 : handles.length - 1 : index + 1 < handles.length ? index + 1 : 0;
1913
1911
  const nextHandle = handles[nextIndex];
1914
1912
  nextHandle.focus();
@@ -1977,7 +1975,7 @@ function PanelResizeHandle({
1977
1975
  return;
1978
1976
  }
1979
1977
  const element = elementRef.current;
1980
- assert(element);
1978
+ assert(element, "Element ref not attached");
1981
1979
  const setResizeHandlerState = (action, isActive, event) => {
1982
1980
  if (isActive) {
1983
1981
  switch (action) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-resizable-panels",
3
- "version": "2.0.9",
3
+ "version": "2.0.11",
4
4
  "description": "React components for resizable panel groups/layouts",
5
5
  "author": "Brian Vaughn <brian.david.vaughn@gmail.com>",
6
6
  "license": "MIT",
@@ -88,7 +88,7 @@ describe("PanelGroup", () => {
88
88
  });
89
89
 
90
90
  it("should expand and collapse the first panel in a group", () => {
91
- assert(mostRecentLayout);
91
+ assert(mostRecentLayout, "");
92
92
 
93
93
  verifyExpandedPanelGroupLayout(mostRecentLayout, [50, 50]);
94
94
  expect(leftPanelRef.current?.isCollapsed()).toBe(false);
@@ -108,7 +108,7 @@ describe("PanelGroup", () => {
108
108
  });
109
109
 
110
110
  it("should expand and collapse the last panel in a group", () => {
111
- assert(mostRecentLayout);
111
+ assert(mostRecentLayout, "");
112
112
 
113
113
  verifyExpandedPanelGroupLayout(mostRecentLayout, [50, 50]);
114
114
  expect(leftPanelRef.current?.isCollapsed()).toBe(false);
@@ -128,7 +128,7 @@ describe("PanelGroup", () => {
128
128
  });
129
129
 
130
130
  it("should re-expand to the most recent size before collapsing", () => {
131
- assert(mostRecentLayout);
131
+ assert(mostRecentLayout, "");
132
132
 
133
133
  verifyExpandedPanelGroupLayout(mostRecentLayout, [50, 50]);
134
134
  act(() => {
@@ -178,7 +178,7 @@ describe("PanelGroup", () => {
178
178
  });
179
179
 
180
180
  it("should resize the first panel in a group", () => {
181
- assert(mostRecentLayout);
181
+ assert(mostRecentLayout, "");
182
182
 
183
183
  verifyExpandedPanelGroupLayout(mostRecentLayout, [20, 60, 20]);
184
184
  act(() => {
@@ -188,7 +188,7 @@ describe("PanelGroup", () => {
188
188
  });
189
189
 
190
190
  it("should resize the middle panel in a group", () => {
191
- assert(mostRecentLayout);
191
+ assert(mostRecentLayout, "");
192
192
 
193
193
  verifyExpandedPanelGroupLayout(mostRecentLayout, [20, 60, 20]);
194
194
  act(() => {
@@ -198,7 +198,7 @@ describe("PanelGroup", () => {
198
198
  });
199
199
 
200
200
  it("should resize the last panel in a group", () => {
201
- assert(mostRecentLayout);
201
+ assert(mostRecentLayout, "");
202
202
 
203
203
  verifyExpandedPanelGroupLayout(mostRecentLayout, [20, 60, 20]);
204
204
  act(() => {
@@ -261,7 +261,7 @@ describe("PanelGroup", () => {
261
261
  });
262
262
 
263
263
  const element = getPanelElement("panel", container);
264
- assert(element);
264
+ assert(element, "");
265
265
  expect(element.tabIndex).toBe(123);
266
266
  expect(element.getAttribute("data-test-name")).toBe("foo");
267
267
  expect(element.title).toBe("bar");
@@ -296,9 +296,9 @@ describe("PanelGroup", () => {
296
296
  let leftElement = getPanelElement("left", container);
297
297
  let middleElement = getPanelElement("middle", container);
298
298
  let rightElement = getPanelElement("right", container);
299
- assert(leftElement);
300
- assert(middleElement);
301
- assert(rightElement);
299
+ assert(leftElement, "");
300
+ assert(middleElement, "");
301
+ assert(rightElement, "");
302
302
  expect(leftElement.getAttribute("data-panel-size")).toBe("10.0");
303
303
  expect(middleElement.getAttribute("data-panel-size")).toBe("80.0");
304
304
  expect(rightElement.getAttribute("data-panel-size")).toBe("10.0");
@@ -348,9 +348,9 @@ describe("PanelGroup", () => {
348
348
  let leftElement = getPanelElement("left", container);
349
349
  let middleElement = getPanelElement("middle", container);
350
350
  let rightElement = getPanelElement("right", container);
351
- assert(leftElement);
352
- assert(middleElement);
353
- assert(rightElement);
351
+ assert(leftElement, "");
352
+ assert(middleElement, "");
353
+ assert(rightElement, "");
354
354
  expect(leftElement.getAttribute("data-panel-size")).toBe("10.0");
355
355
  expect(middleElement.getAttribute("data-panel-size")).toBe("80.0");
356
356
  expect(rightElement.getAttribute("data-panel-size")).toBe("10.0");
@@ -388,9 +388,9 @@ describe("PanelGroup", () => {
388
388
  let leftElement = getPanelElement("left", container);
389
389
  let middleElement = getPanelElement("middle", container);
390
390
  let rightElement = getPanelElement("right", container);
391
- assert(leftElement);
392
- assert(middleElement);
393
- assert(rightElement);
391
+ assert(leftElement, "");
392
+ assert(middleElement, "");
393
+ assert(rightElement, "");
394
394
  expect(leftElement.getAttribute("data-panel-size")).toBe("15.0");
395
395
  expect(middleElement.getAttribute("data-panel-size")).toBe("70.0");
396
396
  expect(rightElement.getAttribute("data-panel-size")).toBe("15.0");
@@ -428,9 +428,9 @@ describe("PanelGroup", () => {
428
428
  let leftElement = getPanelElement("left", container);
429
429
  let middleElement = getPanelElement("middle", container);
430
430
  let rightElement = getPanelElement("right", container);
431
- assert(leftElement);
432
- assert(middleElement);
433
- assert(rightElement);
431
+ assert(leftElement, "");
432
+ assert(middleElement, "");
433
+ assert(rightElement, "");
434
434
  expect(leftElement.getAttribute("data-panel-size")).toBe("25.0");
435
435
  expect(middleElement.getAttribute("data-panel-size")).toBe("50.0");
436
436
  expect(rightElement.getAttribute("data-panel-size")).toBe("25.0");
@@ -691,8 +691,8 @@ describe("PanelGroup", () => {
691
691
  const leftElement = getPanelElement("left-panel", container);
692
692
  const rightElement = getPanelElement("right-panel", container);
693
693
 
694
- assert(leftElement);
695
- assert(rightElement);
694
+ assert(leftElement, "");
695
+ assert(rightElement, "");
696
696
 
697
697
  verifyAttribute(leftElement, "data-panel", "");
698
698
  verifyAttribute(leftElement, "data-panel-id", "left-panel");
@@ -723,8 +723,8 @@ describe("PanelGroup", () => {
723
723
  const leftElement = getPanelElement("left-panel", container);
724
724
  const rightElement = getPanelElement("right-panel", container);
725
725
 
726
- assert(leftElement);
727
- assert(rightElement);
726
+ assert(leftElement, "");
727
+ assert(rightElement, "");
728
728
 
729
729
  verifyAttribute(leftElement, "data-panel-size", "75.0");
730
730
  verifyAttribute(rightElement, "data-panel-size", "25.0");
@@ -1,6 +1,6 @@
1
1
  // @ts-expect-error This is an experimental API
2
2
  // eslint-disable-next-line no-restricted-imports
3
- import { unstable_Activity as Activity } from "react";
3
+ import { unstable_Activity as Activity, Fragment } from "react";
4
4
  import { Root, createRoot } from "react-dom/client";
5
5
  import { act } from "react-dom/test-utils";
6
6
  import {
@@ -130,6 +130,35 @@ describe("PanelGroup", () => {
130
130
  expect(rightPanelElement?.getAttribute("data-panel-size")).toBe("40.0");
131
131
  });
132
132
 
133
+ // github.com/bvaughn/react-resizable-panels/issues/303
134
+ it("should recalculate layout after panels are changed", () => {
135
+ let mostRecentLayout: number[] | null = null;
136
+
137
+ const onLayout = (layout: number[]) => {
138
+ mostRecentLayout = layout;
139
+ };
140
+
141
+ act(() => {
142
+ root.render(
143
+ <PanelGroup direction="vertical" onLayout={onLayout}>
144
+ <Panel id="foo" minSize={30} order={0} />
145
+ <PanelResizeHandle />
146
+ <Panel id="bar" minSize={70} order={1} />
147
+ </PanelGroup>
148
+ );
149
+ });
150
+ expect(mostRecentLayout).toEqual([30, 70]);
151
+
152
+ act(() => {
153
+ root.render(
154
+ <PanelGroup direction="vertical" onLayout={onLayout}>
155
+ <Panel id="bar" minSize={70} order={0} />
156
+ </PanelGroup>
157
+ );
158
+ });
159
+ expect(mostRecentLayout).toEqual([100]);
160
+ });
161
+
133
162
  describe("imperative handle API", () => {
134
163
  it("should report the most recently rendered group id", () => {
135
164
  const ref = createRef<ImperativePanelGroupHandle>();
@@ -194,7 +223,7 @@ describe("PanelGroup", () => {
194
223
  });
195
224
 
196
225
  const element = getPanelGroupElement("group", container);
197
- assert(element);
226
+ assert(element, "");
198
227
  expect(element.tabIndex).toBe(123);
199
228
  expect(element.getAttribute("data-test-name")).toBe("foo");
200
229
  expect(element.title).toBe("bar");
@@ -268,7 +297,7 @@ describe("PanelGroup", () => {
268
297
  });
269
298
 
270
299
  const element = getPanelGroupElement("test-group", container);
271
- assert(element);
300
+ assert(element, "");
272
301
 
273
302
  verifyAttribute(element, "data-panel-group", "");
274
303
  verifyAttribute(element, "data-panel-group-direction", "horizontal");
package/src/PanelGroup.ts CHANGED
@@ -302,7 +302,7 @@ function PanelGroupWithForwardedRef({
302
302
  panelIndex++
303
303
  ) {
304
304
  const panelData = panelDataArray[panelIndex];
305
- assert(panelData);
305
+ assert(panelData, `Panel data not found for index ${panelIndex}`);
306
306
 
307
307
  const isValid = validatePanelConstraints({
308
308
  panelConstraints,
@@ -336,7 +336,10 @@ function PanelGroupWithForwardedRef({
336
336
  pivotIndices,
337
337
  } = panelDataHelper(panelDataArray, panelData, prevLayout);
338
338
 
339
- assert(panelSize != null);
339
+ assert(
340
+ panelSize != null,
341
+ `Panel size not found for panel "${panelData.id}"`
342
+ );
340
343
 
341
344
  if (panelSize !== collapsedSize) {
342
345
  // Store size before collapse;
@@ -443,7 +446,10 @@ function PanelGroupWithForwardedRef({
443
446
 
444
447
  const { panelSize } = panelDataHelper(panelDataArray, panelData, layout);
445
448
 
446
- assert(panelSize != null);
449
+ assert(
450
+ panelSize != null,
451
+ `Panel size not found for panel "${panelData.id}"`
452
+ );
447
453
 
448
454
  return panelSize;
449
455
  }, []);
@@ -489,7 +495,10 @@ function PanelGroupWithForwardedRef({
489
495
  panelSize,
490
496
  } = panelDataHelper(panelDataArray, panelData, layout);
491
497
 
492
- assert(panelSize != null);
498
+ assert(
499
+ panelSize != null,
500
+ `Panel size not found for panel "${panelData.id}"`
501
+ );
493
502
 
494
503
  return !collapsible || panelSize > collapsedSize;
495
504
  }, []);
@@ -699,7 +708,10 @@ function PanelGroupWithForwardedRef({
699
708
  prevLayout
700
709
  );
701
710
 
702
- assert(panelSize != null);
711
+ assert(
712
+ panelSize != null,
713
+ `Panel size not found for panel "${panelData.id}"`
714
+ );
703
715
 
704
716
  const isLastPanel =
705
717
  findPanelDataIndex(panelDataArray, panelData) ===
@@ -756,7 +768,10 @@ function PanelGroupWithForwardedRef({
756
768
  panelData,
757
769
  layout
758
770
  );
759
- assert(prevPanelSize != null);
771
+ if (prevPanelSize == null) {
772
+ // It's possible that the panels in this group have changed since the last render
773
+ return;
774
+ }
760
775
 
761
776
  if (
762
777
  prevCollapsible &&
@@ -788,7 +803,10 @@ function PanelGroupWithForwardedRef({
788
803
  dragHandleId,
789
804
  panelGroupElementRef.current
790
805
  );
791
- assert(handleElement);
806
+ assert(
807
+ handleElement,
808
+ `Drag handle element not found for id "${dragHandleId}"`
809
+ );
792
810
 
793
811
  const initialCursorPosition = getResizeEventCursorPosition(
794
812
  direction,
@@ -66,7 +66,7 @@ describe("PanelResizeHandle", () => {
66
66
  });
67
67
 
68
68
  const element = getResizeHandleElement("handle", container);
69
- assert(element);
69
+ assert(element, "");
70
70
  expect(element.tabIndex).toBe(123);
71
71
  expect(element.getAttribute("data-test-name")).toBe("foo");
72
72
  expect(element.title).toBe("bar");
@@ -94,8 +94,8 @@ describe("PanelResizeHandle", () => {
94
94
  const leftElement = getResizeHandleElement("handle-left", container);
95
95
  const rightElement = getResizeHandleElement("handle-right", container);
96
96
 
97
- assert(leftElement);
98
- assert(rightElement);
97
+ assert(leftElement, "");
98
+ assert(rightElement, "");
99
99
 
100
100
  // JSDom doesn't properly handle bounding rects
101
101
  mockBoundingClientRect(leftElement, {
@@ -116,7 +116,7 @@ export function PanelResizeHandle({
116
116
  }
117
117
 
118
118
  const element = elementRef.current;
119
- assert(element);
119
+ assert(element, "Element ref not attached");
120
120
 
121
121
  const setResizeHandlerState = (
122
122
  action: ResizeHandlerAction,
@@ -49,7 +49,7 @@ export function useWindowSplitterResizeHandlerBehavior({
49
49
  event.preventDefault();
50
50
 
51
51
  const groupId = handleElement.getAttribute("data-panel-group-id");
52
- assert(groupId);
52
+ assert(groupId, `No group element found for id "${groupId}"`);
53
53
 
54
54
  const handles = getResizeHandleElementsForGroup(
55
55
  groupId,
@@ -61,7 +61,10 @@ export function useWindowSplitterResizeHandlerBehavior({
61
61
  panelGroupElement
62
62
  );
63
63
 
64
- assert(index !== null);
64
+ assert(
65
+ index !== null,
66
+ `No resize element found for id "${handleId}"`
67
+ );
65
68
 
66
69
  const nextIndex = event.shiftKey
67
70
  ? index > 0