react-resizable-panels 1.0.7 → 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.
- package/CHANGELOG.md +6 -0
- package/dist/declarations/src/Panel.d.ts +3 -3
- package/dist/declarations/src/PanelGroup.d.ts +2 -2
- package/dist/declarations/src/PanelResizeHandle.d.ts +2 -2
- package/dist/declarations/src/utils/dom/calculateAvailablePanelSizeInPixels.d.ts +1 -1
- package/dist/declarations/src/utils/dom/getAvailableGroupSizePixels.d.ts +1 -1
- package/dist/declarations/src/utils/dom/getPanelElement.d.ts +1 -1
- package/dist/declarations/src/utils/dom/getPanelElementsForGroup.d.ts +1 -1
- package/dist/declarations/src/utils/dom/getPanelGroupElement.d.ts +1 -1
- package/dist/declarations/src/utils/dom/getResizeHandleElement.d.ts +1 -1
- package/dist/declarations/src/utils/dom/getResizeHandleElementIndex.d.ts +1 -1
- package/dist/declarations/src/utils/dom/getResizeHandleElementsForGroup.d.ts +1 -1
- package/dist/declarations/src/utils/dom/getResizeHandlePanelIds.d.ts +1 -1
- package/dist/declarations/src/vendor/react.d.ts +2 -2
- package/dist/react-resizable-panels.browser.cjs.js +74 -51
- package/dist/react-resizable-panels.browser.development.cjs.js +76 -52
- package/dist/react-resizable-panels.browser.development.esm.js +76 -52
- package/dist/react-resizable-panels.browser.esm.js +74 -51
- package/dist/react-resizable-panels.cjs.js +74 -51
- package/dist/react-resizable-panels.development.cjs.js +76 -52
- package/dist/react-resizable-panels.development.esm.js +76 -52
- package/dist/react-resizable-panels.development.node.cjs.js +71 -50
- package/dist/react-resizable-panels.development.node.esm.js +71 -50
- package/dist/react-resizable-panels.esm.js +74 -51
- package/dist/react-resizable-panels.node.cjs.js +69 -49
- package/dist/react-resizable-panels.node.esm.js +69 -49
- package/package.json +1 -1
- package/src/Panel.test.tsx +3 -2
- package/src/Panel.ts +2 -2
- package/src/PanelGroup.test.tsx +3 -2
- package/src/PanelGroup.ts +48 -28
- package/src/PanelGroupContext.ts +4 -2
- package/src/PanelResizeHandle.test.tsx +3 -3
- package/src/PanelResizeHandle.ts +4 -2
- package/src/hooks/useWindowSplitterBehavior.ts +14 -5
- package/src/hooks/useWindowSplitterPanelGroupBehavior.ts +23 -7
- package/src/utils/calculateDeltaPercentage.ts +4 -2
- package/src/utils/calculateDragOffsetPercentage.ts +4 -3
- package/src/utils/determinePivotIndices.ts +7 -2
- package/src/utils/dom/calculateAvailablePanelSizeInPixels.ts +8 -3
- package/src/utils/dom/getAvailableGroupSizePixels.ts +8 -7
- package/src/utils/dom/getPanelElement.ts +5 -2
- package/src/utils/dom/getPanelElementsForGroup.ts +7 -2
- package/src/utils/dom/getPanelGroupElement.ts +14 -2
- package/src/utils/dom/getResizeHandleElement.ts +5 -2
- package/src/utils/dom/getResizeHandleElementIndex.ts +3 -2
- package/src/utils/dom/getResizeHandleElementsForGroup.ts +3 -2
- package/src/utils/dom/getResizeHandlePanelIds.ts +4 -3
- package/src/utils/validatePanelConstraints.test.ts +45 -0
- package/src/utils/validatePanelConstraints.ts +5 -1
- package/src/vendor/react.ts +2 -0
|
@@ -430,41 +430,48 @@ function adjustLayoutByDelta({
|
|
|
430
430
|
return nextLayout;
|
|
431
431
|
}
|
|
432
432
|
|
|
433
|
-
function getResizeHandleElementsForGroup(groupId) {
|
|
434
|
-
return Array.from(
|
|
433
|
+
function getResizeHandleElementsForGroup(groupId, panelGroupElement) {
|
|
434
|
+
return Array.from(panelGroupElement.querySelectorAll(`[data-panel-resize-handle-id][data-panel-group-id="${groupId}"]`));
|
|
435
435
|
}
|
|
436
436
|
|
|
437
|
-
function getResizeHandleElementIndex(groupId, id) {
|
|
438
|
-
const handles = getResizeHandleElementsForGroup(groupId);
|
|
437
|
+
function getResizeHandleElementIndex(groupId, id, panelGroupElement) {
|
|
438
|
+
const handles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
|
|
439
439
|
const index = handles.findIndex(handle => handle.getAttribute("data-panel-resize-handle-id") === id);
|
|
440
440
|
return index !== null && index !== void 0 ? index : null;
|
|
441
441
|
}
|
|
442
442
|
|
|
443
|
-
function determinePivotIndices(groupId, dragHandleId) {
|
|
444
|
-
const index = getResizeHandleElementIndex(groupId, dragHandleId);
|
|
443
|
+
function determinePivotIndices(groupId, dragHandleId, panelGroupElement) {
|
|
444
|
+
const index = getResizeHandleElementIndex(groupId, dragHandleId, panelGroupElement);
|
|
445
445
|
return index != null ? [index, index + 1] : [-1, -1];
|
|
446
446
|
}
|
|
447
447
|
|
|
448
|
-
function getPanelGroupElement(id) {
|
|
449
|
-
|
|
448
|
+
function getPanelGroupElement(id, rootElement) {
|
|
449
|
+
var _dataset;
|
|
450
|
+
//If the root element is the PanelGroup
|
|
451
|
+
if (rootElement instanceof HTMLElement && (rootElement === null || rootElement === void 0 ? void 0 : (_dataset = rootElement.dataset) === null || _dataset === void 0 ? void 0 : _dataset.panelGroupId) == id) {
|
|
452
|
+
return rootElement;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
//Else query children
|
|
456
|
+
const element = rootElement.querySelector(`[data-panel-group][data-panel-group-id="${id}"]`);
|
|
450
457
|
if (element) {
|
|
451
458
|
return element;
|
|
452
459
|
}
|
|
453
460
|
return null;
|
|
454
461
|
}
|
|
455
462
|
|
|
456
|
-
function getResizeHandleElement(id) {
|
|
457
|
-
const element =
|
|
463
|
+
function getResizeHandleElement(id, panelGroupElement) {
|
|
464
|
+
const element = panelGroupElement.querySelector(`[data-panel-resize-handle-id="${id}"]`);
|
|
458
465
|
if (element) {
|
|
459
466
|
return element;
|
|
460
467
|
}
|
|
461
468
|
return null;
|
|
462
469
|
}
|
|
463
470
|
|
|
464
|
-
function getResizeHandlePanelIds(groupId, handleId, panelsArray) {
|
|
471
|
+
function getResizeHandlePanelIds(groupId, handleId, panelsArray, panelGroupElement) {
|
|
465
472
|
var _panelsArray$index$id, _panelsArray$index, _panelsArray$id, _panelsArray;
|
|
466
|
-
const handle = getResizeHandleElement(handleId);
|
|
467
|
-
const handles = getResizeHandleElementsForGroup(groupId);
|
|
473
|
+
const handle = getResizeHandleElement(handleId, panelGroupElement);
|
|
474
|
+
const handles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
|
|
468
475
|
const index = handle ? handles.indexOf(handle) : -1;
|
|
469
476
|
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;
|
|
470
477
|
const idAfter = (_panelsArray$id = (_panelsArray = panelsArray[index + 1]) === null || _panelsArray === void 0 ? void 0 : _panelsArray.id) !== null && _panelsArray$id !== void 0 ? _panelsArray$id : null;
|
|
@@ -479,25 +486,29 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
479
486
|
groupId,
|
|
480
487
|
layout,
|
|
481
488
|
panelDataArray,
|
|
489
|
+
panelGroupElement,
|
|
482
490
|
setLayout
|
|
483
491
|
}) {
|
|
484
492
|
useRef({
|
|
485
493
|
didWarnAboutMissingResizeHandle: false
|
|
486
494
|
});
|
|
487
495
|
useEffect(() => {
|
|
496
|
+
if (!panelGroupElement) {
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
488
499
|
const eagerValues = eagerValuesRef.current;
|
|
489
500
|
assert(eagerValues);
|
|
490
501
|
const {
|
|
491
502
|
panelDataArray
|
|
492
503
|
} = eagerValues;
|
|
493
|
-
const groupElement = getPanelGroupElement(groupId);
|
|
504
|
+
const groupElement = getPanelGroupElement(groupId, panelGroupElement);
|
|
494
505
|
assert(groupElement != null, `No group found for id "${groupId}"`);
|
|
495
|
-
const handles = getResizeHandleElementsForGroup(groupId);
|
|
506
|
+
const handles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
|
|
496
507
|
assert(handles);
|
|
497
508
|
const cleanupFunctions = handles.map(handle => {
|
|
498
509
|
const handleId = handle.getAttribute("data-panel-resize-handle-id");
|
|
499
510
|
assert(handleId);
|
|
500
|
-
const [idBefore, idAfter] = getResizeHandlePanelIds(groupId, handleId, panelDataArray);
|
|
511
|
+
const [idBefore, idAfter] = getResizeHandlePanelIds(groupId, handleId, panelDataArray, panelGroupElement);
|
|
501
512
|
if (idBefore == null || idAfter == null) {
|
|
502
513
|
return () => {};
|
|
503
514
|
}
|
|
@@ -524,7 +535,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
524
535
|
delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
|
|
525
536
|
layout,
|
|
526
537
|
panelConstraints: panelDataArray.map(panelData => panelData.constraints),
|
|
527
|
-
pivotIndices: determinePivotIndices(groupId, handleId),
|
|
538
|
+
pivotIndices: determinePivotIndices(groupId, handleId, panelGroupElement),
|
|
528
539
|
trigger: "keyboard"
|
|
529
540
|
});
|
|
530
541
|
if (layout !== nextLayout) {
|
|
@@ -544,7 +555,7 @@ function useWindowSplitterPanelGroupBehavior({
|
|
|
544
555
|
return () => {
|
|
545
556
|
cleanupFunctions.forEach(cleanupFunction => cleanupFunction());
|
|
546
557
|
};
|
|
547
|
-
}, [committedValuesRef, eagerValuesRef, groupId, layout, panelDataArray, setLayout]);
|
|
558
|
+
}, [panelGroupElement, committedValuesRef, eagerValuesRef, groupId, layout, panelDataArray, setLayout]);
|
|
548
559
|
}
|
|
549
560
|
|
|
550
561
|
function areEqual(arrayA, arrayB) {
|
|
@@ -582,9 +593,9 @@ function getResizeEventCursorPosition(direction, event) {
|
|
|
582
593
|
}
|
|
583
594
|
}
|
|
584
595
|
|
|
585
|
-
function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState) {
|
|
596
|
+
function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState, panelGroupElement) {
|
|
586
597
|
const isHorizontal = direction === "horizontal";
|
|
587
|
-
const handleElement = getResizeHandleElement(dragHandleId);
|
|
598
|
+
const handleElement = getResizeHandleElement(dragHandleId, panelGroupElement);
|
|
588
599
|
assert(handleElement);
|
|
589
600
|
const groupId = handleElement.getAttribute("data-panel-group-id");
|
|
590
601
|
assert(groupId);
|
|
@@ -592,7 +603,7 @@ function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDr
|
|
|
592
603
|
initialCursorPosition
|
|
593
604
|
} = initialDragState;
|
|
594
605
|
const cursorPosition = getResizeEventCursorPosition(direction, event);
|
|
595
|
-
const groupElement = getPanelGroupElement(groupId);
|
|
606
|
+
const groupElement = getPanelGroupElement(groupId, panelGroupElement);
|
|
596
607
|
assert(groupElement);
|
|
597
608
|
const groupRect = groupElement.getBoundingClientRect();
|
|
598
609
|
const groupSizeInPixels = isHorizontal ? groupRect.width : groupRect.height;
|
|
@@ -602,7 +613,7 @@ function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDr
|
|
|
602
613
|
}
|
|
603
614
|
|
|
604
615
|
// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/movementX
|
|
605
|
-
function calculateDeltaPercentage(event, dragHandleId, direction, initialDragState, keyboardResizeBy) {
|
|
616
|
+
function calculateDeltaPercentage(event, dragHandleId, direction, initialDragState, keyboardResizeBy, panelGroupElement) {
|
|
606
617
|
if (isKeyDown(event)) {
|
|
607
618
|
const isHorizontal = direction === "horizontal";
|
|
608
619
|
let delta = 0;
|
|
@@ -639,7 +650,7 @@ function calculateDeltaPercentage(event, dragHandleId, direction, initialDragSta
|
|
|
639
650
|
if (initialDragState == null) {
|
|
640
651
|
return 0;
|
|
641
652
|
}
|
|
642
|
-
return calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState);
|
|
653
|
+
return calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState, panelGroupElement);
|
|
643
654
|
}
|
|
644
655
|
}
|
|
645
656
|
|
|
@@ -944,6 +955,7 @@ function PanelGroupWithForwardedRef({
|
|
|
944
955
|
...rest
|
|
945
956
|
}) {
|
|
946
957
|
const groupId = useUniqueId(idFromProps);
|
|
958
|
+
const panelGroupElementRef = useRef(null);
|
|
947
959
|
const [dragState, setDragState] = useState(null);
|
|
948
960
|
const [layout, setLayout] = useState([]);
|
|
949
961
|
const panelIdToLastNotifiedSizeMapRef = useRef({});
|
|
@@ -1004,7 +1016,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1004
1016
|
groupId,
|
|
1005
1017
|
layout,
|
|
1006
1018
|
panelDataArray: eagerValuesRef.current.panelDataArray,
|
|
1007
|
-
setLayout
|
|
1019
|
+
setLayout,
|
|
1020
|
+
panelGroupElement: panelGroupElementRef.current
|
|
1008
1021
|
});
|
|
1009
1022
|
useEffect(() => {
|
|
1010
1023
|
const {
|
|
@@ -1199,6 +1212,10 @@ function PanelGroupWithForwardedRef({
|
|
|
1199
1212
|
const registerResizeHandle = useCallback(dragHandleId => {
|
|
1200
1213
|
return function resizeHandler(event) {
|
|
1201
1214
|
event.preventDefault();
|
|
1215
|
+
const panelGroupElement = panelGroupElementRef.current;
|
|
1216
|
+
if (!panelGroupElement) {
|
|
1217
|
+
return () => null;
|
|
1218
|
+
}
|
|
1202
1219
|
const {
|
|
1203
1220
|
direction,
|
|
1204
1221
|
dragState,
|
|
@@ -1213,8 +1230,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1213
1230
|
const {
|
|
1214
1231
|
initialLayout
|
|
1215
1232
|
} = dragState !== null && dragState !== void 0 ? dragState : {};
|
|
1216
|
-
const pivotIndices = determinePivotIndices(groupId, dragHandleId);
|
|
1217
|
-
let delta = calculateDeltaPercentage(event, dragHandleId, direction, dragState, keyboardResizeBy);
|
|
1233
|
+
const pivotIndices = determinePivotIndices(groupId, dragHandleId, panelGroupElement);
|
|
1234
|
+
let delta = calculateDeltaPercentage(event, dragHandleId, direction, dragState, keyboardResizeBy, panelGroupElement);
|
|
1218
1235
|
if (delta === 0) {
|
|
1219
1236
|
return;
|
|
1220
1237
|
}
|
|
@@ -1309,7 +1326,10 @@ function PanelGroupWithForwardedRef({
|
|
|
1309
1326
|
const {
|
|
1310
1327
|
layout
|
|
1311
1328
|
} = eagerValuesRef.current;
|
|
1312
|
-
|
|
1329
|
+
if (!panelGroupElementRef.current) {
|
|
1330
|
+
return;
|
|
1331
|
+
}
|
|
1332
|
+
const handleElement = getResizeHandleElement(dragHandleId, panelGroupElementRef.current);
|
|
1313
1333
|
assert(handleElement);
|
|
1314
1334
|
const initialCursorPosition = getResizeEventCursorPosition(direction, event);
|
|
1315
1335
|
setDragState({
|
|
@@ -1354,7 +1374,8 @@ function PanelGroupWithForwardedRef({
|
|
|
1354
1374
|
resizePanel,
|
|
1355
1375
|
startDragging,
|
|
1356
1376
|
stopDragging,
|
|
1357
|
-
unregisterPanel
|
|
1377
|
+
unregisterPanel,
|
|
1378
|
+
panelGroupElement: panelGroupElementRef.current
|
|
1358
1379
|
}), [collapsePanel, dragState, direction, expandPanel, getPanelSize, getPanelStyle, groupId, isPanelCollapsed, isPanelExpanded, registerPanel, registerResizeHandle, resizePanel, startDragging, stopDragging, unregisterPanel]);
|
|
1359
1380
|
const style = {
|
|
1360
1381
|
display: "flex",
|
|
@@ -1373,6 +1394,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1373
1394
|
...style,
|
|
1374
1395
|
...styleFromProps
|
|
1375
1396
|
},
|
|
1397
|
+
ref: panelGroupElementRef,
|
|
1376
1398
|
// CSS selectors
|
|
1377
1399
|
"data-panel-group": "",
|
|
1378
1400
|
"data-panel-group-direction": direction,
|
|
@@ -1407,13 +1429,14 @@ function panelDataHelper(panelDataArray, panelData, layout) {
|
|
|
1407
1429
|
function useWindowSplitterResizeHandlerBehavior({
|
|
1408
1430
|
disabled,
|
|
1409
1431
|
handleId,
|
|
1410
|
-
resizeHandler
|
|
1432
|
+
resizeHandler,
|
|
1433
|
+
panelGroupElement
|
|
1411
1434
|
}) {
|
|
1412
1435
|
useEffect(() => {
|
|
1413
|
-
if (disabled || resizeHandler == null) {
|
|
1436
|
+
if (disabled || resizeHandler == null || panelGroupElement == null) {
|
|
1414
1437
|
return;
|
|
1415
1438
|
}
|
|
1416
|
-
const handleElement = getResizeHandleElement(handleId);
|
|
1439
|
+
const handleElement = getResizeHandleElement(handleId, panelGroupElement);
|
|
1417
1440
|
if (handleElement == null) {
|
|
1418
1441
|
return;
|
|
1419
1442
|
}
|
|
@@ -1438,8 +1461,8 @@ function useWindowSplitterResizeHandlerBehavior({
|
|
|
1438
1461
|
event.preventDefault();
|
|
1439
1462
|
const groupId = handleElement.getAttribute("data-panel-group-id");
|
|
1440
1463
|
assert(groupId);
|
|
1441
|
-
const handles = getResizeHandleElementsForGroup(groupId);
|
|
1442
|
-
const index = getResizeHandleElementIndex(groupId, handleId);
|
|
1464
|
+
const handles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
|
|
1465
|
+
const index = getResizeHandleElementIndex(groupId, handleId, panelGroupElement);
|
|
1443
1466
|
assert(index !== null);
|
|
1444
1467
|
const nextIndex = event.shiftKey ? index > 0 ? index - 1 : handles.length - 1 : index + 1 < handles.length ? index + 1 : 0;
|
|
1445
1468
|
const nextHandle = handles[nextIndex];
|
|
@@ -1452,7 +1475,7 @@ function useWindowSplitterResizeHandlerBehavior({
|
|
|
1452
1475
|
return () => {
|
|
1453
1476
|
handleElement.removeEventListener("keydown", onKeyDown);
|
|
1454
1477
|
};
|
|
1455
|
-
}, [disabled, handleId, resizeHandler]);
|
|
1478
|
+
}, [panelGroupElement, disabled, handleId, resizeHandler]);
|
|
1456
1479
|
}
|
|
1457
1480
|
|
|
1458
1481
|
function PanelResizeHandle({
|
|
@@ -1485,7 +1508,8 @@ function PanelResizeHandle({
|
|
|
1485
1508
|
groupId,
|
|
1486
1509
|
registerResizeHandle,
|
|
1487
1510
|
startDragging,
|
|
1488
|
-
stopDragging
|
|
1511
|
+
stopDragging,
|
|
1512
|
+
panelGroupElement
|
|
1489
1513
|
} = panelGroupContext;
|
|
1490
1514
|
const resizeHandleId = useUniqueId(idFromProps);
|
|
1491
1515
|
const isDragging = (dragState === null || dragState === void 0 ? void 0 : dragState.dragHandleId) === resizeHandleId;
|
|
@@ -1544,7 +1568,8 @@ function PanelResizeHandle({
|
|
|
1544
1568
|
useWindowSplitterResizeHandlerBehavior({
|
|
1545
1569
|
disabled,
|
|
1546
1570
|
handleId: resizeHandleId,
|
|
1547
|
-
resizeHandler
|
|
1571
|
+
resizeHandler,
|
|
1572
|
+
panelGroupElement
|
|
1548
1573
|
});
|
|
1549
1574
|
const style = {
|
|
1550
1575
|
cursor: getCursorStyle(direction),
|
|
@@ -1600,13 +1625,12 @@ function PanelResizeHandle({
|
|
|
1600
1625
|
}
|
|
1601
1626
|
PanelResizeHandle.displayName = "PanelResizeHandle";
|
|
1602
1627
|
|
|
1603
|
-
function calculateAvailablePanelSizeInPixels(groupId) {
|
|
1604
|
-
const panelGroupElement = getPanelGroupElement(groupId);
|
|
1628
|
+
function calculateAvailablePanelSizeInPixels(groupId, panelGroupElement) {
|
|
1605
1629
|
if (panelGroupElement == null) {
|
|
1606
1630
|
return NaN;
|
|
1607
1631
|
}
|
|
1608
1632
|
const direction = panelGroupElement.getAttribute("data-panel-group-direction");
|
|
1609
|
-
const resizeHandles = getResizeHandleElementsForGroup(groupId);
|
|
1633
|
+
const resizeHandles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
|
|
1610
1634
|
if (direction === "horizontal") {
|
|
1611
1635
|
return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
|
|
1612
1636
|
return accumulated + handle.offsetWidth;
|
|
@@ -1618,13 +1642,9 @@ function calculateAvailablePanelSizeInPixels(groupId) {
|
|
|
1618
1642
|
}
|
|
1619
1643
|
}
|
|
1620
1644
|
|
|
1621
|
-
function getAvailableGroupSizePixels(groupId) {
|
|
1622
|
-
const panelGroupElement = getPanelGroupElement(groupId);
|
|
1623
|
-
if (panelGroupElement == null) {
|
|
1624
|
-
return NaN;
|
|
1625
|
-
}
|
|
1645
|
+
function getAvailableGroupSizePixels(groupId, panelGroupElement) {
|
|
1626
1646
|
const direction = panelGroupElement.getAttribute("data-panel-group-direction");
|
|
1627
|
-
const resizeHandles = getResizeHandleElementsForGroup(groupId);
|
|
1647
|
+
const resizeHandles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
|
|
1628
1648
|
if (direction === "horizontal") {
|
|
1629
1649
|
return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
|
|
1630
1650
|
return accumulated + handle.offsetWidth;
|
|
@@ -1636,16 +1656,16 @@ function getAvailableGroupSizePixels(groupId) {
|
|
|
1636
1656
|
}
|
|
1637
1657
|
}
|
|
1638
1658
|
|
|
1639
|
-
function getPanelElement(id) {
|
|
1640
|
-
const element =
|
|
1659
|
+
function getPanelElement(id, panelGroupElement) {
|
|
1660
|
+
const element = panelGroupElement.querySelector(`[data-panel-id="${id}"]`);
|
|
1641
1661
|
if (element) {
|
|
1642
1662
|
return element;
|
|
1643
1663
|
}
|
|
1644
1664
|
return null;
|
|
1645
1665
|
}
|
|
1646
1666
|
|
|
1647
|
-
function getPanelElementsForGroup(groupId) {
|
|
1648
|
-
return Array.from(
|
|
1667
|
+
function getPanelElementsForGroup(groupId, panelGroupElement) {
|
|
1668
|
+
return Array.from(panelGroupElement.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
1649
1669
|
}
|
|
1650
1670
|
|
|
1651
1671
|
export { Panel, PanelGroup, PanelResizeHandle, assert, calculateAvailablePanelSizeInPixels, getAvailableGroupSizePixels, getPanelElement, getPanelElementsForGroup, getPanelGroupElement, getResizeHandleElement, getResizeHandleElementIndex, getResizeHandleElementsForGroup, getResizeHandlePanelIds };
|
package/package.json
CHANGED
package/src/Panel.test.tsx
CHANGED
|
@@ -12,6 +12,7 @@ import { createRef } from "./vendor/react";
|
|
|
12
12
|
describe("PanelGroup", () => {
|
|
13
13
|
let expectedWarnings: string[] = [];
|
|
14
14
|
let root: Root;
|
|
15
|
+
let container: HTMLElement;
|
|
15
16
|
let uninstallMockOffsetWidthAndHeight: () => void;
|
|
16
17
|
|
|
17
18
|
function expectWarning(expectedMessage: string) {
|
|
@@ -24,7 +25,7 @@ describe("PanelGroup", () => {
|
|
|
24
25
|
|
|
25
26
|
uninstallMockOffsetWidthAndHeight = mockPanelGroupOffsetWidthAndHeight();
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
container = document.createElement("div");
|
|
28
29
|
document.body.appendChild(container);
|
|
29
30
|
|
|
30
31
|
expectedWarnings = [];
|
|
@@ -258,7 +259,7 @@ describe("PanelGroup", () => {
|
|
|
258
259
|
);
|
|
259
260
|
});
|
|
260
261
|
|
|
261
|
-
const element = getPanelElement("panel");
|
|
262
|
+
const element = getPanelElement("panel", container);
|
|
262
263
|
assert(element);
|
|
263
264
|
expect(element.tabIndex).toBe(123);
|
|
264
265
|
expect(element.getAttribute("data-test-name")).toBe("foo");
|
package/src/Panel.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
ForwardedRef,
|
|
8
8
|
HTMLAttributes,
|
|
9
9
|
PropsWithChildren,
|
|
10
|
-
|
|
10
|
+
ReactElement,
|
|
11
11
|
createElement,
|
|
12
12
|
forwardRef,
|
|
13
13
|
useContext,
|
|
@@ -93,7 +93,7 @@ export function PanelWithForwardedRef({
|
|
|
93
93
|
...rest
|
|
94
94
|
}: PanelProps & {
|
|
95
95
|
forwardedRef: ForwardedRef<ImperativePanelHandle>;
|
|
96
|
-
}):
|
|
96
|
+
}): ReactElement {
|
|
97
97
|
const context = useContext(PanelGroupContext);
|
|
98
98
|
if (context === null) {
|
|
99
99
|
throw Error(
|
package/src/PanelGroup.test.tsx
CHANGED
|
@@ -15,6 +15,7 @@ import { createRef } from "./vendor/react";
|
|
|
15
15
|
describe("PanelGroup", () => {
|
|
16
16
|
let expectedWarnings: string[] = [];
|
|
17
17
|
let root: Root;
|
|
18
|
+
let container: HTMLElement;
|
|
18
19
|
let uninstallMockOffsetWidthAndHeight: () => void;
|
|
19
20
|
|
|
20
21
|
function expectWarning(expectedMessage: string) {
|
|
@@ -28,7 +29,7 @@ describe("PanelGroup", () => {
|
|
|
28
29
|
// JSDom doesn't support element sizes
|
|
29
30
|
uninstallMockOffsetWidthAndHeight = mockPanelGroupOffsetWidthAndHeight();
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
container = document.createElement("div");
|
|
32
33
|
document.body.appendChild(container);
|
|
33
34
|
|
|
34
35
|
expectedWarnings = [];
|
|
@@ -124,7 +125,7 @@ describe("PanelGroup", () => {
|
|
|
124
125
|
);
|
|
125
126
|
});
|
|
126
127
|
|
|
127
|
-
const element = getPanelGroupElement("group");
|
|
128
|
+
const element = getPanelGroupElement("group", container);
|
|
128
129
|
assert(element);
|
|
129
130
|
expect(element.tabIndex).toBe(123);
|
|
130
131
|
expect(element.getAttribute("data-test-name")).toBe("foo");
|
package/src/PanelGroup.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { isDevelopment } from "#is-development";
|
|
2
2
|
import { PanelData } from "./Panel";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
DragState,
|
|
5
|
+
PanelGroupContext,
|
|
6
|
+
ResizeEvent,
|
|
7
|
+
TPanelGroupContext,
|
|
8
|
+
} from "./PanelGroupContext";
|
|
4
9
|
import useIsomorphicLayoutEffect from "./hooks/useIsomorphicEffect";
|
|
5
10
|
import useUniqueId from "./hooks/useUniqueId";
|
|
6
11
|
import { useWindowSplitterPanelGroupBehavior } from "./hooks/useWindowSplitterPanelGroupBehavior";
|
|
@@ -31,7 +36,7 @@ import {
|
|
|
31
36
|
ForwardedRef,
|
|
32
37
|
HTMLAttributes,
|
|
33
38
|
PropsWithChildren,
|
|
34
|
-
|
|
39
|
+
ReactElement,
|
|
35
40
|
createElement,
|
|
36
41
|
forwardRef,
|
|
37
42
|
useCallback,
|
|
@@ -103,9 +108,9 @@ function PanelGroupWithForwardedRef({
|
|
|
103
108
|
...rest
|
|
104
109
|
}: PanelGroupProps & {
|
|
105
110
|
forwardedRef: ForwardedRef<ImperativePanelGroupHandle>;
|
|
106
|
-
}):
|
|
111
|
+
}): ReactElement {
|
|
107
112
|
const groupId = useUniqueId(idFromProps);
|
|
108
|
-
|
|
113
|
+
const panelGroupElementRef = useRef<HTMLDivElement | null>(null);
|
|
109
114
|
const [dragState, setDragState] = useState<DragState | null>(null);
|
|
110
115
|
const [layout, setLayout] = useState<number[]>([]);
|
|
111
116
|
|
|
@@ -207,6 +212,7 @@ function PanelGroupWithForwardedRef({
|
|
|
207
212
|
layout,
|
|
208
213
|
panelDataArray: eagerValuesRef.current.panelDataArray,
|
|
209
214
|
setLayout,
|
|
215
|
+
panelGroupElement: panelGroupElementRef.current,
|
|
210
216
|
});
|
|
211
217
|
|
|
212
218
|
useEffect(() => {
|
|
@@ -561,7 +567,10 @@ function PanelGroupWithForwardedRef({
|
|
|
561
567
|
const registerResizeHandle = useCallback((dragHandleId: string) => {
|
|
562
568
|
return function resizeHandler(event: ResizeEvent) {
|
|
563
569
|
event.preventDefault();
|
|
564
|
-
|
|
570
|
+
const panelGroupElement = panelGroupElementRef.current;
|
|
571
|
+
if (!panelGroupElement) {
|
|
572
|
+
return () => null;
|
|
573
|
+
}
|
|
565
574
|
const {
|
|
566
575
|
direction,
|
|
567
576
|
dragState,
|
|
@@ -573,14 +582,19 @@ function PanelGroupWithForwardedRef({
|
|
|
573
582
|
|
|
574
583
|
const { initialLayout } = dragState ?? {};
|
|
575
584
|
|
|
576
|
-
const pivotIndices = determinePivotIndices(
|
|
585
|
+
const pivotIndices = determinePivotIndices(
|
|
586
|
+
groupId,
|
|
587
|
+
dragHandleId,
|
|
588
|
+
panelGroupElement
|
|
589
|
+
);
|
|
577
590
|
|
|
578
591
|
let delta = calculateDeltaPercentage(
|
|
579
592
|
event,
|
|
580
593
|
dragHandleId,
|
|
581
594
|
direction,
|
|
582
595
|
dragState,
|
|
583
|
-
keyboardResizeBy
|
|
596
|
+
keyboardResizeBy,
|
|
597
|
+
panelGroupElement
|
|
584
598
|
);
|
|
585
599
|
if (delta === 0) {
|
|
586
600
|
return;
|
|
@@ -709,8 +723,13 @@ function PanelGroupWithForwardedRef({
|
|
|
709
723
|
(dragHandleId: string, event: ResizeEvent) => {
|
|
710
724
|
const { direction } = committedValuesRef.current;
|
|
711
725
|
const { layout } = eagerValuesRef.current;
|
|
712
|
-
|
|
713
|
-
|
|
726
|
+
if (!panelGroupElementRef.current) {
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
const handleElement = getResizeHandleElement(
|
|
730
|
+
dragHandleId,
|
|
731
|
+
panelGroupElementRef.current
|
|
732
|
+
);
|
|
714
733
|
assert(handleElement);
|
|
715
734
|
|
|
716
735
|
const initialCursorPosition = getResizeEventCursorPosition(
|
|
@@ -751,23 +770,25 @@ function PanelGroupWithForwardedRef({
|
|
|
751
770
|
}, []);
|
|
752
771
|
|
|
753
772
|
const context = useMemo(
|
|
754
|
-
() =>
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
773
|
+
() =>
|
|
774
|
+
({
|
|
775
|
+
collapsePanel,
|
|
776
|
+
direction,
|
|
777
|
+
dragState,
|
|
778
|
+
expandPanel,
|
|
779
|
+
getPanelSize,
|
|
780
|
+
getPanelStyle,
|
|
781
|
+
groupId,
|
|
782
|
+
isPanelCollapsed,
|
|
783
|
+
isPanelExpanded,
|
|
784
|
+
registerPanel,
|
|
785
|
+
registerResizeHandle,
|
|
786
|
+
resizePanel,
|
|
787
|
+
startDragging,
|
|
788
|
+
stopDragging,
|
|
789
|
+
unregisterPanel,
|
|
790
|
+
panelGroupElement: panelGroupElementRef.current,
|
|
791
|
+
}) satisfies TPanelGroupContext,
|
|
771
792
|
[
|
|
772
793
|
collapsePanel,
|
|
773
794
|
dragState,
|
|
@@ -800,14 +821,13 @@ function PanelGroupWithForwardedRef({
|
|
|
800
821
|
{ value: context },
|
|
801
822
|
createElement(Type, {
|
|
802
823
|
...rest,
|
|
803
|
-
|
|
804
824
|
children,
|
|
805
825
|
className: classNameFromProps,
|
|
806
826
|
style: {
|
|
807
827
|
...style,
|
|
808
828
|
...styleFromProps,
|
|
809
829
|
},
|
|
810
|
-
|
|
830
|
+
ref: panelGroupElementRef,
|
|
811
831
|
// CSS selectors
|
|
812
832
|
"data-panel-group": "",
|
|
813
833
|
"data-panel-group-direction": direction,
|
package/src/PanelGroupContext.ts
CHANGED
|
@@ -11,7 +11,7 @@ export type DragState = {
|
|
|
11
11
|
initialLayout: number[];
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
export
|
|
14
|
+
export type TPanelGroupContext = {
|
|
15
15
|
collapsePanel: (panelData: PanelData) => void;
|
|
16
16
|
direction: "horizontal" | "vertical";
|
|
17
17
|
dragState: DragState | null;
|
|
@@ -30,6 +30,8 @@ export const PanelGroupContext = createContext<{
|
|
|
30
30
|
startDragging: (dragHandleId: string, event: ResizeEvent) => void;
|
|
31
31
|
stopDragging: () => void;
|
|
32
32
|
unregisterPanel: (panelData: PanelData) => void;
|
|
33
|
-
|
|
33
|
+
panelGroupElement: ParentNode | null;
|
|
34
|
+
};
|
|
35
|
+
export const PanelGroupContext = createContext<TPanelGroupContext | null>(null);
|
|
34
36
|
|
|
35
37
|
PanelGroupContext.displayName = "PanelGroupContext";
|
|
@@ -7,12 +7,12 @@ import { getResizeHandleElement } from "./utils/dom/getResizeHandleElement";
|
|
|
7
7
|
describe("PanelResizeHandle", () => {
|
|
8
8
|
let expectedWarnings: string[] = [];
|
|
9
9
|
let root: Root;
|
|
10
|
+
let container: HTMLElement;
|
|
10
11
|
|
|
11
12
|
beforeEach(() => {
|
|
12
13
|
// @ts-expect-error
|
|
13
14
|
global.IS_REACT_ACT_ENVIRONMENT = true;
|
|
14
|
-
|
|
15
|
-
const container = document.createElement("div");
|
|
15
|
+
container = document.createElement("div");
|
|
16
16
|
document.body.appendChild(container);
|
|
17
17
|
|
|
18
18
|
expectedWarnings = [];
|
|
@@ -59,7 +59,7 @@ describe("PanelResizeHandle", () => {
|
|
|
59
59
|
);
|
|
60
60
|
});
|
|
61
61
|
|
|
62
|
-
const element = getResizeHandleElement("handle");
|
|
62
|
+
const element = getResizeHandleElement("handle", container);
|
|
63
63
|
assert(element);
|
|
64
64
|
expect(element.tabIndex).toBe(123);
|
|
65
65
|
expect(element.getAttribute("data-test-name")).toBe("foo");
|
package/src/PanelResizeHandle.ts
CHANGED
|
@@ -4,8 +4,8 @@ import {
|
|
|
4
4
|
CSSProperties,
|
|
5
5
|
HTMLAttributes,
|
|
6
6
|
PropsWithChildren,
|
|
7
|
+
ReactElement,
|
|
7
8
|
MouseEvent as ReactMouseEvent,
|
|
8
|
-
ReactNode,
|
|
9
9
|
TouchEvent,
|
|
10
10
|
useCallback,
|
|
11
11
|
useContext,
|
|
@@ -49,7 +49,7 @@ export function PanelResizeHandle({
|
|
|
49
49
|
tabIndex = 0,
|
|
50
50
|
tagName: Type = "div",
|
|
51
51
|
...rest
|
|
52
|
-
}: PanelResizeHandleProps):
|
|
52
|
+
}: PanelResizeHandleProps): ReactElement {
|
|
53
53
|
const elementRef = useRef<HTMLElement>(null);
|
|
54
54
|
|
|
55
55
|
// Use a ref to guard against users passing inline props
|
|
@@ -74,6 +74,7 @@ export function PanelResizeHandle({
|
|
|
74
74
|
registerResizeHandle,
|
|
75
75
|
startDragging,
|
|
76
76
|
stopDragging,
|
|
77
|
+
panelGroupElement,
|
|
77
78
|
} = panelGroupContext;
|
|
78
79
|
|
|
79
80
|
const resizeHandleId = useUniqueId(idFromProps);
|
|
@@ -151,6 +152,7 @@ export function PanelResizeHandle({
|
|
|
151
152
|
disabled,
|
|
152
153
|
handleId: resizeHandleId,
|
|
153
154
|
resizeHandler,
|
|
155
|
+
panelGroupElement,
|
|
154
156
|
});
|
|
155
157
|
|
|
156
158
|
const style: CSSProperties = {
|
|
@@ -11,17 +11,19 @@ export function useWindowSplitterResizeHandlerBehavior({
|
|
|
11
11
|
disabled,
|
|
12
12
|
handleId,
|
|
13
13
|
resizeHandler,
|
|
14
|
+
panelGroupElement,
|
|
14
15
|
}: {
|
|
15
16
|
disabled: boolean;
|
|
16
17
|
handleId: string;
|
|
17
18
|
resizeHandler: ResizeHandler | null;
|
|
19
|
+
panelGroupElement: ParentNode | null;
|
|
18
20
|
}): void {
|
|
19
21
|
useEffect(() => {
|
|
20
|
-
if (disabled || resizeHandler == null) {
|
|
22
|
+
if (disabled || resizeHandler == null || panelGroupElement == null) {
|
|
21
23
|
return;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
const handleElement = getResizeHandleElement(handleId);
|
|
26
|
+
const handleElement = getResizeHandleElement(handleId, panelGroupElement);
|
|
25
27
|
if (handleElement == null) {
|
|
26
28
|
return;
|
|
27
29
|
}
|
|
@@ -49,8 +51,15 @@ export function useWindowSplitterResizeHandlerBehavior({
|
|
|
49
51
|
const groupId = handleElement.getAttribute("data-panel-group-id");
|
|
50
52
|
assert(groupId);
|
|
51
53
|
|
|
52
|
-
const handles = getResizeHandleElementsForGroup(
|
|
53
|
-
|
|
54
|
+
const handles = getResizeHandleElementsForGroup(
|
|
55
|
+
groupId,
|
|
56
|
+
panelGroupElement
|
|
57
|
+
);
|
|
58
|
+
const index = getResizeHandleElementIndex(
|
|
59
|
+
groupId,
|
|
60
|
+
handleId,
|
|
61
|
+
panelGroupElement
|
|
62
|
+
);
|
|
54
63
|
|
|
55
64
|
assert(index !== null);
|
|
56
65
|
|
|
@@ -74,5 +83,5 @@ export function useWindowSplitterResizeHandlerBehavior({
|
|
|
74
83
|
return () => {
|
|
75
84
|
handleElement.removeEventListener("keydown", onKeyDown);
|
|
76
85
|
};
|
|
77
|
-
}, [disabled, handleId, resizeHandler]);
|
|
86
|
+
}, [panelGroupElement, disabled, handleId, resizeHandler]);
|
|
78
87
|
}
|