react-resizable-panels 1.0.8 → 1.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.
- package/CHANGELOG.md +9 -0
- package/README.md +16 -15
- package/dist/declarations/src/index.d.ts +1 -3
- 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/react-resizable-panels.browser.cjs.js +56 -51
- package/dist/react-resizable-panels.browser.cjs.mjs +0 -2
- package/dist/react-resizable-panels.browser.development.cjs.js +56 -51
- package/dist/react-resizable-panels.browser.development.cjs.mjs +0 -2
- package/dist/react-resizable-panels.browser.development.esm.js +57 -50
- package/dist/react-resizable-panels.browser.esm.js +57 -50
- package/dist/react-resizable-panels.cjs.js +56 -51
- package/dist/react-resizable-panels.cjs.mjs +0 -2
- package/dist/react-resizable-panels.development.cjs.js +56 -51
- package/dist/react-resizable-panels.development.cjs.mjs +0 -2
- package/dist/react-resizable-panels.development.esm.js +57 -50
- package/dist/react-resizable-panels.development.node.cjs.js +47 -51
- package/dist/react-resizable-panels.development.node.cjs.mjs +0 -2
- package/dist/react-resizable-panels.development.node.esm.js +48 -50
- package/dist/react-resizable-panels.esm.js +57 -50
- package/dist/react-resizable-panels.node.cjs.js +47 -51
- package/dist/react-resizable-panels.node.cjs.mjs +0 -2
- package/dist/react-resizable-panels.node.esm.js +48 -50
- package/package.json +1 -1
- package/src/Panel.test.tsx +186 -0
- package/src/Panel.ts +14 -0
- package/src/PanelGroup.ts +46 -7
- package/src/PanelGroupContext.ts +5 -1
- package/src/index.ts +0 -4
- package/src/utils/dom/getPanelElement.ts +2 -2
- package/src/utils/dom/getPanelElementsForGroup.ts +2 -4
- package/src/utils/dom/getPanelGroupElement.ts +1 -1
- package/src/utils/dom/getResizeHandleElement.ts +2 -4
- package/src/utils/dom/getResizeHandleElementIndex.ts +2 -2
- package/src/utils/dom/getResizeHandleElementsForGroup.ts +2 -2
- package/src/utils/dom/getResizeHandlePanelIds.ts +3 -3
- package/dist/declarations/src/utils/dom/calculateAvailablePanelSizeInPixels.d.ts +0 -1
- package/dist/declarations/src/utils/dom/getAvailableGroupSizePixels.d.ts +0 -1
- package/src/utils/dom/calculateAvailablePanelSizeInPixels.ts +0 -34
- package/src/utils/dom/getAvailableGroupSizePixels.ts +0 -30
|
@@ -65,6 +65,7 @@ function PanelWithForwardedRef({
|
|
|
65
65
|
getPanelStyle,
|
|
66
66
|
groupId,
|
|
67
67
|
isPanelCollapsed,
|
|
68
|
+
reevaluatePanelConstraints,
|
|
68
69
|
registerPanel,
|
|
69
70
|
resizePanel,
|
|
70
71
|
unregisterPanel
|
|
@@ -430,12 +431,12 @@ function adjustLayoutByDelta({
|
|
|
430
431
|
return nextLayout;
|
|
431
432
|
}
|
|
432
433
|
|
|
433
|
-
function getResizeHandleElementsForGroup(groupId,
|
|
434
|
-
return Array.from(
|
|
434
|
+
function getResizeHandleElementsForGroup(groupId, scope = document) {
|
|
435
|
+
return Array.from(scope.querySelectorAll(`[data-panel-resize-handle-id][data-panel-group-id="${groupId}"]`));
|
|
435
436
|
}
|
|
436
437
|
|
|
437
|
-
function getResizeHandleElementIndex(groupId, id,
|
|
438
|
-
const handles = getResizeHandleElementsForGroup(groupId,
|
|
438
|
+
function getResizeHandleElementIndex(groupId, id, scope = document) {
|
|
439
|
+
const handles = getResizeHandleElementsForGroup(groupId, scope);
|
|
439
440
|
const index = handles.findIndex(handle => handle.getAttribute("data-panel-resize-handle-id") === id);
|
|
440
441
|
return index !== null && index !== void 0 ? index : null;
|
|
441
442
|
}
|
|
@@ -445,7 +446,7 @@ function determinePivotIndices(groupId, dragHandleId, panelGroupElement) {
|
|
|
445
446
|
return index != null ? [index, index + 1] : [-1, -1];
|
|
446
447
|
}
|
|
447
448
|
|
|
448
|
-
function getPanelGroupElement(id, rootElement) {
|
|
449
|
+
function getPanelGroupElement(id, rootElement = document) {
|
|
449
450
|
var _dataset;
|
|
450
451
|
//If the root element is the PanelGroup
|
|
451
452
|
if (rootElement instanceof HTMLElement && (rootElement === null || rootElement === void 0 ? void 0 : (_dataset = rootElement.dataset) === null || _dataset === void 0 ? void 0 : _dataset.panelGroupId) == id) {
|
|
@@ -460,18 +461,18 @@ function getPanelGroupElement(id, rootElement) {
|
|
|
460
461
|
return null;
|
|
461
462
|
}
|
|
462
463
|
|
|
463
|
-
function getResizeHandleElement(id,
|
|
464
|
-
const element =
|
|
464
|
+
function getResizeHandleElement(id, scope = document) {
|
|
465
|
+
const element = scope.querySelector(`[data-panel-resize-handle-id="${id}"]`);
|
|
465
466
|
if (element) {
|
|
466
467
|
return element;
|
|
467
468
|
}
|
|
468
469
|
return null;
|
|
469
470
|
}
|
|
470
471
|
|
|
471
|
-
function getResizeHandlePanelIds(groupId, handleId, panelsArray,
|
|
472
|
+
function getResizeHandlePanelIds(groupId, handleId, panelsArray, scope = document) {
|
|
472
473
|
var _panelsArray$index$id, _panelsArray$index, _panelsArray$id, _panelsArray;
|
|
473
|
-
const handle = getResizeHandleElement(handleId,
|
|
474
|
-
const handles = getResizeHandleElementsForGroup(groupId,
|
|
474
|
+
const handle = getResizeHandleElement(handleId, scope);
|
|
475
|
+
const handles = getResizeHandleElementsForGroup(groupId, scope);
|
|
475
476
|
const index = handle ? handles.indexOf(handle) : -1;
|
|
476
477
|
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;
|
|
477
478
|
const idAfter = (_panelsArray$id = (_panelsArray = panelsArray[index + 1]) === null || _panelsArray === void 0 ? void 0 : _panelsArray.id) !== null && _panelsArray$id !== void 0 ? _panelsArray$id : null;
|
|
@@ -1319,6 +1320,35 @@ function PanelGroupWithForwardedRef({
|
|
|
1319
1320
|
callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
|
|
1320
1321
|
}
|
|
1321
1322
|
}, []);
|
|
1323
|
+
const reevaluatePanelConstraints = useCallback((panelData, prevConstraints) => {
|
|
1324
|
+
const {
|
|
1325
|
+
layout,
|
|
1326
|
+
panelDataArray
|
|
1327
|
+
} = eagerValuesRef.current;
|
|
1328
|
+
const {
|
|
1329
|
+
collapsedSize: prevCollapsedSize = 0,
|
|
1330
|
+
collapsible: prevCollapsible
|
|
1331
|
+
} = prevConstraints;
|
|
1332
|
+
const {
|
|
1333
|
+
collapsedSize: nextCollapsedSize = 0,
|
|
1334
|
+
collapsible: nextCollapsible,
|
|
1335
|
+
maxSize: nextMaxSize = 100,
|
|
1336
|
+
minSize: nextMinSize = 0
|
|
1337
|
+
} = panelData.constraints;
|
|
1338
|
+
const {
|
|
1339
|
+
panelSize: prevPanelSize
|
|
1340
|
+
} = panelDataHelper(panelDataArray, panelData, layout);
|
|
1341
|
+
assert(prevPanelSize != null);
|
|
1342
|
+
if (prevCollapsible && nextCollapsible && prevPanelSize === prevCollapsedSize) {
|
|
1343
|
+
if (prevCollapsedSize !== nextCollapsedSize) {
|
|
1344
|
+
resizePanel(panelData, nextCollapsedSize);
|
|
1345
|
+
}
|
|
1346
|
+
} else if (prevPanelSize < nextMinSize) {
|
|
1347
|
+
resizePanel(panelData, nextMinSize);
|
|
1348
|
+
} else if (prevPanelSize > nextMaxSize) {
|
|
1349
|
+
resizePanel(panelData, nextMaxSize);
|
|
1350
|
+
}
|
|
1351
|
+
}, [resizePanel]);
|
|
1322
1352
|
const startDragging = useCallback((dragHandleId, event) => {
|
|
1323
1353
|
const {
|
|
1324
1354
|
direction
|
|
@@ -1369,6 +1399,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1369
1399
|
groupId,
|
|
1370
1400
|
isPanelCollapsed,
|
|
1371
1401
|
isPanelExpanded,
|
|
1402
|
+
reevaluatePanelConstraints,
|
|
1372
1403
|
registerPanel,
|
|
1373
1404
|
registerResizeHandle,
|
|
1374
1405
|
resizePanel,
|
|
@@ -1376,7 +1407,7 @@ function PanelGroupWithForwardedRef({
|
|
|
1376
1407
|
stopDragging,
|
|
1377
1408
|
unregisterPanel,
|
|
1378
1409
|
panelGroupElement: panelGroupElementRef.current
|
|
1379
|
-
}), [collapsePanel, dragState, direction, expandPanel, getPanelSize, getPanelStyle, groupId, isPanelCollapsed, isPanelExpanded, registerPanel, registerResizeHandle, resizePanel, startDragging, stopDragging, unregisterPanel]);
|
|
1410
|
+
}), [collapsePanel, dragState, direction, expandPanel, getPanelSize, getPanelStyle, groupId, isPanelCollapsed, isPanelExpanded, reevaluatePanelConstraints, registerPanel, registerResizeHandle, resizePanel, startDragging, stopDragging, unregisterPanel]);
|
|
1380
1411
|
const style = {
|
|
1381
1412
|
display: "flex",
|
|
1382
1413
|
flexDirection: direction === "horizontal" ? "row" : "column",
|
|
@@ -1411,14 +1442,12 @@ function findPanelDataIndex(panelDataArray, panelData) {
|
|
|
1411
1442
|
return panelDataArray.findIndex(prevPanelData => prevPanelData === panelData || prevPanelData.id === panelData.id);
|
|
1412
1443
|
}
|
|
1413
1444
|
function panelDataHelper(panelDataArray, panelData, layout) {
|
|
1414
|
-
const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
|
|
1415
1445
|
const panelIndex = findPanelDataIndex(panelDataArray, panelData);
|
|
1416
|
-
const panelConstraints = panelConstraintsArray[panelIndex];
|
|
1417
1446
|
const isLastPanel = panelIndex === panelDataArray.length - 1;
|
|
1418
1447
|
const pivotIndices = isLastPanel ? [panelIndex - 1, panelIndex] : [panelIndex, panelIndex + 1];
|
|
1419
1448
|
const panelSize = layout[panelIndex];
|
|
1420
1449
|
return {
|
|
1421
|
-
...
|
|
1450
|
+
...panelData.constraints,
|
|
1422
1451
|
panelSize,
|
|
1423
1452
|
pivotIndices
|
|
1424
1453
|
};
|
|
@@ -1625,47 +1654,16 @@ function PanelResizeHandle({
|
|
|
1625
1654
|
}
|
|
1626
1655
|
PanelResizeHandle.displayName = "PanelResizeHandle";
|
|
1627
1656
|
|
|
1628
|
-
function
|
|
1629
|
-
|
|
1630
|
-
return NaN;
|
|
1631
|
-
}
|
|
1632
|
-
const direction = panelGroupElement.getAttribute("data-panel-group-direction");
|
|
1633
|
-
const resizeHandles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
|
|
1634
|
-
if (direction === "horizontal") {
|
|
1635
|
-
return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
|
|
1636
|
-
return accumulated + handle.offsetWidth;
|
|
1637
|
-
}, 0);
|
|
1638
|
-
} else {
|
|
1639
|
-
return panelGroupElement.offsetHeight - resizeHandles.reduce((accumulated, handle) => {
|
|
1640
|
-
return accumulated + handle.offsetHeight;
|
|
1641
|
-
}, 0);
|
|
1642
|
-
}
|
|
1643
|
-
}
|
|
1644
|
-
|
|
1645
|
-
function getAvailableGroupSizePixels(groupId, panelGroupElement) {
|
|
1646
|
-
const direction = panelGroupElement.getAttribute("data-panel-group-direction");
|
|
1647
|
-
const resizeHandles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
|
|
1648
|
-
if (direction === "horizontal") {
|
|
1649
|
-
return panelGroupElement.offsetWidth - resizeHandles.reduce((accumulated, handle) => {
|
|
1650
|
-
return accumulated + handle.offsetWidth;
|
|
1651
|
-
}, 0);
|
|
1652
|
-
} else {
|
|
1653
|
-
return panelGroupElement.offsetHeight - resizeHandles.reduce((accumulated, handle) => {
|
|
1654
|
-
return accumulated + handle.offsetHeight;
|
|
1655
|
-
}, 0);
|
|
1656
|
-
}
|
|
1657
|
-
}
|
|
1658
|
-
|
|
1659
|
-
function getPanelElement(id, panelGroupElement) {
|
|
1660
|
-
const element = panelGroupElement.querySelector(`[data-panel-id="${id}"]`);
|
|
1657
|
+
function getPanelElement(id, scope = document) {
|
|
1658
|
+
const element = scope.querySelector(`[data-panel-id="${id}"]`);
|
|
1661
1659
|
if (element) {
|
|
1662
1660
|
return element;
|
|
1663
1661
|
}
|
|
1664
1662
|
return null;
|
|
1665
1663
|
}
|
|
1666
1664
|
|
|
1667
|
-
function getPanelElementsForGroup(groupId,
|
|
1668
|
-
return Array.from(
|
|
1665
|
+
function getPanelElementsForGroup(groupId, scope = document) {
|
|
1666
|
+
return Array.from(scope.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
1669
1667
|
}
|
|
1670
1668
|
|
|
1671
|
-
export { Panel, PanelGroup, PanelResizeHandle, assert,
|
|
1669
|
+
export { Panel, PanelGroup, PanelResizeHandle, assert, getPanelElement, getPanelElementsForGroup, getPanelGroupElement, getResizeHandleElement, getResizeHandleElementIndex, getResizeHandleElementsForGroup, getResizeHandlePanelIds };
|
package/package.json
CHANGED
package/src/Panel.test.tsx
CHANGED
|
@@ -266,6 +266,192 @@ describe("PanelGroup", () => {
|
|
|
266
266
|
expect(element.title).toBe("bar");
|
|
267
267
|
});
|
|
268
268
|
|
|
269
|
+
describe("constraints", () => {
|
|
270
|
+
it("should resize a collapsed panel if the collapsedSize prop changes", () => {
|
|
271
|
+
act(() => {
|
|
272
|
+
root.render(
|
|
273
|
+
<PanelGroup direction="horizontal">
|
|
274
|
+
<Panel
|
|
275
|
+
id="left"
|
|
276
|
+
collapsedSize={10}
|
|
277
|
+
collapsible
|
|
278
|
+
defaultSize={10}
|
|
279
|
+
minSize={25}
|
|
280
|
+
/>
|
|
281
|
+
<PanelResizeHandle />
|
|
282
|
+
<Panel id="middle" />
|
|
283
|
+
<PanelResizeHandle />
|
|
284
|
+
<Panel
|
|
285
|
+
id="right"
|
|
286
|
+
collapsedSize={10}
|
|
287
|
+
collapsible
|
|
288
|
+
defaultSize={10}
|
|
289
|
+
minSize={25}
|
|
290
|
+
/>
|
|
291
|
+
</PanelGroup>
|
|
292
|
+
);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
let leftElement = getPanelElement("left", container);
|
|
296
|
+
let middleElement = getPanelElement("middle", container);
|
|
297
|
+
let rightElement = getPanelElement("right", container);
|
|
298
|
+
assert(leftElement);
|
|
299
|
+
assert(middleElement);
|
|
300
|
+
assert(rightElement);
|
|
301
|
+
expect(leftElement.getAttribute("data-panel-size")).toBe("10.0");
|
|
302
|
+
expect(middleElement.getAttribute("data-panel-size")).toBe("80.0");
|
|
303
|
+
expect(rightElement.getAttribute("data-panel-size")).toBe("10.0");
|
|
304
|
+
|
|
305
|
+
act(() => {
|
|
306
|
+
root.render(
|
|
307
|
+
<PanelGroup direction="horizontal">
|
|
308
|
+
<Panel id="left" collapsedSize={5} collapsible minSize={25} />
|
|
309
|
+
<PanelResizeHandle />
|
|
310
|
+
<Panel id="middle" />
|
|
311
|
+
<PanelResizeHandle />
|
|
312
|
+
<Panel id="right" collapsedSize={5} collapsible minSize={25} />
|
|
313
|
+
</PanelGroup>
|
|
314
|
+
);
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
expect(leftElement.getAttribute("data-panel-size")).toBe("5.0");
|
|
318
|
+
expect(middleElement.getAttribute("data-panel-size")).toBe("90.0");
|
|
319
|
+
expect(rightElement.getAttribute("data-panel-size")).toBe("5.0");
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
it("it should not expand a collapsed panel if other constraints change", () => {
|
|
323
|
+
act(() => {
|
|
324
|
+
root.render(
|
|
325
|
+
<PanelGroup direction="horizontal">
|
|
326
|
+
<Panel
|
|
327
|
+
id="left"
|
|
328
|
+
collapsedSize={10}
|
|
329
|
+
collapsible
|
|
330
|
+
defaultSize={10}
|
|
331
|
+
minSize={25}
|
|
332
|
+
/>
|
|
333
|
+
<PanelResizeHandle />
|
|
334
|
+
<Panel id="middle" />
|
|
335
|
+
<PanelResizeHandle />
|
|
336
|
+
<Panel
|
|
337
|
+
id="right"
|
|
338
|
+
collapsedSize={10}
|
|
339
|
+
collapsible
|
|
340
|
+
defaultSize={10}
|
|
341
|
+
minSize={25}
|
|
342
|
+
/>
|
|
343
|
+
</PanelGroup>
|
|
344
|
+
);
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
let leftElement = getPanelElement("left", container);
|
|
348
|
+
let middleElement = getPanelElement("middle", container);
|
|
349
|
+
let rightElement = getPanelElement("right", container);
|
|
350
|
+
assert(leftElement);
|
|
351
|
+
assert(middleElement);
|
|
352
|
+
assert(rightElement);
|
|
353
|
+
expect(leftElement.getAttribute("data-panel-size")).toBe("10.0");
|
|
354
|
+
expect(middleElement.getAttribute("data-panel-size")).toBe("80.0");
|
|
355
|
+
expect(rightElement.getAttribute("data-panel-size")).toBe("10.0");
|
|
356
|
+
|
|
357
|
+
act(() => {
|
|
358
|
+
root.render(
|
|
359
|
+
<PanelGroup direction="horizontal">
|
|
360
|
+
<Panel id="left" collapsedSize={10} collapsible minSize={20} />
|
|
361
|
+
<PanelResizeHandle />
|
|
362
|
+
<Panel id="middle" />
|
|
363
|
+
<PanelResizeHandle />
|
|
364
|
+
<Panel id="right" collapsedSize={10} collapsible minSize={20} />
|
|
365
|
+
</PanelGroup>
|
|
366
|
+
);
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
expect(leftElement.getAttribute("data-panel-size")).toBe("10.0");
|
|
370
|
+
expect(middleElement.getAttribute("data-panel-size")).toBe("80.0");
|
|
371
|
+
expect(rightElement.getAttribute("data-panel-size")).toBe("10.0");
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
it("should resize a panel if the minSize prop changes", () => {
|
|
375
|
+
act(() => {
|
|
376
|
+
root.render(
|
|
377
|
+
<PanelGroup direction="horizontal">
|
|
378
|
+
<Panel id="left" defaultSize={15} minSize={10} />
|
|
379
|
+
<PanelResizeHandle />
|
|
380
|
+
<Panel id="middle" />
|
|
381
|
+
<PanelResizeHandle />
|
|
382
|
+
<Panel id="right" defaultSize={15} minSize={10} />
|
|
383
|
+
</PanelGroup>
|
|
384
|
+
);
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
let leftElement = getPanelElement("left", container);
|
|
388
|
+
let middleElement = getPanelElement("middle", container);
|
|
389
|
+
let rightElement = getPanelElement("right", container);
|
|
390
|
+
assert(leftElement);
|
|
391
|
+
assert(middleElement);
|
|
392
|
+
assert(rightElement);
|
|
393
|
+
expect(leftElement.getAttribute("data-panel-size")).toBe("15.0");
|
|
394
|
+
expect(middleElement.getAttribute("data-panel-size")).toBe("70.0");
|
|
395
|
+
expect(rightElement.getAttribute("data-panel-size")).toBe("15.0");
|
|
396
|
+
|
|
397
|
+
act(() => {
|
|
398
|
+
root.render(
|
|
399
|
+
<PanelGroup direction="horizontal">
|
|
400
|
+
<Panel id="left" minSize={20} />
|
|
401
|
+
<PanelResizeHandle />
|
|
402
|
+
<Panel id="middle" />
|
|
403
|
+
<PanelResizeHandle />
|
|
404
|
+
<Panel id="right" minSize={20} />
|
|
405
|
+
</PanelGroup>
|
|
406
|
+
);
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
expect(leftElement.getAttribute("data-panel-size")).toBe("20.0");
|
|
410
|
+
expect(middleElement.getAttribute("data-panel-size")).toBe("60.0");
|
|
411
|
+
expect(rightElement.getAttribute("data-panel-size")).toBe("20.0");
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
it("should resize a panel if the maxSize prop changes", () => {
|
|
415
|
+
act(() => {
|
|
416
|
+
root.render(
|
|
417
|
+
<PanelGroup direction="horizontal">
|
|
418
|
+
<Panel id="left" defaultSize={25} maxSize={30} />
|
|
419
|
+
<PanelResizeHandle />
|
|
420
|
+
<Panel id="middle" />
|
|
421
|
+
<PanelResizeHandle />
|
|
422
|
+
<Panel id="right" defaultSize={25} maxSize={30} />
|
|
423
|
+
</PanelGroup>
|
|
424
|
+
);
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
let leftElement = getPanelElement("left", container);
|
|
428
|
+
let middleElement = getPanelElement("middle", container);
|
|
429
|
+
let rightElement = getPanelElement("right", container);
|
|
430
|
+
assert(leftElement);
|
|
431
|
+
assert(middleElement);
|
|
432
|
+
assert(rightElement);
|
|
433
|
+
expect(leftElement.getAttribute("data-panel-size")).toBe("25.0");
|
|
434
|
+
expect(middleElement.getAttribute("data-panel-size")).toBe("50.0");
|
|
435
|
+
expect(rightElement.getAttribute("data-panel-size")).toBe("25.0");
|
|
436
|
+
|
|
437
|
+
act(() => {
|
|
438
|
+
root.render(
|
|
439
|
+
<PanelGroup direction="horizontal">
|
|
440
|
+
<Panel id="left" maxSize={20} />
|
|
441
|
+
<PanelResizeHandle />
|
|
442
|
+
<Panel id="middle" />
|
|
443
|
+
<PanelResizeHandle />
|
|
444
|
+
<Panel id="right" maxSize={20} />
|
|
445
|
+
</PanelGroup>
|
|
446
|
+
);
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
expect(leftElement.getAttribute("data-panel-size")).toBe("20.0");
|
|
450
|
+
expect(middleElement.getAttribute("data-panel-size")).toBe("60.0");
|
|
451
|
+
expect(rightElement.getAttribute("data-panel-size")).toBe("20.0");
|
|
452
|
+
});
|
|
453
|
+
});
|
|
454
|
+
|
|
269
455
|
describe("callbacks", () => {
|
|
270
456
|
describe("onCollapse", () => {
|
|
271
457
|
it("should be called on mount if a panels initial size is 0", () => {
|
package/src/Panel.ts
CHANGED
|
@@ -108,6 +108,7 @@ export function PanelWithForwardedRef({
|
|
|
108
108
|
getPanelStyle,
|
|
109
109
|
groupId,
|
|
110
110
|
isPanelCollapsed,
|
|
111
|
+
reevaluatePanelConstraints,
|
|
111
112
|
registerPanel,
|
|
112
113
|
resizePanel,
|
|
113
114
|
unregisterPanel,
|
|
@@ -155,6 +156,8 @@ export function PanelWithForwardedRef({
|
|
|
155
156
|
useIsomorphicLayoutEffect(() => {
|
|
156
157
|
const { callbacks, constraints } = panelDataRef.current;
|
|
157
158
|
|
|
159
|
+
const prevConstraints = { ...constraints };
|
|
160
|
+
|
|
158
161
|
panelDataRef.current.id = panelId;
|
|
159
162
|
panelDataRef.current.idIsFromProps = idFromProps !== undefined;
|
|
160
163
|
panelDataRef.current.order = order;
|
|
@@ -168,6 +171,17 @@ export function PanelWithForwardedRef({
|
|
|
168
171
|
constraints.defaultSize = defaultSize;
|
|
169
172
|
constraints.maxSize = maxSize;
|
|
170
173
|
constraints.minSize = minSize;
|
|
174
|
+
|
|
175
|
+
// If constraints have changed, we should revisit panel sizes.
|
|
176
|
+
// This is uncommon but may happen if people are trying to implement pixel based constraints.
|
|
177
|
+
if (
|
|
178
|
+
prevConstraints.collapsedSize !== constraints.collapsedSize ||
|
|
179
|
+
prevConstraints.collapsible !== constraints.collapsible ||
|
|
180
|
+
prevConstraints.maxSize !== constraints.maxSize ||
|
|
181
|
+
prevConstraints.minSize !== constraints.minSize
|
|
182
|
+
) {
|
|
183
|
+
reevaluatePanelConstraints(panelDataRef.current, prevConstraints);
|
|
184
|
+
}
|
|
171
185
|
});
|
|
172
186
|
|
|
173
187
|
useIsomorphicLayoutEffect(() => {
|
package/src/PanelGroup.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isDevelopment } from "#is-development";
|
|
2
|
-
import { PanelData } from "./Panel";
|
|
2
|
+
import { PanelConstraints, PanelData } from "./Panel";
|
|
3
3
|
import {
|
|
4
4
|
DragState,
|
|
5
5
|
PanelGroupContext,
|
|
@@ -719,6 +719,48 @@ function PanelGroupWithForwardedRef({
|
|
|
719
719
|
[]
|
|
720
720
|
);
|
|
721
721
|
|
|
722
|
+
const reevaluatePanelConstraints = useCallback(
|
|
723
|
+
(panelData: PanelData, prevConstraints: PanelConstraints) => {
|
|
724
|
+
const { layout, panelDataArray } = eagerValuesRef.current;
|
|
725
|
+
|
|
726
|
+
const {
|
|
727
|
+
collapsedSize: prevCollapsedSize = 0,
|
|
728
|
+
collapsible: prevCollapsible,
|
|
729
|
+
} = prevConstraints;
|
|
730
|
+
|
|
731
|
+
const {
|
|
732
|
+
collapsedSize: nextCollapsedSize = 0,
|
|
733
|
+
collapsible: nextCollapsible,
|
|
734
|
+
maxSize: nextMaxSize = 100,
|
|
735
|
+
minSize: nextMinSize = 0,
|
|
736
|
+
} = panelData.constraints;
|
|
737
|
+
|
|
738
|
+
const { panelSize: prevPanelSize } = panelDataHelper(
|
|
739
|
+
panelDataArray,
|
|
740
|
+
panelData,
|
|
741
|
+
layout
|
|
742
|
+
);
|
|
743
|
+
assert(prevPanelSize != null);
|
|
744
|
+
|
|
745
|
+
if (
|
|
746
|
+
prevCollapsible &&
|
|
747
|
+
nextCollapsible &&
|
|
748
|
+
prevPanelSize === prevCollapsedSize
|
|
749
|
+
) {
|
|
750
|
+
if (prevCollapsedSize !== nextCollapsedSize) {
|
|
751
|
+
resizePanel(panelData, nextCollapsedSize);
|
|
752
|
+
} else {
|
|
753
|
+
// Stay collapsed
|
|
754
|
+
}
|
|
755
|
+
} else if (prevPanelSize < nextMinSize) {
|
|
756
|
+
resizePanel(panelData, nextMinSize);
|
|
757
|
+
} else if (prevPanelSize > nextMaxSize) {
|
|
758
|
+
resizePanel(panelData, nextMaxSize);
|
|
759
|
+
}
|
|
760
|
+
},
|
|
761
|
+
[resizePanel]
|
|
762
|
+
);
|
|
763
|
+
|
|
722
764
|
const startDragging = useCallback(
|
|
723
765
|
(dragHandleId: string, event: ResizeEvent) => {
|
|
724
766
|
const { direction } = committedValuesRef.current;
|
|
@@ -781,6 +823,7 @@ function PanelGroupWithForwardedRef({
|
|
|
781
823
|
groupId,
|
|
782
824
|
isPanelCollapsed,
|
|
783
825
|
isPanelExpanded,
|
|
826
|
+
reevaluatePanelConstraints,
|
|
784
827
|
registerPanel,
|
|
785
828
|
registerResizeHandle,
|
|
786
829
|
resizePanel,
|
|
@@ -799,6 +842,7 @@ function PanelGroupWithForwardedRef({
|
|
|
799
842
|
groupId,
|
|
800
843
|
isPanelCollapsed,
|
|
801
844
|
isPanelExpanded,
|
|
845
|
+
reevaluatePanelConstraints,
|
|
802
846
|
registerPanel,
|
|
803
847
|
registerResizeHandle,
|
|
804
848
|
resizePanel,
|
|
@@ -858,12 +902,7 @@ function panelDataHelper(
|
|
|
858
902
|
panelData: PanelData,
|
|
859
903
|
layout: number[]
|
|
860
904
|
) {
|
|
861
|
-
const panelConstraintsArray = panelDataArray.map(
|
|
862
|
-
(panelData) => panelData.constraints
|
|
863
|
-
);
|
|
864
|
-
|
|
865
905
|
const panelIndex = findPanelDataIndex(panelDataArray, panelData);
|
|
866
|
-
const panelConstraints = panelConstraintsArray[panelIndex];
|
|
867
906
|
|
|
868
907
|
const isLastPanel = panelIndex === panelDataArray.length - 1;
|
|
869
908
|
const pivotIndices = isLastPanel
|
|
@@ -873,7 +912,7 @@ function panelDataHelper(
|
|
|
873
912
|
const panelSize = layout[panelIndex];
|
|
874
913
|
|
|
875
914
|
return {
|
|
876
|
-
...
|
|
915
|
+
...panelData.constraints,
|
|
877
916
|
panelSize,
|
|
878
917
|
pivotIndices,
|
|
879
918
|
};
|
package/src/PanelGroupContext.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PanelData } from "./Panel";
|
|
1
|
+
import { PanelConstraints, PanelData } from "./Panel";
|
|
2
2
|
import { CSSProperties, createContext } from "./vendor/react";
|
|
3
3
|
|
|
4
4
|
export type ResizeEvent = KeyboardEvent | MouseEvent | TouchEvent;
|
|
@@ -24,6 +24,10 @@ export type TPanelGroupContext = {
|
|
|
24
24
|
groupId: string;
|
|
25
25
|
isPanelCollapsed: (panelData: PanelData) => boolean;
|
|
26
26
|
isPanelExpanded: (panelData: PanelData) => boolean;
|
|
27
|
+
reevaluatePanelConstraints: (
|
|
28
|
+
panelData: PanelData,
|
|
29
|
+
prevConstraints: PanelConstraints
|
|
30
|
+
) => void;
|
|
27
31
|
registerPanel: (panelData: PanelData) => void;
|
|
28
32
|
registerResizeHandle: (dragHandleId: string) => ResizeHandler;
|
|
29
33
|
resizePanel: (panelData: PanelData, size: number) => void;
|
package/src/index.ts
CHANGED
|
@@ -2,8 +2,6 @@ import { Panel } from "./Panel";
|
|
|
2
2
|
import { PanelGroup } from "./PanelGroup";
|
|
3
3
|
import { PanelResizeHandle } from "./PanelResizeHandle";
|
|
4
4
|
import { assert } from "./utils/assert";
|
|
5
|
-
import { calculateAvailablePanelSizeInPixels } from "./utils/dom/calculateAvailablePanelSizeInPixels";
|
|
6
|
-
import { getAvailableGroupSizePixels } from "./utils/dom/getAvailableGroupSizePixels";
|
|
7
5
|
import { getPanelElement } from "./utils/dom/getPanelElement";
|
|
8
6
|
import { getPanelElementsForGroup } from "./utils/dom/getPanelElementsForGroup";
|
|
9
7
|
import { getPanelGroupElement } from "./utils/dom/getPanelGroupElement";
|
|
@@ -53,8 +51,6 @@ export {
|
|
|
53
51
|
assert,
|
|
54
52
|
|
|
55
53
|
// DOM helpers
|
|
56
|
-
calculateAvailablePanelSizeInPixels,
|
|
57
|
-
getAvailableGroupSizePixels,
|
|
58
54
|
getPanelElement,
|
|
59
55
|
getPanelElementsForGroup,
|
|
60
56
|
getPanelGroupElement,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export function getPanelElement(
|
|
2
2
|
id: string,
|
|
3
|
-
|
|
3
|
+
scope: ParentNode | HTMLElement = document
|
|
4
4
|
): HTMLElement | null {
|
|
5
|
-
const element =
|
|
5
|
+
const element = scope.querySelector(`[data-panel-id="${id}"]`);
|
|
6
6
|
if (element) {
|
|
7
7
|
return element as HTMLElement;
|
|
8
8
|
}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
export function getPanelElementsForGroup(
|
|
2
2
|
groupId: string,
|
|
3
|
-
|
|
3
|
+
scope: ParentNode | HTMLElement = document
|
|
4
4
|
): HTMLElement[] {
|
|
5
5
|
return Array.from(
|
|
6
|
-
|
|
7
|
-
`[data-panel][data-panel-group-id="${groupId}"]`
|
|
8
|
-
)
|
|
6
|
+
scope.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`)
|
|
9
7
|
);
|
|
10
8
|
}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
export function getResizeHandleElement(
|
|
2
2
|
id: string,
|
|
3
|
-
|
|
3
|
+
scope: ParentNode | HTMLElement = document
|
|
4
4
|
): HTMLElement | null {
|
|
5
|
-
const element =
|
|
6
|
-
`[data-panel-resize-handle-id="${id}"]`
|
|
7
|
-
);
|
|
5
|
+
const element = scope.querySelector(`[data-panel-resize-handle-id="${id}"]`);
|
|
8
6
|
if (element) {
|
|
9
7
|
return element as HTMLElement;
|
|
10
8
|
}
|
|
@@ -3,9 +3,9 @@ import { getResizeHandleElementsForGroup } from "./getResizeHandleElementsForGro
|
|
|
3
3
|
export function getResizeHandleElementIndex(
|
|
4
4
|
groupId: string,
|
|
5
5
|
id: string,
|
|
6
|
-
|
|
6
|
+
scope: ParentNode | HTMLElement = document
|
|
7
7
|
): number | null {
|
|
8
|
-
const handles = getResizeHandleElementsForGroup(groupId,
|
|
8
|
+
const handles = getResizeHandleElementsForGroup(groupId, scope);
|
|
9
9
|
const index = handles.findIndex(
|
|
10
10
|
(handle) => handle.getAttribute("data-panel-resize-handle-id") === id
|
|
11
11
|
);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export function getResizeHandleElementsForGroup(
|
|
2
2
|
groupId: string,
|
|
3
|
-
|
|
3
|
+
scope: ParentNode | HTMLElement = document
|
|
4
4
|
): HTMLElement[] {
|
|
5
5
|
return Array.from(
|
|
6
|
-
|
|
6
|
+
scope.querySelectorAll(
|
|
7
7
|
`[data-panel-resize-handle-id][data-panel-group-id="${groupId}"]`
|
|
8
8
|
)
|
|
9
9
|
);
|
|
@@ -6,10 +6,10 @@ export function getResizeHandlePanelIds(
|
|
|
6
6
|
groupId: string,
|
|
7
7
|
handleId: string,
|
|
8
8
|
panelsArray: PanelData[],
|
|
9
|
-
|
|
9
|
+
scope: ParentNode | HTMLElement = document
|
|
10
10
|
): [idBefore: string | null, idAfter: string | null] {
|
|
11
|
-
const handle = getResizeHandleElement(handleId,
|
|
12
|
-
const handles = getResizeHandleElementsForGroup(groupId,
|
|
11
|
+
const handle = getResizeHandleElement(handleId, scope);
|
|
12
|
+
const handles = getResizeHandleElementsForGroup(groupId, scope);
|
|
13
13
|
const index = handle ? handles.indexOf(handle) : -1;
|
|
14
14
|
|
|
15
15
|
const idBefore: string | null = panelsArray[index]?.id ?? null;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function calculateAvailablePanelSizeInPixels(groupId: string, panelGroupElement: HTMLElement): number;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function getAvailableGroupSizePixels(groupId: string, panelGroupElement: HTMLElement): number;
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { getPanelGroupElement } from "./getPanelGroupElement";
|
|
2
|
-
import { getResizeHandleElementsForGroup } from "./getResizeHandleElementsForGroup";
|
|
3
|
-
|
|
4
|
-
export function calculateAvailablePanelSizeInPixels(
|
|
5
|
-
groupId: string,
|
|
6
|
-
panelGroupElement: HTMLElement
|
|
7
|
-
): number {
|
|
8
|
-
if (panelGroupElement == null) {
|
|
9
|
-
return NaN;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const direction = panelGroupElement.getAttribute(
|
|
13
|
-
"data-panel-group-direction"
|
|
14
|
-
);
|
|
15
|
-
const resizeHandles = getResizeHandleElementsForGroup(
|
|
16
|
-
groupId,
|
|
17
|
-
panelGroupElement
|
|
18
|
-
);
|
|
19
|
-
if (direction === "horizontal") {
|
|
20
|
-
return (
|
|
21
|
-
panelGroupElement.offsetWidth -
|
|
22
|
-
resizeHandles.reduce((accumulated, handle) => {
|
|
23
|
-
return accumulated + handle.offsetWidth;
|
|
24
|
-
}, 0)
|
|
25
|
-
);
|
|
26
|
-
} else {
|
|
27
|
-
return (
|
|
28
|
-
panelGroupElement.offsetHeight -
|
|
29
|
-
resizeHandles.reduce((accumulated, handle) => {
|
|
30
|
-
return accumulated + handle.offsetHeight;
|
|
31
|
-
}, 0)
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
}
|