laif-ds 0.2.74 → 0.2.76

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 (155) hide show
  1. package/dist/CHANGELOG.md +446 -0
  2. package/dist/agent-docs/adoption-report.json +615 -0
  3. package/dist/agent-docs/components/Accordion.md +46 -16
  4. package/dist/agent-docs/components/Alert.md +90 -95
  5. package/dist/agent-docs/components/AlertDialog.md +132 -126
  6. package/dist/agent-docs/components/AppEditor.md +90 -90
  7. package/dist/agent-docs/components/AppRadioGroup.md +18 -18
  8. package/dist/agent-docs/components/AppSidebar.md +129 -122
  9. package/dist/agent-docs/components/AppStepper.md +81 -77
  10. package/dist/agent-docs/components/AspectRatio.md +70 -62
  11. package/dist/agent-docs/components/AudioVisualizer.md +5 -5
  12. package/dist/agent-docs/components/Avatar.md +112 -113
  13. package/dist/agent-docs/components/Badge.md +123 -118
  14. package/dist/agent-docs/components/Breadcrumb.md +8 -1
  15. package/dist/agent-docs/components/Button.md +131 -129
  16. package/dist/agent-docs/components/Card.md +172 -147
  17. package/dist/agent-docs/components/Carousel.md +148 -129
  18. package/dist/agent-docs/components/Chat.md +121 -109
  19. package/dist/agent-docs/components/ChatMessage.md +72 -61
  20. package/dist/agent-docs/components/Checkbox.md +150 -135
  21. package/dist/agent-docs/components/CircularProgress.md +53 -49
  22. package/dist/agent-docs/components/CodeHighlighter.md +4 -4
  23. package/dist/agent-docs/components/Collapsible.md +114 -95
  24. package/dist/agent-docs/components/Command.md +141 -142
  25. package/dist/agent-docs/components/Confirmer.md +182 -175
  26. package/dist/agent-docs/components/ContextMenu.md +196 -191
  27. package/dist/agent-docs/components/DataCrossTable.md +114 -94
  28. package/dist/agent-docs/components/DataTable.md +32 -24
  29. package/dist/agent-docs/components/Dialog.md +130 -125
  30. package/dist/agent-docs/components/Drawer.md +141 -127
  31. package/dist/agent-docs/components/FilePreviewer.md +138 -139
  32. package/dist/agent-docs/components/FileUploader.md +149 -129
  33. package/dist/agent-docs/components/Form.md +3 -1
  34. package/dist/agent-docs/components/FormComposer.md +163 -137
  35. package/dist/agent-docs/components/GanttChart.md +125 -122
  36. package/dist/agent-docs/components/HoverCard.md +1 -1
  37. package/dist/agent-docs/components/Icon.md +98 -99
  38. package/dist/agent-docs/components/Input.md +173 -138
  39. package/dist/agent-docs/components/InputOtp.md +6 -1
  40. package/dist/agent-docs/components/InputSelector.md +94 -97
  41. package/dist/agent-docs/components/InterruptPrompt.md +4 -4
  42. package/dist/agent-docs/components/MarkdownRenderer.md +5 -2
  43. package/dist/agent-docs/components/Menubar.md +60 -57
  44. package/dist/agent-docs/components/MessageInput.md +134 -131
  45. package/dist/agent-docs/components/MessageList.md +110 -96
  46. package/dist/agent-docs/components/MultipleSelector.md +147 -146
  47. package/dist/agent-docs/components/NavigationMenu.md +6 -2
  48. package/dist/agent-docs/components/Popover.md +112 -103
  49. package/dist/agent-docs/components/PromptSuggestions.md +5 -5
  50. package/dist/agent-docs/components/RadioGroup.md +97 -90
  51. package/dist/agent-docs/components/Resizable.md +4 -1
  52. package/dist/agent-docs/components/ResizePrompt.md +12 -13
  53. package/dist/agent-docs/components/ScrollArea.md +6 -2
  54. package/dist/agent-docs/components/SecurePdfViewer.md +10 -6
  55. package/dist/agent-docs/components/Select.md +131 -132
  56. package/dist/agent-docs/components/Sheet.md +8 -1
  57. package/dist/agent-docs/components/ShikiHighlighter.md +5 -5
  58. package/dist/agent-docs/components/Sidebar.md +94 -85
  59. package/dist/agent-docs/components/Slider.md +62 -58
  60. package/dist/agent-docs/components/Sonner.md +1 -0
  61. package/dist/agent-docs/components/Spinner.md +14 -14
  62. package/dist/agent-docs/components/Stepper.md +93 -67
  63. package/dist/agent-docs/components/Switch.md +41 -42
  64. package/dist/agent-docs/components/TableSkeleton.md +8 -8
  65. package/dist/agent-docs/components/Tabs.md +106 -86
  66. package/dist/agent-docs/components/TextArea.md +51 -52
  67. package/dist/agent-docs/components/ThemeSwitcher.md +72 -69
  68. package/dist/agent-docs/components/Toaster.md +1 -0
  69. package/dist/agent-docs/components/Tooltip.md +102 -91
  70. package/dist/agent-docs/components/Typo.md +68 -65
  71. package/dist/agent-docs/components/WeeklyCalendar.md +63 -64
  72. package/dist/agent-docs/components-list.md +1 -0
  73. package/dist/agent-docs/manifest.json +5981 -0
  74. package/dist/agent-docs/truncated-cell.md +342 -0
  75. package/dist/components/editor/editor-hooks/use-update-toolbar.js +6 -6
  76. package/dist/components/editor/plugins/actions/counter-character-plugin.js +6 -6
  77. package/dist/components/editor/plugins/toolbar/font-format-toolbar-plugin.js +18 -18
  78. package/dist/components/editor/plugins/toolbar/history-toolbar-plugin.js +10 -10
  79. package/dist/components/editor/plugins/toolbar/toolbar-plugin.js +9 -9
  80. package/dist/components/ui/app-checkbox.js +1 -1
  81. package/dist/components/ui/app-dialog.js +70 -64
  82. package/dist/components/ui/app-editor.js +51 -51
  83. package/dist/components/ui/app-form.js +81 -81
  84. package/dist/components/ui/app-multiple-select-dropdown.js +36 -36
  85. package/dist/components/ui/app-select.js +109 -104
  86. package/dist/components/ui/app-sidebar.js +41 -41
  87. package/dist/components/ui/app-stepper.js +1 -1
  88. package/dist/components/ui/app-time-picker.js +18 -18
  89. package/dist/components/ui/app-tooltip.js +1 -1
  90. package/dist/components/ui/async-select.js +5 -5
  91. package/dist/components/ui/audio-visualizer.js +61 -58
  92. package/dist/components/ui/card.js +1 -1
  93. package/dist/components/ui/carousel.js +2 -2
  94. package/dist/components/ui/chart.js +1 -1
  95. package/dist/components/ui/chat-message.js +8 -8
  96. package/dist/components/ui/chat.js +86 -88
  97. package/dist/components/ui/command.js +2 -2
  98. package/dist/components/ui/copy-button.js +4 -4
  99. package/dist/components/ui/date-picker.js +20 -20
  100. package/dist/components/ui/file-preview/index.js +13 -13
  101. package/dist/components/ui/file-previewer.js +12 -11
  102. package/dist/components/ui/file-uploader.js +86 -78
  103. package/dist/components/ui/form.js +2 -2
  104. package/dist/components/ui/gantt/components/Chart/Bars/Bars.js +56 -56
  105. package/dist/components/ui/gantt/components/Chart/Bars/BarsRow/BarItem/BarItem.js +12 -12
  106. package/dist/components/ui/gantt/components/Chart/Bars/BarsRow/BarsItems/BarItems.js +1 -1
  107. package/dist/components/ui/gantt/components/Chart/Bars/BarsRow/BarsRow.js +4 -4
  108. package/dist/components/ui/gantt/components/Chart/Bars/BarsRow/RepeteadBars/RepeteadBars.js +2 -2
  109. package/dist/components/ui/gantt/components/Chart/Chart.js +23 -23
  110. package/dist/components/ui/gantt/components/Chart/Scale/Scale.js +1 -1
  111. package/dist/components/ui/gantt/components/Chart/Tree/Tree.js +34 -34
  112. package/dist/components/ui/gantt/components/Controls/Controls.js +5 -5
  113. package/dist/components/ui/gantt/components/Gantt/Gantt.js +4 -4
  114. package/dist/components/ui/gantt/hooks/useGanttCalculate.js +25 -18
  115. package/dist/components/ui/input-selector.js +1 -1
  116. package/dist/components/ui/input.js +23 -23
  117. package/dist/components/ui/kanban.js +8 -9
  118. package/dist/components/ui/markdown-renderer.js +41 -35
  119. package/dist/components/ui/message-input.js +45 -44
  120. package/dist/components/ui/multiple-selector.js +91 -82
  121. package/dist/components/ui/secure-pdf-viewer.js +19 -7
  122. package/dist/components/ui/sidebar.js +1 -1
  123. package/dist/components/ui/slider.js +1 -1
  124. package/dist/components/ui/spinner.js +4 -4
  125. package/dist/components/ui/stepper.js +157 -138
  126. package/dist/components/ui/tables/data-cross-table/data-cross-table-buttons.js +29 -29
  127. package/dist/components/ui/tables/data-cross-table/data-cross-table.js +258 -246
  128. package/dist/components/ui/tables/data-table/components/data-table-advanced-filter.js +4 -1
  129. package/dist/components/ui/tables/data-table/components/data-table-body.js +211 -367
  130. package/dist/components/ui/tables/data-table/components/data-table-filter-inputs.js +114 -112
  131. package/dist/components/ui/tables/data-table/components/data-table-filters.js +116 -96
  132. package/dist/components/ui/tables/data-table/components/data-table-header.js +211 -0
  133. package/dist/components/ui/tables/data-table/components/data-table-searchbar.js +8 -8
  134. package/dist/components/ui/tables/data-table/components/data-table-skeleton-rows.js +33 -0
  135. package/dist/components/ui/tables/data-table/data-table.js +258 -250
  136. package/dist/components/ui/tables/data-table/data-table.service.js +112 -97
  137. package/dist/components/ui/tables/data-table/data-table.utils.js +25 -15
  138. package/dist/components/ui/textarea.js +2 -2
  139. package/dist/components/ui/theme-switcher.js +1 -1
  140. package/dist/components/ui/toggle-group.js +2 -2
  141. package/dist/components/ui/truncated-cell.js +100 -0
  142. package/dist/components/ui/weekly-calendar/appointment-card.js +16 -16
  143. package/dist/components/ui/weekly-calendar/calendar-context.js +6 -6
  144. package/dist/components/ui/weekly-calendar/calendar-header.js +12 -12
  145. package/dist/components/ui/weekly-calendar/day-column.js +16 -16
  146. package/dist/components/ui/weekly-calendar/time-column.js +4 -4
  147. package/dist/components/ui/weekly-calendar/weekly-calendar.js +4 -4
  148. package/dist/hooks/use-audio-recording.js +1 -1
  149. package/dist/hooks/use-auto-scroll.js +18 -18
  150. package/dist/hooks/use-autosize-textarea.js +12 -13
  151. package/dist/index.d.ts +100 -45
  152. package/dist/index.js +362 -360
  153. package/dist/lib/utils.js +6 -6
  154. package/dist/styles.v3.css +1 -1
  155. package/package.json +14 -4
