@rowakit/table 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1073 -0
- package/dist/index.cjs +385 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +389 -0
- package/dist/index.d.ts +389 -0
- package/dist/index.js +380 -0
- package/dist/index.js.map +1 -0
- package/package.json +73 -0
- package/src/styles/index.css +18 -0
- package/src/styles/table.css +319 -0
- package/src/styles/tokens.css +177 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Core type definitions for RowaKit Table
|
|
6
|
+
*
|
|
7
|
+
* These types define the contracts for:
|
|
8
|
+
* - Server-side data fetching (Fetcher)
|
|
9
|
+
* - Column definitions (ColumnDef)
|
|
10
|
+
* - Row actions (ActionDef)
|
|
11
|
+
*
|
|
12
|
+
* @packageDocumentation
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Query parameters passed to the fetcher function.
|
|
17
|
+
*
|
|
18
|
+
* All pagination, sorting, and filtering state is passed through this query.
|
|
19
|
+
*/
|
|
20
|
+
interface FetcherQuery {
|
|
21
|
+
/** Current page number (1-based) */
|
|
22
|
+
page: number;
|
|
23
|
+
/** Number of items per page */
|
|
24
|
+
pageSize: number;
|
|
25
|
+
/** Optional sorting configuration */
|
|
26
|
+
sort?: {
|
|
27
|
+
/** Field name to sort by */
|
|
28
|
+
field: string;
|
|
29
|
+
/** Sort direction */
|
|
30
|
+
direction: 'asc' | 'desc';
|
|
31
|
+
};
|
|
32
|
+
/** Optional filters (key-value pairs) */
|
|
33
|
+
filters?: Record<string, unknown>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Result returned from the fetcher function.
|
|
37
|
+
*/
|
|
38
|
+
interface FetcherResult<T> {
|
|
39
|
+
/** Array of data items for the current page */
|
|
40
|
+
items: T[];
|
|
41
|
+
/** Total number of items across all pages */
|
|
42
|
+
total: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Server-side data fetcher function.
|
|
46
|
+
*
|
|
47
|
+
* This is the primary contract for loading table data. The fetcher receives
|
|
48
|
+
* pagination, sorting, and filter state, and returns a page of results.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* const fetchUsers: Fetcher<User> = async (query) => {
|
|
53
|
+
* const response = await fetch(`/api/users?${new URLSearchParams({
|
|
54
|
+
* page: query.page.toString(),
|
|
55
|
+
* pageSize: query.pageSize.toString(),
|
|
56
|
+
* sort: query.sort ? `${query.sort.field}:${query.sort.direction}` : '',
|
|
57
|
+
* })}`);
|
|
58
|
+
* return response.json();
|
|
59
|
+
* };
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
type Fetcher<T> = (query: FetcherQuery) => Promise<FetcherResult<T>>;
|
|
63
|
+
/**
|
|
64
|
+
* Union of supported column kinds.
|
|
65
|
+
*
|
|
66
|
+
* These represent the built-in column types that can be created
|
|
67
|
+
* via the `col.*` helper factory.
|
|
68
|
+
*/
|
|
69
|
+
type ColumnKind = 'text' | 'date' | 'boolean' | 'actions' | 'custom';
|
|
70
|
+
/**
|
|
71
|
+
* Base column definition properties shared across all column types.
|
|
72
|
+
*/
|
|
73
|
+
interface BaseColumnDef<T> {
|
|
74
|
+
/** Unique identifier for this column */
|
|
75
|
+
id: string;
|
|
76
|
+
/** Column kind (text, date, boolean, actions, custom) */
|
|
77
|
+
kind: ColumnKind;
|
|
78
|
+
/** Optional header label (defaults to id if not provided) */
|
|
79
|
+
header?: string;
|
|
80
|
+
/** Whether this column can be sorted (default: false) */
|
|
81
|
+
sortable?: boolean;
|
|
82
|
+
/** Optional field name to extract from row data (for sortable columns) */
|
|
83
|
+
field?: keyof T & string;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Text column definition.
|
|
87
|
+
*/
|
|
88
|
+
interface TextColumnDef<T> extends BaseColumnDef<T> {
|
|
89
|
+
kind: 'text';
|
|
90
|
+
field: keyof T & string;
|
|
91
|
+
format?: (value: unknown) => string;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Date column definition.
|
|
95
|
+
*/
|
|
96
|
+
interface DateColumnDef<T> extends BaseColumnDef<T> {
|
|
97
|
+
kind: 'date';
|
|
98
|
+
field: keyof T & string;
|
|
99
|
+
format?: (value: Date | string | number) => string;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Boolean column definition.
|
|
103
|
+
*/
|
|
104
|
+
interface BooleanColumnDef<T> extends BaseColumnDef<T> {
|
|
105
|
+
kind: 'boolean';
|
|
106
|
+
field: keyof T & string;
|
|
107
|
+
format?: (value: boolean) => string;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Actions column definition.
|
|
111
|
+
*/
|
|
112
|
+
interface ActionsColumnDef<T> extends BaseColumnDef<T> {
|
|
113
|
+
kind: 'actions';
|
|
114
|
+
actions: ActionDef<T>[];
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Custom column definition with render function.
|
|
118
|
+
*
|
|
119
|
+
* This is the escape hatch for any column that doesn't fit
|
|
120
|
+
* the built-in types.
|
|
121
|
+
*/
|
|
122
|
+
interface CustomColumnDef<T> extends BaseColumnDef<T> {
|
|
123
|
+
kind: 'custom';
|
|
124
|
+
field?: keyof T & string;
|
|
125
|
+
render: (row: T) => ReactNode;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Union type for all column definitions.
|
|
129
|
+
*/
|
|
130
|
+
type ColumnDef<T> = TextColumnDef<T> | DateColumnDef<T> | BooleanColumnDef<T> | ActionsColumnDef<T> | CustomColumnDef<T>;
|
|
131
|
+
/**
|
|
132
|
+
* Row action definition.
|
|
133
|
+
*
|
|
134
|
+
* Actions appear in the actions column and can be clicked to perform
|
|
135
|
+
* operations on individual rows.
|
|
136
|
+
*/
|
|
137
|
+
interface ActionDef<T> {
|
|
138
|
+
/** Unique identifier for this action */
|
|
139
|
+
id: string;
|
|
140
|
+
/** Label displayed to the user */
|
|
141
|
+
label: string;
|
|
142
|
+
/** Optional icon identifier or component */
|
|
143
|
+
icon?: string | ReactNode;
|
|
144
|
+
/** Whether to show confirmation dialog before executing (default: false) */
|
|
145
|
+
confirm?: boolean;
|
|
146
|
+
/** Callback invoked when action is clicked (after confirmation if required) */
|
|
147
|
+
onClick: (row: T) => void | Promise<void>;
|
|
148
|
+
/** Optional loading state during async operations */
|
|
149
|
+
loading?: boolean;
|
|
150
|
+
/** Optional disabled state */
|
|
151
|
+
disabled?: boolean | ((row: T) => boolean);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Column helper factory functions
|
|
156
|
+
*
|
|
157
|
+
* These helpers provide a clean, type-safe API for defining table columns.
|
|
158
|
+
* They reduce boilerplate and enforce conventions while maintaining flexibility
|
|
159
|
+
* through the `col.custom` escape hatch.
|
|
160
|
+
*
|
|
161
|
+
* @packageDocumentation
|
|
162
|
+
*/
|
|
163
|
+
|
|
164
|
+
interface TextOptions {
|
|
165
|
+
/** Optional custom header label */
|
|
166
|
+
header?: string;
|
|
167
|
+
/** Enable sorting for this column */
|
|
168
|
+
sortable?: boolean;
|
|
169
|
+
/** Optional formatter function */
|
|
170
|
+
format?: (value: unknown) => string;
|
|
171
|
+
}
|
|
172
|
+
interface DateOptions {
|
|
173
|
+
/** Optional custom header label */
|
|
174
|
+
header?: string;
|
|
175
|
+
/** Enable sorting for this column */
|
|
176
|
+
sortable?: boolean;
|
|
177
|
+
/** Optional date formatter function */
|
|
178
|
+
format?: (value: Date | string | number) => string;
|
|
179
|
+
}
|
|
180
|
+
interface BooleanOptions {
|
|
181
|
+
/** Optional custom header label */
|
|
182
|
+
header?: string;
|
|
183
|
+
/** Enable sorting for this column */
|
|
184
|
+
sortable?: boolean;
|
|
185
|
+
/** Optional boolean formatter function */
|
|
186
|
+
format?: (value: boolean) => string;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Create a text column definition.
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* ```ts
|
|
193
|
+
* col.text('name')
|
|
194
|
+
* col.text('email', { header: 'Email Address', sortable: true })
|
|
195
|
+
* col.text('status', { format: (val) => val.toUpperCase() })
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
198
|
+
declare function text<T>(field: keyof T & string, options?: TextOptions): TextColumnDef<T>;
|
|
199
|
+
/**
|
|
200
|
+
* Create a date column definition.
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* ```ts
|
|
204
|
+
* col.date('createdAt')
|
|
205
|
+
* col.date('updatedAt', { header: 'Last Modified', sortable: true })
|
|
206
|
+
* col.date('birthday', {
|
|
207
|
+
* format: (date) => new Date(date).toLocaleDateString()
|
|
208
|
+
* })
|
|
209
|
+
* ```
|
|
210
|
+
*/
|
|
211
|
+
declare function date<T>(field: keyof T & string, options?: DateOptions): DateColumnDef<T>;
|
|
212
|
+
/**
|
|
213
|
+
* Create a boolean column definition.
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* ```ts
|
|
217
|
+
* col.boolean('active')
|
|
218
|
+
* col.boolean('isPublished', { header: 'Published', sortable: true })
|
|
219
|
+
* col.boolean('enabled', {
|
|
220
|
+
* format: (val) => val ? 'Yes' : 'No'
|
|
221
|
+
* })
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
declare function boolean<T>(field: keyof T & string, options?: BooleanOptions): BooleanColumnDef<T>;
|
|
225
|
+
/**
|
|
226
|
+
* Create an actions column definition.
|
|
227
|
+
*
|
|
228
|
+
* The actions column displays a set of actions (buttons/links) that can be
|
|
229
|
+
* performed on each row.
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* ```ts
|
|
233
|
+
* col.actions([
|
|
234
|
+
* { id: 'edit', label: 'Edit', onClick: (row) => editUser(row) },
|
|
235
|
+
* { id: 'delete', label: 'Delete', confirm: true, onClick: (row) => deleteUser(row) }
|
|
236
|
+
* ])
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
declare function actions<T>(actions: ActionDef<T>[]): ActionsColumnDef<T>;
|
|
240
|
+
/**
|
|
241
|
+
* Create a custom column definition with full rendering control.
|
|
242
|
+
*
|
|
243
|
+
* This is the escape hatch for any column that doesn't fit the standard types.
|
|
244
|
+
* Use this for badges, avatars, complex formatting, or any custom UI.
|
|
245
|
+
*
|
|
246
|
+
* @example
|
|
247
|
+
* ```ts
|
|
248
|
+
* col.custom({
|
|
249
|
+
* id: 'avatar',
|
|
250
|
+
* header: 'User',
|
|
251
|
+
* render: (row) => <img src={row.avatar} alt={row.name} />
|
|
252
|
+
* })
|
|
253
|
+
*
|
|
254
|
+
* col.custom({
|
|
255
|
+
* id: 'price',
|
|
256
|
+
* field: 'price',
|
|
257
|
+
* render: (row) => <Money amount={row.price} currency={row.currency} />
|
|
258
|
+
* })
|
|
259
|
+
*
|
|
260
|
+
* col.custom({
|
|
261
|
+
* id: 'status',
|
|
262
|
+
* render: (row) => (
|
|
263
|
+
* <Badge color={row.status === 'active' ? 'green' : 'gray'}>
|
|
264
|
+
* {row.status}
|
|
265
|
+
* </Badge>
|
|
266
|
+
* )
|
|
267
|
+
* })
|
|
268
|
+
* ```
|
|
269
|
+
*/
|
|
270
|
+
declare function custom<T>(options: {
|
|
271
|
+
/** Unique column identifier */
|
|
272
|
+
id: string;
|
|
273
|
+
/** Optional custom header label */
|
|
274
|
+
header?: string;
|
|
275
|
+
/** Optional field name for sorting/filtering */
|
|
276
|
+
field?: keyof T & string;
|
|
277
|
+
/** Render function for cell content */
|
|
278
|
+
render: (row: T) => ReactNode;
|
|
279
|
+
}): CustomColumnDef<T>;
|
|
280
|
+
/**
|
|
281
|
+
* Column helper factory object.
|
|
282
|
+
*
|
|
283
|
+
* Provides convenient helper functions for creating column definitions.
|
|
284
|
+
*
|
|
285
|
+
* @example
|
|
286
|
+
* ```tsx
|
|
287
|
+
* import { col } from '@rowakit/table';
|
|
288
|
+
*
|
|
289
|
+
* const columns = [
|
|
290
|
+
* col.text('name', { sortable: true }),
|
|
291
|
+
* col.date('createdAt'),
|
|
292
|
+
* col.boolean('active'),
|
|
293
|
+
* col.actions([
|
|
294
|
+
* { id: 'edit', label: 'Edit', onClick: (row) => {} }
|
|
295
|
+
* ]),
|
|
296
|
+
* col.custom({ id: 'badge', render: (row) => <Badge>{row.status}</Badge> })
|
|
297
|
+
* ];
|
|
298
|
+
* ```
|
|
299
|
+
*/
|
|
300
|
+
declare const col: {
|
|
301
|
+
readonly text: typeof text;
|
|
302
|
+
readonly date: typeof date;
|
|
303
|
+
readonly boolean: typeof boolean;
|
|
304
|
+
readonly actions: typeof actions;
|
|
305
|
+
readonly custom: typeof custom;
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
interface SmartTableProps<T> {
|
|
309
|
+
/** Server-side data fetcher function */
|
|
310
|
+
fetcher: Fetcher<T>;
|
|
311
|
+
/** Array of column definitions */
|
|
312
|
+
columns: ColumnDef<T>[];
|
|
313
|
+
/** Available page size options (default: [10, 20, 50]) */
|
|
314
|
+
pageSizeOptions?: number[];
|
|
315
|
+
/** Initial page size (default: 20) */
|
|
316
|
+
defaultPageSize?: number;
|
|
317
|
+
/** Function or field name to extract row key (default: uses 'id' field) */
|
|
318
|
+
rowKey?: keyof T | ((row: T) => string | number);
|
|
319
|
+
/** Optional CSS class name for the table container */
|
|
320
|
+
className?: string;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* RowaKitTable - Server-side table component for internal/business apps.
|
|
324
|
+
*
|
|
325
|
+
* This component renders a table with headers and body based on column definitions.
|
|
326
|
+
* It handles all column types (text, date, boolean, actions, custom) and provides
|
|
327
|
+
* a clean API for defining table structure.
|
|
328
|
+
*
|
|
329
|
+
* Features:
|
|
330
|
+
* - Automatic data fetching on mount and query changes
|
|
331
|
+
* - Loading, error, and empty states
|
|
332
|
+
* - Stale request handling
|
|
333
|
+
* - Retry on error
|
|
334
|
+
*
|
|
335
|
+
* @example
|
|
336
|
+
* ```tsx
|
|
337
|
+
* import { RowaKitTable, col } from '@rowakit/table';
|
|
338
|
+
*
|
|
339
|
+
* interface User {
|
|
340
|
+
* id: string;
|
|
341
|
+
* name: string;
|
|
342
|
+
* email: string;
|
|
343
|
+
* createdAt: Date;
|
|
344
|
+
* active: boolean;
|
|
345
|
+
* }
|
|
346
|
+
*
|
|
347
|
+
* const fetchUsers: Fetcher<User> = async (query) => {
|
|
348
|
+
* const response = await fetch(`/api/users?page=${query.page}&pageSize=${query.pageSize}`);
|
|
349
|
+
* return response.json();
|
|
350
|
+
* };
|
|
351
|
+
*
|
|
352
|
+
* function UsersTable() {
|
|
353
|
+
* return (
|
|
354
|
+
* <RowaKitTable
|
|
355
|
+
* fetcher={fetchUsers}
|
|
356
|
+
* columns={[
|
|
357
|
+
* col.text('name', { header: 'Name', sortable: true }),
|
|
358
|
+
* col.text('email', { header: 'Email' }),
|
|
359
|
+
* col.date('createdAt', { header: 'Created' }),
|
|
360
|
+
* col.boolean('active', { header: 'Active' }),
|
|
361
|
+
* col.actions([
|
|
362
|
+
* { id: 'edit', label: 'Edit', onClick: (user) => editUser(user) },
|
|
363
|
+
* { id: 'delete', label: 'Delete', confirm: true, onClick: (user) => deleteUser(user) }
|
|
364
|
+
* ])
|
|
365
|
+
* ]}
|
|
366
|
+
* defaultPageSize={20}
|
|
367
|
+
* rowKey="id"
|
|
368
|
+
* />
|
|
369
|
+
* );
|
|
370
|
+
* }
|
|
371
|
+
* ```
|
|
372
|
+
*/
|
|
373
|
+
declare function RowaKitTable<T>({ fetcher, columns, defaultPageSize, pageSizeOptions, rowKey, className, }: SmartTableProps<T>): react_jsx_runtime.JSX.Element;
|
|
374
|
+
/**
|
|
375
|
+
* @deprecated Use RowaKitTable instead. SmartTable is kept as an alias for backward compatibility.
|
|
376
|
+
*/
|
|
377
|
+
declare const SmartTable: typeof RowaKitTable;
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* @rowakit/table
|
|
381
|
+
*
|
|
382
|
+
* Opinionated, server-side-first table component for internal/business apps.
|
|
383
|
+
*
|
|
384
|
+
* @packageDocumentation
|
|
385
|
+
*/
|
|
386
|
+
|
|
387
|
+
declare const VERSION = "0.1.0";
|
|
388
|
+
|
|
389
|
+
export { type ActionDef, type ActionsColumnDef, type BaseColumnDef, type BooleanColumnDef, type ColumnDef, type ColumnKind, type CustomColumnDef, type DateColumnDef, type Fetcher, type FetcherQuery, type FetcherResult, RowaKitTable, SmartTable, type SmartTableProps, type TextColumnDef, VERSION, col };
|