@witchcraft/layout 0.4.3 → 0.5.0

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.
Files changed (126) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/FrameDragHandle.vue +3 -3
  3. package/dist/runtime/components/LayoutDragEdgeGrabbed.vue +3 -3
  4. package/dist/runtime/components/LayoutDragEdgeHandle.d.vue.ts +2 -2
  5. package/dist/runtime/components/LayoutDragEdgeHandle.vue +2 -2
  6. package/dist/runtime/components/LayoutDragEdgeHandle.vue.d.ts +2 -2
  7. package/dist/runtime/components/LayoutDragEdges.vue +5 -5
  8. package/dist/runtime/components/LayoutEdgesActiveFrame.vue +2 -2
  9. package/dist/runtime/components/LayoutFrame.vue +2 -2
  10. package/dist/runtime/components/LayoutIntersectionHandle.d.vue.ts +2 -2
  11. package/dist/runtime/components/LayoutIntersectionHandle.vue +2 -2
  12. package/dist/runtime/components/LayoutIntersectionHandle.vue.d.ts +2 -2
  13. package/dist/runtime/components/LayoutIntersections.vue +4 -4
  14. package/dist/runtime/components/LayoutWindow.d.vue.ts +54 -45
  15. package/dist/runtime/components/LayoutWindow.vue +29 -29
  16. package/dist/runtime/components/LayoutWindow.vue.d.ts +54 -45
  17. package/dist/runtime/composables/useFrames.d.ts +142 -129
  18. package/dist/runtime/composables/useFrames.js +122 -94
  19. package/dist/runtime/demo/App.vue +16 -16
  20. package/dist/runtime/demo/DemoControls.d.vue.ts +2 -2
  21. package/dist/runtime/demo/DemoControls.vue +4 -4
  22. package/dist/runtime/demo/DemoControls.vue.d.ts +2 -2
  23. package/dist/runtime/demo/tailwind.css +1 -1
  24. package/dist/runtime/helpers/createZoneSideClipPath.d.ts +2 -2
  25. package/dist/runtime/helpers/findEdgesTouchingWindow.d.ts +7 -0
  26. package/dist/runtime/helpers/findEdgesTouchingWindow.js +20 -0
  27. package/dist/runtime/helpers/{findFrameDraggableEdges.d.ts → findFrameMoveableEdges.d.ts} +2 -2
  28. package/dist/runtime/helpers/{findFrameDraggableEdges.js → findFrameMoveableEdges.js} +3 -3
  29. package/dist/runtime/helpers/{findDraggableEdge.d.ts → findMoveableEdge.d.ts} +1 -1
  30. package/dist/runtime/helpers/{findDraggableEdge.js → findMoveableEdge.js} +1 -1
  31. package/dist/runtime/helpers/index.d.ts +10 -3
  32. package/dist/runtime/helpers/index.js +10 -3
  33. package/dist/runtime/layout/createSplitDecoFromDrag.d.ts +1 -1
  34. package/dist/runtime/layout/createSplitDecoFromDrag.js +2 -2
  35. package/dist/runtime/layout/debugFrame.js +5 -1
  36. package/dist/runtime/layout/findSafeSplitEdge.d.ts +1 -1
  37. package/dist/runtime/layout/findSafeSplitEdge.js +2 -2
  38. package/dist/runtime/layout/getCloseFrameInfo.js +4 -4
  39. package/dist/runtime/layout/getFrameCollapseInfo.d.ts +1 -1
  40. package/dist/runtime/layout/getFrameCollapseInfo.js +9 -29
  41. package/dist/runtime/layout/getFrameDockInfo.d.ts +1 -1
  42. package/dist/runtime/layout/getFrameDockInfo.js +61 -44
  43. package/dist/runtime/layout/getFrameExpandInfo.d.ts +11 -0
  44. package/dist/runtime/layout/getFrameExpandInfo.js +49 -0
  45. package/dist/runtime/layout/getFrameRearrangeInfo.d.ts +2 -2
  46. package/dist/runtime/layout/getFrameRearrangeInfo.js +8 -8
  47. package/dist/runtime/layout/getFrameShrinkInfo.d.ts +14 -0
  48. package/dist/runtime/layout/getFrameShrinkInfo.js +48 -0
  49. package/dist/runtime/layout/getFrameSplitInfo.d.ts +1 -1
  50. package/dist/runtime/layout/getFrameSplitInfo.js +2 -2
  51. package/dist/runtime/layout/getFrameUncollapseInfo.d.ts +1 -1
  52. package/dist/runtime/layout/getFrameUncollapseInfo.js +6 -20
  53. package/dist/runtime/layout/{getFrameDragZones.d.ts → getFrameZones.d.ts} +3 -3
  54. package/dist/runtime/layout/{getFrameDragZones.js → getFrameZones.js} +1 -1
  55. package/dist/runtime/layout/getUpdateWindowSizeInfo.js +10 -12
  56. package/dist/runtime/layout/{getWindowDragZones.d.ts → getWindowZones.d.ts} +1 -1
  57. package/dist/runtime/layout/{getWindowDragZones.js → getWindowZones.js} +1 -1
  58. package/dist/runtime/layout/getZones.d.ts +8 -0
  59. package/dist/runtime/layout/getZones.js +32 -0
  60. package/dist/runtime/layout/index.d.ts +6 -3
  61. package/dist/runtime/layout/index.js +6 -3
  62. package/dist/runtime/{drag/DragActionHandler.d.ts → move/ActionHandler.d.ts} +18 -18
  63. package/dist/runtime/{drag/DragActionHandler.js → move/ActionHandler.js} +19 -19
  64. package/dist/runtime/{drag → move}/CloseAction.d.ts +8 -8
  65. package/dist/runtime/{drag → move}/CloseAction.js +29 -26
  66. package/dist/runtime/{drag → move}/FrameDragAction.d.ts +8 -8
  67. package/dist/runtime/{drag → move}/FrameDragAction.js +23 -21
  68. package/dist/runtime/{drag/DragDirectionStore.d.ts → move/MoveDirectionStore.d.ts} +4 -4
  69. package/dist/runtime/{drag/DragDirectionStore.js → move/MoveDirectionStore.js} +9 -9
  70. package/dist/runtime/{drag → move}/SplitAction.d.ts +9 -9
  71. package/dist/runtime/{drag → move}/SplitAction.js +46 -43
  72. package/dist/runtime/{drag → move}/createDefaultHandlers.d.ts +2 -2
  73. package/dist/runtime/types/index.d.ts +242 -158
  74. package/dist/runtime/types/index.js +4 -3
  75. package/dist/runtime/types/vue.d.ts +25 -18
  76. package/dist/runtime/types/vue.js +1 -1
  77. package/package.json +3 -2
  78. package/src/runtime/components/FrameDragHandle.vue +3 -3
  79. package/src/runtime/components/LayoutDragEdgeGrabbed.vue +3 -3
  80. package/src/runtime/components/LayoutDragEdgeHandle.vue +4 -4
  81. package/src/runtime/components/LayoutDragEdges.vue +5 -5
  82. package/src/runtime/components/LayoutEdgesActiveFrame.vue +2 -2
  83. package/src/runtime/components/LayoutFrame.vue +2 -2
  84. package/src/runtime/components/LayoutIntersectionHandle.vue +4 -4
  85. package/src/runtime/components/LayoutIntersections.vue +4 -4
  86. package/src/runtime/components/LayoutWindow.vue +35 -35
  87. package/src/runtime/composables/useFrames.ts +141 -121
  88. package/src/runtime/demo/App.vue +18 -18
  89. package/src/runtime/demo/DemoControls.vue +5 -5
  90. package/src/runtime/demo/tailwind.css +4 -0
  91. package/src/runtime/helpers/createZoneSideClipPath.ts +2 -2
  92. package/src/runtime/helpers/findEdgesTouchingWindow.ts +30 -0
  93. package/src/runtime/helpers/{findFrameDraggableEdges.ts → findFrameMoveableEdges.ts} +4 -4
  94. package/src/runtime/helpers/{findDraggableEdge.ts → findMoveableEdge.ts} +1 -1
  95. package/src/runtime/helpers/index.ts +10 -3
  96. package/src/runtime/layout/createSplitDecoFromDrag.ts +2 -2
  97. package/src/runtime/layout/debugFrame.ts +6 -1
  98. package/src/runtime/layout/findSafeSplitEdge.ts +4 -4
  99. package/src/runtime/layout/getCloseFrameInfo.ts +4 -4
  100. package/src/runtime/layout/getFrameCollapseInfo.ts +12 -41
  101. package/src/runtime/layout/getFrameDockInfo.ts +77 -57
  102. package/src/runtime/layout/getFrameExpandInfo.ts +84 -0
  103. package/src/runtime/layout/getFrameRearrangeInfo.ts +10 -10
  104. package/src/runtime/layout/getFrameShrinkInfo.ts +87 -0
  105. package/src/runtime/layout/getFrameSplitInfo.ts +5 -5
  106. package/src/runtime/layout/getFrameUncollapseInfo.ts +8 -30
  107. package/src/runtime/layout/{getFrameDragZones.ts → getFrameZones.ts} +4 -4
  108. package/src/runtime/layout/getUpdateWindowSizeInfo.ts +16 -22
  109. package/src/runtime/layout/{getWindowDragZones.ts → getWindowZones.ts} +1 -1
  110. package/src/runtime/layout/getZones.ts +48 -0
  111. package/src/runtime/layout/index.ts +6 -3
  112. package/src/runtime/{drag/DragActionHandler.ts → move/ActionHandler.ts} +44 -42
  113. package/src/runtime/{drag → move}/CloseAction.ts +39 -36
  114. package/src/runtime/{drag → move}/FrameDragAction.ts +36 -35
  115. package/src/runtime/{drag/DragDirectionStore.ts → move/MoveDirectionStore.ts} +10 -10
  116. package/src/runtime/{drag → move}/SplitAction.ts +56 -53
  117. package/src/runtime/{drag/defaultDragActions.ts → move/createDefaultHandlers.ts} +2 -2
  118. package/src/runtime/types/index.ts +104 -55
  119. package/src/runtime/types/vue.ts +18 -16
  120. package/dist/runtime/drag/defaultDragActions.d.ts +0 -9
  121. package/dist/runtime/drag/defaultDragActions.js +0 -10
  122. package/dist/runtime/layout/getDragZones.d.ts +0 -8
  123. package/dist/runtime/layout/getDragZones.js +0 -32
  124. package/src/runtime/drag/createDefaultHandlers.ts +0 -20
  125. package/src/runtime/layout/getDragZones.ts +0 -48
  126. /package/dist/runtime/{drag → move}/createDefaultHandlers.js +0 -0
