@witchcraft/layout 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.json +1 -1
- package/dist/runtime/composables/useFrames.js +7 -3
- package/dist/runtime/move/ActionHandler.d.ts +2 -1
- package/dist/runtime/move/ActionHandler.js +7 -4
- package/dist/runtime/move/CloseAction.d.ts +1 -0
- package/dist/runtime/move/CloseAction.js +7 -6
- package/dist/runtime/move/FrameDragAction.d.ts +1 -0
- package/dist/runtime/move/FrameDragAction.js +4 -5
- package/dist/runtime/move/SplitAction.d.ts +1 -0
- package/dist/runtime/move/SplitAction.js +13 -7
- package/dist/runtime/types/index.d.ts +13 -6
- package/package.json +1 -1
- package/src/runtime/composables/useFrames.ts +10 -5
- package/src/runtime/move/ActionHandler.ts +11 -6
- package/src/runtime/move/CloseAction.ts +8 -6
- package/src/runtime/move/FrameDragAction.ts +5 -5
- package/src/runtime/move/SplitAction.ts +14 -7
- package/src/runtime/types/index.ts +16 -6
package/dist/module.json
CHANGED
|
@@ -102,6 +102,7 @@ export function useFrames(win, handler) {
|
|
|
102
102
|
moveDirStore.reset();
|
|
103
103
|
showMoving.value = false;
|
|
104
104
|
forceRecalculateEdges();
|
|
105
|
+
handler.onMoveEnded();
|
|
105
106
|
}
|
|
106
107
|
function moveStart(e, type, data, {
|
|
107
108
|
moveEvent = "pointermove",
|
|
@@ -169,10 +170,13 @@ export function useFrames(win, handler) {
|
|
|
169
170
|
);
|
|
170
171
|
}
|
|
171
172
|
if (!didChange) return;
|
|
172
|
-
|
|
173
|
+
onMoveChange(e, "move", point);
|
|
174
|
+
}
|
|
175
|
+
function onMoveChange(e, type, point) {
|
|
176
|
+
const res = handler.onMoveChange(type, e, state.value, forceRecalculateEdges, cancel, type === "end" ? void 0 : resolve);
|
|
173
177
|
showMoving.value = res.showMoving ?? true;
|
|
174
178
|
if (!res.updateEdges) return;
|
|
175
|
-
if (isMoving.value === "edge") {
|
|
179
|
+
if (isMoving.value === "edge" && point) {
|
|
176
180
|
requestAnimationFrame(() => {
|
|
177
181
|
for (let i = 0; i < movingEdges.value.length; i++) {
|
|
178
182
|
const movingEdge = movingEdges.value[i];
|
|
@@ -189,6 +193,7 @@ export function useFrames(win, handler) {
|
|
|
189
193
|
const point = toWindowCoord(win.value, e);
|
|
190
194
|
movePoint.value = point;
|
|
191
195
|
}
|
|
196
|
+
onMoveChange(e, "end", movePoint.value);
|
|
192
197
|
if (apply) {
|
|
193
198
|
const applyResult = handler.onMoveApply(state.value, forceRecalculateEdges);
|
|
194
199
|
moveResult = applyResult.result;
|
|
@@ -198,7 +203,6 @@ export function useFrames(win, handler) {
|
|
|
198
203
|
}
|
|
199
204
|
}
|
|
200
205
|
}
|
|
201
|
-
handler.onMoveChange("end", e, state.value, forceRecalculateEdges, void 0, void 0);
|
|
202
206
|
controller?.abort();
|
|
203
207
|
}
|
|
204
208
|
function cancel() {
|
|
@@ -45,7 +45,8 @@ export declare class ActionHandler<TRawActions extends IAction[], TActions exten
|
|
|
45
45
|
*/
|
|
46
46
|
defaultOnMoveChange?: MoveChangeHandler);
|
|
47
47
|
eventHandler(e: KeyboardEvent | PointerEvent, state: MoveState, forceRecalculateEdges: () => void): undefined;
|
|
48
|
-
onMoveChange<T extends "start" | "move" | "end">(type: T, e: T extends "end" ? PointerEvent | undefined : PointerEvent, state: MoveState, forceRecalculateEdges: () => void, cancel:
|
|
48
|
+
onMoveChange<T extends "start" | "move" | "end">(type: T, e: T extends "end" ? PointerEvent | undefined : PointerEvent, state: MoveState, forceRecalculateEdges: () => void, cancel: (e: PointerEvent | KeyboardEvent | undefined, state: MoveState) => void, resolve: T extends "end" ? undefined : (opts: ActionHandlerApplyResult) => void): MoveChangeResult;
|
|
49
|
+
onMoveEnded(): void;
|
|
49
50
|
setTextHints(type: "start" | "move" | "end"): void;
|
|
50
51
|
annotateEdges(edges: Edge[], frames: LayoutFrame[]): void;
|
|
51
52
|
onMoveApply(state: MoveState, forceRecalculateEdges: () => void): ActionHandlerApplyResult;
|
|
@@ -82,11 +82,14 @@ export class ActionHandler {
|
|
|
82
82
|
this.setTextHints(type);
|
|
83
83
|
const res = this.defaultOnMoveChange(type, e, state, forceRecalculateEdges, this.boundCancel, resolve);
|
|
84
84
|
this.shapes.splice(0, this.shapes.length, ...res.shapes);
|
|
85
|
-
if (type === "end") {
|
|
86
|
-
this.activeAction = void 0;
|
|
87
|
-
}
|
|
88
85
|
return res;
|
|
89
86
|
}
|
|
87
|
+
onMoveEnded() {
|
|
88
|
+
if (this.activeAction) {
|
|
89
|
+
this.actions[this.activeAction].onMoveEnded();
|
|
90
|
+
}
|
|
91
|
+
this.activeAction = void 0;
|
|
92
|
+
}
|
|
90
93
|
setTextHints(type) {
|
|
91
94
|
this.textHints.actions = [];
|
|
92
95
|
this.textHints.errors = [];
|
|
@@ -122,7 +125,7 @@ export class ActionHandler {
|
|
|
122
125
|
if (this.activeAction) {
|
|
123
126
|
const res = this.actions[this.activeAction].onMoveApply(state, forceRecalculateEdges);
|
|
124
127
|
this.hooks.onEnd?.({ cancelled: false, applied: res });
|
|
125
|
-
return { apply: res, result: void 0 };
|
|
128
|
+
return { apply: !res, result: void 0 };
|
|
126
129
|
}
|
|
127
130
|
this.hooks.onEnd?.({ cancelled: false, applied: false });
|
|
128
131
|
return { apply: true, result: void 0 };
|
|
@@ -99,10 +99,6 @@ export class CloseAction {
|
|
|
99
99
|
return false;
|
|
100
100
|
}
|
|
101
101
|
onMoveChange(type, _e, state) {
|
|
102
|
-
if (type === "end") {
|
|
103
|
-
this.reset();
|
|
104
|
-
return { shapes: [] };
|
|
105
|
-
}
|
|
106
102
|
if (state.moveDistance <= this.minDragDistance) {
|
|
107
103
|
return { updateEdges: false, shapes: [] };
|
|
108
104
|
}
|
|
@@ -152,7 +148,10 @@ export class CloseAction {
|
|
|
152
148
|
}
|
|
153
149
|
}
|
|
154
150
|
const decos = this._getDecos(state);
|
|
155
|
-
this.state.lastReturn = {
|
|
151
|
+
this.state.lastReturn = {
|
|
152
|
+
updateEdges: !isMovingFromWindowEdge,
|
|
153
|
+
shapes: type === "end" ? [] : decos.flatMap((_) => _.shapes)
|
|
154
|
+
};
|
|
156
155
|
return this.state.lastReturn;
|
|
157
156
|
}
|
|
158
157
|
onMoveApply(state) {
|
|
@@ -170,7 +169,9 @@ export class CloseAction {
|
|
|
170
169
|
return false;
|
|
171
170
|
}
|
|
172
171
|
cancel() {
|
|
173
|
-
this.reset();
|
|
174
172
|
this.hooks.onCancel?.();
|
|
175
173
|
}
|
|
174
|
+
onMoveEnded() {
|
|
175
|
+
this.reset();
|
|
176
|
+
}
|
|
176
177
|
}
|
|
@@ -46,5 +46,6 @@ export declare class FrameDragAction implements IAction {
|
|
|
46
46
|
canHandleRequest(e: PointerEvent | KeyboardEvent, state: MoveState): boolean;
|
|
47
47
|
onMoveChange<T extends "start" | "move" | "end">(type: T, _e: PointerEvent | undefined, state: MoveState): ActionChangeResult;
|
|
48
48
|
onMoveApply(state: MoveState): boolean;
|
|
49
|
+
onMoveEnded(): void;
|
|
49
50
|
cancel(): void;
|
|
50
51
|
}
|
|
@@ -94,10 +94,6 @@ export class FrameDragAction {
|
|
|
94
94
|
return false;
|
|
95
95
|
}
|
|
96
96
|
onMoveChange(type, _e, state) {
|
|
97
|
-
if (type === "end") {
|
|
98
|
-
this.reset();
|
|
99
|
-
return { shapes: [] };
|
|
100
|
-
}
|
|
101
97
|
if (state.moveDistance <= this.minDragDistance) {
|
|
102
98
|
return { updateEdges: false, shapes: [], showMoving: false };
|
|
103
99
|
}
|
|
@@ -119,7 +115,7 @@ export class FrameDragAction {
|
|
|
119
115
|
this.setTextHints(this.state.lastReturn);
|
|
120
116
|
const decos = this.getDecos(matchedZone, state, this.state.lastReturn);
|
|
121
117
|
return {
|
|
122
|
-
shapes: decos.flatMap((_) => _.shapes),
|
|
118
|
+
shapes: type === "end" ? [] : decos.flatMap((_) => _.shapes),
|
|
123
119
|
updateEdges: false,
|
|
124
120
|
showMoving: false
|
|
125
121
|
};
|
|
@@ -142,6 +138,9 @@ export class FrameDragAction {
|
|
|
142
138
|
}
|
|
143
139
|
return true;
|
|
144
140
|
}
|
|
141
|
+
onMoveEnded() {
|
|
142
|
+
this.reset();
|
|
143
|
+
}
|
|
145
144
|
cancel() {
|
|
146
145
|
this.reset();
|
|
147
146
|
}
|
|
@@ -52,5 +52,6 @@ export declare class SplitAction implements IAction {
|
|
|
52
52
|
calculateSplitRequest(state: MoveState): boolean;
|
|
53
53
|
onMoveChange(type: "start" | "end" | "move", _e: PointerEvent | undefined, state: MoveState): ActionChangeResult;
|
|
54
54
|
onMoveApply(state: MoveState): boolean;
|
|
55
|
+
onMoveEnded(): void;
|
|
55
56
|
cancel(): void;
|
|
56
57
|
}
|
|
@@ -119,10 +119,6 @@ export class SplitAction {
|
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
onMoveChange(type, _e, state) {
|
|
122
|
-
if (type === "end") {
|
|
123
|
-
this.reset();
|
|
124
|
-
return { shapes: [] };
|
|
125
|
-
}
|
|
126
122
|
const { moveHoveredFrame, moveDistance } = state;
|
|
127
123
|
if (moveDistance <= this.minDragDistance) {
|
|
128
124
|
return { updateEdges: false, shapes: [], showMoving: false };
|
|
@@ -147,11 +143,19 @@ export class SplitAction {
|
|
|
147
143
|
},
|
|
148
144
|
attrs: { class: "deco-split-error bg-red-500/50" }
|
|
149
145
|
};
|
|
150
|
-
this.state.lastReturn = {
|
|
146
|
+
this.state.lastReturn = {
|
|
147
|
+
updateEdges: true,
|
|
148
|
+
shapes: type === "end" ? [] : [errorDeco],
|
|
149
|
+
showMoving: false
|
|
150
|
+
};
|
|
151
151
|
return this.state.lastReturn;
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
|
-
this.state.lastReturn = {
|
|
154
|
+
this.state.lastReturn = {
|
|
155
|
+
updateEdges: false,
|
|
156
|
+
shapes: type === "end" ? [] : decos.flatMap((_) => _.shapes),
|
|
157
|
+
showMoving: false
|
|
158
|
+
};
|
|
155
159
|
return this.state.lastReturn;
|
|
156
160
|
}
|
|
157
161
|
onMoveApply(state) {
|
|
@@ -169,8 +173,10 @@ export class SplitAction {
|
|
|
169
173
|
}
|
|
170
174
|
return true;
|
|
171
175
|
}
|
|
172
|
-
|
|
176
|
+
onMoveEnded() {
|
|
173
177
|
this.reset();
|
|
178
|
+
}
|
|
179
|
+
cancel() {
|
|
174
180
|
this.hooks.onCancel?.();
|
|
175
181
|
}
|
|
176
182
|
}
|
|
@@ -1917,9 +1917,9 @@ export type MoveChangeResult = Omit<ActionChangeResult, "shapes">;
|
|
|
1917
1917
|
* See also {@link ActionHandler.onMoveChange} to understand it's lifecycle as it is the extended version of.
|
|
1918
1918
|
*/
|
|
1919
1919
|
export type MoveChangeHandler = <T extends "start" | "move" | "end">(type: T, e: T extends "end" ? PointerEvent | undefined : PointerEvent, state: MoveState, forceRecalculateEdges: () => void,
|
|
1920
|
-
/** Calls moveEnd with apply: false */
|
|
1921
|
-
cancel:
|
|
1922
|
-
/** Saves result to resolve moveStart promise with then calls moveEnd with given apply. */
|
|
1920
|
+
/** Calls moveEnd with apply: false. This can technically be called from "end", it should still work. */
|
|
1921
|
+
cancel: (e: PointerEvent | KeyboardEvent | undefined, state: MoveState) => void,
|
|
1922
|
+
/** Saves result to resolve moveStart promise with then calls moveEnd with given apply. Not available during "end" event. It's designed for resolving from other external evente (e.g. key events). */
|
|
1923
1923
|
resolve: T extends "end" ? undefined : ({ apply, result }: {
|
|
1924
1924
|
apply: boolean;
|
|
1925
1925
|
result: any;
|
|
@@ -1977,6 +1977,10 @@ export interface IAction {
|
|
|
1977
1977
|
/** Error texts/hints to display when the action produces an error. */
|
|
1978
1978
|
errors?: string[];
|
|
1979
1979
|
};
|
|
1980
|
+
/**
|
|
1981
|
+
* Called when an action is cancelled. Call action specific onCancel hooks here.
|
|
1982
|
+
*/
|
|
1983
|
+
cancel(e: PointerEvent | KeyboardEvent | undefined, state: MoveState): void;
|
|
1980
1984
|
/**
|
|
1981
1985
|
* Called after visual edges are recalculated, once per edge. Action handlers can annotate edges with error info here ({@link Edge.error}).
|
|
1982
1986
|
*
|
|
@@ -2017,24 +2021,27 @@ export type ActionHandlerApplyResult = {
|
|
|
2017
2021
|
export interface ActionHandler {
|
|
2018
2022
|
eventHandler: (e: KeyboardEvent, state: MoveState, forceRecalculateEdges: () => void) => void;
|
|
2019
2023
|
/**
|
|
2020
|
-
* 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.
|
|
2024
|
+
* 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. See also {@link MoveChangeHandler} for the built in action handler.
|
|
2021
2025
|
*
|
|
2022
2026
|
* Can be used to save some context/info to later apply safely during onMoveApply.
|
|
2023
2027
|
*
|
|
2024
2028
|
* The call order is:
|
|
2025
2029
|
* - onMoveChange("start", ...)
|
|
2026
2030
|
* - onMoveChange("move", ...)
|
|
2031
|
+
* - onMoveChange("end", ...)
|
|
2027
2032
|
* - onMoveApply(...) (IF moveEnd was called with apply: true, otherwise this is skipped)
|
|
2028
|
-
* -
|
|
2033
|
+
* - onMoveEnded() // do cleanup here
|
|
2029
2034
|
*/
|
|
2030
2035
|
onMoveChange: (...args: Parameters<MoveChangeHandler>) => MoveChangeResult;
|
|
2031
2036
|
/**
|
|
2032
2037
|
* Called when drag will be applied. If moveEnd was called with apply false, it will not be called.
|
|
2033
2038
|
* Return false to not apply the regular drag end changes (i.e. return false to reset to the position before dragging).
|
|
2034
2039
|
*
|
|
2035
|
-
* Do not use for resetting handler state, use
|
|
2040
|
+
* Do not use for resetting handler state, use onMoveEnded for that.
|
|
2036
2041
|
*/
|
|
2037
2042
|
onMoveApply: (state: MoveState, forceRecalculateEdges: () => void) => ActionHandlerApplyResult;
|
|
2043
|
+
/** For doing cleanup */
|
|
2044
|
+
onMoveEnded: () => void;
|
|
2038
2045
|
/**
|
|
2039
2046
|
* Called after visual edges are recalculated. Action handlers can annotate edges with error info.
|
|
2040
2047
|
*/
|
package/package.json
CHANGED
|
@@ -134,6 +134,7 @@ export function useFrames(
|
|
|
134
134
|
moveDirStore.reset()
|
|
135
135
|
showMoving.value = false
|
|
136
136
|
forceRecalculateEdges()
|
|
137
|
+
handler.onMoveEnded()
|
|
137
138
|
}
|
|
138
139
|
|
|
139
140
|
function moveStart<T extends "edge" | "frame">(
|
|
@@ -231,13 +232,17 @@ export function useFrames(
|
|
|
231
232
|
)
|
|
232
233
|
}
|
|
233
234
|
if (!didChange) return
|
|
234
|
-
|
|
235
|
+
onMoveChange(e, "move", point)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function onMoveChange(e: PointerEvent | undefined, type: "move" | "end", point: Point | undefined) {
|
|
239
|
+
const res = handler.onMoveChange(type, e, state.value, forceRecalculateEdges, cancel, type === "end" ? undefined : resolve)
|
|
235
240
|
|
|
236
241
|
|
|
237
242
|
showMoving.value = res.showMoving ?? true
|
|
238
243
|
if (!res.updateEdges) return
|
|
239
244
|
|
|
240
|
-
if (isMoving.value === "edge") {
|
|
245
|
+
if (isMoving.value === "edge" && point) {
|
|
241
246
|
requestAnimationFrame(() => {
|
|
242
247
|
for (let i = 0; i < movingEdges.value.length; i++) {
|
|
243
248
|
const movingEdge = movingEdges.value[i]
|
|
@@ -256,6 +261,8 @@ export function useFrames(
|
|
|
256
261
|
movePoint.value = point
|
|
257
262
|
}
|
|
258
263
|
|
|
264
|
+
onMoveChange(e, "end", movePoint.value)
|
|
265
|
+
|
|
259
266
|
if (apply) {
|
|
260
267
|
const applyResult = handler.onMoveApply(state.value, forceRecalculateEdges)
|
|
261
268
|
moveResult = applyResult.result
|
|
@@ -266,10 +273,8 @@ export function useFrames(
|
|
|
266
273
|
}
|
|
267
274
|
}
|
|
268
275
|
|
|
269
|
-
handler.onMoveChange("end", e, state.value, forceRecalculateEdges, undefined, undefined)
|
|
270
|
-
|
|
271
276
|
// this can get called from elsewhere
|
|
272
|
-
// also takes care of cleanup
|
|
277
|
+
// also takes care of cleanup, resolving promise, and calling onMoveEnded
|
|
273
278
|
controller?.abort()
|
|
274
279
|
}
|
|
275
280
|
|
|
@@ -128,7 +128,7 @@ export class ActionHandler<
|
|
|
128
128
|
e: T extends "end" ? PointerEvent | undefined : PointerEvent,
|
|
129
129
|
state: MoveState,
|
|
130
130
|
forceRecalculateEdges: () => void,
|
|
131
|
-
cancel:
|
|
131
|
+
cancel: (e: PointerEvent | KeyboardEvent | undefined, state: MoveState) => void,
|
|
132
132
|
resolve: T extends "end" ? undefined : (opts: ActionHandlerApplyResult) => void
|
|
133
133
|
): MoveChangeResult {
|
|
134
134
|
if (type === "start") {
|
|
@@ -137,7 +137,7 @@ export class ActionHandler<
|
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
if (this.activeAction) {
|
|
140
|
-
const res = this.actions[this.activeAction]!.onMoveChange(type, e, state, forceRecalculateEdges, this.boundCancel as any, resolve
|
|
140
|
+
const res = this.actions[this.activeAction]!.onMoveChange(type, e, state, forceRecalculateEdges, this.boundCancel as any, resolve)
|
|
141
141
|
// in case it's a vue reactive array
|
|
142
142
|
this.shapes.splice(0, this.shapes.length, ...res.shapes)
|
|
143
143
|
this.setTextHints(type)
|
|
@@ -147,12 +147,17 @@ export class ActionHandler<
|
|
|
147
147
|
const res = this.defaultOnMoveChange(type, e, state, forceRecalculateEdges, this.boundCancel as any, resolve as any)
|
|
148
148
|
this.shapes.splice(0, this.shapes.length, ...res.shapes)
|
|
149
149
|
|
|
150
|
-
if (type === "end") {
|
|
151
|
-
this.activeAction = undefined
|
|
152
|
-
}
|
|
153
150
|
return res
|
|
154
151
|
}
|
|
155
152
|
|
|
153
|
+
onMoveEnded() {
|
|
154
|
+
if (this.activeAction) {
|
|
155
|
+
this.actions[this.activeAction]!.onMoveEnded()
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
this.activeAction = undefined
|
|
159
|
+
}
|
|
160
|
+
|
|
156
161
|
setTextHints(type: "start" | "move" | "end") {
|
|
157
162
|
// again in case it's a vue reactive object
|
|
158
163
|
this.textHints.actions = []
|
|
@@ -197,7 +202,7 @@ export class ActionHandler<
|
|
|
197
202
|
if (this.activeAction) {
|
|
198
203
|
const res = this.actions[this.activeAction]!.onMoveApply(state, forceRecalculateEdges)
|
|
199
204
|
this.hooks.onEnd?.({ cancelled: false, applied: res })
|
|
200
|
-
return { apply: res, result: undefined }
|
|
205
|
+
return { apply: !res, result: undefined }
|
|
201
206
|
}
|
|
202
207
|
this.hooks.onEnd?.({ cancelled: false, applied: false })
|
|
203
208
|
return { apply: true, result: undefined }
|
|
@@ -155,10 +155,6 @@ export class CloseAction implements IAction {
|
|
|
155
155
|
_e: PointerEvent | undefined,
|
|
156
156
|
state: MoveState
|
|
157
157
|
): ActionChangeResult {
|
|
158
|
-
if (type === "end") {
|
|
159
|
-
this.reset()
|
|
160
|
-
return { shapes: [] }
|
|
161
|
-
}
|
|
162
158
|
if (state.moveDistance <= this.minDragDistance) {
|
|
163
159
|
return { updateEdges: false, shapes: [] }
|
|
164
160
|
}
|
|
@@ -209,7 +205,10 @@ export class CloseAction implements IAction {
|
|
|
209
205
|
}
|
|
210
206
|
}
|
|
211
207
|
const decos = this._getDecos(state)
|
|
212
|
-
this.state.lastReturn = {
|
|
208
|
+
this.state.lastReturn = {
|
|
209
|
+
updateEdges: !isMovingFromWindowEdge,
|
|
210
|
+
shapes: type === "end" ? [] : decos.flatMap(_ => _.shapes)
|
|
211
|
+
}
|
|
213
212
|
return this.state.lastReturn
|
|
214
213
|
}
|
|
215
214
|
|
|
@@ -225,7 +224,10 @@ export class CloseAction implements IAction {
|
|
|
225
224
|
}
|
|
226
225
|
|
|
227
226
|
cancel(): void {
|
|
228
|
-
this.reset()
|
|
229
227
|
this.hooks.onCancel?.()
|
|
230
228
|
}
|
|
229
|
+
|
|
230
|
+
onMoveEnded() {
|
|
231
|
+
this.reset()
|
|
232
|
+
}
|
|
231
233
|
}
|
|
@@ -155,10 +155,6 @@ export class FrameDragAction implements IAction {
|
|
|
155
155
|
_e: PointerEvent | undefined,
|
|
156
156
|
state: MoveState
|
|
157
157
|
): ActionChangeResult {
|
|
158
|
-
if (type === "end") {
|
|
159
|
-
this.reset()
|
|
160
|
-
return { shapes: [] }
|
|
161
|
-
}
|
|
162
158
|
if (state.moveDistance <= this.minDragDistance) {
|
|
163
159
|
return { updateEdges: false, shapes: [], showMoving: false }
|
|
164
160
|
}
|
|
@@ -185,7 +181,7 @@ export class FrameDragAction implements IAction {
|
|
|
185
181
|
const decos = this.getDecos(matchedZone, state, this.state.lastReturn)
|
|
186
182
|
|
|
187
183
|
return {
|
|
188
|
-
shapes: decos.flatMap(_ => _.shapes),
|
|
184
|
+
shapes: type === "end" ? [] : decos.flatMap(_ => _.shapes),
|
|
189
185
|
updateEdges: false,
|
|
190
186
|
showMoving: false
|
|
191
187
|
}
|
|
@@ -208,6 +204,10 @@ export class FrameDragAction implements IAction {
|
|
|
208
204
|
return true
|
|
209
205
|
}
|
|
210
206
|
|
|
207
|
+
onMoveEnded() {
|
|
208
|
+
this.reset()
|
|
209
|
+
}
|
|
210
|
+
|
|
211
211
|
cancel(): void {
|
|
212
212
|
this.reset()
|
|
213
213
|
}
|
|
@@ -178,10 +178,6 @@ export class SplitAction implements IAction {
|
|
|
178
178
|
_e: PointerEvent | undefined,
|
|
179
179
|
state: MoveState
|
|
180
180
|
): ActionChangeResult {
|
|
181
|
-
if (type === "end") {
|
|
182
|
-
this.reset()
|
|
183
|
-
return { shapes: [] }
|
|
184
|
-
}
|
|
185
181
|
const { moveHoveredFrame, moveDistance } = state
|
|
186
182
|
if (moveDistance <= this.minDragDistance) {
|
|
187
183
|
return { updateEdges: false, shapes: [], showMoving: false }
|
|
@@ -207,11 +203,19 @@ export class SplitAction implements IAction {
|
|
|
207
203
|
},
|
|
208
204
|
attrs: { class: "deco-split-error bg-red-500/50" }
|
|
209
205
|
}
|
|
210
|
-
this.state.lastReturn = {
|
|
206
|
+
this.state.lastReturn = {
|
|
207
|
+
updateEdges: true,
|
|
208
|
+
shapes: type === "end" ? [] : [errorDeco],
|
|
209
|
+
showMoving: false
|
|
210
|
+
}
|
|
211
211
|
return this.state.lastReturn
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
|
-
this.state.lastReturn = {
|
|
214
|
+
this.state.lastReturn = {
|
|
215
|
+
updateEdges: false,
|
|
216
|
+
shapes: type === "end" ? [] : decos.flatMap(_ => _.shapes),
|
|
217
|
+
showMoving: false
|
|
218
|
+
}
|
|
215
219
|
return this.state.lastReturn
|
|
216
220
|
}
|
|
217
221
|
|
|
@@ -229,8 +233,11 @@ export class SplitAction implements IAction {
|
|
|
229
233
|
return true
|
|
230
234
|
}
|
|
231
235
|
|
|
232
|
-
|
|
236
|
+
onMoveEnded() {
|
|
233
237
|
this.reset()
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
cancel(): void {
|
|
234
241
|
this.hooks.onCancel?.()
|
|
235
242
|
}
|
|
236
243
|
}
|
|
@@ -522,9 +522,9 @@ export type MoveChangeHandler = <T extends "start" | "move" | "end">(
|
|
|
522
522
|
e: T extends "end" ? PointerEvent | undefined : PointerEvent,
|
|
523
523
|
state: MoveState,
|
|
524
524
|
forceRecalculateEdges: () => void,
|
|
525
|
-
/** Calls moveEnd with apply: false */
|
|
526
|
-
cancel:
|
|
527
|
-
/** Saves result to resolve moveStart promise with then calls moveEnd with given apply. */
|
|
525
|
+
/** Calls moveEnd with apply: false. This can technically be called from "end", it should still work. */
|
|
526
|
+
cancel: (e: PointerEvent | KeyboardEvent | undefined, state: MoveState) => void,
|
|
527
|
+
/** Saves result to resolve moveStart promise with then calls moveEnd with given apply. Not available during "end" event. It's designed for resolving from other external evente (e.g. key events). */
|
|
528
528
|
resolve: T extends "end" ? undefined : ({ apply, result }: { apply: boolean, result: any }) => void
|
|
529
529
|
) => ActionChangeResult
|
|
530
530
|
|
|
@@ -587,6 +587,11 @@ export interface IAction {
|
|
|
587
587
|
/** Error texts/hints to display when the action produces an error. */
|
|
588
588
|
errors?: string[]
|
|
589
589
|
}
|
|
590
|
+
/**
|
|
591
|
+
* Called when an action is cancelled. Call action specific onCancel hooks here.
|
|
592
|
+
*/
|
|
593
|
+
// note: internally this is done by the actionhandler wrapping the given cancel function for an event
|
|
594
|
+
cancel(e: PointerEvent | KeyboardEvent | undefined, state: MoveState): void
|
|
590
595
|
/**
|
|
591
596
|
* Called after visual edges are recalculated, once per edge. Action handlers can annotate edges with error info here ({@link Edge.error}).
|
|
592
597
|
*
|
|
@@ -624,27 +629,32 @@ export type ActionHandlerApplyResult = {
|
|
|
624
629
|
export interface ActionHandler {
|
|
625
630
|
eventHandler: (e: KeyboardEvent, state: MoveState, forceRecalculateEdges: () => void) => void
|
|
626
631
|
/**
|
|
627
|
-
* 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.
|
|
632
|
+
* 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. See also {@link MoveChangeHandler} for the built in action handler.
|
|
628
633
|
*
|
|
629
634
|
* Can be used to save some context/info to later apply safely during onMoveApply.
|
|
630
635
|
*
|
|
631
636
|
* The call order is:
|
|
632
637
|
* - onMoveChange("start", ...)
|
|
633
638
|
* - onMoveChange("move", ...)
|
|
639
|
+
* - onMoveChange("end", ...)
|
|
634
640
|
* - onMoveApply(...) (IF moveEnd was called with apply: true, otherwise this is skipped)
|
|
635
|
-
* -
|
|
641
|
+
* - onMoveEnded() // do cleanup here
|
|
636
642
|
*/
|
|
637
643
|
onMoveChange: (...args: Parameters<MoveChangeHandler>) => MoveChangeResult
|
|
638
644
|
/**
|
|
639
645
|
* Called when drag will be applied. If moveEnd was called with apply false, it will not be called.
|
|
640
646
|
* Return false to not apply the regular drag end changes (i.e. return false to reset to the position before dragging).
|
|
641
647
|
*
|
|
642
|
-
* Do not use for resetting handler state, use
|
|
648
|
+
* Do not use for resetting handler state, use onMoveEnded for that.
|
|
643
649
|
*/
|
|
644
650
|
onMoveApply: (
|
|
645
651
|
state: MoveState,
|
|
646
652
|
forceRecalculateEdges: () => void
|
|
647
653
|
) => ActionHandlerApplyResult
|
|
654
|
+
|
|
655
|
+
/** For doing cleanup */
|
|
656
|
+
onMoveEnded: () => void
|
|
657
|
+
|
|
648
658
|
/**
|
|
649
659
|
* Called after visual edges are recalculated. Action handlers can annotate edges with error info.
|
|
650
660
|
*/
|