@witchcraft/layout 0.4.4 → 0.5.1
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/module.json +1 -1
- package/dist/runtime/components/FrameDragHandle.vue +3 -3
- package/dist/runtime/components/LayoutDragEdgeGrabbed.vue +3 -3
- package/dist/runtime/components/LayoutDragEdgeHandle.d.vue.ts +2 -2
- package/dist/runtime/components/LayoutDragEdgeHandle.vue +2 -2
- package/dist/runtime/components/LayoutDragEdgeHandle.vue.d.ts +2 -2
- package/dist/runtime/components/LayoutDragEdges.vue +5 -5
- package/dist/runtime/components/LayoutEdgesActiveFrame.vue +2 -2
- package/dist/runtime/components/LayoutFrame.vue +2 -2
- package/dist/runtime/components/LayoutIntersectionHandle.d.vue.ts +2 -2
- package/dist/runtime/components/LayoutIntersectionHandle.vue +2 -2
- package/dist/runtime/components/LayoutIntersectionHandle.vue.d.ts +2 -2
- package/dist/runtime/components/LayoutIntersections.vue +4 -4
- package/dist/runtime/components/LayoutWindow.d.vue.ts +44 -44
- package/dist/runtime/components/LayoutWindow.vue +27 -27
- package/dist/runtime/components/LayoutWindow.vue.d.ts +44 -44
- package/dist/runtime/composables/useFrames.d.ts +107 -109
- package/dist/runtime/composables/useFrames.js +107 -99
- package/dist/runtime/demo/App.vue +16 -16
- package/dist/runtime/demo/DemoControls.d.vue.ts +2 -2
- package/dist/runtime/demo/DemoControls.vue +4 -4
- package/dist/runtime/demo/DemoControls.vue.d.ts +2 -2
- package/dist/runtime/helpers/createZoneSideClipPath.d.ts +2 -2
- package/dist/runtime/helpers/{findFrameDraggableEdges.d.ts → findFrameMoveableEdges.d.ts} +2 -2
- package/dist/runtime/helpers/{findFrameDraggableEdges.js → findFrameMoveableEdges.js} +3 -3
- package/dist/runtime/helpers/{findDraggableEdge.d.ts → findMoveableEdge.d.ts} +1 -1
- package/dist/runtime/helpers/{findDraggableEdge.js → findMoveableEdge.js} +1 -1
- package/dist/runtime/helpers/index.d.ts +2 -2
- package/dist/runtime/helpers/index.js +2 -2
- package/dist/runtime/layout/createSplitDecoFromDrag.d.ts +1 -1
- package/dist/runtime/layout/createSplitDecoFromDrag.js +2 -2
- package/dist/runtime/layout/findSafeSplitEdge.d.ts +1 -1
- package/dist/runtime/layout/findSafeSplitEdge.js +2 -2
- package/dist/runtime/layout/getCloseFrameInfo.js +4 -4
- package/dist/runtime/layout/getFrameRearrangeInfo.d.ts +2 -2
- package/dist/runtime/layout/getFrameRearrangeInfo.js +8 -8
- package/dist/runtime/layout/getFrameSplitInfo.d.ts +1 -1
- package/dist/runtime/layout/getFrameSplitInfo.js +2 -2
- package/dist/runtime/layout/{getFrameDragZones.d.ts → getFrameZones.d.ts} +3 -3
- package/dist/runtime/layout/{getFrameDragZones.js → getFrameZones.js} +1 -1
- package/dist/runtime/layout/{getWindowDragZones.d.ts → getWindowZones.d.ts} +1 -1
- package/dist/runtime/layout/{getWindowDragZones.js → getWindowZones.js} +1 -1
- package/dist/runtime/layout/getZones.d.ts +8 -0
- package/dist/runtime/layout/getZones.js +32 -0
- package/dist/runtime/layout/index.d.ts +3 -3
- package/dist/runtime/layout/index.js +3 -3
- package/dist/runtime/{drag/DragActionHandler.d.ts → move/ActionHandler.d.ts} +19 -21
- package/dist/runtime/{drag/DragActionHandler.js → move/ActionHandler.js} +21 -18
- package/dist/runtime/{drag → move}/CloseAction.d.ts +9 -8
- package/dist/runtime/{drag → move}/CloseAction.js +31 -27
- package/dist/runtime/{drag → move}/FrameDragAction.d.ts +9 -8
- package/dist/runtime/{drag → move}/FrameDragAction.js +23 -22
- package/dist/runtime/{drag/DragDirectionStore.d.ts → move/MoveDirectionStore.d.ts} +4 -4
- package/dist/runtime/{drag/DragDirectionStore.js → move/MoveDirectionStore.js} +9 -9
- package/dist/runtime/{drag → move}/SplitAction.d.ts +10 -9
- package/dist/runtime/{drag → move}/SplitAction.js +53 -44
- package/dist/runtime/{drag → move}/createDefaultHandlers.d.ts +2 -2
- package/dist/runtime/types/index.d.ts +192 -171
- package/dist/runtime/types/index.js +2 -2
- package/dist/runtime/types/vue.d.ts +14 -16
- package/dist/runtime/types/vue.js +1 -1
- package/package.json +1 -1
- package/src/runtime/components/FrameDragHandle.vue +3 -3
- package/src/runtime/components/LayoutDragEdgeGrabbed.vue +3 -3
- package/src/runtime/components/LayoutDragEdgeHandle.vue +4 -4
- package/src/runtime/components/LayoutDragEdges.vue +5 -5
- package/src/runtime/components/LayoutEdgesActiveFrame.vue +2 -2
- package/src/runtime/components/LayoutFrame.vue +2 -2
- package/src/runtime/components/LayoutIntersectionHandle.vue +4 -4
- package/src/runtime/components/LayoutIntersections.vue +4 -4
- package/src/runtime/components/LayoutWindow.vue +32 -32
- package/src/runtime/composables/useFrames.ts +115 -104
- package/src/runtime/demo/App.vue +18 -18
- package/src/runtime/demo/DemoControls.vue +5 -5
- package/src/runtime/helpers/createZoneSideClipPath.ts +2 -2
- package/src/runtime/helpers/{findFrameDraggableEdges.ts → findFrameMoveableEdges.ts} +4 -4
- package/src/runtime/helpers/{findDraggableEdge.ts → findMoveableEdge.ts} +1 -1
- package/src/runtime/helpers/index.ts +2 -2
- package/src/runtime/layout/createSplitDecoFromDrag.ts +2 -2
- package/src/runtime/layout/findSafeSplitEdge.ts +4 -4
- package/src/runtime/layout/getCloseFrameInfo.ts +4 -4
- package/src/runtime/layout/getFrameRearrangeInfo.ts +10 -10
- package/src/runtime/layout/getFrameSplitInfo.ts +5 -5
- package/src/runtime/layout/{getFrameDragZones.ts → getFrameZones.ts} +4 -4
- package/src/runtime/layout/{getWindowDragZones.ts → getWindowZones.ts} +1 -1
- package/src/runtime/layout/getZones.ts +48 -0
- package/src/runtime/layout/index.ts +3 -3
- package/src/runtime/{drag/DragActionHandler.ts → move/ActionHandler.ts} +48 -41
- package/src/runtime/{drag → move}/CloseAction.ts +42 -37
- package/src/runtime/{drag → move}/FrameDragAction.ts +37 -36
- package/src/runtime/{drag/DragDirectionStore.ts → move/MoveDirectionStore.ts} +10 -10
- package/src/runtime/{drag → move}/SplitAction.ts +64 -54
- package/src/runtime/{drag → move}/createDefaultHandlers.ts +2 -2
- package/src/runtime/types/index.ts +90 -69
- package/src/runtime/types/vue.ts +14 -14
- package/dist/runtime/layout/getDragZones.d.ts +0 -8
- package/dist/runtime/layout/getDragZones.js +0 -32
- package/src/runtime/layout/getDragZones.ts +0 -48
- /package/dist/runtime/{drag → move}/createDefaultHandlers.js +0 -0
|
@@ -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,
|
|
12
|
-
const draggingFrame = { ...win.frames[
|
|
11
|
+
export function getFrameRearrangeInfo(win, movingFrameId, hoveredFrameId, zoneSide) {
|
|
12
|
+
const draggingFrame = { ...win.frames[movingFrameId] };
|
|
13
13
|
const hoveredFrame = { ...win.frames[hoveredFrameId] };
|
|
14
|
-
if (
|
|
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 ${
|
|
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.`, {
|
|
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 ${
|
|
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 (
|
|
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,
|
|
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);
|
|
@@ -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,
|
|
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,
|
|
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 =
|
|
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,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Zone } from "../types/index.js";
|
|
2
2
|
/**
|
|
3
3
|
* Returns frame drag zones (in **unrounded** scaled coordinate space).
|
|
4
4
|
*
|
|
@@ -8,9 +8,9 @@ import type { DragZone } from "../types/index.js";
|
|
|
8
8
|
*
|
|
9
9
|
* Unrounded because these are for display purposes only.
|
|
10
10
|
*/
|
|
11
|
-
export declare function
|
|
11
|
+
export declare function getFrameZones(frame: {
|
|
12
12
|
x: number;
|
|
13
13
|
y: number;
|
|
14
14
|
width: number;
|
|
15
15
|
height: number;
|
|
16
|
-
}, thresholdPx: number, windowPxWidth: number, windowPxHeight: number):
|
|
16
|
+
}, thresholdPx: number, windowPxWidth: number, windowPxHeight: number): Zone[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { settings } from "../settings.js";
|
|
2
|
-
export function
|
|
2
|
+
export function getFrameZones(frame, thresholdPx, windowPxWidth, windowPxHeight) {
|
|
3
3
|
const thX = thresholdPx / windowPxWidth * settings.maxInt;
|
|
4
4
|
const thY = thresholdPx / windowPxHeight * settings.maxInt;
|
|
5
5
|
const pxWidth = frame.width / settings.maxInt * windowPxWidth;
|
|
@@ -3,4 +3,4 @@ import type { LayoutWindow, WindowEdgeZone } from "../types/index.js";
|
|
|
3
3
|
* Returns window edge drag zones (in scaled coordinates)
|
|
4
4
|
*
|
|
5
5
|
*/
|
|
6
|
-
export declare function
|
|
6
|
+
export declare function getWindowZones(win: LayoutWindow, thresholdPx: number): WindowEdgeZone[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { numberToScaledPercent } from "../helpers/numberToScaledPercent.js";
|
|
2
2
|
import { settings } from "../settings.js";
|
|
3
|
-
export function
|
|
3
|
+
export function getWindowZones(win, thresholdPx) {
|
|
4
4
|
const thX = numberToScaledPercent(thresholdPx, win.pxWidth);
|
|
5
5
|
const thY = numberToScaledPercent(thresholdPx, win.pxHeight);
|
|
6
6
|
const maxInt = settings.maxInt;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { MoveState, Zone } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Find the drag zone under the drag point.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getZones(state: Pick<MoveState, "movePoint" | "moveHoveredFrame" | "frames" | "win">, { frameEdgePx, windowEdgePx }: {
|
|
6
|
+
frameEdgePx: number;
|
|
7
|
+
windowEdgePx: number;
|
|
8
|
+
}): Zone | undefined;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { getFrameZones } from "./getFrameZones.js";
|
|
2
|
+
import { getWindowZones } from "./getWindowZones.js";
|
|
3
|
+
import { isPointInRect } from "./isPointInRect.js";
|
|
4
|
+
export function getZones(state, { frameEdgePx, windowEdgePx }) {
|
|
5
|
+
const { movePoint, win } = state;
|
|
6
|
+
const frameId = state.moveHoveredFrame?.id;
|
|
7
|
+
if (!frameId) return;
|
|
8
|
+
const frame = state.frames[frameId];
|
|
9
|
+
if (!frame || !movePoint) return;
|
|
10
|
+
const frameZones = getFrameZones(frame, frameEdgePx, win.pxWidth, win.pxHeight);
|
|
11
|
+
const windowZones = getWindowZones(win, windowEdgePx);
|
|
12
|
+
let matchedZone;
|
|
13
|
+
for (const zone of windowZones) {
|
|
14
|
+
if (isPointInRect(zone, movePoint)) {
|
|
15
|
+
matchedZone = {
|
|
16
|
+
...zone,
|
|
17
|
+
type: "window"
|
|
18
|
+
};
|
|
19
|
+
break;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (!matchedZone) {
|
|
23
|
+
for (const zone of frameZones) {
|
|
24
|
+
if (isPointInRect(zone, movePoint)) {
|
|
25
|
+
matchedZone = zone;
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (!matchedZone) return void 0;
|
|
31
|
+
return matchedZone;
|
|
32
|
+
}
|
|
@@ -7,11 +7,11 @@ export { findSafeSplitEdgeAndPosition } from "./findSafeSplitEdge.js";
|
|
|
7
7
|
export { findVisualEdge } from "./findVisualEdge.js";
|
|
8
8
|
export { frameCreate } from "./frameCreate.js";
|
|
9
9
|
export { getCloseFrameInfo } from "./getCloseFrameInfo.js";
|
|
10
|
-
export {
|
|
10
|
+
export { getZones } from "./getZones.js";
|
|
11
11
|
export { getFillEmptySpaceInfo } from "./getFillEmptySpaceInfo.js";
|
|
12
12
|
export { getFrameCollapseInfo } from "./getFrameCollapseInfo.js";
|
|
13
13
|
export { getFrameDockInfo } from "./getFrameDockInfo.js";
|
|
14
|
-
export {
|
|
14
|
+
export { getFrameZones } from "./getFrameZones.js";
|
|
15
15
|
export { getFrameExpandInfo } from "./getFrameExpandInfo.js";
|
|
16
16
|
export { getFrameRearrangeInfo } from "./getFrameRearrangeInfo.js";
|
|
17
17
|
export { getFrameShrinkInfo } from "./getFrameShrinkInfo.js";
|
|
@@ -23,7 +23,7 @@ export { getFrameUncollapseInfo } from "./getFrameUncollapseInfo.js";
|
|
|
23
23
|
export { getFrameUndockInfo } from "./getFrameUndockInfo.js";
|
|
24
24
|
export { getRelaxFramesInfo } from "./getRelaxFramesInfo.js";
|
|
25
25
|
export { getUpdateWindowSizeInfo } from "./getUpdateWindowSizeInfo.js";
|
|
26
|
-
export {
|
|
26
|
+
export { getWindowZones } from "./getWindowZones.js";
|
|
27
27
|
export { isPointInRect } from "./isPointInRect.js";
|
|
28
28
|
export { layoutAddWindow } from "./layoutAddWindow.js";
|
|
29
29
|
export { layoutCreate } from "./layoutCreate.js";
|
|
@@ -7,11 +7,11 @@ export { findSafeSplitEdgeAndPosition } from "./findSafeSplitEdge.js";
|
|
|
7
7
|
export { findVisualEdge } from "./findVisualEdge.js";
|
|
8
8
|
export { frameCreate } from "./frameCreate.js";
|
|
9
9
|
export { getCloseFrameInfo } from "./getCloseFrameInfo.js";
|
|
10
|
-
export {
|
|
10
|
+
export { getZones } from "./getZones.js";
|
|
11
11
|
export { getFillEmptySpaceInfo } from "./getFillEmptySpaceInfo.js";
|
|
12
12
|
export { getFrameCollapseInfo } from "./getFrameCollapseInfo.js";
|
|
13
13
|
export { getFrameDockInfo } from "./getFrameDockInfo.js";
|
|
14
|
-
export {
|
|
14
|
+
export { getFrameZones } from "./getFrameZones.js";
|
|
15
15
|
export { getFrameExpandInfo } from "./getFrameExpandInfo.js";
|
|
16
16
|
export { getFrameRearrangeInfo } from "./getFrameRearrangeInfo.js";
|
|
17
17
|
export { getFrameShrinkInfo } from "./getFrameShrinkInfo.js";
|
|
@@ -23,7 +23,7 @@ export { getFrameUncollapseInfo } from "./getFrameUncollapseInfo.js";
|
|
|
23
23
|
export { getFrameUndockInfo } from "./getFrameUndockInfo.js";
|
|
24
24
|
export { getRelaxFramesInfo } from "./getRelaxFramesInfo.js";
|
|
25
25
|
export { getUpdateWindowSizeInfo } from "./getUpdateWindowSizeInfo.js";
|
|
26
|
-
export {
|
|
26
|
+
export { getWindowZones } from "./getWindowZones.js";
|
|
27
27
|
export { isPointInRect } from "./isPointInRect.js";
|
|
28
28
|
export { layoutAddWindow } from "./layoutAddWindow.js";
|
|
29
29
|
export { layoutCreate } from "./layoutCreate.js";
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { type RecordFromArray } from "@alanscodelog/utils";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ActionHandlerApplyResult, Edge, IAction, LayoutFrame, LayoutShape, MoveChangeHandler, MoveChangeResult, MoveState } from "../types/index.js";
|
|
3
3
|
/**
|
|
4
|
-
* Handles the lifecycle of a drag actions {@link
|
|
4
|
+
* Handles the lifecycle of a drag actions {@link IAction} and provides additional hooks.
|
|
5
5
|
*
|
|
6
6
|
* The first action instance that can handle the request is passed control of the event handlers until the request changes.
|
|
7
7
|
*/
|
|
8
|
-
export declare class
|
|
9
|
-
activeAction?: keyof
|
|
10
|
-
actions:
|
|
11
|
-
eventCanceller: ((e: PointerEvent | KeyboardEvent | undefined, state:
|
|
12
|
-
boundCancel: (e: PointerEvent | KeyboardEvent | undefined, state:
|
|
13
|
-
|
|
8
|
+
export declare class ActionHandler<TRawActions extends IAction[], TActions extends RecordFromArray<TRawActions, "name"> = RecordFromArray<TRawActions, "name">> {
|
|
9
|
+
activeAction?: keyof TActions;
|
|
10
|
+
actions: TActions;
|
|
11
|
+
eventCanceller: ((e: PointerEvent | KeyboardEvent | undefined, state: MoveState) => void) | undefined;
|
|
12
|
+
boundCancel: (e: PointerEvent | KeyboardEvent | undefined, state: MoveState) => void;
|
|
13
|
+
defaultOnMoveChange: MoveChangeHandler;
|
|
14
14
|
hooks: {
|
|
15
15
|
/** Called while dragging during dragChange events. You can use this to update the dragging edges. */
|
|
16
16
|
onRecalculate?: () => void;
|
|
@@ -21,7 +21,7 @@ export declare class DragActionHandler<TRawDragActions extends IDragAction[], TD
|
|
|
21
21
|
*/
|
|
22
22
|
onEvent?: (e: PointerEvent | KeyboardEvent | undefined, cancel: () => void) => void;
|
|
23
23
|
/** Called when the action requested changes. */
|
|
24
|
-
onRequestChange?: (type: keyof
|
|
24
|
+
onRequestChange?: (type: keyof TActions | undefined) => void;
|
|
25
25
|
/** Called when the drag action ends either because it was completed or cancelled. */
|
|
26
26
|
onEnd?: (context: {
|
|
27
27
|
cancelled: boolean;
|
|
@@ -30,30 +30,28 @@ export declare class DragActionHandler<TRawDragActions extends IDragAction[], TD
|
|
|
30
30
|
};
|
|
31
31
|
/** All action shapes merged into a single array. If using vue you can set this to a reactive array for reactivity. */
|
|
32
32
|
shapes: LayoutShape[];
|
|
33
|
-
/** All hint/error text from all actions, updated on every
|
|
33
|
+
/** All hint/error text from all actions, updated on every onMoveChange. If using vue you can set this to a reactive object for reactivity. */
|
|
34
34
|
textHints: {
|
|
35
35
|
actions: string[];
|
|
36
36
|
errors: string[];
|
|
37
37
|
};
|
|
38
|
-
constructor(actions:
|
|
38
|
+
constructor(actions: TRawActions, hooks?: ActionHandler<TRawActions, TActions>["hooks"],
|
|
39
39
|
/**
|
|
40
|
-
* Default
|
|
40
|
+
* Default onMoveChange handler for when no action can handle the request.
|
|
41
41
|
*
|
|
42
42
|
* Should return true to allow the edges to be moved, or false to prevent it.
|
|
43
43
|
*
|
|
44
44
|
* The default prevents movement when the edge is a window edge and when the edge is touching a collapsed frame.
|
|
45
45
|
*/
|
|
46
|
-
|
|
47
|
-
eventHandler(e: KeyboardEvent | PointerEvent, state:
|
|
48
|
-
|
|
46
|
+
defaultOnMoveChange?: MoveChangeHandler);
|
|
47
|
+
eventHandler(e: KeyboardEvent | PointerEvent, state: MoveState, forceRecalculateEdges: () => void): undefined;
|
|
48
|
+
onMoveChange<T extends "start" | "move" | "end">(type: T, e: T extends "end" ? PointerEvent | undefined : PointerEvent, state: MoveState, forceRecalculateEdges: () => void, cancel: (e: PointerEvent | KeyboardEvent | undefined, state: MoveState) => void, resolve: T extends "end" ? undefined : (opts: ActionHandlerApplyResult) => void): MoveChangeResult;
|
|
49
|
+
onMoveEnded(): void;
|
|
49
50
|
setTextHints(type: "start" | "move" | "end"): void;
|
|
50
51
|
annotateEdges(edges: Edge[], frames: LayoutFrame[]): void;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
};
|
|
55
|
-
cancel(e: PointerEvent | KeyboardEvent | undefined, state: DragState): void;
|
|
56
|
-
static debugState(pluginName: string, type: "before" | "after" | string, state: DragState, pluginState?: Record<string, any>,
|
|
52
|
+
onMoveApply(state: MoveState, forceRecalculateEdges: () => void): ActionHandlerApplyResult;
|
|
53
|
+
cancel(e: PointerEvent | KeyboardEvent | undefined, state: MoveState): void;
|
|
54
|
+
static debugState(pluginName: string, type: "before" | "after" | string, state: MoveState, pluginState?: Record<string, any>,
|
|
57
55
|
/** Object key to filter the state by, e.g. state.win.frames. If false is ignored. The idea is you pass this.debug and users can set this.debug to a string to filter. */
|
|
58
56
|
key?: string | boolean): void;
|
|
59
57
|
}
|
|
@@ -3,30 +3,30 @@ import { isWindowEdge } from "../helpers/isWindowEdge.js";
|
|
|
3
3
|
import { findFramesTouchingEdge } from "../layout/findFramesTouchingEdge.js";
|
|
4
4
|
import { LAYOUT_ERROR } from "../types/index.js";
|
|
5
5
|
import { KnownError } from "../utils/KnownError.js";
|
|
6
|
-
export class
|
|
6
|
+
export class ActionHandler {
|
|
7
7
|
activeAction;
|
|
8
8
|
actions;
|
|
9
9
|
eventCanceller = void 0;
|
|
10
10
|
boundCancel;
|
|
11
|
-
|
|
12
|
-
const isTouchingCollapsedFrameEdge = type === "move" && state.
|
|
11
|
+
defaultOnMoveChange = (type, _e, state, _forceRecalculateEdges, _cancel) => {
|
|
12
|
+
const isTouchingCollapsedFrameEdge = type === "move" && state.isMoving === "edge" && state.touchingFramesArrays.some(
|
|
13
13
|
(frames) => (
|
|
14
14
|
// we check with a falsy check on PURPOSE, frames collapsed to 0 aren't an issue, they are ignored anyways
|
|
15
15
|
Object.values(frames).some((f) => f.collapsed)
|
|
16
16
|
)
|
|
17
17
|
);
|
|
18
18
|
return {
|
|
19
|
-
updateEdges: type === "move" ? !(state.
|
|
19
|
+
updateEdges: type === "move" ? !(state.isMovingFromWindowEdge || isTouchingCollapsedFrameEdge) : true,
|
|
20
20
|
shapes: []
|
|
21
21
|
};
|
|
22
22
|
};
|
|
23
23
|
hooks;
|
|
24
24
|
/** All action shapes merged into a single array. If using vue you can set this to a reactive array for reactivity. */
|
|
25
25
|
shapes = [];
|
|
26
|
-
/** All hint/error text from all actions, updated on every
|
|
26
|
+
/** All hint/error text from all actions, updated on every onMoveChange. If using vue you can set this to a reactive object for reactivity. */
|
|
27
27
|
textHints = { actions: [], errors: [] };
|
|
28
|
-
constructor(actions, hooks = {},
|
|
29
|
-
if (
|
|
28
|
+
constructor(actions, hooks = {}, defaultOnMoveChange) {
|
|
29
|
+
if (defaultOnMoveChange) this.defaultOnMoveChange = defaultOnMoveChange;
|
|
30
30
|
this.hooks = hooks;
|
|
31
31
|
this.actions = {};
|
|
32
32
|
for (const action of actions) {
|
|
@@ -35,7 +35,7 @@ export class DragActionHandler {
|
|
|
35
35
|
this.boundCancel = this.cancel.bind(this);
|
|
36
36
|
}
|
|
37
37
|
eventHandler(e, state, forceRecalculateEdges) {
|
|
38
|
-
if (state.
|
|
38
|
+
if (state.isMoving) {
|
|
39
39
|
e.preventDefault();
|
|
40
40
|
}
|
|
41
41
|
let cancelled = false;
|
|
@@ -62,31 +62,34 @@ export class DragActionHandler {
|
|
|
62
62
|
}
|
|
63
63
|
this.hooks.onRequestChange?.(this.activeAction);
|
|
64
64
|
}
|
|
65
|
-
if (state.
|
|
65
|
+
if (state.isMoving) {
|
|
66
66
|
forceRecalculateEdges();
|
|
67
67
|
this.hooks.onRecalculate?.();
|
|
68
68
|
}
|
|
69
69
|
return void 0;
|
|
70
70
|
}
|
|
71
|
-
|
|
71
|
+
onMoveChange(type, e, state, forceRecalculateEdges, cancel, resolve) {
|
|
72
72
|
if (type === "start") {
|
|
73
73
|
this.eventCanceller = cancel;
|
|
74
74
|
this.eventHandler(e, state, forceRecalculateEdges);
|
|
75
75
|
}
|
|
76
|
-
if (type === "end") {
|
|
77
|
-
this.activeAction = void 0;
|
|
78
|
-
}
|
|
79
76
|
if (this.activeAction) {
|
|
80
|
-
const res2 = this.actions[this.activeAction].
|
|
77
|
+
const res2 = this.actions[this.activeAction].onMoveChange(type, e, state, forceRecalculateEdges, this.boundCancel, resolve);
|
|
81
78
|
this.shapes.splice(0, this.shapes.length, ...res2.shapes);
|
|
82
79
|
this.setTextHints(type);
|
|
83
80
|
return res2;
|
|
84
81
|
}
|
|
85
82
|
this.setTextHints(type);
|
|
86
|
-
const res = this.
|
|
83
|
+
const res = this.defaultOnMoveChange(type, e, state, forceRecalculateEdges, this.boundCancel, resolve);
|
|
87
84
|
this.shapes.splice(0, this.shapes.length, ...res.shapes);
|
|
88
85
|
return res;
|
|
89
86
|
}
|
|
87
|
+
onMoveEnded() {
|
|
88
|
+
if (this.activeAction) {
|
|
89
|
+
this.actions[this.activeAction].onMoveEnded();
|
|
90
|
+
}
|
|
91
|
+
this.activeAction = void 0;
|
|
92
|
+
}
|
|
90
93
|
setTextHints(type) {
|
|
91
94
|
this.textHints.actions = [];
|
|
92
95
|
this.textHints.errors = [];
|
|
@@ -118,11 +121,11 @@ export class DragActionHandler {
|
|
|
118
121
|
}
|
|
119
122
|
}
|
|
120
123
|
}
|
|
121
|
-
|
|
124
|
+
onMoveApply(state, forceRecalculateEdges) {
|
|
122
125
|
if (this.activeAction) {
|
|
123
|
-
const res = this.actions[this.activeAction].
|
|
126
|
+
const res = this.actions[this.activeAction].onMoveApply(state, forceRecalculateEdges);
|
|
124
127
|
this.hooks.onEnd?.({ cancelled: false, applied: res });
|
|
125
|
-
return { apply: res, result: void 0 };
|
|
128
|
+
return { apply: !res, result: void 0 };
|
|
126
129
|
}
|
|
127
130
|
this.hooks.onEnd?.({ cancelled: false, applied: false });
|
|
128
131
|
return { apply: true, result: void 0 };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { getCloseFrameInfo } from "../layout/getCloseFrameInfo.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ActionChangeResult, CloseDeco, IAction, MoveState } from "../types/index.js";
|
|
3
3
|
import type { KnownError } from "../utils/KnownError.js";
|
|
4
4
|
export type CloseInfo = Exclude<ReturnType<typeof getCloseFrameInfo>, KnownError>;
|
|
5
|
-
export declare class CloseAction implements
|
|
5
|
+
export declare class CloseAction implements IAction {
|
|
6
6
|
name: "close";
|
|
7
7
|
minDragDistance: number;
|
|
8
8
|
state: {
|
|
@@ -10,13 +10,13 @@ export declare class CloseAction implements IDragAction {
|
|
|
10
10
|
force: boolean;
|
|
11
11
|
res: CloseInfo;
|
|
12
12
|
cacheKey: string | undefined;
|
|
13
|
-
lastReturn:
|
|
13
|
+
lastReturn: ActionChangeResult;
|
|
14
14
|
} | {
|
|
15
15
|
allowed: false;
|
|
16
16
|
force: boolean;
|
|
17
17
|
res: CloseInfo | undefined;
|
|
18
18
|
cacheKey: string | undefined;
|
|
19
|
-
lastReturn:
|
|
19
|
+
lastReturn: ActionChangeResult | undefined;
|
|
20
20
|
};
|
|
21
21
|
debug: boolean | string;
|
|
22
22
|
textHints: {
|
|
@@ -29,7 +29,7 @@ export declare class CloseAction implements IDragAction {
|
|
|
29
29
|
}) => string[]);
|
|
30
30
|
transformError: (e: KnownError) => string;
|
|
31
31
|
};
|
|
32
|
-
handleEvent: (e: PointerEvent | KeyboardEvent, state:
|
|
32
|
+
handleEvent: (e: PointerEvent | KeyboardEvent, state: MoveState) => boolean | "force";
|
|
33
33
|
modifyDecos: (shapes: CloseDeco[]) => void;
|
|
34
34
|
hooks: {
|
|
35
35
|
onStart?: (active: boolean) => void;
|
|
@@ -51,8 +51,9 @@ export declare class CloseAction implements IDragAction {
|
|
|
51
51
|
actions: string[];
|
|
52
52
|
errors: string[];
|
|
53
53
|
};
|
|
54
|
-
canHandleRequest(e: PointerEvent | KeyboardEvent, state:
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
canHandleRequest(e: PointerEvent | KeyboardEvent, state: MoveState): boolean;
|
|
55
|
+
onMoveChange(type: "start" | "end" | "move", _e: PointerEvent | undefined, state: MoveState): ActionChangeResult;
|
|
56
|
+
onMoveApply(state: MoveState): boolean;
|
|
57
57
|
cancel(): void;
|
|
58
|
+
onMoveEnded(): void;
|
|
58
59
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ActionHandler } from "./ActionHandler.js";
|
|
2
2
|
import { dirToOrientation } from "../helpers/dirToOrientation.js";
|
|
3
3
|
import { getEdgeOrientation } from "../helpers/getEdgeOrientation.js";
|
|
4
4
|
import { oppositeSide } from "../helpers/oppositeSide.js";
|
|
@@ -46,8 +46,8 @@ export class CloseAction {
|
|
|
46
46
|
}
|
|
47
47
|
_getDecos(state) {
|
|
48
48
|
let decos = [];
|
|
49
|
-
const {
|
|
50
|
-
if (
|
|
49
|
+
const { isMoving } = state;
|
|
50
|
+
if (isMoving && this.state.allowed && this.state.res) {
|
|
51
51
|
const { force } = this.state;
|
|
52
52
|
decos = this.state.res.deleted.map((_) => ({
|
|
53
53
|
id: _.id,
|
|
@@ -86,11 +86,11 @@ export class CloseAction {
|
|
|
86
86
|
return this.textHints;
|
|
87
87
|
}
|
|
88
88
|
canHandleRequest(e, state) {
|
|
89
|
-
const {
|
|
90
|
-
if (
|
|
89
|
+
const { movingEdges } = state;
|
|
90
|
+
if (movingEdges.length !== 1) return false;
|
|
91
91
|
const res = this.handleEvent(e, state);
|
|
92
92
|
this.state.force = res === "force";
|
|
93
|
-
this.setTextHints(state.
|
|
93
|
+
this.setTextHints(state.isMoving === "edge" ? true : void 0);
|
|
94
94
|
if (res) {
|
|
95
95
|
this.hooks.onStart?.(true);
|
|
96
96
|
return true;
|
|
@@ -98,42 +98,42 @@ export class CloseAction {
|
|
|
98
98
|
this.reset();
|
|
99
99
|
return false;
|
|
100
100
|
}
|
|
101
|
-
|
|
102
|
-
if (state.
|
|
101
|
+
onMoveChange(type, _e, state) {
|
|
102
|
+
if (state.moveDistance <= this.minDragDistance) {
|
|
103
103
|
return { updateEdges: false, shapes: [] };
|
|
104
104
|
}
|
|
105
105
|
const {
|
|
106
106
|
touchingFramesArrays,
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
moveDirections,
|
|
108
|
+
isMoving,
|
|
109
|
+
movingEdges,
|
|
110
110
|
visualEdges,
|
|
111
111
|
frames,
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
isMovingFromWindowEdge,
|
|
113
|
+
movePoint
|
|
114
114
|
} = state;
|
|
115
|
-
const oppositeOrientation = oppositeSide(getEdgeOrientation(
|
|
116
|
-
const cacheKey = `${
|
|
115
|
+
const oppositeOrientation = oppositeSide(getEdgeOrientation(movingEdges[0]));
|
|
116
|
+
const cacheKey = `${movePoint?.x}-${movePoint?.y}-${moveDirections[oppositeOrientation]}-${this.state.force}`;
|
|
117
117
|
if (this.state.allowed) {
|
|
118
118
|
if (this.state.cacheKey === cacheKey) {
|
|
119
119
|
return this.state.lastReturn;
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
|
-
if (
|
|
122
|
+
if (isMoving && movingEdges.length === 1) {
|
|
123
123
|
const res = findFramesTouchingEdge(
|
|
124
|
-
|
|
124
|
+
movingEdges[0],
|
|
125
125
|
touchingFramesArrays[0],
|
|
126
126
|
{
|
|
127
|
-
// referencePoint:
|
|
128
|
-
searchDirections: [
|
|
127
|
+
// referencePoint: movePoint.value, // if force pick smallest frame?
|
|
128
|
+
searchDirections: [moveDirections[oppositeOrientation]]
|
|
129
129
|
}
|
|
130
130
|
);
|
|
131
131
|
if (res.length > 0) {
|
|
132
|
-
const orientation = dirToOrientation(
|
|
132
|
+
const orientation = dirToOrientation(moveDirections[oppositeOrientation]);
|
|
133
133
|
const sizeKey = orientation === "horizontal" ? "width" : "height";
|
|
134
134
|
const smallestFrameSize = Math.min(...res.map((_) => _.frame[sizeKey]));
|
|
135
135
|
const frame = res.find((_) => _.frame[sizeKey] === smallestFrameSize).frame;
|
|
136
|
-
const closeInfo = getCloseFrameInfo(Object.values(frames), visualEdges, frame,
|
|
136
|
+
const closeInfo = getCloseFrameInfo(Object.values(frames), visualEdges, frame, moveDirections[oppositeOrientation], "dir", this.state.force);
|
|
137
137
|
this.state.cacheKey = cacheKey;
|
|
138
138
|
this.setTextHints(closeInfo);
|
|
139
139
|
if (!(closeInfo instanceof Error)) {
|
|
@@ -148,26 +148,30 @@ export class CloseAction {
|
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
const decos = this._getDecos(state);
|
|
151
|
-
this.state.lastReturn = {
|
|
151
|
+
this.state.lastReturn = {
|
|
152
|
+
updateEdges: !isMovingFromWindowEdge,
|
|
153
|
+
shapes: type === "end" ? [] : decos.flatMap((_) => _.shapes)
|
|
154
|
+
};
|
|
152
155
|
return this.state.lastReturn;
|
|
153
156
|
}
|
|
154
|
-
|
|
157
|
+
onMoveApply(state) {
|
|
155
158
|
if (this.state.res) {
|
|
156
159
|
const win = state.win;
|
|
157
160
|
if (this.debug) {
|
|
158
|
-
|
|
161
|
+
ActionHandler.debugState(this.name, "before", state, this.state, this.debug);
|
|
159
162
|
}
|
|
160
163
|
applyFrameChanges(win, this.state.res);
|
|
161
164
|
if (this.debug) {
|
|
162
|
-
|
|
165
|
+
ActionHandler.debugState(this.name, "after", state, this.state, this.debug);
|
|
163
166
|
}
|
|
164
|
-
this.reset();
|
|
165
167
|
return true;
|
|
166
168
|
}
|
|
167
169
|
return false;
|
|
168
170
|
}
|
|
169
171
|
cancel() {
|
|
170
|
-
this.reset();
|
|
171
172
|
this.hooks.onCancel?.();
|
|
172
173
|
}
|
|
174
|
+
onMoveEnded() {
|
|
175
|
+
this.reset();
|
|
176
|
+
}
|
|
173
177
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ActionChangeResult, FrameDeco, IAction, LayoutChange, MoveState, Zone } from "../types/index.js";
|
|
2
2
|
import type { KnownError } from "../utils/KnownError.js";
|
|
3
|
-
export declare class FrameDragAction implements
|
|
3
|
+
export declare class FrameDragAction implements IAction {
|
|
4
4
|
name: "frameDrag";
|
|
5
5
|
minDragDistance: number;
|
|
6
6
|
state: {
|
|
@@ -11,7 +11,7 @@ export declare class FrameDragAction implements IDragAction {
|
|
|
11
11
|
actions: string[];
|
|
12
12
|
errors: string[];
|
|
13
13
|
};
|
|
14
|
-
handleEvent: (e: PointerEvent | KeyboardEvent, state:
|
|
14
|
+
handleEvent: (e: PointerEvent | KeyboardEvent, state: MoveState) => boolean;
|
|
15
15
|
dragHints: {
|
|
16
16
|
actions: {
|
|
17
17
|
split?: string;
|
|
@@ -23,7 +23,7 @@ export declare class FrameDragAction implements IDragAction {
|
|
|
23
23
|
}) => string[]);
|
|
24
24
|
transformError: (e: KnownError) => string;
|
|
25
25
|
};
|
|
26
|
-
modifyDecos: (shapes:
|
|
26
|
+
modifyDecos: (shapes: FrameDeco[]) => void;
|
|
27
27
|
hooks: {
|
|
28
28
|
onStart?: () => void;
|
|
29
29
|
onCancel?: () => void;
|
|
@@ -42,9 +42,10 @@ export declare class FrameDragAction implements IDragAction {
|
|
|
42
42
|
actions: string[];
|
|
43
43
|
errors: string[];
|
|
44
44
|
};
|
|
45
|
-
getDecos(matchedZone:
|
|
46
|
-
canHandleRequest(e: PointerEvent | KeyboardEvent, state:
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
getDecos(matchedZone: Zone | undefined, state: MoveState, result: LayoutChange<"split" | "swap" | "rearrange" | "dock"> | KnownError | undefined): FrameDeco[];
|
|
46
|
+
canHandleRequest(e: PointerEvent | KeyboardEvent, state: MoveState): boolean;
|
|
47
|
+
onMoveChange<T extends "start" | "move" | "end">(type: T, _e: PointerEvent | undefined, state: MoveState): ActionChangeResult;
|
|
48
|
+
onMoveApply(state: MoveState): boolean;
|
|
49
|
+
onMoveEnded(): void;
|
|
49
50
|
cancel(): void;
|
|
50
51
|
}
|