import Ratio from "./math/Ratio"; export interface Cell { value?: string; widthRatio: Ratio; } export interface Row { cells: Cell[]; } export interface Part { title?: string; rows: Row[]; } export interface Grid { id: string; baseCellSize: number; baseCellWidthRatio: Ratio; parts: Part[]; } export interface Doc { grids: Grid[]; } export interface RowRef { partIndex: number; rowIndex: number; } export interface CellRef { partIndex: number; rowIndex: number; cellIndex: number; } export function cellRefEquals(a: CellRef, b: CellRef): boolean { return ( a.partIndex === b.partIndex && a.rowIndex === b.rowIndex && a.cellIndex === b.cellIndex ); } export function mapRowsInRange( doc: Doc, gridId: string, startRef: CellRef, endRef: CellRef, mapFn: (row: Row, ref: RowRef) => Row, ): Doc { const firstPartIndex = Math.min(startRef.partIndex, endRef.partIndex); const lastPartIndex = Math.max(startRef.partIndex, endRef.partIndex); const firstRowIndex = Math.min(startRef.rowIndex, endRef.rowIndex); const lastRowIndex = Math.max(startRef.rowIndex, endRef.rowIndex); return { ...doc, grids: doc.grids.map((grid) => { if (grid.id !== gridId) return grid; return { ...grid, parts: grid.parts.map((part, partIndex) => { if (partIndex < firstPartIndex || partIndex > lastPartIndex) { return part; } return { ...part, rows: part.rows.map((row, rowIndex) => { if (rowIndex < firstRowIndex || rowIndex > lastRowIndex) { return row; } return mapFn(row, { partIndex, rowIndex }); }), }; }), }; }), }; }