@witchcraft/layout 0.4.3 → 0.4.4

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 (50) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/LayoutWindow.d.vue.ts +10 -1
  3. package/dist/runtime/components/LayoutWindow.vue +4 -4
  4. package/dist/runtime/components/LayoutWindow.vue.d.ts +10 -1
  5. package/dist/runtime/composables/useFrames.d.ts +37 -22
  6. package/dist/runtime/composables/useFrames.js +32 -8
  7. package/dist/runtime/demo/tailwind.css +1 -1
  8. package/dist/runtime/drag/DragActionHandler.d.ts +4 -1
  9. package/dist/runtime/drag/DragActionHandler.js +2 -2
  10. package/dist/runtime/helpers/findEdgesTouchingWindow.d.ts +7 -0
  11. package/dist/runtime/helpers/findEdgesTouchingWindow.js +20 -0
  12. package/dist/runtime/helpers/index.d.ts +8 -1
  13. package/dist/runtime/helpers/index.js +8 -1
  14. package/dist/runtime/layout/debugFrame.js +5 -1
  15. package/dist/runtime/layout/getFrameCollapseInfo.d.ts +1 -1
  16. package/dist/runtime/layout/getFrameCollapseInfo.js +9 -29
  17. package/dist/runtime/layout/getFrameDockInfo.d.ts +1 -1
  18. package/dist/runtime/layout/getFrameDockInfo.js +61 -44
  19. package/dist/runtime/layout/getFrameExpandInfo.d.ts +11 -0
  20. package/dist/runtime/layout/getFrameExpandInfo.js +49 -0
  21. package/dist/runtime/layout/getFrameShrinkInfo.d.ts +14 -0
  22. package/dist/runtime/layout/getFrameShrinkInfo.js +48 -0
  23. package/dist/runtime/layout/getFrameUncollapseInfo.d.ts +1 -1
  24. package/dist/runtime/layout/getFrameUncollapseInfo.js +6 -20
  25. package/dist/runtime/layout/getUpdateWindowSizeInfo.js +10 -12
  26. package/dist/runtime/layout/index.d.ts +3 -0
  27. package/dist/runtime/layout/index.js +3 -0
  28. package/dist/runtime/types/index.d.ts +70 -0
  29. package/dist/runtime/types/index.js +2 -1
  30. package/dist/runtime/types/vue.d.ts +12 -3
  31. package/package.json +3 -2
  32. package/src/runtime/components/LayoutWindow.vue +5 -5
  33. package/src/runtime/composables/useFrames.ts +46 -32
  34. package/src/runtime/demo/tailwind.css +4 -0
  35. package/src/runtime/drag/DragActionHandler.ts +3 -3
  36. package/src/runtime/helpers/findEdgesTouchingWindow.ts +30 -0
  37. package/src/runtime/helpers/index.ts +8 -1
  38. package/src/runtime/layout/debugFrame.ts +6 -1
  39. package/src/runtime/layout/getFrameCollapseInfo.ts +12 -41
  40. package/src/runtime/layout/getFrameDockInfo.ts +77 -57
  41. package/src/runtime/layout/getFrameExpandInfo.ts +84 -0
  42. package/src/runtime/layout/getFrameShrinkInfo.ts +87 -0
  43. package/src/runtime/layout/getFrameUncollapseInfo.ts +8 -30
  44. package/src/runtime/layout/getUpdateWindowSizeInfo.ts +16 -22
  45. package/src/runtime/layout/index.ts +3 -0
  46. package/src/runtime/types/index.ts +39 -1
  47. package/src/runtime/types/vue.ts +5 -3
  48. package/dist/runtime/drag/defaultDragActions.d.ts +0 -9
  49. package/dist/runtime/drag/defaultDragActions.js +0 -10
  50. package/src/runtime/drag/defaultDragActions.ts +0 -20
