laif-ds 0.2.44 → 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/index4.js +5 -5
  2. package/dist/_virtual/index5.js +5 -5
  3. package/dist/_virtual/index6.js +2 -2
  4. package/dist/_virtual/index7.js +2 -2
  5. package/dist/agent-docs/components/Accordion.md +157 -0
  6. package/dist/agent-docs/components/Alert.md +95 -0
  7. package/dist/agent-docs/components/AlertDialog.md +126 -0
  8. package/dist/agent-docs/components/AppEditor.md +90 -0
  9. package/dist/agent-docs/components/AppForm.md +242 -0
  10. package/dist/agent-docs/components/AppMultipleSelectDropdown.md +38 -0
  11. package/dist/agent-docs/components/AppRadioGroup.md +223 -0
  12. package/dist/agent-docs/components/AppSelect.md +427 -0
  13. package/dist/agent-docs/components/AppSidebar.md +122 -0
  14. package/dist/agent-docs/components/AppStepper.md +77 -0
  15. package/dist/agent-docs/components/AspectRatio.md +87 -0
  16. package/dist/agent-docs/components/AsyncSelect.md +127 -0
  17. package/dist/agent-docs/components/AudioVisualizer.md +41 -0
  18. package/dist/agent-docs/components/Avatar.md +113 -0
  19. package/dist/agent-docs/components/Badge.md +118 -0
  20. package/dist/agent-docs/components/Breadcrumb.md +78 -0
  21. package/dist/agent-docs/components/Button.md +129 -0
  22. package/dist/agent-docs/components/Calendar.md +222 -0
  23. package/dist/agent-docs/components/Card.md +147 -0
  24. package/dist/agent-docs/components/Carousel.md +129 -0
  25. package/dist/agent-docs/components/Chart.md +75 -0
  26. package/dist/agent-docs/components/Chat.md +109 -0
  27. package/dist/agent-docs/components/ChatMessage.md +61 -0
  28. package/dist/agent-docs/components/Checkbox.md +135 -0
  29. package/dist/agent-docs/components/CircularProgress.md +49 -0
  30. package/dist/agent-docs/components/CodeHighlighter.md +31 -0
  31. package/dist/agent-docs/components/Collapsible.md +95 -0
  32. package/dist/agent-docs/components/Command.md +142 -0
  33. package/dist/agent-docs/components/Confirmer.md +175 -0
  34. package/dist/agent-docs/components/ContextMenu.md +191 -0
  35. package/dist/agent-docs/components/CopyButton.md +26 -0
  36. package/dist/agent-docs/components/DataCrossTable.md +94 -0
  37. package/dist/agent-docs/components/DataTable.md +254 -0
  38. package/dist/agent-docs/components/DatePicker.md +109 -0
  39. package/dist/agent-docs/components/Dialog.md +125 -0
  40. package/dist/agent-docs/components/Drawer.md +127 -0
  41. package/dist/agent-docs/components/DropdownMenu.md +57 -0
  42. package/dist/agent-docs/components/FilePreview.md +99 -0
  43. package/dist/agent-docs/components/FilePreviewer.md +139 -0
  44. package/dist/agent-docs/components/FileUploader.md +129 -0
  45. package/dist/agent-docs/components/Form.md +62 -0
  46. package/dist/agent-docs/components/FormComposer.md +137 -0
  47. package/dist/agent-docs/components/GanttChart.md +122 -0
  48. package/dist/agent-docs/components/HoverCard.md +37 -0
  49. package/dist/agent-docs/components/Icon.md +99 -0
  50. package/dist/agent-docs/components/Input.md +138 -0
  51. package/dist/agent-docs/components/InputOtp.md +40 -0
  52. package/dist/agent-docs/components/InputSelector.md +97 -0
  53. package/dist/agent-docs/components/InterruptPrompt.md +32 -0
  54. package/dist/agent-docs/components/Label.md +28 -0
  55. package/dist/agent-docs/components/MarkdownRenderer.md +36 -0
  56. package/dist/agent-docs/components/Menubar.md +164 -0
  57. package/dist/agent-docs/components/MessageInput.md +131 -0
  58. package/dist/agent-docs/components/MessageList.md +96 -0
  59. package/dist/agent-docs/components/MultipleSelector.md +146 -0
  60. package/dist/agent-docs/components/NavigationMenu.md +51 -0
  61. package/dist/agent-docs/components/Pagination.md +55 -0
  62. package/dist/agent-docs/components/Popover.md +103 -0
  63. package/dist/agent-docs/components/Progress.md +30 -0
  64. package/dist/agent-docs/components/PromptSuggestions.md +33 -0
  65. package/dist/agent-docs/components/RadioGroup.md +90 -0
  66. package/dist/agent-docs/components/Resizable.md +35 -0
  67. package/dist/agent-docs/components/ResizePrompt.md +13 -0
  68. package/dist/agent-docs/components/ScrollArea.md +49 -0
  69. package/dist/agent-docs/components/SecurePdfViewer.md +38 -0
  70. package/dist/agent-docs/components/Select.md +132 -0
  71. package/dist/agent-docs/components/Separator.md +32 -0
  72. package/dist/agent-docs/components/Sheet.md +40 -0
  73. package/dist/agent-docs/components/ShikiHighlighter.md +31 -0
  74. package/dist/agent-docs/components/Sidebar.md +85 -0
  75. package/dist/agent-docs/components/Skeleton.md +29 -0
  76. package/dist/agent-docs/components/Slider.md +58 -0
  77. package/dist/agent-docs/components/Sonner.md +21 -0
  78. package/dist/agent-docs/components/Spinner.md +139 -0
  79. package/dist/agent-docs/components/Stepper.md +67 -0
  80. package/dist/agent-docs/components/Switch.md +42 -0
  81. package/dist/agent-docs/components/Table.md +63 -0
  82. package/dist/agent-docs/components/TableSkeleton.md +46 -0
  83. package/dist/agent-docs/components/Tabs.md +86 -0
  84. package/dist/agent-docs/components/TextArea.md +52 -0
  85. package/dist/agent-docs/components/ThemeSwitcher.md +69 -0
  86. package/dist/agent-docs/components/Toaster.md +23 -0
  87. package/dist/agent-docs/components/Toggle.md +31 -0
  88. package/dist/agent-docs/components/ToggleGroup.md +30 -0
  89. package/dist/agent-docs/components/Tooltip.md +91 -0
  90. package/dist/agent-docs/components/TypingIndicator.md +21 -0
  91. package/dist/agent-docs/components/Typo.md +65 -0
  92. package/dist/agent-docs/components/WeeklyCalendar.md +64 -0
  93. package/dist/agent-docs/components-list.md +144 -0
  94. package/dist/node_modules/eventemitter3/index2.js +1 -1
  95. package/dist/node_modules/hast-util-to-jsx-runtime/lib/index.js +1 -1
  96. package/dist/node_modules/style-to-object/cjs/index.js +1 -1
  97. package/dist/node_modules/unified/lib/index.js +1 -1
  98. package/package.json +3 -2
