laif-ds 0.2.44 → 0.2.46
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/dist/_virtual/index4.js +5 -5
- package/dist/_virtual/index5.js +5 -5
- package/dist/_virtual/index6.js +2 -2
- package/dist/_virtual/index7.js +2 -2
- package/dist/agent-docs/components/Accordion.md +157 -0
- package/dist/agent-docs/components/Alert.md +95 -0
- package/dist/agent-docs/components/AlertDialog.md +126 -0
- package/dist/agent-docs/components/AppEditor.md +90 -0
- package/dist/agent-docs/components/AppForm.md +291 -0
- package/dist/agent-docs/components/AppMultipleSelectDropdown.md +38 -0
- package/dist/agent-docs/components/AppRadioGroup.md +223 -0
- package/dist/agent-docs/components/AppSelect.md +427 -0
- package/dist/agent-docs/components/AppSidebar.md +122 -0
- package/dist/agent-docs/components/AppStepper.md +77 -0
- package/dist/agent-docs/components/AspectRatio.md +87 -0
- package/dist/agent-docs/components/AsyncSelect.md +127 -0
- package/dist/agent-docs/components/AudioVisualizer.md +41 -0
- package/dist/agent-docs/components/Avatar.md +113 -0
- package/dist/agent-docs/components/Badge.md +118 -0
- package/dist/agent-docs/components/Breadcrumb.md +78 -0
- package/dist/agent-docs/components/Button.md +129 -0
- package/dist/agent-docs/components/Calendar.md +222 -0
- package/dist/agent-docs/components/Card.md +147 -0
- package/dist/agent-docs/components/Carousel.md +129 -0
- package/dist/agent-docs/components/Chart.md +75 -0
- package/dist/agent-docs/components/Chat.md +109 -0
- package/dist/agent-docs/components/ChatMessage.md +61 -0
- package/dist/agent-docs/components/Checkbox.md +135 -0
- package/dist/agent-docs/components/CircularProgress.md +49 -0
- package/dist/agent-docs/components/CodeHighlighter.md +31 -0
- package/dist/agent-docs/components/Collapsible.md +95 -0
- package/dist/agent-docs/components/Command.md +142 -0
- package/dist/agent-docs/components/Confirmer.md +175 -0
- package/dist/agent-docs/components/ContextMenu.md +191 -0
- package/dist/agent-docs/components/CopyButton.md +26 -0
- package/dist/agent-docs/components/DataCrossTable.md +94 -0
- package/dist/agent-docs/components/DataTable.md +254 -0
- package/dist/agent-docs/components/DatePicker.md +109 -0
- package/dist/agent-docs/components/Dialog.md +125 -0
- package/dist/agent-docs/components/Drawer.md +127 -0
- package/dist/agent-docs/components/DropdownMenu.md +57 -0
- package/dist/agent-docs/components/FilePreview.md +99 -0
- package/dist/agent-docs/components/FilePreviewer.md +139 -0
- package/dist/agent-docs/components/FileUploader.md +129 -0
- package/dist/agent-docs/components/Form.md +62 -0
- package/dist/agent-docs/components/FormComposer.md +137 -0
- package/dist/agent-docs/components/GanttChart.md +122 -0
- package/dist/agent-docs/components/HoverCard.md +37 -0
- package/dist/agent-docs/components/Icon.md +99 -0
- package/dist/agent-docs/components/Input.md +138 -0
- package/dist/agent-docs/components/InputOtp.md +40 -0
- package/dist/agent-docs/components/InputSelector.md +97 -0
- package/dist/agent-docs/components/InterruptPrompt.md +32 -0
- package/dist/agent-docs/components/Label.md +28 -0
- package/dist/agent-docs/components/MarkdownRenderer.md +36 -0
- package/dist/agent-docs/components/Menubar.md +164 -0
- package/dist/agent-docs/components/MessageInput.md +131 -0
- package/dist/agent-docs/components/MessageList.md +96 -0
- package/dist/agent-docs/components/MultipleSelector.md +146 -0
- package/dist/agent-docs/components/NavigationMenu.md +51 -0
- package/dist/agent-docs/components/Pagination.md +55 -0
- package/dist/agent-docs/components/Popover.md +103 -0
- package/dist/agent-docs/components/Progress.md +30 -0
- package/dist/agent-docs/components/PromptSuggestions.md +33 -0
- package/dist/agent-docs/components/RadioGroup.md +90 -0
- package/dist/agent-docs/components/Resizable.md +35 -0
- package/dist/agent-docs/components/ResizePrompt.md +13 -0
- package/dist/agent-docs/components/ScrollArea.md +49 -0
- package/dist/agent-docs/components/SecurePdfViewer.md +38 -0
- package/dist/agent-docs/components/Select.md +132 -0
- package/dist/agent-docs/components/Separator.md +32 -0
- package/dist/agent-docs/components/Sheet.md +40 -0
- package/dist/agent-docs/components/ShikiHighlighter.md +31 -0
- package/dist/agent-docs/components/Sidebar.md +85 -0
- package/dist/agent-docs/components/Skeleton.md +29 -0
- package/dist/agent-docs/components/Slider.md +58 -0
- package/dist/agent-docs/components/Sonner.md +21 -0
- package/dist/agent-docs/components/Spinner.md +139 -0
- package/dist/agent-docs/components/Stepper.md +67 -0
- package/dist/agent-docs/components/Switch.md +42 -0
- package/dist/agent-docs/components/Table.md +63 -0
- package/dist/agent-docs/components/TableSkeleton.md +46 -0
- package/dist/agent-docs/components/Tabs.md +86 -0
- package/dist/agent-docs/components/TextArea.md +52 -0
- package/dist/agent-docs/components/ThemeSwitcher.md +69 -0
- package/dist/agent-docs/components/Toaster.md +23 -0
- package/dist/agent-docs/components/Toggle.md +31 -0
- package/dist/agent-docs/components/ToggleGroup.md +30 -0
- package/dist/agent-docs/components/Tooltip.md +91 -0
- package/dist/agent-docs/components/TypingIndicator.md +21 -0
- package/dist/agent-docs/components/Typo.md +65 -0
- package/dist/agent-docs/components/WeeklyCalendar.md +64 -0
- package/dist/agent-docs/components-list.md +144 -0
- package/dist/components/ui/app-form.js +61 -60
- package/dist/components/ui/date-picker.js +6 -5
- package/dist/index.d.ts +4 -3
- package/dist/node_modules/date-fns/_lib/normalizeDates.js +5 -5
- package/dist/node_modules/date-fns/isSameWeek.js +15 -0
- package/dist/node_modules/date-fns/locale/it/_lib/formatDistance.js +71 -0
- package/dist/node_modules/date-fns/locale/it/_lib/formatLong.js +34 -0
- package/dist/node_modules/date-fns/locale/it/_lib/formatRelative.js +50 -0
- package/dist/node_modules/date-fns/locale/it/_lib/localize.js +147 -0
- package/dist/node_modules/date-fns/locale/it/_lib/match.js +111 -0
- package/dist/node_modules/date-fns/locale/it.js +22 -0
- package/dist/node_modules/eventemitter3/index2.js +1 -1
- package/dist/node_modules/hast-util-to-jsx-runtime/lib/index.js +1 -1
- package/dist/node_modules/style-to-object/cjs/index.js +1 -1
- package/dist/node_modules/unified/lib/index.js +1 -1
- package/dist/styles.v3.css +1 -1
- 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
|
+
|