import { ACTIONS_COLUMN_ID, SELECTION_COLUMN_ID } from '../../constants' import type { GridRowId } from '../../types' export const positionFactory = ({ flatIds, rowHeight, headerHeight, columnIds, columnsWidths, }: { flatIds: GridRowId[] rowHeight: number headerHeight: number columnIds: string[] columnsWidths: number[] }) => { const columnPositions = new Map< string, { left: number; right: number; width: number } >() let minX = 0 let maxX = 0 let columnLeft = 0 for (let i = 0; i < columnIds.length; i++) { const columnId = columnIds[i] const width = columnsWidths[i] columnPositions.set(columnId, { left: columnLeft, right: columnLeft + width, width, }) columnLeft += width if (columnId === SELECTION_COLUMN_ID) { minX = columnLeft } if (columnId !== ACTIONS_COLUMN_ID) { maxX = columnLeft } } const getColumnFromX = (x: number) => { let columnIdFound: string | null = null for (const [columnId, position] of columnPositions.entries()) { if (x >= position.left && x <= position.right) { columnIdFound = columnId break } } if (x < minX) { return { columnId: columnIds[0] === SELECTION_COLUMN_ID ? columnIds[1] : columnIds[0], outOfBounds: 'min', } } if (x > maxX) { return { columnId: columnIds.at(-1) === ACTIONS_COLUMN_ID ? columnIds.at(-2) : columnIds.at(-1), outOfBounds: 'max', } } return { columnId: columnIdFound, outOfBounds: null, } } const getRowFromY = (y: number) => { const yWithoutHeader = y - headerHeight const rowIndex = Math.floor(yWithoutHeader / rowHeight) if (rowIndex < 0) { return { rowId: flatIds[0], outOfBounds: 'min' } } if (rowIndex > flatIds.length - 1) { return { rowId: flatIds[flatIds.length - 1], outOfBounds: 'max', } } return { rowId: flatIds[rowIndex], outOfBounds: null } } return { getColumnFromX, getRowFromY, } }