npm package: @nacmias/data-grid
Description: A feature-rich data grid component with toolbar, filtering, sorting, grouping, and row expansion modal
Author: Nacmias
Latest version: 0.1.0

# @nacmias/data-grid

A feature-rich, Airtable-like data grid component for React applications. Built on top of [react-data-grid](https://github.com/adazzle/react-data-grid).

## Features

- **Search** - Global search across all columns
- **Filter** - Column-based filtering with multiple operators
- **Sort** - Single and multi-column sorting
- **Group** - Group rows by column values
- **Column Visibility** - Show/hide columns
- **Row Selection** - Single and multi-select with checkboxes
- **Row Expansion** - Modal for viewing/editing full record
- **Action Buttons** - Customizable actions (expand, webhook, etc.)
- **Custom Editors** - Select dropdowns, date pickers
- **Virtualization** - Efficient rendering of large datasets
- **TypeScript** - Full type support

## Installation

```bash
npm install @nacmias/data-grid
# or
yarn add @nacmias/data-grid
```

## Quick Start

```tsx
import { DataGrid, type ColumnDefinition } from '@nacmias/data-grid';
import '@nacmias/data-grid/styles.css';

interface Contact {
  id: string;
  name: string;
  email: string;
  type: 'person' | 'company';
  created_at: string;
}

const columns: ColumnDefinition<Contact>[] = [
  { key: 'name', name: 'Name', sortable: true, filterable: true },
  { 
    key: 'type', 
    name: 'Type',
    fieldType: 'select',
    selectOptions: [
      { value: 'person', label: 'Person' },
      { value: 'company', label: 'Company' },
    ],
    groupable: true,
  },
  { key: 'email', name: 'Email', fieldType: 'email' },
  { key: 'created_at', name: 'Created', fieldType: 'date' },
];

function App() {
  const [contacts, setContacts] = useState<Contact[]>([]);

  return (
    <div style={{ height: '600px' }}>
      <DataGrid
        data={contacts}
        columns={columns}
        rowKeyGetter={(row) => row.id}
        onRowChange={(row) => console.log('Row changed:', row)}
        onWebhook={(row) => console.log('Webhook:', row)}
      />
    </div>
  );
}
```

## Props

### DataGridProps<T>

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `data` | `T[]` | Required | Array of data rows |
| `columns` | `ColumnDefinition<T>[]` | Required | Column definitions |
| `rowKeyGetter` | `(row: T) => string` | Required | Function to get unique key for each row |
| `onRowChange` | `(row: T) => void` | - | Called when a row is edited |
| `onRowsChange` | `(rows: T[]) => void` | - | Called when rows are bulk changed |
| `onWebhook` | `(row: T) => void` | - | Called when webhook button is clicked |
| `onRowExpand` | `(row: T) => void` | - | Called when row is expanded |
| `onSelectionChange` | `(selectedRows: ReadonlySet<string>) => void` | - | Called when selection changes |
| `enableSearch` | `boolean` | `true` | Enable search functionality |
| `enableFilter` | `boolean` | `true` | Enable filtering |
| `enableSort` | `boolean` | `true` | Enable sorting |
| `enableGroup` | `boolean` | `true` | Enable grouping |
| `enableColumnToggle` | `boolean` | `true` | Enable column visibility toggle |
| `enableSelection` | `boolean` | `true` | Enable row selection |
| `enableActions` | `boolean` | `true` | Enable action buttons column |
| `enableRowExpand` | `boolean` | `true` | Enable row expansion modal |
| `enableWebhook` | `boolean` | `true` | Enable webhook button |
| `height` | `string \| number` | `'100%'` | Grid height |
| `searchPlaceholder` | `string` | `'Search...'` | Search input placeholder |
| `toolbarColors` | `Partial<ToolbarColors>` | - | Custom toolbar button colors |
| `modalTitle` | `(row: T) => string` | - | Custom modal title |
| `modalFields` | `string[]` | - | Fields to show in modal |

### ColumnDefinition<T>

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `key` | `string` | Required | Unique column key |
| `name` | `string` | Required | Column header text |
| `width` | `number` | - | Column width in pixels |
| `minWidth` | `number` | - | Minimum column width |
| `maxWidth` | `number` | - | Maximum column width |
| `frozen` | `boolean` | `false` | Freeze column to left |
| `resizable` | `boolean` | `true` | Allow column resize |
| `sortable` | `boolean` | `true` | Allow sorting |
| `filterable` | `boolean` | `true` | Allow filtering |
| `groupable` | `boolean` | `false` | Allow grouping by this column |
| `editable` | `boolean` | `true` | Allow editing in modal |
| `fieldType` | `FieldType` | `'text'` | Field type for modal editor |
| `selectOptions` | `SelectOption[]` | - | Options for select field type |
| `getValue` | `(row: T) => unknown` | - | Custom value getter |
| `setValue` | `(row: T, value: unknown) => T` | - | Custom value setter |
| `renderCell` | `(props) => ReactNode` | - | Custom cell renderer |
| `renderEditCell` | `(props) => ReactNode` | - | Custom cell editor |

### FieldType

- `'text'` - Text input
- `'number'` - Number input
- `'email'` - Email input
- `'phone'` - Phone input
- `'select'` - Dropdown select
- `'date'` - Date picker
- `'datetime'` - DateTime picker
- `'readonly'` - Read-only display

## Toolbar Colors

Customize the Airtable-like color-coded toolbar buttons:

```tsx
<DataGrid
  toolbarColors={{
    columns: { main: '#7c3aed', bg: '#f3e8ff' }, // Purple
    sort: { main: '#2563eb', bg: '#dbeafe' },    // Blue
    filter: { main: '#16a34a', bg: '#dcfce7' },  // Green
    group: { main: '#d97706', bg: '#fef3c7' },   // Amber
  }}
/>
```

## Custom Cell Renderers

```tsx
const columns: ColumnDefinition<Contact>[] = [
  {
    key: 'status',
    name: 'Status',
    renderCell: ({ row }) => (
      <span style={{
        padding: '2px 8px',
        borderRadius: '4px',
        background: row.status === 'active' ? '#dcfce7' : '#fee2e2',
        color: row.status === 'active' ? '#16a34a' : '#dc2626',
      }}>
        {row.status}
      </span>
    ),
  },
];
```

## Nested Values

Handle nested object properties:

```tsx
const columns: ColumnDefinition<Contact>[] = [
  {
    key: 'city',
    name: 'City',
    getValue: (row) => row.address?.city,
    setValue: (row, value) => ({
      ...row,
      address: { ...row.address, city: value as string },
    }),
  },
];
```

## Exported Components

You can also use individual components:

```tsx
import {
  DataGrid,
  GridToolbar,
  RecordModal,
  SelectEditor,
  DateEditor,
  createSelectEditor,
} from '@nacmias/data-grid';
```

## Development

```bash
# Install dependencies
npm install

# Build
npm run build

# Watch mode
npm run dev

# Type check
npm run typecheck
```

## License

MIT