npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@piyushnagar/react-editable-table

v1.0.13

Published

A comprehensive, feature-rich React table component with inline editing, sorting, filtering, column resizing, and more

Downloads

15

Readme

React Editable Table

A comprehensive, feature-rich React table component with inline editing, sorting, filtering, column resizing, drag-and-drop row reordering, and much more.

Features

  • Inline Editing - Edit cells directly with support for multiple data types
  • Column Types - Text, Number, Integer, Date, Select, Multi-Select, Boolean, File Upload
  • File Upload - Upload and manage multiple files including images and videos with preview
  • Sorting & Filtering - Advanced column-based filtering with search
  • Column Resizing - Drag to resize columns with minimum width constraints
  • Row Management - Add, delete, and reorder rows with drag-and-drop
  • Keyboard Navigation - Full keyboard support with arrow keys, Tab, Enter
  • Copy/Paste - Excel-like copy/paste functionality with clipboard support
  • Context Menus - Right-click menus for cells and rows
  • Pagination - Built-in pagination with configurable page sizes
  • CSV Export - Export table data to CSV format
  • TypeScript - Full TypeScript support with comprehensive type definitions
  • Responsive - Mobile-friendly design with horizontal scrolling
  • Customizable - Extensive configuration options and styling

Installation

npm install @your-org/react-editable-table

Quick Start

import React, { useState } from 'react';
import { EditableTable, TableColumn, TableRow } from '@your-org/react-editable-table';
import '@your-org/react-editable-table/styles';

const columns: TableColumn[] = [
  {
    id: 'name',
    title: 'Name',
    type: 'text',
    width: 200,
    sortable: true,
    editable: true,
    required: true,
  },
  {
    id: 'email',
    title: 'Email',
    type: 'text',
    width: 250,
    sortable: true,
    editable: true,
  },
  {
    id: 'age',
    title: 'Age',
    type: 'integer',
    width: 100,
    sortable: true,
    editable: true,
  },
  {
    id: 'department',
    title: 'Department',
    type: 'select',
    options: ['Engineering', 'Marketing', 'Sales', 'HR'],
    width: 150,
    sortable: true,
    editable: true,
  },
  {
    id: 'active',
    title: 'Active',
    type: 'boolean',
    width: 100,
    sortable: true,
    editable: true,
  },
];

const initialData: TableRow[] = [
  {
    id: '1',
    name: 'John Doe',
    email: '[email protected]',
    age: 30,
    department: 'Engineering',
    active: true,
  },
  // ... more data
];

function App() {
  const [data, setData] = useState<TableRow[]>(initialData);
  const [tableColumns, setTableColumns] = useState<TableColumn[]>(columns);

  return (
    <EditableTable
      columns={tableColumns}
      data={data}
      sortable={true}
      filterable={true}
      addRows={true}
      deleteRows={true}
      pagination={{ enabled: true, pageSize: 10 }}
      onDataChange={setData}
      onColumnChange={setTableColumns}
    />
  );
}

Column Types

Text

{
  id: 'name',
  title: 'Name',
  type: 'text',
  width: 200,
  editable: true,
  required: true,
}

Number & Integer

{
  id: 'salary',
  title: 'Salary',
  type: 'number', // Supports decimals
  width: 120,
  editable: true,
}

{
  id: 'age',
  title: 'Age',
  type: 'integer', // Whole numbers only
  width: 80,
  editable: true,
}

Date

{
  id: 'startDate',
  title: 'Start Date',
  type: 'date',
  width: 140,
  editable: true,
}

Select (Dropdown)

{
  id: 'department',
  title: 'Department',
  type: 'select',
  options: ['Engineering', 'Marketing', 'Sales', 'HR'],
  width: 150,
  editable: true,
}

Multi-Select

{
  id: 'skills',
  title: 'Skills',
  type: 'multiselect',
  options: ['JavaScript', 'Python', 'React', 'Node.js'],
  width: 200,
  editable: true,
  multiple: true,
}

Boolean

{
  id: 'active',
  title: 'Active',
  type: 'boolean',
  width: 100,
  editable: true,
}

File Upload

{
  id: 'media',
  title: 'Media Files',
  type: 'file',
  width: 250,
  editable: true,
  acceptedFileTypes: ['.jpg', '.png', '.mp4', '.mov', '.webm'], // Images and videos
  maxFileSize: 100 * 1024 * 1024, // 100MB total limit (not per file)
  maxFiles: 3,
}

// File data structure
interface FileData {
  id: string;
  name: string;
  size: number;
  type: string;
  url?: string; // For display/download
  file?: File; // Actual File object for upload
  lastModified?: number;
}

Video File Support

The file upload component now supports video files with:

  • Video Preview: Inline video player with controls during editing
  • Video Formats: MP4, AVI, MOV, WMV, WebM, MKV, and more
  • Visual Indicators: Different colored badges for videos (red), images (green), and documents (purple)
  • Size Management: Configurable file size limits (recommended 10MB+ for videos)
// Example: Video-specific configuration
{
  id: 'videos',
  title: 'Training Videos',
  type: 'file',
  width: 300,
  editable: true,
  acceptedFileTypes: ['.mp4', '.webm', '.mov'], // Video only
  maxFileSize: 100 * 1024 * 1024, // 100MB total limit
  maxFiles: 2,
}

