@sdziadkowiec/react-datasheet-grid
Version:
An Excel-like React component to create beautiful spreadsheets.
170 lines • 14.7 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Grid = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_virtual_1 = require("@tanstack/react-virtual");
const react_1 = require("react");
const classnames_1 = __importDefault(require("classnames"));
const Cell_1 = require("./Cell");
const useMemoizedIndexCallback_1 = require("../hooks/useMemoizedIndexCallback");
const Grid = ({ data, columns, outerRef, innerRef, columnWidths, hasStickyRightColumn, frozenColumns = 0, displayHeight, headerRowHeight, rowHeight, rowKey, fullWidth, selection, activeCell, rowClassName, cellClassName, children, editing, getContextMenuItems, setRowData, deleteRows, duplicateRows, insertRowAfter, stopEditing, onScroll, }) => {
var _a, _b, _c, _d, _e;
const numFrozen = 1 + frozenColumns;
const fixedLefts = (0, react_1.useMemo)(() => {
var _a;
const lefts = new Array(columns.length).fill(0);
for (let i = 1; i < lefts.length; i++) {
lefts[i] = lefts[i - 1] + ((_a = columnWidths === null || columnWidths === void 0 ? void 0 : columnWidths[i - 1]) !== null && _a !== void 0 ? _a : 100);
}
return lefts;
}, [columns.length, columnWidths]);
const groupFrozen = numFrozen > 1;
const frozenWidth = groupFrozen ? fixedLefts[numFrozen - 1] + ((_a = columnWidths === null || columnWidths === void 0 ? void 0 : columnWidths[numFrozen - 1]) !== null && _a !== void 0 ? _a : 100) : 0;
const rowVirtualizer = (0, react_virtual_1.useVirtualizer)({
count: data.length,
getScrollElement: () => outerRef.current,
paddingStart: headerRowHeight,
estimateSize: (index) => rowHeight(index).height,
getItemKey: (index) => {
if (rowKey && index > 0) {
const row = data[index - 1];
if (typeof rowKey === 'function') {
return rowKey({ rowData: row, rowIndex: index });
}
else if (typeof rowKey === 'string' &&
row instanceof Object &&
rowKey in row) {
const key = row[rowKey];
if (typeof key === 'string' || typeof key === 'number') {
return key;
}
}
}
return index;
},
overscan: 5,
});
const colVirtualizer = (0, react_virtual_1.useVirtualizer)({
count: columns.length,
getScrollElement: () => outerRef.current,
estimateSize: (index) => { var _a; return (_a = columnWidths === null || columnWidths === void 0 ? void 0 : columnWidths[index]) !== null && _a !== void 0 ? _a : 100; },
horizontal: true,
getItemKey: (index) => { var _a; return (_a = columns[index].id) !== null && _a !== void 0 ? _a : index; },
overscan: 1,
rangeExtractor: (range) => {
let result = (0, react_virtual_1.defaultRangeExtractor)(range);
const added = [];
for (let i = 0; i < numFrozen; i++) {
if (!result.includes(i)) {
added.push(i);
}
}
result = [...added, ...result];
if (hasStickyRightColumn && !result.includes(columns.length - 1)) {
result.push(columns.length - 1);
}
return result;
},
});
(0, react_1.useEffect)(() => {
colVirtualizer.measure();
}, [colVirtualizer, columnWidths]);
const setGivenRowData = (0, useMemoizedIndexCallback_1.useMemoizedIndexCallback)(setRowData, 1);
const deleteGivenRow = (0, useMemoizedIndexCallback_1.useMemoizedIndexCallback)(deleteRows, 0);
const duplicateGivenRow = (0, useMemoizedIndexCallback_1.useMemoizedIndexCallback)(duplicateRows, 0);
const insertAfterGivenRow = (0, useMemoizedIndexCallback_1.useMemoizedIndexCallback)(insertRowAfter, 0);
const selectionColMin = (_b = selection === null || selection === void 0 ? void 0 : selection.min.col) !== null && _b !== void 0 ? _b : activeCell === null || activeCell === void 0 ? void 0 : activeCell.col;
const selectionColMax = (_c = selection === null || selection === void 0 ? void 0 : selection.max.col) !== null && _c !== void 0 ? _c : activeCell === null || activeCell === void 0 ? void 0 : activeCell.col;
const selectionMinRow = (_d = selection === null || selection === void 0 ? void 0 : selection.min.row) !== null && _d !== void 0 ? _d : activeCell === null || activeCell === void 0 ? void 0 : activeCell.row;
const selectionMaxRow = (_e = selection === null || selection === void 0 ? void 0 : selection.max.row) !== null && _e !== void 0 ? _e : activeCell === null || activeCell === void 0 ? void 0 : activeCell.row;
return ((0, jsx_runtime_1.jsx)("div", Object.assign({ ref: outerRef, className: "dsg-container", onScroll: onScroll, style: { height: displayHeight } }, { children: (0, jsx_runtime_1.jsxs)("div", Object.assign({ ref: innerRef, style: {
width: fullWidth ? '100%' : colVirtualizer.getTotalSize(),
height: rowVirtualizer.getTotalSize(),
} }, { children: [headerRowHeight > 0 && ((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: (0, classnames_1.default)('dsg-row', 'dsg-row-header'), style: {
width: fullWidth ? '100%' : colVirtualizer.getTotalSize(),
height: headerRowHeight,
} }, { children: [groupFrozen && ((0, jsx_runtime_1.jsx)("div", Object.assign({ className: (0, classnames_1.default)('dsg-frozen-header', 'dsg-cell-sticky-left'), style: { left: 0, width: frozenWidth, height: '100%', display: 'flex', flexDirection: 'row' } }, { children: Array.from({ length: numFrozen }).map((_, i) => {
var _a;
const selected = selectionColMin !== undefined && selectionColMax !== undefined && selectionColMin <= i - 1 && selectionColMax >= i - 1;
return ((0, jsx_runtime_1.jsx)(Cell_1.Cell, Object.assign({ gutter: i === 0, stickyRight: false, stickyLeft: undefined, width: ((_a = columnWidths === null || columnWidths === void 0 ? void 0 : columnWidths[i]) !== null && _a !== void 0 ? _a : 100), left: undefined, className: (0, classnames_1.default)('dsg-cell-header', selected && 'dsg-cell-header-active', columns[i].headerClassName), positionRelative: true }, { children: (0, jsx_runtime_1.jsx)("div", Object.assign({ className: "dsg-cell-header-container" }, { children: columns[i].title })) }), i));
}) }))), colVirtualizer.getVirtualItems().map((col) => {
if (groupFrozen && col.index < numFrozen)
return null;
return ((0, jsx_runtime_1.jsx)(Cell_1.Cell, Object.assign({ gutter: col.index === 0, stickyRight: hasStickyRightColumn && col.index === columns.length - 1, stickyLeft: col.index < numFrozen ? fixedLefts[col.index] : undefined, width: col.size, left: col.start, className: (0, classnames_1.default)('dsg-cell-header', selectionColMin !== undefined &&
selectionColMax !== undefined &&
selectionColMin <= col.index - 1 &&
selectionColMax >= col.index - 1 &&
'dsg-cell-header-active', columns[col.index].headerClassName) }, { children: (0, jsx_runtime_1.jsx)("div", Object.assign({ className: "dsg-cell-header-container" }, { children: columns[col.index].title })) }), col.key));
})] }))), rowVirtualizer.getVirtualItems().map((row) => {
const rowActive = Boolean(row.index >= (selectionMinRow !== null && selectionMinRow !== void 0 ? selectionMinRow : Infinity) &&
row.index <= (selectionMaxRow !== null && selectionMaxRow !== void 0 ? selectionMaxRow : -Infinity));
return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: (0, classnames_1.default)('dsg-row', typeof rowClassName === 'string' ? rowClassName : null, typeof rowClassName === 'function'
? rowClassName({
rowData: data[row.index],
rowIndex: row.index,
})
: null), style: {
height: row.size,
top: row.start,
width: fullWidth ? '100%' : colVirtualizer.getTotalSize(),
} }, { children: [groupFrozen && ((0, jsx_runtime_1.jsx)("div", Object.assign({ className: (0, classnames_1.default)('dsg-frozen-row', 'dsg-cell-sticky-left'), style: { left: 0, width: frozenWidth, height: '100%', display: 'flex', flexDirection: 'row' } }, { children: Array.from({ length: numFrozen }).map((_, i) => {
var _a;
const colCellClassName = columns[i].cellClassName;
const disabled = columns[i].disabled;
const Component = columns[i].component;
const cellDisabled = disabled === true ||
(typeof disabled === 'function' &&
disabled({
rowData: data[row.index],
rowIndex: row.index,
}));
const cellIsActive = (activeCell === null || activeCell === void 0 ? void 0 : activeCell.row) === row.index &&
activeCell.col === i - 1;
return ((0, jsx_runtime_1.jsx)(Cell_1.Cell, Object.assign({ gutter: i === 0, stickyRight: false, stickyLeft: undefined, active: i === 0 && rowActive, disabled: cellDisabled, className: (0, classnames_1.default)(typeof colCellClassName === 'function'
? colCellClassName({
rowData: data[row.index],
rowIndex: row.index,
columnId: columns[i].id,
})
: colCellClassName, typeof cellClassName === 'function'
? cellClassName({
rowData: data[row.index],
rowIndex: row.index,
columnId: columns[i].id,
})
: cellClassName), width: ((_a = columnWidths === null || columnWidths === void 0 ? void 0 : columnWidths[i]) !== null && _a !== void 0 ? _a : 100), left: undefined, positionRelative: true }, { children: (0, jsx_runtime_1.jsx)(Component, { rowData: data[row.index], getContextMenuItems: getContextMenuItems, disabled: cellDisabled, active: cellIsActive, columnIndex: i - 1, rowIndex: row.index, focus: cellIsActive && editing, deleteRow: deleteGivenRow(row.index), duplicateRow: duplicateGivenRow(row.index), stopEditing: stopEditing, insertRowBelow: insertAfterGivenRow(row.index), setRowData: setGivenRowData(row.index), columnData: columns[i].columnData }) }), i));
}) }))), colVirtualizer.getVirtualItems().map((col) => {
if (groupFrozen && col.index < numFrozen)
return null;
const colCellClassName = columns[col.index].cellClassName;
const disabled = columns[col.index].disabled;
const Component = columns[col.index].component;
const cellDisabled = disabled === true ||
(typeof disabled === 'function' &&
disabled({
rowData: data[row.index],
rowIndex: row.index,
}));
const cellIsActive = (activeCell === null || activeCell === void 0 ? void 0 : activeCell.row) === row.index &&
activeCell.col === col.index - 1;
return ((0, jsx_runtime_1.jsx)(Cell_1.Cell, Object.assign({ gutter: col.index === 0, stickyRight: hasStickyRightColumn && col.index === columns.length - 1, stickyLeft: col.index < numFrozen ? fixedLefts[col.index] : undefined, active: col.index === 0 && rowActive, disabled: cellDisabled, className: (0, classnames_1.default)(typeof colCellClassName === 'function'
? colCellClassName({
rowData: data[row.index],
rowIndex: row.index,
columnId: columns[col.index].id,
})
: colCellClassName, typeof cellClassName === 'function'
? cellClassName({
rowData: data[row.index],
rowIndex: row.index,
columnId: columns[col.index].id,
})
: cellClassName), width: col.size, left: col.start }, { children: (0, jsx_runtime_1.jsx)(Component, { rowData: data[row.index], getContextMenuItems: getContextMenuItems, disabled: cellDisabled, active: cellIsActive, columnIndex: col.index - 1, rowIndex: row.index, focus: cellIsActive && editing, deleteRow: deleteGivenRow(row.index), duplicateRow: duplicateGivenRow(row.index), stopEditing: stopEditing, insertRowBelow: insertAfterGivenRow(row.index), setRowData: setGivenRowData(row.index), columnData: columns[col.index].columnData }) }), col.key));
})] }), row.key));
}), children] })) })));
};
exports.Grid = Grid;
//# sourceMappingURL=Grid.js.map