react-resizable-panels 1.0.0-rc.3 → 1.0.0-rc.4

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.
@@ -667,47 +667,6 @@ function calculateDeltaPercentage(event, dragHandleId, direction, initialDragSta
667
667
  }
668
668
  }
669
669
 
670
- function calculateUnsafeDefaultLayout({
671
- panelDataArray
672
- }) {
673
- const layout = Array(panelDataArray.length);
674
- const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
675
- let numPanelsWithSizes = 0;
676
- let remainingSize = 100;
677
-
678
- // Distribute default sizes first
679
- for (let index = 0; index < panelDataArray.length; index++) {
680
- const panelConstraints = panelConstraintsArray[index];
681
- assert(panelConstraints);
682
- const {
683
- defaultSize
684
- } = panelConstraints;
685
- if (defaultSize != null) {
686
- numPanelsWithSizes++;
687
- layout[index] = defaultSize;
688
- remainingSize -= defaultSize;
689
- }
690
- }
691
-
692
- // Remaining size should be distributed evenly between panels without default sizes
693
- for (let index = 0; index < panelDataArray.length; index++) {
694
- const panelConstraints = panelConstraintsArray[index];
695
- assert(panelConstraints);
696
- const {
697
- defaultSize
698
- } = panelConstraints;
699
- if (defaultSize != null) {
700
- continue;
701
- }
702
- const numRemainingPanels = panelDataArray.length - numPanelsWithSizes;
703
- const size = remainingSize / numRemainingPanels;
704
- numPanelsWithSizes++;
705
- layout[index] = size;
706
- remainingSize -= size;
707
- }
708
- return layout;
709
- }
710
-
711
670
  // Layout should be pre-converted into percentages
