react-spreadsheet
Version:
Simple, customizable yet performant spreadsheet for React
240 lines (194 loc) • 6.95 kB
JavaScript
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
/**
* Immutable interface for Matrices
*
* @todo use Types.Point for all point references
*
*
*/
import { range as _range } from "./util";
import * as Types from "./types";
/** Gets the value at row and column of matrix. */
export function get(row, column, matrix) {
var columns = matrix[row];
if (columns === undefined) {
return undefined;
}
return columns[column];
}
/** Creates a slice of matrix from startPoint up to, but not including, endPoint. */
export function slice(startPoint, endPoint, matrix) {
var sliced = [];
var columns = endPoint.column - startPoint.column;
for (var row = startPoint.row; row <= endPoint.row; row++) {
var slicedRow = row - startPoint.row;
sliced[slicedRow] = sliced[slicedRow] || Array(columns);
for (var column = startPoint.column; column <= endPoint.column; column++) {
sliced[slicedRow][column - startPoint.column] = get(row, column, matrix);
}
}
return sliced;
}
/** Sets the value at row and column of matrix. If a row doesn't exist, it's created. */
export function set(row, column, value, matrix) {
var nextMatrix = _toConsumableArray(matrix); // Synchronize first row length
var firstRow = matrix[0];
var nextFirstRow = firstRow ? _toConsumableArray(firstRow) : [];
if (nextFirstRow.length - 1 < column) {
nextFirstRow[column] = undefined;
nextMatrix[0] = nextFirstRow;
}
var nextRow = matrix[row] ? _toConsumableArray(matrix[row]) : [];
nextRow[column] = value;
nextMatrix[row] = nextRow;
return nextMatrix;
}
/** Like Matrix.set() but mutates the matrix */
export function mutableSet(row, column, value, matrix) {
var firstRow = matrix[0];
if (!firstRow) {
firstRow = [];
matrix[0] = firstRow;
}
if (!(row in matrix)) {
matrix[row] = [];
} // Synchronize first row length
if (!(column in firstRow)) {
firstRow[column] = undefined;
}
matrix[row][column] = value;
}
/** Removes the coordinate of matrix */
export function unset(row, column, matrix) {
if (!has(row, column, matrix)) {
return matrix;
}
var nextMatrix = _toConsumableArray(matrix);
var nextRow = _toConsumableArray(matrix[row]); // Avoid deleting to preserve first row length
nextRow[column] = undefined;
nextMatrix[row] = nextRow;
return nextMatrix;
}
export function reduce(func, matrix, initialValue) {
var _getSize = getSize(matrix),
rows = _getSize.rows,
columns = _getSize.columns;
var acc = initialValue;
for (var row = 0; row < rows; row++) {
if (!matrix[row]) {
continue;
}
for (var column = 0; column < columns; column++) {
if (column in matrix[row]) {
acc = func(acc, matrix[row][column], {
row: row,
column: column
});
}
}
}
return acc;
}
/** Creates an array of values by running each element in collection thru iteratee. */
export function map(func, matrix) {
return reduce(function (acc, value, point) {
mutableSet(point.row, point.column, func(value, point), acc);
return acc;
}, matrix, []);
}
/**
* Converts all elements in row into a string separated by horizontalSeparator and each row string
* to string separated by verticalSeparator
*/
export function join(matrix) {
var horizontalSeparator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "\t";
var verticalSeparator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "\n";
var joined = "";
var _getSize2 = getSize(matrix),
rows = _getSize2.rows,
columns = _getSize2.columns;
for (var row = 0; row < rows; row++) {
if (row) {
joined += verticalSeparator;
}
for (var column = 0; column < columns; column++) {
if (column) {
joined += horizontalSeparator;
}
if (matrix[row] && column in matrix[row]) {
joined += String(matrix[row][column]);
}
}
}
return joined;
}
/* Parses a CSV separated by a horizontalSeparator and verticalSeparator into a Matrix */
export function split(csv, getValue) {
var horizontalSeparator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "\t";
var verticalSeparator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : /\r\n|\n|\r/;
return csv.split(verticalSeparator).map(function (row) {
return row.split(horizontalSeparator).map(getValue);
});
}
/** Returns whether the point exists in the matrix or not. */
export function has(row, column, matrix) {
var firstRow = matrix[0];
return firstRow && // validation
row >= 0 && column >= 0 && Number.isInteger(row) && Number.isInteger(column) && // first row length is in sync with other rows
column < firstRow.length && row < matrix.length;
}
/** Gets the size of matrix by returning its number of rows and columns */
export function getSize(matrix) {
var firstRow = matrix[0];
return {
columns: firstRow ? firstRow.length : 0,
rows: matrix.length
};
}
export function padMatrix(matrix, desiredRows) {
var _getSize3 = getSize(matrix),
rows = _getSize3.rows;
var missingRows = desiredRows - rows;
if (rows === 0 || missingRows < 0) return matrix;
var paddingRow = matrix.slice(-1)[0].map(function (v) {
return _objectSpread({}, v, {
value: ""
});
});
return [].concat(_toConsumableArray(matrix), _toConsumableArray(Array(missingRows).fill(paddingRow)));
}
/** Creates an array of points (positive and/or negative) progressing from startPoint up to, but not including, endPoint. */
export function range(endPoint, startPoint) {
var points = [];
var columnsRange = startPoint.column !== endPoint.column ? _range(endPoint.column, startPoint.column) : startPoint.row !== endPoint.row ? [startPoint.column] : [];
var rowsRange = startPoint.row !== endPoint.row ? _range(endPoint.row, startPoint.row) : startPoint.column !== endPoint.column ? [startPoint.row] : [];
for (var i = 0; i < rowsRange.length; i++) {
var row = rowsRange[i];
for (var j = 0; j < columnsRange.length; j++) {
var column = columnsRange[j];
points.push({
row: row,
column: column
});
}
}
return points;
}
/** Like Matrix.range() but including endPoint. */
export var inclusiveRange = function inclusiveRange(endPoint, startPoint) {
return range({
row: endPoint.row + Math.sign(endPoint.row - startPoint.row),
column: endPoint.column + Math.sign(endPoint.column - startPoint.column)
}, startPoint);
};
export function toArray(matrix, transform) {
var array = [];
for (var row = 0; row < matrix.length; row++) {
for (var column = 0; column < matrix.length; column++) {
var _value = matrix[row][column];
array.push(transform ? transform(_value) : _value);
}
}
return array;
}