Stage 17 round 6 (#3): drag-reorder rack tiles with a visual gap
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 8s
CI / integration (pull_request) Successful in 14s
CI / ui (pull_request) Successful in 30s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m7s

Dragging a rack tile and dropping it back on the rack reorders it: the dragged tile is
lifted out (the drag ghost stands in) and the tiles at/after the pointer's drop slot slide
right to open a gap there, so the drop position is visible. On drop the rack and its stable
ids are permuted (reorderIndices, unit-tested). Reorder applies only with no pending tiles,
so it stays a clean permutation; dropping on a board cell still places as before. Server
persistence of the order follows (#4).
This commit is contained in:
Ilia Denisov
2026-06-07 12:21:09 +02:00
parent 35666e1705
commit 2b0b1c0035
4 changed files with 106 additions and 7 deletions
+13
View File
@@ -106,6 +106,19 @@ export function reset(p: Placement): Placement {
return { ...p, pending: [] };
}
/**
* reorderIndices returns the permutation of [0, n) that lifts the element at `from` and
* drops it at slot `toSlot` among the remaining elements (clamped to a valid slot). It is
* applied in parallel to the rack letters and their stable ids when a tile is dragged to a
* new rack position.
*/
export function reorderIndices(n: number, from: number, toSlot: number): number[] {
const order: number[] = [];
for (let i = 0; i < n; i++) if (i !== from) order.push(i);
order.splice(Math.max(0, Math.min(toSlot, order.length)), 0, from);
return order;
}
/**
* direction infers the play orientation from the pending tiles: H if they share a row,
* V if they share a column, null if a single tile (ambiguous) or non-linear (invalid).