Snap-to-grid for moving/resizing canvas objects, plus a per-sheet grid size

Sheet.gridSize (4-200px, default 24, configurable in Settings -> Blatt)
now doubles as both the visible dot-grid's spacing and the snap
increment while dragging to move any canvas object, or free/viewport-
resizing a chart/text/button/fixed-viewport table. An "Automatisch"
table's resize is left unsnapped on top of this -- it already
discretizes to row/col boundaries by construction.

Also fixes the visible grid not actually lining up with real snap
positions once zoomed: the dot pattern's background-size now scales
with zoom like the objects themselves already did, instead of staying a
fixed screen-pixel size regardless of zoom level.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
wkh
2026-09-09 23:33:39 +02:00
co-authored by Claude Sonnet 5
parent 5f75b9c298
commit d0500fcaf5
8 changed files with 101 additions and 14 deletions
+7 -1
View File
@@ -24,7 +24,7 @@ import type {
TableView,
TextObject,
} from '../store/types';
import { defaultTableView } from '../store/types';
import { defaultTableView, MIN_GRID_SIZE, MAX_GRID_SIZE } from '../store/types';
import {
DEFAULT_LOCALE,
isCellNumFmt,
@@ -144,6 +144,11 @@ function zoomOrUndef(x: unknown): number | undefined {
? Math.min(2, Math.max(0.4, Math.round(x * 20) / 20))
: undefined;
}
function gridSizeOrUndef(x: unknown): number | undefined {
return typeof x === 'number' && Number.isFinite(x)
? Math.round(Math.min(MAX_GRID_SIZE, Math.max(MIN_GRID_SIZE, x)))
: undefined;
}
function clampNum(x: unknown, lo: number, hi: number, fallback: number): number {
return typeof x === 'number' && Number.isFinite(x)
? Math.min(hi, Math.max(lo, Math.round(x)))
@@ -433,6 +438,7 @@ export function validateDocument(x: unknown): DocumentState {
background: colorOrUndef(s.background),
foreground: colorOrUndef(s.foreground),
showGrid: boolOrUndef(s.showGrid),
gridSize: gridSizeOrUndef(s.gridSize),
zoom: zoomOrUndef(s.zoom),
})),
activeSheetId: doc.activeSheetId,