react-resizable-panels 1.0.1 → 1.0.3

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.
@@ -984,11 +984,15 @@ function initializeDefaultStorage(storageObject) {
984
984
  }
985
985
  }
986
986
 
987
+ function getPanelGroupKey(autoSaveId) {
988
+ return `react-resizable-panels:${autoSaveId}`;
989
+ }
990
+
987
991
  // Note that Panel ids might be user-provided (stable) or useId generated (non-deterministic)
988
992
  // so they should not be used as part of the serialization key.
989
993
  // Using the min/max size attributes should work well enough as a backup.
990
994
  // Pre-sorting by minSize allows remembering layouts even if panels are re-ordered/dragged.
991
- function getSerializationKey(panels) {
995
+ function getPanelKey(panels) {
992
996
  return panels.map(panel => {
993
997
  const {
994
998
  constraints,
@@ -999,13 +1003,14 @@ function getSerializationKey(panels) {
999
1003
  if (idIsFromProps) {
1000
1004
  return id;
1001
1005
  } else {
1002
- return `${order}:${JSON.stringify(constraints)}`;
1006
+ return order ? `${order}:${JSON.stringify(constraints)}` : JSON.stringify(constraints);
1003
1007
  }
1004
1008
  }).sort((a, b) => a.localeCompare(b)).join(",");
1005
1009
  }
1006
1010
  function loadSerializedPanelGroupState(autoSaveId, storage) {
1007
1011
  try {
1008
- const serialized = storage.getItem(`PanelGroup:sizes:${autoSaveId}`);
1012
+ const panelGroupKey = getPanelGroupKey(autoSaveId);
1013
+ const serialized = storage.getItem(panelGroupKey);
1009
1014
  if (serialized) {
1010
1015
  const parsed = JSON.parse(serialized);
1011
1016
  if (typeof parsed === "object" && parsed != null) {
@@ -1015,21 +1020,23 @@ function loadSerializedPanelGroupState(autoSaveId, storage) {
1015
1020
  } catch (error) {}
1016
1021
  return null;
1017
1022
  }
1018
- function loadPanelLayout(autoSaveId, panels, storage) {
1019
- const state = loadSerializedPanelGroupState(autoSaveId, storage);
1020
- if (state) {
1021
- var _state$key;
1022
- const key = getSerializationKey(panels);
1023
- return (_state$key = state[key]) !== null && _state$key !== void 0 ? _state$key : null;
1024
- }
1025
- return null;
1023
+ function loadPanelGroupState(autoSaveId, panels, storage) {
1024
+ var _loadSerializedPanelG, _state$panelKey;
1025
+ const state = (_loadSerializedPanelG = loadSerializedPanelGroupState(autoSaveId, storage)) !== null && _loadSerializedPanelG !== void 0 ? _loadSerializedPanelG : {};
1026
+ const panelKey = getPanelKey(panels);
1027
+ return (_state$panelKey = state[panelKey]) !== null && _state$panelKey !== void 0 ? _state$panelKey : null;
1026
1028
  }
1027
- function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
1028
- const key = getSerializationKey(panels);
1029
- const state = loadSerializedPanelGroupState(autoSaveId, storage) || {};
1030
- state[key] = sizes;
1029
+ function savePanelGroupState(autoSaveId, panels, panelSizesBeforeCollapse, sizes, storage) {
1030
+ var _loadSerializedPanelG2;
1031
+ const panelGroupKey = getPanelGroupKey(autoSaveId);
1032
+ const panelKey = getPanelKey(panels);
1033
+ const state = (_loadSerializedPanelG2 = loadSerializedPanelGroupState(autoSaveId, storage)) !== null && _loadSerializedPanelG2 !== void 0 ? _loadSerializedPanelG2 : {};
1034
+ state[panelKey] = {
1035
+ expandToSizes: Object.fromEntries(panelSizesBeforeCollapse.entries()),
1036
+ layout: sizes
1037
+ };
1031
1038
  try {
1032
- storage.setItem(`PanelGroup:sizes:${autoSaveId}`, JSON.stringify(state));
1039
+ storage.setItem(panelGroupKey, JSON.stringify(state));
1033
1040
  } catch (error) {
1034
1041
  console.error(error);
1035
1042
  }
@@ -1173,7 +1180,6 @@ function PanelGroupWithForwardedRef({
1173
1180
  const groupId = useUniqueId(idFromProps);
1174
1181
  const [dragState, setDragState] = useState(null);
1175
1182
  const [layout, setLayout] = useState([]);
1176
- useState([]);
1177
1183
  const panelIdToLastNotifiedSizeMapRef = useRef({});
1178
1184
  const panelSizeBeforeCollapseRef = useRef(new Map());
1179
1185
  const prevDeltaRef = useRef(0);
@@ -1256,13 +1262,15 @@ function PanelGroupWithForwardedRef({
1256
1262
 
1257
1263
  // Limit the frequency of localStorage updates.
1258
1264
  if (debouncedSave == null) {
1259
- debouncedSave = debounce(savePanelGroupLayout, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
1265
+ debouncedSave = debounce(savePanelGroupState, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
1260
1266
  debounceMap[autoSaveId] = debouncedSave;
1261
1267
  }
1262
1268
 
1263
- // Clone panel data array before saving since this array is mutated.
1264
- // If we don't clone, we run the risk of saving the wrong panel and layout pair.
1265
- debouncedSave(autoSaveId, [...panelDataArray], layout, storage);
1269
+ // Clone mutable data before passing to the debounced function,
1270
+ // else we run the risk of saving an incorrect combination of mutable and immutable values to state.
1271
+ const clonedPanelDataArray = [...panelDataArray];
1272
+ const clonedPanelSizesBeforeCollapse = new Map(panelSizeBeforeCollapseRef.current);
1273
+ debouncedSave(autoSaveId, clonedPanelDataArray, clonedPanelSizesBeforeCollapse, layout, storage);
1266
1274
  }
1267
1275
  }, [autoSaveId, layout, storage]);
1268
1276
 
@@ -1491,7 +1499,11 @@ function PanelGroupWithForwardedRef({
1491
1499
  // default size should be restored from local storage if possible.
1492
1500
  let unsafeLayout = null;
1493
1501
  if (autoSaveId) {
1494
- unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
1502
+ const state = loadPanelGroupState(autoSaveId, panelDataArray, storage);
1503
+ if (state) {
1504
+ panelSizeBeforeCollapseRef.current = new Map(Object.entries(state.expandToSizes));
1505
+ unsafeLayout = state.layout;
1506
+ }
1495
1507
  }
1496
1508
  if (unsafeLayout == null) {
1497
1509
  unsafeLayout = calculateUnsafeDefaultLayout({
@@ -960,11 +960,15 @@ function initializeDefaultStorage(storageObject) {
960
960
  }
961
961
  }
962
962
 
963
+ function getPanelGroupKey(autoSaveId) {
964
+ return `react-resizable-panels:${autoSaveId}`;
965
+ }
966
+
963
967
  // Note that Panel ids might be user-provided (stable) or useId generated (non-deterministic)
964
968
  // so they should not be used as part of the serialization key.
965
969
  // Using the min/max size attributes should work well enough as a backup.
966
970
  // Pre-sorting by minSize allows remembering layouts even if panels are re-ordered/dragged.
967
- function getSerializationKey(panels) {
971
+ function getPanelKey(panels) {
968
972
  return panels.map(panel => {
969
973
  const {
970
974
  constraints,
@@ -975,13 +979,14 @@ function getSerializationKey(panels) {
975
979
  if (idIsFromProps) {
976
980
  return id;
977
981
  } else {
978
- return `${order}:${JSON.stringify(constraints)}`;
982
+ return order ? `${order}:${JSON.stringify(constraints)}` : JSON.stringify(constraints);
979
983
  }
980
984
  }).sort((a, b) => a.localeCompare(b)).join(",");
981
985
  }
982
986
  function loadSerializedPanelGroupState(autoSaveId, storage) {
983
987
  try {
984
- const serialized = storage.getItem(`PanelGroup:sizes:${autoSaveId}`);
988
+ const panelGroupKey = getPanelGroupKey(autoSaveId);
989
+ const serialized = storage.getItem(panelGroupKey);
985
990
  if (serialized) {
986
991
  const parsed = JSON.parse(serialized);
987
992
  if (typeof parsed === "object" && parsed != null) {
@@ -991,21 +996,23 @@ function loadSerializedPanelGroupState(autoSaveId, storage) {
991
996
  } catch (error) {}
992
997
  return null;
993
998
  }
994
- function loadPanelLayout(autoSaveId, panels, storage) {
995
- const state = loadSerializedPanelGroupState(autoSaveId, storage);
996
- if (state) {
997
- var _state$key;
998
- const key = getSerializationKey(panels);
999
- return (_state$key = state[key]) !== null && _state$key !== void 0 ? _state$key : null;
1000
- }
1001
- return null;
999
+ function loadPanelGroupState(autoSaveId, panels, storage) {
1000
+ var _loadSerializedPanelG, _state$panelKey;
1001
+ const state = (_loadSerializedPanelG = loadSerializedPanelGroupState(autoSaveId, storage)) !== null && _loadSerializedPanelG !== void 0 ? _loadSerializedPanelG : {};
1002
+ const panelKey = getPanelKey(panels);
1003
+ return (_state$panelKey = state[panelKey]) !== null && _state$panelKey !== void 0 ? _state$panelKey : null;
1002
1004
  }
1003
- function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
1004
- const key = getSerializationKey(panels);
1005
- const state = loadSerializedPanelGroupState(autoSaveId, storage) || {};
1006
- state[key] = sizes;
1005
+ function savePanelGroupState(autoSaveId, panels, panelSizesBeforeCollapse, sizes, storage) {
1006
+ var _loadSerializedPanelG2;
1007
+ const panelGroupKey = getPanelGroupKey(autoSaveId);
1008
+ const panelKey = getPanelKey(panels);
1009
+ const state = (_loadSerializedPanelG2 = loadSerializedPanelGroupState(autoSaveId, storage)) !== null && _loadSerializedPanelG2 !== void 0 ? _loadSerializedPanelG2 : {};
1010
+ state[panelKey] = {
1011
+ expandToSizes: Object.fromEntries(panelSizesBeforeCollapse.entries()),
1012
+ layout: sizes
1013
+ };
1007
1014
  try {
1008
- storage.setItem(`PanelGroup:sizes:${autoSaveId}`, JSON.stringify(state));
1015
+ storage.setItem(panelGroupKey, JSON.stringify(state));
1009
1016
  } catch (error) {
1010
1017
  console.error(error);
1011
1018
  }
@@ -1149,7 +1156,6 @@ function PanelGroupWithForwardedRef({
1149
1156
  const groupId = useUniqueId(idFromProps);
1150
1157
  const [dragState, setDragState] = useState(null);
1151
1158
  const [layout, setLayout] = useState([]);
1152
- useState([]);
1153
1159
  const panelIdToLastNotifiedSizeMapRef = useRef({});
1154
1160
  const panelSizeBeforeCollapseRef = useRef(new Map());
1155
1161
  const prevDeltaRef = useRef(0);
@@ -1232,13 +1238,15 @@ function PanelGroupWithForwardedRef({
1232
1238
 
1233
1239
  // Limit the frequency of localStorage updates.
1234
1240
  if (debouncedSave == null) {
1235
- debouncedSave = debounce(savePanelGroupLayout, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
1241
+ debouncedSave = debounce(savePanelGroupState, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
1236
1242
  debounceMap[autoSaveId] = debouncedSave;
1237
1243
  }
1238
1244
 
1239
- // Clone panel data array before saving since this array is mutated.
1240
- // If we don't clone, we run the risk of saving the wrong panel and layout pair.
1241
- debouncedSave(autoSaveId, [...panelDataArray], layout, storage);
1245
+ // Clone mutable data before passing to the debounced function,
1246
+ // else we run the risk of saving an incorrect combination of mutable and immutable values to state.
1247
+ const clonedPanelDataArray = [...panelDataArray];
1248
+ const clonedPanelSizesBeforeCollapse = new Map(panelSizeBeforeCollapseRef.current);
1249
+ debouncedSave(autoSaveId, clonedPanelDataArray, clonedPanelSizesBeforeCollapse, layout, storage);
1242
1250
  }
1243
1251
  }, [autoSaveId, layout, storage]);
1244
1252
 
@@ -1467,7 +1475,11 @@ function PanelGroupWithForwardedRef({
1467
1475
  // default size should be restored from local storage if possible.
1468
1476
  let unsafeLayout = null;
1469
1477
  if (autoSaveId) {
1470
- unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
1478
+ const state = loadPanelGroupState(autoSaveId, panelDataArray, storage);
1479
+ if (state) {
1480
+ panelSizeBeforeCollapseRef.current = new Map(Object.entries(state.expandToSizes));
1481
+ unsafeLayout = state.layout;
1482
+ }
1471
1483
  }
1472
1484
  if (unsafeLayout == null) {
1473
1485
  unsafeLayout = calculateUnsafeDefaultLayout({
@@ -835,11 +835,15 @@ function initializeDefaultStorage(storageObject) {
835
835
  }
836
836
  }
837
837
 
838
+ function getPanelGroupKey(autoSaveId) {
839
+ return `react-resizable-panels:${autoSaveId}`;
840
+ }
841
+
838
842
  // Note that Panel ids might be user-provided (stable) or useId generated (non-deterministic)
839
843
  // so they should not be used as part of the serialization key.
840
844
  // Using the min/max size attributes should work well enough as a backup.
841
845
  // Pre-sorting by minSize allows remembering layouts even if panels are re-ordered/dragged.
842
- function getSerializationKey(panels) {
846
+ function getPanelKey(panels) {
843
847
  return panels.map(panel => {
844
848
  const {
845
849
  constraints,
@@ -850,13 +854,14 @@ function getSerializationKey(panels) {
850
854
  if (idIsFromProps) {
851
855
  return id;
852
856
  } else {
853
- return `${order}:${JSON.stringify(constraints)}`;
857
+ return order ? `${order}:${JSON.stringify(constraints)}` : JSON.stringify(constraints);
854
858
  }
855
859
  }).sort((a, b) => a.localeCompare(b)).join(",");
856
860
  }
857
861
  function loadSerializedPanelGroupState(autoSaveId, storage) {
858
862
  try {
859
- const serialized = storage.getItem(`PanelGroup:sizes:${autoSaveId}`);
863
+ const panelGroupKey = getPanelGroupKey(autoSaveId);
864
+ const serialized = storage.getItem(panelGroupKey);
860
865
  if (serialized) {
861
866
  const parsed = JSON.parse(serialized);
862
867
  if (typeof parsed === "object" && parsed != null) {
@@ -866,12 +871,17 @@ function loadSerializedPanelGroupState(autoSaveId, storage) {
866
871
  } catch (error) {}
867
872
  return null;
868
873
  }
869
- function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
870
- const key = getSerializationKey(panels);
871
- const state = loadSerializedPanelGroupState(autoSaveId, storage) || {};
872
- state[key] = sizes;
874
+ function savePanelGroupState(autoSaveId, panels, panelSizesBeforeCollapse, sizes, storage) {
875
+ var _loadSerializedPanelG2;
876
+ const panelGroupKey = getPanelGroupKey(autoSaveId);
877
+ const panelKey = getPanelKey(panels);
878
+ const state = (_loadSerializedPanelG2 = loadSerializedPanelGroupState(autoSaveId, storage)) !== null && _loadSerializedPanelG2 !== void 0 ? _loadSerializedPanelG2 : {};
879
+ state[panelKey] = {
880
+ expandToSizes: Object.fromEntries(panelSizesBeforeCollapse.entries()),
881
+ layout: sizes
882
+ };
873
883
  try {
874
- storage.setItem(`PanelGroup:sizes:${autoSaveId}`, JSON.stringify(state));
884
+ storage.setItem(panelGroupKey, JSON.stringify(state));
875
885
  } catch (error) {
876
886
  console.error(error);
877
887
  }
@@ -1015,7 +1025,6 @@ function PanelGroupWithForwardedRef({
1015
1025
  const groupId = useUniqueId(idFromProps);
1016
1026
  const [dragState, setDragState] = useState(null);
1017
1027
  const [layout, setLayout] = useState([]);
1018
- useState([]);
1019
1028
  const panelIdToLastNotifiedSizeMapRef = useRef({});
1020
1029
  const panelSizeBeforeCollapseRef = useRef(new Map());
1021
1030
  const prevDeltaRef = useRef(0);
@@ -1090,13 +1099,15 @@ function PanelGroupWithForwardedRef({
1090
1099
 
1091
1100
  // Limit the frequency of localStorage updates.
1092
1101
  if (debouncedSave == null) {
1093
- debouncedSave = debounce(savePanelGroupLayout, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
1102
+ debouncedSave = debounce(savePanelGroupState, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
1094
1103
  debounceMap[autoSaveId] = debouncedSave;
1095
1104
  }
1096
1105
 
1097
- // Clone panel data array before saving since this array is mutated.
1098
- // If we don't clone, we run the risk of saving the wrong panel and layout pair.
1099
- debouncedSave(autoSaveId, [...panelDataArray], layout, storage);
1106
+ // Clone mutable data before passing to the debounced function,
1107
+ // else we run the risk of saving an incorrect combination of mutable and immutable values to state.
1108
+ const clonedPanelDataArray = [...panelDataArray];
1109
+ const clonedPanelSizesBeforeCollapse = new Map(panelSizeBeforeCollapseRef.current);
1110
+ debouncedSave(autoSaveId, clonedPanelDataArray, clonedPanelSizesBeforeCollapse, layout, storage);
1100
1111
  }
1101
1112
  }, [autoSaveId, layout, storage]);
1102
1113
 
@@ -811,11 +811,15 @@ function initializeDefaultStorage(storageObject) {
811
811
  }
812
812
  }
813
813
 
814
+ function getPanelGroupKey(autoSaveId) {
815
+ return `react-resizable-panels:${autoSaveId}`;
816
+ }
817
+
814
818
  // Note that Panel ids might be user-provided (stable) or useId generated (non-deterministic)
815
819
  // so they should not be used as part of the serialization key.
816
820
  // Using the min/max size attributes should work well enough as a backup.
817
821
  // Pre-sorting by minSize allows remembering layouts even if panels are re-ordered/dragged.
818
- function getSerializationKey(panels) {
822
+ function getPanelKey(panels) {
819
823
  return panels.map(panel => {
820
824
  const {
821
825
  constraints,
@@ -826,13 +830,14 @@ function getSerializationKey(panels) {
826
830
  if (idIsFromProps) {
827
831
  return id;
828
832
  } else {
829
- return `${order}:${JSON.stringify(constraints)}`;
833
+ return order ? `${order}:${JSON.stringify(constraints)}` : JSON.stringify(constraints);
830
834
  }
831
835
  }).sort((a, b) => a.localeCompare(b)).join(",");
832
836
  }
833
837
  function loadSerializedPanelGroupState(autoSaveId, storage) {
834
838
  try {
835
- const serialized = storage.getItem(`PanelGroup:sizes:${autoSaveId}`);
839
+ const panelGroupKey = getPanelGroupKey(autoSaveId);
840
+ const serialized = storage.getItem(panelGroupKey);
836
841
  if (serialized) {
837
842
  const parsed = JSON.parse(serialized);
838
843
  if (typeof parsed === "object" && parsed != null) {
@@ -842,12 +847,17 @@ function loadSerializedPanelGroupState(autoSaveId, storage) {
842
847
  } catch (error) {}
843
848
  return null;
844
849
  }
845
- function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
846
- const key = getSerializationKey(panels);
847
- const state = loadSerializedPanelGroupState(autoSaveId, storage) || {};
848
- state[key] = sizes;
850
+ function savePanelGroupState(autoSaveId, panels, panelSizesBeforeCollapse, sizes, storage) {
851
+ var _loadSerializedPanelG2;
852
+ const panelGroupKey = getPanelGroupKey(autoSaveId);
853
+ const panelKey = getPanelKey(panels);
854
+ const state = (_loadSerializedPanelG2 = loadSerializedPanelGroupState(autoSaveId, storage)) !== null && _loadSerializedPanelG2 !== void 0 ? _loadSerializedPanelG2 : {};
855
+ state[panelKey] = {
856
+ expandToSizes: Object.fromEntries(panelSizesBeforeCollapse.entries()),
857
+ layout: sizes
858
+ };
849
859
  try {
850
- storage.setItem(`PanelGroup:sizes:${autoSaveId}`, JSON.stringify(state));
860
+ storage.setItem(panelGroupKey, JSON.stringify(state));
851
861
  } catch (error) {
852
862
  console.error(error);
853
863
  }
@@ -991,7 +1001,6 @@ function PanelGroupWithForwardedRef({
991
1001
  const groupId = useUniqueId(idFromProps);
992
1002
  const [dragState, setDragState] = useState(null);
993
1003
  const [layout, setLayout] = useState([]);
994
- useState([]);
995
1004
  const panelIdToLastNotifiedSizeMapRef = useRef({});
996
1005
  const panelSizeBeforeCollapseRef = useRef(new Map());
997
1006
  const prevDeltaRef = useRef(0);
@@ -1066,13 +1075,15 @@ function PanelGroupWithForwardedRef({
1066
1075
 
1067
1076
  // Limit the frequency of localStorage updates.
1068
1077
  if (debouncedSave == null) {
1069
- debouncedSave = debounce(savePanelGroupLayout, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
1078
+ debouncedSave = debounce(savePanelGroupState, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
1070
1079
  debounceMap[autoSaveId] = debouncedSave;
1071
1080
  }
1072
1081
 
1073
- // Clone panel data array before saving since this array is mutated.
1074
- // If we don't clone, we run the risk of saving the wrong panel and layout pair.
1075
- debouncedSave(autoSaveId, [...panelDataArray], layout, storage);
1082
+ // Clone mutable data before passing to the debounced function,
1083
+ // else we run the risk of saving an incorrect combination of mutable and immutable values to state.
1084
+ const clonedPanelDataArray = [...panelDataArray];
1085
+ const clonedPanelSizesBeforeCollapse = new Map(panelSizeBeforeCollapseRef.current);
1086
+ debouncedSave(autoSaveId, clonedPanelDataArray, clonedPanelSizesBeforeCollapse, layout, storage);
1076
1087
  }
1077
1088
  }, [autoSaveId, layout, storage]);
1078
1089
 
@@ -939,11 +939,15 @@ function initializeDefaultStorage(storageObject) {
939
939
  }
940
940
  }
941
941
 
942
+ function getPanelGroupKey(autoSaveId) {
943
+ return `react-resizable-panels:${autoSaveId}`;
944
+ }
945
+
942
946
  // Note that Panel ids might be user-provided (stable) or useId generated (non-deterministic)
943
947
  // so they should not be used as part of the serialization key.
944
948
  // Using the min/max size attributes should work well enough as a backup.
945
949
  // Pre-sorting by minSize allows remembering layouts even if panels are re-ordered/dragged.
946
- function getSerializationKey(panels) {
950
+ function getPanelKey(panels) {
947
951
  return panels.map(panel => {
948
952
  const {
949
953
  constraints,
@@ -954,13 +958,14 @@ function getSerializationKey(panels) {
954
958
  if (idIsFromProps) {
955
959
  return id;
956
960
  } else {
957
- return `${order}:${JSON.stringify(constraints)}`;
961
+ return order ? `${order}:${JSON.stringify(constraints)}` : JSON.stringify(constraints);
958
962
  }
959
963
  }).sort((a, b) => a.localeCompare(b)).join(",");
960
964
  }
961
965
  function loadSerializedPanelGroupState(autoSaveId, storage) {
962
966
  try {
963
- const serialized = storage.getItem(`PanelGroup:sizes:${autoSaveId}`);
967
+ const panelGroupKey = getPanelGroupKey(autoSaveId);
968
+ const serialized = storage.getItem(panelGroupKey);
964
969
  if (serialized) {
965
970
  const parsed = JSON.parse(serialized);
966
971
  if (typeof parsed === "object" && parsed != null) {
@@ -970,21 +975,23 @@ function loadSerializedPanelGroupState(autoSaveId, storage) {
970
975
  } catch (error) {}
971
976
  return null;
972
977
  }
973
- function loadPanelLayout(autoSaveId, panels, storage) {
974
- const state = loadSerializedPanelGroupState(autoSaveId, storage);
975
- if (state) {
976
- var _state$key;
977
- const key = getSerializationKey(panels);
978
- return (_state$key = state[key]) !== null && _state$key !== void 0 ? _state$key : null;
979
- }
980
- return null;
978
+ function loadPanelGroupState(autoSaveId, panels, storage) {
979
+ var _loadSerializedPanelG, _state$panelKey;
980
+ const state = (_loadSerializedPanelG = loadSerializedPanelGroupState(autoSaveId, storage)) !== null && _loadSerializedPanelG !== void 0 ? _loadSerializedPanelG : {};
981
+ const panelKey = getPanelKey(panels);
982
+ return (_state$panelKey = state[panelKey]) !== null && _state$panelKey !== void 0 ? _state$panelKey : null;
981
983
  }
982
- function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
983
- const key = getSerializationKey(panels);
984
- const state = loadSerializedPanelGroupState(autoSaveId, storage) || {};
985
- state[key] = sizes;
984
+ function savePanelGroupState(autoSaveId, panels, panelSizesBeforeCollapse, sizes, storage) {
985
+ var _loadSerializedPanelG2;
986
+ const panelGroupKey = getPanelGroupKey(autoSaveId);
987
+ const panelKey = getPanelKey(panels);
988
+ const state = (_loadSerializedPanelG2 = loadSerializedPanelGroupState(autoSaveId, storage)) !== null && _loadSerializedPanelG2 !== void 0 ? _loadSerializedPanelG2 : {};
989
+ state[panelKey] = {
990
+ expandToSizes: Object.fromEntries(panelSizesBeforeCollapse.entries()),
991
+ layout: sizes
992
+ };
986
993
  try {
987
- storage.setItem(`PanelGroup:sizes:${autoSaveId}`, JSON.stringify(state));
994
+ storage.setItem(panelGroupKey, JSON.stringify(state));
988
995
  } catch (error) {
989
996
  console.error(error);
990
997
  }
@@ -1081,7 +1088,6 @@ function PanelGroupWithForwardedRef({
1081
1088
  const groupId = useUniqueId(idFromProps);
1082
1089
  const [dragState, setDragState] = useState(null);
1083
1090
  const [layout, setLayout] = useState([]);
1084
- useState([]);
1085
1091
  const panelIdToLastNotifiedSizeMapRef = useRef({});
1086
1092
  const panelSizeBeforeCollapseRef = useRef(new Map());
1087
1093
  const prevDeltaRef = useRef(0);
@@ -1164,13 +1170,15 @@ function PanelGroupWithForwardedRef({
1164
1170
 
1165
1171
  // Limit the frequency of localStorage updates.
1166
1172
  if (debouncedSave == null) {
1167
- debouncedSave = debounce(savePanelGroupLayout, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
1173
+ debouncedSave = debounce(savePanelGroupState, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
1168
1174
  debounceMap[autoSaveId] = debouncedSave;
1169
1175
  }
1170
1176
 
1171
- // Clone panel data array before saving since this array is mutated.
1172
- // If we don't clone, we run the risk of saving the wrong panel and layout pair.
1173
- debouncedSave(autoSaveId, [...panelDataArray], layout, storage);
1177
+ // Clone mutable data before passing to the debounced function,
1178
+ // else we run the risk of saving an incorrect combination of mutable and immutable values to state.
1179
+ const clonedPanelDataArray = [...panelDataArray];
1180
+ const clonedPanelSizesBeforeCollapse = new Map(panelSizeBeforeCollapseRef.current);
1181
+ debouncedSave(autoSaveId, clonedPanelDataArray, clonedPanelSizesBeforeCollapse, layout, storage);
1174
1182
  }
1175
1183
  }, [autoSaveId, layout, storage]);
1176
1184
 
@@ -1357,7 +1365,11 @@ function PanelGroupWithForwardedRef({
1357
1365
  // default size should be restored from local storage if possible.
1358
1366
  let unsafeLayout = null;
1359
1367
  if (autoSaveId) {
1360
- unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
1368
+ const state = loadPanelGroupState(autoSaveId, panelDataArray, storage);
1369
+ if (state) {
1370
+ panelSizeBeforeCollapseRef.current = new Map(Object.entries(state.expandToSizes));
1371
+ unsafeLayout = state.layout;
1372
+ }
1361
1373
  }
1362
1374
  if (unsafeLayout == null) {
1363
1375
  unsafeLayout = calculateUnsafeDefaultLayout({
@@ -824,11 +824,15 @@ function initializeDefaultStorage(storageObject) {
824
824
  }
825
825
  }
826
826
 
827
+ function getPanelGroupKey(autoSaveId) {
828
+ return `react-resizable-panels:${autoSaveId}`;
829
+ }
830
+
827
831
  // Note that Panel ids might be user-provided (stable) or useId generated (non-deterministic)
828
832
  // so they should not be used as part of the serialization key.
829
833
  // Using the min/max size attributes should work well enough as a backup.
830
834
  // Pre-sorting by minSize allows remembering layouts even if panels are re-ordered/dragged.
831
- function getSerializationKey(panels) {
835
+ function getPanelKey(panels) {
832
836
  return panels.map(panel => {
833
837
  const {
834
838
  constraints,
@@ -839,13 +843,14 @@ function getSerializationKey(panels) {
839
843
  if (idIsFromProps) {
840
844
  return id;
841
845
  } else {
842
- return `${order}:${JSON.stringify(constraints)}`;
846
+ return order ? `${order}:${JSON.stringify(constraints)}` : JSON.stringify(constraints);
843
847
  }
844
848
  }).sort((a, b) => a.localeCompare(b)).join(",");
845
849
  }
846
850
  function loadSerializedPanelGroupState(autoSaveId, storage) {
847
851
  try {
848
- const serialized = storage.getItem(`PanelGroup:sizes:${autoSaveId}`);
852
+ const panelGroupKey = getPanelGroupKey(autoSaveId);
853
+ const serialized = storage.getItem(panelGroupKey);
849
854
  if (serialized) {
850
855
  const parsed = JSON.parse(serialized);
851
856
  if (typeof parsed === "object" && parsed != null) {
@@ -855,12 +860,17 @@ function loadSerializedPanelGroupState(autoSaveId, storage) {
855
860
  } catch (error) {}
856
861
  return null;
857
862
  }
858
- function savePanelGroupLayout(autoSaveId, panels, sizes, storage) {
859
- const key = getSerializationKey(panels);
860
- const state = loadSerializedPanelGroupState(autoSaveId, storage) || {};
861
- state[key] = sizes;
863
+ function savePanelGroupState(autoSaveId, panels, panelSizesBeforeCollapse, sizes, storage) {
864
+ var _loadSerializedPanelG2;
865
+ const panelGroupKey = getPanelGroupKey(autoSaveId);
866
+ const panelKey = getPanelKey(panels);
867
+ const state = (_loadSerializedPanelG2 = loadSerializedPanelGroupState(autoSaveId, storage)) !== null && _loadSerializedPanelG2 !== void 0 ? _loadSerializedPanelG2 : {};
868
+ state[panelKey] = {
869
+ expandToSizes: Object.fromEntries(panelSizesBeforeCollapse.entries()),
870
+ layout: sizes
871
+ };
862
872
  try {
863
- storage.setItem(`PanelGroup:sizes:${autoSaveId}`, JSON.stringify(state));
873
+ storage.setItem(panelGroupKey, JSON.stringify(state));
864
874
  } catch (error) {
865
875
  console.error(error);
866
876
  }
@@ -957,7 +967,6 @@ function PanelGroupWithForwardedRef({
957
967
  const groupId = useUniqueId(idFromProps);
958
968
  const [dragState, setDragState] = useState(null);
959
969
  const [layout, setLayout] = useState([]);
960
- useState([]);
961
970
  const panelIdToLastNotifiedSizeMapRef = useRef({});
962
971
  const panelSizeBeforeCollapseRef = useRef(new Map());
963
972
  const prevDeltaRef = useRef(0);
@@ -1032,13 +1041,15 @@ function PanelGroupWithForwardedRef({
1032
1041
 
1033
1042
  // Limit the frequency of localStorage updates.
1034
1043
  if (debouncedSave == null) {
1035
- debouncedSave = debounce(savePanelGroupLayout, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
1044
+ debouncedSave = debounce(savePanelGroupState, LOCAL_STORAGE_DEBOUNCE_INTERVAL);
1036
1045
  debounceMap[autoSaveId] = debouncedSave;
1037
1046
  }
1038
1047
 
1039
- // Clone panel data array before saving since this array is mutated.
1040
- // If we don't clone, we run the risk of saving the wrong panel and layout pair.
1041
- debouncedSave(autoSaveId, [...panelDataArray], layout, storage);
1048
+ // Clone mutable data before passing to the debounced function,
1049
+ // else we run the risk of saving an incorrect combination of mutable and immutable values to state.
1050
+ const clonedPanelDataArray = [...panelDataArray];
1051
+ const clonedPanelSizesBeforeCollapse = new Map(panelSizeBeforeCollapseRef.current);
1052
+ debouncedSave(autoSaveId, clonedPanelDataArray, clonedPanelSizesBeforeCollapse, layout, storage);
1042
1053
  }
1043
1054
  }, [autoSaveId, layout, storage]);
1044
1055