@@ -9,6 +9,7 @@ export { assertValidWinAndFrameIds } from "./assertValidWinAndFrameIds.js";
9
9
  export { assertWindowHasActiveFrame } from "./assertWindowHasActiveFrame.js";
10
10
  export { cloneFrame } from "./cloneFrame.js";
11
11
  export { cloneFrames } from "./cloneFrames.js";
12
+ export { consoleDebugWindow } from "./consoleDebugWindow.js";
12
13
  export { containsEdge } from "./containsEdge.js";
13
14
  export { convertLayoutWindowToWorkspace } from "./convertLayoutWindowToWorkspace.js";
14
15
  export { copySize } from "./copySize.js";
@@ -19,19 +20,23 @@ export { dirToSide } from "./dirToSide.js";
19
20
  export { doEdgesOverlap } from "./doEdgesOverlap.js";
20
21
  export { doesEdgeContinueEdge } from "./doesEdgeContinueEdge.js";
21
22
  export { edgeToPoints } from "./edgeToPoints.js";
22
- export { findDraggableEdge } from "./findDraggableEdge.js";
23
- export { findFrameDraggableEdges } from "./findFrameDraggableEdges.js";
23
+ export { findMoveableEdge } from "./findMoveableEdge.js";
24
+ export { findFrameMoveableEdges } from "./findFrameMoveableEdges.js";
25
+ export { framesRedistributeFix } from "./framesRedistributeFix.js";
24
26
  export { frameToEdges } from "./frameToEdges.js";
25
27
  export { frameToPoints } from "./frameToPoints.js";
28
+ export { getDockBoundaries } from "./getDockBoundaries.js";
26
29
  export { getEdgeLength } from "./getEdgeLength.js";
27
30
  export { getEdgeOrientation } from "./getEdgeOrientation.js";
28
31
  export { getEdgeSharedDirection } from "./getEdgeSharedDirection.js";
29
32
  export { getEdgeSide } from "./getEdgeSide.js";
30
33
  export { getFrameById } from "./getFrameById.js";
31
34
  export { getFrameConstant } from "./getFrameConstant.js";
35
+ export { findEdgesTouchingWindow } from "./findEdgesTouchingWindow.js";
32
36
  export { getIntersections } from "./getIntersections.js";
33
37
  export { getIntersectionsCss } from "./getIntersectionsCss.js";
34
38
  export { getMoveEdgeInfo } from "./getMoveEdgeInfo.js";
39
+ export { getPinnedEdgesForCollapsedFrames } from "./getPinnedEdgesForCollapsedFrames.js";
35
40
  export { getResizeLimit } from "./getResizeLimit.js";
36
41
  export { getShapeRectCss } from "./getShapeRectCss.js";
37
42
  export { getSideTouching } from "./getSideTouching.js";
@@ -52,9 +57,10 @@ export { isWindowEdge } from "./isWindowEdge.js";
52
57
  export { isWindowEdgePoint } from "./isWindowEdgePoint.js";
53
58
  export { moveEdge } from "./moveEdge.js";
54
59
  export { numberToScaledPercent } from "./numberToScaledPercent.js";
55
- export { pxSizeToScaledSize } from "./pxSizeToScaledSize.js";
56
60
  export { oppositeSide } from "./oppositeSide.js";
61
+ export { pxSizeToScaledSize } from "./pxSizeToScaledSize.js";
57
62
  export { resizeByEdge } from "./resizeByEdge.js";
63
+ export { rotateLayout } from "./rotateFrames.js";
58
64
  export { scaledPointToPx } from "./scaledPointToPx.js";
59
65
  export { sideToDirection } from "./sideToDirection.js";
60
66
  export { sideToOrientation } from "./sideToOrientation.js";
@@ -64,3 +70,4 @@ export { toId } from "./toId.js";
64
70
  export { toWindowCoord } from "./toWindowCoord.js";
65
71
  export { unionEdges } from "./unionEdges.js";
66
72
  export { updateWindowWithEvent } from "./updateWindowSizeWithEvent.js";
73
+ export { validateLayoutShape } from "./validateLayoutShape.js";
@@ -1,5 +1,5 @@
1
1
  import type { Direction, LayoutFrame, Point, Size, SplitDeco } from "../types/index.js";
