@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.
- package/dist/module.json +1 -1
- package/dist/runtime/components/LayoutWindow.d.vue.ts +10 -1
- package/dist/runtime/components/LayoutWindow.vue +4 -4
- package/dist/runtime/components/LayoutWindow.vue.d.ts +10 -1
- package/dist/runtime/composables/useFrames.d.ts +37 -22
- package/dist/runtime/composables/useFrames.js +32 -8
- package/dist/runtime/demo/tailwind.css +1 -1
- package/dist/runtime/drag/DragActionHandler.d.ts +4 -1
- package/dist/runtime/drag/DragActionHandler.js +2 -2
- package/dist/runtime/helpers/findEdgesTouchingWindow.d.ts +7 -0
- package/dist/runtime/helpers/findEdgesTouchingWindow.js +20 -0
- package/dist/runtime/helpers/index.d.ts +8 -1
- package/dist/runtime/helpers/index.js +8 -1
- package/dist/runtime/layout/debugFrame.js +5 -1
- package/dist/runtime/layout/getFrameCollapseInfo.d.ts +1 -1
- package/dist/runtime/layout/getFrameCollapseInfo.js +9 -29
- package/dist/runtime/layout/getFrameDockInfo.d.ts +1 -1
- package/dist/runtime/layout/getFrameDockInfo.js +61 -44
- package/dist/runtime/layout/getFrameExpandInfo.d.ts +11 -0
- package/dist/runtime/layout/getFrameExpandInfo.js +49 -0
- package/dist/runtime/layout/getFrameShrinkInfo.d.ts +14 -0
- package/dist/runtime/layout/getFrameShrinkInfo.js +48 -0
- package/dist/runtime/layout/getFrameUncollapseInfo.d.ts +1 -1
- package/dist/runtime/layout/getFrameUncollapseInfo.js +6 -20
- package/dist/runtime/layout/getUpdateWindowSizeInfo.js +10 -12
- package/dist/runtime/layout/index.d.ts +3 -0
- package/dist/runtime/layout/index.js +3 -0
- package/dist/runtime/types/index.d.ts +70 -0
- package/dist/runtime/types/index.js +2 -1
- package/dist/runtime/types/vue.d.ts +12 -3
- package/package.json +3 -2
- package/src/runtime/components/LayoutWindow.vue +5 -5
- package/src/runtime/composables/useFrames.ts +46 -32
- package/src/runtime/demo/tailwind.css +4 -0
- package/src/runtime/drag/DragActionHandler.ts +3 -3
- package/src/runtime/helpers/findEdgesTouchingWindow.ts +30 -0
- package/src/runtime/helpers/index.ts +8 -1
- package/src/runtime/layout/debugFrame.ts +6 -1
- package/src/runtime/layout/getFrameCollapseInfo.ts +12 -41
- package/src/runtime/layout/getFrameDockInfo.ts +77 -57
- package/src/runtime/layout/getFrameExpandInfo.ts +84 -0
- package/src/runtime/layout/getFrameShrinkInfo.ts +87 -0
- package/src/runtime/layout/getFrameUncollapseInfo.ts +8 -30
- package/src/runtime/layout/getUpdateWindowSizeInfo.ts +16 -22
- package/src/runtime/layout/index.ts +3 -0
- package/src/runtime/types/index.ts +39 -1
- package/src/runtime/types/vue.ts +5 -3
- package/dist/runtime/drag/defaultDragActions.d.ts +0 -9
- package/dist/runtime/drag/defaultDragActions.js +0 -10
- 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 {
|
|
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
|
|
64
|
-
|
|
65
|
-
|
|
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 {
|
|
6
|
-
import {
|
|
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"
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
//
|
|
72
|
-
|
|
73
|
-
|
|
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
|
package/src/runtime/types/vue.ts
CHANGED
|
@@ -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 }):
|
|
19
|
-
(e: PointerEvent, type: "frame", data: { frameId: FrameId }):
|
|
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
|
-
}
|