diff options
| author | Adam Malczewski <[email protected]> | 2026-09-07 17:40:29 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-09-07 17:40:29 +0900 |
| commit | 46b5f9d30f149c3e80f483c91f563c0a6fc75b25 (patch) | |
| tree | d6554c2634b624ead9f87881ff506506f88a7cbe /src/features/workspaces/ui/HomeTileGrid.svelte | |
| parent | 828d4e4fb822ec2925c8a625bc5bf326c3425964 (diff) | |
| download | dispatch-web-46b5f9d30f149c3e80f483c91f563c0a6fc75b25.tar.gz dispatch-web-46b5f9d30f149c3e80f483c91f563c0a6fc75b25.zip | |
feat(workspaces): bound the drag append area — 3 columns past the content edge
Dragging a tile far right grew the wide canvas endlessly (the target cell
resolved from the pointer with no upper bound), making precise placement
impossible. Add a pure `dragAppendLimit(placements, geometry, extra = 3)`:
the drag target may aim at most 3 columns (wide) / rows (tall) past the
current span-aware content edge. The bound is measured on the COMMITTED
layout — never the live preview — so it can't ratchet mid-drag; it steps
forward only when a drop commits new content. cellAt applies it on the
growth axis (wide: col, tall: row); the fixed cross-axis clamps are
unchanged. Exported via the unit index.
Verification: svelte-check 0 errors/0 warnings; vitest 1693/1693 (4 new
dragAppendLimit tests); biome clean on touched files; build ok.
Diffstat (limited to 'src/features/workspaces/ui/HomeTileGrid.svelte')
| -rw-r--r-- | src/features/workspaces/ui/HomeTileGrid.svelte | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/src/features/workspaces/ui/HomeTileGrid.svelte b/src/features/workspaces/ui/HomeTileGrid.svelte index 1ec31e5..adcdf08 100644 --- a/src/features/workspaces/ui/HomeTileGrid.svelte +++ b/src/features/workspaces/ui/HomeTileGrid.svelte @@ -6,6 +6,7 @@ import { nextDragPhase, type DragEvent, type DragPhase } from "../logic/drag-controller"; import { displacePlace, + dragAppendLimit, type Cell, type GridGeometry, type Placement, @@ -203,6 +204,14 @@ const pitchX = $derived(geometry.unit.width + geometry.unit.gap); const pitchY = $derived(geometry.unit.height + geometry.unit.gap); + /** + * The drag target's clamp on the growth axis — at most 3 columns (wide) / + * rows (tall) past the current content edge. Measured on the COMMITTED + * placements (the drag preview never ratchets the limit mid-drag), so the + * canvas can't endlessly grow when dragging far right / down. + */ + const appendLimit = $derived(dragAppendLimit(placements, geometry)); + function cellAt(clientX: number, clientY: number): Cell | null { const el = gridEl; if (!el) return null; @@ -213,8 +222,8 @@ const col = Math.max(1, Math.floor((clientX - rect.left) / cellW) + 1); const row = Math.max(1, Math.floor((clientY - rect.top) / pitchY) + 1); return { - col: wide ? col : Math.min(col, geometry.flowCols), - row: wide ? Math.min(row, geometry.flowRows) : row, + col: wide ? Math.min(col, appendLimit) : Math.min(col, geometry.flowCols), + row: wide ? Math.min(row, geometry.flowRows) : Math.min(row, appendLimit), }; } |
