CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-data-grid

Excel-like grid component built with React, with editors, keyboard navigation, copy & paste, and the like

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

components.mddocs/

Components and Customization

Core building blocks and advanced customization options for creating custom grid rendering and specialized functionality.

Capabilities

Core Components

Low-level components that make up the grid structure, available for advanced customization scenarios.

/** Core grid row component */
const Row: React.ComponentType<RowProps>;

/** Individual cell component */
const Cell: React.ComponentType<CellProps>;

/** Header cell component */
const HeaderCell: React.ComponentType<HeaderCellProps>;

/** Empty child row placeholder */
const EmptyChildRow: React.ComponentType<EmptyChildRowProps>;

Row Component

Individual row component that renders a collection of cells.

interface RowProps {
  /** Row index in the dataset */
  idx: number;
  /** Starting column index for visible columns */
  visibleStart: number;
  /** Ending column index for visible columns */
  visibleEnd: number;
  /** Row data object */
  row: any;
  /** Row height in pixels */
  height: number;
  /** Array of column definitions */
  columns: Column[];
  /** Whether the row is selected */
  isSelected?: boolean;
  /** Whether the row is being scrolled */
  isScrolling?: boolean;
  /** CSS classes to apply to the row */
  extraClasses?: string;
  /** Function to get cell actions */
  getCellActions?: (column: Column, row: any) => CellAction[];
  /** Cell selection range */
  cellSelection?: SelectionRange;
  /** Event handlers for row interactions */
  onRowClick?: (rowIdx: number, row: any) => void;
  onRowDoubleClick?: (rowIdx: number, row: any) => void;
  onCellClick?: (position: Position) => void;
  onCellDoubleClick?: (position: Position) => void;
  onCellContextMenu?: (position: Position) => void;
  onDragEnter?: (overRowIdx: number) => void;
}

/**
 * Row component for rendering individual grid rows
 * Handles cell rendering, selection, and user interactions
 */
const Row: React.ComponentType<RowProps>;

Cell Component

Individual cell component that handles content rendering, editing, and interactions.

interface CellProps {
  /** Column definition */
  column: Column;
  /** Cell value */
  value: any;
  /** Complete row data */
  row: any;
  /** Row index */
  rowIdx: number;
  /** Column index */
  idx: number;
  /** Whether the cell is selected */
  isSelected?: boolean;
  /** Whether the cell is being edited */
  isEditing?: boolean;
  /** Whether the cell can be copied */
  isCopied?: boolean;
  /** Cell height in pixels */
  height: number;
  /** Event handlers */
  onCellClick?: (position: Position) => void;
  onCellDoubleClick?: (position: Position) => void;
  onCellContextMenu?: (position: Position) => void;
  onCellExpand?: (args: CellExpandArgs) => void;
  onCommit?: (args: CommitArgs) => void;
  onCommitCancel?: () => void;
}

/**
 * Cell component for rendering individual grid cells
 * Handles content display, editing, and cell-specific interactions
 */
const Cell: React.ComponentType<CellProps>;

HeaderCell Component

Header cell component for column headers with sorting, filtering, and resizing capabilities.

interface HeaderCellProps {
  /** Column definition */
  column: Column;
  /** Row type (header, filter, etc.) */
  rowType: string;
  /** Cell height in pixels */
  height: number;
  /** Event handlers */
  onSort?: (columnKey: string, direction: SortDirection) => void;
  onResize?: (column: Column, width: number) => void;
  onHeaderDrop?: () => void;
  onFilterChange?: (filter: Filter) => void;
  /** Current sort configuration */
  sortColumn?: string;
  sortDirection?: SortDirection;
  /** Whether the column can be dragged */
  draggableHeaderCell?: React.ComponentType<any>;
}

/**
 * Header cell component for column headers
 * Supports sorting, filtering, resizing, and custom header rendering
 */
const HeaderCell: React.ComponentType<HeaderCellProps>;

EmptyChildRow Component

Placeholder component for empty child rows in hierarchical data structures.

interface EmptyChildRowProps {
  /** Row height in pixels */
  height: number;
  /** Column definitions */
  columns: Column[];
  /** Additional CSS classes */
  extraClasses?: string;
}

/**
 * Empty child row component for hierarchical data
 * Renders placeholder rows for expanded parent rows with no children
 */
const EmptyChildRow: React.ComponentType<EmptyChildRowProps>;

Custom Component Integration

Using core components for advanced customization scenarios.

Custom Row Renderer Example:

import React from 'react';
import ReactDataGrid, { Row } from 'react-data-grid';

const CustomRow = (props) => {
  const { row, idx } = props;
  
  // Add custom styling based on row data
  const customStyle = {
    backgroundColor: row.priority === 'high' ? '#fff3cd' : undefined,
    fontWeight: row.isImportant ? 'bold' : 'normal'
  };
  
  return (
    <div style={customStyle}>
      <Row {...props} />
    </div>
  );
};

// Usage with custom row renderer
const GridWithCustomRows = () => {
  return (
    <ReactDataGrid
      columns={columns}
      rowGetter={i => rows[i]}
      rowsCount={rows.length}
      minHeight={400}
      rowGroupRenderer={CustomRow}
    />
  );
};

Custom Cell Actions Example:

import ReactDataGrid from 'react-data-grid';

const getCellActions = (column, row) => {
  if (column.key === 'actions') {
    return [
      {
        icon: 'edit',
        text: 'Edit',
        callback: () => console.log('Edit:', row)
      },
      {
        icon: 'delete',
        text: 'Delete',
        callback: () => console.log('Delete:', row)
      }
    ];
  }
  return [];
};

