import { getRenderedCell, RenderedCell, RenderedGrid, } from "./components/grid/renderGrid"; import { CellRef, cellRefEquals } from "./types"; export abstract class Selection { readonly gridId: string; readonly activeCellRef: CellRef; constructor(gridId: string, activeCellRef: CellRef) { this.gridId = gridId; this.activeCellRef = activeCellRef; } abstract extend(cellRef: CellRef): Selection; abstract getSelectedCells(grid: RenderedGrid): RenderedCell[][]; abstract startCellRef(): CellRef; abstract endCellRef(): CellRef; } export class ActiveCellSelection extends Selection { extend(cellRef: CellRef): Selection { if (cellRefEquals(cellRef, this.activeCellRef)) { return this; } return new RangeSelection(this.gridId, this.activeCellRef, [ this.activeCellRef, cellRef, ]); } getSelectedCells(grid: RenderedGrid): RenderedCell[][] { return [[getRenderedCell(grid, this.activeCellRef)!]]; } startCellRef(): CellRef { return this.activeCellRef; } endCellRef(): CellRef { return this.activeCellRef; } } export type CellRange = [CellRef, CellRef]; export class RangeSelection extends Selection { #range: CellRange; get range() { return this.#range; } constructor(gridId: string, activeCellRef: CellRef, range: CellRange) { super(gridId, activeCellRef); this.#range = range; } extend(cellRef: CellRef): Selection { if (cellRefEquals(cellRef, this.activeCellRef)) { return new ActiveCellSelection(this.gridId, cellRef); } return new RangeSelection(this.gridId, this.activeCellRef, [ this.#range[0], cellRef, ]); } getSelectedCells(grid: RenderedGrid): RenderedCell[][] { const startCell = getRenderedCell(grid, this.range[0]); const endCell = getRenderedCell(grid, this.range[1]); if (!startCell || !endCell) return []; const firstRowIndex = Math.min( startCell.renderedRowIndex, endCell.renderedRowIndex, ); const lastRowIndex = Math.max( startCell.renderedRowIndex, endCell.renderedRowIndex, ); const startRatio = startCell.startRatio.compare(endCell.startRatio) <= 0 ? startCell.startRatio : endCell.startRatio; const endRatio = startCell.endRatio.compare(endCell.endRatio) >= 0 ? startCell.endRatio : endCell.endRatio; return grid.renderedRows .slice(firstRowIndex, lastRowIndex + 1) .map((row) => { const firstCellIndex = row.renderedCells.findIndex( (cell) => cell.startRatio.compare(startRatio) >= 0, ); const lastCellIndex = row.renderedCells.findLastIndex( (cell) => cell.endRatio.compare(endRatio) <= 0, ); return row.renderedCells.slice(firstCellIndex, lastCellIndex + 1); }); } startCellRef(): CellRef { return this.range[0]; } endCellRef(): CellRef { return this.range[1]; } }