shacn-inline-table
v1.0.1
Published
An inline-editable table component built on shadcn/ui table
Maintainers
Readme
shacn-inline-table
An inline-editable table component built on shadcn/ui table. This npm package provides a powerful, customizable table component that supports inline editing with validation.
Installation
npm install shacn-inline-tablePeer Dependencies
This package requires React 18+ and the following dependencies (usually provided by your Tailwind setup):
react^18.0.0react-dom^18.0.0
Make sure you have Tailwind CSS configured in your project with the following classes available.
Basic Usage
import { InlineTable } from "shacn-inline-table";
interface User {
id: number;
name: string;
email: string;
age: number;
}
function App() {
const [users, setUsers] = React.useState<User[]>([
{ id: 1, name: "John Doe", email: "[email protected]", age: 30 },
{ id: 2, name: "Jane Smith", email: "[email protected]", age: 25 },
]);
const columns = [
{ key: "id", header: "ID", editable: false },
{ key: "name", header: "Name", editable: true },
{ key: "email", header: "Email", editable: true, inputType: "email" },
{ key: "age", header: "Age", editable: true, inputType: "number" },
];
const handleCellChange = (rowIndex: number, columnKey: string, value: any) => {
const newUsers = [...users];
newUsers[rowIndex] = { ...newUsers[rowIndex], [columnKey]: value };
setUsers(newUsers);
};
return (
<InlineTable
data={users}
columns={columns}
onCellChange={handleCellChange}
/>
);
}Advanced Usage
Custom Render Function
const columns = [
{
key: "status",
header: "Status",
editable: true,
render: (value, row) => (
<span className={value === "active" ? "text-green-500" : "text-red-500"}>
{value}
</span>
),
},
];Validation
const columns = [
{
key: "email",
header: "Email",
editable: true,
inputType: "email",
validate: (value) => {
if (!value.includes("@")) {
return "Please enter a valid email address";
}
return null;
},
},
{
key: "age",
header: "Age",
editable: true,
inputType: "number",
validate: (value) => {
if (value < 0 || value > 150) {
return "Age must be between 0 and 150";
}
return null;
},
},
];Using onRowUpdate
const handleRowUpdate = (rowIndex: number, updatedRow: User) => {
// Sync with backend
fetch(`/api/users/${updatedRow.id}`, {
method: "PUT",
body: JSON.stringify(updatedRow),
});
};
<InlineTable
data={users}
columns={columns}
onRowUpdate={handleRowUpdate}
/>Custom Styling
<InlineTable
data={users}
columns={columns}
className="my-custom-wrapper"
tableClassName="custom-table-styles"
rowClassName={(row, index) => index % 2 === 0 ? "bg-gray-50" : ""}
cellClassName="custom-cell"
/>API Reference
InlineTable Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| data | T[] | required | Array of data objects to display |
| columns | Column<T>[] | required | Column configuration array |
| onCellChange | (rowIndex, columnKey, value) => void | optional | Callback when a cell value changes |
| onRowUpdate | (rowIndex, updatedRow) => void | optional | Callback when a row is updated |
| className | string | optional | Additional CSS classes for wrapper |
| tableClassName | string | optional | Additional CSS classes for table |
| rowClassName | string \| ((row, index) => string) | optional | CSS classes for rows |
| cellClassName | string \| ((column, row, index) => string) | optional | CSS classes for cells |
| showEditIcon | boolean | true | Show edit icon on hover |
| disabled | boolean | false | Disable editing |
Column Configuration
| Property | Type | Description |
|----------|------|-------------|
| key | keyof T \| string | Field key in data object |
| header | string | Column header text |
| editable | boolean | Whether the column is editable |
| inputType | "text" \| "number" \| "email" \| "tel" \| "url" \| "textarea" | Input type for editing |
| render | (value, row, index) => ReactNode | Custom render function |
| validate | (value) => string \| null | Validation function (returns error message or null) |
Keyboard Shortcuts
- Enter: Save the edited cell
- Escape: Cancel editing
Styling
This package uses Tailwind CSS classes. Make sure your Tailwind config includes the necessary classes or extend it with:
// tailwind.config.js
module.exports = {
// ... your config
theme: {
extend: {
// ... your theme extensions
},
},
};License
MIT
