import { produce } from "immer"; import renderGrid, { getRenderedCell } from "./components/grid/renderGrid"; import { getSelectionRange, GridSelection } from "./components/grid/selection"; import Ratio from "./math/Ratio"; import { Cell, Grid, renderedRowIndexToRef } from "./types"; export function getSelectedSubdivisionsCount( grid: Grid, selection: GridSelection, ): number | undefined { const renderedGrid = renderGrid(grid); const [startCellRef, endCellRef] = getSelectionRange(selection); const startCell = getRenderedCell(renderedGrid, startCellRef); const endCell = getRenderedCell(renderedGrid, endCellRef); if (!startCell || !endCell) throw new Error("Invalid cell refs"); const startRenderedRowIndex = Math.min( startCell.renderedRowIndex, endCell.renderedRowIndex, ); const endRenderedRowIndex = Math.max( startCell.renderedRowIndex, endCell.renderedRowIndex, ); const startRatio = Ratio.min(startCell.startRatio, endCell.startRatio); const endRatio = Ratio.max(startCell.endRatio, endCell.endRatio); return Math.min( ...renderedGrid.renderedRows .slice(startRenderedRowIndex, endRenderedRowIndex + 1) .map((row) => { const startCellIndex = row.renderedCells.findIndex((cell) => cell.startRatio.equals(startRatio), ); const endCellIndex = row.renderedCells.findLastIndex((cell) => cell.endRatio.equals(endRatio), ); return endCellIndex - startCellIndex + 1; }), ); } export function changeSelectedSubdivisions( grid: Grid, selection: GridSelection, subdivisions: number, ): Grid { const renderedGrid = renderGrid(grid); const [startCellRef, endCellRef] = getSelectionRange(selection); const startCell = getRenderedCell(renderedGrid, startCellRef); const endCell = getRenderedCell(renderedGrid, endCellRef); if (!startCell || !endCell) throw new Error("Invalid cell refs"); const startRenderedRowIndex = Math.min( startCell.renderedRowIndex, endCell.renderedRowIndex, ); const endRenderedRowIndex = Math.max( startCell.renderedRowIndex, endCell.renderedRowIndex, ); const startRatio = Ratio.min(startCell.startRatio, endCell.startRatio); const endRatio = Ratio.max(startCell.endRatio, endCell.endRatio); const selectedWidthRatio = endRatio.subtract(startRatio); const widthRatio = selectedWidthRatio.divideRatio( Ratio.fromInteger(subdivisions), ); return produce(grid, (draft) => { for ( let renderedRowIndex = startRenderedRowIndex; renderedRowIndex <= endRenderedRowIndex; renderedRowIndex++ ) { const renderedRow = renderedGrid.renderedRows[renderedRowIndex]; const startCellIndex = renderedRow.renderedCells.findIndex((cell) => cell.startRatio.equals(startRatio), ); const endCellIndex = renderedRow.renderedCells.findLastIndex((cell) => cell.endRatio.equals(endRatio), ); const { partIndex, rowIndex } = renderedRowIndexToRef( grid, renderedRowIndex, ); const row = draft.parts[partIndex].rows[rowIndex]; const previousCells = row.cells.slice(0, startCellIndex); const nextCells = row.cells.slice(endCellIndex + 1); const newCells: Cell[] = Array.from({ length: subdivisions }, () => ({ widthRatio, })); row.cells = [...previousCells, ...newCells, ...nextCells]; } }); }