npm package: @saadbaig/sprintx-ui
Description: A high-performance React table component with virtual scrolling, resizable columns, and inline editing
Author: Saad Baig
Latest version: 1.0.1

# @saadbaig/sprintx-ui

A high-performance React table component library with virtual scrolling, resizable columns, and inline editing. Built with React 19, TypeScript, and Tailwind CSS v4.

[![npm version](https://img.shields.io/npm/v/@saadbaig/sprintx-ui.svg)](https://www.npmjs.com/package/@saadbaig/sprintx-ui)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Features

✨ **Virtual Scrolling** - Smooth performance with 10,000+ rows using TanStack Virtual
🎨 **ClickUp-style Design** - Clean, modern aesthetics with OKLCH colors
📏 **Resizable Columns** - Drag handles with min/max constraints
✏️ **Inline Editing** - Click-to-edit with keyboard navigation
📌 **Fixed Header** - Sticky header stays visible during scroll
📍 **Fixed First Column** - Pin the first column for easy reference
📝 **Truncate with Tooltip** - Automatic ellipsis with hover tooltips
♿ **Accessible** - Full ARIA support and keyboard navigation
📦 **Lightweight** - < 50KB gzipped (excluding React)
🎯 **TypeScript** - Full type safety with comprehensive types

## Installation

```bash
npm install @saadbaig/sprintx-ui
```

### Peer Dependencies

Make sure you have the required peer dependencies installed:

```bash
npm install react react-dom
```

## Quick Start

```tsx
import { Table } from '@saadbaig/sprintx-ui';
import '@saadbaig/sprintx-ui/styles';

interface User {
  id: number;
  name: string;
  email: string;
  role: string;
}

const columns = [
  {
    id: 'name',
    header: 'Name',
    accessorKey: 'name',
    width: 200,
    editable: true,
    fixed: true  // Fixed first column
  },
  {
    id: 'email',
    header: 'Email',
    accessorKey: 'email',
    width: 250
  },
  {
    id: 'role',
    header: 'Role',
    accessorKey: 'role',
    width: 150
  }
];

const data: User[] = [
  { id: 1, name: 'Alice Johnson', email: 'alice@example.com', role: 'Engineer' },
  { id: 2, name: 'Bob Smith', email: 'bob@example.com', role: 'Designer' }
];

function App() {
  return (
    <Table
      data={data}
      columns={columns}
      height={600}
      fixedHeader
      fixedFirstColumn
    />
  );
}
```

## API Reference

### Table Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `data` | `TData[]` | **Required** | Array of data objects |
| `columns` | `ColumnDef<TData>[]` | **Required** | Column definitions |
| `height` | `number \| string` | `600` | Container height |
| `width` | `number \| string` | `'100%'` | Container width |
| `virtualScroll` | `boolean` | Auto | Enable virtual scrolling (auto for 100+ rows) |
| `rowHeight` | `number` | `32` | Height of each row in pixels |
| `overscan` | `number` | `5` | Extra rows to render outside viewport |
| `fixedHeader` | `boolean` | `true` | Make header sticky |
| `fixedFirstColumn` | `boolean` | `false` | Make first column sticky |
| `loading` | `boolean` | `false` | Show loading state |
| `emptyMessage` | `string` | `'No data'` | Message when data is empty |
| `onCellEdit` | `function` | - | Callback when cell is edited |
| `onColumnResize` | `function` | - | Callback when column is resized |
| `onRowClick` | `function` | - | Callback when row is clicked |
| `ariaLabel` | `string` | - | Accessible label for the table |

### ColumnDef

```typescript
interface ColumnDef<TData> {
  id: string;                              // Unique column identifier
  header: string | React.ReactNode;        // Header content

  // Data access
  accessorKey?: keyof TData;               // Property key to access
  accessorFn?: (row: TData) => unknown;    // Custom accessor function

  // Rendering
  cell?: (props: CellContext<TData>) => React.ReactNode;

  // Sizing
  width?: number;                          // Default: 150px
  minWidth?: number;                       // Default: 50px
  maxWidth?: number;                       // Default: 800px

  // Features
  resizable?: boolean;                     // Default: true
  editable?: boolean;                      // Default: false
  fixed?: boolean;                         // Fixed column (first only)

  // Styling
  align?: 'left' | 'center' | 'right';    // Default: 'left'
  className?: string;                      // Custom CSS class
}
```

## Examples

### Custom Cell Renderer

```tsx
const columns = [
  {
    id: 'status',
    header: 'Status',
    accessorKey: 'status',
    cell: ({ value }) => (
      <span className={value === 'active' ? 'badge-success' : 'badge-inactive'}>
        {value}
      </span>
    )
  }
];
```

### Inline Editing

```tsx
const [data, setData] = useState(users);

const handleCellEdit = (event) => {
  const newData = [...data];
  newData[event.rowIndex] = {
    ...newData[event.rowIndex],
    [event.column.accessorKey]: event.newValue
  };
  setData(newData);
};

<Table
  data={data}
  columns={columns}
  onCellEdit={handleCellEdit}
/>
```

### Virtual Scrolling with Large Dataset

```tsx
// Automatically enabled for 100+ rows
<Table
  data={largeDataset}  // 10,000+ rows
  columns={columns}
  height={600}
  virtualScroll
/>
```

## Styling

The library uses Tailwind CSS v4 with OKLCH color space. You can customize colors by overriding CSS variables:

```css
:root {
  --surface-primary: 100% 0 0;      /* White */
  --surface-secondary: 98% 0 0;     /* Light gray */
  --surface-hover: 96% 0 0;         /* Hover background */
  --border-subtle: 90% 0 0;         /* Borders */
  --text-primary: 25% 0 0;          /* Near black */
  --text-secondary: 50% 0 0;        /* Medium gray */
  --primary: 60% 0.15 250;          /* Blue accent */
}
```

### Dark Mode

```css
.dark {
  --surface-primary: 20% 0 0;
  --surface-secondary: 25% 0 0;
  --surface-hover: 30% 0 0;
  --border-subtle: 35% 0 0;
  --text-primary: 98% 0 0;
  --text-secondary: 70% 0 0;
}
```

## Keyboard Navigation

- **Arrow Keys** - Navigate between cells
- **Tab / Shift+Tab** - Navigate forward/backward
- **Enter** - Start editing (if editable)
- **Escape** - Cancel editing
- **Enter (in edit mode)** - Commit changes

## Browser Support

- Chrome/Edge (last 2 versions)
- Firefox (last 2 versions)
- Safari (last 2 versions)

## Performance

- **Initial render:** < 100ms for 10,000 rows
- **Scroll FPS:** 60fps consistent
- **Bundle size:** < 50KB gzipped (excluding React)
- **Memory usage:** < 50MB for 100,000 rows

## Development

```bash
# Install dependencies
npm install

# Run tests
npm test

# Run Storybook
npm run storybook

# Build library
npm run build

# Type check
npm run type-check
```

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## License

MIT © [Saad Baig](https://github.com/saadbaig)

## Links

- [GitHub Repository](https://github.com/saadbaig/sprintx-ui)
- [npm Package](https://www.npmjs.com/package/@saadbaig/sprintx-ui)
- [Report Issues](https://github.com/saadbaig/sprintx-ui/issues)