laif-ds 0.2.43 → 0.2.45

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.
Files changed (98) hide show
  1. package/dist/_virtual/index6.js +2 -2
  2. package/dist/_virtual/index7.js +2 -2
  3. package/dist/agent-docs/components/Accordion.md +157 -0
  4. package/dist/agent-docs/components/Alert.md +95 -0
  5. package/dist/agent-docs/components/AlertDialog.md +126 -0
  6. package/dist/agent-docs/components/AppEditor.md +90 -0
  7. package/dist/agent-docs/components/AppForm.md +242 -0
  8. package/dist/agent-docs/components/AppMultipleSelectDropdown.md +38 -0
  9. package/dist/agent-docs/components/AppRadioGroup.md +223 -0
  10. package/dist/agent-docs/components/AppSelect.md +427 -0
  11. package/dist/agent-docs/components/AppSidebar.md +122 -0
  12. package/dist/agent-docs/components/AppStepper.md +77 -0
  13. package/dist/agent-docs/components/AspectRatio.md +87 -0
  14. package/dist/agent-docs/components/AsyncSelect.md +127 -0
  15. package/dist/agent-docs/components/AudioVisualizer.md +41 -0
  16. package/dist/agent-docs/components/Avatar.md +113 -0
  17. package/dist/agent-docs/components/Badge.md +118 -0
  18. package/dist/agent-docs/components/Breadcrumb.md +78 -0
  19. package/dist/agent-docs/components/Button.md +129 -0
  20. package/dist/agent-docs/components/Calendar.md +222 -0
  21. package/dist/agent-docs/components/Card.md +147 -0
  22. package/dist/agent-docs/components/Carousel.md +129 -0
  23. package/dist/agent-docs/components/Chart.md +75 -0
  24. package/dist/agent-docs/components/Chat.md +109 -0
  25. package/dist/agent-docs/components/ChatMessage.md +61 -0
  26. package/dist/agent-docs/components/Checkbox.md +135 -0
  27. package/dist/agent-docs/components/CircularProgress.md +49 -0
  28. package/dist/agent-docs/components/CodeHighlighter.md +31 -0
  29. package/dist/agent-docs/components/Collapsible.md +95 -0
  30. package/dist/agent-docs/components/Command.md +142 -0
  31. package/dist/agent-docs/components/Confirmer.md +175 -0
  32. package/dist/agent-docs/components/ContextMenu.md +191 -0
  33. package/dist/agent-docs/components/CopyButton.md +26 -0
  34. package/dist/agent-docs/components/DataCrossTable.md +94 -0
  35. package/dist/agent-docs/components/DataTable.md +254 -0
  36. package/dist/agent-docs/components/DatePicker.md +109 -0
  37. package/dist/agent-docs/components/Dialog.md +125 -0
  38. package/dist/agent-docs/components/Drawer.md +127 -0
  39. package/dist/agent-docs/components/DropdownMenu.md +57 -0
  40. package/dist/agent-docs/components/FilePreview.md +99 -0
  41. package/dist/agent-docs/components/FilePreviewer.md +139 -0
  42. package/dist/agent-docs/components/FileUploader.md +129 -0
  43. package/dist/agent-docs/components/Form.md +62 -0
  44. package/dist/agent-docs/components/FormComposer.md +137 -0
  45. package/dist/agent-docs/components/GanttChart.md +122 -0
  46. package/dist/agent-docs/components/HoverCard.md +37 -0
  47. package/dist/agent-docs/components/Icon.md +99 -0
  48. package/dist/agent-docs/components/Input.md +138 -0
  49. package/dist/agent-docs/components/InputOtp.md +40 -0
  50. package/dist/agent-docs/components/InputSelector.md +97 -0
  51. package/dist/agent-docs/components/InterruptPrompt.md +32 -0
  52. package/dist/agent-docs/components/Label.md +28 -0
  53. package/dist/agent-docs/components/MarkdownRenderer.md +36 -0
  54. package/dist/agent-docs/components/Menubar.md +164 -0
  55. package/dist/agent-docs/components/MessageInput.md +131 -0
  56. package/dist/agent-docs/components/MessageList.md +96 -0
  57. package/dist/agent-docs/components/MultipleSelector.md +146 -0
  58. package/dist/agent-docs/components/NavigationMenu.md +51 -0
  59. package/dist/agent-docs/components/Pagination.md +55 -0
  60. package/dist/agent-docs/components/Popover.md +103 -0
  61. package/dist/agent-docs/components/Progress.md +30 -0
  62. package/dist/agent-docs/components/PromptSuggestions.md +33 -0
  63. package/dist/agent-docs/components/RadioGroup.md +90 -0
  64. package/dist/agent-docs/components/Resizable.md +35 -0
  65. package/dist/agent-docs/components/ResizePrompt.md +13 -0
  66. package/dist/agent-docs/components/ScrollArea.md +49 -0
  67. package/dist/agent-docs/components/SecurePdfViewer.md +38 -0
  68. package/dist/agent-docs/components/Select.md +132 -0
  69. package/dist/agent-docs/components/Separator.md +32 -0
  70. package/dist/agent-docs/components/Sheet.md +40 -0
  71. package/dist/agent-docs/components/ShikiHighlighter.md +31 -0
  72. package/dist/agent-docs/components/Sidebar.md +85 -0
  73. package/dist/agent-docs/components/Skeleton.md +29 -0
  74. package/dist/agent-docs/components/Slider.md +58 -0
  75. package/dist/agent-docs/components/Sonner.md +21 -0
  76. package/dist/agent-docs/components/Spinner.md +139 -0
  77. package/dist/agent-docs/components/Stepper.md +67 -0
  78. package/dist/agent-docs/components/Switch.md +42 -0
  79. package/dist/agent-docs/components/Table.md +63 -0
  80. package/dist/agent-docs/components/TableSkeleton.md +46 -0
  81. package/dist/agent-docs/components/Tabs.md +86 -0
  82. package/dist/agent-docs/components/TextArea.md +52 -0
  83. package/dist/agent-docs/components/ThemeSwitcher.md +69 -0
  84. package/dist/agent-docs/components/Toaster.md +23 -0
  85. package/dist/agent-docs/components/Toggle.md +31 -0
  86. package/dist/agent-docs/components/ToggleGroup.md +30 -0
  87. package/dist/agent-docs/components/Tooltip.md +91 -0
  88. package/dist/agent-docs/components/TypingIndicator.md +21 -0
  89. package/dist/agent-docs/components/Typo.md +65 -0
  90. package/dist/agent-docs/components/WeeklyCalendar.md +64 -0
  91. package/dist/agent-docs/components-list.md +144 -0
  92. package/dist/components/ui/spinner.js +67 -0
  93. package/dist/index.d.ts +11 -0
  94. package/dist/index.js +363 -361
  95. package/dist/node_modules/eventemitter3/index2.js +1 -1
  96. package/dist/node_modules/style-to-object/cjs/index.js +1 -1
  97. package/dist/styles.v3.css +1 -1
  98. package/package.json +3 -2