const GridWithActions = () => {
  return (
    <ReactDataGrid
      columns={columns}
      rowGetter={i => rows[i]}
      rowsCount={rows.length}
      minHeight={400}
      getCellActions={getCellActions}
    />
  );
};

Component Types and Interfaces

Supporting types and interfaces for component customization.

interface Position {
  /** Column index */
  idx: number;
  /** Row index */
  rowIdx: number;
}

interface SelectionRange {
  /** Top-left position */
  topLeft: Position;
  /** Bottom-right position */
  bottomRight: Position;
}

interface CellAction {
  /** Action icon identifier */
  icon: string;
  /** Display text for the action */
  text: string;
  /** Callback function when action is triggered */
  callback: () => void;
  /** Whether the action is disabled */
  disabled?: boolean;
}

interface CellExpandArgs {
  /** Row index */
  rowIdx: number;
  /** Column index */
  idx: number;
  /** Row data */
  rowData: any;
  /** Expand arguments */
  expandArgs: any;
}

interface CommitArgs {
  /** Cell position */
  position: Position;
  /** Updated value */
  updated: any;
  /** Update action type */
  action: string;
}

Advanced Customization

Complex customization scenarios using core components and custom renderers.

Custom Header with Actions:

import React from 'react';

const CustomHeaderCell = ({ column, onSort, sortColumn, sortDirection }) => {
  const handleSort = () => {
    const newDirection = 
      sortColumn === column.key && sortDirection === 'ASC' ? 'DESC' : 'ASC';
    onSort(column.key, newDirection);
  };
  
  const getSortIcon = () => {
    if (sortColumn !== column.key) return '↕️';
    return sortDirection === 'ASC' ? '↑' : '↓';
  };
  
  return (
    <div style={{ 
      display: 'flex', 
      justifyContent: 'space-between', 
      alignItems: 'center',
      padding: '8px'
    }}>
      <span>{column.name}</span>
      <div style={{ display: 'flex', gap: '4px' }}>
        {column.sortable && (
          <button 
            onClick={handleSort}
            style={{ border: 'none', background: 'none', cursor: 'pointer' }}
          >
            {getSortIcon()}
          </button>
        )}
        <button 
          onClick={() => console.log('Filter', column.key)}
          style={{ border: 'none', background: 'none', cursor: 'pointer' }}
        >
          🔍
        </button>
      </div>
    </div>
  );
};

// Usage in column definitions
const customColumns = [
  { 
    key: 'id', 
    name: 'ID',
    headerRenderer: <CustomHeaderCell />
  },
  { 
    key: 'name', 
    name: 'Name',
    sortable: true,
    headerRenderer: <CustomHeaderCell />
  }
];

Custom Cell with Rich Content:

const RichCell = ({ value, row, column }) => {
  if (column.key === 'profile') {
    return (
      <div style={{ 
        display: 'flex', 
        alignItems: 'center', 
        gap: '8px',
        padding: '4px'
      }}>
        <img 
          src={row.avatar} 
          alt={row.name}
          style={{ 
            width: '32px', 
            height: '32px', 
            borderRadius: '50%'
          }}
        />
        <div>
          <div style={{ fontWeight: 'bold' }}>{row.name}</div>
          <div style={{ fontSize: '12px', color: '#666' }}>{row.email}</div>
        </div>
      </div>
    );
  }
  
  return <div>{value}</div>;
};

const richColumns = [
  { key: 'id', name: 'ID' },
  { 
    key: 'profile', 
    name: 'Profile',
    formatter: <RichCell />
  },
  { key: 'status', name: 'Status' }
];

Custom Toolbar Integration:

const CustomToolbar = ({ onAddRow, onDeleteRows, selectedCount }) => {
  return (
    <div style={{ 
      padding: '8px', 
      backgroundColor: '#f8f9fa', 
      borderBottom: '1px solid #dee2e6',
      display: 'flex',
      gap: '8px',
      alignItems: 'center'
    }}>
      <button onClick={onAddRow}>Add Row</button>
      <button 
        onClick={onDeleteRows}
        disabled={selectedCount === 0}
      >
        Delete Selected ({selectedCount})
      </button>
      <div style={{ marginLeft: 'auto' }}>
        Total: {rows.length} rows
      </div>
    </div>
  );
};

const GridWithToolbar = () => {
  const [selectedRows, setSelectedRows] = useState([]);
  
  return (
    <ReactDataGrid
      columns={columns}
      rowGetter={i => rows[i]}
      rowsCount={rows.length}
      minHeight={400}
      toolbar={
        <CustomToolbar 
          onAddRow={handleAddRow}
          onDeleteRows={handleDeleteRows}
          selectedCount={selectedRows.length}
        />
      }
      rowSelection={{
        showCheckbox: true,
        onRowsSelected: setSelectedRows,
        selectBy: { indexes: selectedRows }
      }}
    />
  );
};

Performance Optimization

Tips for optimizing custom components for better grid performance.

import React, { memo, useMemo } from 'react';

// Memoized custom formatter
const OptimizedFormatter = memo(({ value, row, column }) => {
  const processedValue = useMemo(() => {
    return expensiveProcessing(value);
  }, [value]);
  
  return <div>{processedValue}</div>;
});

// Memoized row component
const OptimizedRow = memo((props) => {
  return <Row {...props} />;
}, (prevProps, nextProps) => {
  // Custom comparison logic
  return (
    prevProps.row === nextProps.row &&
    prevProps.isSelected === nextProps.isSelected &&
    prevProps.visibleStart === nextProps.visibleStart &&
    prevProps.visibleEnd === nextProps.visibleEnd
  );
});

Install with Tessl CLI

npx tessl i tessl/npm-react-data-grid

docs

components.md

core-grid.md

editors.md

formatters.md

index.md

selection.md

utilities.md

tile.json