react-resizable-panels 1.0.6 → 1.0.8

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 (52) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +20 -4
  3. package/dist/declarations/src/Panel.d.ts +6 -6
  4. package/dist/declarations/src/PanelGroup.d.ts +5 -5
  5. package/dist/declarations/src/PanelResizeHandle.d.ts +4 -4
  6. package/dist/declarations/src/utils/dom/calculateAvailablePanelSizeInPixels.d.ts +1 -1
  7. package/dist/declarations/src/utils/dom/getAvailableGroupSizePixels.d.ts +1 -1
  8. package/dist/declarations/src/utils/dom/getPanelElement.d.ts +1 -1
  9. package/dist/declarations/src/utils/dom/getPanelElementsForGroup.d.ts +1 -1
  10. package/dist/declarations/src/utils/dom/getPanelGroupElement.d.ts +1 -1
  11. package/dist/declarations/src/utils/dom/getResizeHandleElement.d.ts +1 -1
  12. package/dist/declarations/src/utils/dom/getResizeHandleElementIndex.d.ts +1 -1
  13. package/dist/declarations/src/utils/dom/getResizeHandleElementsForGroup.d.ts +1 -1
  14. package/dist/declarations/src/utils/dom/getResizeHandlePanelIds.d.ts +1 -1
  15. package/dist/declarations/src/vendor/react.d.ts +2 -2
  16. package/dist/react-resizable-panels.browser.cjs.js +82 -59
  17. package/dist/react-resizable-panels.browser.development.cjs.js +84 -60
  18. package/dist/react-resizable-panels.browser.development.esm.js +84 -60
  19. package/dist/react-resizable-panels.browser.esm.js +82 -59
  20. package/dist/react-resizable-panels.cjs.js +82 -59
  21. package/dist/react-resizable-panels.development.cjs.js +84 -60
  22. package/dist/react-resizable-panels.development.esm.js +84 -60
  23. package/dist/react-resizable-panels.development.node.cjs.js +79 -58
  24. package/dist/react-resizable-panels.development.node.esm.js +79 -58
  25. package/dist/react-resizable-panels.esm.js +82 -59
  26. package/dist/react-resizable-panels.node.cjs.js +77 -57
  27. package/dist/react-resizable-panels.node.esm.js +77 -57
  28. package/package.json +1 -1
  29. package/src/Panel.test.tsx +3 -2
  30. package/src/Panel.ts +7 -4
  31. package/src/PanelGroup.test.tsx +3 -2
  32. package/src/PanelGroup.ts +53 -30
  33. package/src/PanelGroupContext.ts +4 -2
  34. package/src/PanelResizeHandle.test.tsx +3 -3
  35. package/src/PanelResizeHandle.ts +17 -12
  36. package/src/hooks/useWindowSplitterBehavior.ts +15 -6
  37. package/src/hooks/useWindowSplitterPanelGroupBehavior.ts +23 -7
  38. package/src/utils/calculateDeltaPercentage.ts +4 -2
  39. package/src/utils/calculateDragOffsetPercentage.ts +4 -3
  40. package/src/utils/determinePivotIndices.ts +7 -2
  41. package/src/utils/dom/calculateAvailablePanelSizeInPixels.ts +8 -3
  42. package/src/utils/dom/getAvailableGroupSizePixels.ts +8 -7
  43. package/src/utils/dom/getPanelElement.ts +6 -3
  44. package/src/utils/dom/getPanelElementsForGroup.ts +7 -2
  45. package/src/utils/dom/getPanelGroupElement.ts +15 -3
  46. package/src/utils/dom/getResizeHandleElement.ts +6 -3
  47. package/src/utils/dom/getResizeHandleElementIndex.ts +3 -2
  48. package/src/utils/dom/getResizeHandleElementsForGroup.ts +4 -3
  49. package/src/utils/dom/getResizeHandlePanelIds.ts +4 -3
  50. package/src/utils/validatePanelConstraints.test.ts +45 -0
  51. package/src/utils/validatePanelConstraints.ts +5 -1
  52. package/src/vendor/react.ts +2 -0
