react-resizable-panels 2.0.9 → 2.0.10

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 (33) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/declarations/src/utils/assert.d.ts +1 -1
  3. package/dist/react-resizable-panels.browser.cjs.js +50 -52
  4. package/dist/react-resizable-panels.browser.development.cjs.js +52 -54
  5. package/dist/react-resizable-panels.browser.development.esm.js +52 -54
  6. package/dist/react-resizable-panels.browser.esm.js +50 -52
  7. package/dist/react-resizable-panels.cjs.js +50 -52
  8. package/dist/react-resizable-panels.development.cjs.js +52 -54
  9. package/dist/react-resizable-panels.development.esm.js +52 -54
  10. package/dist/react-resizable-panels.development.node.cjs.js +48 -50
  11. package/dist/react-resizable-panels.development.node.esm.js +48 -50
  12. package/dist/react-resizable-panels.esm.js +50 -52
  13. package/dist/react-resizable-panels.node.cjs.js +46 -48
  14. package/dist/react-resizable-panels.node.esm.js +46 -48
  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/resizePanel.ts +4 -1
  30. package/src/utils/test-utils.ts +1 -1
  31. package/src/utils/validatePanelConstraints.ts +4 -1
  32. package/src/utils/validatePanelGroupLayout.ts +3 -3
  33. package/src/vendor/stacking-order.ts +5 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.10
