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.
- 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 +242 -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/spinner.js +67 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +363 -361
- package/dist/node_modules/eventemitter3/index2.js +1 -1
- package/dist/node_modules/style-to-object/cjs/index.js +1 -1
- package/dist/styles.v3.css +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# Calendar
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Flexible calendar component built on `react-day-picker`. Supports single, multiple, and range selections, localization, week settings, and rich customization via class names and sub-components.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
|
|
11
|
+
Props extend `DayPicker` props with a few defaults and additions.
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
| ---------------- | -------------------------------------------- | ------------ | ------------------------------------------------ |
|
|
15
|
+
| `mode` | `"default" | "single" | "multiple" | "range"` | `"default"` | Selection mode. |
|
|
16
|
+
| `selected` | `Date | Date[] | DateRange` | `undefined` | Controlled selection value. |
|
|
17
|
+
| `defaultMonth` | `Date` | `undefined` | Month to display initially. |
|
|
18
|
+
| `fromDate` | `Date` | `undefined` | Minimum selectable date. |
|
|
19
|
+
| `toDate` | `Date` | `undefined` | Maximum selectable date. |
|
|
20
|
+
| `disabled` | `Matcher | Matcher[]` | `undefined` | Disabled dates. |
|
|
21
|
+
| `showOutsideDays`| `boolean` | `true` | Show days from adjacent months. |
|
|
22
|
+
| `ISOWeek` | `boolean` | `false` | Use ISO week numbering. |
|
|
23
|
+
| `fixedWeeks` | `boolean` | `false` | Always show 6 weeks. |
|
|
24
|
+
| `numberOfMonths` | `number` | `1` | Number of months to display. |
|
|
25
|
+
| `locale` | `Locale` | `undefined` | Locale object for formatting. |
|
|
26
|
+
| `weekStartsOn` | `0 | 1 | 2 | 3 | 4 | 5 | 6` | `0` | Start of the week (0=Sun, 1=Mon, ...). |
|
|
27
|
+
| `captionLayout` | `"label" | "dropdown"` | `"label"` | Caption rendering mode. |
|
|
28
|
+
| `buttonVariant` | `Button["variant"]` | `"ghost"` | Variant for navigation buttons. |
|
|
29
|
+
| `formatters` | `Partial<DayPickerFormatters>` | `{}` | Custom label formatters. |
|
|
30
|
+
| `components` | `Partial<DayPickerComponents>` | `{}` | Custom component overrides. |
|
|
31
|
+
| `className` | `string` | `""` | Additional container classes. |
|
|
32
|
+
| `onSelect` | `(value: Date | Date[] | DateRange | undefined) => void` | `undefined` | Called when selection changes. |
|
|
33
|
+
| `onDayClick` | `(day: Date) => void` | `undefined` | Called on day click. |
|
|
34
|
+
| `onMonthChange` | `(month: Date) => void` | `undefined` | Called when the displayed month changes. |
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Behavior
|
|
39
|
+
|
|
40
|
+
- **Selection**: Single, multiple, and range selection with visual feedback.
|
|
41
|
+
- **Navigation**: Previous/next buttons use `buttonVariant` styling.
|
|
42
|
+
- **Localization**: Supply `locale`, `weekStartsOn`, and `formatters` for i18n.
|
|
43
|
+
- **Accessibility**: Keyboard navigation and focus management included.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Examples
|
|
48
|
+
|
|
49
|
+
### Basic
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
import { Calendar } from "laif-ds";
|
|
53
|
+
|
|
54
|
+
export function BasicCalendar() {
|
|
55
|
+
return (
|
|
56
|
+
<Calendar
|
|
57
|
+
className="border-d-border rounded-md border"
|
|
58
|
+
showOutsideDays
|
|
59
|
+
onDayClick={(d) => console.log("day clicked", d)}
|
|
60
|
+
onMonthChange={(m) => console.log("month", m)}
|
|
61
|
+
/>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Single Selection
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
import { useState } from "react";
|
|
70
|
+
import { Calendar } from "laif-ds";
|
|
71
|
+
|
|
72
|
+
export function SingleSelection() {
|
|
73
|
+
const [date, setDate] = useState<Date | undefined>(new Date());
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<div className="flex flex-col gap-2">
|
|
77
|
+
<Calendar
|
|
78
|
+
mode="single"
|
|
79
|
+
selected={date}
|
|
80
|
+
onSelect={setDate}
|
|
81
|
+
className="border-d-border rounded-md border"
|
|
82
|
+
/>
|
|
83
|
+
<p className="text-sm text-d-secondary-foreground text-center">
|
|
84
|
+
{date ? date.toDateString() : "Nessuna data selezionata"}
|
|
85
|
+
</p>
|
|
86
|
+
</div>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Multiple Selection
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
import { useState } from "react";
|
|
95
|
+
import { Calendar } from "laif-ds";
|
|
96
|
+
|
|
97
|
+
export function MultipleSelection() {
|
|
98
|
+
const [dates, setDates] = useState<Date[] | undefined>([new Date()]);
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<div className="flex flex-col gap-2">
|
|
102
|
+
<Calendar
|
|
103
|
+
mode="multiple"
|
|
104
|
+
selected={dates}
|
|
105
|
+
onSelect={setDates}
|
|
106
|
+
className="border-d-border rounded-md border"
|
|
107
|
+
/>
|
|
108
|
+
<p className="text-sm text-d-secondary-foreground text-center">
|
|
109
|
+
{dates && dates.length > 0 ? `${dates.length} date selezionate` : "Nessuna data selezionata"}
|
|
110
|
+
</p>
|
|
111
|
+
</div>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Range Selection
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
import { useState } from "react";
|
|
120
|
+
import { Calendar } from "laif-ds";
|
|
121
|
+
import type { DateRange } from "react-day-picker";
|
|
122
|
+
|
|
123
|
+
export function RangeSelection() {
|
|
124
|
+
const [range, setRange] = useState<DateRange | undefined>({ from: new Date(), to: new Date() });
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<div className="flex flex-col gap-2">
|
|
128
|
+
<Calendar
|
|
129
|
+
mode="range"
|
|
130
|
+
selected={range}
|
|
131
|
+
onSelect={setRange}
|
|
132
|
+
className="border-d-border rounded-md border"
|
|
133
|
+
numberOfMonths={2}
|
|
134
|
+
showOutsideDays
|
|
135
|
+
/>
|
|
136
|
+
<p className="text-sm text-d-secondary-foreground text-center">
|
|
137
|
+
{range?.from && range?.to
|
|
138
|
+
? `${range.from.toDateString()} - ${range.to.toDateString()}`
|
|
139
|
+
: range?.from
|
|
140
|
+
? `Da ${range.from.toDateString()}`
|
|
141
|
+
: "Seleziona un intervallo"}
|
|
142
|
+
</p>
|
|
143
|
+
</div>
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Disabled Dates
|
|
149
|
+
|
|
150
|
+
```tsx
|
|
151
|
+
import { useState } from "react";
|
|
152
|
+
import { Calendar } from "laif-ds";
|
|
153
|
+
import { addDays } from "date-fns";
|
|
154
|
+
|
|
155
|
+
export function DisabledDates() {
|
|
156
|
+
const [date, setDate] = useState<Date | undefined>(new Date());
|
|
157
|
+
const disabledDays = [
|
|
158
|
+
{ from: addDays(new Date(), 1), to: addDays(new Date(), 5) },
|
|
159
|
+
new Date(new Date().setDate(15)),
|
|
160
|
+
{ before: addDays(new Date(), -10) },
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
return (
|
|
164
|
+
<Calendar
|
|
165
|
+
mode="single"
|
|
166
|
+
selected={date}
|
|
167
|
+
onSelect={setDate}
|
|
168
|
+
disabled={disabledDays}
|
|
169
|
+
className="border-d-border rounded-md border"
|
|
170
|
+
/>
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Localized (Italian) and Week Start
|
|
176
|
+
|
|
177
|
+
```tsx
|
|
178
|
+
import { Calendar } from "laif-ds";
|
|
179
|
+
import { it } from "date-fns/locale";
|
|
180
|
+
import { format } from "date-fns";
|
|
181
|
+
|
|
182
|
+
export function LocalizedCalendar() {
|
|
183
|
+
return (
|
|
184
|
+
<Calendar
|
|
185
|
+
className="border-d-border rounded-md border"
|
|
186
|
+
locale={it}
|
|
187
|
+
weekStartsOn={1}
|
|
188
|
+
formatters={{
|
|
189
|
+
formatMonthCaption: (date: Date) => format(date, "MMMM yyyy", { locale: it }),
|
|
190
|
+
formatWeekdayName: (date: Date) => format(date, "EEEEEE", { locale: it }),
|
|
191
|
+
}}
|
|
192
|
+
/>
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### ISO Week, Fixed Weeks, Multiple Months
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
import { Calendar } from "laif-ds";
|
|
201
|
+
|
|
202
|
+
export function ISOWeekCalendar() {
|
|
203
|
+
return <Calendar className="border-d-border rounded-md border" ISOWeek weekStartsOn={1} />;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function FixedWeeksCalendar() {
|
|
207
|
+
return <Calendar className="border-d-border rounded-md border" fixedWeeks showOutsideDays />;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function MultiMonthCalendar() {
|
|
211
|
+
return <Calendar className="border-d-border rounded-md border" numberOfMonths={2} showOutsideDays />;
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Notes
|
|
218
|
+
|
|
219
|
+
- **Customization**: Use `classNames` and `components` to override internal parts.
|
|
220
|
+
- **Buttons**: `buttonVariant` controls navigation buttons’ appearance.
|
|
221
|
+
- **Range**: Range selection highlights start, middle, and end days with rounded edges.
|
|
222
|
+
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Card
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Composable container with header, content, footer, and optional action area. Supports size variants that control internal padding and spacing.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
|
|
11
|
+
### Card (Root)
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
| ----------- | ----------------------------- | ----------- | -------------------------------------------- |
|
|
15
|
+
| `size` | `"default" | "sm" | "lg" | "none"` | `"default"` | Controls internal padding and spacing. |
|
|
16
|
+
| `className` | `string` | `""` | Additional classes for layout and width. |
|
|
17
|
+
| `children` | `React.ReactNode` | **required**| Compose with subcomponents below. |
|
|
18
|
+
|
|
19
|
+
### Subcomponents
|
|
20
|
+
|
|
21
|
+
- `CardHeader`: Top section, usually with `CardTitle`, `CardDescription`, and optional `CardAction`.
|
|
22
|
+
- `CardTitle`: Title text area.
|
|
23
|
+
- `CardDescription`: Secondary text under the title.
|
|
24
|
+
- `CardAction`: Right-aligned area inside the header for buttons/menus.
|
|
25
|
+
- `CardContent`: Main content area.
|
|
26
|
+
- `CardFooter`: Bottom area for actions or summaries.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Behavior
|
|
31
|
+
|
|
32
|
+
- **Size variants**: `sm`, `default`, `lg`, `none` change vertical padding and gaps.
|
|
33
|
+
- **Header/Footer borders**: Apply border utilities on header/footer to create separators.
|
|
34
|
+
- **Layout**: Use `className` for width and responsive behavior.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Examples
|
|
39
|
+
|
|
40
|
+
### Basic
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from "laif-ds";
|
|
44
|
+
import { Button } from "laif-ds";
|
|
45
|
+
|
|
46
|
+
export function BasicCard() {
|
|
47
|
+
return (
|
|
48
|
+
<Card className="w-[350px]">
|
|
49
|
+
<CardHeader>
|
|
50
|
+
<CardTitle>Card Title</CardTitle>
|
|
51
|
+
<CardDescription>Card description goes here</CardDescription>
|
|
52
|
+
</CardHeader>
|
|
53
|
+
<CardContent>
|
|
54
|
+
<p>This is the main content of the card. You can put any content here.</p>
|
|
55
|
+
</CardContent>
|
|
56
|
+
<CardFooter>
|
|
57
|
+
<Button>Action</Button>
|
|
58
|
+
</CardFooter>
|
|
59
|
+
</Card>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### With Action
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
import { Card, CardHeader, CardTitle, CardDescription, CardAction, CardContent } from "laif-ds";
|
|
68
|
+
import { Button } from "laif-ds";
|
|
69
|
+
|
|
70
|
+
export function CardWithAction() {
|
|
71
|
+
return (
|
|
72
|
+
<Card className="w-[350px]">
|
|
73
|
+
<CardHeader>
|
|
74
|
+
<CardTitle>Card with Action</CardTitle>
|
|
75
|
+
<CardDescription>Card with an action button in the header</CardDescription>
|
|
76
|
+
<CardAction>
|
|
77
|
+
<Button variant="ghost" size="icon">⋯</Button>
|
|
78
|
+
</CardAction>
|
|
79
|
+
</CardHeader>
|
|
80
|
+
<CardContent>
|
|
81
|
+
<p>This card has an action button in the top right corner.</p>
|
|
82
|
+
</CardContent>
|
|
83
|
+
</Card>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Size Variants
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "laif-ds";
|
|
92
|
+
|
|
93
|
+
export function SizeVariants() {
|
|
94
|
+
return (
|
|
95
|
+
<div className="flex flex-col gap-8">
|
|
96
|
+
<Card size="sm" className="w-[350px]">
|
|
97
|
+
<CardHeader>
|
|
98
|
+
<CardTitle>Size: Small</CardTitle>
|
|
99
|
+
<CardDescription>Reduced padding (sm)</CardDescription>
|
|
100
|
+
</CardHeader>
|
|
101
|
+
<CardContent>
|
|
102
|
+
<p>This card uses size="sm".</p>
|
|
103
|
+
</CardContent>
|
|
104
|
+
</Card>
|
|
105
|
+
|
|
106
|
+
<Card size="default" className="w-[350px]">
|
|
107
|
+
<CardHeader>
|
|
108
|
+
<CardTitle>Size: Default</CardTitle>
|
|
109
|
+
<CardDescription>Standard padding (default)</CardDescription>
|
|
110
|
+
</CardHeader>
|
|
111
|
+
<CardContent>
|
|
112
|
+
<p>This card uses size="default".</p>
|
|
113
|
+
</CardContent>
|
|
114
|
+
</Card>
|
|
115
|
+
|
|
116
|
+
<Card size="lg" className="w-[350px]">
|
|
117
|
+
<CardHeader>
|
|
118
|
+
<CardTitle>Size: Large</CardTitle>
|
|
119
|
+
<CardDescription>Spacious padding (lg)</CardDescription>
|
|
120
|
+
</CardHeader>
|
|
121
|
+
<CardContent>
|
|
122
|
+
<p>This card uses size="lg".</p>
|
|
123
|
+
</CardContent>
|
|
124
|
+
</Card>
|
|
125
|
+
|
|
126
|
+
<Card size="none" className="w-[350px]">
|
|
127
|
+
<CardHeader className="border-d-border border-b p-4">
|
|
128
|
+
<CardTitle>Size: None</CardTitle>
|
|
129
|
+
<CardDescription>No default padding (none)</CardDescription>
|
|
130
|
+
</CardHeader>
|
|
131
|
+
<CardContent className="p-4">
|
|
132
|
+
<p>This card uses size="none" with custom padding.</p>
|
|
133
|
+
</CardContent>
|
|
134
|
+
</Card>
|
|
135
|
+
</div>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Notes
|
|
143
|
+
|
|
144
|
+
- **Composability**: Use only the subcomponents you need.
|
|
145
|
+
- **Borders**: Add `border-b`/`border-t` to header/footer for separation.
|
|
146
|
+
- **Action area**: `CardAction` aligns content to the top-right in the header.
|
|
147
|
+
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Carousel
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
A flexible, accessible carousel built on Embla. Supports horizontal/vertical orientation, previous/next controls, keyboard navigation, and responsive layouts.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
|
|
11
|
+
### Carousel (Root)
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
| -------------- | -------------------------------------- | -------------- | -------------------------------------------------- |
|
|
15
|
+
| `orientation` | `"horizontal" | "vertical"` | `"horizontal"` | Scroll axis for the carousel. |
|
|
16
|
+
| `opts` | `EmblaOptionsType` | `{}` | Embla options (e.g., loop). |
|
|
17
|
+
| `plugins` | `EmblaPluginType[]` | `[]` | Embla plugins. |
|
|
18
|
+
| `setApi` | `(api: CarouselApi) => void` | `undefined` | Receives the Embla API instance. |
|
|
19
|
+
| `className` | `string` | `""` | Additional classes for the container. |
|
|
20
|
+
| `children` | `React.ReactNode` | **required** | Compose with subcomponents below. |
|
|
21
|
+
|
|
22
|
+
### Subcomponents
|
|
23
|
+
|
|
24
|
+
- `CarouselContent`: Scroll container (wraps slides).
|
|
25
|
+
- `CarouselItem`: A single slide.
|
|
26
|
+
- `CarouselPrevious`: Previous button (disabled when not scrollable).
|
|
27
|
+
- `CarouselNext`: Next button (disabled when not scrollable).
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Behavior
|
|
32
|
+
|
|
33
|
+
- **Keyboard**: Left/Right arrows move slides (when horizontal).
|
|
34
|
+
- **Controls**: Prev/Next buttons enable/disable based on scroll availability.
|
|
35
|
+
- **Orientation**: Vertical orientation rotates controls appropriately.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Examples
|
|
40
|
+
|
|
41
|
+
### Basic
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext } from "laif-ds";
|
|
45
|
+
import { Card, CardContent } from "laif-ds";
|
|
46
|
+
|
|
47
|
+
export function BasicCarousel() {
|
|
48
|
+
return (
|
|
49
|
+
<Carousel className="w-full max-w-xs">
|
|
50
|
+
<CarouselContent>
|
|
51
|
+
{Array.from({ length: 5 }).map((_, index) => (
|
|
52
|
+
<CarouselItem key={index}>
|
|
53
|
+
<div className="p-1">
|
|
54
|
+
<Card>
|
|
55
|
+
<CardContent className="flex aspect-square items-center justify-center p-6">
|
|
56
|
+
<span className="text-xl font-semibold">{index + 1}</span>
|
|
57
|
+
</CardContent>
|
|
58
|
+
</Card>
|
|
59
|
+
</div>
|
|
60
|
+
</CarouselItem>
|
|
61
|
+
))}
|
|
62
|
+
</CarouselContent>
|
|
63
|
+
<CarouselPrevious />
|
|
64
|
+
<CarouselNext />
|
|
65
|
+
</Carousel>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Multiple Items per Row
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
import { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext } from "laif-ds";
|
|
74
|
+
import { Card, CardContent } from "laif-ds";
|
|
75
|
+
|
|
76
|
+
export function MultipleItems() {
|
|
77
|
+
return (
|
|
78
|
+
<Carousel className="w-full max-w-md">
|
|
79
|
+
<CarouselContent className="-ml-1">
|
|
80
|
+
{Array.from({ length: 10 }).map((_, index) => (
|
|
81
|
+
<CarouselItem key={index} className="pl-1 md:basis-1/2 lg:basis-1/3">
|
|
82
|
+
<div className="p-1">
|
|
83
|
+
<Card>
|
|
84
|
+
<CardContent className="flex aspect-square items-center justify-center p-6">
|
|
85
|
+
<span className="text-lg font-semibold">{index + 1}</span>
|
|
86
|
+
</CardContent>
|
|
87
|
+
</Card>
|
|
88
|
+
</div>
|
|
89
|
+
</CarouselItem>
|
|
90
|
+
))}
|
|
91
|
+
</CarouselContent>
|
|
92
|
+
<CarouselPrevious />
|
|
93
|
+
<CarouselNext />
|
|
94
|
+
</Carousel>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### With API (loop)
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
import { useState } from "react";
|
|
103
|
+
import type { CarouselApi } from "laif-ds";
|
|
104
|
+
import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from "laif-ds";
|
|
105
|
+
|
|
106
|
+
export function CarouselWithApi() {
|
|
107
|
+
const [api, setApi] = useState<CarouselApi | null>(null);
|
|
108
|
+
return (
|
|
109
|
+
<Carousel className="w-full max-w-xs" setApi={setApi} opts={{ loop: true }}>
|
|
110
|
+
<CarouselContent>
|
|
111
|
+
{[1, 2, 3, 4, 5].map((n) => (
|
|
112
|
+
<CarouselItem key={n}><div className="p-6">Slide {n}</div></CarouselItem>
|
|
113
|
+
))}
|
|
114
|
+
</CarouselContent>
|
|
115
|
+
<CarouselPrevious />
|
|
116
|
+
<CarouselNext />
|
|
117
|
+
</Carousel>
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Notes
|
|
125
|
+
|
|
126
|
+
- **Focus**: The root handles arrow keys via `onKeyDownCapture`.
|
|
127
|
+
- **Responsiveness**: Use `basis-*` utilities on `CarouselItem` for multi-column layouts.
|
|
128
|
+
- **Plugins**: Pass Embla plugins via `plugins` prop when needed.
|
|
129
|
+
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Chart
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Design-system primitives around Recharts providing a container with theme-aware color variables, tooltip and legend content helpers.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Exports
|
|
10
|
+
|
|
11
|
+
- `ChartContainer` — wraps `ResponsiveContainer` and provides CSS vars per series
|
|
12
|
+
- `ChartTooltip`, `ChartTooltipContent` — tooltip with indicator and label formatting
|
|
13
|
+
- `ChartLegend`, `ChartLegendContent` — legend component with icon/color support
|
|
14
|
+
- `ChartStyle` — internal style tag used by `ChartContainer`
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Types
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
export type ChartConfig = {
|
|
22
|
+
[k: string]: {
|
|
23
|
+
label?: React.ReactNode;
|
|
24
|
+
icon?: React.ComponentType;
|
|
25
|
+
} & ({ color?: string } | { theme: { light: string; dark: string } });
|
|
26
|
+
};
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Example
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
import {
|
|
35
|
+
ChartContainer,
|
|
36
|
+
ChartTooltip,
|
|
37
|
+
ChartTooltipContent,
|
|
38
|
+
ChartLegend,
|
|
39
|
+
ChartLegendContent,
|
|
40
|
+
} from "laif-ds";
|
|
41
|
+
import {
|
|
42
|
+
LineChart,
|
|
43
|
+
Line,
|
|
44
|
+
XAxis,
|
|
45
|
+
YAxis,
|
|
46
|
+
CartesianGrid,
|
|
47
|
+
Tooltip,
|
|
48
|
+
Legend,
|
|
49
|
+
} from "recharts";
|
|
50
|
+
|
|
51
|
+
const data = [
|
|
52
|
+
{ month: "Jan", users: 400 },
|
|
53
|
+
{ month: "Feb", users: 800 },
|
|
54
|
+
{ month: "Mar", users: 650 },
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
const config = {
|
|
58
|
+
users: { label: "Users", theme: { light: "#0ea5e9", dark: "#7dd3fc" } },
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export function UsersChart() {
|
|
62
|
+
return (
|
|
63
|
+
<ChartContainer config={config} className="w-full">
|
|
64
|
+
<LineChart data={data} margin={{ left: 12, right: 12 }}>
|
|
65
|
+
<CartesianGrid strokeDasharray="3 3" />
|
|
66
|
+
<XAxis dataKey="month" />
|
|
67
|
+
<YAxis />
|
|
68
|
+
<Tooltip content={<ChartTooltipContent />} />
|
|
69
|
+
<Legend content={<ChartLegendContent />} />
|
|
70
|
+
<Line type="monotone" dataKey="users" stroke="var(--color-users)" />
|
|
71
|
+
</LineChart>
|
|
72
|
+
</ChartContainer>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
```
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Chat
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Complete chat interface: message list with markdown rendering, auto-scroll and typing indicator; composer with text, attachments, and voice; optional suggestions for empty state; message actions (copy, rate, save) and inline edit of assistant messages.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
|
|
11
|
+
| Prop | Type | Default | Description |
|
|
12
|
+
| ------------------ | ---------------------------------------------- | ----------- | ----------- |
|
|
13
|
+
| `messages` | `Message[]` | **required**| Messages to render. See `ChatMessage` for shape. |
|
|
14
|
+
| `input` | `string` | **required**| Current input value. |
|
|
15
|
+
| `handleSubmit` | `(event?, opts?) => void` | **required**| Called on form submit. Supports `{ experimental_attachments?: FileList }`. |
|
|
16
|
+
| `handleInputChange`| `React.ChangeEventHandler<HTMLTextAreaElement>`| **required**| Input change handler. |
|
|
17
|
+
| `isGenerating` | `boolean` | `false` | Whether assistant is generating. Enables interrupt UI. |
|
|
18
|
+
| `stop` | `() => void` | `undefined` | Stop generation callback. |
|
|
19
|
+
| `allowAttachments` | `boolean` | `false` | Enable file attachments UI. |
|
|
20
|
+
| `transcribeAudio` | `(blob: Blob) => Promise<string>` | `undefined` | Speech-to-text function for voice input. |
|
|
21
|
+
| `onEdit` | `(messageId: string, newContent: string) => void`| `undefined`| Enable inline edit on assistant messages. |
|
|
22
|
+
| `onMessageSave` | `(messageId: string, content: string) => void` | `undefined` | Enable save action on assistant messages. |
|
|
23
|
+
| `onRateResponse` | `(messageId: string, rating: "thumbs-up" | "thumbs-down") => void` | `undefined` | Enable rating actions. |
|
|
24
|
+
| `append` | `(message: { role: "user"; content: string }) => void` | `undefined` | Show prompt suggestions and handle clicks. |
|
|
25
|
+
| `suggestions` | `string[]` | `undefined` | Suggestions displayed when empty. Requires `append`. |
|
|
26
|
+
| `className` | `string` | `undefined` | Wrapper classes. |
|
|
27
|
+
| `welcomeTitle` | `string` | `"Da dove iniziamo?"` | Title shown in empty state. |
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Behavior
|
|
32
|
+
|
|
33
|
+
- **Auto-scroll**: Scrolls to latest messages unless user scrolls up (then shows "scroll to bottom").
|
|
34
|
+
- **Composer**: `MessageInput` supports Enter-to-send, attachments, and voice input with transcription.
|
|
35
|
+
- **Actions**: Copy, save, thumbs up/down per assistant message.
|
|
36
|
+
- **Edit**: Inline edit of assistant messages with Enter to save / Esc to cancel.
|
|
37
|
+
- **Suggestions**: When `messages` is empty and `suggestions` provided, renders clickable suggestions via `append`.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Examples
|
|
42
|
+
|
|
43
|
+
### Default
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
import * as React from "react";
|
|
47
|
+
import { Chat } from "laif-ds";
|
|
48
|
+
import type { Message } from "laif-ds";
|
|
49
|
+
|
|
50
|
+
export function BasicChat() {
|
|
51
|
+
const [messages, setMessages] = React.useState<Message[]>([
|
|
52
|
+
{ id: "1", role: "user", content: "Hello!", createdAt: new Date() },
|
|
53
|
+
{ id: "2", role: "assistant", content: "How can I help?", createdAt: new Date() },
|
|
54
|
+
]);
|
|
55
|
+
const [input, setInput] = React.useState("");
|
|
56
|
+
|
|
57
|
+
const handleSubmit = () => {
|
|
58
|
+
if (!input.trim()) return;
|
|
59
|
+
setMessages((prev) => [...prev, { id: Date.now().toString(), role: "user", content: input, createdAt: new Date() }]);
|
|
60
|
+
setInput("");
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<div className="h-[500px] w-full max-w-3xl">
|
|
65
|
+
<Chat
|
|
66
|
+
messages={messages}
|
|
67
|
+
input={input}
|
|
68
|
+
handleInputChange={(e) => setInput(e.target.value)}
|
|
69
|
+
handleSubmit={handleSubmit}
|
|
70
|
+
isGenerating={false}
|
|
71
|
+
/>
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### With Attachments and Actions
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
import * as React from "react";
|
|
81
|
+
import { Chat } from "laif-ds";
|
|
82
|
+
|
|
83
|
+
export function FullChat() {
|
|
84
|
+
const [input, setInput] = React.useState("");
|
|
85
|
+
return (
|
|
86
|
+
<div className="h-[600px] w-full">
|
|
87
|
+
<Chat
|
|
88
|
+
messages={[]}
|
|
89
|
+
input={input}
|
|
90
|
+
handleInputChange={(e) => setInput(e.target.value)}
|
|
91
|
+
handleSubmit={() => {}}
|
|
92
|
+
isGenerating={false}
|
|
93
|
+
allowAttachments
|
|
94
|
+
onMessageSave={(id, content) => console.log("save", id, content)}
|
|
95
|
+
onRateResponse={(id, rating) => console.log("rate", id, rating)}
|
|
96
|
+
/>
|
|
97
|
+
</div>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Notes
|
|
105
|
+
|
|
106
|
+
- **Types**: See `Message` in `chat-message.tsx` for full shape (supports tool invocations and parts).
|
|
107
|
+
- **Interrupt**: When `isGenerating` is true and `stop` provided, `Enter` prompts to stop then submit.
|
|
108
|
+
- **Composition**: Chat uses `MessageList`, `MessageInput`, and utilities like `CopyButton` and `PromptSuggestions`.
|
|
109
|
+
|