laif-ds 0.2.57 → 0.2.58

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.
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { getDefaultExportFromCjs as e } from "./_commonjsHelpers.js";
3
- import { __require as r } from "../node_modules/extend/index.js";
4
- var t = r();
5
- const x = /* @__PURE__ */ e(t);
2
+ import { getDefaultExportFromCjs as r } from "./_commonjsHelpers.js";
3
+ import { __require as e } from "../node_modules/style-to-js/cjs/index.js";
4
+ var t = e();
5
+ const a = /* @__PURE__ */ r(t);
6
6
  export {
7
- x as default
7
+ a as default
8
8
  };
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { getDefaultExportFromCjs as r } from "./_commonjsHelpers.js";
3
- import { __require as e } from "../node_modules/style-to-js/cjs/index.js";
4
- var t = e();
5
- const a = /* @__PURE__ */ r(t);
2
+ import { getDefaultExportFromCjs as e } from "./_commonjsHelpers.js";
3
+ import { __require as r } from "../node_modules/extend/index.js";
4
+ var t = r();
5
+ const x = /* @__PURE__ */ e(t);
6
6
  export {
7
- a as default
7
+ x as default
8
8
  };
@@ -1,254 +1,331 @@
1
- # DataTable
2
-
3
- ## Overview
4
-
5
- Powerful table built on TanStack Table v8. Supports client-side and server-side modes with a unified API, advanced filtering (badges + builder), global search, multi-column sorting, row selection, column pinning, dynamic pagination, i18n, and loading skeletons.
6
-
7
- ---
8
-
9
- ## Props
10
-
11
- | Prop | Type | Default | Description |
12
- | ------------------------- | ------------------------------------------- | ------- | ----------- |
13
- | `columns` | `ColumnDef<TData, TValue>[]` | — | TanStack column definitions. Use `meta` to enable features. |
14
- | `data` | `TData[]` | — | Table data. |
15
- | `loading` | `boolean` | `false` | Show skeleton rows. |
16
- | `emptyComponent` | `ReactNode` | `undefined` | Rendered when no rows. |
17
- | `className` | `string` | `undefined` | Wrapper classes. |
18
- | `checkable` | `boolean` | `false` | Adds a left checkbox column for row selection. |
19
- | `rowSelection` | `Record<string, boolean>` | `{}` | Controlled selection map. |
20
- | `onRowSelectionChange` | `OnChangeFn<Record<string, boolean>>` | `undefined` | Selection change handler (controlled selection). |
21
- | `onCheckedRowsChange` | `(checkedRows: TData[]) => void` | `undefined` | Returns selected row values (requires `checkable`). |
22
- | `actions` | `DataTableActions[]` | `[]` | Actions for the actions row. |
23
- | `hidePagination` | `boolean` | `false` | Hide pagination UI. |
24
- | `hideActionsRow` | `boolean` | `false` | Hide actions row. |
25
- | `i18n` | `DataTableI18n` | `defaultDataTableI18n` | Internationalization strings. |
26
- | `maxSortedColumns` | `number` | `2` | Max number of sorted columns. |
27
- | `initialState` | `DataTableState` | `undefined` | Initial filters, sorting, pagination. |
28
- | `serverMode` | `boolean` | `false` | Enable server-side mode. |
29
- | `serverConfig` | `DataTableServerConfig` | `undefined` | `{ totalItems, onStateChange }` handler for server mode. |
30
- | `disableAutoPageSize` | `boolean` | `false` | Disable auto pageSize (still updates pageIndex). |
31
-
32
- ---
33
-
34
- ## Column meta
35
-
36
- Configure columns via `column.meta`:
37
-
38
- ```ts
39
- type ColumnMeta = {
40
- type: 'string' | 'number' | 'boolean' | 'date' | 'datetime' | 'list_single_select' | 'list_multi_select' | 'other'
41
- sortable?: boolean
42
- filterable?: boolean
43
- searchable?: boolean
44
- pinned?: 'left' | 'right'
45
- listOptions?: { value: string; label: string }[]
46
- }
47
- ```
48
-
49
- Notes:
50
- - `id` must match the field key used for filtering/sorting.
51
- - Header should be a simple string (not JSX) for proper filtering/sorting UI.
52
- - Filtering nested accessors (e.g., `"user.name"`) is not supported.
53
-
54
- ---
55
-
56
- ## Behavior
57
-
58
- - **Filtering**: Badge filters + advanced builder with logical `_and`/`_or`.
59
- - **Global search**: Across `meta.searchable` columns; strings use `like`, arrays use `array_overlap` (mapped automatically).
60
- - **Operators**: Full operator set per type, including `eq_null`/`n_eq_null`, list operators (`array_overlap`, `n_array_overlap`), date/time before/after, checked/unchecked.
61
- - **Sorting**: Multi-column (limited by `maxSortedColumns`).
62
- - **Selection**: Integrated checkbox column when `checkable`.
63
- - **Pinning**: `meta.pinned` supports left/right pinned columns.
64
- - **Pagination**: Auto page size from container height; respects `disableAutoPageSize`.
65
- - **Loading**: Skeleton rows adapt to viewport height (no hardcoded length).
66
- - **i18n**: All labels (sorting/filtering menus included) use `DataTableI18n`.
67
- - **Datetime**: Supports microseconds format like `2025-08-22T12:53:54.060315` and timezone-safe date handling.
68
-
69
- ---
70
-
71
- ## Server-side mode
72
-
73
- When `serverMode=true`, the table emits state to `serverConfig.onStateChange(state)` with:
74
-
75
- ```ts
76
- type ServerState = {
77
- pagination: { pageIndex: number; pageSize: number }
78
- filters?: IFilterState
79
- computedFilter?: SearchFilter
80
- computedSorting?: { sort_by: string[]; sort_order: ('asc'|'desc')[] }
81
- }
82
- ```
83
-
84
- The table manages debounced emissions and preserves computed values across updates.
85
-
86
- ---
87
-
88
- ## Examples
89
-
90
- ### Client mode using utilities (columns + filters + initial state)
91
-
92
- ```tsx
93
- import * as React from 'react'
94
- import type { ColumnDef } from '@tanstack/react-table'
95
- import {
96
- DataTable,
97
- createStringColumn,
98
- createNumberColumn,
99
- createSingleSelectColumn,
100
- createMultiSelectColumn,
101
- createActionColumn,
102
- createInitialState,
103
- createStringFilter,
104
- createNumberFilter,
105
- } from 'laif-ds'
106
- import { Button } from 'laif-ds'
107
-
108
- type Person = {
109
- id: string
110
- name: string
111
- age: number
112
- role: string
113
- tags: string[]
114
- created_at: string
115
- active: boolean
116
- }
117
-
118
- const columns = [
119
- createStringColumn<Person>({
120
- accessorKey: 'name',
121
- header: 'Nome',
122
- sortable: true,
123
- filterable: true,
124
- searchable: true,
125
- }),
126
- createNumberColumn<Person>({
127
- accessorKey: 'age',
128
- header: 'Età',
129
- sortable: true,
130
- filterable: true,
131
- }),
132
- createSingleSelectColumn<Person>({
133
- accessorKey: 'role',
134
- header: 'Ruolo',
135
- options: ['Admin', 'User', 'Guest'],
136
- filterable: true,
137
- searchable: true,
138
- }),
139
- createMultiSelectColumn<Person>({
140
- accessorKey: 'tags',
141
- header: 'Tags',
142
- options: ['frontend', 'backend', 'devops'],
143
- filterable: true,
144
- }),
145
- createActionColumn<Person>({
146
- id: 'actions',
147
- header: 'Azioni',
148
- pinned: 'right',
149
- cell: (row) => <Button size="sm">Edit {row.name}</Button>,
150
- }),
151
- ] satisfies ColumnDef<Person, any>[]
152
-
153
- const initialState = createInitialState({
154
- filters: [
155
- createStringFilter('name', 'name', 'Nome', 'like', 'John'),
156
- createNumberFilter('age', 'age', 'Età', 'ge', 18),
157
- ],
158
- searchbarFilter: 'developer',
159
- sorting: [{ column: 'name', order: 'asc' }],
160
- pagination: { pageIndex: 0, pageSize: 15 },
161
- })
162
-
163
- const actions = [
164
- { label: 'Export CSV', icon: 'FileDown', onClick: () => {/* ... */} },
165
- { label: 'Bulk Delete', icon: 'Trash2', onClick: () => {/* ... */} },
166
- ]
167
-
168
- export function ClientTable({ data }: { data: Person[] }) {
169
- return (
170
- <DataTable
171
- columns={columns}
172
- data={data}
173
- initialState={initialState}
174
- actions={actions}
175
- checkable
176
- onCheckedRowsChange={(rows) => console.log('checked rows', rows)}
177
- />
178
- )
179
- }
180
- ```
181
-
182
- ### Server mode using utilities (state-driven fetch)
183
-
184
- ```tsx
185
- import * as React from 'react'
186
- import type { ServerState } from 'laif-ds'
187
- import { DataTable, createInitialState } from 'laif-ds'
188
-
189
- export function ServerTable({ data, total }: { data: Person[]; total: number }) {
190
- const [loading, setLoading] = React.useState(false)
191
-
192
- const handleState = React.useCallback(async (state: ServerState) => {
193
- // Use state.pagination, state.computedFilter, state.computedSorting
194
- // to fetch from your backend
195
- setLoading(true)
196
- try {
197
- await fetch('/api/people', {
198
- method: 'POST',
199
- headers: { 'Content-Type': 'application/json' },
200
- body: JSON.stringify(state),
201
- })
202
- // Update your data + total here based on response
203
- } finally {
204
- setLoading(false)
205
- }
206
- }, [])
207
-
208
- return (
209
- <DataTable
210
- columns={columns}
211
- data={data}
212
- loading={loading}
213
- serverMode
214
- serverConfig={{ totalItems: total, onStateChange: handleState }}
215
- initialState={createInitialState({ pagination: { pageIndex: 0, pageSize: 20 } })}
216
- checkable
217
- />
218
- )
219
- }
220
- ```
221
-
222
- ### Utility recipes (pinning, list options, quick filters)
223
-
224
- ```tsx
225
- import {
226
- pinColumns,
227
- updateColumnListOptions,
228
- toSelectOptions,
229
- createFilterBadges,
230
- createStringFilter,
231
- createNumberFilter,
232
- } from 'laif-ds'
233
-
234
- // Pin columns to left/right
235
- const pinnedColumns = pinColumns(columns, { left: ['name'], right: ['actions'] })
236
-
237
- // Update list options dynamically (e.g., fetched from API)
238
- const roleOptions = toSelectOptions(['Admin', 'User', 'Guest', 'Manager'])
239
- const columnsWithUpdatedRoles = updateColumnListOptions(columns, 'role', roleOptions)
240
-
241
- // Build multiple filter badges quickly
242
- const quickFilters = createFilterBadges([
243
- { columnId: 'name', columnAccessorKey: 'name', columnLabel: 'Nome', columnType: 'string', operator: 'like', value: 'Jane' },
244
- { columnId: 'age', columnAccessorKey: 'age', columnLabel: 'Età', columnType: 'number', operator: 'ge', value: 30 },
245
- ])
246
- ```
247
-
248
- ---
249
-
250
- ## Notes
251
-
252
- - **Performance**: Client mode filters/sorts in-memory; use server mode for large datasets.
253
- - **UX**: Page size auto-adapts; use `disableAutoPageSize` to manage it manually.
254
- - **Internationalization**: Provide custom `i18n` for localized actions and labels.
1
+ # DataTable
2
+
3
+ ## Overview
4
+
5
+ Powerful table built on TanStack Table v8. Supports client-side and server-side modes with a unified API, advanced filtering (badges + builder), global search, multi-column sorting, row selection, column pinning, dynamic pagination, i18n, and loading skeletons.
6
+
7
+ ---
8
+
9
+ ## Props
10
+
11
+ | Prop | Type | Default | Description |
12
+ | ---------------------- | ------------------------------------- | ---------------------- | --------------------------------------------------------------------- |
13
+ | `columns` | `ColumnDef<TData, TValue>[]` | — | TanStack column definitions. Use `meta` to enable features. |
14
+ | `data` | `TData[]` | — | Table data. |
15
+ | `loading` | `boolean` | `false` | Show skeleton rows. |
16
+ | `emptyComponent` | `ReactNode` | `undefined` | Rendered when no rows. |
17
+ | `className` | `string` | `undefined` | Wrapper classes. |
18
+ | `checkable` | `boolean` | `false` | Adds a left checkbox column for row selection. |
19
+ | `rowSelection` | `Record<string, boolean>` | `{}` | Controlled selection map. |
20
+ | `onRowSelectionChange` | `OnChangeFn<Record<string, boolean>>` | `undefined` | Selection change handler (controlled selection). |
21
+ | `onCheckedRowsChange` | `(checkedRows: TData[]) => void` | `undefined` | Returns selected row values (requires `checkable`). |
22
+ | `actions` | `DataTableActions[]` | `[]` | Actions for the actions row. |
23
+ | `hidePagination` | `boolean` | `false` | Hide pagination UI. |
24
+ | `hideActionsRow` | `boolean` | `false` | Hide actions row. |
25
+ | `i18n` | `DataTableI18n` | `defaultDataTableI18n` | Internationalization strings. |
26
+ | `maxSortedColumns` | `number` | `2` | Max number of sorted columns. |
27
+ | `initialState` | `DataTableState<TData>` | `undefined` | Initial filters, sorting, pagination and optional `columnVisibility`. |
28
+ | `serverMode` | `boolean` | `false` | Enable server-side mode. |
29
+ | `serverConfig` | `DataTableServerConfig` | `undefined` | `{ totalItems, onStateChange }` handler for server mode. |
30
+ | `disableAutoPageSize` | `boolean` | `false` | Disable auto pageSize (still updates pageIndex). |
31
+
32
+ ---
33
+
34
+ ## Column meta
35
+
36
+ Configure columns via `column.meta`:
37
+
38
+ ```ts
39
+ type ColumnMeta = {
40
+ type:
41
+ | "string"
42
+ | "number"
43
+ | "boolean"
44
+ | "date"
45
+ | "datetime"
46
+ | "list_single_select"
47
+ | "list_multi_select"
48
+ | "other";
49
+ sortable?: boolean;
50
+ filterable?: boolean;
51
+ searchable?: boolean;
52
+ pinned?: "left" | "right";
53
+ listOptions?: { value: string; label: string }[];
54
+ };
55
+ ```
56
+
57
+ Notes:
58
+
59
+ - `id` must match the field key used for filtering/sorting.
60
+ - Header should be a simple string (not JSX) for proper filtering/sorting UI.
61
+ - Filtering nested accessors (e.g., `"user.name"`) is not supported.
62
+
63
+ ---
64
+
65
+ ## Behavior
66
+
67
+ - **Filtering**: Badge filters + advanced builder with logical `_and`/`_or`.
68
+ - **Global search**: Across `meta.searchable` columns; strings use `like`, arrays use `array_overlap` (mapped automatically).
69
+ - **Operators**: Full operator set per type, including `eq_null`/`n_eq_null`, list operators (`array_overlap`, `n_array_overlap`), date/time before/after, checked/unchecked.
70
+ - **Sorting**: Multi-column (limited by `maxSortedColumns`).
71
+ - **Selection**: Integrated checkbox column when `checkable`.
72
+ - **Column visibility**: Columns can start hidden via `initialState.columnVisibility` and be toggled from the eye icon popover in the toolbar.
73
+ - **Pinning**: `meta.pinned` supports left/right pinned columns.
74
+ - **Pagination**: Auto page size from container height; respects `disableAutoPageSize`.
75
+ - **Loading**: Skeleton rows adapt to viewport height (no hardcoded length).
76
+ - **i18n**: All labels (sorting/filtering menus included) use `DataTableI18n`.
77
+ - **Datetime**: Supports microseconds format like `2025-08-22T12:53:54.060315` and timezone-safe date handling.
78
+
79
+ ---
80
+
81
+ ## Server-side mode
82
+
83
+ When `serverMode=true`, the table emits state to `serverConfig.onStateChange(state)` with:
84
+
85
+ ```ts
86
+ type ServerState = {
87
+ pagination: { pageIndex: number; pageSize: number };
88
+ filters?: IFilterState;
89
+ computedFilter?: SearchFilter;
90
+ computedSorting?: { sort_by: string[]; sort_order: ("asc" | "desc")[] };
91
+ };
92
+ ```
93
+
94
+ The table manages debounced emissions and preserves computed values across updates.
95
+
96
+ ---
97
+
98
+ ## Examples
99
+
100
+ ### Client mode using utilities (columns + filters + initial state)
101
+
102
+ ```tsx
103
+ import * as React from "react";
104
+ import type { ColumnDef } from "@tanstack/react-table";
105
+ import {
106
+ DataTable,
107
+ createStringColumn,
108
+ createNumberColumn,
109
+ createSingleSelectColumn,
110
+ createMultiSelectColumn,
111
+ createActionColumn,
112
+ createInitialState,
113
+ createStringFilter,
114
+ createNumberFilter,
115
+ } from "laif-ds";
116
+ import { Button } from "laif-ds";
117
+
118
+ type Person = {
119
+ id: string;
120
+ name: string;
121
+ age: number;
122
+ role: string;
123
+ tags: string[];
124
+ created_at: string;
125
+ active: boolean;
126
+ };
127
+
128
+ const columns = [
129
+ createStringColumn<Person>({
130
+ accessorKey: "name",
131
+ header: "Nome",
132
+ sortable: true,
133
+ filterable: true,
134
+ searchable: true,
135
+ }),
136
+ createNumberColumn<Person>({
137
+ accessorKey: "age",
138
+ header: "Età",
139
+ sortable: true,
140
+ filterable: true,
141
+ }),
142
+ createSingleSelectColumn<Person>({
143
+ accessorKey: "role",
144
+ header: "Ruolo",
145
+ options: ["Admin", "User", "Guest"],
146
+ filterable: true,
147
+ searchable: true,
148
+ }),
149
+ createMultiSelectColumn<Person>({
150
+ accessorKey: "tags",
151
+ header: "Tags",
152
+ options: ["frontend", "backend", "devops"],
153
+ filterable: true,
154
+ }),
155
+ createActionColumn<Person>({
156
+ id: "actions",
157
+ header: "Azioni",
158
+ pinned: "right",
159
+ cell: (row) => <Button size="sm">Edit {row.name}</Button>,
160
+ }),
161
+ ] satisfies ColumnDef<Person, any>[];
162
+
163
+ const initialState = createInitialState({
164
+ filters: [
165
+ createStringFilter("name", "name", "Nome", "like", "John"),
166
+ createNumberFilter("age", "age", "Età", "ge", 18),
167
+ ],
168
+ searchbarFilter: "developer",
169
+ sorting: [{ column: "name", order: "asc" }],
170
+ pagination: { pageIndex: 0, pageSize: 15 },
171
+ });
172
+
173
+ const actions = [
174
+ {
175
+ label: "Export CSV",
176
+ icon: "FileDown",
177
+ onClick: () => {
178
+ /* ... */
179
+ },
180
+ },
181
+ {
182
+ label: "Bulk Delete",
183
+ icon: "Trash2",
184
+ onClick: () => {
185
+ /* ... */
186
+ },
187
+ },
188
+ ];
189
+
190
+ export function ClientTable({ data }: { data: Person[] }) {
191
+ return (
192
+ <DataTable
193
+ columns={columns}
194
+ data={data}
195
+ initialState={initialState}
196
+ actions={actions}
197
+ checkable
198
+ onCheckedRowsChange={(rows) => console.log("checked rows", rows)}
199
+ />
200
+ );
201
+ }
202
+ ```
203
+
204
+ ### Server mode using utilities (state-driven fetch)
205
+
206
+ ```tsx
207
+ import * as React from "react";
208
+ import type { ServerState } from "laif-ds";
209
+ import { DataTable, createInitialState } from "laif-ds";
210
+
211
+ export function ServerTable({
212
+ data,
213
+ total,
214
+ }: {
215
+ data: Person[];
216
+ total: number;
217
+ }) {
218
+ const [loading, setLoading] = React.useState(false);
219
+
220
+ const handleState = React.useCallback(async (state: ServerState) => {
221
+ // Use state.pagination, state.computedFilter, state.computedSorting
222
+ // to fetch from your backend
223
+ setLoading(true);
224
+ try {
225
+ await fetch("/api/people", {
226
+ method: "POST",
227
+ headers: { "Content-Type": "application/json" },
228
+ body: JSON.stringify(state),
229
+ });
230
+ // Update your data + total here based on response
231
+ } finally {
232
+ setLoading(false);
233
+ }
234
+ }, []);
235
+
236
+ return (
237
+ <DataTable
238
+ columns={columns}
239
+ data={data}
240
+ loading={loading}
241
+ serverMode
242
+ serverConfig={{ totalItems: total, onStateChange: handleState }}
243
+ initialState={createInitialState({
244
+ pagination: { pageIndex: 0, pageSize: 20 },
245
+ })}
246
+ checkable
247
+ />
248
+ );
249
+ }
250
+ ```
251
+
252
+ ### Initial column visibility
253
+
254
+ You can start with some columns hidden and let the user control them via the column-visibility (eye) popover:
255
+
256
+ ```tsx
257
+ const initialStateWithHiddenColumns = createInitialState<Person>({
258
+ pagination: { pageIndex: 0, pageSize: 15 },
259
+ sorting: [{ column: "name", order: "asc" }],
260
+ columnVisibility: {
261
+ // these columns will start hidden in the UI
262
+ secret_field: false,
263
+ debug_column: false,
264
+ },
265
+ });
266
+
267
+ export function TableWithHiddenColumns({ data }: { data: Person[] }) {
268
+ return (
269
+ <DataTable
270
+ columns={columns}
271
+ data={data}
272
+ initialState={initialStateWithHiddenColumns}
273
+ />
274
+ );
275
+ }
276
+ ```
277
+
278
+ ### Utility recipes (pinning, list options, quick filters)
279
+
280
+ ```tsx
281
+ import {
282
+ pinColumns,
283
+ updateColumnListOptions,
284
+ toSelectOptions,
285
+ createFilterBadges,
286
+ createStringFilter,
287
+ createNumberFilter,
288
+ } from "laif-ds";
289
+
290
+ // Pin columns to left/right
291
+ const pinnedColumns = pinColumns(columns, {
292
+ left: ["name"],
293
+ right: ["actions"],
294
+ });
295
+
296
+ // Update list options dynamically (e.g., fetched from API)
297
+ const roleOptions = toSelectOptions(["Admin", "User", "Guest", "Manager"]);
298
+ const columnsWithUpdatedRoles = updateColumnListOptions(
299
+ columns,
300
+ "role",
301
+ roleOptions,
302
+ );
303
+
304
+ // Build multiple filter badges quickly
305
+ const quickFilters = createFilterBadges([
306
+ {
307
+ columnId: "name",
308
+ columnAccessorKey: "name",
309
+ columnLabel: "Nome",
310
+ columnType: "string",
311
+ operator: "like",
312
+ value: "Jane",
313
+ },
314
+ {
315
+ columnId: "age",
316
+ columnAccessorKey: "age",
317
+ columnLabel: "Età",
318
+ columnType: "number",
319
+ operator: "ge",
320
+ value: 30,
321
+ },
322
+ ]);
323
+ ```
324
+
325
+ ---
326
+
327
+ ## Notes
328
+
329
+ - **Performance**: Client mode filters/sorts in-memory; use server mode for large datasets.
330
+ - **UX**: Page size auto-adapts; use `disableAutoPageSize` to manage it manually.
331
+ - **Internationalization**: Provide custom `i18n` for localized actions and labels.