@carbon/ibm-products
Version:
Carbon for IBM Products
667 lines (665 loc) • 25.1 kB
JavaScript
/**
* Copyright IBM Corp. 2020, 2026
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
import { __toESM } from "../../_virtual/_rolldown/runtime.js";
import { require_classnames } from "../../node_modules/classnames/index.js";
import { pkg } from "../../settings.js";
import { useActiveElement } from "../../global/js/hooks/useActiveElement.js";
import { usePreviousValue } from "../../global/js/hooks/usePreviousValue.js";
import { getDevtoolsProps } from "../../global/js/utils/devtools.js";
import uuidv4 from "../../global/js/utils/uuidv4.js";
import { getNodeTextContent } from "../../global/js/utils/getNodeTextContent.js";
import { useMoveActiveCell } from "./hooks/useMoveActiveCell.js";
import { deepCloneObject } from "../../global/js/utils/deepCloneObject.js";
import { removeCellSelections } from "./utils/removeCellSelections.js";
import { selectAllCells } from "./utils/selectAllCells.js";
import { useMultipleKeyTracking } from "./hooks/useMultipleKeyTracking.js";
import { useResetSpreadsheetFocus } from "./hooks/useResetSpreadsheetFocus.js";
import { useSpreadsheetOutsideClick } from "./hooks/useSpreadsheetOutsideClick.js";
import { useSpreadsheetEdit } from "./hooks/useSpreadsheetEdit.js";
import { handleHeaderCellSelection } from "./utils/handleHeaderCellSelection.js";
import { handleKeyPress } from "./utils/commonEventHandlers.js";
import { DataSpreadsheetBody } from "./DataSpreadsheetBody.js";
import { DataSpreadsheetHeader } from "./DataSpreadsheetHeader.js";
import { createActiveCellFn } from "./utils/createActiveCellFn.js";
import { getCellSize } from "./utils/getCellSize.js";
import { getScrollbarWidth } from "../../global/js/utils/getScrollbarWidth.js";
import { handleEditSubmit } from "./utils/handleEditSubmit.js";
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
import PropTypes from "prop-types";
import { useBlockLayout, useColumnOrder, useTable } from "react-table";
//#region src/components/DataSpreadsheet/DataSpreadsheet.tsx
var import_classnames = /* @__PURE__ */ __toESM(require_classnames());
const blockClass = `${pkg.prefix}--data-spreadsheet`;
const componentName = "DataSpreadsheet";
const defaults = {
columns: Object.freeze([]),
data: Object.freeze([]),
defaultEmptyRowCount: 16,
onDataUpdate: Object.freeze(() => {}),
onColDrag: Object.freeze(() => {}),
onActiveCellChange: Object.freeze(() => {}),
onSelectionAreaChange: Object.freeze(() => {}),
theme: "light"
};
/**
* DataSpreadsheet: used to organize and display large amounts of structured data, separated by columns and rows in a grid-like format.
* @deprecated This component is deprecated and will be removed in a future major version. Please migrate to AG Grid, TanStack Table, or Carbon DataTable.
*/
const DataSpreadsheet = React.forwardRef(({ cellSize = "sm", className, columns = defaults.columns, data = defaults.data, defaultEmptyRowCount = defaults.defaultEmptyRowCount, onDataUpdate = defaults.onDataUpdate, onColDrag = defaults.onColDrag, id, onActiveCellChange = defaults.onActiveCellChange, onSelectionAreaChange = defaults.onSelectionAreaChange, renderRowHeader, renderRowHeaderDirection, disableColumnSwapping = false, readOnlyTable = false, selectAllAriaLabel, spreadsheetAriaLabel, theme, totalVisibleColumns, ...rest }, ref) => {
const multiKeyTrackingRef = useRef(null);
const localRef = useRef(void 0);
const spreadsheetRef = ref || localRef;
const focusedElement = useActiveElement();
const [currentColumns, setCurrentColumns] = useState(columns);
const [pastColumns, setPastColumns] = useState([]);
const [containerHasFocus, setContainerHasFocus] = useState(false);
const [activeCellCoordinates, setActiveCellCoordinates] = useState(null);
const [selectionAreas, setSelectionAreas] = useState([]);
const [selectionAreaData, setSelectionAreaData] = useState([]);
const [clickAndHoldActive, setClickAndHoldActive] = useState(false);
const [currentMatcher, setCurrentMatcher] = useState("");
const [isEditing, setIsEditing] = useState(false);
const [cellEditorValue, setCellEditorValue] = useState("");
const [headerCellHoldActive, setHeaderCellHoldActive] = useState(false);
const [selectedHeaderReorderActive, setSelectedHeaderReorderActive] = useState(false);
const isBlurSpreadsheet = useRef(false);
const [isActiveHeaderCellChanged, setIsActiveHeaderCellChanged] = useState(false);
const [activeCellInsideSelectionArea, setActiveCellInsideSelectionArea] = useState(false);
const previousState = usePreviousValue({
activeCellCoordinates,
isEditing,
cellEditorValue,
selectedHeaderReorderActive
}) || {};
const cellSizeValue = getCellSize(cellSize);
const cellEditorRef = useRef(void 0);
const [activeCellContent, setActiveCellContent] = useState();
const activeCellRef = useRef(void 0);
const cellEditorRulerRef = useRef(void 0);
const hasCustomRowHeader = typeof renderRowHeader === "function";
const maxNumRowsCount = data.length.toString().length;
const defaultColumn = useMemo(() => ({
width: 150,
rowHeaderWidth: hasCustomRowHeader ? 40 + maxNumRowsCount * 8.56 : 64,
rowHeight: cellSizeValue
}), [
cellSizeValue,
hasCustomRowHeader,
maxNumRowsCount
]);
const { keysPressedList, usingMac } = useMultipleKeyTracking({
ref: multiKeyTrackingRef,
containerHasFocus,
isEditing
});
const scrollBarSize = useMemo(() => getScrollbarWidth(), []);
const { getTableProps, getTableBodyProps, headerGroups, rows, totalColumnsWidth, prepareRow, setColumnOrder, visibleColumns } = useTable({
columns,
data,
defaultColumn
}, useBlockLayout, useColumnOrder);
const updateData = useCallback((rowIndex, columnId, newValue) => {
onDataUpdate((prev) => prev.map((row, index) => {
if (index === rowIndex) return {
...prev[rowIndex],
[columnId]: cellEditorValue || newValue
};
return row;
}));
}, [cellEditorValue, onDataUpdate]);
useEffect(() => {
const currentHeaders = [];
if (Object.keys(currentColumns).length > 0) Object.keys(currentColumns).forEach((itemIndex) => {
if (typeof currentColumns[itemIndex].Header === "object") if (currentColumns[itemIndex].column_name) currentHeaders.push(currentColumns[itemIndex].column_name);
else currentHeaders.push(getNodeTextContent(currentColumns[itemIndex].Header));
else if (currentColumns[itemIndex].Header) currentHeaders.push(currentColumns[itemIndex].Header);
});
if (previousState.selectedHeaderReorderActive) setPastColumns(currentHeaders);
if (!previousState.selectedHeaderReorderActive && pastColumns.length > 0 && !headerCellHoldActive && JSON.stringify(currentHeaders) !== JSON.stringify(pastColumns)) {
onColDrag({
headers: currentHeaders,
data: activeCellContent.props.data
});
if (currentHeaders.length === 0) setPastColumns([]);
}
}, [
previousState?.selectedHeaderReorderActive,
currentColumns,
headerCellHoldActive,
columns,
activeCellContent,
onColDrag,
pastColumns
]);
const removeActiveCell = useCallback(() => {
const activeCellHighlight = spreadsheetRef?.current?.querySelector(`.${blockClass}__active-cell--highlight`);
if (activeCellHighlight) activeCellHighlight.style.display = "none";
}, [spreadsheetRef]);
const removeCellEditor = useCallback(() => {
setCellEditorValue("");
setIsEditing(false);
if (cellEditorRef?.current) cellEditorRef.current.style.display = "none";
}, []);
useEffect(() => {
const prevCoords = previousState?.activeCellCoordinates;
if ((prevCoords?.row !== activeCellCoordinates?.row || prevCoords?.column !== activeCellCoordinates?.column) && isEditing) {
const cellProps = rows[Number(prevCoords?.row)].cells[Number(prevCoords?.column)];
removeCellEditor();
updateData(prevCoords?.row, cellProps.column.id, void 0);
if (cellEditorRulerRef?.current) cellEditorRulerRef.current.textContent = "";
}
if (prevCoords?.row !== activeCellCoordinates?.row || prevCoords?.column !== activeCellCoordinates?.column) {
if (activeCellCoordinates && activeCellCoordinates?.row !== "header" && activeCellCoordinates?.column !== "header") {
const activeCellFullData = typeof activeCellCoordinates?.column === "number" && typeof activeCellCoordinates?.row === "number" ? rows[activeCellCoordinates?.row].cells[activeCellCoordinates?.column] : null;
if (activeCellFullData) setActiveCellContent(activeCellFullData.render("Cell"));
else setActiveCellContent(null);
}
if (activeCellCoordinates && activeCellCoordinates?.row === "header" || activeCellCoordinates?.column === "header") {
setActiveCellContent(null);
setIsActiveHeaderCellChanged((prev) => !prev);
}
}
if (isEditing && previousState.activeCellCoordinates && isBlurSpreadsheet.current) {
setActiveCellContent(previousState.cellEditorValue);
isBlurSpreadsheet.current = false;
removeCellEditor();
}
}, [
isBlurSpreadsheet,
activeCellCoordinates,
previousState?.activeCellCoordinates,
previousState?.cellEditorValue,
updateData,
rows,
isEditing,
removeCellEditor,
activeCellContent
]);
const createActiveCell = useCallback(({ placementElement, coords, addToHeader = false }) => {
const activeCellFullData = typeof coords?.column === "number" && typeof coords?.row === "number" ? rows[coords?.row].cells[coords?.column] : null;
createActiveCellFn({
placementElement,
coords,
addToHeader,
contextRef: spreadsheetRef,
blockClass,
onActiveCellChange,
activeCellValue: activeCellFullData ? Object.values(activeCellFullData.row.values)[coords?.column] : null,
activeCellRef,
cellEditorRef,
defaultColumn
});
}, [
spreadsheetRef,
rows,
onActiveCellChange,
defaultColumn
]);
useResetSpreadsheetFocus({
focusedElement,
removeActiveCell,
setContainerHasFocus
});
useSpreadsheetOutsideClick({
isBlurSpreadsheet,
spreadsheetRef,
setActiveCellCoordinates,
setSelectionAreas,
removeActiveCell,
setContainerHasFocus,
removeCellEditor
});
useMoveActiveCell({
spreadsheetRef,
activeCellCoordinates,
containerHasFocus,
createActiveCell,
activeCellContent,
isActiveHeaderCellChanged
});
const handleInitialArrowPress = useCallback(() => {
setActiveCellInsideSelectionArea(false);
if (!activeCellCoordinates) setActiveCellCoordinates({
column: "header",
row: "header"
});
}, [activeCellCoordinates]);
const updateActiveCellCoordinates = useCallback(({ coords = { ...activeCellCoordinates }, updatedValue, optOutOfSelectionAreaUpdate = false }) => {
const newActiveCell = {
...coords,
...updatedValue
};
setActiveCellCoordinates(newActiveCell);
if (newActiveCell.row !== "header" && newActiveCell.column !== "header" && !optOutOfSelectionAreaUpdate) {
const tempMatcher = uuidv4();
setSelectionAreas([{
point1: newActiveCell,
matcher: tempMatcher
}]);
setCurrentMatcher(tempMatcher);
}
}, [activeCellCoordinates]);
const handleHomeEndKey = useCallback(({ type }) => {
updateActiveCellCoordinates({
coords: { ...activeCellCoordinates },
updatedValue: { column: type === "Home" ? 0 : columns.length - 1 }
});
removeCellSelections({
matcher: void 0,
spreadsheetRef
});
}, [
activeCellCoordinates,
updateActiveCellCoordinates,
spreadsheetRef,
columns.length
]);
const checkForReturnCondition = useCallback((key) => {
return isEditing || key === "Meta" || key === "Control";
}, [isEditing]);
const handleArrowKeyPress = useCallback((arrowKey) => {
event?.preventDefault();
handleInitialArrowPress();
const coordinatesClone = { ...activeCellCoordinates };
let updatedValue;
switch (arrowKey) {
case "ArrowLeft":
if (coordinatesClone.column === "header") return;
if (typeof coordinatesClone.column === "number") if (coordinatesClone.column === 0) updatedValue = { column: "header" };
else updatedValue = { column: coordinatesClone.column - 1 };
break;
case "ArrowUp":
if (coordinatesClone.row === "header") return;
if (typeof coordinatesClone.row === "number") if (coordinatesClone.row === 0) updatedValue = { row: "header" };
else updatedValue = { row: coordinatesClone.row - 1 };
break;
case "ArrowRight":
if (coordinatesClone.column === "header") updatedValue = { column: 0 };
if (typeof coordinatesClone.column === "number") if (columns.length - 1 === coordinatesClone.column) return;
else updatedValue = { column: coordinatesClone.column + 1 };
break;
case "ArrowDown":
if (coordinatesClone.row === "header") updatedValue = { row: 0 };
if (typeof coordinatesClone.row === "number") if (rows.length - 1 === coordinatesClone.row) return;
else updatedValue = { row: coordinatesClone.row + 1 };
break;
}
if (updatedValue) updateActiveCellCoordinates({
coords: coordinatesClone,
updatedValue
});
}, [
handleInitialArrowPress,
updateActiveCellCoordinates,
activeCellCoordinates,
columns,
rows
]);
const handleKeyPressEvent = useCallback((event) => {
handleKeyPress(event, activeCellInsideSelectionArea, updateActiveCellCoordinates, activeCellCoordinates, removeActiveCell, columns, rows, spreadsheetRef, currentMatcher, removeCellEditor, selectionAreas, handleHomeEndKey, keysPressedList, usingMac, updateData, checkForReturnCondition, handleArrowKeyPress, setSelectionAreas, setSelectionAreaData, setCurrentMatcher, activeCellRef, setActiveCellCoordinates, setContainerHasFocus, setActiveCellContent, readOnlyTable);
}, [
activeCellInsideSelectionArea,
updateActiveCellCoordinates,
activeCellCoordinates,
removeActiveCell,
columns,
rows,
spreadsheetRef,
currentMatcher,
removeCellEditor,
selectionAreas,
handleHomeEndKey,
keysPressedList,
usingMac,
updateData,
checkForReturnCondition,
handleArrowKeyPress,
readOnlyTable
]);
const startEditMode = () => {
setIsEditing(true);
setClickAndHoldActive(false);
const activeCellValue = (typeof activeCellCoordinates?.column === "number" && typeof activeCellCoordinates?.row === "number" ? rows[activeCellCoordinates?.row].cells[activeCellCoordinates?.column] : null)?.row?.cells?.[Number(activeCellCoordinates?.column)]?.value;
setCellEditorValue(activeCellValue || "");
if (cellEditorRulerRef?.current) cellEditorRulerRef.current.textContent = activeCellValue;
if (cellEditorRef?.current && activeCellRef?.current) cellEditorRef.current.style.width = activeCellRef?.current?.style?.width;
};
useEffect(() => {
if (isEditing && !previousState?.isEditing) {
cellEditorRef?.current?.setSelectionRange(Number(cellEditorRulerRef?.current?.textContent?.length), Number(cellEditorRulerRef?.current?.textContent?.length));
cellEditorRef?.current?.focus();
}
}, [isEditing, previousState?.isEditing]);
const handleActiveCellClick = () => {
if (activeCellCoordinates?.row === "header" || activeCellCoordinates?.column === "header") {
const indexValue = activeCellCoordinates?.row === "header" ? activeCellCoordinates?.column : activeCellCoordinates?.row;
if (activeCellCoordinates?.row === "header" && activeCellCoordinates?.column === "header") return;
handleRowColumnHeaderClick({
isKeyboard: false,
index: Number(indexValue)
});
}
};
const handleActiveCellMouseUp = () => {
setClickAndHoldActive(false);
};
const handleActiveCellMouseDown = () => {
if (activeCellCoordinates?.row !== "header" || activeCellCoordinates?.column !== "header") {
const tempMatcher = uuidv4();
setClickAndHoldActive(true);
removeCellSelections({
matcher: null,
spreadsheetRef
});
setSelectionAreas([{
point1: activeCellCoordinates,
matcher: tempMatcher
}]);
setCurrentMatcher(tempMatcher);
setSelectionAreaData([]);
setActiveCellInsideSelectionArea(false);
}
};
const handleActiveCellKeyDown = (event) => {
const { key } = event;
if (key === "Enter" && !activeCellInsideSelectionArea && !readOnlyTable) {
if (activeCellCoordinates?.column !== "header" && activeCellCoordinates?.row !== "header") startEditMode();
if (activeCellCoordinates?.row === "header" || activeCellCoordinates?.column === "header") handleRowColumnHeaderClick({ isKeyboard: true });
}
};
const handleRowColumnHeaderClick = ({ isKeyboard, index = -1 }) => {
const handleHeaderCellProps = {
activeCellCoordinates,
rows,
columns,
currentMatcher,
setActiveCellCoordinates,
setCurrentMatcher,
setSelectionAreas,
spreadsheetRef,
index,
isKeyboard,
setSelectionAreaData,
isHoldingCommandKey: null,
isHoldingShiftKey: null
};
if (activeCellCoordinates?.row === "header" && activeCellCoordinates?.column !== "header") handleHeaderCellSelection({
type: "column",
...handleHeaderCellProps
});
if (activeCellCoordinates?.column === "header" && activeCellCoordinates?.row !== "header") handleHeaderCellSelection({
type: "row",
...handleHeaderCellProps
});
if (activeCellCoordinates?.column === "header" && activeCellCoordinates?.row === "header") selectAllCells({
ref: spreadsheetRef,
setCurrentMatcher,
setSelectionAreas,
rows,
columns,
activeCellCoordinates,
updateActiveCellCoordinates
});
};
const handleActiveCellDoubleClick = (readOnlyTable) => {
if (!readOnlyTable) startEditMode();
};
useSpreadsheetEdit({
isEditing,
rows,
activeCellCoordinates,
activeCellRef,
cellEditorRef,
cellEditorRulerRef,
visibleColumns,
defaultColumn,
cellEditorValue
});
const handleActiveCellMouseEnterCallback = useCallback((areas, clickHold) => {
if (!currentMatcher) return;
if (areas && areas.length && clickHold && currentMatcher) setSelectionAreas((prev) => {
const selectionAreaClone = deepCloneObject(prev);
const indexOfItemToUpdate = selectionAreaClone.findIndex((item) => item.matcher === currentMatcher);
if (indexOfItemToUpdate === -1) return prev;
if (typeof selectionAreaClone[indexOfItemToUpdate].point2 === "object" && selectionAreaClone[indexOfItemToUpdate].areaCreated) {
selectionAreaClone[indexOfItemToUpdate].point2 = selectionAreaClone[indexOfItemToUpdate].point1;
selectionAreaClone[indexOfItemToUpdate].areaCreated = false;
setActiveCellInsideSelectionArea(false);
removeCellSelections({
matcher: currentMatcher,
spreadsheetRef
});
return selectionAreaClone;
}
return prev;
});
}, [spreadsheetRef, currentMatcher]);
const handleActiveCellMouseEnter = useCallback(() => {
handleActiveCellMouseEnterCallback(selectionAreas, clickAndHoldActive);
}, [
clickAndHoldActive,
selectionAreas,
handleActiveCellMouseEnterCallback
]);
return /* @__PURE__ */ React.createElement("div", {
...rest,
...getTableProps(),
...getDevtoolsProps(componentName),
className: (0, import_classnames.default)(blockClass, className, `${blockClass}--interactive-cell-element`, {
[`${blockClass}__container-has-focus`]: containerHasFocus,
[`${blockClass}__${theme}`]: theme === "dark"
}),
ref: spreadsheetRef,
role: "grid",
tabIndex: 0,
"aria-rowcount": rows?.length || 0,
"aria-colcount": columns?.length || 0,
"aria-label": spreadsheetAriaLabel,
onKeyDown: handleKeyPressEvent,
onFocus: () => setContainerHasFocus(true)
}, /* @__PURE__ */ React.createElement("div", { ref: multiKeyTrackingRef }, /* @__PURE__ */ React.createElement(DataSpreadsheetHeader, {
ref: spreadsheetRef,
activeCellCoordinates,
cellSize,
columns,
currentMatcher,
defaultColumn,
selectedHeaderReorderActive,
setSelectedHeaderReorderActive,
headerGroups,
rows,
scrollBarSize,
selectionAreas,
setActiveCellCoordinates,
setSelectionAreas,
setCurrentMatcher,
setSelectionAreaData,
disableColumnSwapping,
readOnlyTable,
totalVisibleColumns,
updateActiveCellCoordinates,
setHeaderCellHoldActive,
headerCellHoldActive,
visibleColumns,
selectAllAriaLabel
}), /* @__PURE__ */ React.createElement(DataSpreadsheetBody, {
activeCellRef,
activeCellCoordinates,
setCurrentColumns,
ref: spreadsheetRef,
clickAndHoldActive,
setClickAndHoldActive,
currentMatcher,
setCurrentMatcher,
setContainerHasFocus,
selectedHeaderReorderActive,
setSelectedHeaderReorderActive,
selectionAreas,
setSelectionAreas,
headerGroups,
defaultColumn,
getTableBodyProps,
hasCustomRowHeader,
onDataUpdate,
renderRowHeaderDirection,
renderRowHeader,
onActiveCellChange,
onSelectionAreaChange,
prepareRow,
rows,
selectionAreaData,
setSelectionAreaData,
setActiveCellCoordinates,
scrollBarSize,
totalColumnsWidth,
id,
columns,
defaultEmptyRowCount,
setActiveCellInsideSelectionArea,
totalVisibleColumns,
setHeaderCellHoldActive,
setColumnOrder,
visibleColumns
}), /* @__PURE__ */ React.createElement("button", {
onMouseDown: handleActiveCellMouseDown,
onMouseUp: handleActiveCellMouseUp,
onClick: handleActiveCellClick,
onKeyDown: handleActiveCellKeyDown,
onDoubleClick: () => handleActiveCellDoubleClick(readOnlyTable),
onMouseEnter: handleActiveCellMouseEnter,
ref: activeCellRef,
className: (0, import_classnames.default)(`${blockClass}--interactive-cell-element`, `${blockClass}__active-cell--highlight`, { [`${blockClass}__active-cell--with-selection`]: activeCellInsideSelectionArea }),
type: "button"
}, activeCellContent), /* @__PURE__ */ React.createElement("textarea", {
id: `${blockClass}__cell-editor-text-area`,
value: cellEditorValue,
onKeyDown: handleEditSubmit({
activeCellCoordinates,
cellEditorRulerRef,
columns,
previousState,
removeCellEditor,
rows,
setActiveCellCoordinates,
setCurrentMatcher,
setSelectionAreas,
spreadsheetRef,
updateData
}),
onChange: (event) => {
if (previousState.isEditing) {
setCellEditorValue(event.target.value);
if (cellEditorRulerRef?.current) cellEditorRulerRef.current.textContent = event.target.value;
}
},
ref: cellEditorRef,
"aria-labelledby": activeCellCoordinates ? `${blockClass}__cell--${activeCellCoordinates?.row}--${activeCellCoordinates?.column}` : "",
className: (0, import_classnames.default)(`${blockClass}__cell-editor`, `${blockClass}--interactive-cell-element`, `${blockClass}__cell-editor--${cellSize}`, { [`${blockClass}__cell-editor--active`]: isEditing })
}), /* @__PURE__ */ React.createElement("pre", {
"aria-hidden": true,
ref: cellEditorRulerRef,
className: `${blockClass}__cell-editor-ruler`
})));
});
/**@ts-ignore*/
DataSpreadsheet.deprecated = {
level: "warn",
details: `${componentName} is deprecated and will be removed in a future major version. Please migrate to AG Grid (https://www.ag-grid.com/), TanStack Table (https://tanstack.com/table/), or Carbon DataTable.`
};
DataSpreadsheet.displayName = componentName;
DataSpreadsheet.propTypes = {
/**
* Specifies the cell height
*/
cellSize: PropTypes.oneOf([
"xs",
"sm",
"md",
"lg"
]),
/**
* Provide an optional class to be applied to the containing node.
*/
className: PropTypes.string,
/**
* The data that will build the column headers
*/
/**@ts-ignore */
columns: PropTypes.arrayOf(PropTypes.shape({
Header: PropTypes.string,
accessor: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
Cell: PropTypes.func
})),
/**
* The spreadsheet data that will be rendered in the body of the spreadsheet component
*/
/**@ts-ignore */
data: PropTypes.arrayOf(PropTypes.shape),
/**
* Sets the number of empty rows to be created when there is no data provided
*/
defaultEmptyRowCount: PropTypes.number,
/**
* Disable column swapping, default false
*/
disableColumnSwapping: PropTypes.bool,
/**
* Check if spreadsheet is using custom row header component attached
*/
hasCustomRowHeader: PropTypes.bool,
/**
* The spreadsheet id
*/
id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
/**
* The event handler that is called when the active cell changes
*/
onActiveCellChange: PropTypes.func,
/**
* Callback for when columns are dropped after dragged
*/
onColDrag: PropTypes.func,
/**
* The setter fn for the data prop
*/
onDataUpdate: PropTypes.func,
/**
* The event handler that is called when the selection area values change
*/
onSelectionAreaChange: PropTypes.func,
/**
* Read-only table
*/
readOnlyTable: PropTypes.bool,
/**
* Component next to numbering rows
*/
renderRowHeader: PropTypes.func,
/**
* Component next to numbering rows
*/
renderRowHeaderDirection: PropTypes.oneOf(["left", "right"]),
/**
* The aria label applied to the Select all button
*/
selectAllAriaLabel: PropTypes.string.isRequired,
/**
* The aria label applied to the Data spreadsheet component
*/
spreadsheetAriaLabel: PropTypes.string.isRequired,
/**
* The theme the DataSpreadsheet should use (only used to render active cell/selection area colors on dark theme)
*/
theme: PropTypes.oneOf(["light", "dark"]),
/**
* The total number of columns to be initially visible, additional columns will be rendered and
* visible via horizontal scrollbar
*/
totalVisibleColumns: PropTypes.number
};
//#endregion
export { DataSpreadsheet };