slate-edit-table
Version:
A Slate plugin to handle keyboard events in tables.
81 lines (66 loc) • 1.69 kB
Flow
// @flow
import { type Change } from 'slate';
import { TablePosition } from '../utils';
import type Options from '../options';
/**
* Move selection by a {x,y} relative movement
*/
function moveSelectionBy(
opts: Options,
change: Change,
x: number, // Move horizontally by x
y: number // Move vertically by y
): Change {
const { value } = change;
const { startKey } = value;
const pos = TablePosition.create(opts, value.document, startKey);
if (!pos.isInCell()) {
throw new Error('moveSelectionBy can only be applied in a cell');
}
const rowIndex = pos.getRowIndex();
const colIndex = pos.getColumnIndex();
const width = pos.getWidth();
const height = pos.getHeight();
const [absX, absY] = normPos(x + colIndex, y + rowIndex, width, height);
const isGoingUp = y < 0;
if (absX === -1) {
// Out of table
return change;
}
const { table } = pos;
const row = table.nodes.get(absY);
const cell = row.nodes.get(absX);
if (isGoingUp) {
change.collapseToEndOf(cell);
} else {
change.collapseToStartOf(cell);
}
return change;
}
/**
* Normalize position in a table. If x is out of the row, update y accordingly.
* Returns [-1, -1] if the new selection is out of table
*/
function normPos(
x: number,
y: number,
width: number,
height: number
): number[] {
if (x < 0) {
x = width - 1;
y -= 1;
}
if (y < 0) {
return [-1, -1];
}
if (x >= width) {
x = 0;
y += 1;
}
if (y >= height) {
return [-1, -1];
}
return [x, y];
}
export default moveSelectionBy;