in frontend/libs/canvasSpreadsheet/src/lib/hooks/useExtendSelectionNextAvailable.ts [9:190]
export function useExtendSelectionNextAvailable() {
const {
gridSizes,
selectionEdges,
getCell,
tableStructure,
setSelectionEdges,
} = useContext(GridStateContext);
const createSingleSelectionFromRangeSelection = useCallback(
(
selection: Edges,
direction: HorizontalDirection | VerticalDirection
): Edges => {
const { startRow, endRow, startCol, endCol } = selection;
let cell;
switch (direction) {
case 'up':
return {
startRow: Math.min(startRow, endRow),
endRow: Math.min(startRow, endRow),
startCol: startCol,
endCol: startCol,
};
case 'down':
return {
startRow: endRow,
startCol: endCol,
endRow: endRow,
endCol: endCol,
};
case 'left':
cell = getCell(endCol, startRow);
return {
startCol: cell?.startCol || endCol,
endCol: cell?.startCol || endCol,
startRow: startRow,
endRow: startRow,
};
case 'right':
return {
startCol: Math.max(startCol, endCol),
endCol: Math.max(startCol, endCol),
startRow: startRow,
endRow: startRow,
};
}
},
[getCell]
);
const checkIsNavigateInsideTable = useCallback(
(
selection: Edges,
direction: HorizontalDirection | VerticalDirection
): Edges | null => {
for (const table of tableStructure) {
const { startRow, endRow, startCol, endCol } = table;
let col = undefined;
let row = undefined;
const isInsideTable =
selection.startRow >= startRow &&
selection.startRow <= endRow &&
selection.startCol >= startCol &&
selection.startCol <= endCol;
const cell = getCell(selection.startCol, selection.startRow);
const isTableHeader = cell?.isTableHeader;
const isNotOnTableEdge =
(direction === 'right' && selection.startCol < endCol) ||
(direction === 'left' && selection.startCol > startCol) ||
(direction === 'up' && selection.startRow > startRow) ||
(direction === 'down' && selection.startRow < endRow);
if (isInsideTable && isNotOnTableEdge && !isTableHeader) {
if (direction === 'right') {
col = endCol;
row = selection.startRow;
}
if (direction === 'left') {
col = startCol;
row = selection.startRow;
}
if (direction === 'up') {
col = selection.startCol;
row = startRow;
}
if (direction === 'down') {
col = selection.startCol;
row = Math.min(gridSizes.edges.row, endRow) - 1;
}
if (col !== undefined && row !== undefined) {
return {
startCol: col,
endCol: col,
startRow: row,
endRow: row,
};
}
}
}
return null;
},
[getCell, gridSizes, tableStructure]
);
const extendSelectionNextAvailable = useCallback(
(direction: HorizontalDirection | VerticalDirection) => {
if (!selectionEdges) return;
const singleSelection = createSingleSelectionFromRangeSelection(
selectionEdges,
direction
);
if (!singleSelection) return null;
const updatedSelection = checkIsNavigateInsideTable(
singleSelection,
direction
);
if (updatedSelection) {
setSelectionEdges(
convertSingleSelectionToRange(
selectionEdges,
updatedSelection,
direction
)
);
return;
}
const nextTable = findNextTableToNavigate(
tableStructure,
singleSelection,
direction
);
if (!nextTable) {
const { edges } = gridSizes;
setSelectionEdges(
extendSelectionToSheet(
selectionEdges,
direction,
edges.row,
edges.col
)
);
return;
}
return setSelectionEdges(
extendSelectionToTable(selectionEdges, nextTable, direction)
);
},
[
checkIsNavigateInsideTable,
createSingleSelectionFromRangeSelection,
gridSizes,
selectionEdges,
setSelectionEdges,
tableStructure,
]
);
return {
extendSelectionNextAvailable,
};
}