react-data-grid
Version:
Feature-rich and customizable data grid React component
1,408 lines • 104 kB
JavaScript
import { createContext, memo, use, useCallback, useEffectEvent, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
import { flushSync } from "react-dom";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
//#region src/utils/frozenColumnUtils.ts
function isStartFrozen(frozen) {
return frozen === true || frozen === "start";
}
//#endregion
//#region src/utils/colSpanUtils.ts
function getColSpan(column, lastStartFrozenColumnIndex, firstEndFrozenColumnIndex, args) {
if (typeof column.colSpan !== "function") return void 0;
const colSpan = column.colSpan(args);
if (!Number.isInteger(colSpan) || colSpan <= 1) return void 0;
const spanEnd = column.idx + colSpan - 1;
if (isStartFrozen(column.frozen) && spanEnd > lastStartFrozenColumnIndex) return void 0;
if (column.frozen === false && firstEndFrozenColumnIndex !== -1 && spanEnd >= firstEndFrozenColumnIndex) return;
return colSpan;
}
//#endregion
//#region src/utils/activePositionUtils.ts
function isCellEditableUtil(column, row) {
return column.renderEditCell != null && (typeof column.editable === "function" ? column.editable(row) : column.editable) !== false;
}
function getCellColSpan({ rows, topSummaryRows, bottomSummaryRows, rowIdx, mainHeaderRowIdx, lastStartFrozenColumnIndex, firstEndFrozenColumnIndex, column }) {
const topSummaryRowsCount = topSummaryRows?.length ?? 0;
if (rowIdx === mainHeaderRowIdx) return getColSpan(column, lastStartFrozenColumnIndex, firstEndFrozenColumnIndex, { type: "HEADER" });
if (topSummaryRows && rowIdx > mainHeaderRowIdx && rowIdx <= topSummaryRowsCount + mainHeaderRowIdx) return getColSpan(column, lastStartFrozenColumnIndex, firstEndFrozenColumnIndex, {
type: "SUMMARY",
row: topSummaryRows[rowIdx + topSummaryRowsCount]
});
if (rowIdx >= 0 && rowIdx < rows.length) {
const row = rows[rowIdx];
return getColSpan(column, lastStartFrozenColumnIndex, firstEndFrozenColumnIndex, {
type: "ROW",
row
});
}
if (bottomSummaryRows) return getColSpan(column, lastStartFrozenColumnIndex, firstEndFrozenColumnIndex, {
type: "SUMMARY",
row: bottomSummaryRows[rowIdx - rows.length]
});
}
function getNextActivePosition({ moveUp, moveNext, cellNavigationMode, columns, colSpanColumns, rows, topSummaryRows, bottomSummaryRows, minRowIdx, mainHeaderRowIdx, maxRowIdx, activePosition: { idx: activeIdx, rowIdx: activeRowIdx }, nextPosition, nextPositionIsCellInActiveBounds, lastStartFrozenColumnIndex, firstEndFrozenColumnIndex }) {
let { idx: nextIdx, rowIdx: nextRowIdx } = nextPosition;
const columnsCount = columns.length;
const setColSpan = (moveNext) => {
for (const column of colSpanColumns) {
const colIdx = column.idx;
if (colIdx > nextIdx) break;
const colSpan = getCellColSpan({
rows,
topSummaryRows,
bottomSummaryRows,
rowIdx: nextRowIdx,
mainHeaderRowIdx,
lastStartFrozenColumnIndex,
firstEndFrozenColumnIndex,
column
});
if (colSpan && nextIdx > colIdx && nextIdx < colSpan + colIdx) {
nextIdx = colIdx + (moveNext ? colSpan : 0);
break;
}
}
};
const getParentRowIdx = (parent) => {
return parent.level + mainHeaderRowIdx;
};
const setHeaderGroupColAndRowSpan = () => {
if (moveNext) {
let { parent } = columns[nextIdx];
while (parent !== void 0) {
const parentRowIdx = getParentRowIdx(parent);
if (nextRowIdx === parentRowIdx) {
nextIdx = parent.idx + parent.colSpan;
break;
}
({parent} = parent);
}
} else if (moveUp) {
let { parent } = columns[nextIdx];
let found = false;
while (parent !== void 0) {
const parentRowIdx = getParentRowIdx(parent);
if (nextRowIdx >= parentRowIdx) {
nextIdx = parent.idx;
nextRowIdx = parentRowIdx;
found = true;
break;
}
({parent} = parent);
}
if (!found) {
nextIdx = activeIdx;
nextRowIdx = activeRowIdx;
}
}
};
if (nextPositionIsCellInActiveBounds) {
setColSpan(moveNext);
if (nextRowIdx < mainHeaderRowIdx) setHeaderGroupColAndRowSpan();
}
if (cellNavigationMode === "CHANGE_ROW") {
const isAfterLastColumn = nextIdx === columnsCount;
const isBeforeFirstColumn = nextIdx === -1;
if (isAfterLastColumn) {
if (!(nextRowIdx === maxRowIdx)) {
nextIdx = 0;
nextRowIdx += 1;
}
} else if (isBeforeFirstColumn) {
if (!(nextRowIdx === minRowIdx)) {
nextRowIdx -= 1;
nextIdx = columnsCount - 1;
}
setColSpan(false);
}
}
if (nextRowIdx < mainHeaderRowIdx && nextIdx > -1 && nextIdx < columnsCount) {
let { parent } = columns[nextIdx];
const nextParentRowIdx = nextRowIdx;
nextRowIdx = mainHeaderRowIdx;
while (parent !== void 0) {
const parentRowIdx = getParentRowIdx(parent);
if (parentRowIdx >= nextParentRowIdx) {
nextRowIdx = parentRowIdx;
nextIdx = parent.idx;
}
({parent} = parent);
}
}
return {
idx: nextIdx,
rowIdx: nextRowIdx
};
}
function canExitGrid({ maxColIdx, minRowIdx, maxRowIdx, activePosition: { rowIdx, idx }, shiftKey }) {
return shiftKey ? idx === 0 && rowIdx === minRowIdx : idx === maxColIdx && rowIdx === maxRowIdx;
}
//#endregion
//#region src/utils/domUtils.ts
function stopPropagation(event) {
event.stopPropagation();
}
function scrollIntoView(element, behavior = "instant") {
element?.scrollIntoView({
inline: "nearest",
block: "nearest",
behavior
});
}
function getRowToScroll(gridEl) {
return gridEl.querySelector("& > [role=\"row\"][tabindex=\"0\"]");
}
function getCellToScroll(gridEl) {
return gridEl.querySelector("& > [role=\"row\"] > [tabindex=\"0\"]");
}
function focusElement(element, shouldScroll) {
if (element === null) return;
if (shouldScroll) scrollIntoView(element);
element.focus({ preventScroll: true });
}
function focusRow(gridEl) {
focusElement(getRowToScroll(gridEl), true);
}
function focusCell(gridEl, shouldScroll = true) {
focusElement(getCellToScroll(gridEl), shouldScroll);
}
//#endregion
//#region src/utils/eventUtils.ts
function createCellEvent(event) {
let defaultPrevented = false;
const cellEvent = {
...event,
preventGridDefault() {
defaultPrevented = true;
},
isGridDefaultPrevented() {
return defaultPrevented;
}
};
Object.setPrototypeOf(cellEvent, Object.getPrototypeOf(event));
return cellEvent;
}
//#endregion
//#region src/utils/keyboardUtils.ts
const nonInputKeys = /* @__PURE__ */ new Set([
"Unidentified",
"Alt",
"AltGraph",
"CapsLock",
"Control",
"Fn",
"FnLock",
"Meta",
"NumLock",
"ScrollLock",
"Shift",
"Tab",
"ArrowDown",
"ArrowLeft",
"ArrowRight",
"ArrowUp",
"End",
"Home",
"PageDown",
"PageUp",
"Insert",
"ContextMenu",
"Escape",
"Pause",
"Play",
"PrintScreen",
"F1",
"F3",
"F4",
"F5",
"F6",
"F7",
"F8",
"F9",
"F10",
"F11",
"F12"
]);
function isCtrlKeyHeldDown(e) {
return (e.ctrlKey || e.metaKey) && e.key !== "Control";
}
const vKey = 86;
function isDefaultCellInput(event, isUserHandlingPaste) {
if (isCtrlKeyHeldDown(event) && (event.keyCode !== vKey || isUserHandlingPaste)) return false;
return !nonInputKeys.has(event.key);
}
/**
* By default, the following navigation keys are enabled while an editor is open, under specific conditions:
* - Tab:
* - The editor must be an <input>, a <textarea>, or a <select> element.
* - The editor element must be the only immediate child of the editor container/a label.
*/
function onEditorNavigation({ key, target }) {
if (key === "Tab" && (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement)) return target.closest(".rdg-editor-container")?.querySelectorAll("input, textarea, select").length === 1;
return false;
}
function getLeftRightKey(direction) {
const isRtl = direction === "rtl";
return {
leftKey: isRtl ? "ArrowRight" : "ArrowLeft",
rightKey: isRtl ? "ArrowLeft" : "ArrowRight"
};
}
//#endregion
//#region src/utils/renderMeasuringCells.tsx
const measuringCellClassname = "rdg-7-0-0-beta-60-fa71d63e";
function renderMeasuringCells(viewportColumns) {
return viewportColumns.map(({ key, idx, minWidth, maxWidth }) => /* @__PURE__ */ jsx("div", {
className: measuringCellClassname,
style: {
gridColumnStart: idx + 1,
minWidth,
maxWidth
},
"data-measuring-cell-key": key
}, key));
}
const cellClassname = `rdg-cell rdg-7-0-0-beta-60-85c48527`;
const cellFrozenBase = "rdg-7-0-0-beta-60-203d9925";
const cellFrozenStartClassname = `rdg-cell-frozen-start ${cellFrozenBase}`;
const cellFrozenEndClassname = `rdg-cell-frozen-end ${cellFrozenBase}`;
const cellDragHandleClassname = `rdg-cell-drag-handle rdg-7-0-0-beta-60-bfba19bc`;
//#endregion
//#region src/utils/styleUtils.ts
function getHeaderCellStyle(column, rowIdx, rowSpan) {
const gridRowEnd = rowIdx + 1;
const paddingBlockStart = `calc(${rowSpan - 1} * var(--rdg-header-row-height))`;
if (column.parent === void 0) return {
insetBlockStart: 0,
gridRowStart: 1,
gridRowEnd,
paddingBlockStart
};
return {
insetBlockStart: `calc(${rowIdx - rowSpan} * var(--rdg-header-row-height))`,
gridRowStart: gridRowEnd - rowSpan,
gridRowEnd,
paddingBlockStart
};
}
function getCellStyle(column, colSpan = 1) {
const index = column.idx + 1;
return {
gridColumnStart: index,
gridColumnEnd: index + colSpan,
insetInlineStart: isStartFrozen(column.frozen) ? `var(--rdg-frozen-start-${column.idx})` : void 0,
insetInlineEnd: column.frozen === "end" ? `var(--rdg-frozen-end-${column.idx + colSpan - 1})` : void 0
};
}
function classnames(...args) {
let classname = "";
for (const arg of args) if (typeof arg === "string") classname += ` ${arg}`;
return classname.slice(1);
}
function getCellClassname(column, ...extraClasses) {
return classnames(cellClassname, isStartFrozen(column.frozen) && cellFrozenStartClassname, column.frozen === "end" && cellFrozenEndClassname, ...extraClasses);
}
//#endregion
//#region src/utils/index.ts
const { min, max, floor, abs } = Math;
function assertIsValidKeyGetter(keyGetter) {
if (typeof keyGetter !== "function") throw new Error("Please specify the rowKeyGetter prop to use selection");
}
function clampColumnWidth(width, { minWidth, maxWidth }) {
width = max(width, minWidth);
if (typeof maxWidth === "number" && maxWidth >= minWidth) return min(width, maxWidth);
return width;
}
function getHeaderCellRowSpan(column, rowIdx) {
return column.parent === void 0 ? rowIdx : column.level - column.parent.level;
}
//#endregion
//#region src/hooks/useActivePosition.ts
const initialActivePosition = {
idx: -1,
rowIdx: Number.NEGATIVE_INFINITY,
mode: "ACTIVE"
};
function useActivePosition({ gridRef, columns, rows, isTreeGrid, maxColIdx, minRowIdx, maxRowIdx, setDraggedOverRowIdx }) {
const [activePosition, setActivePosition] = useState(initialActivePosition);
const [positionToFocus, setPositionToFocus] = useState(null);
const positionToFocusRef = useRef(null);
/**
* Returns whether the given position represents a valid cell or row position in the grid.
* Active bounds: any valid position in the grid
* Viewport: any valid position in the grid outside of header rows and summary rows
* Row selection is only allowed in TreeDataGrid
*/
function validatePosition({ idx, rowIdx }) {
const isColumnPositionAllColumns = isTreeGrid && idx === -1;
const isColumnPositionInActiveBounds = idx >= 0 && idx <= maxColIdx;
const isRowPositionInActiveBounds = rowIdx >= minRowIdx && rowIdx <= maxRowIdx;
const isRowPositionInViewport = rowIdx >= 0 && rowIdx < rows.length;
const isRowInActiveBounds = isColumnPositionAllColumns && isRowPositionInActiveBounds;
const isRowInViewport = isColumnPositionAllColumns && isRowPositionInViewport;
const isCellInActiveBounds = isColumnPositionInActiveBounds && isRowPositionInActiveBounds;
const isCellInViewport = isColumnPositionInActiveBounds && isRowPositionInViewport;
return {
isPositionInActiveBounds: isRowInActiveBounds || isCellInActiveBounds,
isPositionInViewport: isRowInViewport || isCellInViewport,
isRowInActiveBounds,
isRowInViewport,
isCellInActiveBounds,
isCellInViewport
};
}
function getResolvedValues(position) {
return {
resolvedActivePosition: position,
validatedPosition: validatePosition(position)
};
}
function getActiveColumn() {
if (!validatedPosition.isCellInActiveBounds) throw new Error("No column for active position");
return columns[resolvedActivePosition.idx];
}
function getActiveRow() {
if (!validatedPosition.isPositionInViewport) throw new Error("No row for active position");
return rows[resolvedActivePosition.rowIdx];
}
let { resolvedActivePosition, validatedPosition } = getResolvedValues(activePosition);
if (!validatedPosition.isPositionInActiveBounds && resolvedActivePosition !== initialActivePosition) {
setActivePosition(initialActivePosition);
setDraggedOverRowIdx(void 0);
({resolvedActivePosition, validatedPosition} = getResolvedValues(initialActivePosition));
} else if (resolvedActivePosition.mode === "EDIT") {
if ((getActiveColumn().editorOptions?.closeOnExternalRowChange ?? true) && getActiveRow() !== resolvedActivePosition.originalRow) {
const newPosition = {
idx: resolvedActivePosition.idx,
rowIdx: resolvedActivePosition.rowIdx,
mode: "ACTIVE"
};
setActivePosition(newPosition);
setPositionToFocus(null);
({resolvedActivePosition, validatedPosition} = getResolvedValues(newPosition));
}
}
useLayoutEffect(() => {
if (positionToFocus !== null && positionToFocus !== positionToFocusRef.current) {
positionToFocusRef.current = positionToFocus;
if (positionToFocus.idx === -1) focusRow(gridRef.current);
else focusCell(gridRef.current);
}
}, [positionToFocus, gridRef]);
return {
activePosition: resolvedActivePosition,
setActivePosition,
setPositionToFocus,
activePositionIsInActiveBounds: validatedPosition.isPositionInActiveBounds,
activePositionIsInViewport: validatedPosition.isPositionInViewport,
activePositionIsRow: validatedPosition.isRowInActiveBounds,
activePositionIsCellInViewport: validatedPosition.isCellInViewport,
validatePosition,
getActiveColumn,
getActiveRow
};
}
//#endregion
//#region src/cellRenderers/renderCheckbox.tsx
const checkboxClassname = `rdg-checkbox-input rdg-7-0-0-beta-60-3b807ead`;
function renderCheckbox({ onChange, indeterminate, ...props }) {
function handleChange(e) {
onChange(e.target.checked, e.nativeEvent.shiftKey);
}
return /* @__PURE__ */ jsx("input", {
ref: (el) => {
if (el) el.indeterminate = indeterminate === true;
},
type: "checkbox",
className: checkboxClassname,
onChange: handleChange,
...props
});
}
//#endregion
//#region src/cellRenderers/renderToggleGroup.tsx
const groupCellContentClassname = `rdg-group-cell-content rdg-7-0-0-beta-60-07919382`;
const caretClassname = `rdg-caret rdg-7-0-0-beta-60-02a50147`;
function renderToggleGroup(props) {
return /* @__PURE__ */ jsx(ToggleGroup, { ...props });
}
function ToggleGroup({ groupKey, isExpanded, tabIndex, toggleGroup }) {
function handleKeyDown({ key }) {
if (key === "Enter") toggleGroup();
}
return /* @__PURE__ */ jsxs("span", {
className: groupCellContentClassname,
tabIndex,
onKeyDown: handleKeyDown,
children: [groupKey, /* @__PURE__ */ jsx("svg", {
viewBox: "0 0 14 8",
width: "14",
height: "8",
className: caretClassname,
"aria-hidden": true,
children: /* @__PURE__ */ jsx("path", { d: isExpanded ? "M1 1 L 7 7 L 13 1" : "M1 7 L 7 1 L 13 7" })
})]
});
}
//#endregion
//#region src/cellRenderers/renderValue.tsx
function renderValue(props) {
return props.row?.[props.column.key];
}
//#endregion
//#region src/DataGridDefaultRenderersContext.ts
const DataGridDefaultRenderersContext = createContext(void 0);
DataGridDefaultRenderersContext.displayName = "DataGridDefaultRenderersContext";
function useDefaultRenderers() {
return use(DataGridDefaultRenderersContext);
}
//#endregion
//#region src/cellRenderers/SelectCellFormatter.tsx
function SelectCellFormatter({ value, tabIndex, indeterminate, disabled, onChange, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy }) {
const renderCheckbox = useDefaultRenderers().renderCheckbox;
return renderCheckbox({
"aria-label": ariaLabel,
"aria-labelledby": ariaLabelledBy,
tabIndex,
indeterminate,
disabled,
checked: value,
onChange
});
}
//#endregion
//#region src/Columns.tsx
const SELECT_COLUMN_KEY = "rdg-select-column";
function HeaderRenderer({ tabIndex }) {
const { isIndeterminate, isRowSelected, onRowSelectionChange } = useHeaderRowSelection();
return /* @__PURE__ */ jsx(SelectCellFormatter, {
"aria-label": "Select All",
tabIndex,
indeterminate: isIndeterminate,
value: isRowSelected,
onChange: (checked) => {
onRowSelectionChange({ checked: isIndeterminate ? false : checked });
}
});
}
function SelectFormatter({ row, tabIndex }) {
const { isRowSelectionDisabled, isRowSelected, onRowSelectionChange } = useRowSelection();
return /* @__PURE__ */ jsx(SelectCellFormatter, {
"aria-label": "Select",
tabIndex,
disabled: isRowSelectionDisabled,
value: isRowSelected,
onChange: (checked, isShiftClick) => {
onRowSelectionChange({
row,
checked,
isShiftClick
});
}
});
}
function SelectGroupFormatter({ row, tabIndex }) {
const { isRowSelected, onRowSelectionChange } = useRowSelection();
return /* @__PURE__ */ jsx(SelectCellFormatter, {
"aria-label": "Select Group",
tabIndex,
value: isRowSelected,
onChange: (checked) => {
onRowSelectionChange({
row,
checked,
isShiftClick: false
});
}
});
}
const SelectColumn = {
key: SELECT_COLUMN_KEY,
name: "",
width: 35,
minWidth: 35,
maxWidth: 35,
resizable: false,
sortable: false,
frozen: true,
renderHeaderCell(props) {
return /* @__PURE__ */ jsx(HeaderRenderer, { ...props });
},
renderCell(props) {
return /* @__PURE__ */ jsx(SelectFormatter, { ...props });
},
renderGroupCell(props) {
return /* @__PURE__ */ jsx(SelectGroupFormatter, { ...props });
}
};
//#endregion
//#region src/renderHeaderCell.tsx
const headerSortCellClassname = "rdg-7-0-0-beta-60-56a248e4";
const headerSortNameClassname = `rdg-header-sort-name rdg-7-0-0-beta-60-7fad8c83`;
function renderHeaderCell({ column, sortDirection, priority }) {
if (!column.sortable) return column.name;
return /* @__PURE__ */ jsx(SortableHeaderCell, {
sortDirection,
priority,
children: column.name
});
}
function SortableHeaderCell({ sortDirection, priority, children }) {
const renderSortStatus = useDefaultRenderers().renderSortStatus;
return /* @__PURE__ */ jsxs("span", {
className: headerSortCellClassname,
children: [/* @__PURE__ */ jsx("span", {
className: headerSortNameClassname,
children
}), /* @__PURE__ */ jsx("span", { children: renderSortStatus({
sortDirection,
priority
}) })]
});
}
//#endregion
//#region src/hooks/useCalculatedColumns.ts
const DEFAULT_COLUMN_WIDTH = "auto";
const DEFAULT_COLUMN_MIN_WIDTH = 50;
function useCalculatedColumns({ rawColumns, defaultColumnOptions, getColumnWidth, viewportWidth, scrollLeft, enableVirtualization }) {
const defaultWidth = defaultColumnOptions?.width ?? DEFAULT_COLUMN_WIDTH;
const defaultMinWidth = defaultColumnOptions?.minWidth ?? DEFAULT_COLUMN_MIN_WIDTH;
const defaultMaxWidth = defaultColumnOptions?.maxWidth ?? void 0;
const defaultRenderCell = defaultColumnOptions?.renderCell ?? renderValue;
const defaultRenderHeaderCell = defaultColumnOptions?.renderHeaderCell ?? renderHeaderCell;
const defaultSortable = defaultColumnOptions?.sortable ?? false;
const defaultResizable = defaultColumnOptions?.resizable ?? false;
const defaultDraggable = defaultColumnOptions?.draggable ?? false;
const { columns, colSpanColumns, lastStartFrozenColumnIndex, firstEndFrozenColumnIndex, headerRowsCount } = useMemo(() => {
let lastStartFrozenColumnIndex = -1;
let firstEndFrozenColumnIndex = -1;
let headerRowsCount = 1;
const columns = [];
collectColumns(rawColumns, 1);
function collectColumns(rawColumns, level, parent) {
for (const rawColumn of rawColumns) {
if ("children" in rawColumn) {
const calculatedColumnParent = {
name: rawColumn.name,
parent,
idx: -1,
colSpan: 0,
level: 0,
headerCellClass: rawColumn.headerCellClass
};
collectColumns(rawColumn.children, level + 1, calculatedColumnParent);
continue;
}
const frozen = rawColumn.frozen ?? false;
columns.push({
...rawColumn,
parent,
idx: 0,
level: 0,
frozen,
width: rawColumn.width ?? defaultWidth,
minWidth: rawColumn.minWidth ?? defaultMinWidth,
maxWidth: rawColumn.maxWidth ?? defaultMaxWidth,
sortable: rawColumn.sortable ?? defaultSortable,
resizable: rawColumn.resizable ?? defaultResizable,
draggable: rawColumn.draggable ?? defaultDraggable,
renderCell: rawColumn.renderCell ?? defaultRenderCell,
renderHeaderCell: rawColumn.renderHeaderCell ?? defaultRenderHeaderCell
});
if (isStartFrozen(frozen)) lastStartFrozenColumnIndex++;
if (level > headerRowsCount) headerRowsCount = level;
}
}
columns.sort((a, b) => {
if (a.key === "rdg-select-column") return -1;
if (b.key === "rdg-select-column") return 1;
return (a.frozen === "end" ? 2 : a.frozen === false ? 1 : 0) - (b.frozen === "end" ? 2 : b.frozen === false ? 1 : 0);
});
const colSpanColumns = [];
columns.forEach((column, idx) => {
column.idx = idx;
updateColumnParent(column, idx, 0);
if (column.colSpan != null) colSpanColumns.push(column);
if (column.frozen === "end" && firstEndFrozenColumnIndex === -1) firstEndFrozenColumnIndex = idx;
});
return {
columns,
colSpanColumns,
lastStartFrozenColumnIndex,
firstEndFrozenColumnIndex,
headerRowsCount
};
}, [
rawColumns,
defaultWidth,
defaultMinWidth,
defaultMaxWidth,
defaultRenderCell,
defaultRenderHeaderCell,
defaultResizable,
defaultSortable,
defaultDraggable
]);
const { templateColumns, layoutCssVars, totalStartFrozenColumnWidth, totalEndFrozenColumnWidth, columnMetrics } = useMemo(() => {
const columnMetrics = /* @__PURE__ */ new Map();
let left = 0;
let totalStartFrozenColumnWidth = 0;
let totalEndFrozenColumnWidth = 0;
const templateColumns = [];
for (const column of columns) {
let width = getColumnWidth(column);
if (typeof width === "number") width = clampColumnWidth(width, column);
else width = column.minWidth;
templateColumns.push(`${width}px`);
columnMetrics.set(column, {
width,
left
});
left += width;
}
if (lastStartFrozenColumnIndex !== -1) {
const lastStartFrozenColumnMetric = columnMetrics.get(columns[lastStartFrozenColumnIndex]);
totalStartFrozenColumnWidth = lastStartFrozenColumnMetric.left + lastStartFrozenColumnMetric.width;
}
const layoutCssVars = {};
for (let i = 0; i <= lastStartFrozenColumnIndex; i++) {
const column = columns[i];
layoutCssVars[`--rdg-frozen-start-${column.idx}`] = `${columnMetrics.get(column).left}px`;
}
if (firstEndFrozenColumnIndex !== -1) {
const lastColumn = columns[columns.length - 1];
const lastColumnMetric = columnMetrics.get(lastColumn);
const gridEnd = lastColumnMetric.left + lastColumnMetric.width;
totalEndFrozenColumnWidth = gridEnd - columnMetrics.get(columns[firstEndFrozenColumnIndex]).left;
for (let i = firstEndFrozenColumnIndex; i < columns.length; i++) {
const column = columns[i];
const metric = columnMetrics.get(column);
layoutCssVars[`--rdg-frozen-end-${column.idx}`] = `${gridEnd - (metric.left + metric.width)}px`;
}
}
return {
templateColumns,
layoutCssVars,
totalStartFrozenColumnWidth,
totalEndFrozenColumnWidth,
columnMetrics
};
}, [
getColumnWidth,
columns,
lastStartFrozenColumnIndex,
firstEndFrozenColumnIndex
]);
const [colOverscanStartIdx, colOverscanEndIdx] = useMemo(() => {
if (!enableVirtualization) return [0, columns.length - 1];
const viewportLeft = scrollLeft + totalStartFrozenColumnWidth;
const viewportRight = scrollLeft + viewportWidth - totalEndFrozenColumnWidth;
const lastColIdx = columns.length - 1;
const firstUnfrozenColumnIdx = min(lastStartFrozenColumnIndex + 1, lastColIdx);
if (viewportLeft >= viewportRight) return [firstUnfrozenColumnIdx, firstUnfrozenColumnIdx];
let colVisibleStartIdx = firstUnfrozenColumnIdx;
while (colVisibleStartIdx < lastColIdx) {
const { left, width } = columnMetrics.get(columns[colVisibleStartIdx]);
if (left + width > viewportLeft) break;
colVisibleStartIdx++;
}
let colVisibleEndIdx = colVisibleStartIdx;
while (colVisibleEndIdx < lastColIdx) {
const { left, width } = columnMetrics.get(columns[colVisibleEndIdx]);
if (left + width >= viewportRight) break;
colVisibleEndIdx++;
}
return [max(firstUnfrozenColumnIdx, colVisibleStartIdx - 1), min(lastColIdx, colVisibleEndIdx + 1)];
}, [
columnMetrics,
columns,
lastStartFrozenColumnIndex,
scrollLeft,
totalStartFrozenColumnWidth,
totalEndFrozenColumnWidth,
viewportWidth,
enableVirtualization
]);
return {
columns,
colSpanColumns,
colOverscanStartIdx,
colOverscanEndIdx,
templateColumns,
layoutCssVars,
headerRowsCount,
lastStartFrozenColumnIndex,
firstEndFrozenColumnIndex,
totalStartFrozenColumnWidth,
totalEndFrozenColumnWidth
};
}
function updateColumnParent(column, index, level) {
if (level < column.level) column.level = level;
if (column.parent !== void 0) {
const { parent } = column;
if (parent.idx === -1) parent.idx = index;
parent.colSpan += 1;
updateColumnParent(parent, index, level - 1);
}
}
//#endregion
//#region src/hooks/useColumnWidths.ts
function useColumnWidths(columns, viewportColumns, templateColumns, gridRef, gridWidth, columnWidths, onColumnWidthsChange, onColumnResize, setColumnResizing) {
const [columnToAutoResize, setColumnToAutoResize] = useState(null);
const [columnsToMeasureOnResize, setColumnsToMeasureOnResize] = useState(null);
const [prevGridWidth, setPrevGridWidth] = useState(gridWidth);
const columnsCanFlex = columns.length === viewportColumns.length;
const ignorePreviouslyMeasuredColumnsOnGridWidthChange = columnsCanFlex && gridWidth !== prevGridWidth;
const newTemplateColumns = [...templateColumns];
const columnsToMeasure = [];
for (const { key, idx, width } of viewportColumns) {
const columnWidth = columnWidths.get(key);
if (key === columnToAutoResize?.key) {
newTemplateColumns[idx] = columnToAutoResize.width === "max-content" ? columnToAutoResize.width : `${columnToAutoResize.width}px`;
columnsToMeasure.push(key);
} else if (typeof width === "string" && columnWidth?.type !== "resized" && (ignorePreviouslyMeasuredColumnsOnGridWidthChange || columnsToMeasureOnResize?.has(key) === true || columnWidth === void 0)) {
newTemplateColumns[idx] = width;
columnsToMeasure.push(key);
}
}
const gridTemplateColumns = newTemplateColumns.join(" ");
useLayoutEffect(updateMeasuredAndResizedWidths);
function updateMeasuredAndResizedWidths() {
setPrevGridWidth(gridWidth);
if (columnsToMeasure.length === 0) return;
const newColumnWidths = new Map(columnWidths);
let hasChanges = false;
for (const key of columnsToMeasure) {
const measuredWidth = measureColumnWidth(gridRef, key);
hasChanges ||= measuredWidth !== columnWidths.get(key)?.width;
if (measuredWidth === void 0) newColumnWidths.delete(key);
else newColumnWidths.set(key, {
type: "measured",
width: measuredWidth
});
}
if (columnToAutoResize !== null) {
const resizingKey = columnToAutoResize.key;
const oldWidth = columnWidths.get(resizingKey)?.width;
const newWidth = measureColumnWidth(gridRef, resizingKey);
if (newWidth !== void 0 && oldWidth !== newWidth) {
hasChanges = true;
newColumnWidths.set(resizingKey, {
type: "resized",
width: newWidth
});
}
setColumnToAutoResize(null);
}
if (hasChanges) onColumnWidthsChange(newColumnWidths);
}
function handleColumnResize(column, nextWidth) {
const { key: resizingKey } = column;
flushSync(() => {
if (columnsCanFlex) {
const columnsToRemeasure = /* @__PURE__ */ new Set();
for (const { key, width } of viewportColumns) if (resizingKey !== key && typeof width === "string" && columnWidths.get(key)?.type !== "resized") columnsToRemeasure.add(key);
setColumnsToMeasureOnResize(columnsToRemeasure);
}
setColumnToAutoResize({
key: resizingKey,
width: nextWidth
});
setColumnResizing(typeof nextWidth === "number");
});
setColumnsToMeasureOnResize(null);
if (onColumnResize) {
const previousWidth = columnWidths.get(resizingKey)?.width;
const newWidth = typeof nextWidth === "number" ? nextWidth : measureColumnWidth(gridRef, resizingKey);
if (newWidth !== void 0 && newWidth !== previousWidth) onColumnResize(column, newWidth);
}
}
return {
gridTemplateColumns,
handleColumnResize
};
}
function measureColumnWidth(gridRef, key) {
const selector = `[data-measuring-cell-key="${CSS.escape(key)}"]`;
return (gridRef.current?.querySelector(selector))?.getBoundingClientRect().width;
}
//#endregion
//#region src/hooks/useGridDimensions.ts
const initialSize = {
inlineSize: 1,
blockSize: 1
};
const sizeMap = /* @__PURE__ */ new WeakMap();
const targetToRefMap = /* @__PURE__ */ new WeakMap();
const subscribers = /* @__PURE__ */ new Map();
const resizeObserver = globalThis.ResizeObserver == null ? null : new ResizeObserver(resizeObserverCallback);
function resizeObserverCallback(entries) {
for (const entry of entries) {
const target = entry.target;
if (targetToRefMap.has(target)) updateSize(targetToRefMap.get(target), entry.contentBoxSize[0]);
}
}
function updateSize(ref, size) {
if (sizeMap.has(ref)) {
const prevSize = sizeMap.get(ref);
if (prevSize.inlineSize === size.inlineSize && prevSize.blockSize === size.blockSize) return;
}
sizeMap.set(ref, size);
subscribers.get(ref)?.();
}
function getServerSnapshot$1() {
return initialSize;
}
function useGridDimensions(gridRef) {
const { inlineSize, blockSize } = useSyncExternalStore(useCallback((onStoreChange) => {
subscribers.set(gridRef, onStoreChange);
return () => {
subscribers.delete(gridRef);
};
}, [gridRef]), useCallback(() => {
return sizeMap.get(gridRef) ?? initialSize;
}, [gridRef]), getServerSnapshot$1);
useLayoutEffect(() => {
const target = gridRef.current;
targetToRefMap.set(target, gridRef);
resizeObserver?.observe(target);
if (!sizeMap.has(gridRef)) updateSize(gridRef, {
inlineSize: target.clientWidth,
blockSize: target.clientHeight
});
return () => {
resizeObserver?.unobserve(target);
};
}, [gridRef]);
return [inlineSize, blockSize];
}
//#endregion
//#region src/hooks/useLatestFunc.ts
function useLatestFunc(fn) {
const ref = useRef(fn);
useLayoutEffect(() => {
ref.current = fn;
});
const callbackFn = useCallback((...args) => {
ref.current(...args);
}, []);
return fn ? callbackFn : fn;
}
//#endregion
//#region src/hooks/useRovingTabIndex.ts
function useRovingTabIndex(isActive) {
const [isChildFocused, setIsChildFocused] = useState(false);
if (isChildFocused && !isActive) setIsChildFocused(false);
function onFocus(event) {
if (event.target === event.currentTarget) {
const elementToFocus = event.currentTarget.querySelector("[tabindex=\"0\"]");
if (elementToFocus !== null) {
elementToFocus.focus({ preventScroll: true });
setIsChildFocused(true);
} else setIsChildFocused(false);
} else setIsChildFocused(true);
}
return {
tabIndex: isActive && !isChildFocused ? 0 : -1,
childTabIndex: isActive ? 0 : -1,
onFocus: isActive ? onFocus : void 0
};
}
//#endregion
//#region src/hooks/useRowSelection.ts
const RowSelectionContext = createContext(void 0);
RowSelectionContext.displayName = "RowSelectionContext";
const RowSelectionChangeContext = createContext(void 0);
RowSelectionChangeContext.displayName = "RowSelectionChangeContext";
function useRowSelection() {
const rowSelectionContext = use(RowSelectionContext);
const rowSelectionChangeContext = use(RowSelectionChangeContext);
if (rowSelectionContext === void 0 || rowSelectionChangeContext === void 0) throw new Error("useRowSelection must be used within renderCell");
return {
isRowSelectionDisabled: rowSelectionContext.isRowSelectionDisabled,
isRowSelected: rowSelectionContext.isRowSelected,
onRowSelectionChange: rowSelectionChangeContext
};
}
const HeaderRowSelectionContext = createContext(void 0);
HeaderRowSelectionContext.displayName = "HeaderRowSelectionContext";
const HeaderRowSelectionChangeContext = createContext(void 0);
HeaderRowSelectionChangeContext.displayName = "HeaderRowSelectionChangeContext";
function useHeaderRowSelection() {
const headerRowSelectionContext = use(HeaderRowSelectionContext);
const headerRowSelectionChangeContext = use(HeaderRowSelectionChangeContext);
if (headerRowSelectionContext === void 0 || headerRowSelectionChangeContext === void 0) throw new Error("useHeaderRowSelection must be used within renderHeaderCell");
return {
isIndeterminate: headerRowSelectionContext.isIndeterminate,
isRowSelected: headerRowSelectionContext.isRowSelected,
onRowSelectionChange: headerRowSelectionChangeContext
};
}
//#endregion
//#region src/hooks/useScrollState.ts
const initialScrollState = {
scrollTop: 0,
scrollLeft: 0
};
function getServerSnapshot() {
return initialScrollState;
}
const scrollStateMap = /* @__PURE__ */ new WeakMap();
function useScrollState(gridRef) {
return useSyncExternalStore(useCallback((onStoreChange) => {
if (gridRef.current === null) return () => {};
const el = gridRef.current;
setScrollState();
function setScrollState() {
const { scrollTop } = el;
const scrollLeft = abs(el.scrollLeft);
const prev = scrollStateMap.get(gridRef) ?? initialScrollState;
if (prev.scrollTop === scrollTop && prev.scrollLeft === scrollLeft) return false;
scrollStateMap.set(gridRef, {
scrollTop,
scrollLeft
});
return true;
}
function onScroll() {
if (setScrollState()) onStoreChange();
}
el.addEventListener("scroll", onScroll);
return () => el.removeEventListener("scroll", onScroll);
}, [gridRef]), useCallback(() => {
return scrollStateMap.get(gridRef) ?? initialScrollState;
}, [gridRef]), getServerSnapshot);
}
//#endregion
//#region src/hooks/useScrollToPosition.tsx
function useScrollToPosition({ gridRef }) {
const [scrollToPosition, setScrollToPosition] = useState(null);
return {
setScrollToPosition,
scrollToPositionElement: scrollToPosition && /* @__PURE__ */ jsx("div", {
ref: (div) => {
if (div === null) return;
const grid = gridRef.current;
const { scrollLeft, scrollTop } = grid;
scrollIntoView(div, "auto");
if (grid.scrollLeft === scrollLeft && grid.scrollTop === scrollTop) setScrollToPosition(null);
},
style: {
gridColumn: scrollToPosition.idx == null ? "1/-1" : scrollToPosition.idx + 1,
gridRow: scrollToPosition.rowIdx == null ? "1/-1" : scrollToPosition.rowIdx + 1
}
})
};
}
//#endregion
//#region src/hooks/useViewportColumns.ts
function useViewportColumns({ columns, colSpanColumns, rows, topSummaryRows, bottomSummaryRows, colOverscanStartIdx, colOverscanEndIdx, lastStartFrozenColumnIndex, firstEndFrozenColumnIndex, rowOverscanStartIdx, rowOverscanEndIdx }) {
const startIdx = useMemo(() => {
if (colOverscanStartIdx === 0) return 0;
function* iterateOverRowsForColSpanArgs() {
yield { type: "HEADER" };
if (topSummaryRows != null) for (const row of topSummaryRows) yield {
type: "SUMMARY",
row
};
for (let rowIdx = rowOverscanStartIdx; rowIdx <= rowOverscanEndIdx; rowIdx++) yield {
type: "ROW",
row: rows[rowIdx]
};
if (bottomSummaryRows != null) for (const row of bottomSummaryRows) yield {
type: "SUMMARY",
row
};
}
for (const column of colSpanColumns) {
if (column.frozen) continue;
const colIdx = column.idx;
if (colIdx >= colOverscanStartIdx) break;
for (const args of iterateOverRowsForColSpanArgs()) {
const colSpan = getColSpan(column, lastStartFrozenColumnIndex, firstEndFrozenColumnIndex, args);
if (colSpan !== void 0 && colIdx + colSpan > colOverscanStartIdx) return colIdx;
}
}
return colOverscanStartIdx;
}, [
rowOverscanStartIdx,
rowOverscanEndIdx,
rows,
topSummaryRows,
bottomSummaryRows,
colOverscanStartIdx,
lastStartFrozenColumnIndex,
firstEndFrozenColumnIndex,
colSpanColumns
]);
const effectiveOverscanEndIdx = firstEndFrozenColumnIndex > -1 ? Math.min(colOverscanEndIdx, firstEndFrozenColumnIndex - 1) : colOverscanEndIdx;
const iterateOverViewportColumns = useCallback(function* (activeColumnIdx) {
for (let colIdx = 0; colIdx <= lastStartFrozenColumnIndex; colIdx++) yield columns[colIdx];
const unfrozenLastIdx = firstEndFrozenColumnIndex > -1 ? firstEndFrozenColumnIndex - 1 : columns.length - 1;
if (lastStartFrozenColumnIndex < unfrozenLastIdx) {
if (activeColumnIdx > lastStartFrozenColumnIndex && activeColumnIdx < startIdx) yield columns[activeColumnIdx];
for (let colIdx = startIdx; colIdx <= effectiveOverscanEndIdx; colIdx++) yield columns[colIdx];
if (activeColumnIdx > effectiveOverscanEndIdx && activeColumnIdx <= unfrozenLastIdx) yield columns[activeColumnIdx];
}
if (firstEndFrozenColumnIndex > -1) for (let colIdx = firstEndFrozenColumnIndex; colIdx < columns.length; colIdx++) yield columns[colIdx];
}, [
startIdx,
effectiveOverscanEndIdx,
columns,
lastStartFrozenColumnIndex,
firstEndFrozenColumnIndex
]);
const iterateOverViewportColumnsForRow = useCallback(function* (activeColumnIdx = -1, args) {
const iterator = iterateOverViewportColumns(activeColumnIdx);
for (const column of iterator) {
let colSpan = args && getColSpan(column, lastStartFrozenColumnIndex, firstEndFrozenColumnIndex, args);
yield [
column,
column.idx === activeColumnIdx,
colSpan
];
while (colSpan !== void 0 && colSpan > 1) {
iterator.next();
colSpan--;
}
}
}, [
iterateOverViewportColumns,
lastStartFrozenColumnIndex,
firstEndFrozenColumnIndex
]);
const iterateOverViewportColumnsForRowOutsideOfViewport = useCallback(function* (activeColumnIdx = -1, args) {
if (activeColumnIdx >= 0 && activeColumnIdx < columns.length) {
const column = columns[activeColumnIdx];
yield [
column,
true,
args && getColSpan(column, lastStartFrozenColumnIndex, firstEndFrozenColumnIndex, args)
];
}
}, [
columns,
lastStartFrozenColumnIndex,
firstEndFrozenColumnIndex
]);
return {
viewportColumns: useMemo(() => {
return iterateOverViewportColumns(-1).toArray();
}, [iterateOverViewportColumns]),
iterateOverViewportColumnsForRow,
iterateOverViewportColumnsForRowOutsideOfViewport
};
}
//#endregion
//#region src/hooks/useViewportRows.ts
function useViewportRows({ rows, rowHeight, clientHeight, scrollTop, enableVirtualization }) {
const { totalRowHeight, gridTemplateRows, getRowTop, getRowHeight, findRowIdx } = useMemo(() => {
if (typeof rowHeight === "number") return {
totalRowHeight: rowHeight * rows.length,
gridTemplateRows: ` repeat(${rows.length}, ${rowHeight}px)`,
getRowTop: (rowIdx) => rowIdx * rowHeight,
getRowHeight: () => rowHeight,
findRowIdx: (offset) => floor(offset / rowHeight)
};
let totalRowHeight = 0;
let gridTemplateRows = "";
let currentHeight = null;
let repeatCount = 0;
const rowPositions = rows.map((row, index) => {
const currentRowHeight = rowHeight(row);
const position = {
top: totalRowHeight,
height: currentRowHeight
};
totalRowHeight += currentRowHeight;
if (currentHeight === null) {
currentHeight = currentRowHeight;
repeatCount = 1;
} else if (currentHeight === currentRowHeight) repeatCount++;
else {
if (repeatCount > 1) gridTemplateRows += `repeat(${repeatCount}, ${currentHeight}px) `;
else gridTemplateRows += `${currentHeight}px `;
currentHeight = currentRowHeight;
repeatCount = 1;
}
if (index === rows.length - 1) if (repeatCount > 1) gridTemplateRows += `repeat(${repeatCount}, ${currentHeight}px)`;
else gridTemplateRows += `${currentHeight}px`;
return position;
});
const validateRowIdx = (rowIdx) => {
return max(0, min(rows.length - 1, rowIdx));
};
return {
totalRowHeight,
gridTemplateRows,
getRowTop: (rowIdx) => rowPositions[validateRowIdx(rowIdx)].top,
getRowHeight: (rowIdx) => rowPositions[validateRowIdx(rowIdx)].height,
findRowIdx(offset) {
let start = 0;
let end = rowPositions.length - 1;
while (start <= end) {
const middle = start + floor((end - start) / 2);
const currentOffset = rowPositions[middle].top;
if (currentOffset === offset) return middle;
if (currentOffset < offset) start = middle + 1;
else if (currentOffset > offset) end = middle - 1;
if (start > end) return end;
}
return 0;
}
};
}, [rowHeight, rows]);
let rowOverscanStartIdx = 0;
let rowOverscanEndIdx = rows.length - 1;
if (enableVirtualization) {
const overscanThreshold = 4;
const rowVisibleStartIdx = findRowIdx(scrollTop);
const rowVisibleEndIdx = findRowIdx(scrollTop + clientHeight);
rowOverscanStartIdx = max(0, rowVisibleStartIdx - overscanThreshold);
rowOverscanEndIdx = min(rows.length - 1, rowVisibleEndIdx + overscanThreshold);
}
return {
rowOverscanStartIdx,
rowOverscanEndIdx,
totalRowHeight,
gridTemplateRows,
getRowTop,
getRowHeight,
findRowIdx
};
}
//#endregion
//#region src/Cell.tsx
const cellDraggedOverClassname = `rdg-cell-dragged-over rdg-7-0-0-beta-60-35ccb4c8`;
function Cell({ column, colSpan, isCellActive, isDraggedOver, row, rowIdx, className, onMouseDown, onCellMouseDown, onClick, onCellClick, onDoubleClick, onCellDoubleClick, onContextMenu, onCellContextMenu, onRowChange, setActivePosition, style, ...props }) {
const { tabIndex, childTabIndex, onFocus } = useRovingTabIndex(isCellActive);
const { cellClass } = column;
className = getCellClassname(column, isDraggedOver && cellDraggedOverClassname, typeof cellClass === "function" ? cellClass(row) : cellClass, className);
const isEditable = isCellEditableUtil(column, row);
function setActivePositionWrapper(enableEditor = false) {
setActivePosition({
rowIdx,
idx: column.idx
}, { enableEditor });
}
function handleMouseEvent(event, eventHandler) {
let eventHandled = false;
if (eventHandler) {
const cellEvent = createCellEvent(event);
eventHandler({
rowIdx,
row,
column,
setActivePosition: setActivePositionWrapper
}, cellEvent);
eventHandled = cellEvent.isGridDefaultPrevented();
}
return eventHandled;
}
function handleMouseDown(event) {
onMouseDown?.(event);
if (!handleMouseEvent(event, onCellMouseDown)) setActivePositionWrapper();
}
function handleClick(event) {
onClick?.(event);
handleMouseEvent(event, onCellClick);
}
function handleDoubleClick(event) {
onDoubleClick?.(event);
if (!handleMouseEvent(event, onCellDoubleClick)) setActivePositionWrapper(true);
}
function handleContextMenu(event) {
onContextMenu?.(event);
handleMouseEvent(event, onCellContextMenu);
}
function handleRowChange(newRow) {
onRowChange(column, rowIdx, newRow);
}
return /* @__PURE__ */ jsx("div", {
role: "gridcell",
"aria-colindex": column.idx + 1,
"aria-colspan": colSpan,
"aria-selected": isCellActive,
"aria-readonly": !isEditable || void 0,
tabIndex,
className,
style: {
...getCellStyle(column, colSpan),
...style
},
onClick: handleClick,
onMouseDown: handleMouseDown,
onDoubleClick: handleDoubleClick,
onContextMenu: handleContextMenu,
onFocus,
...props,
children: column.renderCell({
column,
row,
rowIdx,
isCellEditable: isEditable,
tabIndex: childTabIndex,
onRowChange: handleRowChange
})
});
}
const CellComponent = memo(Cell);
function defaultRenderCell(key, props) {
return /* @__PURE__ */ jsx(CellComponent, { ...props }, key);
}
//#endregion
//#region src/EditCell.tsx
const canUsePostTask = typeof scheduler === "object" && typeof scheduler.postTask === "function";
const cellEditing = "rdg-7-0-0-beta-60-46f9ea88";
function EditCell({ column, colSpan, row, rowIdx, onRowChange, closeEditor, onKeyDown, navigate }) {
const captureEventRef = useRef(void 0);
const abortControllerRef = useRef(void 0);
const frameRequestRef = useRef(void 0);
const commitOnOutsideClick = column.editorOptions?.commitOnOutsideClick ?? true;
const commitOnOutsideMouseDown = useEffectEvent(() => {
onClose(true, false);
});
useLayoutEffect(() => {
if (!commitOnOutsideClick) return;
function onWindowCaptureMouseDown(event) {
captureEventRef.current = event;
if (canUsePostTask) {
const abortController = new AbortController();
const { signal } = abortController;
abortControllerRef.current = abortController;
scheduler.postTask(commitOnOutsideMouseDown, {
priority: "user-blocking",
signal
}).catch(() => {});
} else frameRequestRef.current = requestAnimationFrame(commitOnOutsideMouseDown);
}
function onWindowMouseDown(event) {
if (captureEventRef.current === event) commitOnOutsideMouseDown();
}
window.addEventListener("mousedown", onWindowCaptureMouseDown, { capture: true });
window.addEventListener("mousedown", onWindowMouseDown);
return () => {
window.removeEventListener("mousedown", onWindowCaptureMouseDown, { capture: true });
window.removeEventListener("mousedown", onWindowMouseDown);
cancelTask();
};
}, [commitOnOutsideClick]);
function cancelTask() {
captureEventRef.current = void 0;
if (abortControllerRef.current !== void 0) {
abortControllerRef.current.abort();
abortControllerRef.current = void 0;
}
if (frameRequestRef.current !== void 0) {
cancelAnimationFrame(frameRequestRef.current);
frameRequestRef.current = void 0;
}
}
function handleKeyDown(event) {
if (onKeyDown) {
const cellEvent = createCellEvent(event);
onKeyDown({
mode: "EDIT",
row,
column,
rowIdx,
navigate() {
navigate(event);
},
onClose
}, cellEvent);
if (cellEvent.isGridDefaultPrevented()) return;
}
if (event.key === "Escape") onClose();
else if (event.key === "Enter") onClose(true);
else if (onEditorNavigation(event)) navigate(event);
}
function onClose(commitChanges = false, shouldFocus = true) {
if (commitChanges) onRowChange(row, true, shouldFocus);
else closeEditor(shouldFocus);
}
function onEditorRowChange(row, commitChangesAndFocus = false) {
onRowChange(row, commitChangesAndFocus, commitChangesAndFocus);
}
const { cellClass } = column;
const className = getCellClassname(column, "rdg-editor-container", !column.editorOptions?.displayCellContent && cellEditing, typeof cellClass === "function" ? cellClass(row) : cellClass);
return /* @__PURE__ */ jsx("div", {
role: "gridcell",
"aria-colindex": column.idx + 1,
"aria-colspan": colSpan,
"aria-selected": true,
className,
style: getCellStyle(column, colSpan),
onKeyDown: handleKeyDown,
onMouseDownCapture: cancelTask,
children: column.renderEditCell != null && /* @__PURE__ */ jsxs(Fragment, { children: [column.renderEditCell({
column,
row,
rowIdx,
onRowChange: onEditorRowChange,
onClose
}), column.editorOptions?.displayCellContent && column.renderCell({
column,
row,
rowIdx,
isCellEditable: true,
tabIndex: -1,
onRowChange: onEditorRowChange
})] })
});
}
//#endregion
//#region src/GroupedColumnHeaderCell.tsx
function GroupedColumnHeaderCell({ column, rowIdx, isCellActive, setPosition }) {
const { tabIndex, onFocus } = useRovingTabIndex(isCellActive);
const { colSpan } = column;
const rowSpan = getHeaderCellRowSpan(column, rowIdx);
const index = column.idx + 1;
function onMouseDown() {
setPosition({
idx: column.idx,
rowIdx
});
}
return /* @__PURE__ */ jsx("div", {
role: "columnheader",
"aria-colindex": index,
"aria-colspan": colSpan,
"aria-rowspan": rowSpan,
"aria-selected": isCellActive,
tabIndex,
className: classnames(cellClassname, column.headerCellClass),
style: {
...getHeaderCellStyle(column, rowIdx, rowSpan),
gridColumnStart: index,
gridColumnEnd: index + colSpan
},
onFocus,
onMouseDown,
children: column.name
});
}
//#endregion
//#region src/HeaderCell.tsx
const cellSortableClassname = "rdg-7-0-0-beta-60-2a7e240d";
const cellResizableClassname = `rdg-cell-resizable rdg-7-0-0-beta-60-1893dc0f`;
const resizeHandleClassname = `rdg-resize-handle rdg-7-0-0-beta-60-4e60db91`;
const cellDraggableClassname = "rdg-cell-draggable";
const cellDraggingOrOver = "rdg-7-0-0-beta-60-f2d18717";
const cellDraggingClassname = `rdg-cell-dragging ${cellDraggingOrOver}`;
const cellOverClassname = `rdg-cell-drag-over ${cellDraggingOrOver}`;
const dragImageClassname = "rdg-7-0-0-beta-60-3d12c7ae";
function HeaderCell({ column, colSpan, rowIdx, isCellActive, onColumnResize, onColumnResizeEnd, onColumnsReorder, sortColumns, onSortColumnsChange, setPosition, shouldFocusGrid, direction, draggedColumnKey, setDraggedColumnKey }) {
const [isOver, setIsOver] = useState(false);
const dragImageRef = useRef(null);
const isDragging = draggedColumnKey === column.key;
const rowSpan = getHeaderCellRowSpan(column, rowIdx);
const { tabIndex, childTabIndex, onFocus } = useRovingTabIndex(shouldFocusGrid || isCellActive);
const sortIndex = sortColumns?.findIndex((sort) => sort.columnKey === column.key);
const sortColumn = sortIndex !== void 0 && sortIndex > -1 ? sortColumns[sortIndex] : void 0;
const sortDirection = sortColumn?.direction;
const priority = sortColumn !== void 0 && sortColumns.length > 1 ? sortIndex + 1 : void 0;
const ariaSort = sortDirection && !priority ? sortDirection === "ASC" ? "ascending" : "descending" : void 0;
const { sortable, resizable, draggable } = column;
const className = getCel