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,119 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { Button } from "@/components/primitives/Button"
|
|
3
|
+
import {
|
|
4
|
+
Select,
|
|
5
|
+
SelectContent,
|
|
6
|
+
SelectItem,
|
|
7
|
+
SelectTrigger,
|
|
8
|
+
SelectValue,
|
|
9
|
+
} from "@/components/primitives/Select"
|
|
10
|
+
import { Label } from "@/components/primitives/Label"
|
|
11
|
+
import type { Table } from "@tanstack/react-table"
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* TablePagination Composite
|
|
15
|
+
*
|
|
16
|
+
* Reusable pagination controls for tables with TanStack Table integration.
|
|
17
|
+
* Composes Button, Select, and Label primitives.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* <TablePagination table={table} />
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export interface TablePaginationProps {
|
|
26
|
+
/**
|
|
27
|
+
* TanStack Table instance
|
|
28
|
+
*/
|
|
29
|
+
table: Table<any>
|
|
30
|
+
/**
|
|
31
|
+
* Available page size options
|
|
32
|
+
*/
|
|
33
|
+
pageSizeOptions?: number[]
|
|
34
|
+
/**
|
|
35
|
+
* Additional CSS classes
|
|
36
|
+
*/
|
|
37
|
+
className?: string
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* TablePagination component
|
|
42
|
+
*
|
|
43
|
+
* Provides pagination controls including page size selection and navigation buttons.
|
|
44
|
+
*/
|
|
45
|
+
export const TablePagination = React.memo<TablePaginationProps>(
|
|
46
|
+
({ table, pageSizeOptions = [10, 20, 30, 40, 50], className }) => {
|
|
47
|
+
return (
|
|
48
|
+
<div className={`flex items-center justify-between px-4 py-2 ${className || ""}`}>
|
|
49
|
+
<div className="text-sm text-muted-foreground">
|
|
50
|
+
{table.getFilteredSelectedRowModel().rows.length} of{" "}
|
|
51
|
+
{table.getFilteredRowModel().rows.length} row(s) selected
|
|
52
|
+
</div>
|
|
53
|
+
<div className="flex items-center gap-8">
|
|
54
|
+
<div className="flex items-center gap-2">
|
|
55
|
+
<Label htmlFor="rows-per-page" className="text-sm">
|
|
56
|
+
Rows per page
|
|
57
|
+
</Label>
|
|
58
|
+
<Select
|
|
59
|
+
value={`${table.getState().pagination.pageSize}`}
|
|
60
|
+
onValueChange={(value) => table.setPageSize(Number(value))}
|
|
61
|
+
>
|
|
62
|
+
<SelectTrigger id="rows-per-page" className="h-8 w-[70px]">
|
|
63
|
+
<SelectValue placeholder={table.getState().pagination.pageSize} />
|
|
64
|
+
</SelectTrigger>
|
|
65
|
+
<SelectContent side="top">
|
|
66
|
+
{pageSizeOptions.map((pageSize) => (
|
|
67
|
+
<SelectItem key={pageSize} value={`${pageSize}`}>
|
|
68
|
+
{pageSize}
|
|
69
|
+
</SelectItem>
|
|
70
|
+
))}
|
|
71
|
+
</SelectContent>
|
|
72
|
+
</Select>
|
|
73
|
+
</div>
|
|
74
|
+
<div className="flex items-center gap-2">
|
|
75
|
+
<div className="text-sm font-medium">
|
|
76
|
+
Page {table.getState().pagination.pageIndex + 1} of {table.getPageCount()}
|
|
77
|
+
</div>
|
|
78
|
+
<div className="flex items-center gap-1">
|
|
79
|
+
<Button
|
|
80
|
+
variant="outline"
|
|
81
|
+
size="sm"
|
|
82
|
+
onClick={() => table.setPageIndex(0)}
|
|
83
|
+
disabled={!table.getCanPreviousPage()}
|
|
84
|
+
>
|
|
85
|
+
First
|
|
86
|
+
</Button>
|
|
87
|
+
<Button
|
|
88
|
+
variant="outline"
|
|
89
|
+
size="sm"
|
|
90
|
+
onClick={() => table.previousPage()}
|
|
91
|
+
disabled={!table.getCanPreviousPage()}
|
|
92
|
+
>
|
|
93
|
+
Previous
|
|
94
|
+
</Button>
|
|
95
|
+
<Button
|
|
96
|
+
variant="outline"
|
|
97
|
+
size="sm"
|
|
98
|
+
onClick={() => table.nextPage()}
|
|
99
|
+
disabled={!table.getCanNextPage()}
|
|
100
|
+
>
|
|
101
|
+
Next
|
|
102
|
+
</Button>
|
|
103
|
+
<Button
|
|
104
|
+
variant="outline"
|
|
105
|
+
size="sm"
|
|
106
|
+
onClick={() => table.setPageIndex(table.getPageCount() - 1)}
|
|
107
|
+
disabled={!table.getCanNextPage()}
|
|
108
|
+
>
|
|
109
|
+
Last
|
|
110
|
+
</Button>
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
TablePagination.displayName = "TablePagination"
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import { TableToolbar } from './TableToolbar'
|
|
3
|
+
import { useReactTable, getCoreRowModel, getFilteredRowModel, createColumnHelper } from '@tanstack/react-table'
|
|
4
|
+
import { Button } from '@/components/primitives/Button'
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Composites/TableToolbar',
|
|
8
|
+
component: TableToolbar,
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
parameters: { layout: 'padded' },
|
|
11
|
+
} satisfies Meta<typeof TableToolbar>
|
|
12
|
+
|
|
13
|
+
export default meta
|
|
14
|
+
type Story = StoryObj<typeof meta>
|
|
15
|
+
|
|
16
|
+
type Person = { id: number; name: string; email: string }
|
|
17
|
+
const data: Person[] = [{ id: 1, name: 'John', email: 'john@example.com' }]
|
|
18
|
+
const columnHelper = createColumnHelper<Person>()
|
|
19
|
+
|
|
20
|
+
export const Default: Story = {
|
|
21
|
+
render: () => {
|
|
22
|
+
const columns = [
|
|
23
|
+
columnHelper.accessor('name', { header: 'Name' }),
|
|
24
|
+
columnHelper.accessor('email', { header: 'Email' }),
|
|
25
|
+
]
|
|
26
|
+
const table = useReactTable({
|
|
27
|
+
data,
|
|
28
|
+
columns,
|
|
29
|
+
getCoreRowModel: getCoreRowModel(),
|
|
30
|
+
getFilteredRowModel: getFilteredRowModel(),
|
|
31
|
+
})
|
|
32
|
+
return <TableToolbar table={table} searchColumn="name" />
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const WithActions: Story = {
|
|
37
|
+
render: () => {
|
|
38
|
+
const columns = [
|
|
39
|
+
columnHelper.accessor('name', { header: 'Name' }),
|
|
40
|
+
columnHelper.accessor('email', { header: 'Email' }),
|
|
41
|
+
]
|
|
42
|
+
const table = useReactTable({
|
|
43
|
+
data,
|
|
44
|
+
columns,
|
|
45
|
+
getCoreRowModel: getCoreRowModel(),
|
|
46
|
+
getFilteredRowModel: getFilteredRowModel(),
|
|
47
|
+
})
|
|
48
|
+
return (
|
|
49
|
+
<TableToolbar
|
|
50
|
+
table={table}
|
|
51
|
+
searchColumn="name"
|
|
52
|
+
actions={
|
|
53
|
+
<Button size="sm" variant="default">
|
|
54
|
+
Add New
|
|
55
|
+
</Button>
|
|
56
|
+
}
|
|
57
|
+
/>
|
|
58
|
+
)
|
|
59
|
+
},
|
|
60
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { Input } from "@/components/primitives/Input"
|
|
3
|
+
import { Button } from "@/components/primitives/Button"
|
|
4
|
+
import {
|
|
5
|
+
DropdownMenu,
|
|
6
|
+
DropdownMenuCheckboxItem,
|
|
7
|
+
DropdownMenuContent,
|
|
8
|
+
DropdownMenuTrigger,
|
|
9
|
+
} from "@/components/primitives/DropdownMenu"
|
|
10
|
+
import { Icon } from "@/components/primitives/Icon"
|
|
11
|
+
import type { Table } from "@tanstack/react-table"
|
|
12
|
+
|
|
13
|
+
export interface TableToolbarProps {
|
|
14
|
+
table: Table<any>
|
|
15
|
+
searchPlaceholder?: string
|
|
16
|
+
searchColumn?: string
|
|
17
|
+
actions?: React.ReactNode
|
|
18
|
+
className?: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const TableToolbar = React.memo<TableToolbarProps>(
|
|
22
|
+
({ table, searchPlaceholder = "Search...", searchColumn, actions, className }) => {
|
|
23
|
+
return (
|
|
24
|
+
<div className={`flex items-center justify-between px-4 py-2 ${className || ""}`}>
|
|
25
|
+
<div className="flex flex-1 items-center gap-2">
|
|
26
|
+
<Input
|
|
27
|
+
placeholder={searchPlaceholder}
|
|
28
|
+
value={(searchColumn && (table.getColumn(searchColumn)?.getFilterValue() as string)) ?? ""}
|
|
29
|
+
onChange={(e) => searchColumn && table.getColumn(searchColumn)?.setFilterValue(e.target.value)}
|
|
30
|
+
className="h-8 w-[150px] lg:w-[250px]"
|
|
31
|
+
/>
|
|
32
|
+
</div>
|
|
33
|
+
<div className="flex items-center gap-2">
|
|
34
|
+
<DropdownMenu>
|
|
35
|
+
<DropdownMenuTrigger asChild>
|
|
36
|
+
<Button variant="outline" size="sm" className="ml-auto">
|
|
37
|
+
<Icon name="settings-2" className="mr-2 h-4 w-4" />
|
|
38
|
+
Columns
|
|
39
|
+
</Button>
|
|
40
|
+
</DropdownMenuTrigger>
|
|
41
|
+
<DropdownMenuContent align="end">
|
|
42
|
+
{table
|
|
43
|
+
.getAllColumns()
|
|
44
|
+
.filter((column) => column.getCanHide())
|
|
45
|
+
.map((column) => {
|
|
46
|
+
return (
|
|
47
|
+
<DropdownMenuCheckboxItem
|
|
48
|
+
key={column.id}
|
|
49
|
+
className="capitalize"
|
|
50
|
+
checked={column.getIsVisible()}
|
|
51
|
+
onCheckedChange={(value) => column.toggleVisibility(!!value)}
|
|
52
|
+
>
|
|
53
|
+
{column.id}
|
|
54
|
+
</DropdownMenuCheckboxItem>
|
|
55
|
+
)
|
|
56
|
+
})}
|
|
57
|
+
</DropdownMenuContent>
|
|
58
|
+
</DropdownMenu>
|
|
59
|
+
{actions}
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
TableToolbar.displayName = "TableToolbar"
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import { ThemeSelector } from './ThemeSelector'
|
|
3
|
+
import { useState } from 'react'
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'Composites/ThemeSelector',
|
|
7
|
+
component: ThemeSelector,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: 'centered',
|
|
11
|
+
},
|
|
12
|
+
} satisfies Meta<typeof ThemeSelector>
|
|
13
|
+
|
|
14
|
+
export default meta
|
|
15
|
+
type Story = StoryObj<typeof meta>
|
|
16
|
+
|
|
17
|
+
const themes = [
|
|
18
|
+
{ label: 'Default', value: 'default' },
|
|
19
|
+
{ label: 'Ocean', value: 'ocean' },
|
|
20
|
+
{ label: 'Forest', value: 'forest' },
|
|
21
|
+
{ label: 'Sunset', value: 'sunset' },
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
export const Default: Story = {
|
|
25
|
+
args: {
|
|
26
|
+
themes,
|
|
27
|
+
placeholder: 'Select theme',
|
|
28
|
+
},
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const WithValue: Story = {
|
|
32
|
+
args: {
|
|
33
|
+
themes,
|
|
34
|
+
value: 'ocean',
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const Interactive: Story = {
|
|
39
|
+
render: () => {
|
|
40
|
+
const [value, setValue] = useState('default')
|
|
41
|
+
return (
|
|
42
|
+
<div style={{ minWidth: '200px' }}>
|
|
43
|
+
<ThemeSelector themes={themes} value={value} onValueChange={setValue} />
|
|
44
|
+
<p style={{ marginTop: '16px', fontSize: '14px' }}>Selected: {value}</p>
|
|
45
|
+
</div>
|
|
46
|
+
)
|
|
47
|
+
},
|
|
48
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import {
|
|
3
|
+
Select,
|
|
4
|
+
SelectContent,
|
|
5
|
+
SelectItem,
|
|
6
|
+
SelectTrigger,
|
|
7
|
+
SelectValue,
|
|
8
|
+
} from "@/components/primitives/Select"
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* ThemeSelector Composite
|
|
12
|
+
*
|
|
13
|
+
* A theme variant selector component that allows users to choose from multiple theme options.
|
|
14
|
+
* Composes Select primitive.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* const themes = [
|
|
19
|
+
* { label: "Default", value: "default" },
|
|
20
|
+
* { label: "Ocean", value: "ocean" },
|
|
21
|
+
* { label: "Forest", value: "forest" },
|
|
22
|
+
* ]
|
|
23
|
+
* <ThemeSelector themes={themes} value="default" onValueChange={setTheme} />
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
export interface Theme {
|
|
28
|
+
label: string
|
|
29
|
+
value: string
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface ThemeSelectorProps {
|
|
33
|
+
/**
|
|
34
|
+
* Available theme options
|
|
35
|
+
*/
|
|
36
|
+
themes: Theme[]
|
|
37
|
+
/**
|
|
38
|
+
* Currently selected theme value
|
|
39
|
+
*/
|
|
40
|
+
value?: string
|
|
41
|
+
/**
|
|
42
|
+
* Callback when theme selection changes
|
|
43
|
+
*/
|
|
44
|
+
onValueChange?: (value: string) => void
|
|
45
|
+
/**
|
|
46
|
+
* Placeholder text when no theme is selected
|
|
47
|
+
*/
|
|
48
|
+
placeholder?: string
|
|
49
|
+
/**
|
|
50
|
+
* Additional CSS classes
|
|
51
|
+
*/
|
|
52
|
+
className?: string
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* ThemeSelector component
|
|
57
|
+
*
|
|
58
|
+
* Provides a select dropdown to choose from multiple theme variants.
|
|
59
|
+
*/
|
|
60
|
+
export const ThemeSelector = React.memo<ThemeSelectorProps>(
|
|
61
|
+
({ themes, value, onValueChange, placeholder = "Select theme", className }) => {
|
|
62
|
+
return (
|
|
63
|
+
<Select value={value} onValueChange={onValueChange}>
|
|
64
|
+
<SelectTrigger className={className}>
|
|
65
|
+
<SelectValue placeholder={placeholder} />
|
|
66
|
+
</SelectTrigger>
|
|
67
|
+
<SelectContent>
|
|
68
|
+
{themes.map((theme) => (
|
|
69
|
+
<SelectItem key={theme.value} value={theme.value}>
|
|
70
|
+
{theme.label}
|
|
71
|
+
</SelectItem>
|
|
72
|
+
))}
|
|
73
|
+
</SelectContent>
|
|
74
|
+
</Select>
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
ThemeSelector.displayName = "ThemeSelector"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import { ToolCallDisplay } from './ToolCallDisplay'
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof ToolCallDisplay> = {
|
|
5
|
+
title: 'Composites/ToolCallDisplay',
|
|
6
|
+
component: ToolCallDisplay,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'padded',
|
|
9
|
+
},
|
|
10
|
+
} satisfies Meta<typeof ToolCallDisplay>
|
|
11
|
+
|
|
12
|
+
export default meta
|
|
13
|
+
type Story = StoryObj<typeof meta>
|
|
14
|
+
|
|
15
|
+
export const Default: Story = {
|
|
16
|
+
args: {
|
|
17
|
+
toolCall: {
|
|
18
|
+
id: 'tool_1',
|
|
19
|
+
name: 'write_file',
|
|
20
|
+
args: { filename: 'research.md', content: 'Research content here...' },
|
|
21
|
+
result: 'File created successfully',
|
|
22
|
+
status: 'completed',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const Pending: Story = {
|
|
28
|
+
args: {
|
|
29
|
+
toolCall: {
|
|
30
|
+
id: 'tool_2',
|
|
31
|
+
name: 'analyze_data',
|
|
32
|
+
args: { dataset: 'user_metrics', filters: ['active_users', 'retention'] },
|
|
33
|
+
result: null,
|
|
34
|
+
status: 'pending',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const Error: Story = {
|
|
40
|
+
args: {
|
|
41
|
+
toolCall: {
|
|
42
|
+
id: 'tool_3',
|
|
43
|
+
name: 'fetch_data',
|
|
44
|
+
args: { url: 'https://api.example.com/data' },
|
|
45
|
+
result: 'Connection timeout after 30 seconds',
|
|
46
|
+
status: 'error',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import {
|
|
3
|
+
Tool,
|
|
4
|
+
ToolHeader,
|
|
5
|
+
ToolContent,
|
|
6
|
+
ToolInput,
|
|
7
|
+
ToolOutput,
|
|
8
|
+
} from "@/components/ai-elements/tool"
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* ToolCallDisplay Block
|
|
12
|
+
*
|
|
13
|
+
* A block component that extends the Tool AI element to display tool execution details
|
|
14
|
+
* with expandable input parameters and output results. Copied logic from reference implementation.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export interface ToolCall {
|
|
18
|
+
id: string
|
|
19
|
+
name: string
|
|
20
|
+
args: Record<string, unknown>
|
|
21
|
+
result?: string
|
|
22
|
+
status: "pending" | "completed" | "error"
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface ToolCallDisplayProps {
|
|
26
|
+
/**
|
|
27
|
+
* Tool call data to display
|
|
28
|
+
*/
|
|
29
|
+
toolCall: ToolCall
|
|
30
|
+
/**
|
|
31
|
+
* Whether the tool call is initially expanded
|
|
32
|
+
*/
|
|
33
|
+
defaultExpanded?: boolean
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* ToolCallDisplay component - displays tool execution with expandable details
|
|
38
|
+
*/
|
|
39
|
+
export const ToolCallDisplay = React.memo<ToolCallDisplayProps>(
|
|
40
|
+
({ toolCall, defaultExpanded = false }) => {
|
|
41
|
+
const [isExpanded, setIsExpanded] = React.useState(defaultExpanded)
|
|
42
|
+
|
|
43
|
+
const { name, args, result, status } = React.useMemo(() => {
|
|
44
|
+
const toolName = toolCall.name || "Unknown Tool"
|
|
45
|
+
const toolArgs = toolCall.args || {}
|
|
46
|
+
let parsedArgs: Record<string, unknown> = {}
|
|
47
|
+
try {
|
|
48
|
+
parsedArgs = typeof toolArgs === "string" ? JSON.parse(toolArgs) : toolArgs
|
|
49
|
+
} catch {
|
|
50
|
+
parsedArgs = { raw: toolArgs }
|
|
51
|
+
}
|
|
52
|
+
const toolResult = toolCall.result || null
|
|
53
|
+
const toolStatus = toolCall.status || "completed"
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
name: toolName,
|
|
57
|
+
args: parsedArgs,
|
|
58
|
+
result: toolResult,
|
|
59
|
+
status: toolStatus,
|
|
60
|
+
}
|
|
61
|
+
}, [toolCall])
|
|
62
|
+
|
|
63
|
+
const toggleExpanded = React.useCallback(() => {
|
|
64
|
+
setIsExpanded((prev) => !prev)
|
|
65
|
+
}, [])
|
|
66
|
+
|
|
67
|
+
const hasContent = React.useMemo(() => {
|
|
68
|
+
return result !== null || Object.keys(args).length > 0
|
|
69
|
+
}, [result, args])
|
|
70
|
+
|
|
71
|
+
// Map our status to Tool AI element status
|
|
72
|
+
const toolState = React.useMemo(() => {
|
|
73
|
+
switch (status) {
|
|
74
|
+
case "pending":
|
|
75
|
+
return "input-available" as const
|
|
76
|
+
case "completed":
|
|
77
|
+
return "output-available" as const
|
|
78
|
+
case "error":
|
|
79
|
+
return "output-error" as const
|
|
80
|
+
default:
|
|
81
|
+
return "output-available" as const
|
|
82
|
+
}
|
|
83
|
+
}, [status])
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<Tool defaultOpen={isExpanded}>
|
|
87
|
+
<ToolHeader
|
|
88
|
+
title={name}
|
|
89
|
+
type={`tool-${name}` as const}
|
|
90
|
+
state={toolState}
|
|
91
|
+
/>
|
|
92
|
+
<ToolContent>
|
|
93
|
+
{Object.keys(args).length > 0 && (
|
|
94
|
+
<ToolInput input={args} />
|
|
95
|
+
)}
|
|
96
|
+
{result && (
|
|
97
|
+
<ToolOutput
|
|
98
|
+
output={result}
|
|
99
|
+
errorText={status === "error" ? result : undefined}
|
|
100
|
+
/>
|
|
101
|
+
)}
|
|
102
|
+
</ToolContent>
|
|
103
|
+
</Tool>
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
ToolCallDisplay.displayName = "ToolCallDisplay"
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import { UserMessage } from './UserMessage'
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof UserMessage> = {
|
|
5
|
+
title: 'Composites/UserMessage',
|
|
6
|
+
component: UserMessage,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'padded',
|
|
9
|
+
},
|
|
10
|
+
} satisfies Meta<typeof UserMessage>
|
|
11
|
+
|
|
12
|
+
export default meta
|
|
13
|
+
type Story = StoryObj<typeof meta>
|
|
14
|
+
|
|
15
|
+
export const Default: Story = {
|
|
16
|
+
args: {
|
|
17
|
+
message: {
|
|
18
|
+
id: '1',
|
|
19
|
+
content: 'Hello, I need help with something',
|
|
20
|
+
avatarSrc: 'https://images.unsplash.com/photo-1494790108755-2616b612b786?w=32&h=32&fit=crop&crop=face',
|
|
21
|
+
avatarName: 'User',
|
|
22
|
+
},
|
|
23
|
+
showAvatar: true,
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const WithoutAvatar: Story = {
|
|
28
|
+
args: {
|
|
29
|
+
message: {
|
|
30
|
+
id: '2',
|
|
31
|
+
content: 'This is a user message without an avatar',
|
|
32
|
+
},
|
|
33
|
+
showAvatar: false,
|
|
34
|
+
},
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const LongMessage: Story = {
|
|
38
|
+
args: {
|
|
39
|
+
message: {
|
|
40
|
+
id: '3',
|
|
41
|
+
content: 'This is a much longer user message that contains multiple sentences. It demonstrates how the component handles longer text content and how it wraps appropriately within the message bubble. The text should remain readable and properly formatted even when it spans multiple lines.',
|
|
42
|
+
avatarSrc: 'https://images.unsplash.com/photo-1494790108755-2616b612b786?w=32&h=32&fit=crop&crop=face',
|
|
43
|
+
avatarName: 'User',
|
|
44
|
+
},
|
|
45
|
+
showAvatar: true,
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const ShortQuestion: Story = {
|
|
50
|
+
args: {
|
|
51
|
+
message: {
|
|
52
|
+
id: '4',
|
|
53
|
+
content: 'Why?',
|
|
54
|
+
avatarSrc: 'https://images.unsplash.com/photo-1494790108755-2616b612b786?w=32&h=32&fit=crop&crop=face',
|
|
55
|
+
avatarName: 'User',
|
|
56
|
+
},
|
|
57
|
+
showAvatar: true,
|
|
58
|
+
},
|
|
59
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import {
|
|
3
|
+
Message,
|
|
4
|
+
MessageContent,
|
|
5
|
+
MessageAvatar,
|
|
6
|
+
} from "@/components/ai-elements/message"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* UserMessage Block
|
|
10
|
+
*
|
|
11
|
+
* A simple block component for displaying user messages.
|
|
12
|
+
* Uses Message AI element with right-alignment.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export interface UserMessageData {
|
|
16
|
+
id: string
|
|
17
|
+
content: string
|
|
18
|
+
avatarSrc?: string
|
|
19
|
+
avatarName?: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface UserMessageProps {
|
|
23
|
+
/**
|
|
24
|
+
* User message data to display
|
|
25
|
+
*/
|
|
26
|
+
message: UserMessageData
|
|
27
|
+
/**
|
|
28
|
+
* Whether to show avatar
|
|
29
|
+
*/
|
|
30
|
+
showAvatar?: boolean
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* UserMessage component - displays user messages with right alignment
|
|
35
|
+
*/
|
|
36
|
+
export const UserMessage = React.memo<UserMessageProps>(
|
|
37
|
+
({ message, showAvatar = true }) => {
|
|
38
|
+
return (
|
|
39
|
+
<Message from="user">
|
|
40
|
+
{showAvatar && (
|
|
41
|
+
<MessageAvatar
|
|
42
|
+
src={message.avatarSrc || "/user-avatar.png"}
|
|
43
|
+
name={message.avatarName || "User"}
|
|
44
|
+
/>
|
|
45
|
+
)}
|
|
46
|
+
<MessageContent variant="contained">{message.content}</MessageContent>
|
|
47
|
+
</Message>
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
UserMessage.displayName = "UserMessage"
|