@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.
Files changed (99) 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 +44 -44
  15. package/dist/runtime/components/LayoutWindow.vue +27 -27
  16. package/dist/runtime/components/LayoutWindow.vue.d.ts +44 -44
  17. package/dist/runtime/composables/useFrames.d.ts +107 -109
  18. package/dist/runtime/composables/useFrames.js +107 -99
  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/helpers/createZoneSideClipPath.d.ts +2 -2
  24. package/dist/runtime/helpers/{findFrameDraggableEdges.d.ts → findFrameMoveableEdges.d.ts} +2 -2
  25. package/dist/runtime/helpers/{findFrameDraggableEdges.js → findFrameMoveableEdges.js} +3 -3
  26. package/dist/runtime/helpers/{findDraggableEdge.d.ts → findMoveableEdge.d.ts} +1 -1
  27. package/dist/runtime/helpers/{findDraggableEdge.js → findMoveableEdge.js} +1 -1
  28. package/dist/runtime/helpers/index.d.ts +2 -2
  29. package/dist/runtime/helpers/index.js +2 -2
  30. package/dist/runtime/layout/createSplitDecoFromDrag.d.ts +1 -1
  31. package/dist/runtime/layout/createSplitDecoFromDrag.js +2 -2
  32. package/dist/runtime/layout/findSafeSplitEdge.d.ts +1 -1
  33. package/dist/runtime/layout/findSafeSplitEdge.js +2 -2
  34. package/dist/runtime/layout/getCloseFrameInfo.js +4 -4
  35. package/dist/runtime/layout/getFrameRearrangeInfo.d.ts +2 -2
  36. package/dist/runtime/layout/getFrameRearrangeInfo.js +8 -8
  37. package/dist/runtime/layout/getFrameSplitInfo.d.ts +1 -1
  38. package/dist/runtime/layout/getFrameSplitInfo.js +2 -2
  39. package/dist/runtime/layout/{getFrameDragZones.d.ts → getFrameZones.d.ts} +3 -3
  40. package/dist/runtime/layout/{getFrameDragZones.js → getFrameZones.js} +1 -1
  41. package/dist/runtime/layout/{getWindowDragZones.d.ts → getWindowZones.d.ts} +1 -1
  42. package/dist/runtime/layout/{getWindowDragZones.js → getWindowZones.js} +1 -1
  43. package/dist/runtime/layout/getZones.d.ts +8 -0
  44. package/dist/runtime/layout/getZones.js +32 -0
  45. package/dist/runtime/layout/index.d.ts +3 -3
  46. package/dist/runtime/layout/index.js +3 -3
  47. package/dist/runtime/{drag/DragActionHandler.d.ts → move/ActionHandler.d.ts} +19 -21
  48. package/dist/runtime/{drag/DragActionHandler.js → move/ActionHandler.js} +21 -18
  49. package/dist/runtime/{drag → move}/CloseAction.d.ts +9 -8
  50. package/dist/runtime/{drag → move}/CloseAction.js +31 -27
  51. package/dist/runtime/{drag → move}/FrameDragAction.d.ts +9 -8
  52. package/dist/runtime/{drag → move}/FrameDragAction.js +23 -22
  53. package/dist/runtime/{drag/DragDirectionStore.d.ts → move/MoveDirectionStore.d.ts} +4 -4
  54. package/dist/runtime/{drag/DragDirectionStore.js → move/MoveDirectionStore.js} +9 -9
  55. package/dist/runtime/{drag → move}/SplitAction.d.ts +10 -9
  56. package/dist/runtime/{drag → move}/SplitAction.js +53 -44
  57. package/dist/runtime/{drag → move}/createDefaultHandlers.d.ts +2 -2
  58. package/dist/runtime/types/index.d.ts +192 -171
  59. package/dist/runtime/types/index.js +2 -2
  60. package/dist/runtime/types/vue.d.ts +14 -16
  61. package/dist/runtime/types/vue.js +1 -1
  62. package/package.json +1 -1
  63. package/src/runtime/components/FrameDragHandle.vue +3 -3
  64. package/src/runtime/components/LayoutDragEdgeGrabbed.vue +3 -3
  65. package/src/runtime/components/LayoutDragEdgeHandle.vue +4 -4
  66. package/src/runtime/components/LayoutDragEdges.vue +5 -5
  67. package/src/runtime/components/LayoutEdgesActiveFrame.vue +2 -2
  68. package/src/runtime/components/LayoutFrame.vue +2 -2
  69. package/src/runtime/components/LayoutIntersectionHandle.vue +4 -4
  70. package/src/runtime/components/LayoutIntersections.vue +4 -4
  71. package/src/runtime/components/LayoutWindow.vue +32 -32
  72. package/src/runtime/composables/useFrames.ts +115 -104
  73. package/src/runtime/demo/App.vue +18 -18
  74. package/src/runtime/demo/DemoControls.vue +5 -5
  75. package/src/runtime/helpers/createZoneSideClipPath.ts +2 -2
  76. package/src/runtime/helpers/{findFrameDraggableEdges.ts → findFrameMoveableEdges.ts} +4 -4
  77. package/src/runtime/helpers/{findDraggableEdge.ts → findMoveableEdge.ts} +1 -1
  78. package/src/runtime/helpers/index.ts +2 -2
  79. package/src/runtime/layout/createSplitDecoFromDrag.ts +2 -2
  80. package/src/runtime/layout/findSafeSplitEdge.ts +4 -4
  81. package/src/runtime/layout/getCloseFrameInfo.ts +4 -4
  82. package/src/runtime/layout/getFrameRearrangeInfo.ts +10 -10
  83. package/src/runtime/layout/getFrameSplitInfo.ts +5 -5
  84. package/src/runtime/layout/{getFrameDragZones.ts → getFrameZones.ts} +4 -4
  85. package/src/runtime/layout/{getWindowDragZones.ts → getWindowZones.ts} +1 -1
  86. package/src/runtime/layout/getZones.ts +48 -0
  87. package/src/runtime/layout/index.ts +3 -3
  88. package/src/runtime/{drag/DragActionHandler.ts → move/ActionHandler.ts} +48 -41
  89. package/src/runtime/{drag → move}/CloseAction.ts +42 -37
  90. package/src/runtime/{drag → move}/FrameDragAction.ts +37 -36
  91. package/src/runtime/{drag/DragDirectionStore.ts → move/MoveDirectionStore.ts} +10 -10
  92. package/src/runtime/{drag → move}/SplitAction.ts +64 -54
  93. package/src/runtime/{drag → move}/createDefaultHandlers.ts +2 -2
  94. package/src/runtime/types/index.ts +90 -69
  95. package/src/runtime/types/vue.ts +14 -14
  96. package/dist/runtime/layout/getDragZones.d.ts +0 -8
  97. package/dist/runtime/layout/getDragZones.js +0 -32
  98. package/src/runtime/layout/getDragZones.ts +0 -48
  99. /package/dist/runtime/{drag → move}/createDefaultHandlers.js +0 -0