@@ -0,0 +1,97 @@
1
+ # InputSelector
2
+
3
+ ## Overview
4
+
5
+ Compact numeric selector with increment/decrement buttons, value bounds, and subtle animations. Useful for choosing small integer quantities (e.g., seats, guests).
6
+
7
+ ---
8
+
9
+ ## Props
10
+
11
+ | Prop | Type | Default | Description |
12
+ | ------------------ | -------------------- | --------- | -------------------------------------------- |
13
+ | `value` | `number` | `1` | Current numeric value. |
14
+ | `onChange` | `(value: number) => void` | `undefined` | Called with the new value. |
15
+ | `min` | `number` | `1` | Minimum allowed value. |
16
+ | `max` | `number` | `4` | Maximum allowed value. |
17
+ | `className` | `string` | `""` | Wrapper classes. |
18
+ | `buttonClassName` | `string` | `""` | Classes for +/- buttons. |
19
+ | `counterClassName` | `string` | `""` | Classes for the numeric counter. |
20
+
21
+ ---
22
+
23
+ ## Behavior
24
+
25
+ - **Controlled**: `value` is controlled; emits `onChange(newValue)` on clicks within bounds.
26
+ - **Bounds**: At min or max, the component vibrates (subtle shake animation) instead of changing value.
27
+ - **A11y**: Buttons are real `<button>` elements with clear `+`/`-` labels.
28
+
29
+ ---
30
+
31
+ ## Examples
32
+
33
+ ### Basic
34
+
35
+ ```tsx
36
+ import { useState } from "react";
37
+ import { InputSelector } from "laif-ds";
38
+
39
+ export function BasicSelector() {
40
+ const [value, setValue] = useState(2);
41
+
42
+ return (
43
+ <InputSelector value={value} onChange={setValue} min={1} max={4} />
44
+ );
45
+ }
46
+ ```
47
+
48
+ ### Controlled
49
+
50
+ ```tsx
51
+ import { useState } from "react";
52
+ import { InputSelector } from "laif-ds";
53
+
54
+ export function ControlledSelector() {
55
+ const [value, setValue] = useState(2);
56
+
57
+ return (
58
+ <div className="flex flex-col items-center gap-2">
59
+ <InputSelector value={value} onChange={setValue} min={1} max={6} />
60
+ <div className="text-d-secondary-foreground text-sm">
61
+ Current value: {value}
62
+ </div>
63
+ </div>
64
+ );
65
+ }
66
+ ```
67
+
68
+ ### Custom Styling
69
+
70
+ ```tsx
71
+ import { useState } from "react";
72
+ import { InputSelector } from "laif-ds";
73
+
74
+ export function CustomStyledSelector() {
75
+ const [value, setValue] = useState(2);
76
+
77
+ return (
78
+ <InputSelector
79
+ value={value}
80
+ onChange={setValue}
81
+ min={1}
82
+ max={4}
83
+ className="bg-d-secondary/10 p-6 rounded-xl"
84
+ buttonClassName="bg-d-primary text-d-primary-foreground hover:bg-d-primary/90 border-0"
85
+ counterClassName="text-d-primary font-bold"
86
+ />
87
+ );
88
+ }
89
+ ```
90
+
91
+ ---
92
+
93
+ ## Notes
94
+
95
+ - **Bounds UX**: The slight vibration on bound hit provides feedback without changing the value.
96
+ - **Styling**: Prefer design tokens (`bg-d-*`, `text-d-*`) over raw colors.
97
+
@@ -0,0 +1,32 @@
1
+ # InterruptPrompt
2
+
3
+ ## Overview
4
+
5
+ Animated prompt that appears to allow interrupting an action (e.g., hitting Enter twice). Built with Framer Motion.
6
+
7
+ ---
8
+
9
+ ## Props
10
+
11
+ | Prop | Type | Description |
12
+ | --- | --- | --- |
13
+ | `isOpen` | `boolean` | Whether the prompt is visible |
14
+ | `close` | `() => void` | Close handler |
15
+
16
+ ---
17
+
18
+ ## Example
19
+
20
+ ```tsx
21
+ import { useState } from "react";
22
+ import { InterruptPrompt } from "laif-ds";
23
+
24
+ export function Demo() {
25
+ const [open, setOpen] = useState(true);
26
+ return (
27
+ <div className="relative h-32">
28
+ <InterruptPrompt isOpen={open} close={() => setOpen(false)} />
29
+ </div>
30
+ );
31
+ }
32
+ ```
@@ -0,0 +1,28 @@
1
+ # Label
2
+
3
+ ## Overview
4
+
5
+ Accessible label component built on Radix Label with default spacing and disabled styles.
6
+
7
+ ---
8
+
9
+ ## Props
10
+
11
+ Extends `@radix-ui/react-label` Root props.
12
+
13
+ ---
14
+
15
+ ## Example
16
+
17
+ ```tsx
18
+ import { Label, Input } from "laif-ds";
19
+
20
+ export function LabeledInput() {
21
+ return (
22
+ <div className="grid gap-2">
23
+ <Label htmlFor="email">Email</Label>
24
+ <Input id="email" type="email" placeholder="you@example.com" />
25
+ </div>
26
+ );
27
+ }
28
+ ```
@@ -0,0 +1,36 @@
1
+ # MarkdownRenderer
2
+
3
+ ## Overview
4
+
5
+ Renders Markdown with GitHub-flavored Markdown (GFM) and async syntax highlighting using Shiki. Includes Copy button for code blocks.
6
+
7
+ ---
8
+
9
+ ## Usage
10
+
11
+ ```tsx
12
+ import { MarkdownRenderer } from "laif-ds";
13
+
14
+ const content = `
15
+ # Hello
16
+
17
+ Some ` + "`code`" + ` and a list:
18
+
19
+ - Item A
20
+ - Item B
21
+ `;
22
+
23
+ export function Doc() {
24
+ return <MarkdownRenderer>{content}</MarkdownRenderer>;
25
+ }
26
+ ```
27
+
28
+ - Supports headings, lists, tables, links, blockquotes, and inline code
29
+ - Code blocks highlighted when a language class is provided (e.g., `language-ts`)
30
+
31
+ ---
32
+
33
+ ## Notes
34
+
35
+ - Uses `react-markdown` + `remark-gfm`
36
+ - Code highlighting falls back to plain `<pre>` if language is unsupported
@@ -0,0 +1,164 @@
1
+ # Menubar
2
+
3
+ ## Overview
4
+
5
+ Top-level horizontal application menu built on Radix Menubar. Supports nested submenus, checkbox and radio items, separators, and keyboard navigation.
6
+
7
+ ---
8
+
9
+ ## Subcomponents & Props
10
+
11
+ - **Menubar**: Root container. Extends `@radix-ui/react-menubar` Root props.
12
+ - **MenubarMenu**: Wraps a single menu.
13
+ - **MenubarTrigger**: Button that opens its menu.
14
+ - **MenubarContent**: The floating panel with items.
15
+ - `align`: `start | center | end` (default `start`)
16
+ - `alignOffset`: `number` (default `-4`)
17
+ - `sideOffset`: `number` (default `8`)
18
+ - **MenubarItem**: Clickable action item.
19
+ - `variant`: `"default" | "destructive"` (default `"default"`)
20
+ - `inset`: `boolean` (indent the item)
21
+ - **MenubarCheckboxItem**: Checkbox item.
22
+ - `checked`: `boolean`
23
+ - **MenubarRadioGroup**: Groups radio items.
24
+ - `value`, `onValueChange`: controlled selection
25
+ - **MenubarRadioItem**: Radio item in a group.
26
+ - **MenubarLabel**: Non-interactive label.
27
+ - **MenubarSeparator**: Horizontal separator.
28
+ - **MenubarShortcut**: Right-aligned keyboard shortcut hint.
29
+ - **MenubarSub / MenubarSubTrigger / MenubarSubContent**: Submenu primitives.
30
+
31
+ ---
32
+
33
+ ## Behavior
34
+
35
+ - **Keyboard navigation**: Arrow keys to move between triggers and items, Enter/Space to select.
36
+ - **States**: Triggers reflect open/focus states. `variant="destructive"` styles an item for dangerous actions.
37
+ - **Accessibility**: Proper roles and aria attributes via Radix primitives.
38
+
39
+ ---
40
+
41
+ ## Examples
42
+
43
+ ### Basic
44
+
45
+ ```tsx
46
+ import {
47
+ Menubar,
48
+ MenubarMenu,
49
+ MenubarTrigger,
50
+ MenubarContent,
51
+ MenubarItem,
52
+ MenubarSeparator,
53
+ MenubarSub,
54
+ MenubarSubTrigger,
55
+ MenubarSubContent,
56
+ MenubarShortcut,
57
+ } from "laif-ds";
58
+
59
+ export function BasicMenubar() {
60
+ return (
61
+ <Menubar>
62
+ <MenubarMenu>
63
+ <MenubarTrigger>File</MenubarTrigger>
64
+ <MenubarContent>
65
+ <MenubarItem>
66
+ New Tab <MenubarShortcut>⌘T</MenubarShortcut>
67
+ </MenubarItem>
68
+ <MenubarItem>
69
+ New Window <MenubarShortcut>⌘N</MenubarShortcut>
70
+ </MenubarItem>
71
+ <MenubarSeparator />
72
+ <MenubarSub>
73
+ <MenubarSubTrigger>Share</MenubarSubTrigger>
74
+ <MenubarSubContent>
75
+ <MenubarItem>Email Link</MenubarItem>
76
+ <MenubarItem>Messages</MenubarItem>
77
+ <MenubarItem>Notes</MenubarItem>
78
+ </MenubarSubContent>
79
+ </MenubarSub>
80
+ <MenubarSeparator />
81
+ <MenubarItem>
82
+ Print... <MenubarShortcut>⌘P</MenubarShortcut>
83
+ </MenubarItem>
84
+ </MenubarContent>
85
+ </MenubarMenu>
86
+ </Menubar>
87
+ );
88
+ }
89
+ ```
90
+
91
+ ### With Groups and Radios
92
+
93
+ ```tsx
94
+ import {
95
+ Menubar,
96
+ MenubarMenu,
97
+ MenubarTrigger,
98
+ MenubarContent,
99
+ MenubarLabel,
100
+ MenubarRadioGroup,
101
+ MenubarRadioItem,
102
+ MenubarSeparator,
103
+ } from "laif-ds";
104
+
105
+ export function MenubarWithGroups() {
106
+ return (
107
+ <Menubar>
108
+ <MenubarMenu>
109
+ <MenubarTrigger>Options</MenubarTrigger>
110
+ <MenubarContent>
111
+ <MenubarLabel>Theme</MenubarLabel>
112
+ <MenubarSeparator />
113
+ <MenubarRadioGroup value="light">
114
+ <MenubarRadioItem value="light">Light</MenubarRadioItem>
115
+ <MenubarRadioItem value="dark">Dark</MenubarRadioItem>
116
+ <MenubarRadioItem value="system">System</MenubarRadioItem>
117
+ </MenubarRadioGroup>
118
+ </MenubarContent>
119
+ </MenubarMenu>
120
+ </Menubar>
121
+ );
122
+ }
123
+ ```
124
+
125
+ ### Destructive Item
126
+
127
+ ```tsx
128
+ import {
129
+ Menubar,
130
+ MenubarMenu,
131
+ MenubarTrigger,
132
+ MenubarContent,
133
+ MenubarItem,
134
+ MenubarSeparator,
135
+ MenubarShortcut,
136
+ } from "laif-ds";
137
+
138
+ export function DestructiveExample() {
139
+ return (
140
+ <Menubar>
141
+ <MenubarMenu>
142
+ <MenubarTrigger>Actions</MenubarTrigger>
143
+ <MenubarContent>
144
+ <MenubarItem>Copy <MenubarShortcut>⌘C</MenubarShortcut></MenubarItem>
145
+ <MenubarItem>Paste <MenubarShortcut>⌘V</MenubarShortcut></MenubarItem>
146
+ <MenubarSeparator />
147
+ <MenubarItem variant="destructive">
148
+ Delete <MenubarShortcut>⌘⌫</MenubarShortcut>
149
+ </MenubarItem>
150
+ </MenubarContent>
151
+ </MenubarMenu>
152
+ </Menubar>
153
+ );
154
+ }
155
+ ```
156
+
157
+ ---
158
+
159
+ ## Notes
160
+
161
+ - **Composition**: Combine subcomponents to build complex menus.
162
+ - **Shortcuts**: Use `MenubarShortcut` for right-aligned hints.
163
+ - **A11y**: Labels and roles are handled by Radix primitives and DS styling.
164
+
@@ -0,0 +1,131 @@
1
+ # MessageInput
2
+
3
+ ## Overview
4
+
5
+ Chat composer with autosizing textarea, optional file attachments, voice input (record/transcribe), and intelligent Enter-to-send behavior with interruption prompts.
6
+
7
+ ---
8
+
9
+ ## Props
10
+
11
+ Extends native `<textarea>` props.
12
+
13
+ | Prop | Type | Default | Description |
14
+ | ------------------ | ---------------------------------------------- | ---------- | ----------- |
15
+ | `value` | `string` | **required** | Controlled text value. |
16
+ | `isGenerating` | `boolean` | `false` | If true, shows stop button and may display interrupt prompt. |
17
+ | `submitOnEnter` | `boolean` | `true` | Press Enter to submit (Shift+Enter for newline). |
18
+ | `stop` | `() => void` | `undefined`| Stop generation handler (used with `isGenerating`). |
19
+ | `enableInterrupt` | `boolean` | `true` | If true, pressing Enter while generating shows confirm to interrupt. |
20
+ | `transcribeAudio` | `(blob: Blob) => Promise<string>` | `undefined`| Optional audio-to-text function. |
21
+ | `allowAttachments` | `boolean` | `false` | Enable file attachments UI. |
22
+ | `files` | `File[] | null` | `null` | Current attached files (when `allowAttachments`). |
23
+ | `setFiles` | `React.Dispatch<React.SetStateAction<File[] | null>>` | `undefined`| Setter for attachments. |
24
+
25
+ ---
26
+
27
+ ## Behavior
28
+
29
+ - **Enter to submit**: If `submitOnEnter` and not `shiftKey`, calls `form.requestSubmit()`.
30
+ - **Interrupt flow**: If `isGenerating` and `stop` and `enableInterrupt`, pressing Enter shows a prompt to confirm stopping the generation and sending the new message.
31
+ - **Autosize**: Textarea grows up to a max height, then scrolls.
32
+ - **Attachments**: Drag & drop, paste files; long pasted text (> 500 chars) becomes a text file. Uses `FilePreview` to show chips.
33
+ - **Voice input**: If supported, toggles microphone recording; shows visualizer while recording and a "transcribing" overlay after.
34
+ - **Actions**: Right-aligned action buttons: attach, mic, send/stop.
35
+
36
+ ---
37
+
38
+ ## Examples
39
+
40
+ ### Basic
41
+
42
+ ```tsx
43
+ import * as React from "react";
44
+ import { MessageInput } from "laif-ds";
45
+
46
+ export function BasicComposer() {
47
+ const [value, setValue] = React.useState("");
48
+ const onSubmit = (e: React.FormEvent) => {
49
+ e.preventDefault();
50
+ console.log("Messaggio inviato:", value);
51
+ setValue("");
52
+ };
53
+ return (
54
+ <form onSubmit={onSubmit} className="w-full max-w-2xl">
55
+ <MessageInput value={value} onChange={(e) => setValue(e.target.value)} isGenerating={false} />
56
+ </form>
57
+ );
58
+ }
59
+ ```
60
+
61
+ ### With Attachments
62
+
63
+ ```tsx
64
+ import * as React from "react";
65
+ import { MessageInput } from "laif-ds";
66
+
67
+ export function WithAttachments() {
68
+ const [value, setValue] = React.useState("");
69
+ const [files, setFiles] = React.useState<File[] | null>(null);
70
+ const onSubmit = (e: React.FormEvent) => {
71
+ e.preventDefault();
72
+ console.log("Messaggio inviato:", value, files);
73
+ setValue("");
74
+ setFiles(null);
75
+ };
76
+ return (
77
+ <form onSubmit={onSubmit} className="w-full max-w-2xl">
78
+ <MessageInput
79
+ value={value}
80
+ onChange={(e) => setValue(e.target.value)}
81
+ isGenerating={false}
82
+ allowAttachments
83
+ files={files}
84
+ setFiles={setFiles}
85
+ placeholder="Scrivi un messaggio o trascina file qui..."
86
+ />
87
+ </form>
88
+ );
89
+ }
90
+ ```
91
+
92
+ ### Generating + Interrupt
93
+
94
+ ```tsx
95
+ import * as React from "react";
96
+ import { MessageInput } from "laif-ds";
97
+
98
+ export function Generating() {
99
+ const [value, setValue] = React.useState("");
100
+ const [isGenerating, setIsGenerating] = React.useState(true);
101
+ const stop = () => setIsGenerating(false);
102
+ const onSubmit = (e: React.FormEvent) => {
103
+ e.preventDefault();
104
+ if (isGenerating) return;
105
+ console.log("Messaggio inviato:", value);
106
+ setValue("");
107
+ setIsGenerating(true);
108
+ setTimeout(() => setIsGenerating(false), 3000);
109
+ };
110
+ return (
111
+ <form onSubmit={onSubmit} className="w-full max-w-2xl">
112
+ <MessageInput
113
+ value={value}
114
+ onChange={(e) => setValue(e.target.value)}
115
+ isGenerating={isGenerating}
116
+ stop={stop}
117
+ placeholder="L'AI sta generando una risposta..."
118
+ />
119
+ </form>
120
+ );
121
+ }
122
+ ```
123
+
124
+ ---
125
+
126
+ ## Notes
127
+
128
+ - **File preview**: Uses `FilePreview` for attachment chips.
129
+ - **Paste handling**: Long text paste becomes a `.txt` file when attachments are enabled.
130
+ - **A11y**: Textarea has aria-label; action buttons have aria-labels as well.
131
+
@@ -0,0 +1,96 @@
1
+ # MessageList
2
+
3
+ ## Overview
4
+
5
+ Vertical list of chat messages with optional typing indicator. Renders each message via `ChatMessage` and supports per-message actions.
6
+
7
+ ---
8
+
9
+ ## Props
10
+
11
+ | Prop | Type | Default | Description |
12
+ | ----------------- | -------------------------------------------------------------------- | ----------- | ----------- |
13
+ | `messages` | `Message[]` | `[]` | Array of messages to render. |
14
+ | `showTimeStamps` | `boolean` | `true` | Show timestamps on each message. |
15
+ | `isTyping` | `boolean` | `false` | Shows a typing indicator at the end of the list. |
16
+ | `messageOptions` | `AdditionalMessageOptions \| (message: Message) => AdditionalMessageOptions` | `undefined` | Additional props/actions per message (static or function of message). |
17
+ | `onEdit` | `(id: string, newContent: string) => void` | `undefined` | Called when a message enters edit mode and changes. |
18
+ | `onMessageSave` | `(id: string, content: string) => void` | `undefined` | Called when a message edit is saved. |
19
+
20
+ `AdditionalMessageOptions` mirrors `ChatMessageProps` except base `Message` fields.
21
+
22
+ ---
23
+
24
+ ## Behavior
25
+
26
+ - **Per-message customization**: Pass `messageOptions` as a function to supply contextual actions.
27
+ - **Typing indicator**: `isTyping` renders `TypingIndicator` as the last item.
28
+ - **Composition**: Each message is passed to `ChatMessage` with merged props.
29
+
30
+ ---
31
+
32
+ ## Examples
33
+
34
+ ### Default
35
+
36
+ ```tsx
37
+ import { MessageList } from "laif-ds";
38
+
39
+ export function Chat() {
40
+ const messages = [
41
+ { id: "1", role: "user", content: "Ciao!", createdAt: new Date() },
42
+ { id: "2", role: "assistant", content: "Come posso aiutarti?", createdAt: new Date() },
43
+ ];
44
+ return (
45
+ <div className="border-d-border w-full max-w-2xl rounded-lg border p-4">
46
+ <MessageList messages={messages} showTimeStamps />
47
+ </div>
48
+ );
49
+ }
50
+ ```
51
+
52
+ ### With Actions
53
+
54
+ ```tsx
55
+ import { Button, Icon } from "laif-ds";
56
+ import { MessageList } from "laif-ds";
57
+
58
+ export function ChatWithActions() {
59
+ const messages = [
60
+ { id: "1", role: "user", content: "Spiegami il virtual DOM", createdAt: new Date() },
61
+ { id: "2", role: "assistant", content: "Il Virtual DOM è...", createdAt: new Date() },
62
+ ];
63
+
64
+ return (
65
+ <div className="border-d-border w-full max-w-2xl rounded-lg border p-4">
66
+ <MessageList
67
+ messages={messages}
68
+ messageOptions={(m) =>
69
+ m.role === "assistant"
70
+ ? {
71
+ actions: (
72
+ <>
73
+ <Button variant="ghost" size="icon" className="h-6 w-6">
74
+ <Icon name="ThumbsUp" className="size-4" />
75
+ </Button>
76
+ <Button variant="ghost" size="icon" className="h-6 w-6">
77
+ <Icon name="ThumbsDown" className="size-4" />
78
+ </Button>
79
+ </>
80
+ ),
81
+ }
82
+ : {}
83
+ }
84
+ />
85
+ </div>
86
+ );
87
+ }
88
+ ```
89
+
90
+ ---
91
+
92
+ ## Notes
93
+
94
+ - **Data model**: See `ChatMessage` for the `Message` shape and advanced features (tool invocations, reasoning parts, edits).
95
+ - **A11y**: Provide readable timestamps and roles; actions should include accessible labels.
96
+