@witchcraft/layout 0.4.3 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +54 -45
- package/dist/runtime/components/LayoutWindow.vue +29 -29
- package/dist/runtime/components/LayoutWindow.vue.d.ts +54 -45
- package/dist/runtime/composables/useFrames.d.ts +142 -129
- package/dist/runtime/composables/useFrames.js +122 -94
- 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/demo/tailwind.css +1 -1
- package/dist/runtime/helpers/createZoneSideClipPath.d.ts +2 -2
- package/dist/runtime/helpers/findEdgesTouchingWindow.d.ts +7 -0
- package/dist/runtime/helpers/findEdgesTouchingWindow.js +20 -0
- 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 +10 -3
- package/dist/runtime/helpers/index.js +10 -3
- package/dist/runtime/layout/createSplitDecoFromDrag.d.ts +1 -1
- package/dist/runtime/layout/createSplitDecoFromDrag.js +2 -2
- package/dist/runtime/layout/debugFrame.js +5 -1
- 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/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/getFrameRearrangeInfo.d.ts +2 -2
- package/dist/runtime/layout/getFrameRearrangeInfo.js +8 -8
- package/dist/runtime/layout/getFrameShrinkInfo.d.ts +14 -0
- package/dist/runtime/layout/getFrameShrinkInfo.js +48 -0
- package/dist/runtime/layout/getFrameSplitInfo.d.ts +1 -1
- package/dist/runtime/layout/getFrameSplitInfo.js +2 -2
- package/dist/runtime/layout/getFrameUncollapseInfo.d.ts +1 -1
- package/dist/runtime/layout/getFrameUncollapseInfo.js +6 -20
- 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/getUpdateWindowSizeInfo.js +10 -12
- 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 +6 -3
- package/dist/runtime/layout/index.js +6 -3
- package/dist/runtime/{drag/DragActionHandler.d.ts → move/ActionHandler.d.ts} +18 -18
- package/dist/runtime/{drag/DragActionHandler.js → move/ActionHandler.js} +19 -19
- package/dist/runtime/{drag → move}/CloseAction.d.ts +8 -8
- package/dist/runtime/{drag → move}/CloseAction.js +29 -26
- package/dist/runtime/{drag → move}/FrameDragAction.d.ts +8 -8
- package/dist/runtime/{drag → move}/FrameDragAction.js +23 -21
- 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 +9 -9
- package/dist/runtime/{drag → move}/SplitAction.js +46 -43
- package/dist/runtime/{drag → move}/createDefaultHandlers.d.ts +2 -2
- package/dist/runtime/types/index.d.ts +242 -158
- package/dist/runtime/types/index.js +4 -3
- package/dist/runtime/types/vue.d.ts +25 -18
- package/dist/runtime/types/vue.js +1 -1
- package/package.json +3 -2
- 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 +35 -35
- package/src/runtime/composables/useFrames.ts +141 -121
- package/src/runtime/demo/App.vue +18 -18
- package/src/runtime/demo/DemoControls.vue +5 -5
- package/src/runtime/demo/tailwind.css +4 -0
- package/src/runtime/helpers/createZoneSideClipPath.ts +2 -2
- package/src/runtime/helpers/findEdgesTouchingWindow.ts +30 -0
- 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 +10 -3
- package/src/runtime/layout/createSplitDecoFromDrag.ts +2 -2
- package/src/runtime/layout/debugFrame.ts +6 -1
- package/src/runtime/layout/findSafeSplitEdge.ts +4 -4
- package/src/runtime/layout/getCloseFrameInfo.ts +4 -4
- 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/getFrameRearrangeInfo.ts +10 -10
- package/src/runtime/layout/getFrameShrinkInfo.ts +87 -0
- package/src/runtime/layout/getFrameSplitInfo.ts +5 -5
- package/src/runtime/layout/getFrameUncollapseInfo.ts +8 -30
- package/src/runtime/layout/{getFrameDragZones.ts → getFrameZones.ts} +4 -4
- package/src/runtime/layout/getUpdateWindowSizeInfo.ts +16 -22
- package/src/runtime/layout/{getWindowDragZones.ts → getWindowZones.ts} +1 -1
- package/src/runtime/layout/getZones.ts +48 -0
- package/src/runtime/layout/index.ts +6 -3
- package/src/runtime/{drag/DragActionHandler.ts → move/ActionHandler.ts} +44 -42
- package/src/runtime/{drag → move}/CloseAction.ts +39 -36
- package/src/runtime/{drag → move}/FrameDragAction.ts +36 -35
- package/src/runtime/{drag/DragDirectionStore.ts → move/MoveDirectionStore.ts} +10 -10
- package/src/runtime/{drag → move}/SplitAction.ts +56 -53
- package/src/runtime/{drag/defaultDragActions.ts → move/createDefaultHandlers.ts} +2 -2
- package/src/runtime/types/index.ts +104 -55
- package/src/runtime/types/vue.ts +18 -16
- package/dist/runtime/drag/defaultDragActions.d.ts +0 -9
- package/dist/runtime/drag/defaultDragActions.js +0 -10
- package/dist/runtime/layout/getDragZones.d.ts +0 -8
- package/dist/runtime/layout/getDragZones.js +0 -32
- package/src/runtime/drag/createDefaultHandlers.ts +0 -20
- package/src/runtime/layout/getDragZones.ts +0 -48
- /package/dist/runtime/{drag → move}/createDefaultHandlers.js +0 -0
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { debounce } from "@alanscodelog/utils/debounce";
|
|
2
2
|
import { keys } from "@alanscodelog/utils/keys";
|
|
3
3
|
import { computed, onBeforeUnmount, onMounted, ref, watch } from "vue";
|
|
4
|
-
import { DragDirectionStore } from "../drag/DragDirectionStore.js";
|
|
5
4
|
import { cloneFrame } from "../helpers/cloneFrame.js";
|
|
6
5
|
import { getIntersections } from "../helpers/getIntersections.js";
|
|
7
6
|
import { getVisualEdges } from "../helpers/getVisualEdges.js";
|
|
@@ -10,8 +9,9 @@ import { moveEdge } from "../helpers/moveEdge.js";
|
|
|
10
9
|
import { toWindowCoord } from "../helpers/toWindowCoord.js";
|
|
11
10
|
import { findFramesTouchingEdge } from "../layout/findFramesTouchingEdge.js";
|
|
12
11
|
import { isPointInRect } from "../layout/isPointInRect.js";
|
|
12
|
+
import { MoveDirectionStore } from "../move/MoveDirectionStore.js";
|
|
13
13
|
export function useFrames(win, handler) {
|
|
14
|
-
const
|
|
14
|
+
const movingEdges = ref([]);
|
|
15
15
|
const touchingFrames = ref([]);
|
|
16
16
|
const allTouchingFrames = computed(() => {
|
|
17
17
|
const result = {};
|
|
@@ -23,22 +23,23 @@ export function useFrames(win, handler) {
|
|
|
23
23
|
return result;
|
|
24
24
|
});
|
|
25
25
|
const touchingFramesArrays = computed(() => touchingFrames.value.map((entry) => Object.values(entry)));
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
let
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
const
|
|
26
|
+
const isMoving = ref(false);
|
|
27
|
+
const showMoving = ref(false);
|
|
28
|
+
const movePoint = ref();
|
|
29
|
+
const moveDirections = ref({});
|
|
30
|
+
let moveStartPoint;
|
|
31
|
+
const moveDistance = ref(-1);
|
|
32
|
+
const movingIntersection = ref(void 0);
|
|
33
|
+
const isMovingFromWindowEdge = ref(false);
|
|
34
|
+
const movingFrameId = ref();
|
|
35
|
+
const eventContext = ref();
|
|
35
36
|
const frames = computed(
|
|
36
|
-
() =>
|
|
37
|
+
() => isMoving.value && showMoving.value ? { ...win.value.frames, ...allTouchingFrames.value } : win.value.frames
|
|
37
38
|
);
|
|
38
|
-
const
|
|
39
|
-
if (
|
|
39
|
+
const moveHoveredFrame = computed(() => {
|
|
40
|
+
if (isMoving.value) {
|
|
40
41
|
for (const id of keys(frames.value)) {
|
|
41
|
-
if (isPointInRect(frames.value[id],
|
|
42
|
+
if (isPointInRect(frames.value[id], movePoint.value)) {
|
|
42
43
|
return frames.value[id];
|
|
43
44
|
}
|
|
44
45
|
}
|
|
@@ -47,83 +48,101 @@ export function useFrames(win, handler) {
|
|
|
47
48
|
});
|
|
48
49
|
const visualEdges = ref([]);
|
|
49
50
|
const intersections = computed(() => getIntersections(visualEdges.value));
|
|
50
|
-
const
|
|
51
|
+
const debounceGetMoveableEdges = debounce((f) => {
|
|
51
52
|
visualEdges.value = getVisualEdges(f, { includeWindowEdges: true });
|
|
52
53
|
handler.annotateEdges?.(visualEdges.value, f);
|
|
53
54
|
}, 50, {});
|
|
54
|
-
watch([
|
|
55
|
-
if (
|
|
56
|
-
|
|
55
|
+
watch([isMoving, frames], () => {
|
|
56
|
+
if (isMoving.value) return;
|
|
57
|
+
debounceGetMoveableEdges(Object.values(frames.value));
|
|
57
58
|
}, { deep: true });
|
|
58
|
-
|
|
59
|
+
debounceGetMoveableEdges(Object.values(frames.value));
|
|
59
60
|
function forceRecalculateEdges() {
|
|
60
61
|
visualEdges.value = getVisualEdges(Object.values(frames.value), { includeWindowEdges: true });
|
|
61
62
|
handler.annotateEdges?.(visualEdges.value, Object.values(frames.value));
|
|
62
63
|
}
|
|
63
|
-
const
|
|
64
|
-
onUpdate: (dir) =>
|
|
64
|
+
const moveDirStore = new MoveDirectionStore({
|
|
65
|
+
onUpdate: (dir) => moveDirections.value = dir
|
|
65
66
|
});
|
|
66
67
|
const state = computed(() => ({
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
68
|
+
moveDirections: moveDirections.value,
|
|
69
|
+
movePoint: movePoint.value,
|
|
70
|
+
moveDistance: moveDistance.value,
|
|
71
|
+
isMoving: isMoving.value,
|
|
72
|
+
showMoving: showMoving.value,
|
|
73
|
+
movingFrameId: movingFrameId.value,
|
|
74
|
+
movingEdges: movingEdges.value,
|
|
75
|
+
movingIntersection: movingIntersection.value,
|
|
75
76
|
visualEdges: visualEdges.value,
|
|
76
77
|
touchingFrames: touchingFrames.value,
|
|
77
78
|
touchingFramesArrays: touchingFramesArrays.value,
|
|
78
79
|
frames: frames.value,
|
|
79
|
-
|
|
80
|
+
moveHoveredFrame: moveHoveredFrame.value,
|
|
80
81
|
intersections: intersections.value,
|
|
81
|
-
|
|
82
|
+
isMovingFromWindowEdge: isMovingFromWindowEdge.value,
|
|
83
|
+
eventContext: eventContext.value,
|
|
82
84
|
win: win.value
|
|
83
85
|
}));
|
|
84
86
|
let controller;
|
|
87
|
+
let moveResolve;
|
|
88
|
+
let moveResult;
|
|
85
89
|
function resetState() {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
moveStartPoint = void 0;
|
|
91
|
+
moveResolve?.(moveResult);
|
|
92
|
+
moveResolve = void 0;
|
|
93
|
+
moveResult = void 0;
|
|
94
|
+
movingEdges.value = [];
|
|
95
|
+
movingIntersection.value = void 0;
|
|
96
|
+
isMoving.value = false;
|
|
97
|
+
movePoint.value = void 0;
|
|
98
|
+
moveDistance.value = -1;
|
|
92
99
|
touchingFrames.value = [];
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
100
|
+
movingFrameId.value = void 0;
|
|
101
|
+
eventContext.value = void 0;
|
|
102
|
+
moveDirStore.reset();
|
|
103
|
+
showMoving.value = false;
|
|
96
104
|
forceRecalculateEdges();
|
|
97
105
|
}
|
|
98
|
-
function
|
|
106
|
+
function moveStart(e, type, data, {
|
|
107
|
+
moveEvent = "pointermove",
|
|
108
|
+
endEvent = "pointerup",
|
|
109
|
+
context
|
|
110
|
+
} = {}) {
|
|
111
|
+
if (controller) {
|
|
112
|
+
controller.abort();
|
|
113
|
+
}
|
|
114
|
+
const promise = new Promise((resolve2) => {
|
|
115
|
+
moveResolve = resolve2;
|
|
116
|
+
});
|
|
99
117
|
controller = new AbortController();
|
|
100
118
|
controller.signal.addEventListener("abort", () => resetState());
|
|
101
119
|
e.preventDefault();
|
|
102
|
-
window.addEventListener(
|
|
103
|
-
window.addEventListener(
|
|
120
|
+
window.addEventListener(moveEvent, onMove, { signal: controller.signal });
|
|
121
|
+
window.addEventListener(endEvent, moveEnd, { signal: controller.signal });
|
|
104
122
|
const point = toWindowCoord(win.value, e);
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
123
|
+
movePoint.value = point;
|
|
124
|
+
moveStartPoint = { ...point };
|
|
125
|
+
moveDirStore.update(point);
|
|
126
|
+
eventContext.value = context;
|
|
127
|
+
isMoving.value = type;
|
|
128
|
+
showMoving.value = true;
|
|
110
129
|
if (type === "frame") {
|
|
111
|
-
|
|
130
|
+
movingFrameId.value = data.frameId;
|
|
112
131
|
} else {
|
|
113
132
|
const { edge, intersection } = data;
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
...
|
|
117
|
-
...
|
|
133
|
+
movingIntersection.value = intersection;
|
|
134
|
+
movingEdges.value = edge ? [edge] : [
|
|
135
|
+
...movingIntersection.value?.sharedEdges.horizontal ?? [],
|
|
136
|
+
...movingIntersection.value?.sharedEdges.vertical ?? []
|
|
118
137
|
];
|
|
119
|
-
|
|
138
|
+
isMovingFromWindowEdge.value = movingEdges.value.some((_) => isWindowEdge(_));
|
|
120
139
|
const framesArray = Object.values(win.value.frames);
|
|
121
140
|
touchingFrames.value = [];
|
|
122
141
|
const clones = /* @__PURE__ */ new Map();
|
|
123
|
-
for (let i = 0; i <
|
|
124
|
-
const
|
|
142
|
+
for (let i = 0; i < movingEdges.value.length; i++) {
|
|
143
|
+
const movingEdge = movingEdges.value[i];
|
|
125
144
|
touchingFrames.value[i] = {};
|
|
126
|
-
for (const { frame } of findFramesTouchingEdge(
|
|
145
|
+
for (const { frame } of findFramesTouchingEdge(movingEdge, framesArray)) {
|
|
127
146
|
if (!clones.has(frame.id)) {
|
|
128
147
|
const clone = cloneFrame(frame);
|
|
129
148
|
touchingFrames.value[i][frame.id] = clone;
|
|
@@ -134,52 +153,60 @@ export function useFrames(win, handler) {
|
|
|
134
153
|
}
|
|
135
154
|
}
|
|
136
155
|
}
|
|
137
|
-
const res = handler.
|
|
138
|
-
|
|
156
|
+
const res = handler.onMoveChange("start", e, state.value, forceRecalculateEdges, cancel, resolve);
|
|
157
|
+
showMoving.value = res.showMoving ?? true;
|
|
158
|
+
return promise;
|
|
139
159
|
}
|
|
140
|
-
function
|
|
160
|
+
function onMove(e) {
|
|
141
161
|
e.preventDefault();
|
|
142
162
|
const point = toWindowCoord(win.value, e);
|
|
143
|
-
const didChange =
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (
|
|
147
|
-
|
|
148
|
-
Math.pow(point.x -
|
|
163
|
+
const didChange = moveDirStore.update(point);
|
|
164
|
+
movePoint.value = point;
|
|
165
|
+
moveDistance.value = 0;
|
|
166
|
+
if (moveStartPoint) {
|
|
167
|
+
moveDistance.value = Math.sqrt(
|
|
168
|
+
Math.pow(point.x - moveStartPoint.x, 2) + Math.pow(point.y - moveStartPoint.y, 2)
|
|
149
169
|
);
|
|
150
170
|
}
|
|
151
171
|
if (!didChange) return;
|
|
152
|
-
const res = handler.
|
|
153
|
-
|
|
172
|
+
const res = handler.onMoveChange("move", e, state.value, forceRecalculateEdges, cancel, resolve);
|
|
173
|
+
showMoving.value = res.showMoving ?? true;
|
|
154
174
|
if (!res.updateEdges) return;
|
|
155
|
-
if (
|
|
175
|
+
if (isMoving.value === "edge") {
|
|
156
176
|
requestAnimationFrame(() => {
|
|
157
|
-
for (let i = 0; i <
|
|
158
|
-
const
|
|
159
|
-
if (
|
|
160
|
-
moveEdge(touchingFramesArrays.value[i],
|
|
177
|
+
for (let i = 0; i < movingEdges.value.length; i++) {
|
|
178
|
+
const movingEdge = movingEdges.value[i];
|
|
179
|
+
if (movingEdge) {
|
|
180
|
+
moveEdge(touchingFramesArrays.value[i], movingEdge, point);
|
|
161
181
|
}
|
|
162
182
|
}
|
|
163
183
|
forceRecalculateEdges();
|
|
164
184
|
});
|
|
165
185
|
}
|
|
166
186
|
}
|
|
167
|
-
function
|
|
187
|
+
function moveEnd(e, { apply = true } = {}) {
|
|
168
188
|
if (e) {
|
|
169
189
|
const point = toWindowCoord(win.value, e);
|
|
170
|
-
|
|
190
|
+
movePoint.value = point;
|
|
171
191
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
192
|
+
if (apply) {
|
|
193
|
+
const applyResult = handler.onMoveApply(state.value, forceRecalculateEdges);
|
|
194
|
+
moveResult = applyResult.result;
|
|
195
|
+
if (applyResult.apply) {
|
|
196
|
+
for (const frame of touchingFramesArrays.value.flat()) {
|
|
197
|
+
win.value.frames[frame.id] = frame;
|
|
198
|
+
}
|
|
176
199
|
}
|
|
177
200
|
}
|
|
178
|
-
handler.
|
|
201
|
+
handler.onMoveChange("end", e, state.value, forceRecalculateEdges, void 0, void 0);
|
|
179
202
|
controller?.abort();
|
|
180
203
|
}
|
|
181
204
|
function cancel() {
|
|
182
|
-
|
|
205
|
+
moveEnd(void 0, { apply: false });
|
|
206
|
+
}
|
|
207
|
+
function resolve({ apply, result: value }) {
|
|
208
|
+
moveResult = value;
|
|
209
|
+
moveEnd(void 0, { apply });
|
|
183
210
|
}
|
|
184
211
|
const keydownController = new AbortController();
|
|
185
212
|
const wrappedKeydownHandler = (e) => {
|
|
@@ -194,25 +221,26 @@ export function useFrames(win, handler) {
|
|
|
194
221
|
keydownController?.abort();
|
|
195
222
|
});
|
|
196
223
|
return {
|
|
197
|
-
|
|
198
|
-
|
|
224
|
+
moveStart,
|
|
225
|
+
moveEnd,
|
|
199
226
|
cancel,
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
227
|
+
onMove,
|
|
228
|
+
moveDirections,
|
|
229
|
+
movePoint,
|
|
230
|
+
isMoving,
|
|
231
|
+
movingEdges,
|
|
232
|
+
movingIntersection,
|
|
206
233
|
visualEdges,
|
|
207
234
|
touchingFrames,
|
|
208
235
|
touchingFramesArrays,
|
|
209
236
|
frames,
|
|
210
|
-
|
|
237
|
+
moveHoveredFrame,
|
|
211
238
|
intersections,
|
|
212
|
-
|
|
239
|
+
isMovingFromWindowEdge,
|
|
213
240
|
forceRecalculateEdges,
|
|
214
241
|
state,
|
|
215
|
-
|
|
216
|
-
|
|
242
|
+
showMoving,
|
|
243
|
+
movingFrameId,
|
|
244
|
+
actionHandler: handler
|
|
217
245
|
};
|
|
218
246
|
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
v-if="win"
|
|
11
11
|
:frames="frames"
|
|
12
12
|
:win="win"
|
|
13
|
-
:
|
|
13
|
+
:actionHandler="actionHandler"
|
|
14
14
|
/>
|
|
15
15
|
|
|
16
16
|
<LayoutWindow
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
:textHints="textHints"
|
|
35
35
|
textHintsTeleportTo="#status-bar"
|
|
36
36
|
v-model:win="win"
|
|
37
|
-
@is-showing-
|
|
38
|
-
@
|
|
37
|
+
@is-showing-move="isShowingMove = $event"
|
|
38
|
+
@move-state="moveState = $event"
|
|
39
39
|
>
|
|
40
40
|
<LayoutFrame class="
|
|
41
41
|
flex
|
|
@@ -175,7 +175,7 @@ import {
|
|
|
175
175
|
import { settings } from "../settings.js";
|
|
176
176
|
import { throwIfError } from "@alanscodelog/utils/throwIfError";
|
|
177
177
|
import { useTemplateRef } from "vue";
|
|
178
|
-
import {
|
|
178
|
+
import { ActionHandler } from "../move/ActionHandler.js";
|
|
179
179
|
import LayoutDragEdgeHandle from "../components/LayoutDragEdgeHandle.vue";
|
|
180
180
|
import LayoutDragEdgeVisible from "../components/LayoutDragEdgeVisible.vue";
|
|
181
181
|
import LayoutIntersectionVisible from "../components/LayoutIntersectionVisible.vue";
|
|
@@ -213,25 +213,25 @@ function layoutInitialize(layout, { defaultPos, defaultSize } = {
|
|
|
213
213
|
}));
|
|
214
214
|
w.activeFrame = frame.id;
|
|
215
215
|
}
|
|
216
|
-
const
|
|
217
|
-
const
|
|
216
|
+
const isShowingMove = ref(false);
|
|
217
|
+
const moveState = ref(void 0);
|
|
218
218
|
function handleUndock(frameId) {
|
|
219
219
|
const changes = throwIfError(getFrameUndockInfo(win.value, frameId));
|
|
220
|
-
|
|
220
|
+
ActionHandler.debugState("undock", "before", moveState.value, {}, void 0);
|
|
221
221
|
applyFrameChanges(win.value, changes);
|
|
222
|
-
|
|
222
|
+
ActionHandler.debugState("undock", "after", moveState.value, {}, void 0);
|
|
223
223
|
}
|
|
224
224
|
function handleCollapse(frameId) {
|
|
225
225
|
const changes = throwIfError(getFrameCollapseInfo(win.value, frameId));
|
|
226
|
-
|
|
226
|
+
ActionHandler.debugState("collapse", "before", moveState.value, {}, void 0);
|
|
227
227
|
applyFrameChanges(win.value, changes);
|
|
228
|
-
|
|
228
|
+
ActionHandler.debugState("collapse", "after", moveState.value, {}, void 0);
|
|
229
229
|
}
|
|
230
230
|
function handleUncollapse(frameId) {
|
|
231
231
|
const changes = throwIfError(getFrameUncollapseInfo(win.value, frameId));
|
|
232
|
-
|
|
232
|
+
ActionHandler.debugState("uncollapse", "before", moveState.value, {}, void 0);
|
|
233
233
|
applyFrameChanges(win.value, changes);
|
|
234
|
-
|
|
234
|
+
ActionHandler.debugState("uncollapse", "after", moveState.value, {}, void 0);
|
|
235
235
|
}
|
|
236
236
|
const collapsedDocks = computed(() => {
|
|
237
237
|
const sides = {};
|
|
@@ -242,12 +242,12 @@ const collapsedDocks = computed(() => {
|
|
|
242
242
|
}
|
|
243
243
|
return sides;
|
|
244
244
|
});
|
|
245
|
-
const
|
|
245
|
+
const actionHandler = computed(() => layoutComponent.value?.actionHandler);
|
|
246
246
|
const textHints = computed(() => {
|
|
247
|
-
const
|
|
248
|
-
const textHints2 =
|
|
247
|
+
const isMoving = moveState.value?.isMoving;
|
|
248
|
+
const textHints2 = actionHandler.value?.textHints ?? { actions: [], errors: [] };
|
|
249
249
|
return [
|
|
250
|
-
...!
|
|
250
|
+
...!isMoving ? [{ classes: "", text: "Drag from an edge to create a new frame." }] : [],
|
|
251
251
|
...textHints2.errors.map((_) => ({ classes: "text-red-500", text: _ })),
|
|
252
252
|
...textHints2.actions.map((_) => ({ text: _ }))
|
|
253
253
|
];
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { LayoutFrame, LayoutWindow } from "../types/index.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ActionHandler } from "../move/ActionHandler.js";
|
|
3
3
|
type __VLS_Props = {
|
|
4
4
|
win: LayoutWindow;
|
|
5
5
|
frames: LayoutFrame[];
|
|
6
|
-
|
|
6
|
+
actionHandler?: ActionHandler<any>;
|
|
7
7
|
};
|
|
8
8
|
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
9
9
|
export default _default;
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
<WButton class="flex-1" @click="copyState">Copy State</WButton>
|
|
27
27
|
<WCheckbox v-model="renameFrames">Easy Ids</WCheckbox>
|
|
28
28
|
</div>
|
|
29
|
-
<label class="flex flex-col gap-2 text-sm" v-if="
|
|
29
|
+
<label class="flex flex-col gap-2 text-sm" v-if="actionHandler">
|
|
30
30
|
<span>Plugin Debug Logs (true | debug path):</span>
|
|
31
31
|
<WSimpleInput v-model="debugKey" />
|
|
32
32
|
</label>
|
|
@@ -55,7 +55,7 @@ import { rotateLayout } from "../helpers/rotateFrames.js";
|
|
|
55
55
|
const props = defineProps({
|
|
56
56
|
win: { type: Object, required: true },
|
|
57
57
|
frames: { type: Array, required: true },
|
|
58
|
-
|
|
58
|
+
actionHandler: { type: Object, required: false }
|
|
59
59
|
});
|
|
60
60
|
const showDevActions = ref(false);
|
|
61
61
|
const collapseSizeValue = ref(settings.collapseSizePx.width);
|
|
@@ -101,9 +101,9 @@ function copyState() {
|
|
|
101
101
|
}
|
|
102
102
|
const debugKey = ref(import.meta.dev ? "state.win.frames" : "false");
|
|
103
103
|
watch(debugKey, () => {
|
|
104
|
-
if (!props.
|
|
104
|
+
if (!props.actionHandler) return;
|
|
105
105
|
const value = debugKey.value === "true" ? true : debugKey.value === "false" ? false : debugKey.value;
|
|
106
|
-
for (const plugin of Object.values(props.
|
|
106
|
+
for (const plugin of Object.values(props.actionHandler.actions)) {
|
|
107
107
|
plugin.debug = value;
|
|
108
108
|
}
|
|
109
109
|
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { LayoutFrame, LayoutWindow } from "../types/index.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ActionHandler } from "../move/ActionHandler.js";
|
|
3
3
|
type __VLS_Props = {
|
|
4
4
|
win: LayoutWindow;
|
|
5
5
|
frames: LayoutFrame[];
|
|
6
|
-
|
|
6
|
+
actionHandler?: ActionHandler<any>;
|
|
7
7
|
};
|
|
8
8
|
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
9
9
|
export default _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
@import "tailwindcss";@import "../../../playground/.nuxt/witchcraft-ui.css";@import "../../../playground/.nuxt/witchcraft-layout.css";@source "../../../src/runtime/demo";
|
|
1
|
+
@import "tailwindcss";@import "../../../playground/.nuxt/witchcraft-ui.css";@import "../../../playground/.nuxt/witchcraft-layout.css";@source "../../../src/runtime/demo";button{cursor:pointer}
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Accepts scaled coordinates.
|
|
7
7
|
*/
|
|
8
|
-
import type {
|
|
9
|
-
export declare function createZoneSideClipPath(zone:
|
|
8
|
+
import type { Zone } from "../types/index.js";
|
|
9
|
+
export declare function createZoneSideClipPath(zone: Zone, { frameEdgePx, windowEdgePx }: {
|
|
10
10
|
frameEdgePx: number;
|
|
11
11
|
windowEdgePx: number;
|
|
12
12
|
}): string | undefined;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { EdgeSide, LayoutFrame } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Checks which window edges a frame touches and how.
|
|
4
|
+
*
|
|
5
|
+
* @returns Record mapping touched sides to `"full"` (spans the entire edge) or `"partial"` (touches but doesn't span fully). Only touched sides are included as keys.
|
|
6
|
+
*/
|
|
7
|
+
export declare function findEdgesTouchingWindow(frame: LayoutFrame): Partial<Record<EdgeSide, "full" | "partial">>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { settings } from "../settings.js";
|
|
2
|
+
export function findEdgesTouchingWindow(frame) {
|
|
3
|
+
const maxInt = settings.maxInt;
|
|
4
|
+
const result = {};
|
|
5
|
+
const spansVertical = frame.y === 0 && frame.y + frame.height === maxInt;
|
|
6
|
+
const spansHorizontal = frame.x === 0 && frame.x + frame.width === maxInt;
|
|
7
|
+
if (frame.x === 0) {
|
|
8
|
+
result.left = spansVertical ? "full" : "partial";
|
|
9
|
+
}
|
|
10
|
+
if (frame.x + frame.width === maxInt) {
|
|
11
|
+
result.right = spansVertical ? "full" : "partial";
|
|
12
|
+
}
|
|
13
|
+
if (frame.y === 0) {
|
|
14
|
+
result.top = spansHorizontal ? "full" : "partial";
|
|
15
|
+
}
|
|
16
|
+
if (frame.y + frame.height === maxInt) {
|
|
17
|
+
result.bottom = spansHorizontal ? "full" : "partial";
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Edge, EdgeSide, LayoutFrame } from "../types/index.js";
|
|
2
|
-
export declare function
|
|
3
|
-
/** See {@link
|
|
2
|
+
export declare function findFrameMoveableEdges(frame: LayoutFrame, edges: Edge[],
|
|
3
|
+
/** See {@link findMoveableEdge} */
|
|
4
4
|
exact?: boolean, sides?: EdgeSide[]): {
|
|
5
5
|
edge: Edge;
|
|
6
6
|
side: EdgeSide;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { findMoveableEdge } from "./findMoveableEdge.js";
|
|
2
2
|
import { frameToEdges } from "./frameToEdges.js";
|
|
3
3
|
import { isWindowEdge } from "./isWindowEdge.js";
|
|
4
4
|
import { sideToOrientation } from "./sideToOrientation.js";
|
|
5
|
-
export function
|
|
5
|
+
export function findFrameMoveableEdges(frame, edges, exact = true, sides = ["left", "right", "top", "bottom"]) {
|
|
6
6
|
const frameEdges = frameToEdges(frame);
|
|
7
7
|
const res = [];
|
|
8
8
|
for (const side of sides) {
|
|
@@ -10,7 +10,7 @@ export function findFrameDraggableEdges(frame, edges, exact = true, sides = ["le
|
|
|
10
10
|
const edgeDirection = sideToOrientation(side);
|
|
11
11
|
const isWinEdge = isWindowEdge(edge, edgeDirection);
|
|
12
12
|
if (isWinEdge) continue;
|
|
13
|
-
const maybeEdge =
|
|
13
|
+
const maybeEdge = findMoveableEdge(edge, edges, exact, edgeDirection);
|
|
14
14
|
if (maybeEdge) res.push({ edge: maybeEdge, side });
|
|
15
15
|
}
|
|
16
16
|
if (res.length > 0) return res;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Edge, Orientation } from "../types/index.js";
|
|
2
|
-
export declare function
|
|
2
|
+
export declare function findMoveableEdge(edge: Edge, edges: Edge[],
|
|
3
3
|
/** Whether the edge must match exactly and does not "contain/touch" another frame. */
|
|
4
4
|
exact?: boolean, edgeOrientation?: Orientation): Edge | undefined;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { containsEdge } from "./containsEdge.js";
|
|
2
2
|
import { getEdgeOrientation } from "./getEdgeOrientation.js";
|
|
3
3
|
import { isEdgeEqual } from "./isEdgeEqual.js";
|
|
4
|
-
export function
|
|
4
|
+
export function findMoveableEdge(edge, edges, exact = true, edgeOrientation) {
|
|
5
5
|
edgeOrientation ??= getEdgeOrientation(edge);
|
|
6
6
|
for (const otherEdge of edges) {
|
|
7
7
|
const didFindEdge = exact ? isEdgeEqual(edge, otherEdge, edgeOrientation) : containsEdge(edge, otherEdge, edgeOrientation);
|
|
@@ -9,6 +9,7 @@ export { assertValidWinAndFrameIds } from "./assertValidWinAndFrameIds.js";
|
|
|
9
9
|
export { assertWindowHasActiveFrame } from "./assertWindowHasActiveFrame.js";
|
|
10
10
|
export { cloneFrame } from "./cloneFrame.js";
|
|
11
11
|
export { cloneFrames } from "./cloneFrames.js";
|
|
12
|
+
export { consoleDebugWindow } from "./consoleDebugWindow.js";
|
|
12
13
|
export { containsEdge } from "./containsEdge.js";
|
|
13
14
|
export { convertLayoutWindowToWorkspace } from "./convertLayoutWindowToWorkspace.js";
|
|
14
15
|
export { copySize } from "./copySize.js";
|
|
@@ -19,19 +20,23 @@ export { dirToSide } from "./dirToSide.js";
|
|
|
19
20
|
export { doEdgesOverlap } from "./doEdgesOverlap.js";
|
|
20
21
|
export { doesEdgeContinueEdge } from "./doesEdgeContinueEdge.js";
|
|
21
22
|
export { edgeToPoints } from "./edgeToPoints.js";
|
|
22
|
-
export {
|
|
23
|
-
export {
|
|
23
|
+
export { findMoveableEdge } from "./findMoveableEdge.js";
|
|
24
|
+
export { findFrameMoveableEdges } from "./findFrameMoveableEdges.js";
|
|
25
|
+
export { framesRedistributeFix } from "./framesRedistributeFix.js";
|
|
24
26
|
export { frameToEdges } from "./frameToEdges.js";
|
|
25
27
|
export { frameToPoints } from "./frameToPoints.js";
|
|
28
|
+
export { getDockBoundaries } from "./getDockBoundaries.js";
|
|
26
29
|
export { getEdgeLength } from "./getEdgeLength.js";
|
|
27
30
|
export { getEdgeOrientation } from "./getEdgeOrientation.js";
|
|
28
31
|
export { getEdgeSharedDirection } from "./getEdgeSharedDirection.js";
|
|
29
32
|
export { getEdgeSide } from "./getEdgeSide.js";
|
|
30
33
|
export { getFrameById } from "./getFrameById.js";
|
|
31
34
|
export { getFrameConstant } from "./getFrameConstant.js";
|
|
35
|
+
export { findEdgesTouchingWindow } from "./findEdgesTouchingWindow.js";
|
|
32
36
|
export { getIntersections } from "./getIntersections.js";
|
|
33
37
|
export { getIntersectionsCss } from "./getIntersectionsCss.js";
|
|
34
38
|
export { getMoveEdgeInfo } from "./getMoveEdgeInfo.js";
|
|
39
|
+
export { getPinnedEdgesForCollapsedFrames } from "./getPinnedEdgesForCollapsedFrames.js";
|
|
35
40
|
export { getResizeLimit } from "./getResizeLimit.js";
|
|
36
41
|
export { getShapeRectCss } from "./getShapeRectCss.js";
|
|
37
42
|
export { getSideTouching } from "./getSideTouching.js";
|
|
@@ -52,9 +57,10 @@ export { isWindowEdge } from "./isWindowEdge.js";
|
|
|
52
57
|
export { isWindowEdgePoint } from "./isWindowEdgePoint.js";
|
|
53
58
|
export { moveEdge } from "./moveEdge.js";
|
|
54
59
|
export { numberToScaledPercent } from "./numberToScaledPercent.js";
|
|
55
|
-
export { pxSizeToScaledSize } from "./pxSizeToScaledSize.js";
|
|
56
60
|
export { oppositeSide } from "./oppositeSide.js";
|
|
61
|
+
export { pxSizeToScaledSize } from "./pxSizeToScaledSize.js";
|
|
57
62
|
export { resizeByEdge } from "./resizeByEdge.js";
|
|
63
|
+
export { rotateLayout } from "./rotateFrames.js";
|
|
58
64
|
export { scaledPointToPx } from "./scaledPointToPx.js";
|
|
59
65
|
export { sideToDirection } from "./sideToDirection.js";
|
|
60
66
|
export { sideToOrientation } from "./sideToOrientation.js";
|
|
@@ -64,3 +70,4 @@ export { toId } from "./toId.js";
|
|
|
64
70
|
export { toWindowCoord } from "./toWindowCoord.js";
|
|
65
71
|
export { unionEdges } from "./unionEdges.js";
|
|
66
72
|
export { updateWindowWithEvent } from "./updateWindowSizeWithEvent.js";
|
|
73
|
+
export { validateLayoutShape } from "./validateLayoutShape.js";
|