From efc8886bd8d74bc5187edf87a4ddcf38133a8cad Mon Sep 17 00:00:00 2001 From: John Coffey Date: Thu, 10 Sep 2026 09:59:14 -0700 Subject: [PATCH] Take gridstack to 13, and handle the grid it may not return gridstack 13 changed `GridStack.init` to return `GridStack | null` where 11 always handed one back. The dashboard held the result in a `GridStack | undefined` and called `.on('change')` on it straight after, so svelte-check stopped on two errors: null is not undefined, and the value is possibly neither. Coalesced to undefined so the declared type stays as it was, then guarded before the listener is attached. `gridEl` is already checked at the top of the function, so a null here should not occur -- but the type allows it, and a dashboard that quietly stops persisting drags beats one that throws inside an effect. Nothing else in the repository touches gridstack: one import of `GridStack` and its stylesheet, in this file. Worth noting `vite build` passes either way. Only `npm run check` sees this, and no CI job runs it -- the two majors would have gone in looking clean. --- web/src/routes/dashboards/[id]/+page.svelte | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/web/src/routes/dashboards/[id]/+page.svelte b/web/src/routes/dashboards/[id]/+page.svelte index 5e17c3b..968ae04 100644 --- a/web/src/routes/dashboards/[id]/+page.svelte +++ b/web/src/routes/dashboards/[id]/+page.svelte @@ -167,7 +167,12 @@ function setupGrid() { if (!gridEl || !dashboard?.panels) return; grid?.destroy(false); - grid = GridStack.init({ float: true, cellHeight: 60, column: 12 }, gridEl); + // gridstack 13 returns null when it cannot bind to the element, where + // 11 always handed back a grid. `gridEl` is guarded above so this + // should not happen -- but the type says it can, and a missed drag is + // better than a thrown error inside an effect. + grid = GridStack.init({ float: true, cellHeight: 60, column: 12 }, gridEl) ?? undefined; + if (!grid) return; grid.on('change', (_event: Event, items: GridStackNode[]) => { for (const item of items) { const panel = dashboard?.panels?.find((p) => p.id === item.id);