poc-table-dragandrop
v0.2.7
Published
Draggable table React component (POC) with reorderable columns
Readme
POC Table Drag and Drop
Minimal Vite + React proof-of-concept demonstrating draggable table rows.
Quick start
cd /Volumes/extended/project/poc-table-dragandrop
npm install
npm run devBuild
npm run build
npm run previewNote about dependencies
If you see peer dependency resolution errors during npm install, run:
npm install --legacy-peer-depsThis project uses Vite 5 and @vitejs/plugin-react; some plugin versions may have peer constraints targeting Vite 4.x. Using --legacy-peer-deps is a pragmatic way to install in local dev. For production, prefer aligning plugin versions.
Building the library
This repo includes a small library entry under src/lib/ exporting a DraggableTable component. To build the library bundles (ES / UMD):
npm run build:libThe output will be in dist/ (files named draggable-table.es.js, draggable-table.umd.js, etc.). React is externalized by default.
Usage examples
Installation:
npm install poc-table-dragandrop antdRequirements:
- React ^18.0.0
- Ant Design ^4.0.0 or ^5.0.0 (for TablePaginationNew component)
1. DraggableTable (Vanilla React)
import { DraggableTable } from 'poc-table-dragandrop'
const columns = [
{ key: 'col1', label: 'Column 1' },
{ key: 'col2', label: 'Column 2' },
{ key: 'col3', label: 'Column 3' },
{ key: 'col4', label: 'Column 4' }
]
const rows = [
{ id: 1, col1: 'A1', col2: 'A2', col3: 'A3', col4: 'A4' },
{ id: 2, col1: 'B1', col2: 'B2', col3: 'B3', col4: 'B4' },
]
function App() {
return (
<DraggableTable
initialColumns={columns}
initialRows={rows}
freezeLastColumn={true} // optional: freeze last column
/>
)
}2. TablePaginationNew (with Ant Design)
import { TablePaginationNew } from 'poc-table-dragandrop'
import { useState } from 'react'
// Define columns (Ant Design format)
const columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
},
{
title: 'Age',
dataIndex: 'age',
key: 'age',
},
{
title: 'Address',
dataIndex: 'address',
key: 'address',
},
]
// Sample data
const data = [
{ key: '1', name: 'John', age: 32, address: 'New York' },
{ key: '2', name: 'Jane', age: 28, address: 'London' },
// ... more data
]
function App() {
const [current, setCurrent] = useState(1)
const [pageSize, setPageSize] = useState(10)
const handlePageChange = (page, size) => {
setCurrent(page)
setPageSize(size)
}
return (
<TablePaginationNew
dataSource={data}
columns={columns}
// Pagination
current={current}
pageSize={pageSize}
totalData={100} // total records (for backend pagination)
onChange={handlePageChange}
usePagination={true}
// Features
enableDragColumn={true} // ✅ Enable column dragging & resizing
freezeColumns={[0, 'email']} // ✅ Freeze columns by index or key
useSelect={true} // Show column visibility selector
loading={false}
// Optional
type="BE" // "BE" for backend pagination, "FE" for frontend
className="custom-class"
tableScrolled={{ x: 1000, y: 400 }}
// Event handlers
onSort={(pagination, filters, sorter) => {
console.log('Sort:', sorter)
}}
/>
)
}Freeze Columns Usage:
The freezeColumns prop supports two formats:
1. Simple Format (all frozen to LEFT):
// Freeze by index
freezeColumns={[0, 1, 2]}
// Freeze by column key/dataIndex
freezeColumns={['id', 'name']}
// Mix index and key
freezeColumns={[0, 'email', 2]}2. Advanced Format (specify LEFT or RIGHT):
freezeColumns={[
0, // Simple: freeze index 0 on left (default)
'name', // Simple: freeze 'name' on left (default)
{ index: 2, position: 'left' }, // Freeze by index, specify left
{ key: 'email', position: 'left' }, // Freeze by key, specify left
{ key: 'action', position: 'right' } // Freeze 'action' column on RIGHT
]}Features:
- Frozen columns stick (sticky) when scrolling horizontally
- Cannot be dragged or reordered
- Visual indicator: gray background + blue border (left/right based on position)
- Cursor changes to
not-allowed - Can still be resized
- Use with
tableScrolled={{ x: <width> }}to enable horizontal scroll
Sort & Filter Usage:
Built-in Column Sorting:
<TablePaginationNew
enableColumnSorter={true} // Enable sorting on all columns
// For Frontend (FE) sorting - automatic
type="FE"
// For Backend (BE) sorting - handle in onChange
type="BE"
onChange={(pagination, filters, sorter) => {
if (sorter.field) {
// sorter.field = column dataIndex
// sorter.order = 'ascend' | 'descend' | undefined
fetchDataFromAPI({
page: pagination.current,
sortField: sorter.field,
sortOrder: sorter.order
});
}
}}
/>Built-in Column Filtering:
<TablePaginationNew
enableColumnFilter={true} // Enable filtering on all columns
// Automatically creates:
// - Dropdown filter for columns with ≤50 unique values
// - Search filter for columns with >50 values or long text
// For Frontend (FE) - automatic
type="FE"
// For Backend (BE) - handle in onChange
type="BE"
onChange={(pagination, filters, sorter) => {
// filters = { columnKey: [selectedValues] }
fetchDataFromAPI({
page: pagination.current,
filters: filters
});
}}
/>Disable Sort/Filter for Specific Columns:
const columns = [
{
title: 'ID',
dataIndex: 'id',
disableSorter: true, // ❌ No sorting for this column
disableFilter: true, // ❌ No filtering for this column
},
{
title: 'Name',
dataIndex: 'name',
disableFilter: true, // ❌ Disable filter only (sorting still enabled)
},
{
title: 'Phone',
dataIndex: 'phone',
disableSorter: true, // ❌ Disable sorting only (filtering still enabled)
},
{
title: 'Email',
dataIndex: 'email',
// Both sorting and filtering enabled (default)
},
]
<TablePaginationNew
columns={columns}
enableColumnSorter={true}
enableColumnFilter={true}
/>});}} />
**Migration from onSort:**
```jsx
// OLD (deprecated)
<TablePaginationNew
onSort={(pagination, filters, sorter) => { /* handle sort */ }}
/>
// NEW (recommended)
<TablePaginationNew
enableColumnSorter={true}
onChange={(pagination, filters, sorter) => {
// onChange now handles pagination, filters, AND sorting
}}
/>Column Resize Usage:
- When
enableDragColumn={true}, a resize handle (⋮) appears at the right edge of each column header - Hover over the handle to see it turn blue with a border
- The cursor will automatically change to resize cursor (
col-resize) - Click and drag the handle to resize the column (minimum width: 50px)
- Drag the header center (not the edge) to reorder columns
- Resize is disabled during column drag to prevent conflicts
All TablePaginationNew Props:
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| dataSource | array | required | Data array for table |
| columns | array | required | Ant Design column definitions |
| enableDragColumn | boolean | false | Enable column drag, reorder & resize |
| enableColumnSorter | boolean | false | Enable built-in column sorting |
| enableColumnFilter | boolean | false | Enable built-in column filtering |
| freezeColumns | array | - | Array of column indices or keys to freeze |
| current | number | - | Current page number |
| pageSize | number | - | Items per page |
| totalData | number | - | Total records (for BE pagination) |
| onChange | function | - | Callback for pagination, filter, sort changes |
| usePagination | boolean | true | Show pagination |
| useSelect | boolean | true | Show column selector |
| type | "BE" \| "FE" | "BE" | Pagination type |
| loading | boolean | false | Loading state |
| tableScrolled | object | - | Scroll config {x, y} |
| className | string | - | Custom CSS class |
| onSort | function | - | Sort callback |
| rowSelection | object | - | Ant Design row selection |
| expandable | object | - | Ant Design expandable config |
Manual CSS import (if needed):
import 'poc-table-dragandrop/dist/draggable-table.css'
```UMD usage via script tag (React must be provided globally):
```html
<script src="https://unpkg.com/react/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.production.min.js"></script>
<script src="/path/to/dist/draggable-table.umd.js"></script>
<script>
const { DraggableTable } = window.DraggableTable
// render with ReactDOM
</script>Publishing to npm
- Fill
package.jsonmetadata fields:author,repository.url, and confirmnameis unique on npm. - Build the library (prepare script runs automatically on publish):
npm run build:lib- Login and publish:
npm login
npm publish --access publicAfter publishing, other projects can install:
npm install poc-table-dragandrop