summaryrefslogtreecommitdiffhomepage
path: root/src/features/workspaces/logic/tile-layout.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/features/workspaces/logic/tile-layout.ts')
-rw-r--r--src/features/workspaces/logic/tile-layout.ts19
1 files changed, 14 insertions, 5 deletions
diff --git a/src/features/workspaces/logic/tile-layout.ts b/src/features/workspaces/logic/tile-layout.ts
index 4b5c89c..c4720d3 100644
--- a/src/features/workspaces/logic/tile-layout.ts
+++ b/src/features/workspaces/logic/tile-layout.ts
@@ -413,7 +413,9 @@ function firstFitFrom(
* one; the displaced re-anchor at the next fitting slot forward (spans ride
* along; a span that can't fit the fixed cross-axis anywhere forward wraps to
* the first fitting slot — it must land somewhere). Pure: placements + drop
- * in, a NEW placements array out (stream order).
+ * in, a NEW placements array out — in the INPUT array order (only coordinates
+ * change). A keyed `{#each}` over the result therefore never moves DOM nodes;
+ * moving a captured element drops its pointer capture — the "stuck tile" bug.
*/
export function displacePlace(
placements: readonly Placement[],
@@ -447,9 +449,12 @@ export function displacePlace(
occupy(occupied, slot.col, slot.row, colSpan, rowSpan);
placed.push({ ...placement, col: slot.col, row: slot.row });
}
- return placed.sort(
- (a, b) => fillOrderKey(a.col, a.row, geometry) - fillOrderKey(b.col, b.row, geometry),
- );
+ // Return in the INPUT render order (coordinates change only): the live drag
+ // preview feeds a keyed `{#each}`, and a reordered array moves the DOM nodes
+ // — a moved captured element silently loses pointer capture (the stuck-tile
+ // bug). The commit path re-sorts to stream order itself (`placeAtCell`).
+ const byId = new Map(placed.map((placement) => [placement.id, placement]));
+ return placements.map((placement) => byId.get(placement.id) ?? placement);
}
/**
@@ -468,7 +473,11 @@ export function placeAtCell(
// An unknown dragged id changes nothing (order-sorted copy — the op's
// canonical no-op shape, like `moveTile` before it).
if (!tiles.some((tile) => tile.id === id)) return sortTiles(tiles);
- const displaced = displacePlace(pack(tiles, geometry), id, cell, geometry);
+ // displacePlace preserves the input RENDER order for the live preview; the
+ // commit pins + renumbers in STREAM order, so re-sort before pinning.
+ const displaced = displacePlace(pack(tiles, geometry), id, cell, geometry)
+ .slice()
+ .sort((a, b) => fillOrderKey(a.col, a.row, geometry) - fillOrderKey(b.col, b.row, geometry));
const result: TileLayoutEntry[] = [];
for (const placement of displaced) {
const entry = tiles.find((tile) => tile.id === placement.id);