ai-design-system 0.1.0
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/README.md +307 -0
- package/components/ai-elements/actions.tsx +65 -0
- package/components/ai-elements/artifact.tsx +147 -0
- package/components/ai-elements/branch.tsx +212 -0
- package/components/ai-elements/canvas.tsx +24 -0
- package/components/ai-elements/chain-of-thought.tsx +228 -0
- package/components/ai-elements/code-block.tsx +179 -0
- package/components/ai-elements/confirmation.tsx +169 -0
- package/components/ai-elements/connection.tsx +28 -0
- package/components/ai-elements/context.tsx +408 -0
- package/components/ai-elements/controls.tsx +18 -0
- package/components/ai-elements/conversation.tsx +97 -0
- package/components/ai-elements/edge.tsx +140 -0
- package/components/ai-elements/image.tsx +24 -0
- package/components/ai-elements/inline-citation.tsx +287 -0
- package/components/ai-elements/loader.tsx +96 -0
- package/components/ai-elements/message.tsx +80 -0
- package/components/ai-elements/node.tsx +71 -0
- package/components/ai-elements/open-in-chat.tsx +363 -0
- package/components/ai-elements/panel.tsx +15 -0
- package/components/ai-elements/plan.tsx +142 -0
- package/components/ai-elements/prompt-input.tsx +1352 -0
- package/components/ai-elements/queue.tsx +274 -0
- package/components/ai-elements/reasoning.tsx +178 -0
- package/components/ai-elements/response.tsx +22 -0
- package/components/ai-elements/shimmer.tsx +64 -0
- package/components/ai-elements/sources.tsx +77 -0
- package/components/ai-elements/suggestion.tsx +56 -0
- package/components/ai-elements/task.tsx +87 -0
- package/components/ai-elements/tool.tsx +179 -0
- package/components/ai-elements/toolbar.tsx +16 -0
- package/components/ai-elements/web-preview.tsx +263 -0
- package/components/blocks/AIConversation/AIConversation.stories.tsx +164 -0
- package/components/blocks/AIConversation/AIConversation.tsx +186 -0
- package/components/blocks/AIConversation/index.ts +8 -0
- package/components/blocks/AppSidebar/AppSidebar.stories.tsx +63 -0
- package/components/blocks/AppSidebar/AppSidebar.tsx +87 -0
- package/components/blocks/AppSidebar/index.ts +2 -0
- package/components/blocks/DocumentEditorWithComments/DocumentEditorWithComments.stories.tsx +341 -0
- package/components/blocks/DocumentEditorWithComments/DocumentEditorWithComments.tsx +255 -0
- package/components/blocks/DocumentEditorWithComments/index.ts +9 -0
- package/components/blocks/FileChangeQueue/FileChangeQueue.stories.tsx +207 -0
- package/components/blocks/FileChangeQueue/FileChangeQueue.tsx +143 -0
- package/components/blocks/FileChangeQueue/index.ts +7 -0
- package/components/blocks/LayoutProvider/LayoutProvider.tsx +34 -0
- package/components/blocks/LayoutProvider/index.ts +1 -0
- package/components/blocks/index.ts +2 -0
- package/components/composites/AgentIndicator/AgentIndicator.stories.tsx +154 -0
- package/components/composites/AgentIndicator/AgentIndicator.tsx +102 -0
- package/components/composites/AgentIndicator/index.ts +8 -0
- package/components/composites/AppHeader/AppHeader.stories.tsx +46 -0
- package/components/composites/AppHeader/AppHeader.tsx +24 -0
- package/components/composites/AppHeader/index.ts +2 -0
- package/components/composites/CommentBox/CommentBox.stories.tsx +192 -0
- package/components/composites/CommentBox/CommentBox.tsx +364 -0
- package/components/composites/CommentBox/index.ts +8 -0
- package/components/composites/Confirmation/Confirmation.stories.tsx +151 -0
- package/components/composites/Confirmation/Confirmation.tsx +93 -0
- package/components/composites/Confirmation/index.ts +7 -0
- package/components/composites/DataTable/DataTable.stories.tsx +35 -0
- package/components/composites/DataTable/DataTable.tsx +95 -0
- package/components/composites/DataTable/index.ts +2 -0
- package/components/composites/DocumentEditor/DocumentEditor.css +106 -0
- package/components/composites/DocumentEditor/DocumentEditor.stories.tsx +927 -0
- package/components/composites/DocumentEditor/DocumentEditor.tsx +279 -0
- package/components/composites/DocumentEditor/index.ts +8 -0
- package/components/composites/FileQueue/FileQueue.stories.tsx +175 -0
- package/components/composites/FileQueue/FileQueue.tsx +161 -0
- package/components/composites/FileQueue/FileStatusBadge.tsx +74 -0
- package/components/composites/FileQueue/index.ts +24 -0
- package/components/composites/InteractiveChart/InteractiveChart.stories.tsx +49 -0
- package/components/composites/InteractiveChart/InteractiveChart.tsx +69 -0
- package/components/composites/InteractiveChart/index.ts +2 -0
- package/components/composites/ModeToggle/ModeToggle.stories.tsx +212 -0
- package/components/composites/ModeToggle/ModeToggle.tsx +100 -0
- package/components/composites/ModeToggle/index.ts +7 -0
- package/components/composites/NavUser/NavUser.stories.tsx +50 -0
- package/components/composites/NavUser/NavUser.tsx +60 -0
- package/components/composites/NavUser/index.ts +2 -0
- package/components/composites/NavigationList/NavigationList.stories.tsx +46 -0
- package/components/composites/NavigationList/NavigationList.tsx +46 -0
- package/components/composites/NavigationList/index.ts +2 -0
- package/components/composites/OrchestratorMessage/OrchestratorMessage.stories.tsx +188 -0
- package/components/composites/OrchestratorMessage/OrchestratorMessage.tsx +72 -0
- package/components/composites/OrchestratorMessage/index.ts +8 -0
- package/components/composites/PageContainer/PageContainer.stories.tsx +41 -0
- package/components/composites/PageContainer/PageContainer.tsx +24 -0
- package/components/composites/PageContainer/index.ts +2 -0
- package/components/composites/PromptInput/PromptInput.stories.tsx +200 -0
- package/components/composites/PromptInput/PromptInput.tsx +129 -0
- package/components/composites/PromptInput/index.ts +8 -0
- package/components/composites/SpecialistMessage/SpecialistMessage.stories.tsx +286 -0
- package/components/composites/SpecialistMessage/SpecialistMessage.tsx +107 -0
- package/components/composites/SpecialistMessage/index.ts +8 -0
- package/components/composites/StatsCard/StatsCard.stories.tsx +76 -0
- package/components/composites/StatsCard/StatsCard.tsx +81 -0
- package/components/composites/StatsCard/index.ts +2 -0
- package/components/composites/TablePagination/TablePagination.stories.tsx +38 -0
- package/components/composites/TablePagination/TablePagination.tsx +119 -0
- package/components/composites/TablePagination/index.ts +2 -0
- package/components/composites/TableToolbar/TableToolbar.stories.tsx +60 -0
- package/components/composites/TableToolbar/TableToolbar.tsx +66 -0
- package/components/composites/TableToolbar/index.ts +2 -0
- package/components/composites/ThemeSelector/ThemeSelector.stories.tsx +48 -0
- package/components/composites/ThemeSelector/ThemeSelector.tsx +79 -0
- package/components/composites/ThemeSelector/index.ts +2 -0
- package/components/composites/ToolCallDisplay/ToolCallDisplay.stories.tsx +49 -0
- package/components/composites/ToolCallDisplay/ToolCallDisplay.tsx +108 -0
- package/components/composites/ToolCallDisplay/index.ts +8 -0
- package/components/composites/UserMessage/UserMessage.stories.tsx +59 -0
- package/components/composites/UserMessage/UserMessage.tsx +52 -0
- package/components/composites/UserMessage/index.ts +8 -0
- package/components/composites/index.ts +90 -0
- package/components/features/AIDocEditor/AIDocEditor.behaviors.stories.tsx +451 -0
- package/components/features/AIDocEditor/AIDocEditor.mocks.ts +96 -0
- package/components/features/AIDocEditor/AIDocEditor.stories.tsx +140 -0
- package/components/features/AIDocEditor/AIDocEditor.tsx +130 -0
- package/components/features/AIDocEditor/index.ts +8 -0
- package/components/features/AIDocEditor/useAIDocEditor.d.ts +97 -0
- package/components/features/AIDocEditor/useAIDocEditor.mock.ts +83 -0
- package/components/features/PageLayout/PageLayout.behaviors.stories.tsx +119 -0
- package/components/features/PageLayout/PageLayout.mocks.ts +27 -0
- package/components/features/PageLayout/PageLayout.stories.tsx +142 -0
- package/components/features/PageLayout/PageLayout.tsx +94 -0
- package/components/features/PageLayout/index.ts +4 -0
- package/components/features/PageLayout/usePageLayout.d.ts +24 -0
- package/components/features/PageLayout/usePageLayout.mock.ts +19 -0
- package/components/features/RefinementPanel/README.md +189 -0
- package/components/features/RefinementPanel/RefinementPanel.behaviors.stories.tsx +475 -0
- package/components/features/RefinementPanel/RefinementPanel.mocks.ts +131 -0
- package/components/features/RefinementPanel/RefinementPanel.stories.tsx +141 -0
- package/components/features/RefinementPanel/RefinementPanel.tsx +160 -0
- package/components/features/RefinementPanel/index.ts +25 -0
- package/components/features/RefinementPanel/useRefinementPanel.d.ts +74 -0
- package/components/features/RefinementPanel/useRefinementPanel.mock.ts +121 -0
- package/components/features/SpecNavigator/SpecNavigator.behaviors.stories.tsx +379 -0
- package/components/features/SpecNavigator/SpecNavigator.mocks.ts +131 -0
- package/components/features/SpecNavigator/SpecNavigator.stories.tsx +122 -0
- package/components/features/SpecNavigator/SpecNavigator.tsx +43 -0
- package/components/features/SpecNavigator/index.ts +2 -0
- package/components/features/SpecNavigator/useSpecNavigator.d.ts +122 -0
- package/components/features/SpecNavigator/useSpecNavigator.mock.ts +93 -0
- package/components/features/index.ts +18 -0
- package/components/index.ts +14 -0
- package/components/primitives/Accordion/Accordion.stories.tsx +87 -0
- package/components/primitives/Accordion/Accordion.tsx +66 -0
- package/components/primitives/Accordion/index.ts +13 -0
- package/components/primitives/Alert/Alert.stories.tsx +422 -0
- package/components/primitives/Alert/Alert.tsx +61 -0
- package/components/primitives/Alert/index.ts +8 -0
- package/components/primitives/AlertDialog/AlertDialog.stories.tsx +367 -0
- package/components/primitives/AlertDialog/AlertDialog.tsx +182 -0
- package/components/primitives/AlertDialog/index.ts +25 -0
- package/components/primitives/Avatar/Avatar.stories.tsx +321 -0
- package/components/primitives/Avatar/Avatar.tsx +63 -0
- package/components/primitives/Avatar/index.ts +8 -0
- package/components/primitives/Badge/Badge.stories.tsx +74 -0
- package/components/primitives/Badge/Badge.tsx +49 -0
- package/components/primitives/Badge/index.ts +2 -0
- package/components/primitives/Button/Button.stories.tsx +445 -0
- package/components/primitives/Button/Button.tsx +89 -0
- package/components/primitives/Button/index.ts +7 -0
- package/components/primitives/Card/Card.stories.tsx +831 -0
- package/components/primitives/Card/Card.tsx +242 -0
- package/components/primitives/Card/index.ts +30 -0
- package/components/primitives/Carousel/Carousel.stories.tsx +32 -0
- package/components/primitives/Carousel/Carousel.tsx +63 -0
- package/components/primitives/Carousel/index.ts +13 -0
- package/components/primitives/Chart/Chart.stories.tsx +346 -0
- package/components/primitives/Chart/Chart.tsx +117 -0
- package/components/primitives/Chart/index.ts +20 -0
- package/components/primitives/Checkbox/Checkbox.stories.tsx +87 -0
- package/components/primitives/Checkbox/Checkbox.tsx +38 -0
- package/components/primitives/Checkbox/index.ts +2 -0
- package/components/primitives/Collapsible/Collapsible.stories.tsx +38 -0
- package/components/primitives/Collapsible/Collapsible.tsx +39 -0
- package/components/primitives/Collapsible/index.ts +8 -0
- package/components/primitives/Command/Command.stories.tsx +150 -0
- package/components/primitives/Command/Command.tsx +147 -0
- package/components/primitives/Command/index.ts +20 -0
- package/components/primitives/Dialog/Dialog.stories.tsx +390 -0
- package/components/primitives/Dialog/Dialog.tsx +140 -0
- package/components/primitives/Dialog/index.ts +22 -0
- package/components/primitives/Drawer/Drawer.stories.tsx +327 -0
- package/components/primitives/Drawer/Drawer.tsx +208 -0
- package/components/primitives/Drawer/index.ts +27 -0
- package/components/primitives/DropdownMenu/DropdownMenu.stories.tsx +150 -0
- package/components/primitives/DropdownMenu/DropdownMenu.tsx +73 -0
- package/components/primitives/DropdownMenu/index.ts +1 -0
- package/components/primitives/HoverCard/HoverCard.stories.tsx +26 -0
- package/components/primitives/HoverCard/HoverCard.tsx +39 -0
- package/components/primitives/HoverCard/index.ts +8 -0
- package/components/primitives/Icon/Icon.stories.tsx +281 -0
- package/components/primitives/Icon/Icon.tsx +87 -0
- package/components/primitives/Icon/index.ts +8 -0
- package/components/primitives/Input/Input.stories.tsx +370 -0
- package/components/primitives/Input/Input.tsx +88 -0
- package/components/primitives/Input/index.ts +7 -0
- package/components/primitives/InputGroup/InputGroup.stories.tsx +40 -0
- package/components/primitives/InputGroup/InputGroup.tsx +72 -0
- package/components/primitives/InputGroup/index.ts +14 -0
- package/components/primitives/Label/Label.stories.tsx +227 -0
- package/components/primitives/Label/Label.tsx +53 -0
- package/components/primitives/Label/index.ts +7 -0
- package/components/primitives/Popover/Popover.stories.tsx +42 -0
- package/components/primitives/Popover/Popover.tsx +107 -0
- package/components/primitives/Popover/index.ts +2 -0
- package/components/primitives/Progress/Progress.stories.tsx +340 -0
- package/components/primitives/Progress/Progress.tsx +31 -0
- package/components/primitives/Progress/index.ts +1 -0
- package/components/primitives/ScrollArea/ScrollArea.stories.tsx +26 -0
- package/components/primitives/ScrollArea/ScrollArea.tsx +28 -0
- package/components/primitives/ScrollArea/index.ts +6 -0
- package/components/primitives/Select/Select.stories.tsx +288 -0
- package/components/primitives/Select/Select.tsx +162 -0
- package/components/primitives/Select/index.ts +22 -0
- package/components/primitives/Separator/Separator.stories.tsx +264 -0
- package/components/primitives/Separator/Separator.tsx +48 -0
- package/components/primitives/Separator/index.ts +7 -0
- package/components/primitives/Sidebar/Sidebar.stories.tsx +358 -0
- package/components/primitives/Sidebar/Sidebar.tsx +317 -0
- package/components/primitives/Sidebar/index.ts +41 -0
- package/components/primitives/Table/Table.stories.tsx +389 -0
- package/components/primitives/Table/Table.tsx +191 -0
- package/components/primitives/Table/index.ts +26 -0
- package/components/primitives/Tabs/Tabs.stories.tsx +129 -0
- package/components/primitives/Tabs/Tabs.tsx +70 -0
- package/components/primitives/Tabs/index.ts +13 -0
- package/components/primitives/Textarea/Textarea.stories.tsx +358 -0
- package/components/primitives/Textarea/Textarea.tsx +91 -0
- package/components/primitives/Textarea/index.ts +7 -0
- package/components/primitives/ToggleGroup/ToggleGroup.stories.tsx +87 -0
- package/components/primitives/ToggleGroup/ToggleGroup.tsx +52 -0
- package/components/primitives/ToggleGroup/index.ts +6 -0
- package/components/primitives/Tooltip/Tooltip.stories.tsx +336 -0
- package/components/primitives/Tooltip/Tooltip.tsx +78 -0
- package/components/primitives/Tooltip/index.ts +10 -0
- package/components/primitives/index.ts +34 -0
- package/components/ui/accordion.tsx +66 -0
- package/components/ui/alert-dialog.tsx +157 -0
- package/components/ui/alert.tsx +66 -0
- package/components/ui/avatar.tsx +53 -0
- package/components/ui/badge.tsx +46 -0
- package/components/ui/button.tsx +60 -0
- package/components/ui/card.tsx +117 -0
- package/components/ui/carousel.tsx +241 -0
- package/components/ui/chart.tsx +334 -0
- package/components/ui/checkbox.tsx +32 -0
- package/components/ui/collapsible.tsx +33 -0
- package/components/ui/command.tsx +184 -0
- package/components/ui/dialog.tsx +143 -0
- package/components/ui/drawer.tsx +118 -0
- package/components/ui/dropdown-menu.tsx +257 -0
- package/components/ui/hover-card.tsx +44 -0
- package/components/ui/input-group.tsx +170 -0
- package/components/ui/input.tsx +48 -0
- package/components/ui/label.tsx +26 -0
- package/components/ui/popover.tsx +33 -0
- package/components/ui/progress.tsx +31 -0
- package/components/ui/scroll-area.tsx +58 -0
- package/components/ui/select.tsx +187 -0
- package/components/ui/separator.tsx +31 -0
- package/components/ui/sidebar.tsx +577 -0
- package/components/ui/table.tsx +120 -0
- package/components/ui/tabs.tsx +66 -0
- package/components/ui/textarea.tsx +46 -0
- package/components/ui/toggle-group.tsx +83 -0
- package/components/ui/toggle.tsx +47 -0
- package/components/ui/tooltip.tsx +61 -0
- package/dist/index.cjs +7389 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.css +75 -0
- package/dist/index.css.map +1 -0
- package/dist/index.js +7160 -0
- package/dist/index.js.map +1 -0
- package/hooks/useAIDocReviewer.d.ts +0 -0
- package/lib/utils.ts +6 -0
- package/package.json +140 -0
- package/tokens/color/base.json +14 -0
- package/tokens/color/dark.json +40 -0
- package/tokens/color/green.json +21 -0
- package/tokens/color/light.json +52 -0
- package/tokens/color/neutral.json +20 -0
- package/tokens/color/violet.json +21 -0
- package/tokens/spacing.json +22 -0
- package/utils/ai-editor/format-date.ts +41 -0
- package/utils/ai-editor/index.ts +22 -0
- package/utils/ai-editor/type-guards.ts +72 -0
- package/utils/ai-editor/validation.ts +130 -0
- package/utils/editor-annotations.ts +122 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import { OrchestratorMessage } from './OrchestratorMessage'
|
|
3
|
+
import { SpecialistMessage } from '../SpecialistMessage'
|
|
4
|
+
import { ToolCallDisplay } from '../ToolCallDisplay'
|
|
5
|
+
import { Search, BarChart, FileText } from 'lucide-react'
|
|
6
|
+
|
|
7
|
+
const meta: Meta<typeof OrchestratorMessage> = {
|
|
8
|
+
title: 'Composites/OrchestratorMessage',
|
|
9
|
+
component: OrchestratorMessage,
|
|
10
|
+
parameters: {
|
|
11
|
+
layout: 'padded',
|
|
12
|
+
},
|
|
13
|
+
} satisfies Meta<typeof OrchestratorMessage>
|
|
14
|
+
|
|
15
|
+
export default meta
|
|
16
|
+
type Story = StoryObj<typeof meta>
|
|
17
|
+
|
|
18
|
+
export const Default: Story = {
|
|
19
|
+
args: {
|
|
20
|
+
message: {
|
|
21
|
+
id: '1',
|
|
22
|
+
content: 'I will coordinate the analysis across multiple specialist agents.',
|
|
23
|
+
avatarSrc: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=32&h=32&fit=crop&crop=face',
|
|
24
|
+
avatarName: 'Coordinator',
|
|
25
|
+
},
|
|
26
|
+
showAvatar: true,
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const WithoutAvatar: Story = {
|
|
31
|
+
args: {
|
|
32
|
+
message: {
|
|
33
|
+
id: '2',
|
|
34
|
+
content: 'Orchestrating workflow without avatar display...',
|
|
35
|
+
},
|
|
36
|
+
showAvatar: false,
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const WithSpecialists: Story = {
|
|
41
|
+
args: {
|
|
42
|
+
message: {
|
|
43
|
+
id: '3',
|
|
44
|
+
content: 'I am delegating tasks to specialized agents for comprehensive analysis.',
|
|
45
|
+
avatarSrc: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=32&h=32&fit=crop&crop=face',
|
|
46
|
+
avatarName: 'Coordinator',
|
|
47
|
+
},
|
|
48
|
+
showAvatar: true,
|
|
49
|
+
children: (
|
|
50
|
+
<>
|
|
51
|
+
<SpecialistMessage
|
|
52
|
+
message={{
|
|
53
|
+
id: 'spec_1',
|
|
54
|
+
name: 'research-agent',
|
|
55
|
+
description: 'Gathering relevant information from multiple sources',
|
|
56
|
+
icon: <Search className="size-4" />,
|
|
57
|
+
content: 'Researching the topic and gathering relevant information...',
|
|
58
|
+
status: 'completed',
|
|
59
|
+
}}
|
|
60
|
+
isNested={true}
|
|
61
|
+
/>
|
|
62
|
+
<SpecialistMessage
|
|
63
|
+
message={{
|
|
64
|
+
id: 'spec_2',
|
|
65
|
+
name: 'analysis-agent',
|
|
66
|
+
description: 'Performing comprehensive analysis on research data',
|
|
67
|
+
icon: <BarChart className="size-4" />,
|
|
68
|
+
content: 'Analyzing the collected data and extracting insights...',
|
|
69
|
+
status: 'active',
|
|
70
|
+
}}
|
|
71
|
+
isNested={true}
|
|
72
|
+
/>
|
|
73
|
+
<SpecialistMessage
|
|
74
|
+
message={{
|
|
75
|
+
id: 'spec_3',
|
|
76
|
+
name: 'summary-agent',
|
|
77
|
+
description: 'Creating comprehensive summary of findings',
|
|
78
|
+
icon: <FileText className="size-4" />,
|
|
79
|
+
content: 'Preparing comprehensive summary of findings...',
|
|
80
|
+
status: 'pending',
|
|
81
|
+
}}
|
|
82
|
+
isNested={true}
|
|
83
|
+
/>
|
|
84
|
+
</>
|
|
85
|
+
),
|
|
86
|
+
},
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export const WithToolCalls: Story = {
|
|
90
|
+
args: {
|
|
91
|
+
message: {
|
|
92
|
+
id: '4',
|
|
93
|
+
content: 'Executing direct tool calls before delegating to specialists.',
|
|
94
|
+
avatarSrc: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=32&h=32&fit=crop&crop=face',
|
|
95
|
+
avatarName: 'Coordinator',
|
|
96
|
+
},
|
|
97
|
+
showAvatar: true,
|
|
98
|
+
children: (
|
|
99
|
+
<>
|
|
100
|
+
<ToolCallDisplay
|
|
101
|
+
toolCall={{
|
|
102
|
+
id: 'tool_1',
|
|
103
|
+
name: 'write_file',
|
|
104
|
+
args: { filename: 'plan.md', content: 'Execution plan...' },
|
|
105
|
+
result: 'File created successfully',
|
|
106
|
+
status: 'completed',
|
|
107
|
+
}}
|
|
108
|
+
/>
|
|
109
|
+
<ToolCallDisplay
|
|
110
|
+
toolCall={{
|
|
111
|
+
id: 'tool_2',
|
|
112
|
+
name: 'write_todos',
|
|
113
|
+
args: { todos: ['Task 1', 'Task 2', 'Task 3'] },
|
|
114
|
+
result: 'Todo list created',
|
|
115
|
+
status: 'completed',
|
|
116
|
+
}}
|
|
117
|
+
/>
|
|
118
|
+
</>
|
|
119
|
+
),
|
|
120
|
+
},
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export const CompleteWorkflow: Story = {
|
|
124
|
+
args: {
|
|
125
|
+
message: {
|
|
126
|
+
id: '5',
|
|
127
|
+
content: 'I will manage this complex workflow with both direct tools and specialist agents.',
|
|
128
|
+
avatarSrc: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=32&h=32&fit=crop&crop=face',
|
|
129
|
+
avatarName: 'Coordinator',
|
|
130
|
+
},
|
|
131
|
+
showAvatar: true,
|
|
132
|
+
children: (
|
|
133
|
+
<>
|
|
134
|
+
<ToolCallDisplay
|
|
135
|
+
toolCall={{
|
|
136
|
+
id: 'tool_1',
|
|
137
|
+
name: 'create_plan',
|
|
138
|
+
args: { objective: 'Complete analysis' },
|
|
139
|
+
result: 'Plan created',
|
|
140
|
+
status: 'completed',
|
|
141
|
+
}}
|
|
142
|
+
/>
|
|
143
|
+
<SpecialistMessage
|
|
144
|
+
message={{
|
|
145
|
+
id: 'spec_1',
|
|
146
|
+
name: 'data-collector',
|
|
147
|
+
description: 'Collecting data from multiple sources',
|
|
148
|
+
icon: <Search className="size-4" />,
|
|
149
|
+
content: 'Collecting data from multiple sources...',
|
|
150
|
+
status: 'completed',
|
|
151
|
+
toolCalls: [
|
|
152
|
+
{
|
|
153
|
+
id: 'subtool_1',
|
|
154
|
+
name: 'fetch_data',
|
|
155
|
+
args: { source: 'API' },
|
|
156
|
+
result: 'Data fetched',
|
|
157
|
+
status: 'completed',
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
|
+
}}
|
|
161
|
+
isNested={true}
|
|
162
|
+
/>
|
|
163
|
+
<SpecialistMessage
|
|
164
|
+
message={{
|
|
165
|
+
id: 'spec_2',
|
|
166
|
+
name: 'processor',
|
|
167
|
+
description: 'Processing and transforming the collected data',
|
|
168
|
+
icon: <BarChart className="size-4" />,
|
|
169
|
+
content: 'Processing and transforming the collected data...',
|
|
170
|
+
status: 'active',
|
|
171
|
+
}}
|
|
172
|
+
isNested={true}
|
|
173
|
+
/>
|
|
174
|
+
<SpecialistMessage
|
|
175
|
+
message={{
|
|
176
|
+
id: 'spec_3',
|
|
177
|
+
name: 'reporter',
|
|
178
|
+
description: 'Generating final report with visualizations',
|
|
179
|
+
icon: <FileText className="size-4" />,
|
|
180
|
+
content: 'Generating final report with visualizations...',
|
|
181
|
+
status: 'pending',
|
|
182
|
+
}}
|
|
183
|
+
isNested={true}
|
|
184
|
+
/>
|
|
185
|
+
</>
|
|
186
|
+
),
|
|
187
|
+
},
|
|
188
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import {
|
|
3
|
+
Message,
|
|
4
|
+
MessageContent,
|
|
5
|
+
MessageAvatar,
|
|
6
|
+
} from "@/components/ai-elements/message"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* OrchestratorMessage Block
|
|
10
|
+
*
|
|
11
|
+
* A block component for displaying orchestrator/coordinator agent messages.
|
|
12
|
+
* Accepts children components (SpecialistMessage and ToolCallDisplay) for composition.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export interface OrchestratorMessageData {
|
|
16
|
+
id: string
|
|
17
|
+
content: string
|
|
18
|
+
avatarSrc?: string
|
|
19
|
+
avatarName?: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface OrchestratorMessageProps {
|
|
23
|
+
/**
|
|
24
|
+
* Orchestrator message data to display
|
|
25
|
+
*/
|
|
26
|
+
message: OrchestratorMessageData
|
|
27
|
+
/**
|
|
28
|
+
* Whether to show avatar
|
|
29
|
+
*/
|
|
30
|
+
showAvatar?: boolean
|
|
31
|
+
/**
|
|
32
|
+
* Child components (SpecialistMessage, ToolCallDisplay)
|
|
33
|
+
*/
|
|
34
|
+
children?: React.ReactNode
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* OrchestratorMessage component - displays coordinator messages with nested specialists and tools
|
|
39
|
+
*/
|
|
40
|
+
export const OrchestratorMessage = React.memo<OrchestratorMessageProps>(
|
|
41
|
+
({ message, showAvatar = true, children }) => {
|
|
42
|
+
const hasContent = React.useMemo(
|
|
43
|
+
() => message.content && message.content.trim() !== "",
|
|
44
|
+
[message.content]
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<Message from="assistant">
|
|
49
|
+
{showAvatar && (
|
|
50
|
+
<MessageAvatar
|
|
51
|
+
src={message.avatarSrc || "/coordinator-avatar.png"}
|
|
52
|
+
name={message.avatarName || "Coordinator"}
|
|
53
|
+
/>
|
|
54
|
+
)}
|
|
55
|
+
|
|
56
|
+
<div className="flex-1">
|
|
57
|
+
{/* Orchestrator's message content */}
|
|
58
|
+
{hasContent && (
|
|
59
|
+
<MessageContent variant="contained">
|
|
60
|
+
{message.content}
|
|
61
|
+
</MessageContent>
|
|
62
|
+
)}
|
|
63
|
+
|
|
64
|
+
{/* Child components (specialists and tool calls) */}
|
|
65
|
+
{children && <div className="mt-4 space-y-4">{children}</div>}
|
|
66
|
+
</div>
|
|
67
|
+
</Message>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
OrchestratorMessage.displayName = "OrchestratorMessage"
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OrchestratorMessage Block
|
|
3
|
+
*
|
|
4
|
+
* Central export point for the OrchestratorMessage block component and its related types.
|
|
5
|
+
*/
|
|
6
|
+
export { OrchestratorMessage } from './OrchestratorMessage'
|
|
7
|
+
|
|
8
|
+
export type { OrchestratorMessageProps, OrchestratorMessageData } from './OrchestratorMessage'
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import { PageContainer } from './PageContainer'
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'Composites/PageContainer',
|
|
6
|
+
component: PageContainer,
|
|
7
|
+
tags: ['autodocs'],
|
|
8
|
+
parameters: {
|
|
9
|
+
layout: 'fullscreen',
|
|
10
|
+
},
|
|
11
|
+
} satisfies Meta<typeof PageContainer>
|
|
12
|
+
|
|
13
|
+
export default meta
|
|
14
|
+
type Story = StoryObj<typeof meta>
|
|
15
|
+
|
|
16
|
+
export const Default: Story = {
|
|
17
|
+
args: {
|
|
18
|
+
children: (
|
|
19
|
+
<div className="p-6">
|
|
20
|
+
<h1 className="text-2xl font-bold">Page Content</h1>
|
|
21
|
+
<p className="mt-4 text-muted-foreground">
|
|
22
|
+
This is the main page content wrapped in PageContainer.
|
|
23
|
+
</p>
|
|
24
|
+
</div>
|
|
25
|
+
),
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const WithCustomClass: Story = {
|
|
30
|
+
args: {
|
|
31
|
+
children: (
|
|
32
|
+
<div className="p-6">
|
|
33
|
+
<h1 className="text-2xl font-bold">Custom Styled Container</h1>
|
|
34
|
+
<p className="mt-4 text-muted-foreground">
|
|
35
|
+
PageContainer with custom className applied.
|
|
36
|
+
</p>
|
|
37
|
+
</div>
|
|
38
|
+
),
|
|
39
|
+
className: 'bg-muted',
|
|
40
|
+
},
|
|
41
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { SidebarInset } from "@/components/primitives/Sidebar"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* PageContainer Composite
|
|
6
|
+
*
|
|
7
|
+
* Container for page content that works with Sidebar layout.
|
|
8
|
+
* Wraps content with SidebarInset primitive.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export interface PageContainerProps {
|
|
12
|
+
children: React.ReactNode
|
|
13
|
+
className?: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const PageContainer = React.memo<PageContainerProps>(({ children, className }) => {
|
|
17
|
+
return (
|
|
18
|
+
<SidebarInset className={className}>
|
|
19
|
+
{children}
|
|
20
|
+
</SidebarInset>
|
|
21
|
+
)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
PageContainer.displayName = "PageContainer"
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { PromptInput } from "./PromptInput";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof PromptInput> = {
|
|
6
|
+
title: "Blocks/PromptInput",
|
|
7
|
+
component: PromptInput,
|
|
8
|
+
parameters: {
|
|
9
|
+
layout: "padded",
|
|
10
|
+
},
|
|
11
|
+
argTypes: {
|
|
12
|
+
disabled: {
|
|
13
|
+
control: "boolean",
|
|
14
|
+
description: "Blocks form submission when true. Textarea remains editable.",
|
|
15
|
+
},
|
|
16
|
+
placeholder: {
|
|
17
|
+
control: "text",
|
|
18
|
+
description: "Placeholder text for the textarea input",
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
} satisfies Meta<typeof PromptInput>;
|
|
22
|
+
|
|
23
|
+
export default meta;
|
|
24
|
+
type Story = StoryObj<typeof meta>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Default uncontrolled PromptInput
|
|
28
|
+
* The AI element manages its own internal state
|
|
29
|
+
*/
|
|
30
|
+
export const Default: Story = {
|
|
31
|
+
args: {
|
|
32
|
+
placeholder: "What would you like to know?",
|
|
33
|
+
onSubmit: (message) => {
|
|
34
|
+
console.log("Submitted:", message);
|
|
35
|
+
alert(`Submitted: ${message.text}`);
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Controlled state example
|
|
42
|
+
* Parent component manages the input value
|
|
43
|
+
*/
|
|
44
|
+
export const ControlledState: Story = {
|
|
45
|
+
render: () => {
|
|
46
|
+
const [value, setValue] = useState("");
|
|
47
|
+
const [submittedMessages, setSubmittedMessages] = useState<string[]>([]);
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<div className="space-y-4">
|
|
51
|
+
<div className="rounded-md border border-border bg-muted p-4">
|
|
52
|
+
<h3 className="mb-2 font-semibold text-sm">Parent State:</h3>
|
|
53
|
+
<p className="font-mono text-xs">
|
|
54
|
+
Current value: "{value}" ({value.length} chars)
|
|
55
|
+
</p>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<PromptInput
|
|
59
|
+
value={value}
|
|
60
|
+
onChange={setValue}
|
|
61
|
+
placeholder="Type something (controlled mode)"
|
|
62
|
+
onSubmit={(message) => {
|
|
63
|
+
setSubmittedMessages((prev) => [...prev, message.text || ""]);
|
|
64
|
+
setValue(""); // Clear after submit
|
|
65
|
+
}}
|
|
66
|
+
/>
|
|
67
|
+
|
|
68
|
+
{submittedMessages.length > 0 && (
|
|
69
|
+
<div className="rounded-md border border-border bg-muted p-4">
|
|
70
|
+
<h3 className="mb-2 font-semibold text-sm">Submitted Messages:</h3>
|
|
71
|
+
<ul className="space-y-1">
|
|
72
|
+
{submittedMessages.map((msg, i) => (
|
|
73
|
+
<li key={i} className="font-mono text-xs">
|
|
74
|
+
{i + 1}. {msg}
|
|
75
|
+
</li>
|
|
76
|
+
))}
|
|
77
|
+
</ul>
|
|
78
|
+
</div>
|
|
79
|
+
)}
|
|
80
|
+
</div>
|
|
81
|
+
);
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Disabled state
|
|
87
|
+
* Form submission is blocked, but textarea remains editable for drafts
|
|
88
|
+
*/
|
|
89
|
+
export const DisabledState: Story = {
|
|
90
|
+
render: () => {
|
|
91
|
+
const [isDisabled, setIsDisabled] = useState(true);
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<div className="space-y-4">
|
|
95
|
+
<div className="rounded-md border border-border bg-muted p-4">
|
|
96
|
+
<label className="flex items-center gap-2">
|
|
97
|
+
<input
|
|
98
|
+
type="checkbox"
|
|
99
|
+
checked={isDisabled}
|
|
100
|
+
onChange={(e) => setIsDisabled(e.target.checked)}
|
|
101
|
+
/>
|
|
102
|
+
<span className="text-sm">Disable submission (textarea stays editable)</span>
|
|
103
|
+
</label>
|
|
104
|
+
</div>
|
|
105
|
+
|
|
106
|
+
<PromptInput
|
|
107
|
+
disabled={isDisabled}
|
|
108
|
+
placeholder="Try typing and submitting (disabled mode)"
|
|
109
|
+
onSubmit={(message) => {
|
|
110
|
+
alert(`This should not appear when disabled! Message: ${message.text}`);
|
|
111
|
+
}}
|
|
112
|
+
/>
|
|
113
|
+
|
|
114
|
+
<div className="rounded-md border border-border bg-muted p-4">
|
|
115
|
+
<p className="text-muted-foreground text-xs">
|
|
116
|
+
When disabled, the submit button is blocked but you can still type in the textarea.
|
|
117
|
+
This is useful for review workflows where users can draft responses but cannot submit until approval.
|
|
118
|
+
</p>
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
);
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Custom placeholder
|
|
127
|
+
* Different placeholder text for various contexts
|
|
128
|
+
*/
|
|
129
|
+
export const CustomPlaceholder: Story = {
|
|
130
|
+
args: {
|
|
131
|
+
placeholder: "Ask a question or describe a task...",
|
|
132
|
+
onSubmit: (message) => {
|
|
133
|
+
console.log("Submitted:", message);
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Custom submit handler
|
|
140
|
+
* Demonstrates async submit handling with loading state
|
|
141
|
+
*/
|
|
142
|
+
export const CustomSubmitHandler: Story = {
|
|
143
|
+
render: () => {
|
|
144
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
145
|
+
const [lastSubmitted, setLastSubmitted] = useState<string>("");
|
|
146
|
+
|
|
147
|
+
return (
|
|
148
|
+
<div className="space-y-4">
|
|
149
|
+
{isSubmitting && (
|
|
150
|
+
<div className="rounded-md border border-border bg-muted p-4">
|
|
151
|
+
<p className="text-sm">Processing your message...</p>
|
|
152
|
+
</div>
|
|
153
|
+
)}
|
|
154
|
+
|
|
155
|
+
{lastSubmitted && (
|
|
156
|
+
<div className="rounded-md border border-border bg-muted p-4">
|
|
157
|
+
<h3 className="mb-2 font-semibold text-sm">Last Submitted:</h3>
|
|
158
|
+
<p className="font-mono text-xs">{lastSubmitted}</p>
|
|
159
|
+
</div>
|
|
160
|
+
)}
|
|
161
|
+
|
|
162
|
+
<PromptInput
|
|
163
|
+
placeholder="Type something and submit (simulates 2s async processing)"
|
|
164
|
+
disabled={isSubmitting}
|
|
165
|
+
onSubmit={async (message) => {
|
|
166
|
+
setIsSubmitting(true);
|
|
167
|
+
// Simulate async processing
|
|
168
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
169
|
+
setLastSubmitted(message.text || "");
|
|
170
|
+
setIsSubmitting(false);
|
|
171
|
+
}}
|
|
172
|
+
/>
|
|
173
|
+
</div>
|
|
174
|
+
);
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* No attachment UI
|
|
180
|
+
* Verifies compositional hiding - no attachment components visible
|
|
181
|
+
*/
|
|
182
|
+
export const NoAttachmentUI: Story = {
|
|
183
|
+
args: {
|
|
184
|
+
placeholder: "Text-only input - no attachment options available",
|
|
185
|
+
onSubmit: (message) => {
|
|
186
|
+
console.log("Message with files array:", message);
|
|
187
|
+
alert(
|
|
188
|
+
`Text: ${message.text}\nFiles: ${message.files?.length || 0} (should always be 0)`
|
|
189
|
+
);
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
parameters: {
|
|
193
|
+
docs: {
|
|
194
|
+
description: {
|
|
195
|
+
story:
|
|
196
|
+
"The PromptInput block hides all attachment-related UI through compositional hiding. No attachment buttons, dropdowns, or drag-drop functionality is exposed.",
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import {
|
|
5
|
+
PromptInput as AIPromptInput,
|
|
6
|
+
PromptInputBody,
|
|
7
|
+
PromptInputFooter,
|
|
8
|
+
PromptInputSubmit,
|
|
9
|
+
PromptInputTextarea,
|
|
10
|
+
PromptInputTools,
|
|
11
|
+
PromptInputProvider,
|
|
12
|
+
type PromptInputMessage,
|
|
13
|
+
type PromptInputProps as AIPromptInputProps,
|
|
14
|
+
} from "@/components/ai-elements/prompt-input";
|
|
15
|
+
import type { FormEvent } from "react";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* PromptInput Block
|
|
19
|
+
*
|
|
20
|
+
* A thin wrapper around the PromptInput AI element that hides attachment functionality.
|
|
21
|
+
* This block provides a simplified prompt input interface focused on text-only input.
|
|
22
|
+
*
|
|
23
|
+
* Features:
|
|
24
|
+
* - Controlled and uncontrolled state support
|
|
25
|
+
* - Disabled state (blocks submission, keeps textarea editable)
|
|
26
|
+
* - Custom placeholder text
|
|
27
|
+
* - No attachment UI (compositional hiding)
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
export interface PromptInputBlockProps
|
|
31
|
+
extends Omit<
|
|
32
|
+
AIPromptInputProps,
|
|
33
|
+
"accept" | "multiple" | "maxFiles" | "maxFileSize" | "globalDrop" | "syncHiddenInput" | "onSubmit" | "onChange"
|
|
34
|
+
> {
|
|
35
|
+
/**
|
|
36
|
+
* Blocks form submission when true. Textarea remains editable for drafts.
|
|
37
|
+
*/
|
|
38
|
+
disabled?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Placeholder text for the textarea input
|
|
41
|
+
*/
|
|
42
|
+
placeholder?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Controlled state value (when provided with onChange)
|
|
45
|
+
*/
|
|
46
|
+
value?: string;
|
|
47
|
+
/**
|
|
48
|
+
* Controlled state change handler (when provided with value)
|
|
49
|
+
*/
|
|
50
|
+
onChange?: (value: string) => void;
|
|
51
|
+
/**
|
|
52
|
+
* Submit handler called when form is submitted
|
|
53
|
+
*/
|
|
54
|
+
onSubmit: (
|
|
55
|
+
message: PromptInputMessage,
|
|
56
|
+
event: FormEvent<HTMLFormElement>
|
|
57
|
+
) => void | Promise<void>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* PromptInput component - text-only prompt input without attachments
|
|
62
|
+
*/
|
|
63
|
+
export const PromptInput = React.memo<PromptInputBlockProps>(
|
|
64
|
+
({
|
|
65
|
+
disabled = false,
|
|
66
|
+
placeholder,
|
|
67
|
+
value,
|
|
68
|
+
onChange,
|
|
69
|
+
onSubmit,
|
|
70
|
+
...props
|
|
71
|
+
}) => {
|
|
72
|
+
// Handle form submission with disabled state
|
|
73
|
+
const handleSubmit = React.useCallback(
|
|
74
|
+
(message: PromptInputMessage, event: FormEvent<HTMLFormElement>) => {
|
|
75
|
+
if (disabled) {
|
|
76
|
+
event.preventDefault();
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
onSubmit(message, event);
|
|
80
|
+
},
|
|
81
|
+
[disabled, onSubmit]
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
// Controlled mode: wrap in PromptInputProvider
|
|
85
|
+
const isControlled = value !== undefined && onChange !== undefined;
|
|
86
|
+
|
|
87
|
+
// Handle controlled state change
|
|
88
|
+
const handleControlledChange = React.useCallback(
|
|
89
|
+
(e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
90
|
+
if (onChange) {
|
|
91
|
+
onChange(e.target.value);
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
[onChange]
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
// Render the prompt input composition
|
|
98
|
+
const promptInputContent = (
|
|
99
|
+
<AIPromptInput onSubmit={handleSubmit} {...props}>
|
|
100
|
+
<PromptInputBody>
|
|
101
|
+
<PromptInputTextarea
|
|
102
|
+
placeholder={placeholder}
|
|
103
|
+
disabled={false} // Keep editable even when form is disabled
|
|
104
|
+
onChange={isControlled ? handleControlledChange : undefined}
|
|
105
|
+
/>
|
|
106
|
+
</PromptInputBody>
|
|
107
|
+
<PromptInputFooter>
|
|
108
|
+
<PromptInputTools>
|
|
109
|
+
{/* No attachment menu - compositionally hidden */}
|
|
110
|
+
</PromptInputTools>
|
|
111
|
+
<PromptInputSubmit disabled={disabled} />
|
|
112
|
+
</PromptInputFooter>
|
|
113
|
+
</AIPromptInput>
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
// Wrap in provider for controlled mode
|
|
117
|
+
if (isControlled) {
|
|
118
|
+
return (
|
|
119
|
+
<PromptInputProvider initialInput={value}>
|
|
120
|
+
{promptInputContent}
|
|
121
|
+
</PromptInputProvider>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return promptInputContent;
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
PromptInput.displayName = "PromptInput";
|