@window-splitter/state 0.4.0 → 0.4.2

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/dist/esm/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import Cookies from "universal-cookie";
1
2
  import { raf } from "@react-spring/rafz";
2
3
  import { createMachine, assign, enqueueActions, fromPromise, } from "xstate";
3
4
  import invariant from "invariant";
@@ -70,9 +71,7 @@ export function getCursor(context) {
70
71
  }
71
72
  }
72
73
  export function prepareSnapshot(snapshot) {
73
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
74
- const snapshotContext = snapshot
75
- .context;
74
+ const snapshotContext = snapshot.context;
76
75
  snapshotContext.dragOvershoot = new Big(snapshotContext.dragOvershoot);
77
76
  for (const item of snapshotContext.items) {
78
77
  if (isPanelData(item)) {
@@ -349,6 +348,7 @@ export function getPanelPercentageSize(context, panelId) {
349
348
  /** Build the grid template from the item values. */
350
349
  export function buildTemplate(context) {
351
350
  const staticWidth = getStaticWidth(context);
351
+ let hasSeenFillPanel = false;
352
352
  return context.items
353
353
  .map((item) => {
354
354
  if (item.type === "panel") {
@@ -362,6 +362,12 @@ export function buildTemplate(context) {
362
362
  return formatUnit(item.currentValue);
363
363
  }
364
364
  else if (item.currentValue.type === "percent") {
365
+ if (!hasSeenFillPanel &&
366
+ (item.max === "1fr" ||
367
+ (item.max.type === "percent" && item.max.value.eq(100)))) {
368
+ hasSeenFillPanel = true;
369
+ return `minmax(${min}, 1fr)`;
370
+ }
365
371
  const max = item.max === "1fr" ? "100%" : formatUnit(item.max);
366
372
  return `minmax(${min}, min(calc(${item.currentValue.value} * (100% - ${staticWidth}px)), ${max}))`;
367
373
  }
@@ -467,6 +473,13 @@ export function prepareItems(context) {
467
473
  newItems.push({ ...item });
468
474
  continue;
469
475
  }
476
+ if (item.lastKnownSize) {
477
+ const lastSize = makePixelUnit(context.orientation === "horizontal"
478
+ ? item.lastKnownSize.width
479
+ : item.lastKnownSize.height);
480
+ newItems.push({ ...item, currentValue: lastSize });
481
+ continue;
482
+ }
470
483
  if (item.currentValue.type === "pixel") {
471
484
  newItems.push({ ...item });
472
485
  continue;
@@ -776,6 +789,9 @@ function handleOverflow(context) {
776
789
  }
777
790
  return { ...newContext, items: commitLayout(newContext) };
778
791
  }
792
+ function clearLastKnownSize(items) {
793
+ return items.map((i) => ({ ...i, lastKnownSize: undefined }));
794
+ }
779
795
  function getDeltaForEvent(context, event) {
780
796
  const panel = getPanelWithId(context, event.panelId);
781
797
  if (event.type === "expandPanel") {
@@ -835,15 +851,17 @@ export const groupMachine = createMachine({
835
851
  orientation: input.orientation || "horizontal",
836
852
  dragOvershoot: new Big(0),
837
853
  groupId: input.groupId,
854
+ autosaveStrategy: input.autosaveStrategy,
838
855
  }),
839
856
  states: {
840
857
  idle: {
858
+ entry: ["onAutosave"],
841
859
  on: {
842
- setActualItemsSize: { actions: ["recordActualItemSize", "onResize"] },
843
860
  dragHandleStart: { target: "dragging" },
844
861
  setPanelPixelSize: {
845
862
  actions: [
846
863
  "prepare",
864
+ "onClearLastKnownSize",
847
865
  "onSetPanelSize",
848
866
  "commit",
849
867
  "onResize",
@@ -871,7 +889,9 @@ export const groupMachine = createMachine({
871
889
  dragging: {
872
890
  entry: ["prepare"],
873
891
  on: {
874
- dragHandle: { actions: ["onDragHandle", "onResize"] },
892
+ dragHandle: {
893
+ actions: ["onClearLastKnownSize", "onDragHandle", "onResize"],
894
+ },
875
895
  dragHandleEnd: { target: "idle" },
876
896
  collapsePanel: {
877
897
  guard: "shouldCollapseToggle",
@@ -882,16 +902,16 @@ export const groupMachine = createMachine({
882
902
  actions: "runCollapseToggle",
883
903
  },
884
904
  },
885
- exit: ["commit", "onAutosave"],
905
+ exit: ["commit"],
886
906
  },
887
907
  togglingCollapse: {
888
- entry: ["prepare"],
908
+ entry: ["prepare", "onClearLastKnownSize"],
889
909
  invoke: {
890
910
  src: "animation",
891
911
  input: (i) => ({ ...i, send: i.self.send }),
892
912
  onDone: {
893
913
  target: "idle",
894
- actions: ["onToggleCollapseComplete", "commit", "onAutosave"],
914
+ actions: ["onToggleCollapseComplete", "commit"],
895
915
  },
896
916
  },
897
917
  on: {
@@ -900,25 +920,44 @@ export const groupMachine = createMachine({
900
920
  },
901
921
  },
902
922
  on: {
923
+ setActualItemsSize: { actions: ["recordActualItemSize", "onResize"] },
903
924
  registerPanel: { actions: ["assignPanelData"] },
925
+ rebindPanelCallbacks: { actions: ["rebindPanelCallbacks"] },
904
926
  registerDynamicPanel: {
905
927
  actions: [
906
928
  "prepare",
907
929
  "onRegisterDynamicPanel",
930
+ "onClearLastKnownSize",
908
931
  "commit",
909
932
  "onResize",
910
933
  "onAutosave",
911
934
  ],
912
935
  },
913
936
  unregisterPanel: {
914
- actions: ["prepare", "removeItem", "commit", "onResize", "onAutosave"],
937
+ actions: [
938
+ "prepare",
939
+ "removeItem",
940
+ "onClearLastKnownSize",
941
+ "commit",
942
+ "onResize",
943
+ "onAutosave",
944
+ ],
915
945
  },
916
946
  registerPanelHandle: { actions: ["assignPanelHandleData"] },
917
947
  unregisterPanelHandle: {
918
- actions: ["prepare", "removeItem", "commit", "onResize", "onAutosave"],
948
+ actions: [
949
+ "prepare",
950
+ "removeItem",
951
+ "onClearLastKnownSize",
952
+ "commit",
953
+ "onResize",
954
+ "onAutosave",
955
+ ],
919
956
  },
920
957
  setSize: { actions: ["updateSize", "onResize"] },
921
- setOrientation: { actions: ["updateOrientation", "onResize"] },
958
+ setOrientation: {
959
+ actions: ["updateOrientation", "onClearLastKnownSize", "onResize"],
960
+ },
922
961
  },
923
962
  }, {
924
963
  guards: {
@@ -960,6 +999,24 @@ export const groupMachine = createMachine({
960
999
  animation: animationActor,
961
1000
  },
962
1001
  actions: {
1002
+ onAutosave: ({ context, self }) => {
1003
+ if (!context.autosaveStrategy || typeof window === "undefined") {
1004
+ return;
1005
+ }
1006
+ const snapshot = self.getPersistedSnapshot();
1007
+ snapshot.context.items = clearLastKnownSize(context.items);
1008
+ snapshot.value = "idle";
1009
+ const data = JSON.stringify(snapshot);
1010
+ if (context.autosaveStrategy === "localStorage") {
1011
+ localStorage.setItem(context.groupId, data);
1012
+ }
1013
+ else {
1014
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1015
+ const ActualClass = Cookies.default || Cookies;
1016
+ const cookies = new ActualClass(null, { path: "/" });
1017
+ cookies.set(context.groupId, data, { path: "/", maxAge: 31536000 });
1018
+ }
1019
+ },
963
1020
  notifyCollapseToggle: ({ context, event }) => {
964
1021
  isEvent(event, ["collapsePanel", "expandPanel"]);
965
1022
  const panel = getPanelWithId(context, event.panelId);
@@ -983,8 +1040,7 @@ export const groupMachine = createMachine({
983
1040
  }),
984
1041
  onToggleCollapseComplete: assign({
985
1042
  items: ({ context, event: e }) => {
986
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
987
- const output = e.output;
1043
+ const { output } = e;
988
1044
  invariant(output, "Expected output from animation actor");
989
1045
  const panel = getPanelWithId(context, output.panelId);
990
1046
  panel.collapsed = output.action === "collapse";
@@ -994,27 +1050,42 @@ export const groupMachine = createMachine({
994
1050
  return context.items;
995
1051
  },
996
1052
  }),
997
- updateSize: enqueueActions(({ context, event, enqueue }) => {
998
- isEvent(event, ["setSize"]);
999
- if (event.handleOverflow) {
1000
- enqueue.assign(handleOverflow({ ...context, size: event.size }));
1001
- }
1002
- else {
1003
- enqueue.assign({ size: event.size });
1004
- }
1053
+ updateSize: assign({
1054
+ size: ({ event }) => {
1055
+ isEvent(event, ["setSize"]);
1056
+ return event.size;
1057
+ },
1005
1058
  }),
1006
1059
  recordActualItemSize: assign({
1007
1060
  items: ({ context, event }) => {
1008
1061
  isEvent(event, ["setActualItemsSize"]);
1009
- const orientation = context.orientation;
1010
- for (const [id, size] of Object.entries(event.childrenSizes)) {
1011
- const item = context.items.find((i) => i.id === id);
1012
- if (!isPanelData(item)) {
1013
- continue;
1062
+ const withLastKnownSize = context.items.map((i) => {
1063
+ if (!isPanelData(i))
1064
+ return i;
1065
+ const lastKnownSize = event.childrenSizes[i.id] || i.lastKnownSize;
1066
+ return { ...i, lastKnownSize };
1067
+ });
1068
+ let totalSize = 0;
1069
+ for (const item of withLastKnownSize) {
1070
+ if (isPanelData(item)) {
1071
+ const size = item.lastKnownSize?.[context.orientation === "horizontal" ? "width" : "height"];
1072
+ // If any size is 0 don't handle overflow
1073
+ if (!size) {
1074
+ return withLastKnownSize;
1075
+ }
1076
+ totalSize += size;
1077
+ }
1078
+ else {
1079
+ totalSize += item.size.value.toNumber();
1014
1080
  }
1015
- item.currentValue = makePixelUnit(orientation === "horizontal" ? size.width : size.height);
1016
1081
  }
1017
- return commitLayout(context);
1082
+ if (totalSize > getGroupSize(context)) {
1083
+ return handleOverflow({
1084
+ ...context,
1085
+ items: prepareItems({ ...context, items: withLastKnownSize }),
1086
+ }).items;
1087
+ }
1088
+ return withLastKnownSize;
1018
1089
  },
1019
1090
  }),
1020
1091
  updateOrientation: assign({
@@ -1023,6 +1094,9 @@ export const groupMachine = createMachine({
1023
1094
  return event.orientation;
1024
1095
  },
1025
1096
  }),
1097
+ onClearLastKnownSize: assign({
1098
+ items: ({ context }) => clearLastKnownSize(context.items),
1099
+ }),
1026
1100
  assignPanelData: assign({
1027
1101
  items: ({ context, event }) => {
1028
1102
  isEvent(event, ["registerPanel"]);
@@ -1033,6 +1107,18 @@ export const groupMachine = createMachine({
1033
1107
  });
1034
1108
  },
1035
1109
  }),
1110
+ rebindPanelCallbacks: assign({
1111
+ items: ({ context, event }) => {
1112
+ isEvent(event, ["rebindPanelCallbacks"]);
1113
+ for (const item of context.items) {
1114
+ if (isPanelData(item) && item.id === event.data.id) {
1115
+ item.onCollapseChange = event.data.onCollapseChange;
1116
+ item.onResize = event.data.onResize;
1117
+ }
1118
+ }
1119
+ return context.items;
1120
+ },
1121
+ }),
1036
1122
  onRegisterDynamicPanel: assign({
1037
1123
  items: ({ context, event }) => {
1038
1124
  isEvent(event, ["registerDynamicPanel"]);
@@ -1142,7 +1228,11 @@ export const groupMachine = createMachine({
1142
1228
  onResize: ({ context }) => {
1143
1229
  for (const item of context.items) {
1144
1230
  if (isPanelData(item)) {
1145
- const pixel = clampUnit(context, item, getUnitPixelValue(context, item.currentValue));
1231
+ const pixel = item.lastKnownSize
1232
+ ? new Big(context.orientation === "horizontal"
1233
+ ? item.lastKnownSize.width
1234
+ : item.lastKnownSize.height)
1235
+ : clampUnit(context, item, getUnitPixelValue(context, item.currentValue));
1146
1236
  const groupSize = getGroupSize(context);
1147
1237
  item.onResize?.current?.({
1148
1238
  pixel: pixel.toNumber(),