UNPKG

react-data-grid

Version:

Feature-rich and customizable data grid React component

1,712 lines (1,677 loc) • 102 kB
'use strict'; Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } }); const react = require('react'); const reactDom = require('react-dom'); const clsx = require('clsx'); const jsxRuntime = require('react/jsx-runtime'); function getColSpan(column, lastFrozenColumnIndex, args) { const colSpan = typeof column.colSpan === 'function' ? column.colSpan(args) : 1; if (Number.isInteger(colSpan) && colSpan > 1 && (!column.frozen || column.idx + colSpan - 1 <= lastFrozenColumnIndex)) { return colSpan; } return undefined; } function stopPropagation(event) { event.stopPropagation(); } function scrollIntoView(element) { element?.scrollIntoView({ inline: 'nearest', block: 'nearest' }); } function createCellEvent(event) { let defaultPrevented = false; const cellEvent = { ...event, preventGridDefault() { defaultPrevented = true; }, isGridDefaultPrevented() { return defaultPrevented; } }; Object.setPrototypeOf(cellEvent, Object.getPrototypeOf(event)); return cellEvent; } const nonInputKeys = 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'; } function isDefaultCellInput(event) { const vKey = 86; if (isCtrlKeyHeldDown(event) && event.keyCode !== vKey) return false; return !nonInputKeys.has(event.key); } 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; } const measuringCellClassname = "mlln6zg7-0-0-beta-44"; function renderMeasuringCells(viewportColumns) { return viewportColumns.map(({ key, idx, minWidth, maxWidth }) => /*#__PURE__*/jsxRuntime.jsx("div", { className: measuringCellClassname, style: { gridColumnStart: idx + 1, minWidth, maxWidth }, "data-measuring-cell-key": key }, key)); } function isSelectedCellEditable({ selectedPosition, columns, rows }) { const column = columns[selectedPosition.idx]; const row = rows[selectedPosition.rowIdx]; return isCellEditableUtil(column, row); } function isCellEditableUtil(column, row) { return column.renderEditCell != null && (typeof column.editable === 'function' ? column.editable(row) : column.editable) !== false; } function getSelectedCellColSpan({ rows, topSummaryRows, bottomSummaryRows, rowIdx, mainHeaderRowIdx, lastFrozenColumnIndex, column }) { const topSummaryRowsCount = topSummaryRows?.length ?? 0; if (rowIdx === mainHeaderRowIdx) { return getColSpan(column, lastFrozenColumnIndex, { type: 'HEADER' }); } if (topSummaryRows && rowIdx > mainHeaderRowIdx && rowIdx <= topSummaryRowsCount + mainHeaderRowIdx) { return getColSpan(column, lastFrozenColumnIndex, { type: 'SUMMARY', row: topSummaryRows[rowIdx + topSummaryRowsCount] }); } if (rowIdx >= 0 && rowIdx < rows.length) { const row = rows[rowIdx]; return getColSpan(column, lastFrozenColumnIndex, { type: 'ROW', row }); } if (bottomSummaryRows) { return getColSpan(column, lastFrozenColumnIndex, { type: 'SUMMARY', row: bottomSummaryRows[rowIdx - rows.length] }); } return undefined; } function getNextSelectedCellPosition({ moveUp, moveNext, cellNavigationMode, columns, colSpanColumns, rows, topSummaryRows, bottomSummaryRows, minRowIdx, mainHeaderRowIdx, maxRowIdx, currentPosition: { idx: currentIdx, rowIdx: currentRowIdx }, nextPosition, lastFrozenColumnIndex, isCellWithinBounds }) { 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 = getSelectedCellColSpan({ rows, topSummaryRows, bottomSummaryRows, rowIdx: nextRowIdx, mainHeaderRowIdx, lastFrozenColumnIndex, 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) { const nextColumn = columns[nextIdx]; let parent = nextColumn.parent; while (parent !== undefined) { const parentRowIdx = getParentRowIdx(parent); if (nextRowIdx === parentRowIdx) { nextIdx = parent.idx + parent.colSpan; break; } parent = parent.parent; } } else if (moveUp) { const nextColumn = columns[nextIdx]; let parent = nextColumn.parent; let found = false; while (parent !== undefined) { const parentRowIdx = getParentRowIdx(parent); if (nextRowIdx >= parentRowIdx) { nextIdx = parent.idx; nextRowIdx = parentRowIdx; found = true; break; } parent = parent.parent; } if (!found) { nextIdx = currentIdx; nextRowIdx = currentRowIdx; } } }; if (isCellWithinBounds(nextPosition)) { setColSpan(moveNext); if (nextRowIdx < mainHeaderRowIdx) { setHeaderGroupColAndRowSpan(); } } if (cellNavigationMode === 'CHANGE_ROW') { const isAfterLastColumn = nextIdx === columnsCount; const isBeforeFirstColumn = nextIdx === -1; if (isAfterLastColumn) { const isLastRow = nextRowIdx === maxRowIdx; if (!isLastRow) { nextIdx = 0; nextRowIdx += 1; } } else if (isBeforeFirstColumn) { const isFirstRow = nextRowIdx === minRowIdx; if (!isFirstRow) { nextRowIdx -= 1; nextIdx = columnsCount - 1; } setColSpan(false); } } if (nextRowIdx < mainHeaderRowIdx) { const nextColumn = columns[nextIdx]; let parent = nextColumn.parent; const nextParentRowIdx = nextRowIdx; nextRowIdx = mainHeaderRowIdx; while (parent !== undefined) { const parentRowIdx = getParentRowIdx(parent); if (parentRowIdx >= nextParentRowIdx) { nextRowIdx = parentRowIdx; nextIdx = parent.idx; } parent = parent.parent; } } return { idx: nextIdx, rowIdx: nextRowIdx }; } function canExitGrid({ maxColIdx, minRowIdx, maxRowIdx, selectedPosition: { rowIdx, idx }, shiftKey }) { const atLastCellInRow = idx === maxColIdx; const atFirstCellInRow = idx === 0; const atLastRow = rowIdx === maxRowIdx; const atFirstRow = rowIdx === minRowIdx; return shiftKey ? atFirstCellInRow && atFirstRow : atLastCellInRow && atLastRow; } const cell = "cj343x07-0-0-beta-44"; const cellClassname = `rdg-cell ${cell}`; const cellFrozen = "csofj7r7-0-0-beta-44"; const cellFrozenClassname = `rdg-cell-frozen ${cellFrozen}`; function getRowStyle(rowIdx, height) { if (height !== undefined) { return { '--rdg-grid-row-start': rowIdx, '--rdg-row-height': `${height}px` }; } return { '--rdg-grid-row-start': rowIdx }; } function getHeaderCellStyle(column, rowIdx, rowSpan) { const gridRowEnd = rowIdx + 1; const paddingBlockStart = `calc(${rowSpan - 1} * var(--rdg-header-row-height))`; if (column.parent === undefined) { 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: column.frozen ? `var(--rdg-frozen-left-${column.idx})` : undefined }; } function getCellClassname(column, ...extraClasses) { return clsx(cellClassname, ...extraClasses, column.frozen && cellFrozenClassname); } const { min, max, floor, sign, 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 === undefined ? rowIdx : column.level - column.parent.level; } const checkboxLabel = "c1bn88vv7-0-0-beta-44"; const checkboxLabelClassname = `rdg-checkbox-label ${checkboxLabel}`; const checkboxInput = "c1qt073l7-0-0-beta-44"; const checkboxInputClassname = `rdg-checkbox-input ${checkboxInput}`; const checkbox = "cf71kmq7-0-0-beta-44"; const checkboxClassname = `rdg-checkbox ${checkbox}`; const checkboxLabelDisabled = "c1lwve4p7-0-0-beta-44"; const checkboxLabelDisabledClassname = `rdg-checkbox-label-disabled ${checkboxLabelDisabled}`; function renderCheckbox({ onChange, ...props }) { function handleChange(e) { onChange(e.target.checked, e.nativeEvent.shiftKey); } return /*#__PURE__*/jsxRuntime.jsxs("label", { className: clsx(checkboxLabelClassname, props.disabled && checkboxLabelDisabledClassname), children: [/*#__PURE__*/jsxRuntime.jsx("input", { type: "checkbox", ...props, className: checkboxInputClassname, onChange: handleChange }), /*#__PURE__*/jsxRuntime.jsx("div", { className: checkboxClassname })] }); } const groupCellContent = "g1s9ylgp7-0-0-beta-44"; const groupCellContentClassname = `rdg-group-cell-content ${groupCellContent}`; const caret = "cz54e4y7-0-0-beta-44"; const caretClassname = `rdg-caret ${caret}`; function renderToggleGroup(props) { return /*#__PURE__*/jsxRuntime.jsx(ToggleGroup, { ...props }); } function ToggleGroup({ groupKey, isExpanded, tabIndex, toggleGroup }) { function handleKeyDown({ key }) { if (key === 'Enter') { toggleGroup(); } } const d = isExpanded ? 'M1 1 L 7 7 L 13 1' : 'M1 7 L 7 1 L 13 7'; return /*#__PURE__*/jsxRuntime.jsxs("span", { className: groupCellContentClassname, tabIndex: tabIndex, onKeyDown: handleKeyDown, children: [groupKey, /*#__PURE__*/jsxRuntime.jsx("svg", { viewBox: "0 0 14 8", width: "14", height: "8", className: caretClassname, "aria-hidden": true, children: /*#__PURE__*/jsxRuntime.jsx("path", { d: d }) })] }); } function renderValue(props) { try { return props.row[props.column.key]; } catch { return null; } } const DataGridDefaultRenderersContext = /*#__PURE__*/react.createContext(undefined); const DataGridDefaultRenderersProvider = DataGridDefaultRenderersContext.Provider; function useDefaultRenderers() { return react.useContext(DataGridDefaultRenderersContext); } function SelectCellFormatter({ value, tabIndex, disabled, onChange, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy }) { const renderCheckbox = useDefaultRenderers().renderCheckbox; return renderCheckbox({ 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, tabIndex, disabled, checked: value, onChange }); } const RowSelectionContext = /*#__PURE__*/react.createContext(undefined); const RowSelectionProvider = RowSelectionContext.Provider; const RowSelectionChangeContext = /*#__PURE__*/react.createContext(undefined); const RowSelectionChangeProvider = RowSelectionChangeContext.Provider; function useRowSelection() { const rowSelectionContext = react.useContext(RowSelectionContext); const rowSelectionChangeContext = react.useContext(RowSelectionChangeContext); if (rowSelectionContext === undefined || rowSelectionChangeContext === undefined) { throw new Error('useRowSelection must be used within DataGrid cells'); } return [rowSelectionContext, rowSelectionChangeContext]; } const SELECT_COLUMN_KEY = 'select-row'; function HeaderRenderer(props) { const [isRowSelected, onRowSelectionChange] = useRowSelection(); return /*#__PURE__*/jsxRuntime.jsx(SelectCellFormatter, { "aria-label": "Select All", tabIndex: props.tabIndex, value: isRowSelected, onChange: checked => { onRowSelectionChange({ type: 'HEADER', checked }); } }); } function SelectFormatter(props) { const [isRowSelected, onRowSelectionChange] = useRowSelection(); return /*#__PURE__*/jsxRuntime.jsx(SelectCellFormatter, { "aria-label": "Select", tabIndex: props.tabIndex, value: isRowSelected, onChange: (checked, isShiftClick) => { onRowSelectionChange({ type: 'ROW', row: props.row, checked, isShiftClick }); } }); } function SelectGroupFormatter(props) { const [isRowSelected, onRowSelectionChange] = useRowSelection(); return /*#__PURE__*/jsxRuntime.jsx(SelectCellFormatter, { "aria-label": "Select Group", tabIndex: props.tabIndex, value: isRowSelected, onChange: checked => { onRowSelectionChange({ type: 'ROW', row: props.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__*/jsxRuntime.jsx(HeaderRenderer, { ...props }); }, renderCell(props) { return /*#__PURE__*/jsxRuntime.jsx(SelectFormatter, { ...props }); }, renderGroupCell(props) { return /*#__PURE__*/jsxRuntime.jsx(SelectGroupFormatter, { ...props }); } }; 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 ?? undefined; const defaultCellRenderer = defaultColumnOptions?.renderCell ?? renderValue; const defaultSortable = defaultColumnOptions?.sortable ?? false; const defaultResizable = defaultColumnOptions?.resizable ?? false; const defaultDraggable = defaultColumnOptions?.draggable ?? false; const { columns, colSpanColumns, lastFrozenColumnIndex, headerRowsCount } = react.useMemo(() => { let lastFrozenColumnIndex = -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; const column = { ...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 ?? defaultCellRenderer }; columns.push(column); if (frozen) { lastFrozenColumnIndex++; } if (level > headerRowsCount) { headerRowsCount = level; } } } columns.sort(({ key: aKey, frozen: frozenA }, { key: bKey, frozen: frozenB }) => { if (aKey === SELECT_COLUMN_KEY) return -1; if (bKey === SELECT_COLUMN_KEY) return 1; if (frozenA) { if (frozenB) return 0; return -1; } if (frozenB) return 1; return 0; }); const colSpanColumns = []; columns.forEach((column, idx) => { column.idx = idx; updateColumnParent(column, idx, 0); if (column.colSpan != null) { colSpanColumns.push(column); } }); return { columns, colSpanColumns, lastFrozenColumnIndex, headerRowsCount }; }, [rawColumns, defaultWidth, defaultMinWidth, defaultMaxWidth, defaultCellRenderer, defaultResizable, defaultSortable, defaultDraggable]); const { templateColumns, layoutCssVars, totalFrozenColumnWidth, columnMetrics } = react.useMemo(() => { const columnMetrics = new Map(); let left = 0; let totalFrozenColumnWidth = 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 (lastFrozenColumnIndex !== -1) { const columnMetric = columnMetrics.get(columns[lastFrozenColumnIndex]); totalFrozenColumnWidth = columnMetric.left + columnMetric.width; } const layoutCssVars = {}; for (let i = 0; i <= lastFrozenColumnIndex; i++) { const column = columns[i]; layoutCssVars[`--rdg-frozen-left-${column.idx}`] = `${columnMetrics.get(column).left}px`; } return { templateColumns, layoutCssVars, totalFrozenColumnWidth, columnMetrics }; }, [getColumnWidth, columns, lastFrozenColumnIndex]); const [colOverscanStartIdx, colOverscanEndIdx] = react.useMemo(() => { if (!enableVirtualization) { return [0, columns.length - 1]; } const viewportLeft = scrollLeft + totalFrozenColumnWidth; const viewportRight = scrollLeft + viewportWidth; const lastColIdx = columns.length - 1; const firstUnfrozenColumnIdx = min(lastFrozenColumnIndex + 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++; } const colOverscanStartIdx = max(firstUnfrozenColumnIdx, colVisibleStartIdx - 1); const colOverscanEndIdx = min(lastColIdx, colVisibleEndIdx + 1); return [colOverscanStartIdx, colOverscanEndIdx]; }, [columnMetrics, columns, lastFrozenColumnIndex, scrollLeft, totalFrozenColumnWidth, viewportWidth, enableVirtualization]); return { columns, colSpanColumns, colOverscanStartIdx, colOverscanEndIdx, templateColumns, layoutCssVars, headerRowsCount, lastFrozenColumnIndex, totalFrozenColumnWidth }; } function updateColumnParent(column, index, level) { if (level < column.level) { column.level = level; } if (column.parent !== undefined) { const { parent } = column; if (parent.idx === -1) { parent.idx = index; } parent.colSpan += 1; updateColumnParent(parent, index, level - 1); } } const useLayoutEffect = typeof window === 'undefined' ? react.useEffect : react.useLayoutEffect; function useColumnWidths(columns, viewportColumns, templateColumns, gridRef, gridWidth, resizedColumnWidths, measuredColumnWidths, setResizedColumnWidths, setMeasuredColumnWidths, onColumnResize) { const prevGridWidthRef = react.useRef(gridWidth); const columnsCanFlex = columns.length === viewportColumns.length; const ignorePreviouslyMeasuredColumns = columnsCanFlex && gridWidth !== prevGridWidthRef.current; const newTemplateColumns = [...templateColumns]; const columnsToMeasure = []; for (const { key, idx, width } of viewportColumns) { if (typeof width === 'string' && (ignorePreviouslyMeasuredColumns || !measuredColumnWidths.has(key)) && !resizedColumnWidths.has(key)) { newTemplateColumns[idx] = width; columnsToMeasure.push(key); } } const gridTemplateColumns = newTemplateColumns.join(' '); useLayoutEffect(() => { prevGridWidthRef.current = gridWidth; updateMeasuredWidths(columnsToMeasure); }); function updateMeasuredWidths(columnsToMeasure) { if (columnsToMeasure.length === 0) return; setMeasuredColumnWidths(measuredColumnWidths => { const newMeasuredColumnWidths = new Map(measuredColumnWidths); let hasChanges = false; for (const key of columnsToMeasure) { const measuredWidth = measureColumnWidth(gridRef, key); hasChanges ||= measuredWidth !== measuredColumnWidths.get(key); if (measuredWidth === undefined) { newMeasuredColumnWidths.delete(key); } else { newMeasuredColumnWidths.set(key, measuredWidth); } } return hasChanges ? newMeasuredColumnWidths : measuredColumnWidths; }); } function handleColumnResize(column, nextWidth) { const { key: resizingKey } = column; const newTemplateColumns = [...templateColumns]; const columnsToMeasure = []; for (const { key, idx, width } of viewportColumns) { if (resizingKey === key) { const width = typeof nextWidth === 'number' ? `${nextWidth}px` : nextWidth; newTemplateColumns[idx] = width; } else if (columnsCanFlex && typeof width === 'string' && !resizedColumnWidths.has(key)) { newTemplateColumns[idx] = width; columnsToMeasure.push(key); } } gridRef.current.style.gridTemplateColumns = newTemplateColumns.join(' '); const measuredWidth = typeof nextWidth === 'number' ? nextWidth : measureColumnWidth(gridRef, resizingKey); reactDom.flushSync(() => { setResizedColumnWidths(resizedColumnWidths => { const newResizedColumnWidths = new Map(resizedColumnWidths); newResizedColumnWidths.set(resizingKey, measuredWidth); return newResizedColumnWidths; }); updateMeasuredWidths(columnsToMeasure); }); onColumnResize?.(column.idx, measuredWidth); } return { gridTemplateColumns, handleColumnResize }; } function measureColumnWidth(gridRef, key) { const selector = `[data-measuring-cell-key="${CSS.escape(key)}"]`; const measuringCell = gridRef.current.querySelector(selector); return measuringCell?.getBoundingClientRect().width; } function useGridDimensions() { const gridRef = react.useRef(null); const [inlineSize, setInlineSize] = react.useState(1); const [blockSize, setBlockSize] = react.useState(1); const [horizontalScrollbarHeight, setHorizontalScrollbarHeight] = react.useState(0); useLayoutEffect(() => { const { ResizeObserver } = window; if (ResizeObserver == null) return; const { clientWidth, clientHeight, offsetWidth, offsetHeight } = gridRef.current; const { width, height } = gridRef.current.getBoundingClientRect(); const initialHorizontalScrollbarHeight = offsetHeight - clientHeight; const initialWidth = width - offsetWidth + clientWidth; const initialHeight = height - initialHorizontalScrollbarHeight; setInlineSize(initialWidth); setBlockSize(initialHeight); setHorizontalScrollbarHeight(initialHorizontalScrollbarHeight); const resizeObserver = new ResizeObserver(entries => { const size = entries[0].contentBoxSize[0]; const { clientHeight, offsetHeight } = gridRef.current; reactDom.flushSync(() => { setInlineSize(size.inlineSize); setBlockSize(size.blockSize); setHorizontalScrollbarHeight(offsetHeight - clientHeight); }); }); resizeObserver.observe(gridRef.current); return () => { resizeObserver.disconnect(); }; }, []); return [gridRef, inlineSize, blockSize, horizontalScrollbarHeight]; } function useLatestFunc(fn) { const ref = react.useRef(fn); react.useEffect(() => { ref.current = fn; }); const callbackFn = react.useCallback((...args) => { ref.current(...args); }, []); return fn ? callbackFn : fn; } function useRovingTabIndex(isSelected) { const [isChildFocused, setIsChildFocused] = react.useState(false); if (isChildFocused && !isSelected) { setIsChildFocused(false); } function onFocus(event) { if (event.target !== event.currentTarget) { setIsChildFocused(true); } } const isFocusable = isSelected && !isChildFocused; return { tabIndex: isFocusable ? 0 : -1, childTabIndex: isSelected ? 0 : -1, onFocus: isSelected ? onFocus : undefined }; } function useViewportColumns({ columns, colSpanColumns, rows, topSummaryRows, bottomSummaryRows, colOverscanStartIdx, colOverscanEndIdx, lastFrozenColumnIndex, rowOverscanStartIdx, rowOverscanEndIdx }) { const startIdx = react.useMemo(() => { if (colOverscanStartIdx === 0) return 0; let startIdx = colOverscanStartIdx; const updateStartIdx = (colIdx, colSpan) => { if (colSpan !== undefined && colIdx + colSpan > colOverscanStartIdx) { startIdx = colIdx; return true; } return false; }; for (const column of colSpanColumns) { const colIdx = column.idx; if (colIdx >= startIdx) break; if (updateStartIdx(colIdx, getColSpan(column, lastFrozenColumnIndex, { type: 'HEADER' }))) { break; } for (let rowIdx = rowOverscanStartIdx; rowIdx <= rowOverscanEndIdx; rowIdx++) { const row = rows[rowIdx]; if (updateStartIdx(colIdx, getColSpan(column, lastFrozenColumnIndex, { type: 'ROW', row }))) { break; } } if (topSummaryRows != null) { for (const row of topSummaryRows) { if (updateStartIdx(colIdx, getColSpan(column, lastFrozenColumnIndex, { type: 'SUMMARY', row }))) { break; } } } if (bottomSummaryRows != null) { for (const row of bottomSummaryRows) { if (updateStartIdx(colIdx, getColSpan(column, lastFrozenColumnIndex, { type: 'SUMMARY', row }))) { break; } } } } return startIdx; }, [rowOverscanStartIdx, rowOverscanEndIdx, rows, topSummaryRows, bottomSummaryRows, colOverscanStartIdx, lastFrozenColumnIndex, colSpanColumns]); return react.useMemo(() => { const viewportColumns = []; for (let colIdx = 0; colIdx <= colOverscanEndIdx; colIdx++) { const column = columns[colIdx]; if (colIdx < startIdx && !column.frozen) continue; viewportColumns.push(column); } return viewportColumns; }, [startIdx, colOverscanEndIdx, columns]); } function useViewportRows({ rows, rowHeight, clientHeight, scrollTop, enableVirtualization }) { const { totalRowHeight, gridTemplateRows, getRowTop, getRowHeight, findRowIdx } = react.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 = ' '; const rowPositions = rows.map(row => { const currentRowHeight = rowHeight(row); const position = { top: totalRowHeight, height: currentRowHeight }; gridTemplateRows += `${currentRowHeight}px `; totalRowHeight += currentRowHeight; 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 }; } const cellDragHandle = "c1w9bbhr7-0-0-beta-44"; const cellDragHandleFrozenClassname = "c1creorc7-0-0-beta-44"; const cellDragHandleClassname = `rdg-cell-drag-handle ${cellDragHandle}`; function DragHandle({ gridRowStart, rows, column, columnWidth, maxColIdx, isLastRow, selectedPosition, latestDraggedOverRowIdx, isCellEditable, onRowsChange, onFill, onClick, setDragging, setDraggedOverRowIdx }) { const { idx, rowIdx } = selectedPosition; function handleMouseDown(event) { event.preventDefault(); if (event.buttons !== 1) return; setDragging(true); window.addEventListener('mouseover', onMouseOver); window.addEventListener('mouseup', onMouseUp); function onMouseOver(event) { if (event.buttons !== 1) onMouseUp(); } function onMouseUp() { window.removeEventListener('mouseover', onMouseOver); window.removeEventListener('mouseup', onMouseUp); setDragging(false); handleDragEnd(); } } function handleDragEnd() { const overRowIdx = latestDraggedOverRowIdx.current; if (overRowIdx === undefined) return; const startRowIndex = rowIdx < overRowIdx ? rowIdx + 1 : overRowIdx; const endRowIndex = rowIdx < overRowIdx ? overRowIdx + 1 : rowIdx; updateRows(startRowIndex, endRowIndex); setDraggedOverRowIdx(undefined); } function handleDoubleClick(event) { event.stopPropagation(); updateRows(rowIdx + 1, rows.length); } function updateRows(startRowIdx, endRowIdx) { const sourceRow = rows[rowIdx]; const updatedRows = [...rows]; const indexes = []; for (let i = startRowIdx; i < endRowIdx; i++) { if (isCellEditable({ rowIdx: i, idx })) { const updatedRow = onFill({ columnKey: column.key, sourceRow, targetRow: rows[i] }); if (updatedRow !== rows[i]) { updatedRows[i] = updatedRow; indexes.push(i); } } } if (indexes.length > 0) { onRowsChange?.(updatedRows, { indexes, column }); } } function getStyle() { const colSpan = column.colSpan?.({ type: 'ROW', row: rows[rowIdx] }) ?? 1; const { insetInlineStart, ...style } = getCellStyle(column, colSpan); const marginEnd = 'calc(var(--rdg-drag-handle-size) * -0.5 + 1px)'; const isLastColumn = column.idx + colSpan - 1 === maxColIdx; return { ...style, gridRowStart, marginInlineEnd: isLastColumn ? undefined : marginEnd, marginBlockEnd: isLastRow ? undefined : marginEnd, insetInlineStart: insetInlineStart ? `calc(${insetInlineStart} + ${columnWidth}px + var(--rdg-drag-handle-size) * -0.5 - 1px)` : undefined }; } return /*#__PURE__*/jsxRuntime.jsx("div", { style: getStyle(), className: clsx(cellDragHandleClassname, column.frozen && cellDragHandleFrozenClassname), onClick: onClick, onMouseDown: handleMouseDown, onDoubleClick: handleDoubleClick }); } const cellEditing = "cis5rrm7-0-0-beta-44"; function EditCell({ column, colSpan, row, rowIdx, onRowChange, closeEditor, onKeyDown, navigate }) { const frameRequestRef = react.useRef(); const commitOnOutsideClick = column.editorOptions?.commitOnOutsideClick !== false; const commitOnOutsideMouseDown = useLatestFunc(() => { onClose(true, false); }); react.useEffect(() => { if (!commitOnOutsideClick) return; function onWindowCaptureMouseDown() { frameRequestRef.current = requestAnimationFrame(commitOnOutsideMouseDown); } addEventListener('mousedown', onWindowCaptureMouseDown, { capture: true }); return () => { removeEventListener('mousedown', onWindowCaptureMouseDown, { capture: true }); cancelFrameRequest(); }; }, [commitOnOutsideClick, commitOnOutsideMouseDown]); function cancelFrameRequest() { cancelAnimationFrame(frameRequestRef.current); } 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, shouldFocusCell = true) { if (commitChanges) { onRowChange(row, true, shouldFocusCell); } else { closeEditor(shouldFocusCell); } } function onEditorRowChange(row, commitChangesAndFocus = false) { onRowChange(row, commitChangesAndFocus, commitChangesAndFocus); } const { cellClass } = column; const className = getCellClassname(column, 'rdg-editor-container', typeof cellClass === 'function' ? cellClass(row) : cellClass, !column.editorOptions?.displayCellContent && cellEditing); return /*#__PURE__*/jsxRuntime.jsx("div", { role: "gridcell", "aria-colindex": column.idx + 1, "aria-colspan": colSpan, "aria-selected": true, className: className, style: getCellStyle(column, colSpan), onKeyDown: handleKeyDown, onMouseDownCapture: cancelFrameRequest, children: column.renderEditCell != null && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [column.renderEditCell({ column, row, onRowChange: onEditorRowChange, onClose }), column.editorOptions?.displayCellContent && column.renderCell({ column, row, rowIdx, isCellEditable: true, tabIndex: -1, onRowChange: onEditorRowChange })] }) }); } function GroupedColumnHeaderCell({ column, rowIdx, isCellSelected, selectCell }) { const { tabIndex, onFocus } = useRovingTabIndex(isCellSelected); const { colSpan } = column; const rowSpan = getHeaderCellRowSpan(column, rowIdx); const index = column.idx + 1; function onClick() { selectCell({ idx: column.idx, rowIdx }); } return /*#__PURE__*/jsxRuntime.jsx("div", { role: "columnheader", "aria-colindex": index, "aria-colspan": colSpan, "aria-rowspan": rowSpan, "aria-selected": isCellSelected, tabIndex: tabIndex, className: clsx(cellClassname, column.headerCellClass), style: { ...getHeaderCellStyle(column, rowIdx, rowSpan), gridColumnStart: index, gridColumnEnd: index + colSpan }, onFocus: onFocus, onClick: onClick, children: column.name }); } const headerSortCellClassname = "h44jtk67-0-0-beta-44"; const headerSortName = "hcgkhxz7-0-0-beta-44"; const headerSortNameClassname = `rdg-header-sort-name ${headerSortName}`; function renderHeaderCell({ column, sortDirection, priority }) { if (!column.sortable) return column.name; return /*#__PURE__*/jsxRuntime.jsx(SortableHeaderCell, { sortDirection: sortDirection, priority: priority, children: column.name }); } function SortableHeaderCell({ sortDirection, priority, children }) { const renderSortStatus = useDefaultRenderers().renderSortStatus; return /*#__PURE__*/jsxRuntime.jsxs("span", { className: headerSortCellClassname, children: [/*#__PURE__*/jsxRuntime.jsx("span", { className: headerSortNameClassname, children: children }), /*#__PURE__*/jsxRuntime.jsx("span", { children: renderSortStatus({ sortDirection, priority }) })] }); } const cellSortableClassname = "c6l2wv17-0-0-beta-44"; const cellResizable = "c1kqdw7y7-0-0-beta-44"; const cellResizableClassname = `rdg-cell-resizable ${cellResizable}`; const resizeHandleClassname = "r1y6ywlx7-0-0-beta-44"; const cellDraggableClassname = 'rdg-cell-draggable'; const cellDragging = "c1bezg5o7-0-0-beta-44"; const cellDraggingClassname = `rdg-cell-dragging ${cellDragging}`; const cellOver = "c1vc96037-0-0-beta-44"; const cellOverClassname = `rdg-cell-drag-over ${cellOver}`; function HeaderCell({ column, colSpan, rowIdx, isCellSelected, onColumnResize, onColumnsReorder, sortColumns, onSortColumnsChange, selectCell, shouldFocusGrid, direction, dragDropKey }) { const [isDragging, setIsDragging] = react.useState(false); const [isOver, setIsOver] = react.useState(false); const isRtl = direction === 'rtl'; const rowSpan = getHeaderCellRowSpan(column, rowIdx); const { tabIndex, childTabIndex, onFocus } = useRovingTabIndex(isCellSelected); const sortIndex = sortColumns?.findIndex(sort => sort.columnKey === column.key); const sortColumn = sortIndex !== undefined && sortIndex > -1 ? sortColumns[sortIndex] : undefined; const sortDirection = sortColumn?.direction; const priority = sortColumn !== undefined && sortColumns.length > 1 ? sortIndex + 1 : undefined; const ariaSort = sortDirection && !priority ? sortDirection === 'ASC' ? 'ascending' : 'descending' : undefined; const { sortable, resizable, draggable } = column; const className = getCellClassname(column, column.headerCellClass, sortable && cellSortableClassname, resizable && cellResizableClassname, draggable && cellDraggableClassname, isDragging && cellDraggingClassname, isOver && cellOverClassname); const renderHeaderCell$1 = column.renderHeaderCell ?? renderHeaderCell; function onPointerDown(event) { if (event.pointerType === 'mouse' && event.buttons !== 1) { return; } event.preventDefault(); const { currentTarget, pointerId } = event; const headerCell = currentTarget.parentElement; const { right, left } = headerCell.getBoundingClientRect(); const offset = isRtl ? event.clientX - left : right - event.clientX; function onPointerMove(event) { const { right, left } = headerCell.getBoundingClientRect(); const width = isRtl ? right + offset - event.clientX : event.clientX + offset - left; if (width > 0) { onColumnResize(column, clampColumnWidth(width, column)); } } function onLostPointerCapture() { currentTarget.removeEventListener('pointermove', onPointerMove); currentTarget.removeEventListener('lostpointercapture', onLostPointerCapture); } currentTarget.setPointerCapture(pointerId); currentTarget.addEventListener('pointermove', onPointerMove); currentTarget.addEventListener('lostpointercapture', onLostPointerCapture); } function onSort(ctrlClick) { if (onSortColumnsChange == null) return; const { sortDescendingFirst } = column; if (sortColumn === undefined) { const nextSort = { columnKey: column.key, direction: sortDescendingFirst ? 'DESC' : 'ASC' }; onSortColumnsChange(sortColumns && ctrlClick ? [...sortColumns, nextSort] : [nextSort]); } else { let nextSortColumn; if (sortDescendingFirst === true && sortDirection === 'DESC' || sortDescendingFirst !== true && sortDirection === 'ASC') { nextSortColumn = { columnKey: column.key, direction: sortDirection === 'ASC' ? 'DESC' : 'ASC' }; } if (ctrlClick) { const nextSortColumns = [...sortColumns]; if (nextSortColumn) { nextSortColumns[sortIndex] = nextSortColumn; } else { nextSortColumns.splice(sortIndex, 1); } onSortColumnsChange(nextSortColumns); } else { onSortColumnsChange(nextSortColumn ? [nextSortColumn] : []); } } } function onClick(event) { selectCell({ idx: column.idx, rowIdx }); if (sortable) { onSort(event.ctrlKey || event.metaKey); } } function onDoubleClick() { onColumnResize(column, 'max-content'); } function handleFocus(event) { onFocus?.(event); if (shouldFocusGrid) { selectCell({ idx: 0, rowIdx }); } } function onKeyDown(event) { if (event.key === ' ' || event.key === 'Enter') { event.preventDefault(); onSort(event.ctrlKey || event.metaKey); } } function onDragStart(event) { event.dataTransfer.setData(dragDropKey, column.key); event.dataTransfer.dropEffect = 'move'; setIsDragging(true); } function onDragEnd() { setIsDragging(false); } function onDragOver(event) { event.preventDefault(); event.dataTransfer.dropEffect = 'move'; } function onDrop(event) { setIsOver(false); if (event.dataTransfer.types.includes(dragDropKey)) { const sourceKey = event.dataTransfer.getData(dragDropKey); if (sourceKey !== column.key) { event.preventDefault(); onColumnsReorder?.(sourceKey, column.key); } } } function onDragEnter(event) { if (isEventPertinent(event)) { setIsOver(true); } } function onDragLeave(event) { if (isEventPertinent(event)) { setIsOver(false); } } let draggableProps; if (draggable) { draggableProps = { draggable: true, onDragStart, onDragEnd, onDragOver, onDragEnter, onDragLeave, onDrop }; } return /*#__PURE__*/jsxRuntime.jsxs("div", { role: "columnheader", "aria-colindex": column.idx + 1, "aria-colspan": colSpan, "aria-rowspan": rowSpan, "aria-selected": isCellSelected, "aria-sort": ariaSort, tabIndex: shouldFocusGrid ? 0 : tabIndex, className: className, style: { ...getHeaderCellStyle(column, rowIdx, rowSpan), ...getCellStyle(column, colSpan) }, onFocus: handleFocus, onClick: onClick, onKeyDown: sortable ? onKeyDown : undefined, ...draggableProps, children: [renderHeaderCell$1({ column, sortDirection, priority, tabIndex: childTabIndex }), resizable && /*#__PURE__*/jsxRuntime.jsx("div", { className: resizeHandleClassname, onClick: stopPropagation, onDoubleClick: onDoubleClick, onPointerDown: onPointerDown })] }); } function isEventPertinent(event) { const relatedTarget = event.relatedTarget; return !event.currentTarget.contains(relatedTarget); } const row = "r1upfr807-0-0-beta-44"; const rowClassname = `rdg-row ${row}`; const rowSelected = "r190mhd37-0-0-beta-44"; const rowSelectedClassname = 'rdg-row-selected'; const rowSelectedWithFrozenCell = "r139qu9m7-0-0-beta-44"; const topSummaryRowClassname = 'rdg-top-summary-row'; const bottomSummaryRowClassname = 'rdg-bottom-summary-row'; const headerRow = "h10tskcx7-0-0-beta-44"; const headerRowClassname = `rdg-header-row ${headerRow}`; function HeaderRow({ rowIdx, columns, onColumnResize, onColumnsReorder, sortColumns, onSortColumnsChange, lastFrozenColumnIndex, selectedCellIdx, selectCell, shouldFocusGrid, direction }) { const dragDropKey = react.useId(); const cells = []; for (let index = 0; index < columns.length; index++) { const column = columns[index]; const colSpan = getColSpan(column, lastFrozenColumnIndex, { type: 'HEADER' }); if (colSpan !== undefined) { index += colSpan - 1; } cells.push( /*#__PURE__*/jsxRuntime.jsx(HeaderCell, { column: column, colSpan: colSpan, rowIdx: rowIdx, isCellSelected: selectedCellIdx === column.idx, onColumnResize: onColumnResize, onColumnsReorder: onColumnsReorder, onSortColumnsChange: onSortColumnsChange, sortColumns: sortColumns, selectCell: selectCell, shouldFocusGrid: shouldFocusGrid && index === 0, direction: direction, dragDropKey: dragDropKey }, column.key)); } return /*#__PURE__*/jsxRuntime.jsx("div", { role: "row", "aria-rowindex": rowIdx, className: clsx(headerRowClassname, selectedCellIdx === -1 && rowSelectedClassname), children: cells }); } const HeaderRow$1 = /*#__PURE__*/react.memo(HeaderRow); function GroupedColumnHeaderRow({ rowIdx, level, columns, selectedCellIdx, selectCell }) { const cells = []; const renderedParents = new Set(); for (const column of columns) { let { parent } = column; if (parent === undefined) continue; while (parent.level > level) { if (parent.parent === undefined) break; parent = parent.parent; } if (parent.level === level && !renderedParents.has(parent)) { renderedParents.add(parent); const { idx } = parent; cells.push( /*#__PURE__*/jsxRuntime.jsx(GroupedColumnHeaderCell, { column: parent, rowIdx: rowIdx, isCellSelected: selectedCellIdx === idx, selectCell: selectCell }, idx)); } } return /*#__PURE__*/jsxRuntime.jsx("div", { role: "row", "aria-rowindex": rowIdx, className: headerRowClassname, children: cells }); } const GroupedColumnHeaderRow$1 = /*#__PURE__*/react.memo(GroupedColumnHeaderRow); const cellCopied = "c6ra8a37-0-0-beta-44"; const cellCopiedClassname = `rdg-cell-copied ${cellCopied}`; const cellDraggedOver = "cq910m07-0-0-beta-44"; const cellDraggedOverClassname = `rdg-cell-dragged-over ${cellDraggedOver}`; function Cell({ column, colSpan, isCellSelected, isCopied, isDraggedOver, row, rowIdx, onClick, onDoubleClick, onContextMenu, onRowChange, selectCell, ...props }) { const { tabIndex, childTabIndex, onFocus } = useRovingTabIndex(isCellSelected); const { cellClass } = column; const className = getCellClassname(column, typeof cellClass === 'function' ? cellClass(row) : cellClass, isCopied && cellCopiedClassname, isDraggedOver && cellDraggedOverClassname); const isEditable = isCellEditableUtil(column, row); function selectCellWrapper(openEditor) { selectCell({ rowIdx, idx: column.idx }, openEditor); } function handleClick(event) { if (onClick) { const cellEvent = createCellEvent(event); onClick({ row, column, selectCell: selectCellWrapper }, cellEvent); if (cellEvent.isGridDefaultPrevented()) return; } selectCellWrapper(); } function handleContextMenu(event) { if (onContextMenu) { const cellEvent = createCellEvent(event); onContextMenu({ row, column, selectCell: selectCellWrapper }, cellEvent); if (cellEvent.isGridDefaultPrevented()) return; } selectCellWrapper(); } function handleDoubleClick(event) { if (onDoubleClick) { const cellEvent = createCellEvent(event); onDoubleClick({ row, column, selectCell: selectCellWrapper }, cellEvent); if (cellEvent.isGridDefaultPrevented()) return; } selectCellWrapper(true); } function handleRowChange(newRow) { onRowChange(column, newRow); } return /*#__PURE__*/jsxRuntime.jsx("div", { role: "gridcell", "aria-colindex": column.idx + 1, "aria-colspan": colSpan, "aria-selected": isCellSelected, "aria-readonly": !isEditable || undefined, tabIndex: tabIndex, className: className, style: getCellStyle(column, colSpan), onClick: ha