react-resizable-panels 2.0.8 → 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 (34) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/declarations/src/utils/assert.d.ts +1 -1
  3. package/dist/react-resizable-panels.browser.cjs.js +158 -53
  4. package/dist/react-resizable-panels.browser.development.cjs.js +160 -55
  5. package/dist/react-resizable-panels.browser.development.esm.js +159 -54
  6. package/dist/react-resizable-panels.browser.esm.js +157 -52
  7. package/dist/react-resizable-panels.cjs.js +158 -53
  8. package/dist/react-resizable-panels.development.cjs.js +160 -55
  9. package/dist/react-resizable-panels.development.esm.js +159 -54
  10. package/dist/react-resizable-panels.development.node.cjs.js +156 -51
  11. package/dist/react-resizable-panels.development.node.esm.js +155 -50
  12. package/dist/react-resizable-panels.esm.js +157 -52
  13. package/dist/react-resizable-panels.node.cjs.js +154 -49
  14. package/dist/react-resizable-panels.node.esm.js +153 -48
  15. package/package.json +1 -4
  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/PanelResizeHandleRegistry.ts +2 -2
  22. package/src/hooks/useWindowSplitterBehavior.ts +5 -2
  23. package/src/hooks/useWindowSplitterPanelGroupBehavior.ts +5 -5
  24. package/src/utils/adjustLayoutByDelta.ts +47 -20
  25. package/src/utils/assert.ts +1 -1
  26. package/src/utils/calculateAriaValues.ts +1 -1
  27. package/src/utils/calculateDragOffsetPercentage.ts +6 -3
  28. package/src/utils/calculateUnsafeDefaultLayout.ts +2 -2
  29. package/src/utils/callPanelCallbacks.ts +1 -1
  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 +133 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.10