// Access video files in callbacks
const handleCellUpdate = (rowId, columnId, oldValue, newValue) => {
  if (column.type === 'file' && Array.isArray(newValue)) {
    newValue.forEach(fileData => {
      if (fileData.file) {
        // Check if it's a video file
        if (fileData.type.startsWith('video/')) {
          console.log('Video file uploaded:', fileData.name);
          uploadVideoToServer(fileData.file);
        } else {
          uploadFileToServer(fileData.file);
        }
      }
    });
  }
};

Configuration Options

Table Configuration

interface TableConfig {
  columns: TableColumn[];
  data: TableRow[];
  sortable?: boolean;           // Enable sorting (default: true)
  filterable?: boolean;         // Enable filtering (default: true)
  addRows?: boolean;           // Allow adding rows (default: true)
  deleteRows?: boolean;        // Allow deleting rows (default: true)
  addColumns?: boolean;        // Allow adding columns (default: false)
  deleteColumns?: boolean;     // Allow deleting columns (default: false)
  pagination?: {
    enabled: boolean;
    pageSize?: number;          // Items per page (default: 10)
  };
  onDataChange?: (data: TableRow[]) => void;
  onColumnChange?: (columns: TableColumn[]) => void;
  
  // Row-wise callback methods
  onRowAdd?: (newRow: TableRow, insertIndex?: number) => void;
  onRowUpdate?: (updatedRow: TableRow, rowIndex: number, changes: Partial<TableRow>) => void;
  onRowDelete?: (deletedRow: TableRow, rowIndex: number) => void;
  onRowsDelete?: (deletedRows: TableRow[], rowIndices: number[]) => void;
  onRowMove?: (movedRow: TableRow, fromIndex: number, toIndex: number) => void;
  onRowSelect?: (selectedRows: TableRow[], selectedIndices: number[]) => void;
  onRowCopy?: (copiedRows: TableRow[], rowIndices: number[]) => void;
  onRowCut?: (cutRows: TableRow[], rowIndices: number[]) => void;
  onRowPaste?: (pastedRows: TableRow[], targetIndex: number) => void;
  
  // Cell-wise callback methods
  onCellUpdate?: (rowId: string, columnId: string, oldValue: any, newValue: any, rowIndex: number, columnIndex: number) => void;
  onCellSelect?: (rowId: string, columnId: string, value: any, position: CellPosition) => void;
  onCellEdit?: (rowId: string, columnId: string, value: any, position: CellPosition) => void;
  
  // Validation callbacks
  onValidationError?: (errors: ValidationError[]) => void;
  validateRow?: (row: TableRow, rowIndex: number) => ValidationError[];
  validateCell?: (value: any, column: TableColumn, row: TableRow) => string | null;
}

Column Configuration

interface TableColumn {
  id: string;                  // Unique identifier
  title: string;               // Display name
  type: 'text' | 'number' | 'integer' | 'date' | 'select' | 'multiselect' | 'boolean';
  width?: number;              // Column width in pixels
  required?: boolean;          // Required field validation
  options?: string[];          // Options for select/multiselect
  sortable?: boolean;          // Enable sorting for this column
  editable?: boolean;          // Enable editing for this column
  multiple?: boolean;          // For multiselect type
  acceptedFileTypes?: string[]; // For file type - e.g., ['.pdf', '.jpg']
  maxFileSize?: number;        // For file type - in bytes
  maxFiles?: number;           // For file type - maximum number of files
}

Keyboard Shortcuts

  • Arrow Keys - Navigate between cells
  • Tab / Shift+Tab - Navigate to next/previous cell
  • Enter - Start editing selected cell
  • Escape - Cancel editing
  • Delete / Backspace - Clear cell content
  • Ctrl+C - Copy selected cells
  • Ctrl+V - Paste clipboard content
  • Ctrl+X - Cut selected cells

Advanced Usage

Custom Data Validation

import { validateRowData } from '@your-org/react-editable-table';

const errors = validateRowData(rowData, columns);
if (errors.length > 0) {
  console.log('Validation errors:', errors);
}

Sample Data Generation

import { createSampleData } from '@your-org/react-editable-table';

const sampleData = createSampleData(columns, 100); // Generate 100 sample rows

Using Hooks Directly

import { useClipboard, useColumnFilters } from '@your-org/react-editable-table';

// Use individual hooks for custom implementations
const { copyToClipboard, pasteFromClipboard } = useClipboard({
  data,
  columns,
  selectedCell,
  selectionRange,
  onDataChange,
});

Styling

The component uses Tailwind CSS classes. Import the styles:

import '@your-org/react-editable-table/styles';

Or if you're using Tailwind CSS in your project, the component will inherit your theme.

Browser Support

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Changelog

v1.0.0

  • Initial release
  • Full feature set with inline editing, sorting, filtering
  • Column resizing and drag-and-drop row reordering
  • Configurable pagination with customizable page size
  • TypeScript support
  • Comprehensive documentation
  • Enhanced callback system for granular control
  • Built-in validation support