@@ -454,41 +454,48 @@ function adjustLayoutByDelta({
454
454
  return nextLayout;
455
455
  }
456
456
 
457
- function getResizeHandleElementsForGroup(groupId) {
458
- return Array.from(document.querySelectorAll(`[data-panel-resize-handle-id][data-panel-group-id="${groupId}"]`));
457
+ function getResizeHandleElementsForGroup(groupId, panelGroupElement) {
458
+ return Array.from(panelGroupElement.querySelectorAll(`[data-panel-resize-handle-id][data-panel-group-id="${groupId}"]`));
459
459
  }
460
460
 
461
- function getResizeHandleElementIndex(groupId, id) {
462
- const handles = getResizeHandleElementsForGroup(groupId);
461
+ function getResizeHandleElementIndex(groupId, id, panelGroupElement) {
462
+ const handles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
463
463
  const index = handles.findIndex(handle => handle.getAttribute("data-panel-resize-handle-id") === id);
464
464
  return index !== null && index !== void 0 ? index : null;
465
465
  }
466
466
 
467
- function determinePivotIndices(groupId, dragHandleId) {
468
- const index = getResizeHandleElementIndex(groupId, dragHandleId);
467
+ function determinePivotIndices(groupId, dragHandleId, panelGroupElement) {
468
+ const index = getResizeHandleElementIndex(groupId, dragHandleId, panelGroupElement);
469
469
  return index != null ? [index, index + 1] : [-1, -1];
470
470
  }
471
471
 
472
- function getPanelGroupElement(id) {
473
- const element = document.querySelector(`[data-panel-group][data-panel-group-id="${id}"]`);
472
+ function getPanelGroupElement(id, rootElement) {
473
+ var _dataset;
474
+ //If the root element is the PanelGroup
475
+ if (rootElement instanceof HTMLElement && (rootElement === null || rootElement === void 0 ? void 0 : (_dataset = rootElement.dataset) === null || _dataset === void 0 ? void 0 : _dataset.panelGroupId) == id) {
476
+ return rootElement;
477
+ }
478
+
479
+ //Else query children
480
+ const element = rootElement.querySelector(`[data-panel-group][data-panel-group-id="${id}"]`);
474
481
  if (element) {
475
482
  return element;
476
483
  }
477
484
  return null;
478
485
  }
479
486
 
480
- function getResizeHandleElement(id) {
481
- const element = document.querySelector(`[data-panel-resize-handle-id="${id}"]`);
487
+ function getResizeHandleElement(id, panelGroupElement) {
488
+ const element = panelGroupElement.querySelector(`[data-panel-resize-handle-id="${id}"]`);
482
489
  if (element) {
483
490
  return element;
484
491
  }
485
492
  return null;
486
493
  }
487
494
 
488
- function getResizeHandlePanelIds(groupId, handleId, panelsArray) {
495
+ function getResizeHandlePanelIds(groupId, handleId, panelsArray, panelGroupElement) {
489
496
  var _panelsArray$index$id, _panelsArray$index, _panelsArray$id, _panelsArray;
490
- const handle = getResizeHandleElement(handleId);
491
- const handles = getResizeHandleElementsForGroup(groupId);
497
+ const handle = getResizeHandleElement(handleId, panelGroupElement);
498
+ const handles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
492
499
  const index = handle ? handles.indexOf(handle) : -1;
493
500
  const idBefore = (_panelsArray$index$id = (_panelsArray$index = panelsArray[index]) === null || _panelsArray$index === void 0 ? void 0 : _panelsArray$index.id) !== null && _panelsArray$index$id !== void 0 ? _panelsArray$index$id : null;
494
501
  const idAfter = (_panelsArray$id = (_panelsArray = panelsArray[index + 1]) === null || _panelsArray === void 0 ? void 0 : _panelsArray.id) !== null && _panelsArray$id !== void 0 ? _panelsArray$id : null;
@@ -503,25 +510,29 @@ function useWindowSplitterPanelGroupBehavior({
503
510
  groupId,
504
511
  layout,
505
512
  panelDataArray,
513
+ panelGroupElement,
506
514
  setLayout
507
515
  }) {
508
516
  useRef({
509
517
  didWarnAboutMissingResizeHandle: false
510
518
  });
511
519
  useEffect(() => {
520
+ if (!panelGroupElement) {
521
+ return;
522
+ }
512
523
  const eagerValues = eagerValuesRef.current;
513
524
  assert(eagerValues);
514
525
  const {
515
526
  panelDataArray
516
527
  } = eagerValues;
517
- const groupElement = getPanelGroupElement(groupId);
528
+ const groupElement = getPanelGroupElement(groupId, panelGroupElement);
518
529
  assert(groupElement != null, `No group found for id "${groupId}"`);
519
- const handles = getResizeHandleElementsForGroup(groupId);
530
+ const handles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
520
531
  assert(handles);
521
532
  const cleanupFunctions = handles.map(handle => {
522
533
  const handleId = handle.getAttribute("data-panel-resize-handle-id");
523
534
  assert(handleId);
524
- const [idBefore, idAfter] = getResizeHandlePanelIds(groupId, handleId, panelDataArray);
535
+ const [idBefore, idAfter] = getResizeHandlePanelIds(groupId, handleId, panelDataArray, panelGroupElement);
525
536
  if (idBefore == null || idAfter == null) {
526
537
  return () => {};
527
538
  }
@@ -548,7 +559,7 @@ function useWindowSplitterPanelGroupBehavior({
548
559
  delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
549
560
  layout,
550
561
  panelConstraints: panelDataArray.map(panelData => panelData.constraints),
551
- pivotIndices: determinePivotIndices(groupId, handleId),
562
+ pivotIndices: determinePivotIndices(groupId, handleId, panelGroupElement),
552
563
  trigger: "keyboard"
553
564
  });
554
565
  if (layout !== nextLayout) {
@@ -568,7 +579,7 @@ function useWindowSplitterPanelGroupBehavior({
568
579
  return () => {
569
580
  cleanupFunctions.forEach(cleanupFunction => cleanupFunction());
570
581
  };
571
- }, [committedValuesRef, eagerValuesRef, groupId, layout, panelDataArray, setLayout]);
582
+ }, [panelGroupElement, committedValuesRef, eagerValuesRef, groupId, layout, panelDataArray, setLayout]);
572
583
  }
573
584
 
574
585
  function areEqual(arrayA, arrayB) {
@@ -606,9 +617,9 @@ function getResizeEventCursorPosition(direction, event) {
606
617
  }
607
618
  }
608
619
 
609
- function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState) {
620
+ function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState, panelGroupElement) {
610
621
  const isHorizontal = direction === "horizontal";
611
- const handleElement = getResizeHandleElement(dragHandleId);
622
+ const handleElement = getResizeHandleElement(dragHandleId, panelGroupElement);
612
623
  assert(handleElement);
613
624
  const groupId = handleElement.getAttribute("data-panel-group-id");
614
625
  assert(groupId);
@@ -616,7 +627,7 @@ function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDr
616
627
  initialCursorPosition
617
628
  } = initialDragState;
618
629
  const cursorPosition = getResizeEventCursorPosition(direction, event);
619
- const groupElement = getPanelGroupElement(groupId);
630
+ const groupElement = getPanelGroupElement(groupId, panelGroupElement);
620
631
  assert(groupElement);
621
632
  const groupRect = groupElement.getBoundingClientRect();
622
633
  const groupSizeInPixels = isHorizontal ? groupRect.width : groupRect.height;
@@ -626,7 +637,7 @@ function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDr
626
637
  }
627
638
 
628
639
  // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/movementX
629
- function calculateDeltaPercentage(event, dragHandleId, direction, initialDragState, keyboardResizeBy) {
640
+ function calculateDeltaPercentage(event, dragHandleId, direction, initialDragState, keyboardResizeBy, panelGroupElement) {
630
641
  if (isKeyDown(event)) {
631
642
  const isHorizontal = direction === "horizontal";
632
643
  let delta = 0;
@@ -663,7 +674,7 @@ function calculateDeltaPercentage(event, dragHandleId, direction, initialDragSta
663
674
  if (initialDragState == null) {
664
675
  return 0;
665
676
  }
666
- return calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState);
677
+ return calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState, panelGroupElement);
667
678
  }
668
679
  }
669
680
 
@@ -968,6 +979,7 @@ function PanelGroupWithForwardedRef({
968
979
  ...rest
969
980
  }) {
970
981
  const groupId = useUniqueId(idFromProps);
982
+ const panelGroupElementRef = useRef(null);
971
983
  const [dragState, setDragState] = useState(null);
972
984
  const [layout, setLayout] = useState([]);
973
985
  const panelIdToLastNotifiedSizeMapRef = useRef({});
@@ -1028,7 +1040,8 @@ function PanelGroupWithForwardedRef({
1028
1040
  groupId,
1029
1041
  layout,
1030
1042
  panelDataArray: eagerValuesRef.current.panelDataArray,
1031
- setLayout
1043
+ setLayout,
1044
+ panelGroupElement: panelGroupElementRef.current
1032
1045
  });
1033
1046
  useEffect(() => {
1034
1047
  const {
@@ -1223,6 +1236,10 @@ function PanelGroupWithForwardedRef({
1223
1236
  const registerResizeHandle = useCallback(dragHandleId => {
1224
1237
  return function resizeHandler(event) {
1225
1238
  event.preventDefault();
1239
+ const panelGroupElement = panelGroupElementRef.current;
1240
+ if (!panelGroupElement) {
1241
+ return () => null;
1242
+ }
1226
1243
  const {
1227
1244
  direction,
1228
1245
  dragState,
@@ -1237,8 +1254,8 @@ function PanelGroupWithForwardedRef({
1237
1254
  const {
1238
1255
  initialLayout
1239
1256
  } = dragState !== null && dragState !== void 0 ? dragState : {};
1240
- const pivotIndices = determinePivotIndices(groupId, dragHandleId);
1241
- let delta = calculateDeltaPercentage(event, dragHandleId, direction, dragState, keyboardResizeBy);
1257
+ const pivotIndices = determinePivotIndices(groupId, dragHandleId, panelGroupElement);
1258
+ let delta = calculateDeltaPercentage(event, dragHandleId, direction, dragState, keyboardResizeBy, panelGroupElement);
1242
1259
  if (delta === 0) {
1243
1260
  return;
1244
1261
  }
@@ -1333,7 +1350,10 @@ function PanelGroupWithForwardedRef({
1333
1350
  const {
1334
1351
  layout
1335
1352
  } = eagerValuesRef.current;
1336
- const handleElement = getResizeHandleElement(dragHandleId);
1353
+ if (!panelGroupElementRef.current) {
1354
+ return;
1355
+ }
1356
+ const handleElement = getResizeHandleElement(dragHandleId, panelGroupElementRef.current);
1337
1357
  assert(handleElement);
1338
1358
  const initialCursorPosition = getResizeEventCursorPosition(direction, event);
1339
1359
  setDragState({
@@ -1378,7 +1398,8 @@ function PanelGroupWithForwardedRef({
1378
1398
  resizePanel,
1379
1399
  startDragging,
1380
1400
  stopDragging,
1381
- unregisterPanel
1401
+ unregisterPanel,
1402
+ panelGroupElement: panelGroupElementRef.current
1382
1403
  }), [collapsePanel, dragState, direction, expandPanel, getPanelSize, getPanelStyle, groupId, isPanelCollapsed, isPanelExpanded, registerPanel, registerResizeHandle, resizePanel, startDragging, stopDragging, unregisterPanel]);
1383
1404
  const style = {
1384
1405
  display: "flex",
@@ -1397,6 +1418,7 @@ function PanelGroupWithForwardedRef({
1397
1418
  ...style,
1398
1419
  ...styleFromProps
1399
1420
  },
1421
+ ref: panelGroupElementRef,
1400
1422
  // CSS selectors
1401
1423
  "data-panel-group": "",
1402
1424
  "data-panel-group-direction": direction,
@@ -1431,13 +1453,14 @@ function panelDataHelper(panelDataArray, panelData, layout) {
1431
1453
  function useWindowSplitterResizeHandlerBehavior({
1432
1454
  disabled,
1433
1455
  handleId,
1434
- resizeHandler
1456
+ resizeHandler,
1457
+ panelGroupElement
1435
1458
  }) {
1436
1459
  useEffect(() => {
1437
- if (disabled || resizeHandler == null) {
1460
+ if (disabled || resizeHandler == null || panelGroupElement == null) {
1438
1461
  return;
1439
1462
  }
1440
- const handleElement = getResizeHandleElement(handleId);
1463
+ const handleElement = getResizeHandleElement(handleId, panelGroupElement);
1441
1464
  if (handleElement == null) {
1442
1465
  return;
1443
1466
  }
@@ -1462,8 +1485,8 @@ function useWindowSplitterResizeHandlerBehavior({
1462
1485
  event.preventDefault();
1463
1486
  const groupId = handleElement.getAttribute("data-panel-group-id");
1464
1487
  assert(groupId);
1465
- const handles = getResizeHandleElementsForGroup(groupId);
1466
- const index = getResizeHandleElementIndex(groupId, handleId);
1488
+ const handles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
1489
+ const index = getResizeHandleElementIndex(groupId, handleId, panelGroupElement);
1467
1490
  assert(index !== null);
1468
1491
  const nextIndex = event.shiftKey ? index > 0 ? index - 1 : handles.length - 1 : index + 1 < handles.length ? index + 1 : 0;
1469
1492
  const nextHandle = handles[nextIndex];
@@ -1476,7 +1499,7 @@ function useWindowSplitterResizeHandlerBehavior({
1476
1499
  return () => {
1477
1500
  handleElement.removeEventListener("keydown", onKeyDown);
1478
1501
  };
1479
- }, [disabled, handleId, resizeHandler]);
1502
+ }, [panelGroupElement, disabled, handleId, resizeHandler]);
1480
1503
  }
1481
1504
 
1482
1505
  function PanelResizeHandle({
@@ -1490,7 +1513,7 @@ function PanelResizeHandle({
1490
1513
  tagName: Type = "div",
1491
1514
  ...rest
1492
1515
  }) {
1493
- const divElementRef = useRef(null);
1516
+ const elementRef = useRef(null);
1494
1517
 
1495
1518
  // Use a ref to guard against users passing inline props
1496
1519
  const callbacksRef = useRef({
@@ -1509,7 +1532,8 @@ function PanelResizeHandle({
1509
1532
  groupId,
1510
1533
  registerResizeHandle,
1511
1534
  startDragging,
1512
- stopDragging
1535
+ stopDragging,
1536
+ panelGroupElement
1513
1537
  } = panelGroupContext;
1514
1538
  const resizeHandleId = useUniqueId(idFromProps);
1515
1539
  const isDragging = (dragState === null || dragState === void 0 ? void 0 : dragState.dragHandleId) === resizeHandleId;
@@ -1518,9 +1542,9 @@ function PanelResizeHandle({
1518
1542
  const stopDraggingAndBlur = useCallback(() => {
1519
1543
  // Clicking on the drag handle shouldn't leave it focused;
1520
1544
  // That would cause the PanelGroup to think it was still active.
1521
- const divElement = divElementRef.current;
1522
- assert(divElement);
1523
- divElement.blur();
1545
+ const element = elementRef.current;
1546
+ assert(element);
1547
+ element.blur();
1524
1548
  stopDragging();
1525
1549
  const {
1526
1550
  onDragging
@@ -1547,9 +1571,9 @@ function PanelResizeHandle({
1547
1571
  const onMouseLeave = event => {
1548
1572
  resizeHandler(event);
1549
1573
  };
1550
- const divElement = divElementRef.current;
1551
- assert(divElement);
1552
- const targetDocument = divElement.ownerDocument;
1574
+ const element = elementRef.current;
1575
+ assert(element);
1576
+ const targetDocument = element.ownerDocument;
1553
1577
  targetDocument.body.addEventListener("contextmenu", stopDraggingAndBlur);
1554
1578
  targetDocument.body.addEventListener("mousemove", onMove);
1555
1579
  targetDocument.body.addEventListener("touchmove", onMove);
@@ -1568,7 +1592,8 @@ function PanelResizeHandle({
1568
1592
  useWindowSplitterResizeHandlerBehavior({
1569
1593
  disabled,
1570
1594
  handleId: resizeHandleId,
1571
- resizeHandler
1595
+ resizeHandler,
1596
+ panelGroupElement
1572
1597
  });
1573
1598
  const style = {
1574
1599
  cursor: getCursorStyle(direction),
@@ -1606,7 +1631,7 @@ function PanelResizeHandle({
1606
1631
  onDragging(true);
1607
1632
  }
1608
1633
  },
1609
- ref: divElementRef,
1634
+ ref: elementRef,
1610
1635
  role: "separator",
1611
1636
  style: {
1612
1637
  ...style,
@@ -1624,13 +1649,12 @@ function PanelResizeHandle({
1624
1649
  }
1625
1650
  PanelResizeHandle.displayName = "PanelResizeHandle";
1626
1651
 
1627
- function calculateAvailablePanelSizeInPixels(groupId) {
1628
- const panelGroupElement = getPanelGroupElement(groupId);
1652
+ function calculateAvailablePanelSizeInPixels(groupId, panelGroupElement) {
1629
1653
  if (panelGroupElement == null) {
1630
1654
  return NaN;
1631
1655
  }
1632
1656
  const direction = panelGroupElement.getAttribute("data-panel-group-direction");
1633
- const resizeHandles = getResizeHandleElementsForGroup(groupId);
1657
+ const resizeHandles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
1634
1658
  if (direction === "horizontal") {
1635
1659
  return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
1636
1660
  return accumulated + handle.offsetWidth;
@@ -1642,13 +1666,9 @@ function calculateAvailablePanelSizeInPixels(groupId) {
1642
1666
  }
1643
1667
  }
1644
1668
 
1645
- function getAvailableGroupSizePixels(groupId) {
1646
- const panelGroupElement = getPanelGroupElement(groupId);
1647
- if (panelGroupElement == null) {
1648
- return NaN;
1649
- }
1669
+ function getAvailableGroupSizePixels(groupId, panelGroupElement) {
1650
1670
  const direction = panelGroupElement.getAttribute("data-panel-group-direction");
1651
- const resizeHandles = getResizeHandleElementsForGroup(groupId);
1671
+ const resizeHandles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
1652
1672
  if (direction === "horizontal") {
1653
1673
  return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
1654
1674
  return accumulated + handle.offsetWidth;
@@ -1660,16 +1680,16 @@ function getAvailableGroupSizePixels(groupId) {
1660
1680
  }
1661
1681
  }
1662
1682
 
1663
- function getPanelElement(id) {
1664
- const element = document.querySelector(`[data-panel-id="${id}"]`);
1683
+ function getPanelElement(id, panelGroupElement) {
1684
+ const element = panelGroupElement.querySelector(`[data-panel-id="${id}"]`);
1665
1685
  if (element) {
1666
1686
  return element;
1667
1687
  }
1668
1688
  return null;
1669
1689
  }
1670
1690
 
1671
- function getPanelElementsForGroup(groupId) {
1672
- return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
1691
+ function getPanelElementsForGroup(groupId, panelGroupElement) {
1692
+ return Array.from(panelGroupElement.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
1673
1693
  }
1674
1694
 
1675
1695
  exports.Panel = Panel;