712
671
  function callPanelCallbacks(panelsArray, layout, panelIdToLastNotifiedSizeMap) {
713
672
  layout.forEach((size, index) => {
@@ -841,10 +800,6 @@ function debounce(callback, durationMs = 10) {
841
800
  return callable;
842
801
  }
843
802
 
844
- function getPanelElementsForGroup(groupId) {
845
- return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
846
- }
847
-
848
803
  // PanelGroup might be rendering in a server-side environment where localStorage is not available
849
804
  // or on a browser with cookies/storage disabled.
850
805
  // In either case, this function avoids accessing localStorage until needed,
@@ -900,15 +855,6 @@ function loadSerializedPanelGroupState(autoSaveId, storage) {
900
855
  } catch (error) {}
901
856
  return null;
902
857
  }
903
- function loadPanelLayout(autoSaveId, panels, storage) {
904
- const state = loadSerializedPanelGroupState(autoSaveId, storage);
905
- if (state) {
906
- var _state$key;
907
- const key = getSerializationKey(panels);
908
- return (_state$key = state[key]) !== null && _state$key !== void 0 ? _state$key : null;
909
- }
910
- return null;
911
- }
912
858
  function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
913
859
  const key = getSerializationKey(panels);
914
860
  const state = loadSerializedPanelGroupState(autoSaveId, storage) || {};
@@ -1011,6 +957,7 @@ function PanelGroupWithForwardedRef({
1011
957
  const groupId = useUniqueId(idFromProps);
1012
958
  const [dragState, setDragState] = useState(null);
1013
959
  const [layout, setLayout] = useState([]);
960
+ useState([]);
1014
961
  const panelIdToLastNotifiedSizeMapRef = useRef({});
1015
962
  const panelSizeBeforeCollapseRef = useRef(new Map());
1016
963
  const prevDeltaRef = useRef(0);
@@ -1025,7 +972,8 @@ function PanelGroupWithForwardedRef({
1025
972
  });
1026
973
  const eagerValuesRef = useRef({
1027
974
  layout,
1028
- panelDataArray: []
975
+ panelDataArray: [],
976
+ panelDataArrayChanged: false
1029
977
  });
1030
978
  useRef({
1031
979
  didLogIdAndOrderWarning: false,
@@ -1236,28 +1184,8 @@ function PanelGroupWithForwardedRef({
1236
1184
  }, []);
1237
1185
  const registerPanel = useCallback(panelData => {
1238
1186
  const {
1239
- autoSaveId,
1240
- id: groupId,
1241
- onLayout,
1242
- storage
1243
- } = committedValuesRef.current;
1244
- const {
1245
- layout: prevLayout,
1246
1187
  panelDataArray
1247
1188
  } = eagerValuesRef.current;
1248
-
1249
- // HACK
1250
- // This appears to be triggered by some React Suspense+Offscreen+StrictMode bug;
1251
- // see app.replay.io/recording/17b6e11d-4500-4173-b23d-61dfd141fed1
1252
- const index = findPanelDataIndex(panelDataArray, panelData);
1253
- if (index >= 0) {
1254
- if (panelData.idIsFromProps) {
1255
- console.warn(`Panel with id "${panelData.id}" registered twice`);
1256
- } else {
1257
- console.warn(`Panel registered twice`);
1258
- }
1259
- return;
1260
- }
1261
1189
  panelDataArray.push(panelData);
1262
1190
  panelDataArray.sort((panelA, panelB) => {
1263
1191
  const orderA = panelA.order;
@@ -1272,44 +1200,7 @@ function PanelGroupWithForwardedRef({
1272
1200
  return orderA - orderB;
1273
1201
  }
1274
1202
  });
1275
-
1276
- // Wait until all panels have registered before we try to compute layout;
1277
- // doing it earlier is both wasteful and may trigger misleading warnings in development mode.
1278
- const panelElements = getPanelElementsForGroup(groupId);
1279
- if (panelElements.length !== panelDataArray.length) {
1280
- return;
1281
- }
1282
-
1283
- // If this panel has been configured to persist sizing information,
1284
- // default size should be restored from local storage if possible.
1285
- let unsafeLayout = null;
1286
- if (autoSaveId) {
1287
- unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
1288
- }
1289
- if (unsafeLayout == null) {
1290
- unsafeLayout = calculateUnsafeDefaultLayout({
1291
- panelDataArray
1292
- });
1293
- }
1294
-
1295
- // Validate even saved layouts in case something has changed since last render
1296
- // e.g. for pixel groups, this could be the size of the window
1297
- const nextLayout = validatePanelGroupLayout({
1298
- layout: unsafeLayout,
1299
- panelConstraints: panelDataArray.map(panelData => panelData.constraints)
1300
- });
1301
-
1302
- // Offscreen mode makes this a bit weird;
1303
- // Panels unregister when hidden and re-register when shown again,
1304
- // but the overall layout doesn't change between these two cases.
1305
- setLayout(nextLayout);
1306
- eagerValuesRef.current.layout = nextLayout;
1307
- if (!areEqual(prevLayout, nextLayout)) {
1308
- if (onLayout) {
1309
- onLayout(nextLayout);
1310
- }
1311
- callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1312
- }
1203
+ eagerValuesRef.current.panelDataArrayChanged = true;
1313
1204
  }, []);
1314
1205
  const registerResizeHandle = useCallback(dragHandleId => {
1315
1206
  return function resizeHandler(event) {
@@ -1438,79 +1329,21 @@ function PanelGroupWithForwardedRef({
1438
1329
  resetGlobalCursorStyle();
1439
1330
  setDragState(null);
1440
1331
  }, []);
1441
- const unregisterPanelRef = useRef({
1442
- pendingPanelIds: new Set(),
1443
- timeout: null
1444
- });
1445
1332
  const unregisterPanel = useCallback(panelData => {
1446
1333
  const {
1447
- onLayout
1448
- } = committedValuesRef.current;
1449
- const {
1450
- layout: prevLayout,
1451
1334
  panelDataArray
1452
1335
  } = eagerValuesRef.current;
1453
1336
  const index = findPanelDataIndex(panelDataArray, panelData);
1454
1337
  if (index >= 0) {
1455
1338
  panelDataArray.splice(index, 1);
1456
- unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
1457
- }
1458
- if (unregisterPanelRef.current.timeout != null) {
1459
- clearTimeout(unregisterPanelRef.current.timeout);
1460
- }
1461
-
1462
- // Batch panel unmounts so that we only calculate layout once;
1463
- // This is more efficient and avoids misleading warnings in development mode.
1464
- // We can't check the DOM to detect this because Panel elements have not yet been removed.
1465
- unregisterPanelRef.current.timeout = setTimeout(() => {
1466
- const {
1467
- pendingPanelIds
1468
- } = unregisterPanelRef.current;
1469
- const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
1470
1339
 
1471
1340
  // TRICKY
1472
- // Strict effects mode
1473
- let unmountDueToStrictMode = false;
1474
- pendingPanelIds.forEach(panelId => {
1475
- pendingPanelIds.delete(panelId);
1476
- if (panelDataArray.find(({
1477
- id
1478
- }) => id === panelId) != null) {
1479
- unmountDueToStrictMode = true;
1480
- } else {
1481
- // TRICKY
1482
- // When a panel is removed from the group, we should delete the most recent prev-size entry for it.
1483
- // If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
1484
- // Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
1485
- delete panelIdToLastNotifiedSizeMap[panelId];
1486
- }
1487
- });
1488
- if (unmountDueToStrictMode) {
1489
- return;
1490
- }
1491
- if (panelDataArray.length === 0) {
1492
- // The group is unmounting; skip layout calculation.
1493
- return;
1494
- }
1495
- let unsafeLayout = calculateUnsafeDefaultLayout({
1496
- panelDataArray
1497
- });
1498
-
1499
- // Validate even saved layouts in case something has changed since last render
1500
- // e.g. for pixel groups, this could be the size of the window
1501
- const nextLayout = validatePanelGroupLayout({
1502
- layout: unsafeLayout,
1503
- panelConstraints: panelDataArray.map(panelData => panelData.constraints)
1504
- });
1505
- if (!areEqual(prevLayout, nextLayout)) {
1506
- setLayout(nextLayout);
1507
- eagerValuesRef.current.layout = nextLayout;
1508
- if (onLayout) {
1509
- onLayout(nextLayout);
1510
- }
1511
- callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1512
- }
1513
- }, 0);
1341
+ // When a panel is removed from the group, we should delete the most recent prev-size entry for it.
1342
+ // If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
1343
+ // Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
1344
+ delete panelIdToLastNotifiedSizeMapRef.current[panelData.id];
1345
+ eagerValuesRef.current.panelDataArrayChanged = true;
1346
+ }
1514
1347
  }, []);
1515
1348
  const context = useMemo(() => ({
1516
1349
  collapsePanel,
@@ -643,47 +643,6 @@ function calculateDeltaPercentage(event, dragHandleId, direction, initialDragSta
643
643
  }
644
644
  }
645
645
 
646
- function calculateUnsafeDefaultLayout({
647
- panelDataArray
648
- }) {
649
- const layout = Array(panelDataArray.length);
650
- const panelConstraintsArray = panelDataArray.map(panelData => panelData.constraints);
651
- let numPanelsWithSizes = 0;
652
- let remainingSize = 100;
653
-
654
- // Distribute default sizes first
655
- for (let index = 0; index < panelDataArray.length; index++) {
656
- const panelConstraints = panelConstraintsArray[index];
657
- assert(panelConstraints);
658
- const {
659
- defaultSize
660
- } = panelConstraints;
661
- if (defaultSize != null) {
662
- numPanelsWithSizes++;
663
- layout[index] = defaultSize;
664
- remainingSize -= defaultSize;
665
- }
666
- }
667
-
668
- // Remaining size should be distributed evenly between panels without default sizes
669
- for (let index = 0; index < panelDataArray.length; index++) {
670
- const panelConstraints = panelConstraintsArray[index];
671
- assert(panelConstraints);
672
- const {
673
- defaultSize
674
- } = panelConstraints;
675
- if (defaultSize != null) {
676
- continue;
677
- }
678
- const numRemainingPanels = panelDataArray.length - numPanelsWithSizes;
679
- const size = remainingSize / numRemainingPanels;
680
- numPanelsWithSizes++;
681
- layout[index] = size;
682
- remainingSize -= size;
683
- }
684
- return layout;
685
- }
686
-
687
646
  // Layout should be pre-converted into percentages
688
647
  function callPanelCallbacks(panelsArray, layout, panelIdToLastNotifiedSizeMap) {
689
648
  layout.forEach((size, index) => {
@@ -817,10 +776,6 @@ function debounce(callback, durationMs = 10) {
817
776
  return callable;
818
777
  }
819
778
 
820
- function getPanelElementsForGroup(groupId) {
821
- return Array.from(document.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
822
- }
823
-
824
779
  // PanelGroup might be rendering in a server-side environment where localStorage is not available
825
780
  // or on a browser with cookies/storage disabled.
826
781
  // In either case, this function avoids accessing localStorage until needed,
@@ -876,15 +831,6 @@ function loadSerializedPanelGroupState(autoSaveId, storage) {
876
831
  } catch (error) {}
877
832
  return null;
878
833
  }
879
- function loadPanelLayout(autoSaveId, panels, storage) {
880
- const state = loadSerializedPanelGroupState(autoSaveId, storage);
881
- if (state) {
882
- var _state$key;
883
- const key = getSerializationKey(panels);
884
- return (_state$key = state[key]) !== null && _state$key !== void 0 ? _state$key : null;
885
- }
886
- return null;
887
- }
888
834
  function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
889
835
  const key = getSerializationKey(panels);
890
836
  const state = loadSerializedPanelGroupState(autoSaveId, storage) || {};
@@ -987,6 +933,7 @@ function PanelGroupWithForwardedRef({
987
933
  const groupId = useUniqueId(idFromProps);
988
934
  const [dragState, setDragState] = useState(null);
989
935
  const [layout, setLayout] = useState([]);
936
+ useState([]);
990
937
  const panelIdToLastNotifiedSizeMapRef = useRef({});
991
938
  const panelSizeBeforeCollapseRef = useRef(new Map());
992
939
  const prevDeltaRef = useRef(0);
@@ -1001,7 +948,8 @@ function PanelGroupWithForwardedRef({
1001
948
  });
1002
949
  const eagerValuesRef = useRef({
1003
950
  layout,
1004
- panelDataArray: []
951
+ panelDataArray: [],
952
+ panelDataArrayChanged: false
1005
953
  });
1006
954
  useRef({
1007
955
  didLogIdAndOrderWarning: false,
@@ -1212,28 +1160,8 @@ function PanelGroupWithForwardedRef({
1212
1160
  }, []);
1213
1161
  const registerPanel = useCallback(panelData => {
1214
1162
  const {
1215
- autoSaveId,
1216
- id: groupId,
1217
- onLayout,
1218
- storage
1219
- } = committedValuesRef.current;
1220
- const {
1221
- layout: prevLayout,
1222
1163
  panelDataArray
1223
1164
  } = eagerValuesRef.current;
1224
-
1225
- // HACK
1226
- // This appears to be triggered by some React Suspense+Offscreen+StrictMode bug;
1227
- // see app.replay.io/recording/17b6e11d-4500-4173-b23d-61dfd141fed1
1228
- const index = findPanelDataIndex(panelDataArray, panelData);
1229
- if (index >= 0) {
1230
- if (panelData.idIsFromProps) {
1231
- console.warn(`Panel with id "${panelData.id}" registered twice`);
1232
- } else {
1233
- console.warn(`Panel registered twice`);
1234
- }
1235
- return;
1236
- }
1237
1165
  panelDataArray.push(panelData);
1238
1166
  panelDataArray.sort((panelA, panelB) => {
1239
1167
  const orderA = panelA.order;
@@ -1248,44 +1176,7 @@ function PanelGroupWithForwardedRef({
1248
1176
  return orderA - orderB;
1249
1177
  }
1250
1178
  });
1251
-
1252
- // Wait until all panels have registered before we try to compute layout;
1253
- // doing it earlier is both wasteful and may trigger misleading warnings in development mode.
1254
- const panelElements = getPanelElementsForGroup(groupId);
1255
- if (panelElements.length !== panelDataArray.length) {
1256
- return;
1257
- }
1258
-
1259
- // If this panel has been configured to persist sizing information,
1260
- // default size should be restored from local storage if possible.
1261
- let unsafeLayout = null;
1262
- if (autoSaveId) {
1263
- unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
1264
- }
1265
- if (unsafeLayout == null) {
1266
- unsafeLayout = calculateUnsafeDefaultLayout({
1267
- panelDataArray
1268
- });
1269
- }
1270
-
1271
- // Validate even saved layouts in case something has changed since last render
1272
- // e.g. for pixel groups, this could be the size of the window
1273
- const nextLayout = validatePanelGroupLayout({
1274
- layout: unsafeLayout,
1275
- panelConstraints: panelDataArray.map(panelData => panelData.constraints)
1276
- });
1277
-
1278
- // Offscreen mode makes this a bit weird;
1279
- // Panels unregister when hidden and re-register when shown again,
1280
- // but the overall layout doesn't change between these two cases.
1281
- setLayout(nextLayout);
1282
- eagerValuesRef.current.layout = nextLayout;
1283
- if (!areEqual(prevLayout, nextLayout)) {
1284
- if (onLayout) {
1285
- onLayout(nextLayout);
1286
- }
1287
- callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1288
- }
1179
+ eagerValuesRef.current.panelDataArrayChanged = true;
1289
1180
  }, []);
1290
1181
  const registerResizeHandle = useCallback(dragHandleId => {
1291
1182
  return function resizeHandler(event) {
@@ -1414,79 +1305,21 @@ function PanelGroupWithForwardedRef({
1414
1305
  resetGlobalCursorStyle();
1415
1306
  setDragState(null);
1416
1307
  }, []);
1417
- const unregisterPanelRef = useRef({
1418
- pendingPanelIds: new Set(),
1419
- timeout: null
1420
- });
1421
1308
  const unregisterPanel = useCallback(panelData => {
1422
1309
  const {
1423
- onLayout
1424
- } = committedValuesRef.current;
1425
- const {
1426
- layout: prevLayout,
1427
1310
  panelDataArray
1428
1311
  } = eagerValuesRef.current;
1429
1312
  const index = findPanelDataIndex(panelDataArray, panelData);
1430
1313
  if (index >= 0) {
1431
1314
  panelDataArray.splice(index, 1);
1432
- unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
1433
- }
1434
- if (unregisterPanelRef.current.timeout != null) {
1435
- clearTimeout(unregisterPanelRef.current.timeout);
1436
- }
1437
-
1438
- // Batch panel unmounts so that we only calculate layout once;
1439
- // This is more efficient and avoids misleading warnings in development mode.
1440
- // We can't check the DOM to detect this because Panel elements have not yet been removed.
1441
- unregisterPanelRef.current.timeout = setTimeout(() => {
1442
- const {
1443
- pendingPanelIds
1444
- } = unregisterPanelRef.current;
1445
- const panelIdToLastNotifiedSizeMap = panelIdToLastNotifiedSizeMapRef.current;
1446
1315
 
1447
1316
  // TRICKY
1448
- // Strict effects mode
1449
- let unmountDueToStrictMode = false;
1450
- pendingPanelIds.forEach(panelId => {
1451
- pendingPanelIds.delete(panelId);
1452
- if (panelDataArray.find(({
1453
- id
1454
- }) => id === panelId) != null) {
1455
- unmountDueToStrictMode = true;
1456
- } else {
1457
- // TRICKY
1458
- // When a panel is removed from the group, we should delete the most recent prev-size entry for it.
1459
- // If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
1460
- // Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
1461
- delete panelIdToLastNotifiedSizeMap[panelId];
1462
- }
1463
- });
1464
- if (unmountDueToStrictMode) {
1465
- return;
1466
- }
1467
- if (panelDataArray.length === 0) {
1468
- // The group is unmounting; skip layout calculation.
1469
- return;
1470
- }
1471
- let unsafeLayout = calculateUnsafeDefaultLayout({
1472
- panelDataArray
1473
- });
1474
-
1475
- // Validate even saved layouts in case something has changed since last render
1476
- // e.g. for pixel groups, this could be the size of the window
1477
- const nextLayout = validatePanelGroupLayout({
1478
- layout: unsafeLayout,
1479
- panelConstraints: panelDataArray.map(panelData => panelData.constraints)
1480
- });
1481
- if (!areEqual(prevLayout, nextLayout)) {
1482
- setLayout(nextLayout);
1483
- eagerValuesRef.current.layout = nextLayout;
1484
- if (onLayout) {
1485
- onLayout(nextLayout);
1486
- }
1487
- callPanelCallbacks(panelDataArray, nextLayout, panelIdToLastNotifiedSizeMapRef.current);
1488
- }
1489
- }, 0);
1317
+ // When a panel is removed from the group, we should delete the most recent prev-size entry for it.
1318
+ // If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
1319
+ // Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
1320
+ delete panelIdToLastNotifiedSizeMapRef.current[panelData.id];
1321
+ eagerValuesRef.current.panelDataArrayChanged = true;
1322
+ }
1490
1323
  }, []);
1491
1324
  const context = useMemo(() => ({
1492
1325
  collapsePanel,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-resizable-panels",
3
- "version": "1.0.0-rc.3",
3
+ "version": "1.0.0-rc.4",
4
4
  "description": "React components for resizable panel groups/layouts",
5
5
  "author": "Brian Vaughn <brian.david.vaughn@gmail.com>",
6
6
  "license": "MIT",