diff --git a/README.md b/README.md
index 4a80556fa8..ef726156e7 100644
--- a/README.md
+++ b/README.md
@@ -42,7 +42,7 @@
- [Cell copy / pasting](https://adazzle.github.io/react-data-grid/#/AllFeatures)
- [Cell value dragging / filling](https://adazzle.github.io/react-data-grid/#/AllFeatures)
- [Customizable Renderers](https://adazzle.github.io/react-data-grid/#/CustomizableRenderers)
-- Right-to-left (RTL) support. We recommend using Firefox as Chrome has a [bug](https://bugs.chromium.org/p/chromium/issues/detail?id=1140374) with frozen columns, and the [`:dir` pseudo class](https://developer.mozilla.org/en-US/docs/Web/CSS/:dir) is not supported
+- Right-to-left (RTL) support. We recommend using Firefox as Chrome has a [bug](https://bugs.chromium.org/p/chromium/issues/detail?id=1140374) with frozen columns.
## Links
@@ -87,7 +87,7 @@ function App() {
#### ``
-##### Props
+##### DataGridProps
###### `columns: readonly Column[]`
@@ -103,9 +103,11 @@ An array of rows, the rows data can be of any type.
###### `topSummaryRows?: Maybe`
+An optional array of summary rows, usually used to display total values for example. `topSummaryRows` are pinned at the top of the rows view and the vertical scroll bar will not scroll these rows.
+
###### `bottomSummaryRows?: Maybe`
-An optional array of summary rows, usually used to display total values for example.
+An optional array of summary rows, usually used to display total values for example. `bottomSummaryRows` are pinned at the bottom of the rows view and the vertical scroll bar will not scroll these rows.
###### `rowKeyGetter?: Maybe<(row: R) => K>`
@@ -167,23 +169,116 @@ A number defining the height of summary rows.
###### `selectedRows?: Maybe>`
+A set of selected row keys. `rowKeyGetter` is required for row selection to work.
+
###### `isRowSelectionDisabled?: Maybe<(row: NoInfer) => boolean>`
+A function used to disable row selection on certain rows.
+
###### `onSelectedRowsChange?: Maybe<(selectedRows: Set) => void>`
+A function called when row selection is changed.
+
+```tsx
+import { useState } from 'react';
+import DataGrid, { SelectColumn } from 'react-data-grid';
+
+const rows: readonly Rows[] = [...];
+
+const columns: readonly Column[] = [
+ SelectColumn,
+ // other columns
+];
+
+function MyGrid() {
+ const [selectedRows, setSelectedRows] = useState((): ReadonlySet => new Set());
+
+ return (
+
+ );
+}
+
+function rowKeyGetter(row: Row) {
+ return row.id;
+}
+
+function isRowSelectionDisabled(row: Row) {
+ return !row.isActive;
+}
+```
+
###### `sortColumns?: Maybe`
+An array of sorted columns.
+
###### `onSortColumnsChange?: Maybe<(sortColumns: SortColumn[]) => void>`
-###### `defaultColumnOptions?: Maybe>`
+A function called when sorting is changed
-###### `groupBy?: Maybe`
+```tsx
+import { useState } from 'react';
+import DataGrid, { SelectColumn } from 'react-data-grid';
-###### `rowGrouper?: Maybe<(rows: readonly R[], columnKey: string) => Record>`
+const rows: readonly Rows[] = [...];
-###### `expandedGroupIds?: Maybe>`
+const columns: readonly Column[] = [
+ {
+ key: 'name',
+ name: 'Name',
+ sortable: true
+ },
+ // other columns
+];
-###### `onExpandedGroupIdsChange?: Maybe<(expandedGroupIds: Set) => void>`
+function MyGrid() {
+ const [sortColumns, setSortColumns] = useState([]);
+
+ return (
+
+ );
+}
+```
+
+Grid can be sorted on multiple columns using `ctrl (command) + click`. To disable multiple column sorting, change the `onSortColumnsChange` function to
+
+```tsx
+onSortColumnsChange(sortColumns: SortColumn[]) {
+ setSortColumns(sortColumns.slice(-1));
+}
+```
+
+###### `defaultColumnOptions?: Maybe>`
+
+Column options that are applied to all the columns
+
+```tsx
+function MyGrid() {
+ return (
+
+ );
+}
+```
###### `onFill?: Maybe<(event: FillEvent) => R>`
@@ -193,12 +288,99 @@ A number defining the height of summary rows.
###### `onCellClick?: Maybe<(args: CellClickArgs, event: CellMouseEvent) => void>`
+Triggered when a cell is clicked. The default behavior is to select the cell. Call `preventGridDefault` to prevent the default behavior
+
+```tsx
+function onCellClick(args: CellClickArgs, event: CellMouseEvent) {
+ if (args.column.key === 'id') {
+ event.preventGridDefault();
+ }
+}
+
+;
+```
+
+This event can be used to open cell editor on single click
+
+```tsx
+function onCellClick(args: CellClickArgs, event: CellMouseEvent) {
+ if (args.column.key === 'id') {
+ event.preventGridDefault();
+ args.selectCell(true);
+ }
+}
+```
+
+Arguments:
+
+`args: CellClickArgs`
+
+- `args.rowIdx`: `number` - row index of the currently selected cell
+- `args.row`: `R` - row object of the currently selected cell
+- `args.column`: `CalculatedColumn` - column object of the currently selected cell
+- `args.selectCell`: `(enableEditor?: boolean) => void` - function to manually select the cell and optionally pass `true` to start editing
+
+`event` extends `React.MouseEvent`
+
+- `event.preventGridDefault:`: `() => void`
+- `event.isGridDefaultPrevented`: `boolean`
+
###### `onCellDoubleClick?: Maybe<(args: CellClickArgs, event: CellMouseEvent) => void>`
+Triggered when a cell is double clicked. The default behavior is to open the editor if the cell is editable. Call `preventGridDefault` to prevent the default behavior
+
+```tsx
+function onCellDoubleClick(args: CellClickArgs, event: CellMouseEvent) {
+ if (args.column.key === 'id') {
+ event.preventGridDefault();
+ }
+}
+
+;
+```
+
###### `onCellContextMenu?: Maybe<(args: CellClickArgs, event: CellMouseEvent) => void>`
+Triggered when a cell is right clicked. The default behavior is to select the cell. Call `preventGridDefault` to prevent the default behavior
+
+```tsx
+function onCellContextMenu(args: CellClickArgs, event: CellMouseEvent) {
+ if (args.column.key === 'id') {
+ event.preventGridDefault();
+ }
+}
+
+;
+```
+
###### `onCellKeyDown?: Maybe<(args: CellKeyDownArgs, event: CellKeyboardEvent) => void>`
+A function called when keydown event is triggered on a cell. This event can be used to customize cell navigation and editing behavior.
+
+**Examples**
+
+- Prevent editing on `Enter`
+
+```tsx
+function onCellKeyDown(args: CellKeyDownArgs, event: CellKeyboardEvent) {
+ if (args.mode === 'SELECT' && event.key === 'Enter') {
+ event.preventGridDefault();
+ }
+}
+```
+
+- Prevent navigation on `Tab`
+
+```tsx
+function onCellKeyDown(args: CellKeyDownArgs, event: CellKeyboardEvent) {
+ if (args.mode === 'SELECT' && event.key === 'Tab') {
+ event.preventGridDefault();
+ }
+}
+```
+
+Check [more examples](website/routes/CellNavigation.lazy.tsx)
+
###### `onSelectedCellChange?: Maybe<(args: CellSelectArgs) => void>;`
Triggered when the selected cell is changed.
@@ -211,20 +393,28 @@ Arguments:
###### `onScroll?: Maybe<(event: React.UIEvent) => void>`
-###### `onColumnResize?: Maybe<(idx: number, width: number) => void>`
+A function called when the grid is scrolled.
+
+###### `onColumnResize?: Maybe<(column: CalculatedColumn, width: number) => void>`
+
+A function called when column is resized.
###### `enableVirtualization?: Maybe`
+**Default:** `true`
+
+This prop can be used to disable virtualization.
+
###### `renderers?: Maybe>`
This prop can be used to override the internal renderers. The prop accepts an object of type
```tsx
interface Renderers {
+ renderCell?: Maybe<(key: Key, props: CellRendererProps) => ReactNode>;
renderCheckbox?: Maybe<(props: RenderCheckboxProps) => ReactNode>;
renderRow?: Maybe<(key: Key, props: RenderRowProps) => ReactNode>;
renderSortStatus?: Maybe<(props: RenderSortStatusProps) => ReactNode>;
- renderCell?: Maybe<(key: Key, props: CellRendererProps) => ReactNode>;
noRowsFallback?: Maybe;
}
```
@@ -249,9 +439,23 @@ function MyGrid() {
:warning: To prevent all rows from being unmounted on re-renders, make sure to pass a static or memoized component to `renderRow`.
-###### `rowClass?: Maybe<(row: R) => Maybe>`
+###### `rowClass?: Maybe<(row: R, rowIdx: number) => Maybe>`
-##### `direction?: Maybe<'ltr' | 'rtl'>`
+A function to add a class on the row
+
+```tsx
+import DataGrid from 'react-data-grid';
+
+function MyGrid() {
+ return ;
+}
+
+function rowClass(row: Row, rowIdx: number) {
+ return rowIdx % 2 === 0 ? 'even' : 'odd';
+}
+```
+
+###### `direction?: Maybe<'ltr' | 'rtl'>`
This property sets the text direction of the grid, it defaults to `'ltr'` (left-to-right). Setting `direction` to `'rtl'` has the following effects:
@@ -262,16 +466,54 @@ This property sets the text direction of the grid, it defaults to `'ltr'` (left-
###### `className?: string | undefined`
+custom classname
+
###### `style?: CSSProperties | undefined`
+custom styles
+
###### `'aria-label'?: string | undefined`
+The label of the grid. We recommend providing a label using `aria-label` or `aria-labelledby`
+
###### `'aria-labelledby'?: string | undefined`
+The id of the element containing a label for the grid. We recommend providing a label using `aria-label` or `aria-labelledby`
+
+###### `'aria-description'?: string | undefined`
+
###### `'aria-describedby'?: string | undefined`
+If the grid has a caption or description, `aria-describedby` can be set on the grid element with a value referring to the element containing the description.
+
###### `'data-testid'?: Maybe`
+This prop can be used to add a testid for testing. We recommend using `role` and `name` to find the grid element
+
+```tsx
+function MyGrid() {
+ return ;
+}
+
+function MyGridTest() {
+ const grid = screen.getByRole('grid', { name: 'my-grid' });
+}
+```
+
+#### ``
+
+`TreeDataGrid` is component built on top of `DataGrid` to add row grouping. This implements the [Treegrid pattern](https://www.w3.org/WAI/ARIA/apg/patterns/treegrid/). At the moment `TreeDataGrid` does not support `onFill` and `isRowSelectionDisabled` props
+
+##### TreeDataGridProps
+
+###### `groupBy?: Maybe`
+
+###### `rowGrouper?: Maybe<(rows: readonly R[], columnKey: string) => Record>`
+
+###### `expandedGroupIds?: Maybe>`
+
+###### `onExpandedGroupIdsChange?: Maybe<(expandedGroupIds: Set) => void>`
+
#### ``
##### Props
@@ -334,18 +576,73 @@ See [`RenderGroupCellProps`](#rendergroupcellprops)
### Hooks
-#### `useRowSelection(): [boolean, (selectRowEvent: SelectRowEvent) => void]`
+#### `useHeaderRowSelection(): { isIndeterminate, isRowSelected, onRowSelectionChange }`
+
+#### `useRowSelection(): { isRowSelectionDisabled, isRowSelected, onRowSelectionChange }`
### Other
#### `SelectColumn: Column`
-#### `SELECT_COLUMN_KEY = 'select-row'`
+#### `SELECT_COLUMN_KEY = 'rdg-select-column'`
### Types
#### `Column`
+##### `name: string | ReactElement`
+
+The name of the column. By default it will be displayed in the header cell
+
+##### `key: string`
+
+A unique key to distinguish each column
+
+##### `width?: Maybe`
+
+**Default** `auto`
+
+Width can be any valid css grid column value. If not specified, it will be determined automatically based on grid width and specified widths of other columns.
+
+```tsx
+width: 80; // pixels
+width: '25%';
+width: 'max-content';
+width: 'minmax(100px, max-content)';
+```
+
+`max-content` can be used to expand the column to show all the content. Note that the grid is only able to calculate column width for visible rows.
+
+##### `minWidth?: Maybe`
+
+**Default**: `50` pixels
+
+Sets the maximum width of a column.
+
+##### `maxWidth?: Maybe`
+
+Sets the maximum width of a column.
+
+##### `cellClass?: Maybe Maybe)>`
+
+A function to add a class on the row
+
+##### `headerCellClass?: Maybe`
+
+##### `summaryCellClass?: Maybe Maybe)>`
+
+##### `renderCell?: Maybe<(props: RenderCellProps) => ReactNode>`
+
+Render function used to render the content of cells
+
+##### `renderHeaderCell`
+
+Render function used to render the content of header cells
+
+##### `renderSummaryCell`
+
+Render function used to render the content of summary cells
+
#### `DataGridHandle`
#### `RenderEditCellProps`
diff --git a/eslint.config.js b/eslint.config.js
index be52560a1d..82d8178c16 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -9,6 +9,7 @@ import reactHooks from 'eslint-plugin-react-hooks';
import reactHooksExtra from 'eslint-plugin-react-hooks-extra';
import sonarjs from 'eslint-plugin-sonarjs';
import testingLibrary from 'eslint-plugin-testing-library';
+import markdown from '@eslint/markdown';
export default [
{
@@ -728,5 +729,23 @@ export default [
'no-undef': 1,
'no-use-before-define': [1, { functions: false, classes: false, variables: false }]
}
+ },
+
+ {
+ name: 'markdown',
+ files: ['**/*.md'],
+ plugins: {
+ markdown
+ },
+ language: 'markdown/commonmark',
+ rules: {
+ 'markdown/fenced-code-language': 1,
+ 'markdown/heading-increment': 1,
+ 'markdown/no-duplicate-headings': 0,
+ 'markdown/no-empty-links': 1,
+ 'markdown/no-html': 0,
+ 'markdown/no-invalid-label-refs': 1,
+ 'markdown/no-missing-label-refs': 1
+ }
}
];
diff --git a/package.json b/package.json
index 391d80fe22..555d76b87f 100644
--- a/package.json
+++ b/package.json
@@ -63,6 +63,7 @@
"@babel/runtime": "^7.26.0",
"@biomejs/biome": "1.9.4",
"@eslint/compat": "^1.2.4",
+ "@eslint/markdown": "^6.2.1",
"@faker-js/faker": "^9.3.0",
"@ianvs/prettier-plugin-sort-imports": "^4.0.2",
"@linaria/core": "^6.0.0",
diff --git a/src/DataGrid.tsx b/src/DataGrid.tsx
index dc6f6aeb58..1fff78dd17 100644
--- a/src/DataGrid.tsx
+++ b/src/DataGrid.tsx
@@ -85,7 +85,7 @@ interface EditCellState extends Position {
readonly originalRow: R;
}
-type DefaultColumnOptions = Pick<
+export type DefaultColumnOptions = Pick<
Column,
'renderCell' | 'width' | 'minWidth' | 'maxWidth' | 'resizable' | 'sortable' | 'draggable'
>;
diff --git a/src/index.ts b/src/index.ts
index d76283ea28..f016f98853 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,6 +1,11 @@
import './style/layers.css';
-export { default, type DataGridProps, type DataGridHandle } from './DataGrid';
+export {
+ default,
+ type DataGridProps,
+ type DataGridHandle,
+ type DefaultColumnOptions
+} from './DataGrid';
export { default as TreeDataGrid, type TreeDataGridProps } from './TreeDataGrid';
export { DataGridDefaultRenderersProvider } from './DataGridDefaultRenderersProvider';
export { default as Row } from './Row';
diff --git a/src/types.ts b/src/types.ts
index 561bb651be..ebd01a9671 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -13,19 +13,25 @@ export interface Column {
readonly name: string | ReactElement;
/** A unique key to distinguish each column */
readonly key: string;
- /** Column width. If not specified, it will be determined automatically based on grid width and specified widths of other columns */
+ /**
+ * Column width. If not specified, it will be determined automatically based on grid width and specified widths of other columns
+ * @default 'auto'
+ */
readonly width?: Maybe;
- /** Minimum column width in px. */
+ /**
+ * Minimum column width in px
+ * @default '50px'
+ */
readonly minWidth?: Maybe;
/** Maximum column width in px. */
readonly maxWidth?: Maybe;
readonly cellClass?: Maybe Maybe)>;
readonly headerCellClass?: Maybe;
readonly summaryCellClass?: Maybe Maybe)>;
- /** Render function used to render the content of the column's header cell */
- readonly renderHeaderCell?: Maybe<(props: RenderHeaderCellProps) => ReactNode>;
/** Render function used to render the content of cells */
readonly renderCell?: Maybe<(props: RenderCellProps) => ReactNode>;
+ /** Render function used to render the content of the column's header cell */
+ readonly renderHeaderCell?: Maybe<(props: RenderHeaderCellProps) => ReactNode>;
/** Render function used to render the content of summary cells */
readonly renderSummaryCell?: Maybe<
(props: RenderSummaryCellProps) => ReactNode
@@ -310,10 +316,10 @@ export interface RenderCheckboxProps
}
export interface Renderers {
+ renderCell?: Maybe<(key: Key, props: CellRendererProps) => ReactNode>;
renderCheckbox?: Maybe<(props: RenderCheckboxProps) => ReactNode>;
renderRow?: Maybe<(key: Key, props: RenderRowProps) => ReactNode>;
renderSortStatus?: Maybe<(props: RenderSortStatusProps) => ReactNode>;
- renderCell?: Maybe<(key: Key, props: CellRendererProps) => ReactNode>;
noRowsFallback?: Maybe;
}