@@ -7,7 +7,7 @@ import { getSideTouching } from "../helpers/getSideTouching.js"
7
7
  import { isEdgeEqual } from "../helpers/isEdgeEqual.js"
8
8
  import { oppositeSide } from "../helpers/oppositeSide.js"
9
9
  import { sideToDirection } from "../helpers/sideToDirection.js"
10
- import type { DragZone, LayoutChange, LayoutWindow } from "../types/index.js"
10
+ import type { LayoutChange, LayoutWindow, Zone } from "../types/index.js"
11
11
  import { LAYOUT_ERROR } from "../types/index.js"
12
12
  import { KnownError } from "../utils/KnownError.js"
13
13
 
@@ -150,9 +150,9 @@ import { KnownError } from "../utils/KnownError.js"
150
150
 
151
151
  export function getFrameRearrangeInfo(
152
152
  win: LayoutWindow,
153
- draggingFrameId: string,
153
+ movingFrameId: string,
154
154
  hoveredFrameId: string,
155
- zoneSide: DragZone["side"]
155
+ zoneSide: Zone["side"]
156
156
  ): LayoutChange<"split" | "swap" | "rearrange">
157
157
  | KnownError<typeof LAYOUT_ERROR.CANT_SWAP_WITH_SELF>
158
158
  | KnownError<typeof LAYOUT_ERROR.CANT_SPLIT_FRAME_TOO_SMALL>
@@ -161,10 +161,10 @@ export function getFrameRearrangeInfo(
161
161
  | KnownError<typeof LAYOUT_ERROR.CANT_REARRANGE_DOCKED_WITH_NON_DOCKED>
162
162
  | KnownError<typeof LAYOUT_ERROR.CANT_SPLIT_DOCKED_FRAME>
163
163
  | KnownError<typeof LAYOUT_ERROR.NO_FILL_CANDIDATES> {
164
- const draggingFrame = { ...win.frames[draggingFrameId] }
164
+ const draggingFrame = { ...win.frames[movingFrameId] }
165
165
  const hoveredFrame = { ...win.frames[hoveredFrameId] }
166
166
 
167
- if (draggingFrameId === hoveredFrameId) {
167
+ if (movingFrameId === hoveredFrameId) {
168
168
  if (zoneSide === "center") return new KnownError(LAYOUT_ERROR.CANT_SWAP_WITH_SELF, `Can't swap frame with self.`, { frame: hoveredFrame, zoneSide })
169
169
  }
170
170
 
@@ -180,12 +180,12 @@ export function getFrameRearrangeInfo(
180
180
  }
181
181
 
182
182
  if (draggingFrame.docked && !hoveredFrame.docked) { // center swapping IS allowed above
183
- 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 })
183
+ 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 })
184
184
  }
185
185
 
186
186
  // block edge rearrange on docked frames
