From a984c69e3cca4bcf822989bb78a8befe2397e487 Mon Sep 17 00:00:00 2001 From: Josh Kingsley Date: Sun, 26 Oct 2025 18:31:23 +0200 Subject: feat(web): draw selection --- web/src/components/grid/index.ts | 69 +++++++++++++++++++++++++++++++++------- 1 file changed, 57 insertions(+), 12 deletions(-) (limited to 'web/src/components/grid/index.ts') diff --git a/web/src/components/grid/index.ts b/web/src/components/grid/index.ts index 0acace4..fbb9c60 100644 --- a/web/src/components/grid/index.ts +++ b/web/src/components/grid/index.ts @@ -1,6 +1,7 @@ import h, { type CreateElement } from "../../html"; +import { CellRef } from "../../types"; import cellAtCoord from "./cellAtCoord"; -import drawGrid from "./drawGrid"; +import drawGrid, { getGridColors } from "./drawGrid"; import "./index.css"; class NotiveGridElement extends HTMLElement { @@ -26,18 +27,12 @@ class NotiveGridElement extends HTMLElement { throw new Error("ntv-grid requries gridId attribute"); } - this.canvasEl.addEventListener("mousedown", (event) => { - const clientRect = this.canvasEl.getBoundingClientRect(); - const x = event.x - clientRect.x; - const y = event.y - clientRect.y; - const cellRef = cellAtCoord(this.renderedGrid, x, y); - if (!cellRef) return; - window.notive.selectCell(this.#gridId, cellRef); - }); + window.addEventListener("ntv:selection-changed", () => this.draw()); - window.addEventListener("ntv:selection-changed", () => { - this.draw(); - }); + this.canvasEl.addEventListener( + "mousedown", + this.#canvasMouseDownCallback.bind(this), + ); this.append(this.canvasEl); this.draw(); @@ -55,13 +50,63 @@ class NotiveGridElement extends HTMLElement { this.canvasEl.setAttribute("width", grid.rect.width + "px"); this.canvasEl.setAttribute("height", grid.rect.height + "px"); + const colors = getGridColors(this); + drawGrid( ctx, + colors, grid, window.notive.selection, window.notive.pendingSelection, ); } + + #mouseEventCellRef( + this: NotiveGridElement, + event: MouseEvent, + ): CellRef | undefined { + const clientRect = this.canvasEl.getBoundingClientRect(); + const x = event.x - clientRect.x; + const y = event.y - clientRect.y; + return cellAtCoord(this.renderedGrid, x, y); + } + + #canvasMouseDownCallback(this: NotiveGridElement, event: MouseEvent) { + const cellRef = this.#mouseEventCellRef(event); + + if (!cellRef) return; + + window.notive.startSelecting(this.gridId, cellRef); + + this.#selectionAbortController = new AbortController(); + const { signal } = this.#selectionAbortController; + + window.addEventListener( + "mousemove", + this.#selectionMouseMoveCallback.bind(this), + { signal }, + ); + + window.addEventListener( + "mouseup", + this.#selectionMouseUpCallback.bind(this), + { signal }, + ); + } + + #selectionAbortController?: AbortController; + + #selectionMouseMoveCallback(this: NotiveGridElement, event: MouseEvent) { + const cellRef = this.#mouseEventCellRef(event); + if (!cellRef) return; + window.notive.extendSelection(cellRef); + } + + #selectionMouseUpCallback(this: NotiveGridElement, event: MouseEvent) { + this.#selectionAbortController?.abort(); + this.#selectionAbortController = undefined; + window.notive.finishSelecting(); + } } customElements.define("ntv-grid", NotiveGridElement); -- cgit v1.2.3