@nexgrid/react 0.1.0 → 0.2.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 +41 -37
- package/dist/index.cjs +857 -303
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +93 -30
- package/dist/index.d.ts +93 -30
- package/dist/index.js +863 -306
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
- package/styles.css +1555 -411
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A server-driven data grid for React and Next.js.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
TableX renders one page of rows at a time and never holds the dataset. Every
|
|
6
6
|
piece of user intent — page, page size, sort, search, filters — is expressed as
|
|
7
7
|
a single `QueryState` object that **you** own; the grid hands you the next one
|
|
8
8
|
and re-renders when you hand back the matching page. That is the whole contract.
|
|
@@ -21,6 +21,10 @@ identical on every platform.
|
|
|
21
21
|
- Ships ESM and CJS, with a `"use client"` banner so it drops straight into the
|
|
22
22
|
Next.js App Router.
|
|
23
23
|
|
|
24
|
+
<p align="center">
|
|
25
|
+
<img src="https://raw.githubusercontent.com/ChhaganSinha/NexGrid/master/docs/assets/tablex-preview.png" alt="TableX React Data Grid Preview" width="100%" />
|
|
26
|
+
</p>
|
|
27
|
+
|
|
24
28
|
## Installation
|
|
25
29
|
|
|
26
30
|
```bash
|
|
@@ -43,10 +47,10 @@ changes, and pass the result straight through.
|
|
|
43
47
|
|
|
44
48
|
import { useCallback, useEffect, useState } from "react";
|
|
45
49
|
import {
|
|
46
|
-
|
|
50
|
+
TableX,
|
|
47
51
|
defaultQuery,
|
|
48
52
|
serializeQuery,
|
|
49
|
-
type
|
|
53
|
+
type TableXReactColumn,
|
|
50
54
|
type PagedResponse,
|
|
51
55
|
type QueryState,
|
|
52
56
|
} from "@nexgrid/react";
|
|
@@ -60,7 +64,7 @@ interface Student {
|
|
|
60
64
|
joinedAt: string;
|
|
61
65
|
}
|
|
62
66
|
|
|
63
|
-
const columns:
|
|
67
|
+
const columns: TableXReactColumn<Student>[] = [
|
|
64
68
|
{ accessorKey: "name", header: "Name", meta: { minWidth: 180 } },
|
|
65
69
|
{ accessorKey: "email", header: "Email" },
|
|
66
70
|
{
|
|
@@ -105,7 +109,7 @@ export function StudentsGrid() {
|
|
|
105
109
|
}, [load, query]);
|
|
106
110
|
|
|
107
111
|
return (
|
|
108
|
-
<
|
|
112
|
+
<TableX
|
|
109
113
|
caption="Students"
|
|
110
114
|
columns={columns}
|
|
111
115
|
data={page?.items ?? []}
|
|
@@ -132,7 +136,7 @@ Your endpoint must answer with a `PagedResponse<T>`:
|
|
|
132
136
|
{ "items": [], "page": 1, "pageSize": 10, "total": 0, "totalPages": 1 }
|
|
133
137
|
```
|
|
134
138
|
|
|
135
|
-
If your API is ASP.NET Core, `
|
|
139
|
+
If your API is ASP.NET Core, `TableX.AspNetCore` binds exactly the query string
|
|
136
140
|
`serializeQuery` produces and returns exactly this shape.
|
|
137
141
|
|
|
138
142
|
### Putting the query in the URL
|
|
@@ -145,7 +149,7 @@ const searchParams = useSearchParams();
|
|
|
145
149
|
const router = useRouter();
|
|
146
150
|
const query = useMemo(() => parseQuery(searchParams.toString()), [searchParams]);
|
|
147
151
|
|
|
148
|
-
<
|
|
152
|
+
<TableX
|
|
149
153
|
query={query}
|
|
150
154
|
onQueryChange={(next) => router.replace(`?${serializeQuery(next)}`)}
|
|
151
155
|
{...rest}
|
|
@@ -158,7 +162,7 @@ never put the grid into an impossible state.
|
|
|
158
162
|
|
|
159
163
|
## Next.js App Router
|
|
160
164
|
|
|
161
|
-
The published bundle starts with `"use client"`, so `<
|
|
165
|
+
The published bundle starts with `"use client"`, so `<TableX />` can be imported
|
|
162
166
|
directly from a Server Component without a wrapper:
|
|
163
167
|
|
|
164
168
|
```tsx
|
|
@@ -182,7 +186,7 @@ Two notes:
|
|
|
182
186
|
|
|
183
187
|
| Prop | Type | Default | Description |
|
|
184
188
|
|------|------|---------|-------------|
|
|
185
|
-
| `columns` | `
|
|
189
|
+
| `columns` | `TableXReactColumn<TData>[]` | required | Column definitions, in display order. |
|
|
186
190
|
| `data` | `TData[]` | required | The **current page** of rows only. |
|
|
187
191
|
| `total` | `number` | required | Total filtered row count from the server. Drives the pager. |
|
|
188
192
|
| `query` | `QueryState` | required | The query the `data` above answers. |
|
|
@@ -206,9 +210,9 @@ Two notes:
|
|
|
206
210
|
| `onExportAll` | `() => void \| Promise<void>` | — | Takes over exporting entirely; the built-in flow never runs. |
|
|
207
211
|
| `fetchEndpoint` | `string` | — | List endpoint used to page in the rest of the dataset when exporting. |
|
|
208
212
|
| `badgeRules` | `readonly ExcelBadgeRule[]` | core's `DEFAULT_BADGE_RULES` | Value-based cell styling for the Excel export. |
|
|
209
|
-
| `locale` | `Partial<
|
|
210
|
-
| `onNotify` | `(notice:
|
|
211
|
-
| `theme` | `"light" \| "dark" \| "auto"` | `"light"` | Adds `.
|
|
213
|
+
| `locale` | `Partial<TableXLocale>` | English defaults | Overrides for any user-facing string. |
|
|
214
|
+
| `onNotify` | `(notice: TableXNotice) => void` | no-op | Receives `{ type, message }` for export progress, failures, and successes. |
|
|
215
|
+
| `theme` | `"light" \| "dark" \| "auto"` | `"light"` | Adds `.tbx-dark` / `.tbx-auto` to the root. |
|
|
212
216
|
|
|
213
217
|
## Column definitions
|
|
214
218
|
|
|
@@ -222,7 +226,7 @@ A column is a plain object, structurally compatible with TanStack Table's
|
|
|
222
226
|
| `header` | `string \| (ctx) => ReactNode` | Header content. A string is also used for menus and export headers. |
|
|
223
227
|
| `cell` | `(ctx: { row: { original: TData }, getValue(): unknown }) => ReactNode` | Custom cell renderer. Without it the raw value is rendered as text. |
|
|
224
228
|
| `enableSorting` | `boolean` | Sorting is on by default; set `false` to opt out. |
|
|
225
|
-
| `meta` | `
|
|
229
|
+
| `meta` | `TableXColumnMeta` | Layout and behavior hints — see below. |
|
|
226
230
|
|
|
227
231
|
### `meta`
|
|
228
232
|
|
|
@@ -245,7 +249,7 @@ hideable, and never exported.
|
|
|
245
249
|
the mobile card list, so the two can never drift apart.
|
|
246
250
|
|
|
247
251
|
```tsx
|
|
248
|
-
const columns:
|
|
252
|
+
const columns: TableXReactColumn<Student>[] = [
|
|
249
253
|
// A status pill.
|
|
250
254
|
{
|
|
251
255
|
accessorKey: "status",
|
|
@@ -298,38 +302,38 @@ Every color and shape in the stylesheet reads a CSS custom property, so you
|
|
|
298
302
|
re-skin the grid by overriding tokens — no class overrides, no `!important`.
|
|
299
303
|
|
|
300
304
|
```css
|
|
301
|
-
.
|
|
302
|
-
--
|
|
303
|
-
--
|
|
304
|
-
--
|
|
305
|
-
--
|
|
305
|
+
.tbx-root {
|
|
306
|
+
--tbx-primary: #7c3aed;
|
|
307
|
+
--tbx-primary-fg: #ffffff;
|
|
308
|
+
--tbx-radius: 8px;
|
|
309
|
+
--tbx-font: "Inter", system-ui, sans-serif;
|
|
306
310
|
}
|
|
307
311
|
```
|
|
308
312
|
|
|
309
313
|
| Token | Purpose |
|
|
310
314
|
|-------|---------|
|
|
311
|
-
| `--
|
|
312
|
-
| `--
|
|
313
|
-
| `--
|
|
314
|
-
| `--
|
|
315
|
-
| `--
|
|
316
|
-
| `--
|
|
317
|
-
| `--
|
|
318
|
-
| `--
|
|
319
|
-
| `--
|
|
320
|
-
| `--
|
|
315
|
+
| `--tbx-font`, `--tbx-font-mono` | Body font, and the serial-number font. |
|
|
316
|
+
| `--tbx-bg` | Input and pager background. |
|
|
317
|
+
| `--tbx-card`, `--tbx-card-2` | Panel background, and the table header band. |
|
|
318
|
+
| `--tbx-border` | Every border and divider. |
|
|
319
|
+
| `--tbx-fg`, `--tbx-muted-fg` | Primary and secondary text. |
|
|
320
|
+
| `--tbx-muted` | Hover fills and subtle chips. |
|
|
321
|
+
| `--tbx-primary`, `--tbx-primary-fg` | Accent: sort icons, current page, selection. |
|
|
322
|
+
| `--tbx-danger` | Destructive accents. |
|
|
323
|
+
| `--tbx-radius`, `--tbx-radius-sm` | Panel and control corner radii. |
|
|
324
|
+
| `--tbx-shadow`, `--tbx-focus-ring` | Elevation, and the focus ring. |
|
|
321
325
|
|
|
322
326
|
Dark mode is a class, not a media query, so it can follow whatever your app
|
|
323
327
|
already uses:
|
|
324
328
|
|
|
325
329
|
```tsx
|
|
326
|
-
<
|
|
327
|
-
<
|
|
330
|
+
<TableX theme="dark" {...props} /> {/* always dark */}
|
|
331
|
+
<TableX theme="auto" {...props} /> {/* follows the OS */}
|
|
328
332
|
```
|
|
329
333
|
|
|
330
|
-
`theme="dark"` puts `.
|
|
331
|
-
dark class higher up the tree, add `
|
|
332
|
-
alone — the stylesheet matches `.
|
|
334
|
+
`theme="dark"` puts `.tbx-dark` on the grid root. If your app already toggles a
|
|
335
|
+
dark class higher up the tree, add `tbx-dark` alongside it and leave `theme`
|
|
336
|
+
alone — the stylesheet matches `.tbx-dark .tbx-root` as well.
|
|
333
337
|
|
|
334
338
|
Responsive behavior is driven entirely by the stylesheet: the grid renders both a
|
|
335
339
|
table and a card list, and CSS shows the table at ≥ 768px and the cards below it.
|
|
@@ -348,7 +352,7 @@ If those requests fail it notifies you and falls back to the current page rather
|
|
|
348
352
|
than producing nothing.
|
|
349
353
|
|
|
350
354
|
```tsx
|
|
351
|
-
<
|
|
355
|
+
<TableX
|
|
352
356
|
fetchEndpoint="/api/students"
|
|
353
357
|
exportFileName="student_roster"
|
|
354
358
|
badgeRules={[
|
|
@@ -375,7 +379,7 @@ is `"info" | "success" | "error"`, ready to forward to whatever you already use.
|
|
|
375
379
|
Every user-facing string comes from a locale object. Override any subset:
|
|
376
380
|
|
|
377
381
|
```tsx
|
|
378
|
-
<
|
|
382
|
+
<TableX
|
|
379
383
|
locale={{
|
|
380
384
|
searchPlaceholder: "Rechercher…",
|
|
381
385
|
emptyText: "Aucun enregistrement ne correspond à votre recherche.",
|
|
@@ -428,5 +432,5 @@ one and that the sort cycle stays `asc → desc → cleared` across every adapte
|
|
|
428
432
|
|
|
429
433
|
## License
|
|
430
434
|
|
|
431
|
-
[MIT](https://github.com/ChhaganSinha/
|
|
435
|
+
[MIT](https://github.com/ChhaganSinha/TableX/blob/main/LICENSE) © 2026 Chhagan Sinha
|
|
432
436
|
|