4
+
5
+ - Fix conditional layout edge case (#309)
6
+
3
7
  ## 2.0.9
4
8
 
5
9
  - Fix Flex stacking context bug (#301)
@@ -1 +1 @@
1
- export declare function assert(expectedCondition: any, message?: string): asserts expectedCondition;
1
+ export declare function assert(expectedCondition: any, message: string): asserts expectedCondition;
@@ -325,7 +325,7 @@ function compare(a, b) {
325
325
  b = ancestors.b.pop();
326
326
  common_ancestor = a;
327
327
  }
328
- assert(common_ancestor);
328
+ assert(common_ancestor, "Stacking order can only be calculated for elements with a common ancestor");
329
329
  const z_indexes = {
330
330
  a: get_z_index(find_stacking_context(ancestors.a)),
331
331
  b: get_z_index(find_stacking_context(ancestors.b))
@@ -383,7 +383,7 @@ function find_stacking_context(nodes) {
383
383
  let i = nodes.length;
384
384
  while (i--) {
385
385
  const node = nodes[i];
386
- assert(node);
386
+ assert(node, "Missing node");
387
387
  if (creates_stacking_context(node)) return node;
388
388
  }
389
389
  return null;
@@ -670,7 +670,7 @@ function updateResizeHandlerStates(action, event) {
670
670
  });
671
671
  }
672
672
 
673
- function assert(expectedCondition, message = "Assertion failed!") {
673
+ function assert(expectedCondition, message) {
674
674
  if (!expectedCondition) {
675
675
  console.error(message);
676
676
  throw Error(message);
@@ -701,7 +701,7 @@ function resizePanel({
701
701
  size
702
702
  }) {
703
703
  const panelConstraints = panelConstraintsArray[panelIndex];
704
- assert(panelConstraints != null);
704
+ assert(panelConstraints != null, `Panel constraints not found for index ${panelIndex}`);
705
705
  let {
706
706
  collapsedSize = 0,
707
707
  collapsible,
@@ -739,8 +739,8 @@ function adjustLayoutByDelta({
739
739
  }
740
740
  const nextLayout = [...prevLayout];
741
741
  const [firstPivotIndex, secondPivotIndex] = pivotIndices;
742
- assert(firstPivotIndex != null);
743
- assert(secondPivotIndex != null);
742
+ assert(firstPivotIndex != null, "Invalid first pivot index");
743
+ assert(secondPivotIndex != null, "Invalid second pivot index");
744
744
  let deltaApplied = 0;
745
745
 
746
746
  //const DEBUG = [];
@@ -766,19 +766,18 @@ function adjustLayoutByDelta({
766
766
  // Check if we should expand a collapsed panel
767
767
  const index = delta < 0 ? secondPivotIndex : firstPivotIndex;
768
768
  const panelConstraints = panelConstraintsArray[index];
769
- assert(panelConstraints);
769
+ assert(panelConstraints, `Panel constraints not found for index ${index}`);
770
+ const {
771
+ collapsedSize = 0,
772
+ collapsible,
773
+ minSize = 0
774
+ } = panelConstraints;
770
775
 
771
776
  //DEBUG.push(`edge case check 1: ${index}`);
772
777
  //DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
773
- if (panelConstraints.collapsible) {
778
+ if (collapsible) {
774
779
  const prevSize = prevLayout[index];
775
- assert(prevSize != null);
776
- const panelConstraints = panelConstraintsArray[index];
777
- assert(panelConstraints);
778
- const {
779
- collapsedSize = 0,
780
- minSize = 0
781
- } = panelConstraints;
780
+ assert(prevSize != null, `Previous layout not found for panel index ${index}`);
782
781
  if (fuzzyNumbersEqual(prevSize, collapsedSize)) {
783
782
  const localDelta = minSize - prevSize;
784
783
  //DEBUG.push(` -> expand delta: ${localDelta}`);
@@ -795,22 +794,18 @@ function adjustLayoutByDelta({
795
794
  // Check if we should collapse a panel at its minimum size
796
795
  const index = delta < 0 ? firstPivotIndex : secondPivotIndex;
797
796
  const panelConstraints = panelConstraintsArray[index];
798
- assert(panelConstraints);
797
+ assert(panelConstraints, `No panel constraints found for index ${index}`);
799
798
  const {
800
- collapsible
799
+ collapsedSize = 0,
800
+ collapsible,
801
+ minSize = 0
801
802
  } = panelConstraints;
802
803
 
803
804
  //DEBUG.push(`edge case check 2: ${index}`);
804
805
  //DEBUG.push(` -> collapsible? ${collapsible}`);
805
806
  if (collapsible) {
806
807
  const prevSize = prevLayout[index];
807
- assert(prevSize != null);
808
- const panelConstraints = panelConstraintsArray[index];
809
- assert(panelConstraints);
810
- const {
811
- collapsedSize = 0,
812
- minSize = 0
813
- } = panelConstraints;
808
+ assert(prevSize != null, `Previous layout not found for panel index ${index}`);
814
809
  if (fuzzyNumbersEqual(prevSize, minSize)) {
815
810
  const localDelta = prevSize - collapsedSize;
816
811
  //DEBUG.push(` -> expand delta: ${localDelta}`);
@@ -840,7 +835,7 @@ function adjustLayoutByDelta({
840
835
  //DEBUG.push("pre calc...");
841
836
  while (true) {
842
837
  const prevSize = prevLayout[index];
843
- assert(prevSize != null);
838
+ assert(prevSize != null, `Previous layout not found for panel index ${index}`);
844
839
  const maxSafeSize = resizePanel({
845
840
  panelConstraints: panelConstraintsArray,
846
841
  panelIndex: index,
@@ -871,7 +866,7 @@ function adjustLayoutByDelta({
871
866
  while (index >= 0 && index < panelConstraintsArray.length) {
872
867
  const deltaRemaining = Math.abs(delta) - Math.abs(deltaApplied);
873
868
  const prevSize = prevLayout[index];
874
- assert(prevSize != null);
869
+ assert(prevSize != null, `Previous layout not found for panel index ${index}`);
875
870
  const unsafeSize = prevSize - deltaRemaining;
876
871
  const safeSize = resizePanel({
877
872
  panelConstraints: panelConstraintsArray,
@@ -908,7 +903,7 @@ function adjustLayoutByDelta({
908
903
  // Now distribute the applied delta to the panels in the other direction
909
904
  const pivotIndex = delta < 0 ? secondPivotIndex : firstPivotIndex;
910
905
  const prevSize = prevLayout[pivotIndex];
911
- assert(prevSize != null);
906
+ assert(prevSize != null, `Previous layout not found for panel index ${pivotIndex}`);
912
907
  const unsafeSize = prevSize + deltaApplied;
913
908
  const safeSize = resizePanel({
914
909
  panelConstraints: panelConstraintsArray,
@@ -926,7 +921,7 @@ function adjustLayoutByDelta({
926
921
  let index = pivotIndex;
927
922
  while (index >= 0 && index < panelConstraintsArray.length) {
928
923
  const prevSize = nextLayout[index];
929
- assert(prevSize != null);
924
+ assert(prevSize != null, `Previous layout not found for panel index ${index}`);
930
925
  const unsafeSize = prevSize + deltaRemaining;
931
926
  const safeSize = resizePanel({
932
927
  panelConstraints: panelConstraintsArray,
@@ -972,7 +967,7 @@ function calculateAriaValues({
972
967
  let totalMinSize = 0;
973
968
  let totalMaxSize = 0;
974
969
  const firstIndex = pivotIndices[0];
975
- assert(firstIndex != null);
970
+ assert(firstIndex != null, "No pivot index found");
976
971
 
977
972
  // A panel's effective min/max sizes also need to account for other panel's sizes.
978
973
  panelsArray.forEach((panelData, index) => {
@@ -1081,7 +1076,7 @@ function useWindowSplitterPanelGroupBehavior({
1081
1076
  const resizeHandleElement = resizeHandleElements[index];
1082
1077
  if (resizeHandleElement == null) ; else {
1083
1078
  const panelData = panelDataArray[index];
1084
- assert(panelData);
1079
+ assert(panelData, `No panel data found for index "${index}"`);
1085
1080
  resizeHandleElement.setAttribute("aria-controls", panelData.id);
1086
1081
  resizeHandleElement.setAttribute("aria-valuemax", "" + Math.round(valueMax));
1087
1082
  resizeHandleElement.setAttribute("aria-valuemin", "" + Math.round(valueMin));
@@ -1102,17 +1097,17 @@ function useWindowSplitterPanelGroupBehavior({
1102
1097
  return;
1103
1098
  }
1104
1099
  const eagerValues = eagerValuesRef.current;
1105
- assert(eagerValues);
1100
+ assert(eagerValues, `Eager values not found`);
1106
1101
  const {
1107
1102
  panelDataArray
1108
1103
  } = eagerValues;
1109
1104
  const groupElement = getPanelGroupElement(groupId, panelGroupElement);
1110
1105
  assert(groupElement != null, `No group found for id "${groupId}"`);
1111
1106
  const handles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
1112
- assert(handles);
1107
+ assert(handles, `No resize handles found for group id "${groupId}"`);
1113
1108
  const cleanupFunctions = handles.map(handle => {
1114
1109
  const handleId = handle.getAttribute("data-panel-resize-handle-id");
1115
- assert(handleId);
1110
+ assert(handleId, `Resize handle element has no handle id attribute`);
1116
1111
  const [idBefore, idAfter] = getResizeHandlePanelIds(groupId, handleId, panelDataArray, panelGroupElement);
1117
1112
  if (idBefore == null || idAfter == null) {
1118
1113
  return () => {};
@@ -1128,7 +1123,7 @@ function useWindowSplitterPanelGroupBehavior({
1128
1123
  const index = panelDataArray.findIndex(panelData => panelData.id === idBefore);
1129
1124
  if (index >= 0) {
1130
1125
  const panelData = panelDataArray[index];
1131
- assert(panelData);
1126
+ assert(panelData, `No panel data found for index ${index}`);
1132
1127
  const size = layout[index];
1133
1128
  const {
1134
1129
  collapsedSize = 0,
@@ -1187,15 +1182,15 @@ function getResizeEventCursorPosition(direction, event) {
1187
1182
  function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState, panelGroupElement) {
1188
1183
  const isHorizontal = direction === "horizontal";
1189
1184
  const handleElement = getResizeHandleElement(dragHandleId, panelGroupElement);
1190
- assert(handleElement);
1185
+ assert(handleElement, `No resize handle element found for id "${dragHandleId}"`);
1191
1186
  const groupId = handleElement.getAttribute("data-panel-group-id");
1192
- assert(groupId);
1187
+ assert(groupId, `Resize handle element has no group id attribute`);
1193
1188
  let {
1194
1189
  initialCursorPosition
1195
1190
  } = initialDragState;
1196
1191
  const cursorPosition = getResizeEventCursorPosition(direction, event);
1197
1192
  const groupElement = getPanelGroupElement(groupId, panelGroupElement);
1198
- assert(groupElement);
1193
+ assert(groupElement, `No group element found for id "${groupId}"`);
1199
1194
  const groupRect = groupElement.getBoundingClientRect();
1200
1195
  const groupSizeInPixels = isHorizontal ? groupRect.width : groupRect.height;
1201
1196
  const offsetPixels = cursorPosition - initialCursorPosition;
@@ -1256,7 +1251,7 @@ function calculateUnsafeDefaultLayout({
1256
1251
  // Distribute default sizes first
1257
1252
  for (let index = 0; index < panelDataArray.length; index++) {
1258
1253
  const panelConstraints = panelConstraintsArray[index];
1259
- assert(panelConstraints);
1254
+ assert(panelConstraints, `Panel constraints not found for index ${index}`);
1260
1255
  const {
1261
1256
  defaultSize
1262
1257
  } = panelConstraints;
@@ -1270,7 +1265,7 @@ function calculateUnsafeDefaultLayout({
1270
1265
  // Remaining size should be distributed evenly between panels without default sizes
1271
1266
  for (let index = 0; index < panelDataArray.length; index++) {
1272
1267
  const panelConstraints = panelConstraintsArray[index];
1273
- assert(panelConstraints);
1268
+ assert(panelConstraints, `Panel constraints not found for index ${index}`);
1274
1269
  const {
1275
1270
  defaultSize
1276
1271
  } = panelConstraints;
@@ -1290,7 +1285,7 @@ function calculateUnsafeDefaultLayout({
1290
1285
  function callPanelCallbacks(panelsArray, layout, panelIdToLastNotifiedSizeMap) {
1291
1286
  layout.forEach((size, index) => {
1292
1287
  const panelData = panelsArray[index];
1293
- assert(panelData);
1288
+ assert(panelData, `Panel data not found for index ${index}`);
1294
1289
  const {
1295
1290
  callbacks,
1296
1291
  constraints,
@@ -1480,7 +1475,7 @@ function validatePanelGroupLayout({
1480
1475
  } else if (!fuzzyNumbersEqual(nextLayoutTotalSize, 100)) {
1481
1476
  for (let index = 0; index < panelConstraints.length; index++) {
1482
1477
  const unsafeSize = nextLayout[index];
1483
- assert(unsafeSize != null);
1478
+ assert(unsafeSize != null, `No layout data found for index ${index}`);
1484
1479
  const safeSize = 100 / nextLayoutTotalSize * unsafeSize;
1485
1480
  nextLayout[index] = safeSize;
1486
1481
  }
@@ -1490,7 +1485,7 @@ function validatePanelGroupLayout({
1490
1485
  // First pass: Validate the proposed layout given each panel's constraints
1491
1486
  for (let index = 0; index < panelConstraints.length; index++) {
1492
1487
  const unsafeSize = nextLayout[index];
1493
- assert(unsafeSize != null);
1488
+ assert(unsafeSize != null, `No layout data found for index ${index}`);
1494
1489
  const safeSize = resizePanel({
1495
1490
  panelConstraints,
1496
1491
  panelIndex: index,
@@ -1507,7 +1502,7 @@ function validatePanelGroupLayout({
1507
1502
  if (!fuzzyNumbersEqual(remainingSize, 0)) {
1508
1503
  for (let index = 0; index < panelConstraints.length; index++) {
1509
1504
  const prevSize = nextLayout[index];
1510
- assert(prevSize != null);
1505
+ assert(prevSize != null, `No layout data found for index ${index}`);
1511
1506
  const unsafeSize = prevSize + remainingSize;
1512
1507
  const safeSize = resizePanel({
1513
1508
  panelConstraints,
@@ -1673,7 +1668,7 @@ function PanelGroupWithForwardedRef({
1673
1668
  panelSize,
1674
1669
  pivotIndices
1675
1670
  } = panelDataHelper(panelDataArray, panelData, prevLayout);
1676
- assert(panelSize != null);
1671
+ assert(panelSize != null, `Panel size not found for panel "${panelData.id}"`);
1677
1672
  if (panelSize !== collapsedSize) {
1678
1673
  // Store size before collapse;
1679
1674
  // This is the size that gets restored if the expand() API is used.
@@ -1750,7 +1745,7 @@ function PanelGroupWithForwardedRef({
1750
1745
  const {
1751
1746
  panelSize
1752
1747
  } = panelDataHelper(panelDataArray, panelData, layout);
1753
- assert(panelSize != null);
1748
+ assert(panelSize != null, `Panel size not found for panel "${panelData.id}"`);
1754
1749
  return panelSize;
1755
1750
  }, []);
1756
1751
 
@@ -1794,7 +1789,7 @@ function PanelGroupWithForwardedRef({
1794
1789
  collapsible,
1795
1790
  panelSize
1796
1791
  } = panelDataHelper(panelDataArray, panelData, layout);
1797
- assert(panelSize != null);
1792
+ assert(panelSize != null, `Panel size not found for panel "${panelData.id}"`);
1798
1793
  return !collapsible || panelSize > collapsedSize;
1799
1794
  }, []);
1800
1795
  const registerPanel = useCallback(panelData => {
@@ -1961,7 +1956,7 @@ function PanelGroupWithForwardedRef({
1961
1956
  panelSize,
1962
1957
  pivotIndices
1963
1958
  } = panelDataHelper(panelDataArray, panelData, prevLayout);
1964
- assert(panelSize != null);
1959
+ assert(panelSize != null, `Panel size not found for panel "${panelData.id}"`);
1965
1960
  const isLastPanel = findPanelDataIndex(panelDataArray, panelData) === panelDataArray.length - 1;
1966
1961
  const delta = isLastPanel ? panelSize - unsafePanelSize : unsafePanelSize - panelSize;
1967
1962
  const nextLayout = adjustLayoutByDelta({
@@ -1998,7 +1993,10 @@ function PanelGroupWithForwardedRef({
1998
1993
  const {
1999
1994
  panelSize: prevPanelSize
2000
1995
  } = panelDataHelper(panelDataArray, panelData, layout);
2001
- assert(prevPanelSize != null);
1996
+ if (prevPanelSize == null) {
1997
+ // It's possible that the panels in this group have changed since the last render
1998
+ return;
1999
+ }
2002
2000
  if (prevCollapsible && nextCollapsible && prevPanelSize === prevCollapsedSize) {
2003
2001
  if (prevCollapsedSize !== nextCollapsedSize) {
2004
2002
  resizePanel(panelData, nextCollapsedSize);
@@ -2020,7 +2018,7 @@ function PanelGroupWithForwardedRef({
2020
2018
  return;
2021
2019
  }
2022
2020
  const handleElement = getResizeHandleElement(dragHandleId, panelGroupElementRef.current);
2023
- assert(handleElement);
2021
+ assert(handleElement, `Drag handle element not found for id "${dragHandleId}"`);
2024
2022
  const initialCursorPosition = getResizeEventCursorPosition(direction, event);
2025
2023
  setDragState({
2026
2024
  dragHandleId,
@@ -2149,10 +2147,10 @@ function useWindowSplitterResizeHandlerBehavior({
2149
2147
  {
2150
2148
  event.preventDefault();
2151
2149
  const groupId = handleElement.getAttribute("data-panel-group-id");
2152
- assert(groupId);
2150
+ assert(groupId, `No group element found for id "${groupId}"`);
2153
2151
  const handles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
2154
2152
  const index = getResizeHandleElementIndex(groupId, handleId, panelGroupElement);
2155
- assert(index !== null);
2153
+ assert(index !== null, `No resize element found for id "${handleId}"`);
2156
2154
  const nextIndex = event.shiftKey ? index > 0 ? index - 1 : handles.length - 1 : index + 1 < handles.length ? index + 1 : 0;
2157
2155
  const nextHandle = handles[nextIndex];
2158
2156
  nextHandle.focus();
@@ -2224,7 +2222,7 @@ function PanelResizeHandle({
2224
2222
  return;
2225
2223
  }
2226
2224
  const element = elementRef.current;
2227
- assert(element);
2225
+ assert(element, "Element ref not attached");
2228
2226
  const setResizeHandlerState = (action, isActive, event) => {
2229
2227
  if (isActive) {
2230
2228
  switch (action) {