@@ -0,0 +1,84 @@
1
+ import { pushIfNotIn } from "@alanscodelog/utils/pushIfNotIn"
2
+ import { walk } from "@alanscodelog/utils/walk"
3
+
4
+ import { applyFrameChanges } from "./applyFrameChanges.js"
5
+ import { getFramesRedistributeInfo } from "./getFramesRedistributeInfo.js"
6
+
7
+ import { findEdgesTouchingWindow } from "../helpers/findEdgesTouchingWindow.js"
8
+ import { framesRedistributeFix } from "../helpers/framesRedistributeFix.js"
9
+ import { getPinnedEdgesForCollapsedFrames } from "../helpers/getPinnedEdgesForCollapsedFrames.js"
10
+ import { oppositeSide } from "../helpers/oppositeSide.js"
11
+ import type { EdgeSide, LayoutChange, LayoutWindow } from "../types/index.js"
12
+ import { LAYOUT_ERROR } from "../types/index.js"
13
+ import { KnownError } from "../utils/KnownError.js"
14
+
15
+ /**
16
+ * Returns a {@link LayoutChange} with the information necessary to expand a frame touching a window edge by a given amount.
17
+ *
18
+ * Changes can be applied to a window with {@link applyFrameChanges}.
19
+ *
20
+ * It expands the frame by redistributing space from neighboring frames.
21
+ */
22
+ export function getFrameExpandInfo(
23
+ win: LayoutWindow,
24
+ frameId: string,
25
+ amount: number,
26
+ expandSide: EdgeSide
27
+ ): LayoutChange
28
+ | KnownError<typeof LAYOUT_ERROR.REDISTRIBUTE_OUT_OF_BOUNDS>
29
+ | KnownError<typeof LAYOUT_ERROR.NO_SPACE_TO_REDISTRIBUTE>
30
+ | KnownError<typeof LAYOUT_ERROR.REDISTRIBUTE_WOULD_RESULT_IN_INVALID_FRAMES>
31
+ | KnownError<typeof LAYOUT_ERROR.CANT_RESIZE_SINGLE_FRAME> {
32
+ win = walk(win, undefined, { save: true })
33
+ const frame = win.frames[frameId]
34
+ if (!frame) { throw new Error(`Unknown frame ${frameId}`) }
35
+ if (!frame.docked) { throw new Error(`Frame ${frameId} is not docked.`) }
36
+ const toExtract = [frame.id]
37
+
38
+ if (Object.keys(win.frames).length === 1) {
39
+ return new KnownError(LAYOUT_ERROR.CANT_RESIZE_SINGLE_FRAME, `Frame ${frameId} is the only frame, cannot expand.`, { frame })
40
+ }
41
+
42
+ // verify the frame actually touches the specified edge
43
+ if (!(expandSide in findEdgesTouchingWindow(frame))) {
44
+ throw new Error(`Frame ${frameId} does not touch the ${expandSide} edge.`)
45
+ }
46
+
47
+
48
+ const isVertical = frame.docked === "left" || frame.docked === "right"
49
+ const sizeKey = isVertical ? "width" : "height" as const
50
+ const posKey = isVertical ? "x" : "y"
51
+ const currentSize = frame[sizeKey]
52
+
53
+
54
+ const dockedSide = frame.docked as EdgeSide
55
+
56
+ const { applyFixes, toFix } = framesRedistributeFix(win, frame, dockedSide, posKey, sizeKey, "expand")
57
+
58
+ // note fully collapsed frames without an area are already excluded by getFramesRedistributeInfo
59
+ const otherFrameIds = Object.keys(win.frames).filter(id => id !== frameId)
60
+
61
+ const redistributeSide = oppositeSide(frame.docked)
62
+
63
+ const pinnedEdgeCoordinates: number[] = getPinnedEdgesForCollapsedFrames(win, frame, dockedSide, posKey, sizeKey)
64
+
65
+ const changes = getFramesRedistributeInfo(win, redistributeSide, otherFrameIds, amount, { pinnedEdgeCoordinates })
66
+
67
+ if (changes instanceof KnownError) {
68
+ return changes
69
+ }
70
+
71
+ applyFrameChanges(win, changes)
72
+ pushIfNotIn(toExtract, changes.modified.map(_ => _.id))
73
+
74
+ applyFixes()
75
+ pushIfNotIn(toExtract, toFix)
76
+
77
+ frame[sizeKey] = currentSize + amount
78
+
79
+ if (frame.docked === "right" || frame.docked === "bottom") {
80
+ frame[posKey] -= amount
81
+ }
82
+
83
+ return { modified: toExtract.map(_ => win.frames[_]), created: [], deleted: [] }
84
+ }
@@ -0,0 +1,87 @@
1
+ import { pushIfNotIn } from "@alanscodelog/utils/pushIfNotIn"
2
+ import { walk } from "@alanscodelog/utils/walk"
3
+
4
+ import { applyFrameChanges } from "./applyFrameChanges.js"
5
+ import { getFramesRedistributeInfo } from "./getFramesRedistributeInfo.js"
6
+
7
+ import { findEdgesTouchingWindow } from "../helpers/findEdgesTouchingWindow.js"
8
+ import { framesRedistributeFix } from "../helpers/framesRedistributeFix.js"
9
+ import { getPinnedEdgesForCollapsedFrames } from "../helpers/getPinnedEdgesForCollapsedFrames.js"
10
+ import { oppositeSide } from "../helpers/oppositeSide.js"
11
+ import type { EdgeSide, LayoutChange, LayoutWindow } from "../types/index.js"
12
+ import { LAYOUT_ERROR } from "../types/index.js"
13
+ import { KnownError } from "../utils/KnownError.js"
14
+
15
+ /**
16
+ * Returns a {@link LayoutChange} with the information necessary to shrink a frame touching a window edge by a given amount.
17
+ *
18
+ * Changes can be applied to a window with {@link applyFrameChanges}.
19
+ *
20
+ * It shrinks the frame by redistributing the freed space to neighboring frames.
21
+ */
22
+ export function getFrameShrinkInfo(
23
+ win: LayoutWindow,
24
+ frameId: string,
25
+ amount: number,
26
+ shrinkSide: EdgeSide,
27
+ {
28
+ allowOutOfBounds = false
29
+ }: {
30
+ /** Allow the resize span to exceed window bounds. */
31
+ allowOutOfBounds?: boolean
32
+ } = {}
33
+ ): LayoutChange
34
+ | KnownError<typeof LAYOUT_ERROR.REDISTRIBUTE_WOULD_RESULT_IN_INVALID_FRAMES>
35
+ | KnownError<typeof LAYOUT_ERROR.CANT_RESIZE_SINGLE_FRAME> {
36
+ win = walk(win, undefined, { save: true }) as typeof win
37
+ const frame = win.frames[frameId]
38
+ if (!frame) throw new Error(`Unknown frame ${frameId}`)
39
+
40
+ if (Object.keys(win.frames).length === 1) {
41
+ return new KnownError(LAYOUT_ERROR.CANT_RESIZE_SINGLE_FRAME, `Frame ${frameId} is the only frame, cannot shrink.`, { frame })
42
+ }
43
+
44
+ // verify the frame actually touches the specified edge
45
+ if (!(shrinkSide in findEdgesTouchingWindow(frame))) {
46
+ throw new Error(`Frame ${frameId} does not touch the ${shrinkSide} edge.`)
47
+ }
48
+
49
+ const isVertical = shrinkSide === "left" || shrinkSide === "right"
50
+ const sizeKey = isVertical ? "width" : "height" as const
51
+ const posKey = isVertical ? "x" : "y"
52
+
53
+ const toExtract = [frame.id]
54
+
55
+ const { applyFixes, toFix } = framesRedistributeFix(win, frame, shrinkSide, posKey, sizeKey, "shrink")
56
+
57
+ // note fully collapsed frames without an area are already excluded by getFramesRedistributeInfo
58
+ const otherFrameIds = Object.keys(win.frames).filter(id => id !== frameId)
59
+
60
+ const redistributeSide = oppositeSide(shrinkSide)
61
+
62
+ const pinnedEdgeCoordinates: number[] = getPinnedEdgesForCollapsedFrames(win, frame, shrinkSide, posKey, sizeKey)
63
+
64
+ const changes = getFramesRedistributeInfo(win, redistributeSide, otherFrameIds, -amount, { allowOutOfBounds, pinnedEdgeCoordinates })
65
+
66
+ if (changes instanceof KnownError) {
67
+ // we should never get out of bounds and because this is a shrink there should always be space
68
+ if (changes.code === LAYOUT_ERROR.REDISTRIBUTE_OUT_OF_BOUNDS || changes.code === LAYOUT_ERROR.NO_SPACE_TO_REDISTRIBUTE) {
69
+ changes.message = `This error should never happen, please file a bug report: ${changes.message}`
70
+ throw changes
71
+ }
72
+ return changes
73
+ }
74
+ applyFrameChanges(win, changes)
75
+ pushIfNotIn(toExtract, changes.modified.map(_ => _.id))
76
+
77
+
78
+ applyFixes()
79
+ pushIfNotIn(toExtract, toFix)
80
+
81
+ if (shrinkSide === "right" || shrinkSide === "bottom") {
82
+ frame[posKey] = frame[posKey] + amount
83
+ }
84
+ frame[sizeKey] = frame[sizeKey] - amount
85
+
86
+ return { modified: toExtract.map(_ => win.frames[_]), created: [], deleted: [] }
87
+ }
@@ -2,11 +2,8 @@ import { pushIfNotIn } from "@alanscodelog/utils/pushIfNotIn"
2
2
  import { walk } from "@alanscodelog/utils/walk"