@@ -0,0 +1,191 @@
1
+ # ContextMenu
2
+
3
+ ## Overview
4
+
5
+ Right-click context menu built on Radix. Supports items, groups, separators, submenus, checkbox items, radio groups, and keyboard shortcuts.
6
+
7
+ ---
8
+
9
+ ## Props
10
+
11
+ ### ContextMenu (Root)
12
+
13
+ | Prop | Type | Default | Description |
14
+ | ----------- | ----------------- | ----------- | ----------------------------------------- |
15
+ | `children` | `React.ReactNode` | **required**| Include `ContextMenuTrigger` and content. |
16
+
17
+ ### Subcomponents
18
+
19
+ - `ContextMenuTrigger`: The element that opens the menu on right-click.
20
+ - `ContextMenuContent`: The menu panel container.
21
+ - `ContextMenuItem`: A clickable item. Props:
22
+ - `variant?: "default" | "destructive"`
23
+ - `inset?: boolean`
24
+ - `ContextMenuCheckboxItem`: Checkbox-like item. Props:
25
+ - `checked?: boolean`
26
+ - `ContextMenuRadioGroup`: Radio group container. Props: `value: string`.
27
+ - `ContextMenuRadioItem`: A radio item. Props: `value: string`.
28
+ - `ContextMenuSub` / `ContextMenuSubTrigger` / `ContextMenuSubContent`: Submenu controls.
29
+ - `ContextMenuLabel`: Section label. Props: `inset?: boolean`.
30
+ - `ContextMenuSeparator`: Horizontal separator.
31
+ - `ContextMenuShortcut`: Right-aligned text (e.g., keyboard shortcut).
32
+
33
+ ---
34
+
35
+ ## Behavior
36
+
37
+ - **Trigger**: Right-click (contextmenu) on the trigger shows the menu.
38
+ - **Submenus**: Use `ContextMenuSub` to nest menus.
39
+ - **Checkbox/Radio**: Use state to control `checked` and `value` props.
40
+ - **Accessibility**: Keyboard navigation and ARIA attributes handled by Radix.
41
+
42
+ ---
43
+
44
+ ## Examples
45
+
46
+ ### Basic
47
+
48
+ ```tsx
49
+ import {
50
+ ContextMenu,
51
+ ContextMenuTrigger,
52
+ ContextMenuContent,
53
+ ContextMenuItem,
54
+ ContextMenuSeparator,
55
+ ContextMenuShortcut,
56
+ } from "laif-ds";
57
+
58
+ export function BasicContextMenu() {
59
+ return (
60
+ <ContextMenu>
61
+ <ContextMenuTrigger className="flex h-[150px] w-[300px] items-center justify-center rounded-md border border-dashed text-sm">
62
+ Right click here
63
+ </ContextMenuTrigger>
64
+ <ContextMenuContent className="w-64">
65
+ <ContextMenuItem>
66
+ Back
67
+ <ContextMenuShortcut>⌘[</ContextMenuShortcut>
68
+ </ContextMenuItem>
69
+ <ContextMenuItem>
70
+ Forward
71
+ <ContextMenuShortcut>⌘]</ContextMenuShortcut>
72
+ </ContextMenuItem>
73
+ <ContextMenuItem>
74
+ Reload
75
+ <ContextMenuShortcut>⌘R</ContextMenuShortcut>
76
+ </ContextMenuItem>
77
+ <ContextMenuSeparator />
78
+ <ContextMenuItem>
79
+ Save As...
80
+ <ContextMenuShortcut>⌘S</ContextMenuShortcut>
81
+ </ContextMenuItem>
82
+ <ContextMenuItem>
83
+ Print...
84
+ <ContextMenuShortcut>⌘P</ContextMenuShortcut>
85
+ </ContextMenuItem>
86
+ </ContextMenuContent>
87
+ </ContextMenu>
88
+ );
89
+ }
90
+ ```
91
+
92
+ ### With Submenu
93
+
94
+ ```tsx
95
+ import {
96
+ ContextMenu,
97
+ ContextMenuTrigger,
98
+ ContextMenuContent,
99
+ ContextMenuItem,
100
+ ContextMenuSub,
101
+ ContextMenuSubTrigger,
102
+ ContextMenuSubContent,
103
+ ContextMenuSeparator,
104
+ ContextMenuShortcut,
105
+ } from "laif-ds";
106
+
107
+ export function WithSubmenu() {
108
+ return (
109
+ <ContextMenu>
110
+ <ContextMenuTrigger className="flex h-[150px] w-[300px] items-center justify-center rounded-md border border-dashed text-sm">
111
+ Right click here
112
+ </ContextMenuTrigger>
113
+ <ContextMenuContent className="w-64">
114
+ <ContextMenuItem>
115
+ Back
116
+ <ContextMenuShortcut>⌘[</ContextMenuShortcut>
117
+ </ContextMenuItem>
118
+ <ContextMenuItem>
119
+ Forward
120
+ <ContextMenuShortcut>⌘]</ContextMenuShortcut>
121
+ </ContextMenuItem>
122
+ <ContextMenuSub>
123
+ <ContextMenuSubTrigger>More Tools</ContextMenuSubTrigger>
124
+ <ContextMenuSubContent className="w-48">
125
+ <ContextMenuItem>
126
+ Save Page As...
127
+ <ContextMenuShortcut>⇧⌘S</ContextMenuShortcut>
128
+ </ContextMenuItem>
129
+ <ContextMenuItem>Create Shortcut...</ContextMenuItem>
130
+ <ContextMenuItem>Name Window...</ContextMenuItem>
131
+ <ContextMenuSeparator />
132
+ <ContextMenuItem>Developer Tools</ContextMenuItem>
133
+ </ContextMenuSubContent>
134
+ </ContextMenuSub>
135
+ <ContextMenuSeparator />
136
+ <ContextMenuItem>
137
+ Print...
138
+ <ContextMenuShortcut>⌘P</ContextMenuShortcut>
139
+ </ContextMenuItem>
140
+ </ContextMenuContent>
141
+ </ContextMenu>
142
+ );
143
+ }
144
+ ```
145
+
146
+ ### With Checkbox and Radio
147
+
148
+ ```tsx
149
+ import {
150
+ ContextMenu,
151
+ ContextMenuTrigger,
152
+ ContextMenuContent,
153
+ ContextMenuCheckboxItem,
154
+ ContextMenuLabel,
155
+ ContextMenuSeparator,
156
+ ContextMenuRadioGroup,
157
+ ContextMenuRadioItem,
158
+ } from "laif-ds";
159
+
160
+ export function WithCheckboxAndRadio() {
161
+ return (
162
+ <ContextMenu>
163
+ <ContextMenuTrigger className="flex h-[150px] w-[300px] items-center justify-center rounded-md border border-dashed text-sm">
164
+ Right click here
165
+ </ContextMenuTrigger>
166
+ <ContextMenuContent className="w-64">
167
+ <ContextMenuLabel>Options</ContextMenuLabel>
168
+ <ContextMenuSeparator />
169
+ <ContextMenuCheckboxItem>Show Bookmarks Bar</ContextMenuCheckboxItem>
170
+ <ContextMenuCheckboxItem checked>Show Full URLs</ContextMenuCheckboxItem>
171
+ <ContextMenuSeparator />
172
+ <ContextMenuLabel>View</ContextMenuLabel>
173
+ <ContextMenuRadioGroup value="comfortable">
174
+ <ContextMenuRadioItem value="comfortable">Comfortable</ContextMenuRadioItem>
175
+ <ContextMenuRadioItem value="compact">Compact</ContextMenuRadioItem>
176
+ <ContextMenuRadioItem value="condensed">Condensed</ContextMenuRadioItem>
177
+ </ContextMenuRadioGroup>
178
+ </ContextMenuContent>
179
+ </ContextMenu>
180
+ );
181
+ }
182
+ ```
183
+
184
+ ---
185
+
186
+ ## Notes
187
+
188
+ - **Variants**: Use `variant="destructive"` on `ContextMenuItem` for dangerous actions.
189
+ - **Inset**: Use `inset` on items/labels to align with other content.
190
+ - **Keyboard**: Use arrow keys and Enter to navigate/activate items.
191
+
@@ -0,0 +1,26 @@
1
+ # CopyButton
2
+
3
+ ## Overview
4
+
5
+ Button that copies provided content to clipboard and animates icon state.
6
+
7
+ ---
8
+
9
+ ## Props
10
+
11
+ | Prop | Type | Description |
12
+ | ------------- | -------- | ------------------------------------------------ |
13
+ | `content` | `string` | Text to copy |
14
+ | `copyMessage` | `string` | Optional message displayed by the clipboard hook |
15
+
16
+ ---
17
+
18
+ ## Example
19
+
20
+ ```tsx
21
+ import { CopyButton } from "laif-ds";
22
+
23
+ export function CopySnippet() {
24
+ return <CopyButton content="npm i laif-ds" copyMessage="Copied!" />;
25
+ }
26
+ ```
@@ -0,0 +1,94 @@
1
+ # DataCrossTable
2
+
3
+ ## Overview
4
+
5
+ Cross table component that renders a matrix from two headers (top/left) with virtualized rows, sticky headers/first column, optional filtering/sorting, and an edit mode supported by a context provider and action buttons.
6
+
7
+ ---
8
+
9
+ ## Props
10
+
11
+ | Prop | Type | Default | Description |
12
+ | ------------------ | ----------------------- | ------- | ----------- |
13
+ | `crossTableData` | `CrossTableData` | — | Matrix data and headers. |
14
+ | `filterable` | `boolean` | `false` | Enables sorting via header buttons and row sorting by selected row. |
15
+ | `loading` | `boolean` | `false` | Shows a skeleton table. |
16
+ | `emptyComponent` | `ReactNode` | `undefined` | Shown when no data. |
17
+ | `className` | `string` | `undefined` | Wrapper classes. |
18
+ | `notFoundMessage` | `string` | `"Nessun risultato trovato."` | Fallback empty message. |
19
+ | `cornerHeaderFrom` | `string` | `"Da"` | Corner label (top-left) from. |
20
+ | `cornerHeaderTo` | `string` | `"A"` | Corner label (top-left) to. |
21
+ | `minWidthCell` | `number` | `160` | Minimum cell width in px. |
22
+ | `editable` | `boolean` | `false` | Enable edit mode features. |
23
+ | `editMode` | `boolean` | `false` | Control edit mode from outside. |
24
+ | `onEditModeChange` | `(editMode: boolean) => void` | `undefined` | Notified when edit mode changes. |
25
+ | `onSelectedRow` | `(row: CrossTableHeader) => void` | `undefined` | Emitted when selecting a row for sorting. |
26
+ | `selectedRow` | `CrossTableHeader` | `undefined` | Controlled selected row. |
27
+ | `rowSortAsc` | `boolean` | `true` | Sort ascending when selecting a row. |
28
+
29
+ ### Types
30
+
31
+ - `CrossTableHeader` → `{ id: string; label: string }`
32
+ - `CrossTableCell` → `{ render?:(fromId,toId,id?)=>ReactNode; value?: number|string|null; bgColor?: string; textColor?: string; fromId: string; toId: string; id?: string; editable?: boolean }`
33
+ - `CrossTableData` → `{ headerTop: CrossTableHeader[]; headerLeft: CrossTableHeader[]; data: (CrossTableCell|null)[][] }`
34
+
35
+ ---
36
+
37
+ ## Provider & Actions
38
+
39
+ Use `DataCrossTableProvider` to manage edit state across the table and expose a buttons group.
40
+
41
+ - `DataCrossTableProvider` props:
42
+ - `onConfirmedCells?(data: { editedCells: ConfirmedCell[]; toDefaultCells: ConfirmedCell[] })`
43
+ - Labels: `editConfirmLabel`, `editCancelLabel`, `editRestoreDefaultLabel`
44
+ - Flags: `initialEditMode` (default `false`), `showDefaultActionButton` (default `false`)
45
+ - Editable input labels: `cellEditTitleLabel`, `cellEditModifiedLabel`, `cellConfirmButtonLabel`, `cellCancelButtonLabel`, `cellResetButtonLabel`
46
+ - `DataCrossTableButtonsGroup`: shows Confirm/Cancel/Restore actions when `editMode=true`.
47
+
48
+ ---
49
+
50
+ ## Examples
51
+
52
+ ### Default with Provider
53
+
54
+ ```tsx
55
+ import { DataCrossTable, DataCrossTableProvider, DataCrossTableButtonsGroup } from "laif-ds";
56
+
57
+ export function CrossEditable({ data }: { data: CrossTableData }) {
58
+ return (
59
+ <DataCrossTableProvider initialEditMode onConfirmedCells={(cells) => console.log(cells)}>
60
+ {({ editMode }) => (
61
+ <div className="space-y-3">
62
+ <DataCrossTableButtonsGroup />
63
+ <DataCrossTable crossTableData={data} editable editMode={editMode} minWidthCell={200} />
64
+ </div>
65
+ )}
66
+ </DataCrossTableProvider>
67
+ );
68
+ }
69
+ ```
70
+
71
+ ### Filterable
72
+
73
+ ```tsx
74
+ <DataCrossTableProvider>
75
+ <DataCrossTable crossTableData={data} filterable minWidthCell={200} cornerHeaderFrom="From" cornerHeaderTo="To" />
76
+ </DataCrossTableProvider>
77
+ ```
78
+
79
+ ### Loading State
80
+
81
+ ```tsx
82
+ <DataCrossTableProvider>
83
+ <DataCrossTable loading crossTableData={{ headerTop: [], headerLeft: [], data: [] }} />
84
+ </DataCrossTableProvider>
85
+ ```
86
+
87
+ ---
88
+
89
+ ## Notes
90
+
91
+ - **Virtualization**: Rows are virtualized for performance on large datasets.
92
+ - **Sticky**: Top header row and first column are sticky; corner cell has higher z-index.
93
+ - **Editing**: Editable cells open a popover editor; edited/reset markers are shown per cell.
94
+
@@ -0,0 +1,254 @@
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.
@@ -0,0 +1,109 @@
1
+ # DatePicker
2
+
3
+ ## Overview
4
+
5
+ Single-date picker composed of a `Button`-like trigger and a `Calendar` in a popover. Supports min/max date constraints, allowed dates, custom display format, sizes, and button variants.
6
+
7
+ ---
8
+
9
+ ## Props
10
+
11
+ | Prop | Type | Default | Description |
12
+ | --------------- | -------------------------------------------------------------------- | ------------- | -------------------------------------------------- |
13
+ | `value` | `Date` | `undefined` | Controlled selected date. |
14
+ | `onChange` | `(date: Date | undefined) => void` | `undefined` | Called when the date changes. |
15
+ | `placeholder` | `string` | `"Seleziona data"` | Text when no date is selected. |
16
+ | `dateFormat` | `string` | `"PPP"` | `date-fns` format string for the trigger text. |
17
+ | `className` | `string` | `""` | Additional classes for the trigger. |
18
+ | `buttonVariant` | `"default" | "destructive" | "outline" | "secondary" | "ghost" | "link"` | `"default"` | Variant of the trigger button. |
19
+ | `disabled` | `boolean` | `false` | Disables interactions and the popover. |
20
+ | `size` | `"sm" | "default" | "lg"` | `"default"` | Trigger size. |
21
+ | `firstDate` | `Date` | `undefined` | Minimum selectable date. |
22
+ | `lastDate` | `Date` | `undefined` | Maximum selectable date. |
23
+ | `availableDates`| `Date[]` | `undefined` | Only these dates are selectable. |
24
+
25
+ ---
26
+
27
+ ## Behavior
28
+
29
+ - **Disabled dates**: `firstDate`, `lastDate`, and `availableDates` are combined into the `Calendar`’s `disabled` matcher array.
30
+ - **Disabled**: When `disabled` is true, the popover will not open and the trigger is non-interactive.
31
+ - **Formatting**: `dateFormat` is applied via `date-fns/format` to the selected date.
32
+
33
+ ---
34
+
35
+ ## Examples
36
+
37
+ ### Basic
38
+
39
+ ```tsx
40
+ import { DatePicker } from "laif-ds";
41
+
42
+ export function BasicDatePicker() {
43
+ return <DatePicker />;
44
+ }
45
+ ```
46
+
47
+ ### Configurable
48
+
49
+ ```tsx
50
+ import { DatePicker } from "laif-ds";
51
+
52
+ export function ConfigurableDatePicker() {
53
+ return (
54
+ <DatePicker
55
+ value={new Date()}
56
+ placeholder="Seleziona una data"
57
+ dateFormat="PPP"
58
+ className="w-[300px]"
59
+ buttonVariant="outline"
60
+ />
61
+ );
62
+ }
63
+ ```
64
+
65
+ ### With Min/Max Dates
66
+
67
+ ```tsx
68
+ import { DatePicker } from "laif-ds";
69
+
70
+ export function WithMinMaxDates() {
71
+ return (
72
+ <DatePicker
73
+ placeholder="Seleziona una data tra le date minima e massima"
74
+ firstDate={new Date("2025-09-20")}
75
+ lastDate={new Date("2025-09-28")}
76
+ buttonVariant="outline"
77
+ />
78
+ );
79
+ }
80
+ ```
81
+
82
+ ### With Available Dates
83
+
84
+ ```tsx
85
+ import { DatePicker } from "laif-ds";
86
+
87
+ export function WithAvailableDates() {
88
+ return (
89
+ <DatePicker
90
+ placeholder="Scegli una delle date disponibili"
91
+ availableDates={[
92
+ new Date("2025-09-22"),
93
+ new Date("2025-09-25"),
94
+ new Date("2025-09-27"),
95
+ ]}
96
+ buttonVariant="outline"
97
+ />
98
+ );
99
+ }
100
+ ```
101
+
102
+ ---
103
+
104
+ ## Notes
105
+
106
+ - **Sizing**: Use `size` to control the trigger typography and height.
107
+ - **Popover width**: The popover content uses the `Calendar` with no extra padding by default.
108
+ - **Internationalization**: The displayed date depends on the `dateFormat` string.
109
+