4
+
5
+ - Fix conditional layout edge case (#309)
6
+
7
+ ## 2.0.9
8
+
9
+ - Fix Flex stacking context bug (#301)
10
+ - Fix case where pointer event listeners were sometimes added to the document unnecessarily
11
+
3
12
  ## 2.0.8
4
13
 
5
14
  - `Panel`/`PanelGroup`/`PanelResizeHandle`` pass "id" prop through to DOM (#299)
@@ -1 +1 @@
1
- export declare function assert(expectedCondition: any, message?: string): asserts expectedCondition;
1
+ export declare function assert(expectedCondition: any, message: string): asserts expectedCondition;
@@ -3,7 +3,6 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var React = require('react');
6
- var stackingOrder = require('stacking-order');
7
6
 
8
7
  function _interopNamespace(e) {
9
8
  if (e && e.__esModule) return e;
@@ -304,6 +303,114 @@ function intersects(rectOne, rectTwo, strict) {
304
303
  }
305
304
  }
306
305
 
306
+ // Forked from NPM stacking-order@2.0.0
307
+
308
+ /**
309
+ * Determine which of two nodes appears in front of the other —
310
+ * if `a` is in front, returns 1, otherwise returns -1
311
+ * @param {HTMLElement} a
312
+ * @param {HTMLElement} b
313
+ */
314
+ function compare(a, b) {
315
+ if (a === b) throw new Error("Cannot compare node with itself");
316
+ const ancestors = {
317
+ a: get_ancestors(a),
318
+ b: get_ancestors(b)
319
+ };
320
+ let common_ancestor;
321
+
322
+ // remove shared ancestors
323
+ while (ancestors.a.at(-1) === ancestors.b.at(-1)) {
324
+ a = ancestors.a.pop();
325
+ b = ancestors.b.pop();
326
+ common_ancestor = a;
327
+ }
328
+ assert(common_ancestor, "Stacking order can only be calculated for elements with a common ancestor");
329
+ const z_indexes = {
330
+ a: get_z_index(find_stacking_context(ancestors.a)),
331
+ b: get_z_index(find_stacking_context(ancestors.b))
332
+ };
333
+ if (z_indexes.a === z_indexes.b) {
334
+ const children = common_ancestor.childNodes;
335
+ const furthest_ancestors = {
336
+ a: ancestors.a.at(-1),
337
+ b: ancestors.b.at(-1)
338
+ };
339
+ let i = children.length;
340
+ while (i--) {
341
+ const child = children[i];
342
+ if (child === furthest_ancestors.a) return 1;
343
+ if (child === furthest_ancestors.b) return -1;
344
+ }
345
+ }
346
+ return Math.sign(z_indexes.a - z_indexes.b);
347
+ }
348
+ const props = /\b(?:position|zIndex|opacity|transform|webkitTransform|mixBlendMode|filter|webkitFilter|isolation)\b/;
349
+
350
+ /** @param {HTMLElement} node */
351
+ function is_flex_item(node) {
352
+ const display = getComputedStyle(get_parent(node)).display;
353
+ return display === "flex" || display === "inline-flex";
354
+ }
355
+
356
+ /** @param {HTMLElement} node */
357
+ function creates_stacking_context(node) {
358
+ const style = getComputedStyle(node);
359
+
360
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
361
+ if (style.position === "fixed") return true;
362
+ // Forked to fix upstream bug https://github.com/Rich-Harris/stacking-order/issues/3
363
+ // if (
364
+ // (style.zIndex !== "auto" && style.position !== "static") ||
365
+ // is_flex_item(node)
366
+ // )
367
+ if (style.zIndex !== "auto" && (style.position !== "static" || is_flex_item(node))) return true;
368
+ if (+style.opacity < 1) return true;
369
+ if ("transform" in style && style.transform !== "none") return true;
370
+ if ("webkitTransform" in style && style.webkitTransform !== "none") return true;
371
+ if ("mixBlendMode" in style && style.mixBlendMode !== "normal") return true;
372
+ if ("filter" in style && style.filter !== "none") return true;
373
+ if ("webkitFilter" in style && style.webkitFilter !== "none") return true;
374
+ if ("isolation" in style && style.isolation === "isolate") return true;
375
+ if (props.test(style.willChange)) return true;
376
+ // @ts-expect-error
377
+ if (style.webkitOverflowScrolling === "touch") return true;
378
+ return false;
379
+ }
380
+
381
+ /** @param {HTMLElement[]} nodes */
382
+ function find_stacking_context(nodes) {
383
+ let i = nodes.length;
384
+ while (i--) {
385
+ const node = nodes[i];
386
+ assert(node, "Missing node");
387
+ if (creates_stacking_context(node)) return node;
388
+ }
389
+ return null;
390
+ }
391
+
392
+ /** @param {HTMLElement} node */
393
+ function get_z_index(node) {
394
+ return node && Number(getComputedStyle(node).zIndex) || 0;
395
+ }
396
+
397
+ /** @param {HTMLElement} node */
398
+ function get_ancestors(node) {
399
+ const ancestors = [];
400
+ while (node) {
401
+ ancestors.push(node);
402
+ node = get_parent(node);
403
+ }
404
+ return ancestors; // [ node, ... <body>, <html>, document ]
405
+ }
406
+
407
+ /** @param {HTMLElement} node */
408
+ function get_parent(node) {
409
+ var _node$parentNode;
410
+ // @ts-ignore
411
+ return ((_node$parentNode = node.parentNode) === null || _node$parentNode === void 0 ? void 0 : _node$parentNode.host) || node.parentNode;
412
+ }
413
+
307
414
  const EXCEEDED_HORIZONTAL_MIN = 0b0001;
308
415
  const EXCEEDED_HORIZONTAL_MAX = 0b0010;
309
416
  const EXCEEDED_VERTICAL_MIN = 0b0100;
@@ -445,7 +552,7 @@ function recalculateIntersectingHandles({
445
552
  // Calculating stacking order has a cost, so we should avoid it if possible
446
553
  // That is why we only check potentially intersecting handles,
447
554
  // and why we skip if the event target is within the handle's DOM
448
- stackingOrder.compare(targetElement, dragHandleElement) > 0) {
555
+ compare(targetElement, dragHandleElement) > 0) {
449
556
  // If the target is above the drag handle, then we also need to confirm they overlap
450
557
  // If they are beside each other (e.g. a panel and its drag handle) then the handle is still interactive
451
558
  //
@@ -516,7 +623,7 @@ function updateListeners() {
516
623
  window.removeEventListener("mouseup", handlePointerUp);
517
624
  window.removeEventListener("touchcancel", handlePointerUp);
518
625
  window.removeEventListener("touchend", handlePointerUp);
519
- if (registerResizeHandle.length > 0) {
626
+ if (registeredResizeHandlers.size > 0) {
520
627
  if (isPointerDown) {
521
628
  if (intersectingHandles.length > 0) {
522
629
  ownerDocumentCounts.forEach((count, ownerDocument) => {
@@ -563,7 +670,7 @@ function updateResizeHandlerStates(action, event) {
563
670
  });
564
671
  }
565
672
 
566
- function assert(expectedCondition, message = "Assertion failed!") {
673
+ function assert(expectedCondition, message) {
567
674
  if (!expectedCondition) {
568
675
  console.error(message);
569
676
  throw Error(message);
@@ -594,7 +701,7 @@ function resizePanel({
594
701
  size
595
702
  }) {
596
703
  const panelConstraints = panelConstraintsArray[panelIndex];
597
- assert(panelConstraints != null);
704
+ assert(panelConstraints != null, `Panel constraints not found for index ${panelIndex}`);
598
705
  let {
599
706
  collapsedSize = 0,
600
707
  collapsible,
@@ -632,8 +739,8 @@ function adjustLayoutByDelta({
632
739
  }
633
740
  const nextLayout = [...prevLayout];
634
741
  const [firstPivotIndex, secondPivotIndex] = pivotIndices;
635
- assert(firstPivotIndex != null);
636
- assert(secondPivotIndex != null);
742
+ assert(firstPivotIndex != null, "Invalid first pivot index");
743
+ assert(secondPivotIndex != null, "Invalid second pivot index");
637
744
  let deltaApplied = 0;
638
745
 
639
746
  //const DEBUG = [];
@@ -659,19 +766,18 @@ function adjustLayoutByDelta({
659
766
  // Check if we should expand a collapsed panel
660
767
  const index = delta < 0 ? secondPivotIndex : firstPivotIndex;
661
768
  const panelConstraints = panelConstraintsArray[index];
662
- assert(panelConstraints);
769
+ assert(panelConstraints, `Panel constraints not found for index ${index}`);
770
+ const {
771
+ collapsedSize = 0,
772
+ collapsible,
773
+ minSize = 0
774
+ } = panelConstraints;
663
775
 
664
776
  //DEBUG.push(`edge case check 1: ${index}`);
665
777
  //DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
666
- if (panelConstraints.collapsible) {
778
+ if (collapsible) {
667
779
  const prevSize = prevLayout[index];
668
- assert(prevSize != null);
669
- const panelConstraints = panelConstraintsArray[index];
670
- assert(panelConstraints);
671
- const {
672
- collapsedSize = 0,
673
- minSize = 0
674
- } = panelConstraints;
780
+ assert(prevSize != null, `Previous layout not found for panel index ${index}`);
675
781
  if (fuzzyNumbersEqual(prevSize, collapsedSize)) {
676
782
  const localDelta = minSize - prevSize;
677
783
  //DEBUG.push(` -> expand delta: ${localDelta}`);
@@ -688,22 +794,18 @@ function adjustLayoutByDelta({
688
794
  // Check if we should collapse a panel at its minimum size
689
795
  const index = delta < 0 ? firstPivotIndex : secondPivotIndex;
690
796
  const panelConstraints = panelConstraintsArray[index];
691
- assert(panelConstraints);
797
+ assert(panelConstraints, `No panel constraints found for index ${index}`);
692
798
  const {
693
- collapsible
799
+ collapsedSize = 0,
800
+ collapsible,
801
+ minSize = 0
694
802
  } = panelConstraints;
695
803
 
696
804
  //DEBUG.push(`edge case check 2: ${index}`);
697
805
  //DEBUG.push(` -> collapsible? ${collapsible}`);
698
806
  if (collapsible) {
699
807
  const prevSize = prevLayout[index];
700
- assert(prevSize != null);
701
- const panelConstraints = panelConstraintsArray[index];
702
- assert(panelConstraints);
703
- const {
704
- collapsedSize = 0,
705
- minSize = 0
706
- } = panelConstraints;
808
+ assert(prevSize != null, `Previous layout not found for panel index ${index}`);
707
809
  if (fuzzyNumbersEqual(prevSize, minSize)) {
708
810
  const localDelta = prevSize - collapsedSize;
709
811
  //DEBUG.push(` -> expand delta: ${localDelta}`);
@@ -733,7 +835,7 @@ function adjustLayoutByDelta({
733
835
  //DEBUG.push("pre calc...");
734
836
  while (true) {
735
837
  const prevSize = prevLayout[index];
736
- assert(prevSize != null);
838
+ assert(prevSize != null, `Previous layout not found for panel index ${index}`);
737
839
  const maxSafeSize = resizePanel({
738
840
  panelConstraints: panelConstraintsArray,
739
841
  panelIndex: index,
@@ -764,7 +866,7 @@ function adjustLayoutByDelta({
764
866
  while (index >= 0 && index < panelConstraintsArray.length) {
765
867
  const deltaRemaining = Math.abs(delta) - Math.abs(deltaApplied);
766
868
  const prevSize = prevLayout[index];
767
- assert(prevSize != null);
869
+ assert(prevSize != null, `Previous layout not found for panel index ${index}`);
768
870
  const unsafeSize = prevSize - deltaRemaining;
769
871
  const safeSize = resizePanel({
770
872
  panelConstraints: panelConstraintsArray,
@@ -801,7 +903,7 @@ function adjustLayoutByDelta({
801
903
  // Now distribute the applied delta to the panels in the other direction
802
904
  const pivotIndex = delta < 0 ? secondPivotIndex : firstPivotIndex;
803
905
  const prevSize = prevLayout[pivotIndex];
804
- assert(prevSize != null);
906
+ assert(prevSize != null, `Previous layout not found for panel index ${pivotIndex}`);
805
907
  const unsafeSize = prevSize + deltaApplied;
806
908
  const safeSize = resizePanel({
807
909
  panelConstraints: panelConstraintsArray,
@@ -819,7 +921,7 @@ function adjustLayoutByDelta({
819
921
  let index = pivotIndex;
820
922
  while (index >= 0 && index < panelConstraintsArray.length) {
821
923
  const prevSize = nextLayout[index];
822
- assert(prevSize != null);
924
+ assert(prevSize != null, `Previous layout not found for panel index ${index}`);
823
925
  const unsafeSize = prevSize + deltaRemaining;
824
926
  const safeSize = resizePanel({
825
927
  panelConstraints: panelConstraintsArray,
@@ -865,7 +967,7 @@ function calculateAriaValues({
865
967
  let totalMinSize = 0;
866
968
  let totalMaxSize = 0;
867
969
  const firstIndex = pivotIndices[0];
868
- assert(firstIndex != null);
970
+ assert(firstIndex != null, "No pivot index found");
869
971
 
870
972
  // A panel's effective min/max sizes also need to account for other panel's sizes.
871
973
  panelsArray.forEach((panelData, index) => {
@@ -974,7 +1076,7 @@ function useWindowSplitterPanelGroupBehavior({
974
1076
  const resizeHandleElement = resizeHandleElements[index];
975
1077
  if (resizeHandleElement == null) ; else {
976
1078
  const panelData = panelDataArray[index];
977
- assert(panelData);
1079
+ assert(panelData, `No panel data found for index "${index}"`);
978
1080
  resizeHandleElement.setAttribute("aria-controls", panelData.id);
979
1081
  resizeHandleElement.setAttribute("aria-valuemax", "" + Math.round(valueMax));
980
1082
  resizeHandleElement.setAttribute("aria-valuemin", "" + Math.round(valueMin));
@@ -995,17 +1097,17 @@ function useWindowSplitterPanelGroupBehavior({
995
1097
  return;
996
1098
  }
997
1099
  const eagerValues = eagerValuesRef.current;
998
- assert(eagerValues);
1100
+ assert(eagerValues, `Eager values not found`);
999
1101
  const {
1000
1102
  panelDataArray
1001
1103
  } = eagerValues;
1002
1104
  const groupElement = getPanelGroupElement(groupId, panelGroupElement);
1003
1105
  assert(groupElement != null, `No group found for id "${groupId}"`);
1004
1106
  const handles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
1005
- assert(handles);
1107
+ assert(handles, `No resize handles found for group id "${groupId}"`);
1006
1108
  const cleanupFunctions = handles.map(handle => {
1007
1109
  const handleId = handle.getAttribute("data-panel-resize-handle-id");
1008
- assert(handleId);
1110
+ assert(handleId, `Resize handle element has no handle id attribute`);
1009
1111
  const [idBefore, idAfter] = getResizeHandlePanelIds(groupId, handleId, panelDataArray, panelGroupElement);
1010
1112
  if (idBefore == null || idAfter == null) {
1011
1113
  return () => {};
@@ -1021,7 +1123,7 @@ function useWindowSplitterPanelGroupBehavior({
1021
1123
  const index = panelDataArray.findIndex(panelData => panelData.id === idBefore);
1022
1124
  if (index >= 0) {
1023
1125
  const panelData = panelDataArray[index];
1024
- assert(panelData);
1126
+ assert(panelData, `No panel data found for index ${index}`);
1025
1127
  const size = layout[index];
1026
1128
  const {
1027
1129
  collapsedSize = 0,
@@ -1080,15 +1182,15 @@ function getResizeEventCursorPosition(direction, event) {
1080
1182
  function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState, panelGroupElement) {
1081
1183
  const isHorizontal = direction === "horizontal";
1082
1184
  const handleElement = getResizeHandleElement(dragHandleId, panelGroupElement);
1083
- assert(handleElement);
1185
+ assert(handleElement, `No resize handle element found for id "${dragHandleId}"`);
1084
1186
  const groupId = handleElement.getAttribute("data-panel-group-id");
1085
- assert(groupId);
1187
+ assert(groupId, `Resize handle element has no group id attribute`);
1086
1188
  let {
1087
1189
  initialCursorPosition
1088
1190
  } = initialDragState;
1089
1191
  const cursorPosition = getResizeEventCursorPosition(direction, event);
1090
1192
  const groupElement = getPanelGroupElement(groupId, panelGroupElement);
1091
- assert(groupElement);
1193
+ assert(groupElement, `No group element found for id "${groupId}"`);
1092
1194
  const groupRect = groupElement.getBoundingClientRect();
1093
1195
  const groupSizeInPixels = isHorizontal ? groupRect.width : groupRect.height;
1094
1196
  const offsetPixels = cursorPosition - initialCursorPosition;
@@ -1149,7 +1251,7 @@ function calculateUnsafeDefaultLayout({
1149
1251
  // Distribute default sizes first
1150
1252
  for (let index = 0; index < panelDataArray.length; index++) {
1151
1253
  const panelConstraints = panelConstraintsArray[index];
1152
- assert(panelConstraints);
1254
+ assert(panelConstraints, `Panel constraints not found for index ${index}`);
1153
1255
  const {
1154
1256
  defaultSize
1155
1257
  } = panelConstraints;
@@ -1163,7 +1265,7 @@ function calculateUnsafeDefaultLayout({
1163
1265
  // Remaining size should be distributed evenly between panels without default sizes
1164
1266
  for (let index = 0; index < panelDataArray.length; index++) {
1165
1267
  const panelConstraints = panelConstraintsArray[index];
1166
- assert(panelConstraints);
1268
+ assert(panelConstraints, `Panel constraints not found for index ${index}`);
1167
1269
  const {
1168
1270
  defaultSize
1169
1271
  } = panelConstraints;
@@ -1183,7 +1285,7 @@ function calculateUnsafeDefaultLayout({
1183
1285
  function callPanelCallbacks(panelsArray, layout, panelIdToLastNotifiedSizeMap) {
1184
1286
  layout.forEach((size, index) => {
1185
1287
  const panelData = panelsArray[index];
1186
- assert(panelData);
1288
+ assert(panelData, `Panel data not found for index ${index}`);
1187
1289
  const {
1188
1290
  callbacks,
1189
1291
  constraints,
@@ -1373,7 +1475,7 @@ function validatePanelGroupLayout({
1373
1475
  } else if (!fuzzyNumbersEqual(nextLayoutTotalSize, 100)) {
1374
1476
  for (let index = 0; index < panelConstraints.length; index++) {
1375
1477
  const unsafeSize = nextLayout[index];
1376
- assert(unsafeSize != null);
1478
+ assert(unsafeSize != null, `No layout data found for index ${index}`);
1377
1479
  const safeSize = 100 / nextLayoutTotalSize * unsafeSize;
1378
1480
  nextLayout[index] = safeSize;
1379
1481
  }
@@ -1383,7 +1485,7 @@ function validatePanelGroupLayout({
1383
1485
  // First pass: Validate the proposed layout given each panel's constraints
1384
1486
  for (let index = 0; index < panelConstraints.length; index++) {
1385
1487
  const unsafeSize = nextLayout[index];
1386
- assert(unsafeSize != null);
1488
+ assert(unsafeSize != null, `No layout data found for index ${index}`);
1387
1489
  const safeSize = resizePanel({
1388
1490
  panelConstraints,
1389
1491
  panelIndex: index,
@@ -1400,7 +1502,7 @@ function validatePanelGroupLayout({
1400
1502
  if (!fuzzyNumbersEqual(remainingSize, 0)) {
1401
1503
  for (let index = 0; index < panelConstraints.length; index++) {
1402
1504
  const prevSize = nextLayout[index];
1403
- assert(prevSize != null);
1505
+ assert(prevSize != null, `No layout data found for index ${index}`);
1404
1506
  const unsafeSize = prevSize + remainingSize;
1405
1507
  const safeSize = resizePanel({
1406
1508
  panelConstraints,
@@ -1566,7 +1668,7 @@ function PanelGroupWithForwardedRef({
1566
1668
  panelSize,
1567
1669
  pivotIndices
1568
1670
  } = panelDataHelper(panelDataArray, panelData, prevLayout);
1569
- assert(panelSize != null);
1671
+ assert(panelSize != null, `Panel size not found for panel "${panelData.id}"`);
1570
1672
  if (panelSize !== collapsedSize) {
1571
1673
  // Store size before collapse;
1572
1674
  // This is the size that gets restored if the expand() API is used.
@@ -1643,7 +1745,7 @@ function PanelGroupWithForwardedRef({
1643
1745
  const {
1644
1746
  panelSize
1645
1747
  } = panelDataHelper(panelDataArray, panelData, layout);
1646
- assert(panelSize != null);
1748
+ assert(panelSize != null, `Panel size not found for panel "${panelData.id}"`);
1647
1749
  return panelSize;
1648
1750
  }, []);
1649
1751
 
@@ -1687,7 +1789,7 @@ function PanelGroupWithForwardedRef({
1687
1789
  collapsible,
1688
1790
  panelSize
1689
1791
  } = panelDataHelper(panelDataArray, panelData, layout);
1690
- assert(panelSize != null);
1792
+ assert(panelSize != null, `Panel size not found for panel "${panelData.id}"`);
1691
1793
  return !collapsible || panelSize > collapsedSize;
1692
1794
  }, []);
1693
1795
  const registerPanel = useCallback(panelData => {
@@ -1854,7 +1956,7 @@ function PanelGroupWithForwardedRef({
1854
1956
  panelSize,
1855
1957
  pivotIndices
1856
1958
  } = panelDataHelper(panelDataArray, panelData, prevLayout);
1857
- assert(panelSize != null);
1959
+ assert(panelSize != null, `Panel size not found for panel "${panelData.id}"`);
1858
1960
  const isLastPanel = findPanelDataIndex(panelDataArray, panelData) === panelDataArray.length - 1;
1859
1961
  const delta = isLastPanel ? panelSize - unsafePanelSize : unsafePanelSize - panelSize;
1860
1962
  const nextLayout = adjustLayoutByDelta({
@@ -1891,7 +1993,10 @@ function PanelGroupWithForwardedRef({
1891
1993
  const {
1892
1994
  panelSize: prevPanelSize
1893
1995
  } = panelDataHelper(panelDataArray, panelData, layout);
1894
- 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
+ }
1895
2000
  if (prevCollapsible && nextCollapsible && prevPanelSize === prevCollapsedSize) {
1896
2001
  if (prevCollapsedSize !== nextCollapsedSize) {
1897
2002
  resizePanel(panelData, nextCollapsedSize);
@@ -1913,7 +2018,7 @@ function PanelGroupWithForwardedRef({
1913
2018
  return;
1914
2019
  }
1915
2020
  const handleElement = getResizeHandleElement(dragHandleId, panelGroupElementRef.current);
1916
- assert(handleElement);
2021
+ assert(handleElement, `Drag handle element not found for id "${dragHandleId}"`);
1917
2022
  const initialCursorPosition = getResizeEventCursorPosition(direction, event);
1918
2023
  setDragState({
1919
2024
  dragHandleId,
@@ -2042,10 +2147,10 @@ function useWindowSplitterResizeHandlerBehavior({
2042
2147
  {
2043
2148
  event.preventDefault();
2044
2149
  const groupId = handleElement.getAttribute("data-panel-group-id");
2045
- assert(groupId);
2150
+ assert(groupId, `No group element found for id "${groupId}"`);
2046
2151
  const handles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
2047
2152
  const index = getResizeHandleElementIndex(groupId, handleId, panelGroupElement);
2048
- assert(index !== null);
2153
+ assert(index !== null, `No resize element found for id "${handleId}"`);
2049
2154
  const nextIndex = event.shiftKey ? index > 0 ? index - 1 : handles.length - 1 : index + 1 < handles.length ? index + 1 : 0;
2050
2155
  const nextHandle = handles[nextIndex];
2051
2156
  nextHandle.focus();
@@ -2117,7 +2222,7 @@ function PanelResizeHandle({
2117
2222
  return;
2118
2223
  }
2119
2224
  const element = elementRef.current;
2120
- assert(element);
2225
+ assert(element, "Element ref not attached");
2121
2226
  const setResizeHandlerState = (action, isActive, event) => {
2122
2227
  if (isActive) {
2123
2228
  switch (action) {