2
- export declare function createSplitDecoFromDrag(frames: Record<string, LayoutFrame>, frame: LayoutFrame, dragDirection: Direction, dragPoint: Point, snapAmount?: Point, minSize?: Size, classes?: {
2
+ export declare function createSplitDecoFromDrag(frames: Record<string, LayoutFrame>, frame: LayoutFrame, dragDirection: Direction, movePoint: Point, snapAmount?: Point, minSize?: Size, classes?: {
3
3
  /** @default "deco-split-edge bg-red-500" */
4
4
  splitEdge?: string;
5
5
  /** @default "deco-split-new-frame bg-blue-500/50" */
@@ -1,12 +1,12 @@
1
1
  import { createSplitDecoShapes } from "./createSplitDecoShapes.js";
2
2
  import { dirToOrientation } from "../helpers/dirToOrientation.js";
3
3
  import { settings } from "../settings.js";
4
- export function createSplitDecoFromDrag(frames, frame, dragDirection, dragPoint, snapAmount = settings.snapPointScaled, minSize = settings.minSizeScaled, classes = {}) {
4
+ export function createSplitDecoFromDrag(frames, frame, dragDirection, movePoint, snapAmount = settings.snapPointScaled, minSize = settings.minSizeScaled, classes = {}) {
5
5
  const orientation = dirToOrientation(dragDirection);
6
6
  const deco = {
7
7
  type: "split",
8
8
  id: frame.id,
9
- position: dragPoint[orientation === "horizontal" ? "x" : "y"],
9
+ position: movePoint[orientation === "horizontal" ? "x" : "y"],
10
10
  direction: dragDirection
11
11
  };
12
12
  deco.shapes = createSplitDecoShapes(frames, deco, snapAmount, minSize, classes);
@@ -1,5 +1,9 @@
1
+ import { keys } from "@alanscodelog/utils/keys";
2
+ const builtinProperties = ["id", "x", "y", "width", "height", "docked", "collapsed"];
1
3
  export function debugFrame(frame) {
2
4
  const f = frame;
5
+ const otherProperties = keys(f).filter((k) => !builtinProperties.includes(k)).map((k) => `${k}: ${f[k]}`);
6
+ const otherPropertiesString = otherProperties.length > 0 ? `, ${otherProperties.join(", ")}` : "";
3
7
  return `id: ${f.id.slice(0, 4)}, x: ${f.x}, y: ${f.y}, w: ${f.width}, h: ${f.height}
4
- docked: ${f.docked}, collapsed: ${f.collapsed}`;
8
+ docked: ${f.docked}, collapsed: ${f.collapsed}${otherPropertiesString}`;
5
9
  }
@@ -1,5 +1,5 @@
1
1
  import type { Direction, Edge, LayoutFrame, Point, Size } from "../types/index.js";
2
- export declare function findSafeSplitEdgeAndPosition(frame: LayoutFrame, dragDirection: Direction, dragPointOrPosition: Point | number, snapAmount?: Point, minSize?: Size): {
2
+ export declare function findSafeSplitEdgeAndPosition(frame: LayoutFrame, dragDirection: Direction, movePointOrPosition: Point | number, snapAmount?: Point, minSize?: Size): {
3
3
  edge: Edge;
4
4
  position: number;
5
5
  };
@@ -2,9 +2,9 @@ import { clampNumber, snapNumber } from "@alanscodelog/utils";
2
2
  import { dirToOrientation } from "../helpers/dirToOrientation.js";
3
3
  import { oppositeSide } from "../helpers/oppositeSide.js";
4
4
  import { settings } from "../settings.js";
5
- export function findSafeSplitEdgeAndPosition(frame, dragDirection, dragPointOrPosition, snapAmount = settings.snapPointScaled, minSize = settings.minSizeScaled) {
5
+ export function findSafeSplitEdgeAndPosition(frame, dragDirection, movePointOrPosition, snapAmount = settings.snapPointScaled, minSize = settings.minSizeScaled) {
6
6
  const orientation = dirToOrientation(dragDirection);
7
- const position = typeof dragPointOrPosition === "number" ? dragPointOrPosition : dragPointOrPosition[orientation === "horizontal" ? "x" : "y"];
7
+ const position = typeof movePointOrPosition === "number" ? movePointOrPosition : movePointOrPosition[orientation === "horizontal" ? "x" : "y"];
8
8
  const coordKey = orientation === "vertical" ? "y" : "x";
9
9
  const sizeKey = orientation === "vertical" ? "height" : "width";
10
10
  const pos = snapNumber(position, snapAmount[coordKey]);
@@ -5,7 +5,7 @@ import { findFramesTouchingEdge } from "./findFramesTouchingEdge.js";
5
5
  import { findVisualEdge } from "./findVisualEdge.js";
6
6
  import { cloneFrame } from "../helpers/cloneFrame.js";
7
7
  import { dirToSide } from "../helpers/dirToSide.js";
8
- import { findFrameDraggableEdges } from "../helpers/findFrameDraggableEdges.js";
8
+ import { findFrameMoveableEdges } from "../helpers/findFrameMoveableEdges.js";
9
9
  import { getEdgeOrientation } from "../helpers/getEdgeOrientation.js";
10
10
  import { oppositeSide } from "../helpers/oppositeSide.js";
11
11
  import { settings } from "../settings.js";
@@ -28,9 +28,9 @@ export function getCloseFrameInfo(frames, visualEdges, frame, closeDirOrSide, cl
28
28
  }
29
29
  const side = closeBy === "dir" ? oppositeSide(dirToSide(closeDirOrSide)) : closeDirOrSide;
30
30
  const sideOpposite = oppositeSide(side);
31
- const draggableEdges = findFrameDraggableEdges(frame, visualEdges, !force, [side]);
32
- if (!draggableEdges) return new KnownError(LAYOUT_ERROR.CANT_CLOSE_NO_DRAG_EDGE, `Could not find draggable edge for frame ${frame.id}`, { frame });
33
- const { edge: frameEdge } = draggableEdges[0];
31
+ const moveableEdges = findFrameMoveableEdges(frame, visualEdges, !force, [side]);
32
+ if (!moveableEdges) return new KnownError(LAYOUT_ERROR.CANT_CLOSE_NO_DRAG_EDGE, `Could not find draggable edge for frame ${frame.id}`, { frame });
33
+ const { edge: frameEdge } = moveableEdges[0];
34
34
  const visualEdge = findVisualEdge(visualEdges, frameEdge);
35
35
  if (visualEdge === void 0) unreachable();
36
36
  const direction = oppositeSide(getEdgeOrientation(visualEdge));
@@ -13,4 +13,4 @@ import { KnownError } from "../utils/KnownError.js";
13
13
  export declare function getFrameCollapseInfo(win: LayoutWindow, frameId: string, { collapseSizeScaled }?: {
14
14
  /** Override the target collapse size. If provided, the frame will collapse to this size instead of settings.collapseSizeScaled. */
15
15
  collapseSizeScaled?: Size;
16
- }): LayoutChange | KnownError<typeof LAYOUT_ERROR.CANT_COLLAPSE_NOT_DOCKED> | KnownError<typeof LAYOUT_ERROR.REDISTRIBUTE_WOULD_RESULT_IN_INVALID_FRAMES>;
16
+ }): LayoutChange | KnownError<typeof LAYOUT_ERROR.CANT_COLLAPSE_NOT_DOCKED> | KnownError<typeof LAYOUT_ERROR.REDISTRIBUTE_WOULD_RESULT_IN_INVALID_FRAMES> | KnownError<typeof LAYOUT_ERROR.CANT_RESIZE_SINGLE_FRAME>;
@@ -1,10 +1,7 @@
1
1
  import { pushIfNotIn } from "@alanscodelog/utils/pushIfNotIn";
2
2
  import { walk } from "@alanscodelog/utils/walk";
3
3
  import { applyFrameChanges } from "./applyFrameChanges.js";
4
- import { getFramesRedistributeInfo } from "./getFramesRedistributeInfo.js";
5
- import { framesRedistributeFix } from "../helpers/framesRedistributeFix.js";
6
- import { getPinnedEdgesForCollapsedFrames } from "../helpers/getPinnedEdgesForCollapsedFrames.js";
7
- import { oppositeSide } from "../helpers/oppositeSide.js";
4
+ import { getFrameShrinkInfo } from "./getFrameShrinkInfo.js";
8
5
  import { settings } from "../settings.js";
9
6
  import { LAYOUT_ERROR } from "../types/index.js";
10
7
  import { KnownError } from "../utils/KnownError.js";
@@ -27,35 +24,18 @@ export function getFrameCollapseInfo(win, frameId, {
27
24
  }
28
25
  const isVertical = frame.docked === "left" || frame.docked === "right";
29
26
  const sizeKey = isVertical ? "width" : "height";
30
- const posKey = isVertical ? "x" : "y";
31
- const oppositePosKey = isVertical ? "y" : "x";
32
- const oppositeSizeKey = isVertical ? "height" : "width";
33
27
  const currentSize = frame[sizeKey];
34
- const collapseAmount = collapseSizeScaled[sizeKey];
35
- const shrinkAmount = currentSize - collapseAmount;
36
- const dockedSide = frame.docked;
37
- const { applyFixes, toFix } = framesRedistributeFix(win, frame, dockedSide, posKey, sizeKey, "shrink");
38
- const otherFrameIds = Object.keys(win.frames).filter((id) => id !== frameId);
39
- const redistributeSide = oppositeSide(dockedSide);
40
- const pinnedEdgeCoordinates = getPinnedEdgesForCollapsedFrames(win, frame, dockedSide, posKey, sizeKey);
41
- const changes = getFramesRedistributeInfo(win, redistributeSide, otherFrameIds, -shrinkAmount, { allowOutOfBounds: true, pinnedEdgeCoordinates });
42
- if (changes instanceof KnownError) {
43
- if (changes.code === LAYOUT_ERROR.REDISTRIBUTE_OUT_OF_BOUNDS || changes.code === LAYOUT_ERROR.NO_SPACE_TO_REDISTRIBUTE) {
44
- changes.message = `This error should never happen, please file a bug report: ${changes.message}`;
45
- throw changes;
46
- }
47
- return changes;
28
+ const shrinkAmount = currentSize - collapseSizeScaled[sizeKey];
29
+ const shrinkResult = getFrameShrinkInfo(win, frameId, shrinkAmount, frame.docked, { allowOutOfBounds: true });
30
+ if (shrinkResult instanceof KnownError) {
31
+ return shrinkResult;
48
32
  }
49
- applyFrameChanges(win, changes);
50
- pushIfNotIn(toExtract, changes.modified.map((_) => _.id));
51
- applyFixes();
52
- pushIfNotIn(toExtract, toFix);
53
- if (frame.docked === "right" || frame.docked === "bottom") {
54
- frame[posKey] = frame[posKey] + (frame[sizeKey] - collapseSizeScaled[sizeKey]);
55
- }
56
- frame[sizeKey] = collapseSizeScaled[sizeKey];
33
+ applyFrameChanges(win, shrinkResult);
34
+ pushIfNotIn(toExtract, shrinkResult.modified.map((_) => _.id));
57
35
  frame.collapsed = currentSize;
58
36
  if (collapseSizeScaled[sizeKey] === 0) {
37
+ const oppositePosKey = isVertical ? "y" : "x";
38
+ const oppositeSizeKey = isVertical ? "height" : "width";
59
39
  frame[oppositePosKey] = 0;
60
40
  frame[oppositeSizeKey] = settings.maxInt;
61
41
  }
@@ -6,4 +6,4 @@ import { KnownError } from "../utils/KnownError.js";
6
6
  *
7
7
  * Changes can be applied to a window with {@link applyFrameChanges}.
8
8
  */
9
- export declare function getFrameDockInfo(win: LayoutWindow, frameId: string, side: EdgeSide, maxPerpendicularLength?: number): LayoutChange | KnownError<typeof LAYOUT_ERROR.REDISTRIBUTE_OUT_OF_BOUNDS> | KnownError<typeof LAYOUT_ERROR.NO_SPACE_TO_REDISTRIBUTE> | KnownError<typeof LAYOUT_ERROR.REDISTRIBUTE_WOULD_RESULT_IN_INVALID_FRAMES> | KnownError<typeof LAYOUT_ERROR.CANT_LEAVE_NO_UNDOCKED_FRAMES> | KnownError<typeof LAYOUT_ERROR.FRAME_ALREADY_DOCKED_ON_SIDE> | KnownError<typeof LAYOUT_ERROR.CANT_UNDOCK_COLLAPSED_FRAME> | KnownError<typeof LAYOUT_ERROR.NO_FILL_CANDIDATES>;
9
+ export declare function getFrameDockInfo(win: LayoutWindow, frameId: string, side: EdgeSide, maxPerpendicularLength?: number): LayoutChange | KnownError<typeof LAYOUT_ERROR.REDISTRIBUTE_OUT_OF_BOUNDS> | KnownError<typeof LAYOUT_ERROR.NO_SPACE_TO_REDISTRIBUTE> | KnownError<typeof LAYOUT_ERROR.REDISTRIBUTE_WOULD_RESULT_IN_INVALID_FRAMES> | KnownError<typeof LAYOUT_ERROR.CANT_LEAVE_NO_UNDOCKED_FRAMES> | KnownError<typeof LAYOUT_ERROR.FRAME_ALREADY_DOCKED_ON_SIDE> | KnownError<typeof LAYOUT_ERROR.CANT_UNDOCK_COLLAPSED_FRAME> | KnownError<typeof LAYOUT_ERROR.NO_FILL_CANDIDATES> | KnownError<typeof LAYOUT_ERROR.CANT_RESIZE_SINGLE_FRAME>;
@@ -2,9 +2,11 @@ import { pushIfNotIn } from "@alanscodelog/utils/pushIfNotIn";
2
2
  import { walk } from "@alanscodelog/utils/walk";
3
3
  import { applyFrameChanges } from "./applyFrameChanges.js";
4
4
  import { getFillEmptySpaceInfo } from "./getFillEmptySpaceInfo.js";
5
+ import { getFrameShrinkInfo } from "./getFrameShrinkInfo.js";
5
6
  import { getFramesRedistributeInfo } from "./getFramesRedistributeInfo.js";
6
7
  import { getFrameUndockInfo } from "./getFrameUndockInfo.js";
7
8
  import { cloneFrame } from "../helpers/cloneFrame.js";
9
+ import { findEdgesTouchingWindow } from "../helpers/findEdgesTouchingWindow.js";
8
10
  import { getDockBoundaries } from "../helpers/getDockBoundaries.js";
9
11
  import { getPinnedEdgesForCollapsedFrames } from "../helpers/getPinnedEdgesForCollapsedFrames.js";
10
12
  import { oppositeSide } from "../helpers/oppositeSide.js";
@@ -29,58 +31,73 @@ export function getFrameDockInfo(win, frameId, side, maxPerpendicularLength) {
29
31
  }
30
32
  const isHorizontal = side === "left" || side === "right";
31
33
  const perpendicular = isHorizontal ? "width" : "height";
32
- const oldFrame = cloneFrame(frame);
34
+ const posKey = isHorizontal ? "x" : "y";
35
+ const sizeKey = isHorizontal ? "width" : "height";
33
36
  const otherFrameIds = Object.keys(win.frames).filter((_) => _ !== frameId);
34
37
  const nonDockedFrameIds = otherFrameIds.filter((id) => !win.frames[id].docked);
35
38
  if (nonDockedFrameIds.length === 0) {
36
39
  return new KnownError(LAYOUT_ERROR.CANT_LEAVE_NO_UNDOCKED_FRAMES, `Can't dock frame ${frameId} because there are no other undocked frames.`, { frameId });
37
40
  }
38
- const effectiveMaxPerpendicular = maxPerpendicularLength ?? settings.maxPerpendicularLengthScaled.width;
39
- const perpendicularLength = otherFrameIds.length > 0 ? Math.min(frame[perpendicular], effectiveMaxPerpendicular) : frame[perpendicular];
41
+ const maxPerpendicular = maxPerpendicularLength ?? settings.maxPerpendicularLengthScaled.width;
42
+ const perpendicularLength = otherFrameIds.length > 0 ? Math.min(frame[perpendicular], maxPerpendicular) : frame[perpendicular];
40
43
  frame.docked = side;
41
44
  frame.collapsed = void 0;
42
45
  const toExtract = [frame.id];
43
- const changes = getFillEmptySpaceInfo(win, oldFrame, [], [frameId]);
44
- if (changes instanceof Error) return changes;
45
- applyFrameChanges(win, changes);
46
- pushIfNotIn(toExtract, changes.modified.map((_) => _.id));
47
- const sideToPushTowards = oppositeSide(side);
48
- const posKey = isHorizontal ? "x" : "y";
49
- const sizeKey = isHorizontal ? "width" : "height";
50
- const pinnedEdgeCoordinates = getPinnedEdgesForCollapsedFrames(win, frame, side, posKey, sizeKey);
51
- const redistributeChanges = getFramesRedistributeInfo(win, sideToPushTowards, nonDockedFrameIds, perpendicularLength, { pinnedEdgeCoordinates });
52
- if (redistributeChanges instanceof KnownError) {
53
- return redistributeChanges;
46
+ if (frame[perpendicular] === perpendicularLength) {
47
+ return { modified: toExtract.map((_) => win.frames[_]), created: [], deleted: [] };
54
48
  }
55
- applyFrameChanges(win, redistributeChanges);
56
- pushIfNotIn(toExtract, redistributeChanges.modified.map((_) => _.id));
57
- const { minX, maxX, minY, maxY } = getDockBoundaries(win);
58
- switch (side) {
59
- case "left":
60
- frame.x = 0;
61
- frame.y = minY;
62
- frame.width = perpendicularLength;
63
- frame.height = maxY - minY;
64
- break;
65
- case "right":
66
- frame.x = settings.maxInt - perpendicularLength;
67
- frame.y = minY;
68
- frame.width = perpendicularLength;
69
- frame.height = maxY - minY;
70
- break;
71
- case "top":
72
- frame.x = minX;
73
- frame.y = 0;
74
- frame.width = maxX - minX;
75
- frame.height = perpendicularLength;
76
- break;
77
- case "bottom":
78
- frame.x = minX;
79
- frame.y = settings.maxInt - perpendicularLength;
80
- frame.width = maxX - minX;
81
- frame.height = perpendicularLength;
82
- break;
49
+ const touchesEntireEdge = findEdgesTouchingWindow(frame)[side] === "full";
50
+ if (touchesEntireEdge) {
51
+ const shrinkAmount = frame[sizeKey] - perpendicularLength;
52
+ if (shrinkAmount > 0) {
53
+ const shrinkResult = getFrameShrinkInfo(win, frameId, shrinkAmount, side);
54
+ if (shrinkResult instanceof KnownError) {
55
+ return shrinkResult;
56
+ }
57
+ applyFrameChanges(win, shrinkResult);
58
+ pushIfNotIn(toExtract, shrinkResult.modified.map((_) => _.id));
59
+ }
60
+ } else {
61
+ const oldFrame = cloneFrame(frame);
62
+ const changes = getFillEmptySpaceInfo(win, oldFrame, [], [frameId]);
63
+ if (changes instanceof Error) return changes;
64
+ applyFrameChanges(win, changes);
65
+ pushIfNotIn(toExtract, changes.modified.map((_) => _.id));
66
+ const sideToPushTowards = oppositeSide(side);
67
+ const pinnedEdgeCoordinates = getPinnedEdgesForCollapsedFrames(win, frame, side, posKey, sizeKey);
68
+ const redistributeChanges = getFramesRedistributeInfo(win, sideToPushTowards, nonDockedFrameIds, perpendicularLength, { pinnedEdgeCoordinates });
69
+ if (redistributeChanges instanceof KnownError) {
70
+ return redistributeChanges;
71
+ }
72
+ applyFrameChanges(win, redistributeChanges);
73
+ pushIfNotIn(toExtract, redistributeChanges.modified.map((_) => _.id));
74
+ const { minX, maxX, minY, maxY } = getDockBoundaries(win);
75
+ switch (side) {
76
+ case "left":
77
+ frame.x = 0;
78
+ frame.y = minY;
79
+ frame.width = perpendicularLength;
80
+ frame.height = maxY - minY;
81
+ break;
82
+ case "right":
83
+ frame.x = settings.maxInt - perpendicularLength;
84
+ frame.y = minY;
85
+ frame.width = perpendicularLength;
86
+ frame.height = maxY - minY;
87
+ break;
88
+ case "top":
89
+ frame.x = minX;
90
+ frame.y = 0;
91
+ frame.width = maxX - minX;
92
+ frame.height = perpendicularLength;
93
+ break;
94
+ case "bottom":
95
+ frame.x = minX;
96
+ frame.y = settings.maxInt - perpendicularLength;
97
+ frame.width = maxX - minX;
98
+ frame.height = perpendicularLength;
99
+ break;
100
+ }
83
101
  }
84
- const res = toExtract.map((_) => win.frames[_]);
85
- return { modified: res, created: [], deleted: [] };
102
+ return { modified: toExtract.map((_) => win.frames[_]), created: [], deleted: [] };
86
103
  }
@@ -0,0 +1,11 @@
1
+ import type { EdgeSide, LayoutChange, LayoutWindow } from "../types/index.js";
2
+ import { LAYOUT_ERROR } from "../types/index.js";
3
+ import { KnownError } from "../utils/KnownError.js";
4
+ /**
5
+ * Returns a {@link LayoutChange} with the information necessary to expand a frame touching a window edge by a given amount.
6
+ *
7
+ * Changes can be applied to a window with {@link applyFrameChanges}.
8
+ *
9
+ * It expands the frame by redistributing space from neighboring frames.
10
+ */
11
+ export declare function getFrameExpandInfo(win: LayoutWindow, frameId: string, amount: number, expandSide: EdgeSide): LayoutChange | KnownError<typeof LAYOUT_ERROR.REDISTRIBUTE_OUT_OF_BOUNDS> | KnownError<typeof LAYOUT_ERROR.NO_SPACE_TO_REDISTRIBUTE> | KnownError<typeof LAYOUT_ERROR.REDISTRIBUTE_WOULD_RESULT_IN_INVALID_FRAMES> | KnownError<typeof LAYOUT_ERROR.CANT_RESIZE_SINGLE_FRAME>;
@@ -0,0 +1,49 @@
1
+ import { pushIfNotIn } from "@alanscodelog/utils/pushIfNotIn";
2
+ import { walk } from "@alanscodelog/utils/walk";
3
+ import { applyFrameChanges } from "./applyFrameChanges.js";
4
+ import { getFramesRedistributeInfo } from "./getFramesRedistributeInfo.js";
5
+ import { findEdgesTouchingWindow } from "../helpers/findEdgesTouchingWindow.js";
6
+ import { framesRedistributeFix } from "../helpers/framesRedistributeFix.js";
7
+ import { getPinnedEdgesForCollapsedFrames } from "../helpers/getPinnedEdgesForCollapsedFrames.js";
8
+ import { oppositeSide } from "../helpers/oppositeSide.js";
9
+ import { LAYOUT_ERROR } from "../types/index.js";
10
+ import { KnownError } from "../utils/KnownError.js";
11
+ export function getFrameExpandInfo(win, frameId, amount, expandSide) {
12
+ win = walk(win, void 0, { save: true });
13
+ const frame = win.frames[frameId];
14
+ if (!frame) {
15
+ throw new Error(`Unknown frame ${frameId}`);
16
+ }
17
+ if (!frame.docked) {
18
+ throw new Error(`Frame ${frameId} is not docked.`);
19
+ }
20
+ const toExtract = [frame.id];
21
+ if (Object.keys(win.frames).length === 1) {
22
+ return new KnownError(LAYOUT_ERROR.CANT_RESIZE_SINGLE_FRAME, `Frame ${frameId} is the only frame, cannot expand.`, { frame });
23
+ }
24
+ if (!(expandSide in findEdgesTouchingWindow(frame))) {
25
+ throw new Error(`Frame ${frameId} does not touch the ${expandSide} edge.`);
26
+ }
27
+ const isVertical = frame.docked === "left" || frame.docked === "right";
28
+ const sizeKey = isVertical ? "width" : "height";
29
+ const posKey = isVertical ? "x" : "y";
30
+ const currentSize = frame[sizeKey];
31
+ const dockedSide = frame.docked;
32
+ const { applyFixes, toFix } = framesRedistributeFix(win, frame, dockedSide, posKey, sizeKey, "expand");
33
+ const otherFrameIds = Object.keys(win.frames).filter((id) => id !== frameId);
34
+ const redistributeSide = oppositeSide(frame.docked);
35
+ const pinnedEdgeCoordinates = getPinnedEdgesForCollapsedFrames(win, frame, dockedSide, posKey, sizeKey);
36
+ const changes = getFramesRedistributeInfo(win, redistributeSide, otherFrameIds, amount, { pinnedEdgeCoordinates });
37
+ if (changes instanceof KnownError) {
38
+ return changes;
39
+ }
40
+ applyFrameChanges(win, changes);
41
+ pushIfNotIn(toExtract, changes.modified.map((_) => _.id));
42
+ applyFixes();
43
+ pushIfNotIn(toExtract, toFix);
44
+ frame[sizeKey] = currentSize + amount;
45
+ if (frame.docked === "right" || frame.docked === "bottom") {
46
+ frame[posKey] -= amount;
47
+ }
48
+ return { modified: toExtract.map((_) => win.frames[_]), created: [], deleted: [] };
49
+ }
@@ -1,4 +1,4 @@
1
- import type { DragZone, LayoutChange, LayoutWindow } from "../types/index.js";
1
+ import type { LayoutChange, LayoutWindow, Zone } from "../types/index.js";
2
2
  import { LAYOUT_ERROR } from "../types/index.js";
3
3
  import { KnownError } from "../utils/KnownError.js";
4
4
  /**
@@ -136,4 +136,4 @@ import { KnownError } from "../utils/KnownError.js";
136
136
  * │ │ │
137
137
  * └───────────┴─────┘
138
138
  */
139
- export declare function getFrameRearrangeInfo(win: LayoutWindow, draggingFrameId: string, hoveredFrameId: string, zoneSide: DragZone["side"]): LayoutChange<"split" | "swap" | "rearrange"> | KnownError<typeof LAYOUT_ERROR.CANT_SWAP_WITH_SELF> | KnownError<typeof LAYOUT_ERROR.CANT_SPLIT_FRAME_TOO_SMALL> | KnownError<typeof LAYOUT_ERROR.CANT_REARRANGE_TO_SAME_RELATIVE_POSITION> | KnownError<typeof LAYOUT_ERROR.CANT_REARRANGE_WITH_DOCKED_EDGES> | KnownError<typeof LAYOUT_ERROR.CANT_REARRANGE_DOCKED_WITH_NON_DOCKED> | KnownError<typeof LAYOUT_ERROR.CANT_SPLIT_DOCKED_FRAME> | KnownError<typeof LAYOUT_ERROR.NO_FILL_CANDIDATES>;
139
+ export declare function getFrameRearrangeInfo(win: LayoutWindow, movingFrameId: string, hoveredFrameId: string, zoneSide: Zone["side"]): LayoutChange<"split" | "swap" | "rearrange"> | KnownError<typeof LAYOUT_ERROR.CANT_SWAP_WITH_SELF> | KnownError<typeof LAYOUT_ERROR.CANT_SPLIT_FRAME_TOO_SMALL> | KnownError<typeof LAYOUT_ERROR.CANT_REARRANGE_TO_SAME_RELATIVE_POSITION> | KnownError<typeof LAYOUT_ERROR.CANT_REARRANGE_WITH_DOCKED_EDGES> | KnownError<typeof LAYOUT_ERROR.CANT_REARRANGE_DOCKED_WITH_NON_DOCKED> | KnownError<typeof LAYOUT_ERROR.CANT_SPLIT_DOCKED_FRAME> | KnownError<typeof LAYOUT_ERROR.NO_FILL_CANDIDATES>;
@@ -8,10 +8,10 @@ import { oppositeSide } from "../helpers/oppositeSide.js";
8
8
  import { sideToDirection } from "../helpers/sideToDirection.js";
9
9
  import { LAYOUT_ERROR } from "../types/index.js";
10
10
  import { KnownError } from "../utils/KnownError.js";
11
- export function getFrameRearrangeInfo(win, draggingFrameId, hoveredFrameId, zoneSide) {
12
- const draggingFrame = { ...win.frames[draggingFrameId] };
11
+ export function getFrameRearrangeInfo(win, movingFrameId, hoveredFrameId, zoneSide) {
12
+ const draggingFrame = { ...win.frames[movingFrameId] };
13
13
  const hoveredFrame = { ...win.frames[hoveredFrameId] };
14
- if (draggingFrameId === hoveredFrameId) {
14
+ if (movingFrameId === hoveredFrameId) {
15
15
  if (zoneSide === "center") return new KnownError(LAYOUT_ERROR.CANT_SWAP_WITH_SELF, `Can't swap frame with self.`, { frame: hoveredFrame, zoneSide });
16
16
  }
17
17
  if (zoneSide === "center") {
@@ -25,10 +25,10 @@ export function getFrameRearrangeInfo(win, draggingFrameId, hoveredFrameId, zone
25
25
  };
26
26
  }
27
27
  if (draggingFrame.docked && !hoveredFrame.docked) {
28
- return new KnownError(LAYOUT_ERROR.CANT_REARRANGE_DOCKED_WITH_NON_DOCKED, `Can't rearrange docked frame ${draggingFrameId} with non-docked frame ${hoveredFrameId}, can only swap.`, { draggingFrameId, hoveredFrameId, zoneSide });
28
+ return new KnownError(LAYOUT_ERROR.CANT_REARRANGE_DOCKED_WITH_NON_DOCKED, `Can't rearrange docked frame ${movingFrameId} with non-docked frame ${hoveredFrameId}, can only swap.`, { movingFrameId, hoveredFrameId, zoneSide });
29
29
  }
30
30
  if (hoveredFrame.docked) {
31
- return new KnownError(LAYOUT_ERROR.CANT_REARRANGE_WITH_DOCKED_EDGES, `Can't rearrange with docked frame ${hoveredFrameId} edge, can only swap.`, { draggingFrameId, hoveredFrameId, zoneSide });
31
+ return new KnownError(LAYOUT_ERROR.CANT_REARRANGE_WITH_DOCKED_EDGES, `Can't rearrange with docked frame ${hoveredFrameId} edge, can only swap.`, { movingFrameId, hoveredFrameId, zoneSide });
32
32
  }
33
33
  const touchingSide = getSideTouching(draggingFrame, hoveredFrame);
34
34
  if (touchingSide) {
@@ -47,7 +47,7 @@ export function getFrameRearrangeInfo(win, draggingFrameId, hoveredFrameId, zone
47
47
  };
48
48
  }
49
49
  if (hoverOppositeSide === zoneSide) {
50
- return new KnownError(LAYOUT_ERROR.CANT_REARRANGE_TO_SAME_RELATIVE_POSITION, `Frame ${draggingFrameId} is already on the ${zoneSide} of ${hoveredFrameId}`, { draggingFrameId, hoveredFrameId, zoneSide });
50
+ return new KnownError(LAYOUT_ERROR.CANT_REARRANGE_TO_SAME_RELATIVE_POSITION, `Frame ${movingFrameId} is already on the ${zoneSide} of ${hoveredFrameId}`, { movingFrameId, hoveredFrameId, zoneSide });
51
51
  }
52
52
  }
53
53
  }
@@ -59,7 +59,7 @@ export function getFrameRearrangeInfo(win, draggingFrameId, hoveredFrameId, zone
59
59
  }
60
60
  const splitFrame = splitResult.modified[0];
61
61
  const newFrame = splitResult.created[0];
62
- if (draggingFrameId === hoveredFrameId) {
62
+ if (movingFrameId === hoveredFrameId) {
63
63
  return { ...splitResult, deleted: [], info: "split" };
64
64
  }
65
65
  hoveredFrame.x = splitFrame.x;
@@ -78,7 +78,7 @@ export function getFrameRearrangeInfo(win, draggingFrameId, hoveredFrameId, zone
78
78
  [draggingFrame.id]: draggingFrame
79
79
  }
80
80
  };
81
- const changes = getFillEmptySpaceInfo(winCopy, emptySpace, [hoveredFrameId, draggingFrameId]);
81
+ const changes = getFillEmptySpaceInfo(winCopy, emptySpace, [hoveredFrameId, movingFrameId]);
82
82
  if (changes instanceof KnownError) return changes;
83
83
  const notMissing = changes.modified.map((_) => _.id).filter((id) => id === hoveredFrame.id || draggingFrame.id);
84
84
  if (!notMissing.includes(hoveredFrame.id)) changes.modified.push(hoveredFrame);
@@ -0,0 +1,14 @@
1
+ import type { EdgeSide, LayoutChange, LayoutWindow } from "../types/index.js";
2
+ import { LAYOUT_ERROR } from "../types/index.js";
3
+ import { KnownError } from "../utils/KnownError.js";
4
+ /**
5
+ * Returns a {@link LayoutChange} with the information necessary to shrink a frame touching a window edge by a given amount.
6
+ *
7
+ * Changes can be applied to a window with {@link applyFrameChanges}.
8
+ *
9
+ * It shrinks the frame by redistributing the freed space to neighboring frames.
10
+ */
11
+ export declare function getFrameShrinkInfo(win: LayoutWindow, frameId: string, amount: number, shrinkSide: EdgeSide, { allowOutOfBounds }?: {
12
+ /** Allow the resize span to exceed window bounds. */
13
+ allowOutOfBounds?: boolean;
14
+ }): LayoutChange | KnownError<typeof LAYOUT_ERROR.REDISTRIBUTE_WOULD_RESULT_IN_INVALID_FRAMES> | KnownError<typeof LAYOUT_ERROR.CANT_RESIZE_SINGLE_FRAME>;
@@ -0,0 +1,48 @@
1
+ import { pushIfNotIn } from "@alanscodelog/utils/pushIfNotIn";
2
+ import { walk } from "@alanscodelog/utils/walk";
3
+ import { applyFrameChanges } from "./applyFrameChanges.js";
4
+ import { getFramesRedistributeInfo } from "./getFramesRedistributeInfo.js";
5
+ import { findEdgesTouchingWindow } from "../helpers/findEdgesTouchingWindow.js";
6
+ import { framesRedistributeFix } from "../helpers/framesRedistributeFix.js";
7
+ import { getPinnedEdgesForCollapsedFrames } from "../helpers/getPinnedEdgesForCollapsedFrames.js";
8
+ import { oppositeSide } from "../helpers/oppositeSide.js";
9
+ import { LAYOUT_ERROR } from "../types/index.js";
10
+ import { KnownError } from "../utils/KnownError.js";
11
+ export function getFrameShrinkInfo(win, frameId, amount, shrinkSide, {
12
+ allowOutOfBounds = false
13
+ } = {}) {
14
+ win = walk(win, void 0, { save: true });
15
+ const frame = win.frames[frameId];
16
+ if (!frame) throw new Error(`Unknown frame ${frameId}`);
17
+ if (Object.keys(win.frames).length === 1) {
18
+ return new KnownError(LAYOUT_ERROR.CANT_RESIZE_SINGLE_FRAME, `Frame ${frameId} is the only frame, cannot shrink.`, { frame });
19
+ }
20
+ if (!(shrinkSide in findEdgesTouchingWindow(frame))) {
21
+ throw new Error(`Frame ${frameId} does not touch the ${shrinkSide} edge.`);
22
+ }
23
+ const isVertical = shrinkSide === "left" || shrinkSide === "right";
24
+ const sizeKey = isVertical ? "width" : "height";
25
+ const posKey = isVertical ? "x" : "y";
26
+ const toExtract = [frame.id];
27
+ const { applyFixes, toFix } = framesRedistributeFix(win, frame, shrinkSide, posKey, sizeKey, "shrink");
28
+ const otherFrameIds = Object.keys(win.frames).filter((id) => id !== frameId);
29
+ const redistributeSide = oppositeSide(shrinkSide);
30
+ const pinnedEdgeCoordinates = getPinnedEdgesForCollapsedFrames(win, frame, shrinkSide, posKey, sizeKey);
31
+ const changes = getFramesRedistributeInfo(win, redistributeSide, otherFrameIds, -amount, { allowOutOfBounds, pinnedEdgeCoordinates });
32
+ if (changes instanceof KnownError) {
33
+ if (changes.code === LAYOUT_ERROR.REDISTRIBUTE_OUT_OF_BOUNDS || changes.code === LAYOUT_ERROR.NO_SPACE_TO_REDISTRIBUTE) {
34
+ changes.message = `This error should never happen, please file a bug report: ${changes.message}`;
35
+ throw changes;
36
+ }
37
+ return changes;
38
+ }
39
+ applyFrameChanges(win, changes);
40
+ pushIfNotIn(toExtract, changes.modified.map((_) => _.id));
41
+ applyFixes();
42
+ pushIfNotIn(toExtract, toFix);
43
+ if (shrinkSide === "right" || shrinkSide === "bottom") {
44
+ frame[posKey] = frame[posKey] + amount;
45
+ }
46
+ frame[sizeKey] = frame[sizeKey] - amount;
47
+ return { modified: toExtract.map((_) => win.frames[_]), created: [], deleted: [] };
48
+ }
@@ -5,4 +5,4 @@ import { KnownError } from "../utils/KnownError.js";
5
5
  *
6
6
  * Changes can be applied to a window with {@link applyFrameChanges}.
7
7
  */
8
- export declare function getFrameSplitInfo(frame: LayoutFrame, dir: Direction, dragPointOrPosition?: Point | number | "midpoint", minSize?: Size, snapAmount?: Point): LayoutChange | KnownError<typeof LAYOUT_ERROR.CANT_SPLIT_FRAME_TOO_SMALL> | KnownError<typeof LAYOUT_ERROR.CANT_SPLIT_DOCKED_FRAME>;
8
+ export declare function getFrameSplitInfo(frame: LayoutFrame, dir: Direction, movePointOrPosition?: Point | number | "midpoint", minSize?: Size, snapAmount?: Point): LayoutChange | KnownError<typeof LAYOUT_ERROR.CANT_SPLIT_FRAME_TOO_SMALL> | KnownError<typeof LAYOUT_ERROR.CANT_SPLIT_DOCKED_FRAME>;
@@ -6,7 +6,7 @@ import {
6
6
  LAYOUT_ERROR
7
7
  } from "../types/index.js";
8
8
  import { KnownError } from "../utils/KnownError.js";
9
- export function getFrameSplitInfo(frame, dir, dragPointOrPosition = "midpoint", minSize = settings.minSizeScaled, snapAmount = settings.snapPointScaled) {
9
+ export function getFrameSplitInfo(frame, dir, movePointOrPosition = "midpoint", minSize = settings.minSizeScaled, snapAmount = settings.snapPointScaled) {
10
10
  if (frame.docked) {
11
11
  return new KnownError(
12
12
  LAYOUT_ERROR.CANT_SPLIT_DOCKED_FRAME,
@@ -19,7 +19,7 @@ export function getFrameSplitInfo(frame, dir, dragPointOrPosition = "midpoint",
19
19
  const isHorz = dir === "left" || dir === "right";
20
20
  const sizeKey = isHorz ? "width" : "height";
21
21
  const posKey = isHorz ? "x" : "y";
22
- const position = dragPointOrPosition === "midpoint" ? isHorz ? frame.x + frame.width / 2 : frame.y + frame.height / 2 : typeof dragPointOrPosition === "number" ? dragPointOrPosition : dragPointOrPosition[isHorz ? "x" : "y"];
22
+ const position = movePointOrPosition === "midpoint" ? isHorz ? frame.x + frame.width / 2 : frame.y + frame.height / 2 : typeof movePointOrPosition === "number" ? movePointOrPosition : movePointOrPosition[isHorz ? "x" : "y"];
23
23
  const safePosition = findSafeSplitEdgeAndPosition(
24
24
  frame,
25
25
  dir,
@@ -12,4 +12,4 @@ import { KnownError } from "../utils/KnownError.js";
12
12
  export declare function getFrameUncollapseInfo(win: LayoutWindow, frameId: string, { restoreSize }?: {
13
13
  /** Override the size to restore the frame to. */
14
14
  restoreSize?: Size;
15
- }): LayoutChange | KnownError<typeof LAYOUT_ERROR.CANT_UNCOLLAPSE_NOT_COLLAPSED> | KnownError<typeof LAYOUT_ERROR.REDISTRIBUTE_OUT_OF_BOUNDS> | KnownError<typeof LAYOUT_ERROR.NO_SPACE_TO_REDISTRIBUTE> | KnownError<typeof LAYOUT_ERROR.REDISTRIBUTE_WOULD_RESULT_IN_INVALID_FRAMES>;
15
+ }): LayoutChange | KnownError<typeof LAYOUT_ERROR.CANT_UNCOLLAPSE_NOT_COLLAPSED> | KnownError<typeof LAYOUT_ERROR.REDISTRIBUTE_OUT_OF_BOUNDS> | KnownError<typeof LAYOUT_ERROR.NO_SPACE_TO_REDISTRIBUTE> | KnownError<typeof LAYOUT_ERROR.REDISTRIBUTE_WOULD_RESULT_IN_INVALID_FRAMES> | KnownError<typeof LAYOUT_ERROR.CANT_RESIZE_SINGLE_FRAME>;
@@ -1,10 +1,7 @@
1
1
  import { pushIfNotIn } from "@alanscodelog/utils/pushIfNotIn";
2
2
  import { walk } from "@alanscodelog/utils/walk";
3
3
  import { applyFrameChanges } from "./applyFrameChanges.js";
4
- import { getFramesRedistributeInfo } from "./getFramesRedistributeInfo.js";
5
- import { framesRedistributeFix } from "../helpers/framesRedistributeFix.js";
6
- import { getPinnedEdgesForCollapsedFrames } from "../helpers/getPinnedEdgesForCollapsedFrames.js";
7
- import { oppositeSide } from "../helpers/oppositeSide.js";
4
+ import { getFrameExpandInfo } from "./getFrameExpandInfo.js";
8
5
  import { LAYOUT_ERROR } from "../types/index.js";
9
6
  import { KnownError } from "../utils/KnownError.js";
10
7
  export function getFrameUncollapseInfo(win, frameId, {
@@ -21,7 +18,6 @@ export function getFrameUncollapseInfo(win, frameId, {
21
18
  const toExtract = [frame.id];
22
19
  const isVertical = frame.docked === "left" || frame.docked === "right";
23
20
  const sizeKey = isVertical ? "width" : "height";
24
- const posKey = isVertical ? "x" : "y";
25
21
  const currentSize = frame[sizeKey];
26
22
  const storedSize = restoreSize !== void 0 ? restoreSize[sizeKey] : frame.collapsed;
27
23
  if (frame.collapsed === void 0) {
@@ -33,22 +29,12 @@ export function getFrameUncollapseInfo(win, frameId, {
33
29
  }
34
30
  const expandAmount = storedSize - currentSize;
35
31
  const dockedSide = frame.docked;
36
- const { applyFixes, toFix } = framesRedistributeFix(win, frame, dockedSide, posKey, sizeKey, "expand");
37
- const otherFrameIds = Object.keys(win.frames).filter((id) => id !== frameId);
38
- const redistributeSide = oppositeSide(frame.docked);
39
- const pinnedEdgeCoordinates = getPinnedEdgesForCollapsedFrames(win, frame, dockedSide, posKey, sizeKey);
40
- const changes = getFramesRedistributeInfo(win, redistributeSide, otherFrameIds, expandAmount, { pinnedEdgeCoordinates });
41
- if (changes instanceof KnownError) {
42
- return changes;
32
+ const expandResult = getFrameExpandInfo(win, frameId, expandAmount, dockedSide);
33
+ if (expandResult instanceof KnownError) {
34
+ return expandResult;
43
35
  }
44
- applyFrameChanges(win, changes);
45
- pushIfNotIn(toExtract, changes.modified.map((_) => _.id));
46
- applyFixes();
47
- pushIfNotIn(toExtract, toFix);
48
- frame[sizeKey] = storedSize;
36
+ applyFrameChanges(win, expandResult);
37
+ pushIfNotIn(toExtract, expandResult.modified.map((_) => _.id));
49
38
  frame.collapsed = void 0;
50
- if (frame.docked === "right" || frame.docked === "bottom") {
51
- frame[posKey] -= expandAmount;
52
- }
53
39
  return { modified: toExtract.map((_) => win.frames[_]), created: [], deleted: [] };
54
40
  }