187
187
  if (hoveredFrame.docked) { // again center swapping docked to undocked and vice versa is allowed
188
- return new KnownError(LAYOUT_ERROR.CANT_REARRANGE_WITH_DOCKED_EDGES, `Can't rearrange with docked frame ${hoveredFrameId} edge, can only swap.`, { draggingFrameId, hoveredFrameId, zoneSide })
188
+ return new KnownError(LAYOUT_ERROR.CANT_REARRANGE_WITH_DOCKED_EDGES, `Can't rearrange with docked frame ${hoveredFrameId} edge, can only swap.`, { movingFrameId, hoveredFrameId, zoneSide })
189
189
  }
190
190
 
191
191
  const touchingSide = getSideTouching(draggingFrame, hoveredFrame)
@@ -206,7 +206,7 @@ export function getFrameRearrangeInfo(
206
206
  }
207
207
  }
208
208
  if (hoverOppositeSide === zoneSide) {
209
- return new KnownError(LAYOUT_ERROR.CANT_REARRANGE_TO_SAME_RELATIVE_POSITION, `Frame ${draggingFrameId} is already on the ${zoneSide} of ${hoveredFrameId}`, { draggingFrameId, hoveredFrameId, zoneSide })
209
+ return new KnownError(LAYOUT_ERROR.CANT_REARRANGE_TO_SAME_RELATIVE_POSITION, `Frame ${movingFrameId} is already on the ${zoneSide} of ${hoveredFrameId}`, { movingFrameId, hoveredFrameId, zoneSide })
210
210
  }
211
211
  }
212
212
  }