@@ -1,97 +1,94 @@
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
-
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 <InputSelector value={value} onChange={setValue} min={1} max={4} />;
43
+ }
44
+ ```
45
+
46
+ ### Controlled
47
+
48
+ ```tsx
49
+ import { useState } from "react";
50
+ import { InputSelector } from "laif-ds";
51
+
52
+ export function ControlledSelector() {
53
+ const [value, setValue] = useState(2);
54
+
55
+ return (
56
+ <div className="flex flex-col items-center gap-2">
57
+ <InputSelector value={value} onChange={setValue} min={1} max={6} />
58
+ <div className="text-d-secondary-foreground text-sm">
59
+ Current value: {value}
60
+ </div>
61
+ </div>
62
+ );
63
+ }
64
+ ```
65
+
66
+ ### Custom Styling
67
+
68
+ ```tsx
69
+ import { useState } from "react";
70
+ import { InputSelector } from "laif-ds";
71
+
72
+ export function CustomStyledSelector() {
73
+ const [value, setValue] = useState(2);
74
+
75
+ return (
76
+ <InputSelector
77
+ value={value}
78
+ onChange={setValue}
79
+ min={1}
80
+ max={4}
81
+ className="bg-d-secondary/10 rounded-xl p-6"
82
+ buttonClassName="bg-d-primary text-d-primary-foreground hover:bg-d-primary/90 border-0"
83
+ counterClassName="text-d-primary font-bold"
84
+ />
85
+ );
86
+ }
87
+ ```
88
+
89
+ ---
90
+
91
+ ## Notes
92
+
93
+ - **Bounds UX**: The slight vibration on bound hit provides feedback without changing the value.
94
+ - **Styling**: Prefer design tokens (`bg-d-*`, `text-d-*`) over raw colors.
@@ -8,10 +8,10 @@ Animated prompt that appears to allow interrupting an action (e.g., hitting Ente
8
8
 
9
9
  ## Props
10
10
 
11
- | Prop | Type | Description |
12
- | --- | --- | --- |
13
- | `isOpen` | `boolean` | Whether the prompt is visible |
14
- | `close` | `() => void` | Close handler |
11
+ | Prop | Type | Description |
12
+ | -------- | ------------ | ----------------------------- |
13
+ | `isOpen` | `boolean` | Whether the prompt is visible |
14
+ | `close` | `() => void` | Close handler |
15
15
 
16
16
  ---
17
17
 
@@ -11,10 +11,13 @@ Renders Markdown with GitHub-flavored Markdown (GFM) and async syntax highlighti
11
11
  ```tsx
