Skip to content

Commit a630c98

Browse files
CopilotTechQuery
andcommitted
Add documentation and fix TypeScript issues
Co-authored-by: TechQuery <[email protected]>
1 parent e60e064 commit a630c98

File tree

7 files changed

+403
-40
lines changed

7 files changed

+403
-40
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"devDependencies": {
3535
"@eslint/eslintrc": "^3.3.1",
3636
"@tailwindcss/postcss": "^4.1.11",
37+
"@types/lodash": "^4.17.20",
3738
"@types/node": "^20.19.9",
3839
"@types/react": "19.1.2",
3940
"@types/react-dom": "19.1.2",

pnpm-lock.yaml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/r/rest-table.json

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
# RestTable Component
2+
3+
A MobX-powered table component with full CRUD operations support, migrated to use shadcn UI components.
4+
5+
## Features
6+
7+
- **React Class Component**: Maintains the original React class component architecture
8+
- **MobX Integration**: Full reactive data management with MobX
9+
- **CRUD Operations**: Built-in support for Create, Read, Update, Delete operations
10+
- **Pagination**: Integrated pagination controls
11+
- **Row Selection**: Checkbox-based row selection
12+
- **Custom Rendering**: Flexible column rendering with custom components
13+
- **Type Safety**: Full TypeScript support
14+
- **shadcn UI**: Built on top of shadcn UI components
15+
16+
## Installation
17+
18+
```bash
19+
npx shadcn@latest add rest-table
20+
```
21+
22+
This will install:
23+
- The RestTable component and all its supporting components
24+
- Required UI components (table, checkbox, spinner, badge, button, card, input, label)
25+
- Required dependencies (mobx, mobx-react, mobx-restful, etc.)
26+
27+
## Usage
28+
29+
### Basic Example
30+
31+
```tsx
32+
import { RestTable } from "@/components/rest-table"
33+
import { RestStore } from "mobx-restful"
34+
import { TranslationModel } from "mobx-i18n"
35+
36+
// Define your data type
37+
interface User {
38+
id: string
39+
name: string
40+
email: string
41+
role: string
42+
}
43+
44+
// Create a MobX store
45+
const userStore = new RestStore<User>({
46+
baseURI: "https://api.example.com/users",
47+
indexKey: "id"
48+
})
49+
50+
// Create translator
51+
const translator = new TranslationModel({
52+
en: {
53+
create: "Create",
54+
edit: "Edit",
55+
delete: "Delete",
56+
view: "View",
57+
total_x_rows: "Total {totalCount} rows",
58+
sure_to_delete_x: "Are you sure to delete {keys}?"
59+
}
60+
})
61+
62+
// Use the RestTable component
63+
function UsersTable() {
64+
return (
65+
<RestTable
66+
store={userStore}
67+
translator={translator}
68+
editable
69+
deletable
70+
columns={[
71+
{
72+
key: "name",
73+
renderHead: () => "Name",
74+
},
75+
{
76+
key: "email",
77+
type: "email",
78+
renderHead: () => "Email",
79+
},
80+
{
81+
key: "role",
82+
renderHead: () => "Role",
83+
}
84+
]}
85+
/>
86+
)
87+
}
88+
```
89+
90+
### Advanced Column Rendering
91+
92+
```tsx
93+
<RestTable
94+
store={userStore}
95+
translator={translator}
96+
columns={[
97+
{
98+
key: "avatar",
99+
type: "file",
100+
accept: "image/*",
101+
renderHead: () => "Avatar",
102+
},
103+
{
104+
key: "name",
105+
renderHead: () => "Name",
106+
renderBody: (user) => (
107+
<div className="font-semibold">{user.name}</div>
108+
)
109+
},
110+
{
111+
key: "tags",
112+
multiple: true,
113+
renderHead: () => "Tags",
114+
},
115+
{
116+
key: "website",
117+
type: "url",
118+
renderHead: () => "Website",
119+
}
120+
]}
121+
/>
122+
```
123+
124+
### With Row Selection
125+
126+
```tsx
127+
function UsersTable() {
128+
const handleCheck = (keys: string[]) => {
129+
console.log("Selected keys:", keys)
130+
}
131+
132+
return (
133+
<RestTable
134+
store={userStore}
135+
translator={translator}
136+
onCheck={handleCheck}
137+
columns={[...]}
138+
/>
139+
)
140+
}
141+
```
142+
143+
### Custom Submit Handler
144+
145+
```tsx
146+
<RestTable
147+
store={userStore}
148+
translator={translator}
149+
editable
150+
onSubmit={async (data) => {
151+
// Custom submit logic
152+
await customAPI.save(data)
153+
}}
154+
columns={[...]}
155+
/>
156+
```
157+
158+
## API Reference
159+
160+
### RestTable Props
161+
162+
| Prop | Type | Description |
163+
|------|------|-------------|
164+
| `store` | `RestStore<D>` | MobX RESTful store instance |
165+
| `translator` | `Translator<D>` | Translation model with required keys |
166+
| `columns` | `Column<D>[]` | Array of column definitions |
167+
| `filter` | `Filter<D>` | Optional filter for data fetching |
168+
| `editable` | `boolean` | Enable edit/create operations |
169+
| `deletable` | `boolean` | Enable delete operations |
170+
| `onCheck` | `(keys: IDType[]) => void` | Callback for row selection |
171+
| `onSubmit` | `(data: D) => Promise<void>` | Custom submit handler |
172+
| `responsive` | `boolean` | Enable responsive table layout (default: true) |
173+
174+
### Column Definition
175+
176+
| Property | Type | Description |
177+
|----------|------|-------------|
178+
| `key` | `keyof T` | Data field key |
179+
| `type` | `string` | Field type: 'text', 'email', 'url', 'tel', 'file' |
180+
| `renderHead` | `React.ReactNode \| Function` | Custom header renderer |
181+
| `renderBody` | `(data: T) => React.ReactNode` | Custom cell renderer |
182+
| `renderFoot` | `React.ReactNode \| Function` | Custom footer renderer |
183+
| `readOnly` | `boolean` | Make field read-only |
184+
| `disabled` | `boolean` | Disable field |
185+
| `multiple` | `boolean` | Enable multiple values (renders as badges) |
186+
| `options` | `any[]` | Field options |
187+
| `accept` | `string` | File accept types |
188+
| `rows` | `number` | Textarea rows |
189+
190+
## Translation Keys
191+
192+
The translator must provide the following translation keys:
193+
194+
- `create`: Create button text
195+
- `edit`: Edit button text
196+
- `view`: View button text
197+
- `delete`: Delete button text
198+
- `total_x_rows`: Total rows text (with `{totalCount}` placeholder)
199+
- `sure_to_delete_x`: Delete confirmation text (with `{keys}` placeholder)
200+
201+
## Architecture
202+
203+
The RestTable maintains the **React class component** architecture from the original MobX-RESTful-table implementation:
204+
205+
- Uses `@observer` decorator for MobX reactivity
206+
- Extends `ObservedComponent` for enhanced observable props handling
207+
- Uses class properties with `@observable` and `@computed` decorators
208+
- All methods are class methods, not hooks
209+
210+
This ensures compatibility with existing MobX-based applications and maintains the proven architecture pattern.
211+
212+
## Components Structure
213+
214+
The RestTable includes several supporting components:
215+
216+
- **BadgeBar**: Displays multiple values as badges
217+
- **FilePreview**: Previews file URLs (images or links)
218+
- **Pager**: Pagination controls
219+
- **RestFormModal**: Modal form for create/edit operations
220+
221+
All components follow the same class component pattern for consistency.

registry/new-york/blocks/rest-table/components/rest-form-modal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { Input } from "@/registry/new-york/ui/input"
1414
import { Label } from "@/registry/new-york/ui/label"
1515

1616
export interface Field<T extends DataObject> {
17-
key: keyof T
17+
key?: keyof T
1818
type?: string
1919
renderLabel?: ((key: keyof T) => React.ReactNode) | React.ReactNode
2020
readOnly?: boolean
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
"use client"
2+
3+
import * as React from "react"
4+
import { RestTable, Column } from "./rest-table"
5+
import { makeObservable, observable } from "mobx"
6+
import { DataObject } from "mobx-restful"
7+
8+
// Mock store for demonstration
9+
class MockStore<T extends DataObject> {
10+
@observable accessor currentPage: T[] = []
11+
@observable accessor currentOne: Partial<T> = {}
12+
@observable accessor downloading = 0
13+
@observable accessor pageSize = 10
14+
@observable accessor pageIndex = 1
15+
@observable accessor pageCount = 1
16+
@observable accessor totalCount = 0
17+
18+
indexKey: keyof T = "id" as keyof T
19+
20+
constructor() {
21+
makeObservable(this)
22+
}
23+
24+
clear() {
25+
this.currentPage = []
26+
}
27+
28+
async getList() {
29+
// Mock data
30+
this.downloading = 1
31+
setTimeout(() => {
32+
this.currentPage = [] as T[]
33+
this.totalCount = 0
34+
this.pageCount = 1
35+
this.downloading = 0
36+
}, 500)
37+
}
38+
39+
async deleteOne(id: any) {
40+
this.currentPage = this.currentPage.filter(
41+
(item) => item[this.indexKey] !== id
42+
)
43+
}
44+
45+
async createOne(data: Partial<T>) {
46+
// Mock create
47+
console.log("Creating:", data)
48+
}
49+
50+
async updateOne(data: Partial<T>, id: any) {
51+
// Mock update
52+
console.log("Updating:", data, id)
53+
}
54+
}
55+
56+
// Mock translator
57+
const mockTranslator = {
58+
t: (key: string, params?: any) => {
59+
const translations: Record<string, string> = {
60+
create: "Create",
61+
edit: "Edit",
62+
view: "View",
63+
delete: "Delete",
64+
total_x_rows: `Total ${params?.totalCount || 0} rows`,
65+
sure_to_delete_x: `Are you sure to delete ${params?.keys || ""}?`,
66+
}
67+
return translations[key] || key
68+
},
69+
}
70+
71+
interface ExampleData extends DataObject {
72+
id: string
73+
name: string
74+
email: string
75+
status: string
76+
}
77+
78+
export function RestTableExample() {
79+
const [store] = React.useState(() => new MockStore<ExampleData>())
80+
81+
const columns: Column<ExampleData>[] = [
82+
{
83+
key: "name",
84+
renderHead: () => "Name",
85+
},
86+
{
87+
key: "email",
88+
type: "email",
89+
renderHead: () => "Email",
90+
},
91+
{
92+
key: "status",
93+
renderHead: () => "Status",
94+
},
95+
]
96+
97+
return (
98+
<div className="container mx-auto py-10">
99+
<RestTable
100+
store={store}
101+
translator={mockTranslator}
102+
columns={columns}
103+
editable
104+
deletable
105+
/>
106+
</div>
107+
)
108+
}

0 commit comments

Comments
 (0)