From 9af6ac08e40f5840edf0cb883b9482c147e9f958 Mon Sep 17 00:00:00 2001 From: Leon Sorokin Date: Mon, 28 Apr 2025 13:26:11 -0500 Subject: [PATCH 1/4] PoC: Add grid.rowStyle and col.cellStyle options --- src/Cell.tsx | 8 ++++++-- src/DataGrid.tsx | 4 ++++ src/Row.tsx | 10 +++++++++- src/types.ts | 3 +++ website/routes/AllFeatures.tsx | 6 +++++- 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/Cell.tsx b/src/Cell.tsx index 128cdd113e..6db547db08 100644 --- a/src/Cell.tsx +++ b/src/Cell.tsx @@ -31,7 +31,7 @@ function Cell({ }: CellRendererProps) { const { tabIndex, childTabIndex, onFocus } = useRovingTabIndex(isCellSelected); - const { cellClass } = column; + const { cellClass, cellStyle } = column; className = getCellClassname( column, { @@ -40,6 +40,9 @@ function Cell({ typeof cellClass === 'function' ? cellClass(row) : cellClass, className ); + + const _cellStyle = typeof cellStyle === 'function' ? cellStyle(row) : cellStyle; + const isEditable = isCellEditableUtil(column, row); function selectCellWrapper(openEditor?: boolean) { @@ -88,7 +91,8 @@ function Cell({ className={className} style={{ ...getCellStyle(column, colSpan), - ...style + ...style, + ..._cellStyle }} onClick={handleClick} onDoubleClick={handleDoubleClick} diff --git a/src/DataGrid.tsx b/src/DataGrid.tsx index bfd99d9511..b0a5284efc 100644 --- a/src/DataGrid.tsx +++ b/src/DataGrid.tsx @@ -232,6 +232,8 @@ export interface DataGridProps extends Sha renderers?: Maybe, NoInfer>>; /** Function to apply custom class names to rows */ rowClass?: Maybe<(row: NoInfer, rowIdx: number) => Maybe>; + /** Function to apply custom row style */ + rowStyle?: Maybe<(row: NoInfer, rowIdx: number) => Maybe>; /** Custom class name for the header row */ headerRowClass?: Maybe; /** @@ -292,6 +294,7 @@ export function DataGrid(props: DataGridPr className, style, rowClass, + rowStyle, headerRowClass, direction: rawDirection, // ARIA @@ -1145,6 +1148,7 @@ export function DataGrid(props: DataGridPr onCellDoubleClick: onCellDoubleClickLatest, onCellContextMenu: onCellContextMenuLatest, rowClass, + rowStyle, gridRowStart, selectedCellIdx: selectedRowIdx === rowIdx ? selectedIdx : undefined, draggedOverCellIdx: getDraggedOverCellIdx(rowIdx), diff --git a/src/Row.tsx b/src/Row.tsx index 7b92e964f7..4b20a6216c 100644 --- a/src/Row.tsx +++ b/src/Row.tsx @@ -23,6 +23,7 @@ function Row({ onCellDoubleClick, onCellContextMenu, rowClass, + rowStyle, onRowChange, selectCell, ...props @@ -43,6 +44,8 @@ function Row({ className ); + const _rowStyle = rowStyle?.(row, rowIdx); + const cells = []; for (let index = 0; index < viewportColumns.length; index++) { @@ -83,7 +86,12 @@ function Row({ return ( -
+
{cells}
diff --git a/src/types.ts b/src/types.ts index 9e1adc4014..0162f60896 100644 --- a/src/types.ts +++ b/src/types.ts @@ -27,6 +27,8 @@ export interface Column { readonly maxWidth?: Maybe; /** Class name(s) for the cell */ readonly cellClass?: Maybe Maybe)>; + /** Styles for the cell */ + readonly cellStyle?: Maybe Maybe)>; /** Class name(s) for the header cell */ readonly headerCellClass?: Maybe; /** Class name(s) for the summary cell */ @@ -241,6 +243,7 @@ export interface RenderRowProps selectedCellEditor: ReactElement> | undefined; onRowChange: (column: CalculatedColumn, rowIdx: number, newRow: TRow) => void; rowClass: Maybe<(row: TRow, rowIdx: number) => Maybe>; + rowStyle: Maybe<(row: TRow, rowIdx: number) => Maybe>; } export interface RowsChangeData { diff --git a/website/routes/AllFeatures.tsx b/website/routes/AllFeatures.tsx index 21b16e10ed..b629e9102e 100644 --- a/website/routes/AllFeatures.tsx +++ b/website/routes/AllFeatures.tsx @@ -141,7 +141,8 @@ const columns: readonly Column[] = [ width: 200, resizable: true, frozen: true, - renderEditCell: textEditor + renderEditCell: textEditor, + cellStyle: (row) => (row.lastName.startsWith('S') ? { color: '#ff9800' } : null) }, { key: 'email', @@ -295,6 +296,9 @@ function AllFeatures() { [copiedRowClassname]: copiedCell?.row === row }); }} + rowStyle={(row) => { + return row.email.includes('_') ? { color: '#2196f3' } : null; + }} direction={direction} onCellClick={(args, event) => { if (args.column.key === 'title') { From 2835a72089b1ad85e0ea9c0e849d3e4136fc0c7f Mon Sep 17 00:00:00 2001 From: Leon Sorokin Date: Fri, 2 May 2025 14:14:56 -0500 Subject: [PATCH 2/4] Revert "PoC: Add grid.rowStyle and col.cellStyle options" This reverts commit 9af6ac08e40f5840edf0cb883b9482c147e9f958. --- src/Cell.tsx | 8 ++------ src/DataGrid.tsx | 4 ---- src/Row.tsx | 10 +--------- src/types.ts | 3 --- website/routes/AllFeatures.tsx | 6 +----- 5 files changed, 4 insertions(+), 27 deletions(-) diff --git a/src/Cell.tsx b/src/Cell.tsx index 6db547db08..128cdd113e 100644 --- a/src/Cell.tsx +++ b/src/Cell.tsx @@ -31,7 +31,7 @@ function Cell({ }: CellRendererProps) { const { tabIndex, childTabIndex, onFocus } = useRovingTabIndex(isCellSelected); - const { cellClass, cellStyle } = column; + const { cellClass } = column; className = getCellClassname( column, { @@ -40,9 +40,6 @@ function Cell({ typeof cellClass === 'function' ? cellClass(row) : cellClass, className ); - - const _cellStyle = typeof cellStyle === 'function' ? cellStyle(row) : cellStyle; - const isEditable = isCellEditableUtil(column, row); function selectCellWrapper(openEditor?: boolean) { @@ -91,8 +88,7 @@ function Cell({ className={className} style={{ ...getCellStyle(column, colSpan), - ...style, - ..._cellStyle + ...style }} onClick={handleClick} onDoubleClick={handleDoubleClick} diff --git a/src/DataGrid.tsx b/src/DataGrid.tsx index b0a5284efc..bfd99d9511 100644 --- a/src/DataGrid.tsx +++ b/src/DataGrid.tsx @@ -232,8 +232,6 @@ export interface DataGridProps extends Sha renderers?: Maybe, NoInfer>>; /** Function to apply custom class names to rows */ rowClass?: Maybe<(row: NoInfer, rowIdx: number) => Maybe>; - /** Function to apply custom row style */ - rowStyle?: Maybe<(row: NoInfer, rowIdx: number) => Maybe>; /** Custom class name for the header row */ headerRowClass?: Maybe; /** @@ -294,7 +292,6 @@ export function DataGrid(props: DataGridPr className, style, rowClass, - rowStyle, headerRowClass, direction: rawDirection, // ARIA @@ -1148,7 +1145,6 @@ export function DataGrid(props: DataGridPr onCellDoubleClick: onCellDoubleClickLatest, onCellContextMenu: onCellContextMenuLatest, rowClass, - rowStyle, gridRowStart, selectedCellIdx: selectedRowIdx === rowIdx ? selectedIdx : undefined, draggedOverCellIdx: getDraggedOverCellIdx(rowIdx), diff --git a/src/Row.tsx b/src/Row.tsx index 4b20a6216c..7b92e964f7 100644 --- a/src/Row.tsx +++ b/src/Row.tsx @@ -23,7 +23,6 @@ function Row({ onCellDoubleClick, onCellContextMenu, rowClass, - rowStyle, onRowChange, selectCell, ...props @@ -44,8 +43,6 @@ function Row({ className ); - const _rowStyle = rowStyle?.(row, rowIdx); - const cells = []; for (let index = 0; index < viewportColumns.length; index++) { @@ -86,12 +83,7 @@ function Row({ return ( -
+
{cells}
diff --git a/src/types.ts b/src/types.ts index 0162f60896..9e1adc4014 100644 --- a/src/types.ts +++ b/src/types.ts @@ -27,8 +27,6 @@ export interface Column { readonly maxWidth?: Maybe; /** Class name(s) for the cell */ readonly cellClass?: Maybe Maybe)>; - /** Styles for the cell */ - readonly cellStyle?: Maybe Maybe)>; /** Class name(s) for the header cell */ readonly headerCellClass?: Maybe; /** Class name(s) for the summary cell */ @@ -243,7 +241,6 @@ export interface RenderRowProps selectedCellEditor: ReactElement> | undefined; onRowChange: (column: CalculatedColumn, rowIdx: number, newRow: TRow) => void; rowClass: Maybe<(row: TRow, rowIdx: number) => Maybe>; - rowStyle: Maybe<(row: TRow, rowIdx: number) => Maybe>; } export interface RowsChangeData { diff --git a/website/routes/AllFeatures.tsx b/website/routes/AllFeatures.tsx index b629e9102e..21b16e10ed 100644 --- a/website/routes/AllFeatures.tsx +++ b/website/routes/AllFeatures.tsx @@ -141,8 +141,7 @@ const columns: readonly Column[] = [ width: 200, resizable: true, frozen: true, - renderEditCell: textEditor, - cellStyle: (row) => (row.lastName.startsWith('S') ? { color: '#ff9800' } : null) + renderEditCell: textEditor }, { key: 'email', @@ -296,9 +295,6 @@ function AllFeatures() { [copiedRowClassname]: copiedCell?.row === row }); }} - rowStyle={(row) => { - return row.email.includes('_') ? { color: '#2196f3' } : null; - }} direction={direction} onCellClick={(args, event) => { if (args.column.key === 'title') { From 84ac4a0f945cb0b04acb2de14a3f74cc45fdb096 Mon Sep 17 00:00:00 2001 From: Leon Sorokin Date: Fri, 2 May 2025 14:40:14 -0500 Subject: [PATCH 3/4] different approach --- src/index.ts | 4 ++-- src/types.ts | 2 +- website/routes/AllFeatures.tsx | 29 +++++++++++++++++++++++++++-- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/index.ts b/src/index.ts index a4940bb07b..7c72567b2b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,8 +8,8 @@ export { } from './DataGrid'; export { TreeDataGrid, type TreeDataGridProps } from './TreeDataGrid'; export { DataGridDefaultRenderersContext } from './DataGridDefaultRenderersContext'; -export { default as Row } from './Row'; -export { default as Cell } from './Cell'; +export { default as Row, defaultRenderRow } from './Row'; +export { default as Cell, defaultRenderCell } from './Cell'; export * from './Columns'; export * from './cellRenderers'; export { default as textEditor } from './editors/textEditor'; diff --git a/src/types.ts b/src/types.ts index 9e1adc4014..ada154d0b6 100644 --- a/src/types.ts +++ b/src/types.ts @@ -219,7 +219,7 @@ export interface CellSelectArgs { } export interface BaseRenderRowProps - extends Omit, 'style' | 'children'>, + extends Omit, 'children'>, Pick< DataGridProps, 'onCellClick' | 'onCellDoubleClick' | 'onCellContextMenu' diff --git a/website/routes/AllFeatures.tsx b/website/routes/AllFeatures.tsx index 21b16e10ed..9238f42004 100644 --- a/website/routes/AllFeatures.tsx +++ b/website/routes/AllFeatures.tsx @@ -4,8 +4,16 @@ import { createFileRoute } from '@tanstack/react-router'; import { css } from '@linaria/core'; import clsx from 'clsx'; -import { DataGrid, SelectColumn, textEditor } from '../../src'; -import type { CalculatedColumn, CellCopyEvent, CellPasteEvent, Column, FillEvent } from '../../src'; +import { DataGrid, defaultRenderCell, defaultRenderRow, SelectColumn, textEditor } from '../../src'; +import type { + CalculatedColumn, + CellCopyEvent, + CellPasteEvent, + CellRendererProps, + Column, + FillEvent, + RenderRowProps +} from '../../src'; import { textEditorClassname } from '../../src/editors/textEditor'; import { useDirection } from '../directionContext'; @@ -44,6 +52,19 @@ function createRows(): Row[] { return rows; } +function renderRow(key: React.Key, props: RenderRowProps>) { + const style = props.row.email.includes('_') ? { color: '#2196f3' } : null; + return defaultRenderRow(key, { ...props, style: { ...props.style, ...style } }); +} + +function renderCell(key: React.Key, props: CellRendererProps, unknown>) { + const style = + props.column.key === 'lastName' && props.row.lastName.startsWith('S') + ? { color: '#ff9800' } + : null; + return defaultRenderCell(key, { ...props, style: { ...props.style, ...style } }); +} + const highlightClassname = css` .rdg-cell { background-color: #9370db; @@ -289,6 +310,10 @@ function AllFeatures() { isRowSelectionDisabled={(row) => row.id === 'id_2'} onSelectedRowsChange={setSelectedRows} className="fill-grid" + renderers={{ + renderRow, + renderCell + }} rowClass={(row, index) => { return clsx({ [highlightClassname]: row.id.includes('7') || index === 0, From c68c6530bf10074d6aab6f199097d243236a2d13 Mon Sep 17 00:00:00 2001 From: Aman Mahajan Date: Sat, 3 May 2025 21:24:06 -0500 Subject: [PATCH 4/4] Fix row style, update example --- src/Row.tsx | 11 ++++++++- src/index.ts | 4 ++-- website/routes/AllFeatures.tsx | 29 ++--------------------- website/routes/CustomizableRenderers.tsx | 30 +++++++++++++++++++++--- 4 files changed, 41 insertions(+), 33 deletions(-) diff --git a/src/Row.tsx b/src/Row.tsx index 7b92e964f7..711276b7a8 100644 --- a/src/Row.tsx +++ b/src/Row.tsx @@ -25,6 +25,7 @@ function Row({ rowClass, onRowChange, selectCell, + style, ...props }: RenderRowProps) { const renderCell = useDefaultRenderers()!.renderCell!; @@ -83,7 +84,15 @@ function Row({ return ( -
+
{cells}
diff --git a/src/index.ts b/src/index.ts index 7c72567b2b..a4940bb07b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,8 +8,8 @@ export { } from './DataGrid'; export { TreeDataGrid, type TreeDataGridProps } from './TreeDataGrid'; export { DataGridDefaultRenderersContext } from './DataGridDefaultRenderersContext'; -export { default as Row, defaultRenderRow } from './Row'; -export { default as Cell, defaultRenderCell } from './Cell'; +export { default as Row } from './Row'; +export { default as Cell } from './Cell'; export * from './Columns'; export * from './cellRenderers'; export { default as textEditor } from './editors/textEditor'; diff --git a/website/routes/AllFeatures.tsx b/website/routes/AllFeatures.tsx index 9238f42004..21b16e10ed 100644 --- a/website/routes/AllFeatures.tsx +++ b/website/routes/AllFeatures.tsx @@ -4,16 +4,8 @@ import { createFileRoute } from '@tanstack/react-router'; import { css } from '@linaria/core'; import clsx from 'clsx'; -import { DataGrid, defaultRenderCell, defaultRenderRow, SelectColumn, textEditor } from '../../src'; -import type { - CalculatedColumn, - CellCopyEvent, - CellPasteEvent, - CellRendererProps, - Column, - FillEvent, - RenderRowProps -} from '../../src'; +import { DataGrid, SelectColumn, textEditor } from '../../src'; +import type { CalculatedColumn, CellCopyEvent, CellPasteEvent, Column, FillEvent } from '../../src'; import { textEditorClassname } from '../../src/editors/textEditor'; import { useDirection } from '../directionContext'; @@ -52,19 +44,6 @@ function createRows(): Row[] { return rows; } -function renderRow(key: React.Key, props: RenderRowProps>) { - const style = props.row.email.includes('_') ? { color: '#2196f3' } : null; - return defaultRenderRow(key, { ...props, style: { ...props.style, ...style } }); -} - -function renderCell(key: React.Key, props: CellRendererProps, unknown>) { - const style = - props.column.key === 'lastName' && props.row.lastName.startsWith('S') - ? { color: '#ff9800' } - : null; - return defaultRenderCell(key, { ...props, style: { ...props.style, ...style } }); -} - const highlightClassname = css` .rdg-cell { background-color: #9370db; @@ -310,10 +289,6 @@ function AllFeatures() { isRowSelectionDisabled={(row) => row.id === 'id_2'} onSelectedRowsChange={setSelectedRows} className="fill-grid" - renderers={{ - renderRow, - renderCell - }} rowClass={(row, index) => { return clsx({ [highlightClassname]: row.id.includes('7') || index === 0, diff --git a/website/routes/CustomizableRenderers.tsx b/website/routes/CustomizableRenderers.tsx index d8d4ba165f..c1ae4ccb33 100644 --- a/website/routes/CustomizableRenderers.tsx +++ b/website/routes/CustomizableRenderers.tsx @@ -2,8 +2,15 @@ import { useMemo, useState } from 'react'; import { createFileRoute } from '@tanstack/react-router'; import { css } from '@linaria/core'; -import { DataGrid, SelectColumn, textEditor } from '../../src'; -import type { Column, RenderCheckboxProps, RenderSortStatusProps, SortColumn } from '../../src'; +import { Row as BaseRow, Cell, DataGrid, SelectColumn, textEditor } from '../../src'; +import type { + CellRendererProps, + Column, + RenderCheckboxProps, + RenderRowProps, + RenderSortStatusProps, + SortColumn +} from '../../src'; import { useDirection } from '../directionContext'; export const Route = createFileRoute('/CustomizableRenderers')({ @@ -115,7 +122,7 @@ function CustomizableRenderers() { onSortColumnsChange={setSortColumns} selectedRows={selectedRows} onSelectedRowsChange={setSelectedRows} - renderers={{ renderSortStatus, renderCheckbox }} + renderers={{ renderSortStatus, renderCheckbox, renderCell, renderRow }} direction={direction} /> ); @@ -149,6 +156,23 @@ function renderSortStatus({ sortDirection, priority }: RenderSortStatusProps) { ); } +const cellStyle: React.CSSProperties = { color: 'red' }; + +function renderCell(key: React.Key, props: CellRendererProps) { + const style = + props.column.key === 'priority' && props.row.priority === 'Critical' ? cellStyle : undefined; + + return ; +} + +const rowStyle: React.CSSProperties = { color: 'green' }; + +function renderRow(key: React.Key, props: RenderRowProps) { + const style = props.row.complete === 100 ? rowStyle : undefined; + + return ; +} + function rowKeyGetter(row: Row) { return row.id; }