import { Num, Optional } from '@ephox/katamari';
export interface WrapArrNavigationOutcome {
readonly row: number;
readonly column: number;
}
export type ArrNavigationFunc = (values: A[], index: number, numRows: number, numCols: number) => Optional;
const withGrid = (values: A[], index: number, numCols: number, f: (oldRow: number, oldColumn: number) => Optional): Optional => {
const oldRow = Math.floor(index / numCols);
const oldColumn = index % numCols;
return f(oldRow, oldColumn).bind((address) => {
const newIndex = address.row * numCols + address.column;
return newIndex >= 0 && newIndex < values.length ? Optional.some(values[newIndex]) : Optional.none();
});
};
const cycleHorizontal = (values: A[], index: number, numRows: number, numCols: number, delta: number) => withGrid(values, index, numCols, (oldRow, oldColumn) => {
const onLastRow = oldRow === numRows - 1;
const colsInRow = onLastRow ? values.length - (oldRow * numCols) : numCols;
const newColumn = Num.cycleBy(oldColumn, delta, 0, colsInRow - 1);
return Optional.some({
row: oldRow,
column: newColumn
});
});
const cycleVertical = (values: A[], index: number, numRows: number, numCols: number, delta: number) => withGrid(values, index, numCols, (oldRow, oldColumn) => {
const newRow = Num.cycleBy(oldRow, delta, 0, numRows - 1);
const onLastRow = newRow === numRows - 1;
const colsInRow = onLastRow ? values.length - (newRow * numCols) : numCols;
const newCol = Num.clamp(oldColumn, 0, colsInRow - 1);
return Optional.some({
row: newRow,
column: newCol
});
});
const cycleRight = (values: A[], index: number, numRows: number, numCols: number): Optional =>
cycleHorizontal(values, index, numRows, numCols, +1);
const cycleLeft = (values: A[], index: number, numRows: number, numCols: number): Optional =>
cycleHorizontal(values, index, numRows, numCols, -1);
const cycleUp = (values: A[], index: number, numRows: number, numCols: number): Optional =>
cycleVertical(values, index, numRows, numCols, -1);
const cycleDown = (values: A[], index: number, numRows: number, numCols: number): Optional =>
cycleVertical(values, index, numRows, numCols, +1);
export {
cycleDown,
cycleUp,
cycleLeft,
cycleRight
};