@@ -224,7 +224,7 @@ export function getFrameRearrangeInfo(
224
224
  const splitFrame = splitResult.modified[0]
225
225
  const newFrame = splitResult.created[0]
226
226
 
227
- if (draggingFrameId === hoveredFrameId) {
227
+ if (movingFrameId === hoveredFrameId) {
228
228
  return { ...splitResult, deleted: [], info: "split" }
229
229
  }
230
230
 
@@ -249,7 +249,7 @@ export function getFrameRearrangeInfo(
249
249
  [draggingFrame.id]: draggingFrame
250
250
  }
251
251
  }
252
- const changes = getFillEmptySpaceInfo(winCopy, emptySpace, [hoveredFrameId, draggingFrameId])
252
+ const changes = getFillEmptySpaceInfo(winCopy, emptySpace, [hoveredFrameId, movingFrameId])
253
253
  if (changes instanceof KnownError) return changes
254
254
 
255
255
  // it will also be missing said changes unless it further moved the frames which is not alway
@@ -21,7 +21,7 @@ import { KnownError } from "../utils/KnownError.js"
21
21
  export function getFrameSplitInfo(
22
22
  frame: LayoutFrame,
23
23
  dir: Direction,
24
- dragPointOrPosition: Point | number | "midpoint" = "midpoint",
24
+ movePointOrPosition: Point | number | "midpoint" = "midpoint",
25
25
  minSize: Size = settings.minSizeScaled,
26
26
  snapAmount: Point = settings.snapPointScaled
27
27
  ): LayoutChange
@@ -42,11 +42,11 @@ export function getFrameSplitInfo(
42
42
  const sizeKey: "width" | "height" = isHorz ? "width" : "height"
43
43
  const posKey: "x" | "y" = isHorz ? "x" : "y"
44
44
 
45
- const position = dragPointOrPosition === "midpoint"
45
+ const position = movePointOrPosition === "midpoint"
46
46
  ? (isHorz ? frame.x + (frame.width / 2) : frame.y + (frame.height / 2))
47
- : typeof dragPointOrPosition === "number"
48
- ? dragPointOrPosition
49
- : dragPointOrPosition[isHorz ? "x" : "y"]
47
+ : typeof movePointOrPosition === "number"
48
+ ? movePointOrPosition
49
+ : movePointOrPosition[isHorz ? "x" : "y"]
50
50
 
51
51
  const safePosition = findSafeSplitEdgeAndPosition(
52
52
  frame,
@@ -1,5 +1,5 @@
1
1
  import { settings } from "../settings.js"
2
- import type { DragZone } from "../types/index.js"
2
+ import type { Zone } from "../types/index.js"
3
3
 
4
4
  /**
5
5
  * Returns frame drag zones (in **unrounded** scaled coordinate space).
@@ -10,12 +10,12 @@ import type { DragZone } from "../types/index.js"
10
10
  *
11
11
  * Unrounded because these are for display purposes only.
12
12
  */
13
- export function getFrameDragZones(
13
+ export function getFrameZones(
14
14
  frame: { x: number, y: number, width: number, height: number },
15
15
  thresholdPx: number,
16
16
  windowPxWidth: number,
17
17
  windowPxHeight: number
18
- ): DragZone[] {
18
+ ): Zone[] {
19
19
  // we do not round as we might undo this transform and drag along errors
20
20
  // plugs this is is for display purposes only
21
21
  const thX = thresholdPx / windowPxWidth * settings.maxInt
@@ -36,7 +36,7 @@ export function getFrameDragZones(
36
36
  }]
37
37
  }
38
38
 
39
- const zones: DragZone[] = []
39
+ const zones: Zone[] = []
40
40
 
41
41
  zones.push({
42
42
  type: "frame",
@@ -6,7 +6,7 @@ import type { LayoutWindow, WindowEdgeZone } from "../types/index.js"
6
6
  * Returns window edge drag zones (in scaled coordinates)
7
7
  *
8
8
  */
9
- export function getWindowDragZones(
9
+ export function getWindowZones(
10
10
  win: LayoutWindow,
11
11
  thresholdPx: number
12
12
  ): WindowEdgeZone[] {
@@ -0,0 +1,48 @@
1
+ import { getFrameZones } from "./getFrameZones.js"
2
+ import { getWindowZones } from "./getWindowZones.js"
3
+ import { isPointInRect } from "./isPointInRect.js"
4
+
5
+ import type { MoveState, WindowEdgeZone, Zone } from "../types/index.js"
6
+
7
+ /**
8
+ * Find the drag zone under the drag point.
9
+ */
10
+ export function getZones(
11
+ state: Pick<MoveState, "movePoint" | "moveHoveredFrame" | "frames" | "win">,
12
+ { frameEdgePx, windowEdgePx }: { frameEdgePx: number, windowEdgePx: number }
13
+ ): Zone | undefined {
14
+ const { movePoint, win } = state
15
+ const frameId = state.moveHoveredFrame?.id
16
+ if (!frameId) return
17
+
18
+ const frame = state.frames[frameId]
19
+ if (!frame || !movePoint) return
20
+
21
+ const frameZones = getFrameZones(frame, frameEdgePx, win.pxWidth, win.pxHeight)
22
+
23
+ const windowZones = getWindowZones(win, windowEdgePx)
24
+
25
+ let matchedZone: Zone | undefined
26
+ for (const zone of windowZones) {
27
+ if (isPointInRect(zone, movePoint)) {
28
+ matchedZone = {
29
+ ...zone,
30
+ type: "window"
31
+ } as WindowEdgeZone
32
+ break
33
+ }
34
+ }
35
+
36
+ if (!matchedZone) {
37
+ for (const zone of frameZones) {
38
+ if (isPointInRect(zone, movePoint)) {
39
+ matchedZone = zone
40
+ break
41
+ }
42
+ }
43
+ }
44
+
45
+ if (!matchedZone) return undefined
46
+
47
+ return matchedZone
48
+ }
@@ -9,11 +9,11 @@ export { findSafeSplitEdgeAndPosition } from "./findSafeSplitEdge.js"
9
9
  export { findVisualEdge } from "./findVisualEdge.js"
10
10
  export { frameCreate } from "./frameCreate.js"
11
11
  export { getCloseFrameInfo } from "./getCloseFrameInfo.js"
12
- export { getDragZones } from "./getDragZones.js"
12
+ export { getZones } from "./getZones.js"
13
13
  export { getFillEmptySpaceInfo } from "./getFillEmptySpaceInfo.js"
14
14
  export { getFrameCollapseInfo } from "./getFrameCollapseInfo.js"
15
15
  export { getFrameDockInfo } from "./getFrameDockInfo.js"
16
- export { getFrameDragZones } from "./getFrameDragZones.js"
16
+ export { getFrameZones } from "./getFrameZones.js"
17
17
  export { getFrameExpandInfo } from "./getFrameExpandInfo.js"
18
18
  export { getFrameRearrangeInfo } from "./getFrameRearrangeInfo.js"
19
19
  export { getFrameShrinkInfo } from "./getFrameShrinkInfo.js"
@@ -25,7 +25,7 @@ export { getFrameUncollapseInfo } from "./getFrameUncollapseInfo.js"
25
25
  export { getFrameUndockInfo } from "./getFrameUndockInfo.js"
26
26
  export { getRelaxFramesInfo } from "./getRelaxFramesInfo.js"
27
27
  export { getUpdateWindowSizeInfo } from "./getUpdateWindowSizeInfo.js"
28
- export { getWindowDragZones } from "./getWindowDragZones.js"
28
+ export { getWindowZones } from "./getWindowZones.js"
29
29
  export { isPointInRect } from "./isPointInRect.js"
30
30
  export { layoutAddWindow } from "./layoutAddWindow.js"
31
31
  export { layoutCreate } from "./layoutCreate.js"
@@ -2,36 +2,36 @@ import { get, type RecordFromArray } from "@alanscodelog/utils"
2
2
 
3
3
  import { isWindowEdge } from "../helpers/isWindowEdge.js"
4
4
  import { findFramesTouchingEdge } from "../layout/findFramesTouchingEdge.js"
5
- import type { DragChangeHandler, DragChangeResult, DragState, Edge, IDragAction, LayoutFrame, LayoutShape } from "../types/index.js"
5
+ import type { ActionHandlerApplyResult, Edge, IAction, LayoutFrame, LayoutShape, MoveChangeHandler, MoveChangeResult, MoveState } from "../types/index.js"
6
6
  import { LAYOUT_ERROR } from "../types/index.js"
7
7
  import { KnownError } from "../utils/KnownError.js"
8
8
 
9
9
  /**
10
- * Handles the lifecycle of a drag actions {@link IDragAction} and provides additional hooks.
10
+ * Handles the lifecycle of a drag actions {@link IAction} and provides additional hooks.
11
11
  *
12
12
  * The first action instance that can handle the request is passed control of the event handlers until the request changes.
13
13
  */
14
- export class DragActionHandler<
15
- TRawDragActions extends IDragAction[],
16
- TDragActions extends RecordFromArray<TRawDragActions, "name"> = RecordFromArray<TRawDragActions, "name">
14
+ export class ActionHandler<
15
+ TRawActions extends IAction[],
16
+ TActions extends RecordFromArray<TRawActions, "name"> = RecordFromArray<TRawActions, "name">
17
17
  > {
18
- activeAction?: keyof TDragActions
18
+ activeAction?: keyof TActions
19
19
 
20
- actions: TDragActions
20
+ actions: TActions
21
21
 
22
- eventCanceller: ((e: PointerEvent | KeyboardEvent | undefined, state: DragState) => void) | undefined = undefined
22
+ eventCanceller: ((e: PointerEvent | KeyboardEvent | undefined, state: MoveState) => void) | undefined = undefined
23
23
 
24
- boundCancel: (e: PointerEvent | KeyboardEvent | undefined, state: DragState) => void
24
+ boundCancel: (e: PointerEvent | KeyboardEvent | undefined, state: MoveState) => void
25
25
 
26
- defaultOnDragChange: DragChangeHandler = (type, _e, state, _forceRecalculateEdges, _cancel) => {
26
+ defaultOnMoveChange: MoveChangeHandler = (type, _e, state, _forceRecalculateEdges, _cancel) => {
27
27
  const isTouchingCollapsedFrameEdge = type === "move"
28
- && state.isDragging === "edge"
28
+ && state.isMoving === "edge"
29
29
  && state.touchingFramesArrays.some(frames =>
30
30
  // we check with a falsy check on PURPOSE, frames collapsed to 0 aren't an issue, they are ignored anyways
31
31
  Object.values(frames).some(f => f.collapsed)
32
32
  )
33
33
  return {
34
- updateEdges: type === "move" ? !(state.isDraggingFromWindowEdge || isTouchingCollapsedFrameEdge) : true,
34
+ updateEdges: type === "move" ? !(state.isMovingFromWindowEdge || isTouchingCollapsedFrameEdge) : true,
35
35
  shapes: []
36
36
  }
37
37
  }
@@ -46,7 +46,7 @@ export class DragActionHandler<
46
46
  */
47
47
  onEvent?: (e: PointerEvent | KeyboardEvent | undefined, cancel: () => void) => void
48
48
  /** Called when the action requested changes. */
49
- onRequestChange?: (type: keyof TDragActions | undefined) => void
49
+ onRequestChange?: (type: keyof TActions | undefined) => void
50
50
  /** Called when the drag action ends either because it was completed or cancelled. */
51
51
  onEnd?: (context: { cancelled: boolean, applied: boolean }) => void
52
52
  }
@@ -54,22 +54,22 @@ export class DragActionHandler<
54
54
  /** All action shapes merged into a single array. If using vue you can set this to a reactive array for reactivity. */
55
55
  shapes: LayoutShape[] = []
56
56
 
57
- /** All hint/error text from all actions, updated on every onDragChange. If using vue you can set this to a reactive object for reactivity. */
57
+ /** All hint/error text from all actions, updated on every onMoveChange. If using vue you can set this to a reactive object for reactivity. */
58
58
  textHints: { actions: string[], errors: string[] } = { actions: [], errors: [] }
59
59
 
60
60
  constructor(
61
- actions: TRawDragActions,
62
- hooks: DragActionHandler<TRawDragActions, TDragActions>["hooks"] = {},
61
+ actions: TRawActions,
62
+ hooks: ActionHandler<TRawActions, TActions>["hooks"] = {},
63
63
  /**
64
- * Default onDragChange handler for when no action can handle the request.
64
+ * Default onMoveChange handler for when no action can handle the request.
65
65
  *
66
66
  * Should return true to allow the edges to be moved, or false to prevent it.
67
67
  *
68
68
  * The default prevents movement when the edge is a window edge and when the edge is touching a collapsed frame.
69
69
  */
70
- defaultOnDragChange?: DragChangeHandler
70
+ defaultOnMoveChange?: MoveChangeHandler
71
71
  ) {
72
- if (defaultOnDragChange) this.defaultOnDragChange = defaultOnDragChange
72
+ if (defaultOnMoveChange) this.defaultOnMoveChange = defaultOnMoveChange
73
73
  this.hooks = hooks
74
74
  this.actions = {} as any
75
75
  for (const action of actions) {
@@ -80,10 +80,10 @@ export class DragActionHandler<
80
80
 
81
81
  eventHandler(
82
82
  e: KeyboardEvent | PointerEvent,
83
- state: DragState,
83
+ state: MoveState,
84
84
  forceRecalculateEdges: () => void
85
85
  ) {
86
- if (state.isDragging) {
86
+ if (state.isMoving) {
87
87
  e.preventDefault()
88
88
  }
89
89
  let cancelled = false
@@ -95,7 +95,7 @@ export class DragActionHandler<
95
95
 
96
96
  let found = false
97
97
  const oldActiveAction = this.activeAction
98
- for (const action of Object.values<TRawDragActions[number]>(this.actions)) {
98
+ for (const action of Object.values<TRawActions[number]>(this.actions)) {
99
99
  if (action.canHandleRequest(e, state, forceRecalculateEdges)) {
100
100
  // if (this.activeAction !== action.name) {
101
101
  // }
@@ -116,46 +116,53 @@ export class DragActionHandler<
116
116
  this.hooks.onRequestChange?.(this.activeAction)
117
117
  }
118
118
 
119
- if (state.isDragging) {
119
+ if (state.isMoving) {
120
120
  forceRecalculateEdges()
121
121
  this.hooks.onRecalculate?.()
122
122
  }
123
123
  return undefined
124
124
  }
125
125
 
126
- onDragChange<T extends "start" | "move" | "end">(
126
+ onMoveChange<T extends "start" | "move" | "end">(
127
127
  type: T,
128
128
  e: T extends "end" ? PointerEvent | undefined : PointerEvent,
129
- state: DragState,
129
+ state: MoveState,
130
130
  forceRecalculateEdges: () => void,
131
- cancel: (e: PointerEvent | KeyboardEvent | undefined, state: DragState) => void
132
- ): DragChangeResult {
131
+ cancel: (e: PointerEvent | KeyboardEvent | undefined, state: MoveState) => void,
132
+ resolve: T extends "end" ? undefined : (opts: ActionHandlerApplyResult) => void
133
+ ): MoveChangeResult {
133
134
  if (type === "start") {
134
135
  this.eventCanceller = cancel
135
136
  this.eventHandler(e!, state, forceRecalculateEdges)
136
137
  }
137
- if (type === "end") {
138
- this.activeAction = undefined
139
- }
140
138
 
141
139
  if (this.activeAction) {
142
- const res = this.actions[this.activeAction]!.onDragChange(type, e, state, forceRecalculateEdges, this.boundCancel)
140
+ const res = this.actions[this.activeAction]!.onMoveChange(type, e, state, forceRecalculateEdges, this.boundCancel as any, resolve)
143
141
  // in case it's a vue reactive array
144
142
  this.shapes.splice(0, this.shapes.length, ...res.shapes)
145
143
  this.setTextHints(type)
146
144
  return res
147
145
  }
148
146
  this.setTextHints(type)
149
- const res = this.defaultOnDragChange(type, e, state, forceRecalculateEdges, this.boundCancel)
147
+ const res = this.defaultOnMoveChange(type, e, state, forceRecalculateEdges, this.boundCancel as any, resolve as any)
150
148
  this.shapes.splice(0, this.shapes.length, ...res.shapes)
149
+
151
150
  return res
152
151
  }
153
152
 
153
+ onMoveEnded() {
154
+ if (this.activeAction) {
155
+ this.actions[this.activeAction]!.onMoveEnded()
156
+ }
157
+
158
+ this.activeAction = undefined
159
+ }
160
+
154
161
  setTextHints(type: "start" | "move" | "end") {
155
162
  // again in case it's a vue reactive object
156
163
  this.textHints.actions = []
157
164
  this.textHints.errors = []
158
- for (const action of Object.values<IDragAction>(this.actions)) {
165
+ for (const action of Object.values<IAction>(this.actions)) {
159
166
  const res = action.getTextHints?.(type)
160
167
  this.textHints.actions.push(...(res?.actions ?? []))
161
168
  this.textHints.errors.push(...(res?.errors ?? []))
@@ -166,7 +173,7 @@ export class DragActionHandler<
166
173
  for (const edge of edges) {
167
174
  // edge already has an error
168
175
  if (edge.error) continue
169
- for (const action of Object.values<IDragAction>(this.actions)) {
176
+ for (const action of Object.values<IAction>(this.actions)) {
170
177
  action.annotateEdge?.(edge, frames)
171
178
  if (edge.error) break
172
179
  }
@@ -188,20 +195,20 @@ export class DragActionHandler<
188
195
  }
189
196
  }
190
197
 
191
- onDragApply(
192
- state: DragState,
198
+ onMoveApply(
199
+ state: MoveState,
193
200
  forceRecalculateEdges: () => void
194
- ): { apply: boolean, result: any } {
201
+ ): ActionHandlerApplyResult {
195
202
  if (this.activeAction) {
196
- const res = this.actions[this.activeAction]!.onDragApply(state, forceRecalculateEdges)
203
+ const res = this.actions[this.activeAction]!.onMoveApply(state, forceRecalculateEdges)
197
204
  this.hooks.onEnd?.({ cancelled: false, applied: res })
198
- return { apply: res, result: undefined }
205
+ return { apply: !res, result: undefined }
199
206
  }
200
207
  this.hooks.onEnd?.({ cancelled: false, applied: false })
201
208
  return { apply: true, result: undefined }
202
209
  }
203
210
 
204
- cancel(e: PointerEvent | KeyboardEvent | undefined, state: DragState): void {
211
+ cancel(e: PointerEvent | KeyboardEvent | undefined, state: MoveState): void {
205
212
  if (this.activeAction) {
206
213
  this.actions[this.activeAction].cancel(e, state)
207
214
  }
@@ -213,7 +220,7 @@ export class DragActionHandler<
213
220
  static debugState(
214
221
  pluginName: string,
215
222
  type: "before" | "after" | string,
216
- state: DragState,
223
+ state: MoveState,
217
224
  pluginState: Record<string, any> = {},
218
225
  /** 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. */
219
226
  key?: string | boolean
@@ -1,4 +1,4 @@
1
- import { DragActionHandler } from "./DragActionHandler.js"
1
+ import { ActionHandler } from "./ActionHandler.js"
2
2
 
3
3
  import { dirToOrientation } from "../helpers/dirToOrientation.js"
4
4
  import { getEdgeOrientation } from "../helpers/getEdgeOrientation.js"
@@ -6,12 +6,12 @@ import { oppositeSide } from "../helpers/oppositeSide.js"
6
6
  import { applyFrameChanges } from "../layout/applyFrameChanges.js"
7
7
  import { findFramesTouchingEdge } from "../layout/findFramesTouchingEdge.js"
8
8
  import { getCloseFrameInfo } from "../layout/getCloseFrameInfo.js"
9
- import type { ActionDragChangeResult, CloseDeco, DragState, IDragAction } from "../types/index.js"
9
+ import type { ActionChangeResult, CloseDeco, IAction, MoveState } from "../types/index.js"
10
10
  import type { KnownError } from "../utils/KnownError.js"
11
11
 
12
12
  export type CloseInfo = Exclude<ReturnType<typeof getCloseFrameInfo>, KnownError>
13
13
 
14
- export class CloseAction implements IDragAction {
14
+ export class CloseAction implements IAction {
15
15
  name = "close" as const
16
16
  minDragDistance = 5
17
17
 
@@ -20,13 +20,13 @@ export class CloseAction implements IDragAction {
20
20
  force: boolean
21
21
  res: CloseInfo
22
22
  cacheKey: string | undefined
23
- lastReturn: ActionDragChangeResult
23
+ lastReturn: ActionChangeResult
24
24
  } | {
25
25
  allowed: false
26
26
  force: boolean
27
27
  res: CloseInfo | undefined
28
28
  cacheKey: string | undefined
29
- lastReturn: ActionDragChangeResult | undefined
29
+ lastReturn: ActionChangeResult | undefined
30
30
  } = {} as any // this is initialized by this.reset()
31
31
 
32
32
  debug: boolean | string = false
@@ -40,7 +40,7 @@ export class CloseAction implements IDragAction {
40
40
  transformError: e => e.message
41
41
  }
42
42
 
43
- handleEvent: (e: PointerEvent | KeyboardEvent, state: DragState) => boolean | "force" = (e: PointerEvent | KeyboardEvent) => {
43
+ handleEvent: (e: PointerEvent | KeyboardEvent, state: MoveState) => boolean | "force" = (e: PointerEvent | KeyboardEvent) => {
44
44
  if (e.ctrlKey && e.shiftKey) {
45
45
  return "force"
46
46
  }
@@ -86,10 +86,10 @@ export class CloseAction implements IDragAction {
86
86
  this.modifyDecos([])
87
87
  }
88
88
 
89
- private _getDecos(state: DragState): CloseDeco[] {
89
+ private _getDecos(state: MoveState): CloseDeco[] {
90
90
  let decos: CloseDeco[] = []
91
- const { isDragging } = state
92
- if (isDragging && this.state.allowed && this.state.res) {
91
+ const { isMoving } = state
92
+ if (isMoving && this.state.allowed && this.state.res) {
93
93
  const { force } = this.state
94
94
  decos = this.state.res.deleted.map(_ => ({
95
95
  id: _.id,
@@ -136,12 +136,12 @@ export class CloseAction implements IDragAction {
136
136
  }
137
137
 
138
138
 
139
- canHandleRequest(e: PointerEvent | KeyboardEvent, state: DragState): boolean {
140
- const { draggingEdges } = state
141
- if (draggingEdges.length !== 1) return false
139
+ canHandleRequest(e: PointerEvent | KeyboardEvent, state: MoveState): boolean {
140
+ const { movingEdges } = state
141
+ if (movingEdges.length !== 1) return false
142
142
  const res = this.handleEvent(e, state)
143
143
  this.state.force = res === "force"
144
- this.setTextHints(state.isDragging === "edge" ? true : undefined)
144
+ this.setTextHints(state.isMoving === "edge" ? true : undefined)
145
145
  if (res) {
146
146
  this.hooks.onStart?.(true)
147
147
  return true
@@ -150,47 +150,47 @@ export class CloseAction implements IDragAction {
150
150
  return false
151
151
  }
152
152
 
153
- onDragChange(
154
- _type: "start" | "end" | "move",
153
+ onMoveChange(
154
+ type: "start" | "end" | "move",
155
155
  _e: PointerEvent | undefined,
156
- state: DragState
157
- ): ActionDragChangeResult {
158
- if (state.dragDistance <= this.minDragDistance) {
156
+ state: MoveState
157
+ ): ActionChangeResult {
158
+ if (state.moveDistance <= this.minDragDistance) {
159
159
  return { updateEdges: false, shapes: [] }
160
160
  }
161
161
  const {
162
162
  touchingFramesArrays,
163
- dragDirections,
164
- isDragging,
165
- draggingEdges,
163
+ moveDirections,
164
+ isMoving,
165
+ movingEdges,
166
166
  visualEdges,
167
167
  frames,
168
- isDraggingFromWindowEdge,
169
- dragPoint
168
+ isMovingFromWindowEdge,
169
+ movePoint
170
170
  } = state
171
- const oppositeOrientation = oppositeSide(getEdgeOrientation(draggingEdges[0]))
172
- const cacheKey = `${dragPoint?.x}-${dragPoint?.y}-${dragDirections[oppositeOrientation]!}-${this.state.force}`
171
+ const oppositeOrientation = oppositeSide(getEdgeOrientation(movingEdges[0]))
172
+ const cacheKey = `${movePoint?.x}-${movePoint?.y}-${moveDirections[oppositeOrientation]!}-${this.state.force}`
173
173
  if (this.state.allowed) {
174
174
  if (this.state.cacheKey === cacheKey) {
175
175
  return this.state.lastReturn
176
176
  }
177
177
  }
178
- if (isDragging && draggingEdges.length === 1) {
178
+ if (isMoving && movingEdges.length === 1) {
179
179
  const res = findFramesTouchingEdge(
180
- draggingEdges[0],
180
+ movingEdges[0],
181
181
  touchingFramesArrays[0],
182
182
  {
183
- // referencePoint: dragPoint.value, // if force pick smallest frame?
184
- searchDirections: [dragDirections[oppositeOrientation]!]
183
+ // referencePoint: movePoint.value, // if force pick smallest frame?
184
+ searchDirections: [moveDirections[oppositeOrientation]!]
185
185
  }
186
186
  )
187
187
  if (res.length > 0) {
188
- const orientation = dirToOrientation(dragDirections[oppositeOrientation]!)
188
+ const orientation = dirToOrientation(moveDirections[oppositeOrientation]!)
189
189
  const sizeKey = orientation === "horizontal" ? "width" : "height"
190
190
  const smallestFrameSize = Math.min(...res.map(_ => _.frame[sizeKey]))
191
191
  const frame = res.find(_ => _.frame[sizeKey] === smallestFrameSize)!.frame!
192
192
 
193
- const closeInfo = getCloseFrameInfo(Object.values(frames), visualEdges, frame, dragDirections[oppositeOrientation]!, "dir", this.state.force)
193
+ const closeInfo = getCloseFrameInfo(Object.values(frames), visualEdges, frame, moveDirections[oppositeOrientation]!, "dir", this.state.force)
194
194
  this.state.cacheKey = cacheKey
195
195
  this.setTextHints(closeInfo)
196
196
  if (!(closeInfo instanceof Error)) {
@@ -205,24 +205,29 @@ export class CloseAction implements IDragAction {
205
205
  }
206
206
  }
207
207
  const decos = this._getDecos(state)
208
- this.state.lastReturn = { updateEdges: !isDraggingFromWindowEdge, shapes: decos.flatMap(_ => _.shapes) }
208
+ this.state.lastReturn = {
209
+ updateEdges: !isMovingFromWindowEdge,
210
+ shapes: type === "end" ? [] : decos.flatMap(_ => _.shapes)
211
+ }
209
212
  return this.state.lastReturn
210
213
  }
211
214
 
212
- onDragApply(state: DragState): boolean {
215
+ onMoveApply(state: MoveState): boolean {
213
216
  if (this.state.res) {
214
217
  const win = state.win
215
- if (this.debug) { DragActionHandler.debugState(this.name, "before", state, this.state, this.debug) }
218
+ if (this.debug) { ActionHandler.debugState(this.name, "before", state, this.state, this.debug) }
216
219
  applyFrameChanges(win, this.state.res)
217
- if (this.debug) { DragActionHandler.debugState(this.name, "after", state, this.state, this.debug) }
218
- this.reset()
220
+ if (this.debug) { ActionHandler.debugState(this.name, "after", state, this.state, this.debug) }
219
221
  return true
220
222
  }
221
223
  return false
222
224
  }
223
225
 
224
226
  cancel(): void {
225
- this.reset()
226
227
  this.hooks.onCancel?.()
227
228
  }
229
+
230
+ onMoveEnded() {
231
+ this.reset()
232
+ }
228
233
  }