3
3
 
4
4
  import { applyFrameChanges } from "./applyFrameChanges.js"
5
- import { getFramesRedistributeInfo } from "./getFramesRedistributeInfo.js"
5
+ import { getFrameExpandInfo } from "./getFrameExpandInfo.js"
6
6
 
7
- import { framesRedistributeFix } from "../helpers/framesRedistributeFix.js"
8
- import { getPinnedEdgesForCollapsedFrames } from "../helpers/getPinnedEdgesForCollapsedFrames.js"
9
- import { oppositeSide } from "../helpers/oppositeSide.js"
10
7
  import type { EdgeSide, LayoutChange, LayoutWindow, Size } from "../types/index.js"
11
8
  import { LAYOUT_ERROR } from "../types/index.js"
12
9
  import { KnownError } from "../utils/KnownError.js"
@@ -32,7 +29,8 @@ export function getFrameUncollapseInfo(
32
29
  | KnownError<typeof LAYOUT_ERROR.CANT_UNCOLLAPSE_NOT_COLLAPSED>
33
30
  | KnownError<typeof LAYOUT_ERROR.REDISTRIBUTE_OUT_OF_BOUNDS>
34
31
  | KnownError<typeof LAYOUT_ERROR.NO_SPACE_TO_REDISTRIBUTE>
35
- | KnownError<typeof LAYOUT_ERROR.REDISTRIBUTE_WOULD_RESULT_IN_INVALID_FRAMES> {
32
+ | KnownError<typeof LAYOUT_ERROR.REDISTRIBUTE_WOULD_RESULT_IN_INVALID_FRAMES>
33
+ | KnownError<typeof LAYOUT_ERROR.CANT_RESIZE_SINGLE_FRAME> {
36
34
  win = walk(win, undefined, { save: true })
37
35
  const frame = win.frames[frameId]
38
36
  if (!frame) { throw new Error(`Unknown frame ${frameId}`) }
@@ -42,7 +40,6 @@ export function getFrameUncollapseInfo(
42
40
 
43
41
  const isVertical = frame.docked === "left" || frame.docked === "right"
44
42
  const sizeKey = isVertical ? "width" : "height" as const
45
- const posKey = isVertical ? "x" : "y"
46
43
  const currentSize = frame[sizeKey]
47
44
 
48
45
  const storedSize = (restoreSize !== undefined ? restoreSize[sizeKey] : frame.collapsed)!
@@ -60,34 +57,15 @@ export function getFrameUncollapseInfo(
60
57
 
61
58
  const dockedSide = frame.docked as EdgeSide
62
59
 
63
- const { applyFixes, toFix } = framesRedistributeFix(win, frame, dockedSide, posKey, sizeKey, "expand")
64
-
65
- // note fully collapsed frames without an area are already excluded by getFramesRedistributeInfo
66
- const otherFrameIds = Object.keys(win.frames).filter(id => id !== frameId)
67
-
68
- const redistributeSide = oppositeSide(frame.docked)
69
-
70
- const pinnedEdgeCoordinates: number[] = getPinnedEdgesForCollapsedFrames(win, frame, dockedSide, posKey, sizeKey)
71
-
72
- const changes = getFramesRedistributeInfo(win, redistributeSide, otherFrameIds, expandAmount, { pinnedEdgeCoordinates })
73
-
74
- if (changes instanceof KnownError) {
75
- return changes
60
+ const expandResult = getFrameExpandInfo(win, frameId, expandAmount, dockedSide)
61
+ if (expandResult instanceof KnownError) {
62
+ return expandResult
76
63
  }
64
+ applyFrameChanges(win, expandResult)
65
+ pushIfNotIn(toExtract, expandResult.modified.map(_ => _.id))
77
66
 
78
- applyFrameChanges(win, changes)
79
- pushIfNotIn(toExtract, changes.modified.map(_ => _.id))
80
-
81
- applyFixes()
82
- pushIfNotIn(toExtract, toFix)
83
-
84
- frame[sizeKey] = storedSize
85
67
  frame.collapsed = undefined
86
68
 
87
- if (frame.docked === "right" || frame.docked === "bottom") {
88
- frame[posKey] -= expandAmount
89
- }
90
-
91
69
  return { modified: toExtract.map(_ => win.frames[_]), created: [], deleted: [] }
92
70
  }
93
71
 
@@ -2,8 +2,8 @@ import { pushIfNotIn } from "@alanscodelog/utils/pushIfNotIn"
2
2
  import { walk } from "@alanscodelog/utils/walk"
3
3
 
4
4
  import { applyFrameChanges } from "../layout/applyFrameChanges.js"
5
- import { getFrameCollapseInfo } from "../layout/getFrameCollapseInfo.js"
6
- import { getFrameUncollapseInfo } from "../layout/getFrameUncollapseInfo.js"
5
+ import { getFrameExpandInfo } from "../layout/getFrameExpandInfo.js"
6
+ import { getFrameShrinkInfo } from "../layout/getFrameShrinkInfo.js"
7
7
  import { getRelaxFramesInfo } from "../layout/getRelaxFramesInfo.js"
8
8
  import { settings } from "../settings.js"
9
9
  import type { LayoutChange, LayoutWindow, PxSize } from "../types/index.js"
@@ -48,29 +48,27 @@ export function getUpdateWindowSizeInfo(
48
48
  for (const frameId of dockedFrameIds) {
49
49
  const frame = win.frames[frameId]
50
50
  const orientation = (frame.docked === "left" || frame.docked === "right") ? "horizontal" : "vertical"
51
- const sizeKey = orientation === "horizontal" ? "width" : "height" as const
51
+ const sizeKey = orientation === "horizontal" ? "width" : "height"
52
52
  const targetPxSize = settings.collapseSizePx[sizeKey]
53
53
  const targetScaled = Math.round((targetPxSize / (orientation === "horizontal" ? win.pxWidth : win.pxHeight)) * maxInt)
54
54
 
55
-
56
55
  if (frame[sizeKey] === targetScaled) continue
57
56
  if (frame[sizeKey] === 0) continue
58
57
 
59
- let result: LayoutChange | KnownError<any>
60
-
61
- // the logic needed to do this is nearly identical to the collapse/uncollapse logic
62
- // so we abuse the functions a bit, in future might allow a more flexible collapse/uncollapse function
63
- const wasCollapsed = frame.collapsed
64
- const wasMinSize = { ...settings.minSize }
65
- settings.minSize = 1
66
- if (targetScaled < frame[sizeKey]) {
67
- // clear temporarily so collapse doesn't error
68
- frame.collapsed = undefined
69
- result = getFrameCollapseInfo(win, frame.id, { collapseSizeScaled: { width: targetScaled, height: targetScaled } })
58
+ const side = frame.docked!
59
+ const diff = targetScaled - frame[sizeKey]
60
+
61
+ let result: ReturnType<typeof getFrameShrinkInfo> | ReturnType<typeof getFrameExpandInfo>
62
+
63
+ if (diff < 0) {
64
+ result = getFrameShrinkInfo(win, frame.id, -diff, side, { allowOutOfBounds: true })
70
65
  } else {
71
- // set to something, could be anything
72
- frame.collapsed = Infinity
73
- result = getFrameUncollapseInfo(win, frame.id, { restoreSize: { width: targetScaled, height: targetScaled } })
66
+ // in worst case scenario allow frames to shrink
67
+ // minSize must be 1 (not 0) to avoid zero-size frames during redistribution
68
+ const wasMinSize = { ...settings.minSize }
69
+ settings.minSize = 1
70
+ result = getFrameExpandInfo(win, frame.id, diff, side)
71
+ settings.minSize = wasMinSize
74
72
  }
75
73
 
76
74
  if (!(result instanceof KnownError)) {
@@ -78,10 +76,6 @@ export function getUpdateWindowSizeInfo(
78
76
  pushIfNotIn(toExtract, result.modified.map(f => f.id))
79
77
  }
80
78
 
81
- // restore original collapsed value
82
- frame.collapsed = wasCollapsed
83
- settings.minSize = wasMinSize
84
-
85
79
 
86
80
  // attempt relaxation
87
81
  const result2 = getRelaxFramesInfo(win, relaxPasses)
@@ -14,13 +14,16 @@ export { getFillEmptySpaceInfo } from "./getFillEmptySpaceInfo.js"
14
14
  export { getFrameCollapseInfo } from "./getFrameCollapseInfo.js"
15
15
  export { getFrameDockInfo } from "./getFrameDockInfo.js"
16
16
  export { getFrameDragZones } from "./getFrameDragZones.js"
17
+ export { getFrameExpandInfo } from "./getFrameExpandInfo.js"
17
18
  export { getFrameRearrangeInfo } from "./getFrameRearrangeInfo.js"
19
+ export { getFrameShrinkInfo } from "./getFrameShrinkInfo.js"
18
20
  export { getFrameSplitInfo } from "./getFrameSplitInfo.js"
19
21
  export { getFramesRedistributeInfo } from "./getFramesRedistributeInfo.js"
20
22
  export { getFrameSwapInfo } from "./getFrameSwapInfo.js"
21
23
  export { getFrameTo } from "./getFrameTo.js"
22
24
  export { getFrameUncollapseInfo } from "./getFrameUncollapseInfo.js"
23
25
  export { getFrameUndockInfo } from "./getFrameUndockInfo.js"
26
+ export { getRelaxFramesInfo } from "./getRelaxFramesInfo.js"
24
27
  export { getUpdateWindowSizeInfo } from "./getUpdateWindowSizeInfo.js"
25
28
  export { getWindowDragZones } from "./getWindowDragZones.js"
26
29
  export { isPointInRect } from "./isPointInRect.js"
@@ -287,7 +287,8 @@ export const LAYOUT_ERROR = enumFromArray([
287
287
  "CANT_COLLAPSE_NOT_DOCKED",
288
288
  "CANT_UNCOLLAPSE_NOT_COLLAPSED",
289
289
  "NO_FILL_CANDIDATES",
290
- "CANT_RESIZE_COLLAPSED_FRAME"
290
+ "CANT_RESIZE_COLLAPSED_FRAME",
291
+ "CANT_RESIZE_SINGLE_FRAME"
291
292
  ])
292
293
 
293
294
  export type LayoutError = EnumLike<typeof LAYOUT_ERROR>
@@ -376,6 +377,9 @@ export type LayoutErrorsInfo = {
376
377
  [LAYOUT_ERROR.CANT_RESIZE_COLLAPSED_FRAME]: {
377
378
  frame: LayoutFrame
378
379
  }
380
+ [LAYOUT_ERROR.CANT_RESIZE_SINGLE_FRAME]: {
381
+ frame: LayoutFrame
382
+ }
379
383
  [LAYOUT_ERROR.REDISTRIBUTE_WOULD_RESULT_IN_INVALID_FRAMES]: {
380
384
  problemEdgeCoordinates: number[]
381
385
  }
@@ -486,6 +490,8 @@ export type DragState = {
486
490
  * Whether the drag was initiated from a point along the window edge.
487
491
  */
488
492
  isDraggingFromWindowEdge: boolean
493
+ /** Custom context passed to dragStart, available to action handlers via state.eventContext. */
494
+ eventContext?: Record<string, unknown>
489
495
  win: LayoutWindow
490
496
  }
491
497
 
@@ -602,6 +608,38 @@ export interface IDragAction {
602
608
  export type EdgeDragStartData = { edge?: Edge, intersection?: IntersectionEntry }
603
609
  export type FrameDragStartData = { frameId: FrameId }
604
610
 
611
+ /**
612
+ * Handler interface for drag actions.
613
+ */
614
+ export interface ActionHandler {
615
+ eventHandler: (e: KeyboardEvent, state: DragState, forceRecalculateEdges: () => void) => void
616
+ /**
617
+ * Called when the drag coordinates change (during any event). Should return true to allow the edges to be updated/moved, or false to prevent it.
618
+ *
619
+ * Can return anything for the end event as it's ignored.
620
+ *
621
+ * Can be used to save some context/info to later apply safely during onDragApply.
622
+ */
623
+ onDragChange: (...args: Parameters<DragChangeHandler>) => DragChangeResult
624
+ /**
625
+ * Called when drag will be applied. If dragEnd was called with apply false, it will not be called.
626
+ * Return false to not apply the regular drag end changes (i.e. return false to reset to the position before dragging).
627
+ */
628
+ onDragApply: (
629
+ state: DragState,
630
+ forceRecalculateEdges: () => void
631
+ ) => {
632
+ /** Whether to apply the regular drag end changes. Return false to reset to the position before dragging. */
633
+ apply: boolean
634
+ /** Value to resolve the drag promise with. Ignored if `apply` is false. */
635
+ result: any
636
+ }
637
+ /**
638
+ * Called after visual edges are recalculated. Action handlers can annotate edges with error info.
639
+ */
640
+ annotateEdges?: (edges: Edge[], frames: LayoutFrame[]) => void
641
+ }
642
+
605
643
  // drag start overloads for triggering dragsj
606
644
  export type DragStartFn = {
607
645
  (e: PointerEvent, type: "edge", data: EdgeDragStartData): void
@@ -1,10 +1,11 @@
1
1
  import type { ComputedRef, InjectionKey, Ref } from "vue"
2
2
 
3
3
  // eslint-disable-next-line no-restricted-imports
4
- import type { Direction, DragState, Edge, FrameId, IntersectionEntry, LayoutFrame, LayoutShape, LayoutWindow, Orientation, Point } from "./index.js"
4
+ import type { ActionHandler, Direction, DragState, Edge, FrameId, IntersectionEntry, LayoutFrame, LayoutShape, LayoutWindow, Orientation, Point } from "./index.js"
5
5
 
6
6
  export type LayoutContext = ComputedRef<
7
7
  & {
8
+
8
9
  /** The owning window, needed so we can correctly scale coordinates. */
9
10
  win: LayoutWindow
10
11
  onFocus: (frameId: string) => void
@@ -14,9 +15,10 @@ export type LayoutContext = ComputedRef<
14
15
  export const layoutContextInjectionKey = Symbol.for("@witchcraft/layout:context") as InjectionKey<LayoutContext>
15
16
 
16
17
  export interface UseFramesContext {
18
+ actionHandler: ActionHandler
17
19
  dragStart: {
18
- (e: PointerEvent, type: "edge", data: { edge?: Edge, intersection?: IntersectionEntry }): void
19
- (e: PointerEvent, type: "frame", data: { frameId: FrameId }): void
20
+ (e: PointerEvent, type: "edge", data: { edge?: Edge, intersection?: IntersectionEntry }, opts?: { moveEvent?: string, endEvent?: string, context?: Record<string, unknown> }): Promise<any>
21
+ (e: PointerEvent, type: "frame", data: { frameId: FrameId }, opts?: { moveEvent?: string, endEvent?: string, context?: Record<string, unknown> }): Promise<any>
20
22
  }
21
23
  dragMove: (e: PointerEvent) => void
22
24
  dragEnd: (e?: PointerEvent, options?: { apply?: boolean }) => void
@@ -1,9 +0,0 @@
1
- import type { IDragAction } from "../types/index.js";
2
- /**
3
- * Creates the default drag actions (Split, Close, FrameDrag).
4
- */
5
- export declare function createDefaultHandlers(config: {
6
- debugSplit?: boolean;
7
- debugClose?: boolean;
8
- debugFrameDrag?: boolean;
9
- }): IDragAction[];
@@ -1,10 +0,0 @@
1
- import { CloseAction } from "./CloseAction.js";
2
- import { FrameDragAction } from "./FrameDragAction.js";
3
- import { SplitAction } from "./SplitAction.js";
4
- export function createDefaultHandlers(config) {
5
- return [
6
- new SplitAction(void 0, void 0, void 0, { debug: config.debugSplit }),
7
- new CloseAction(void 0, void 0, void 0, { debug: config.debugClose }),
8
- new FrameDragAction(void 0, void 0, void 0, { debug: config.debugFrameDrag })
9
- ];
10
- }
@@ -1,20 +0,0 @@
1
- import { CloseAction } from "./CloseAction"
2
- import { FrameDragAction } from "./FrameDragAction.js"
3
- import { SplitAction } from "./SplitAction.js"
4
-
5
- import type { IDragAction } from "../types/index.js"
6
-
7
- /**
8
- * Creates the default drag actions (Split, Close, FrameDrag).
9
- */
10
- export function createDefaultHandlers(config: {
11
- debugSplit?: boolean
12
- debugClose?: boolean
13
- debugFrameDrag?: boolean
14
- }): IDragAction[] {
15
- return [
16
- new SplitAction(undefined, undefined, undefined, { debug: config.debugSplit }),
17
- new CloseAction(undefined, undefined, undefined, { debug: config.debugClose }),
18
- new FrameDragAction(undefined, undefined, undefined, { debug: config.debugFrameDrag })
19
- ]
20
- }