12
12
  import { MarkdownRenderer } from "laif-ds";
13
13
 
14
- const content = `
14
+ const content =
15
+ `
15
16
  # Hello
16
17
 
17
- Some ` + "`code`" + ` and a list:
18
+ Some ` +
19
+ "`code`" +
20
+ ` and a list:
18
21
 
19
22
  - Item A
20
23
  - Item B
@@ -1,47 +1,47 @@
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
-
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
41
  ## Examples
42
-
42
+
43
43
  ### Basic
44
-
44
+
45
45
  ```tsx
46
46
  import {
47
47
  Menubar,
@@ -87,9 +87,9 @@ export function BasicMenubar() {
87
87
  );
88
88
  }
89
89
  ```
90
-
90
+
91
91
  ### With Groups and Radios
92
-
92
+
93
93
  ```tsx
94
94
  import {
95
95
  Menubar,
@@ -121,9 +121,9 @@ export function MenubarWithGroups() {
121
121
  );
122
122
  }
123
123
  ```
124
-
124
+
125
125
  ### Destructive Item
126
-
126
+
127
127
  ```tsx
128
128
  import {
129
129
  Menubar,
@@ -141,8 +141,12 @@ export function DestructiveExample() {
141
141
  <MenubarMenu>
142
142
  <MenubarTrigger>Actions</MenubarTrigger>
143
143
  <MenubarContent>
144
- <MenubarItem>Copy <MenubarShortcut>⌘C</MenubarShortcut></MenubarItem>
145
- <MenubarItem>Paste <MenubarShortcut>⌘V</MenubarShortcut></MenubarItem>
144
+ <MenubarItem>
145
+ Copy <MenubarShortcut>⌘C</MenubarShortcut>
146
+ </MenubarItem>
147
+ <MenubarItem>
148
+ Paste <MenubarShortcut>⌘V</MenubarShortcut>
149
+ </MenubarItem>
146
150
  <MenubarSeparator />
147
151
  <MenubarItem variant="destructive">
148
152
  Delete <MenubarShortcut>⌘⌫</MenubarShortcut>
@@ -153,12 +157,11 @@ export function DestructiveExample() {
153
157
  );
154
158
  }
155
159
  ```
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
-
160
+
161
+ ---
162
+
163
+ ## Notes
164
+
165
+ - **Composition**: Combine subcomponents to build complex menus.
166
+ - **Shortcuts**: Use `MenubarShortcut` for right-aligned hints.
167
+ - **A11y**: Labels and roles are handled by Radix primitives and DS styling.
@@ -1,131 +1,134 @@
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
-
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
56
+ value={value}
57
+ onChange={(e) => setValue(e.target.value)}
58
+ isGenerating={false}
59
+ />
60
+ </form>
61
+ );
62
+ }
63
+ ```
64
+
65
+ ### With Attachments
66
+
67
+ ```tsx
68
+ import * as React from "react";
69
+ import { MessageInput } from "laif-ds";
70
+
71
+ export function WithAttachments() {
72
+ const [value, setValue] = React.useState("");
73
+ const [files, setFiles] = React.useState<File[] | null>(null);
74
+ const onSubmit = (e: React.FormEvent) => {
75
+ e.preventDefault();
76
+ console.log("Messaggio inviato:", value, files);
77
+ setValue("");
78
+ setFiles(null);
79
+ };
80
+ return (
81
+ <form onSubmit={onSubmit} className="w-full max-w-2xl">
82
+ <MessageInput
83
+ value={value}
84
+ onChange={(e) => setValue(e.target.value)}
85
+ isGenerating={false}
86
+ allowAttachments
87
+ files={files}
88
+ setFiles={setFiles}
89
+ placeholder="Scrivi un messaggio o trascina file qui..."
90
+ />
91
+ </form>
92
+ );
93
+ }
94
+ ```
95
+
96
+ ### Generating + Interrupt
97
+
98
+ ```tsx
99
+ import * as React from "react";
100
+ import { MessageInput } from "laif-ds";
101
+
102
+ export function Generating() {
103
+ const [value, setValue] = React.useState("");
104
+ const [isGenerating, setIsGenerating] = React.useState(true);
105
+ const stop = () => setIsGenerating(false);
106
+ const onSubmit = (e: React.FormEvent) => {
107
+ e.preventDefault();
108
+ if (isGenerating) return;
109
+ console.log("Messaggio inviato:", value);
110
+ setValue("");
111
+ setIsGenerating(true);
112
+ setTimeout(() => setIsGenerating(false), 3000);
113
+ };
114
+ return (
115
+ <form onSubmit={onSubmit} className="w-full max-w-2xl">
116
+ <MessageInput
117
+ value={value}
118
+ onChange={(e) => setValue(e.target.value)}
119
+ isGenerating={isGenerating}
120
+ stop={stop}
121
+ placeholder="L'AI sta generando una risposta..."
122
+ />
123
+ </form>
124
+ );
125
+ }
126
+ ```
127
+
128
+ ---
129
+
130
+ ## Notes
131
+
132
+ - **File preview**: Uses `FilePreview` for attachment chips.
133
+ - **Paste handling**: Long text paste becomes a `.txt` file when attachments are enabled.
134
+ - **A11y**: Textarea has aria-label; action buttons have aria-labels as well.