diff options
Diffstat (limited to 'web/src/components/grid/index.ts')
| -rw-r--r-- | web/src/components/grid/index.ts | 87 |
1 files changed, 45 insertions, 42 deletions
diff --git a/web/src/components/grid/index.ts b/web/src/components/grid/index.ts index 6c7f735..78bb14e 100644 --- a/web/src/components/grid/index.ts +++ b/web/src/components/grid/index.ts @@ -1,12 +1,12 @@ import NotiveElement, { customElement, eventHandler } from "../../element"; import h from "../../html"; -import { ActiveCellSelection, Selection } from "../../selection"; import { CellRef } from "../../types"; import cellAtCoord from "./cellAtCoord"; import drawGrid, { GridStyles } from "./drawGrid"; import drawSelection, { SelectionStyles } from "./drawSelection"; import "./index.css"; import { getRenderedCell, RenderedGrid } from "./renderGrid"; +import { extendSelection, GridSelection } from "./selection"; @customElement("ntv-grid") export class NotiveGridElement extends NotiveElement { @@ -14,25 +14,26 @@ export class NotiveGridElement extends NotiveElement { grid?: RenderedGrid; - #selection?: Selection; + #selection?: GridSelection; get selection() { return this.#selection; } - set selection(selection: Selection | undefined) { + set selection(selection: GridSelection | undefined) { this.#selection = selection; this.drawSelection(); } @eventHandler("ntv:grid:selectionchange") - ongridselectionchange?: (event: GridSelectionEvent) => any; + ongridselectionchange?: (event: GridSelectionChangeEvent) => any; @eventHandler("ntv:grid:cellchange") oncellchange?: (event: GridCellChangeEvent) => any; canvas: HTMLCanvasElement = h.canvas({ onmousedown: (event) => { + if (event.button !== 0) return; if (!this.grid) return; const cellRef = this.#mouseEventCellRef(event); if (!cellRef) return; @@ -114,7 +115,7 @@ export class NotiveGridElement extends NotiveElement { }; } - #pendingSelection?: Selection; + #pendingSelection?: GridSelection; #selectionAbortController?: AbortController; startSelecting(cellRef: CellRef) { @@ -123,12 +124,6 @@ export class NotiveGridElement extends NotiveElement { this.#internals.states.add("selecting"); this.#selectionAbortController = new AbortController(); - - this.#selectionAbortController.signal.addEventListener("abort", () => { - this.#internals.states.delete("selecting"); - this.#selectionAbortController = undefined; - }); - const { signal } = this.#selectionAbortController; window.addEventListener( @@ -136,33 +131,43 @@ export class NotiveGridElement extends NotiveElement { (event) => { const cellRef = this.#mouseEventCellRef(event); if (!cellRef) return; - this.#pendingSelection = this.#pendingSelection?.extend(cellRef); + this.#pendingSelection = extendSelection( + this.#pendingSelection, + cellRef, + ); this.drawSelection(); }, { signal }, ); - window.addEventListener( - "mouseup", - () => { - this.#selectionAbortController?.abort(); - - if (!this.#pendingSelection) return; - - this.dispatchEvent( - new GridSelectionEvent( - "ntv:grid:selectionchange", - this.#pendingSelection, - ), - ); + window.addEventListener("mouseup", () => this.#finishSelecting(), { + signal, + }); - this.#pendingSelection = undefined; - this.drawSelection(); + window.addEventListener( + "keydown", + (event) => { + event.preventDefault(); + if (event.key === "Escape") { + this.#pendingSelection = undefined; + this.#finishSelecting(); + } }, { signal }, ); - this.#pendingSelection = new ActiveCellSelection(this.grid.id, cellRef); + this.#pendingSelection = extendSelection(undefined, cellRef); + this.drawSelection(); + } + + #finishSelecting() { + this.#selectionAbortController?.abort(); + this.#selectionAbortController = undefined; + this.#internals.states.delete("selecting"); + if (this.#pendingSelection) { + this.dispatchEvent(new GridSelectionChangeEvent(this.#pendingSelection)); + } + this.#pendingSelection = undefined; this.drawSelection(); } @@ -235,30 +240,28 @@ export class NotiveGridElement extends NotiveElement { export default NotiveGridElement.makeFactory(); -export class GridSelectionEvent extends Event { - selection: Selection; +export class GridSelectionChangeEvent extends Event { + static readonly TYPE = "ntv:grid:selectionchange"; - constructor(type: string, selection: Selection) { - super(type); - this.selection = selection; + constructor(public selection: GridSelection) { + super(GridSelectionChangeEvent.TYPE); } } export class GridCellChangeEvent extends Event { - cellRef: CellRef; - value?: string; - - constructor(cellRef: CellRef, value: string | undefined) { - super("ntv:grid:cellchange"); + static readonly TYPE = "ntv:grid:cellchange"; - this.cellRef = cellRef; - this.value = value; + constructor( + public cellRef: CellRef, + public value: string | undefined, + ) { + super(GridCellChangeEvent.TYPE); } } declare global { interface HTMLElementEventMap { - "ntv:grid:selectionchange": GridSelectionEvent; - "ntv:grid:cellchange": GridCellChangeEvent; + [GridSelectionChangeEvent.TYPE]: GridSelectionChangeEvent; + [GridCellChangeEvent.TYPE]: GridCellChangeEvent; } } |
