Skip to content

Commit f0aee70

Browse files
fix: add looping for finding the next/previous node during movement
1 parent dc5f6e7 commit f0aee70

File tree

1 file changed

+75
-8
lines changed

1 file changed

+75
-8
lines changed

src/keyboard_drag_strategy.ts

Lines changed: 75 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -150,15 +150,9 @@ export class KeyboardDragStrategy extends dragging.BlockDragStrategy {
150150
const dir = this.currentDragDirection;
151151
while (potential && !candidateConnection) {
152152
if (dir === Direction.Up || dir === Direction.Left) {
153-
potential = cursor.getPreviousNode(potential, (node) => {
154-
// @ts-expect-error isConnectionType is private.
155-
return node && ASTNode.isConnectionType(node.getType());
156-
});
153+
potential = this.getPreviousNode(potential, cursor);
157154
} else if (dir === Direction.Down || dir === Direction.Right) {
158-
potential = cursor.getNextNode(potential, (node) => {
159-
// @ts-expect-error isConnectionType is private.
160-
return node && ASTNode.isConnectionType(node.getType());
161-
});
155+
potential = this.getNextNode(potential, cursor);
162156
}
163157

164158
localConns.forEach((conn: RenderedConnection) => {
@@ -289,4 +283,77 @@ export class KeyboardDragStrategy extends dragging.BlockDragStrategy {
289283
override shouldHealStack(e: PointerEvent | undefined): boolean {
290284
return true;
291285
}
286+
287+
/**
288+
* Get the previous node in the tree, with loopback to the last
289+
* stack on the workspace if needed.
290+
*
291+
* @param start Where to start traversal.
292+
* @param cursor The workspace's cursor
293+
* @returns The previous node, or null if there were no valid nodes
294+
* on the workspace.
295+
*/
296+
private getPreviousNode(start: ASTNode, cursor: LineCursor) {
297+
let potential: ASTNode | null = start;
298+
potential = cursor.getPreviousNode(potential, (node) => {
299+
// @ts-expect-error isConnectionType is private.
300+
return node && ASTNode.isConnectionType(node.getType());
301+
});
302+
if (!potential) {
303+
// Loop back to last block if it exists.
304+
// @ts-expect-error workspace is private
305+
const topBlocks = this.workspace.getTopBlocks(true);
306+
if (!topBlocks.length) return null;
307+
308+
// Find the last stack.
309+
const lastTopBlockNode = ASTNode.createStackNode(
310+
topBlocks[topBlocks.length - 1],
311+
);
312+
let prevNode = lastTopBlockNode;
313+
let nextNode: ASTNode | null = lastTopBlockNode;
314+
// Iterate until you fall off the end of the stack.
315+
while (nextNode) {
316+
prevNode = nextNode;
317+
nextNode = cursor.getNextNode(prevNode, (node) => {
318+
return !!node;
319+
});
320+
}
321+
322+
// Resume searching.
323+
potential = cursor.getPreviousNode(prevNode, (node) => {
324+
// @ts-expect-error isConnectionType is private.
325+
return node && ASTNode.isConnectionType(node.getType());
326+
});
327+
}
328+
return potential;
329+
}
330+
331+
/**
332+
* Get the next node in the tree, with loopback to the first
333+
* stack on the workspace if needed.
334+
*
335+
* @param start Where to start traversal.
336+
* @param cursor The workspace's cursor
337+
* @returns The next node, or null if there were no valid nodes
338+
* on the workspace.
339+
*/
340+
private getNextNode(start: ASTNode, cursor: LineCursor) {
341+
let potential: ASTNode | null = start;
342+
potential = cursor.getNextNode(potential, (node) => {
343+
// @ts-expect-error isConnectionType is private.
344+
return node && ASTNode.isConnectionType(node.getType());
345+
});
346+
if (!potential) {
347+
// Loop back to first block if it exists.
348+
// @ts-expect-error workspace is private
349+
const topBlocks = this.workspace.getTopBlocks(true);
350+
if (!topBlocks.length) return null;
351+
const initial = ASTNode.createTopNode(topBlocks[0]);
352+
potential = cursor.getNextNode(initial, (node) => {
353+
// @ts-expect-error isConnectionType is private.
354+
return node && ASTNode.isConnectionType(node.getType());
355+
});
356+
}
357+
return potential;
358+
}
292359
}

0 commit comments

Comments
 (0)