feat: Stop on workspace during constrained move (#9649)

This commit is contained in:
Michael Harvey
2026-03-27 09:41:39 -04:00
committed by GitHub
parent 6059d1f5fc
commit 1ad060819e
2 changed files with 31 additions and 23 deletions
@@ -573,18 +573,13 @@ export class BlockDragStrategy implements IDragStrategy {
const direction = this.getDirectionToNewLocation(
Coordinate.sum(this.startLoc!, delta),
);
const candidate = this.findTraversalCandidate(direction);
if (candidate) {
return candidate;
}
delta = new Coordinate(0, 0);
return this.findTraversalCandidate(direction);
}
// If we do not have a candidate yet, we fallback to the closest one nearby.
let radius = this.getSearchRadius();
const localConns = this.getLocalConnections(this.block);
let candidate = null;
let candidate: ConnectionCandidate | null = null;
for (const conn of localConns) {
const {connection: neighbour, radius: rad} = conn.closest(radius, delta);
@@ -775,30 +770,40 @@ export class BlockDragStrategy implements IDragStrategy {
* @returns A candidate connection and radius, or null if none was found.
*/
findTraversalCandidate(direction: Direction): ConnectionCandidate | null {
const currentPairIndex = this.allConnectionPairs.findIndex(
const pairs = this.allConnectionPairs;
if (direction === Direction.NONE || !pairs.length) {
return this.connectionCandidate;
}
const forwardTraversal =
direction === Direction.RIGHT || direction === Direction.DOWN;
const currentPairIndex = pairs.findIndex(
(pair) =>
this.connectionCandidate?.local === pair.local &&
this.connectionCandidate?.neighbour === pair.neighbour,
);
if (currentPairIndex !== -1) {
if (direction === Direction.UP || direction === Direction.LEFT) {
const nextPair =
this.allConnectionPairs[currentPairIndex - 1] ??
this.allConnectionPairs[this.allConnectionPairs.length - 1];
return {...nextPair, distance: 0};
} else if (
direction === Direction.DOWN ||
direction === Direction.RIGHT
) {
const nextPair =
this.allConnectionPairs[currentPairIndex + 1] ??
this.allConnectionPairs[0];
return {...nextPair, distance: 0};
if (forwardTraversal) {
if (currentPairIndex === -1) {
return this.pairToCandidate(pairs[0]);
} else if (currentPairIndex === pairs.length - 1) {
return null;
} else {
return this.pairToCandidate(pairs[currentPairIndex + 1]);
}
} else {
if (currentPairIndex === -1) {
return this.pairToCandidate(pairs[pairs.length - 1]);
} else if (currentPairIndex === 0) {
return null;
} else {
return this.pairToCandidate(pairs[currentPairIndex - 1]);
}
}
return null;
}
private pairToCandidate(pair: ConnectionPair): ConnectionCandidate {
return {...pair, distance: 0};
}
/**
* Returns the cardinal direction that the block being dragged would have to
* move in to reach the given location.
@@ -583,6 +583,7 @@ suite('Keyboard-driven movement', function () {
{id: 'controls_if', index: 6, ownIndex: 0}, // "Else" statement input.
{id: 'controls_if', index: 1, ownIndex: 0}, // Next.
{id: 'p5_draw', index: 0, ownIndex: 0}, // Statement input.
null, // Disconnected on workspace
];
/**
* Expected connection candidates when moving STATEMENT_SIMPLE after
@@ -653,6 +654,7 @@ suite('Keyboard-driven movement', function () {
{id: 'controls_if', index: 6, ownIndex: 0}, // "Else" statement input.
{id: 'controls_if', index: 1, ownIndex: 0}, // Next.
{id: 'p5_draw', index: 0, ownIndex: 0}, // Statement input.
null, // Disconnected on workspace
];
/**
* Expected connection candidates when moving STATEMENT_COMPLEX after
@@ -761,6 +763,7 @@ suite('Keyboard-driven movement', function () {
{id: 'join2', index: 1, ownIndex: 0}, // Join block ADD0 input.
{id: 'join2', index: 2, ownIndex: 0}, // Join block ADD1 input.
// Skip input of unattached join block.
null, // Disconnected on workspace
];
/**
* Expected connection candidates when moving BLOCK_SIMPLE, after