@iloveagents/foundry-web-ui 0.3.0 → 0.4.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 +14 -5
- package/dist/components/ag-ui-runtime-provider.d.ts +64 -0
- package/dist/components/ag-ui-runtime-provider.js +71 -0
- package/dist/components/app-brand.d.ts +6 -0
- package/dist/components/app-brand.js +13 -0
- package/dist/components/assistant-chat.d.ts +26 -0
- package/dist/components/assistant-chat.js +93 -0
- package/dist/components/chat-attachments.d.ts +25 -0
- package/dist/components/chat-attachments.js +20 -0
- package/dist/components/chat-bubble.d.ts +1 -0
- package/dist/components/chat-bubble.js +103 -0
- package/dist/components/chat-header.d.ts +2 -0
- package/dist/components/chat-header.js +16 -0
- package/dist/components/client-tool-executor.d.ts +12 -0
- package/dist/components/client-tool-executor.js +108 -0
- package/dist/components/collection-empty-state.d.ts +9 -0
- package/dist/components/collection-empty-state.js +6 -0
- package/dist/components/collection-filter-bar.d.ts +19 -0
- package/dist/components/collection-filter-bar.js +28 -0
- package/dist/components/collection-search-input.d.ts +6 -0
- package/dist/components/collection-search-input.js +8 -0
- package/dist/components/collection-skeleton.d.ts +6 -0
- package/dist/components/collection-skeleton.js +10 -0
- package/dist/components/collection-sort-menu.d.ts +10 -0
- package/dist/components/collection-sort-menu.js +9 -0
- package/dist/components/collection-surface.d.ts +8 -0
- package/dist/components/collection-surface.js +5 -0
- package/dist/components/collection-toolbar.d.ts +9 -0
- package/dist/components/collection-toolbar.js +5 -0
- package/dist/components/collection-view-toggle.d.ts +7 -0
- package/dist/components/collection-view-toggle.js +17 -0
- package/dist/components/composer-submit-bridge.d.ts +1 -0
- package/dist/components/composer-submit-bridge.js +15 -0
- package/dist/components/confirm-dialog.d.ts +11 -0
- package/dist/components/confirm-dialog.js +6 -0
- package/dist/components/confirmation-card.d.ts +14 -0
- package/dist/components/confirmation-card.js +12 -0
- package/dist/components/context-badges.d.ts +16 -0
- package/dist/components/context-badges.js +56 -0
- package/dist/components/context-bar.d.ts +41 -0
- package/dist/components/context-bar.js +123 -0
- package/dist/components/form-dialog.d.ts +12 -0
- package/dist/components/form-dialog.js +13 -0
- package/dist/components/global-selection-popover.d.ts +7 -0
- package/dist/components/global-selection-popover.js +167 -0
- package/dist/components/infinite-scroll-sentinel.d.ts +6 -0
- package/dist/components/infinite-scroll-sentinel.js +25 -0
- package/dist/components/json-viewer.d.ts +10 -0
- package/dist/components/json-viewer.js +80 -0
- package/dist/components/loading-indicator.d.ts +4 -0
- package/dist/components/loading-indicator.js +22 -0
- package/dist/components/markdown-text.d.ts +13 -0
- package/dist/components/markdown-text.js +221 -0
- package/dist/components/name-dialog.d.ts +16 -0
- package/dist/components/name-dialog.js +23 -0
- package/dist/components/selection-popover.d.ts +12 -0
- package/dist/components/selection-popover.js +111 -0
- package/dist/components/show-document-tool-ui.d.ts +1 -0
- package/dist/components/show-document-tool-ui.js +53 -0
- package/dist/components/sidebar.d.ts +4 -0
- package/dist/components/sidebar.js +904 -0
- package/dist/components/surface-card.d.ts +9 -0
- package/dist/components/surface-card.js +33 -0
- package/dist/components/theme-runtime-provider.d.ts +15 -0
- package/dist/components/theme-runtime-provider.js +48 -0
- package/dist/components/theme-toggle.d.ts +2 -0
- package/dist/components/theme-toggle.js +19 -0
- package/dist/components/tool-call-card.d.ts +27 -0
- package/dist/components/tool-call-card.js +13 -0
- package/dist/components/tool-fallback.d.ts +26 -0
- package/dist/components/tool-fallback.js +129 -0
- package/dist/components/tool-panel-layout.d.ts +10 -0
- package/dist/components/tool-panel-layout.js +12 -0
- package/dist/components/tool-panel.d.ts +1 -0
- package/dist/components/tool-panel.js +89 -0
- package/dist/components/tooltip-icon-button.d.ts +7 -0
- package/dist/components/tooltip-icon-button.js +9 -0
- package/dist/components/user-menu.d.ts +2 -0
- package/dist/components/user-menu.js +14 -0
- package/dist/index.d.ts +68 -0
- package/dist/index.js +83 -0
- package/dist/lib/ag-ui-adapter.d.ts +29 -0
- package/dist/lib/ag-ui-adapter.js +373 -0
- package/dist/lib/app-store.d.ts +115 -0
- package/dist/lib/app-store.js +199 -0
- package/dist/lib/attachment-adapter.d.ts +20 -0
- package/dist/lib/attachment-adapter.js +99 -0
- package/dist/lib/auth-provider.d.ts +16 -0
- package/dist/lib/auth-provider.js +88 -0
- package/dist/lib/chat-bubble-store.d.ts +30 -0
- package/dist/lib/chat-bubble-store.js +23 -0
- package/dist/lib/chat-lifecycle-store.d.ts +10 -0
- package/{src/lib/chat-lifecycle-store.ts → dist/lib/chat-lifecycle-store.js} +3 -13
- package/dist/lib/client-tools.d.ts +11 -0
- package/dist/lib/client-tools.js +274 -0
- package/dist/lib/composer-submit-store.d.ts +12 -0
- package/dist/lib/composer-submit-store.js +17 -0
- package/dist/lib/dev-store.d.ts +38 -0
- package/dist/lib/dev-store.js +32 -0
- package/dist/lib/nav-config.d.ts +159 -0
- package/dist/lib/nav-config.js +162 -0
- package/dist/lib/nav-dnd.d.ts +8 -0
- package/dist/lib/nav-dnd.js +9 -0
- package/dist/lib/nav-store.d.ts +45 -0
- package/dist/lib/nav-store.js +49 -0
- package/dist/lib/selection-context.d.ts +21 -0
- package/dist/lib/selection-context.js +34 -0
- package/dist/lib/sidebar-store.d.ts +23 -0
- package/dist/lib/sidebar-store.js +98 -0
- package/dist/lib/theme-runtime.d.ts +130 -0
- package/dist/lib/theme-runtime.js +479 -0
- package/dist/lib/theme-store.d.ts +15 -0
- package/dist/lib/theme-store.js +53 -0
- package/dist/lib/tool-panel-store.d.ts +48 -0
- package/dist/lib/tool-panel-store.js +69 -0
- package/dist/lib/use-new-conversation.d.ts +8 -0
- package/dist/lib/use-new-conversation.js +62 -0
- package/dist/lib/use-page-tools.d.ts +27 -0
- package/{src/lib/use-page-tools.ts → dist/lib/use-page-tools.js} +11 -13
- package/dist/styles.css +142 -0
- package/dist/ui/collapsible.d.ts +5 -0
- package/{src/ui/collapsible.tsx → dist/ui/collapsible.js} +0 -2
- package/dist/ui/dialog.d.ts +15 -0
- package/dist/ui/dialog.js +25 -0
- package/dist/ui/dropdown-menu.d.ts +7 -0
- package/dist/ui/dropdown-menu.js +19 -0
- package/dist/ui/popover.d.ts +7 -0
- package/dist/ui/popover.js +10 -0
- package/dist/ui/select.d.ts +4 -0
- package/dist/ui/select.js +9 -0
- package/dist/ui/tooltip.d.ts +7 -0
- package/dist/ui/tooltip.js +10 -0
- package/package.json +31 -12
- package/AGENTS.md +0 -59
- package/CHANGELOG.md +0 -203
- package/CLAUDE.md +0 -1
- package/src/__tests__/no-spaces-imports.test.ts +0 -59
- package/src/__tests__/open-core-guards.test.ts +0 -307
- package/src/__tests__/theme-runtime.test.ts +0 -81
- package/src/__tests__/tool-fallback.test.tsx +0 -109
- package/src/components/__tests__/context-bar.test.ts +0 -112
- package/src/components/ag-ui-runtime-provider.tsx +0 -170
- package/src/components/app-brand.tsx +0 -38
- package/src/components/assistant-chat.tsx +0 -461
- package/src/components/chat-attachments.tsx +0 -68
- package/src/components/chat-bubble.tsx +0 -373
- package/src/components/chat-header.tsx +0 -44
- package/src/components/client-tool-executor.tsx +0 -230
- package/src/components/collection-empty-state.tsx +0 -37
- package/src/components/collection-filter-bar.tsx +0 -168
- package/src/components/collection-search-input.tsx +0 -41
- package/src/components/collection-skeleton.tsx +0 -55
- package/src/components/collection-sort-menu.tsx +0 -62
- package/src/components/collection-surface.tsx +0 -46
- package/src/components/collection-toolbar.tsx +0 -33
- package/src/components/collection-view-toggle.tsx +0 -61
- package/src/components/composer-submit-bridge.tsx +0 -19
- package/src/components/confirm-dialog.tsx +0 -49
- package/src/components/confirmation-card.tsx +0 -32
- package/src/components/context-badges.tsx +0 -136
- package/src/components/context-bar.tsx +0 -238
- package/src/components/form-dialog.tsx +0 -56
- package/src/components/global-selection-popover.tsx +0 -266
- package/src/components/infinite-scroll-sentinel.tsx +0 -48
- package/src/components/json-viewer.tsx +0 -232
- package/src/components/loading-indicator.tsx +0 -40
- package/src/components/markdown-text-citations.test.tsx +0 -108
- package/src/components/markdown-text.tsx +0 -508
- package/src/components/name-dialog.tsx +0 -87
- package/src/components/selection-popover.tsx +0 -156
- package/src/components/show-document-tool-ui.tsx +0 -90
- package/src/components/sidebar.test.tsx +0 -611
- package/src/components/sidebar.tsx +0 -1689
- package/src/components/surface-card.tsx +0 -45
- package/src/components/theme-runtime-provider.tsx +0 -93
- package/src/components/theme-toggle.tsx +0 -27
- package/src/components/tool-call-card.tsx +0 -126
- package/src/components/tool-fallback.tsx +0 -169
- package/src/components/tool-panel-layout.tsx +0 -36
- package/src/components/tool-panel.tsx +0 -233
- package/src/components/tooltip-icon-button.tsx +0 -28
- package/src/components/user-menu.tsx +0 -60
- package/src/index.ts +0 -185
- package/src/lib/__tests__/ag-ui-adapter.test.ts +0 -273
- package/src/lib/__tests__/app-store.test.ts +0 -405
- package/src/lib/__tests__/attachment-adapter.test.ts +0 -48
- package/src/lib/__tests__/chat-bubble-store.test.ts +0 -67
- package/src/lib/__tests__/client-tools.test.ts +0 -124
- package/src/lib/__tests__/dev-store.test.ts +0 -78
- package/src/lib/__tests__/nav-config.test.ts +0 -135
- package/src/lib/__tests__/nav-dnd.test.ts +0 -24
- package/src/lib/__tests__/nav-store.test.ts +0 -59
- package/src/lib/__tests__/selection-context.test.ts +0 -114
- package/src/lib/__tests__/sidebar-store.test.ts +0 -144
- package/src/lib/__tests__/theme-store.test.ts +0 -83
- package/src/lib/__tests__/tool-panel-store.test.ts +0 -61
- package/src/lib/__tests__/use-page-context.test.ts +0 -58
- package/src/lib/ag-ui-adapter.ts +0 -412
- package/src/lib/app-store.ts +0 -361
- package/src/lib/attachment-adapter.ts +0 -92
- package/src/lib/auth-provider.tsx +0 -144
- package/src/lib/chat-bubble-store.ts +0 -46
- package/src/lib/client-tools.ts +0 -293
- package/src/lib/composer-submit-store.ts +0 -32
- package/src/lib/dev-store.ts +0 -69
- package/src/lib/nav-config.ts +0 -329
- package/src/lib/nav-dnd.ts +0 -14
- package/src/lib/nav-store.ts +0 -89
- package/src/lib/selection-context.ts +0 -65
- package/src/lib/sidebar-store.ts +0 -113
- package/src/lib/theme-runtime.ts +0 -660
- package/src/lib/theme-store.ts +0 -67
- package/src/lib/tool-panel-store.ts +0 -121
- package/src/lib/use-new-conversation.test.tsx +0 -168
- package/src/lib/use-new-conversation.ts +0 -64
- package/src/ui/dialog.tsx +0 -109
- package/src/ui/dropdown-menu.tsx +0 -75
- package/src/ui/popover.tsx +0 -34
- package/src/ui/select.tsx +0 -15
- package/src/ui/tooltip.tsx +0 -30
- package/src/vite-env.d.ts +0 -1
- package/tsconfig.json +0 -16
- package/vitest.config.ts +0 -8
|
@@ -1,461 +0,0 @@
|
|
|
1
|
-
import { type FC, useState, useRef, useCallback } from "react";
|
|
2
|
-
import {
|
|
3
|
-
ThreadPrimitive,
|
|
4
|
-
ComposerPrimitive,
|
|
5
|
-
MessagePrimitive,
|
|
6
|
-
ActionBarPrimitive,
|
|
7
|
-
BranchPickerPrimitive,
|
|
8
|
-
ErrorPrimitive,
|
|
9
|
-
useAuiState,
|
|
10
|
-
useComposerRuntime,
|
|
11
|
-
useThreadViewport,
|
|
12
|
-
} from "@assistant-ui/react";
|
|
13
|
-
import {
|
|
14
|
-
ArrowUp,
|
|
15
|
-
Copy,
|
|
16
|
-
Check,
|
|
17
|
-
RefreshCw,
|
|
18
|
-
PencilIcon,
|
|
19
|
-
ChevronLeft,
|
|
20
|
-
ChevronRight,
|
|
21
|
-
ChevronDown,
|
|
22
|
-
Square,
|
|
23
|
-
Bot,
|
|
24
|
-
Paperclip,
|
|
25
|
-
Minimize2,
|
|
26
|
-
PanelRightClose,
|
|
27
|
-
PanelRightOpen,
|
|
28
|
-
} from "lucide-react";
|
|
29
|
-
import { cn } from "@iloveagents/foundry-web-primitives";
|
|
30
|
-
import { Button } from "@iloveagents/foundry-web-primitives";
|
|
31
|
-
import { TooltipIconButton } from "./tooltip-icon-button.tsx";
|
|
32
|
-
import { userAttachmentComponents, composerAttachmentComponents } from "./chat-attachments.tsx";
|
|
33
|
-
import { SentContextBadges, ComposerContextBadges } from "./context-badges.tsx";
|
|
34
|
-
import { ContextPins } from "./context-bar.tsx";
|
|
35
|
-
import { ComposerSubmitBridge } from "./composer-submit-bridge.tsx";
|
|
36
|
-
import { useChatBubbleStore } from "../lib/chat-bubble-store.ts";
|
|
37
|
-
import { MarkdownText } from "./markdown-text.tsx";
|
|
38
|
-
import { ToolFallback } from "./tool-fallback.tsx";
|
|
39
|
-
import { LoadingIndicator, LoadingBar } from "./loading-indicator.tsx";
|
|
40
|
-
|
|
41
|
-
const BranchPicker: FC = () => (
|
|
42
|
-
<BranchPickerPrimitive.Root
|
|
43
|
-
hideWhenSingleBranch
|
|
44
|
-
className="inline-flex items-center gap-1 text-xs"
|
|
45
|
-
>
|
|
46
|
-
<BranchPickerPrimitive.Previous asChild>
|
|
47
|
-
<TooltipIconButton tooltip="Previous" size="icon">
|
|
48
|
-
<ChevronLeft className="size-4" />
|
|
49
|
-
</TooltipIconButton>
|
|
50
|
-
</BranchPickerPrimitive.Previous>
|
|
51
|
-
<span className="text-muted-foreground">
|
|
52
|
-
<BranchPickerPrimitive.Number /> / <BranchPickerPrimitive.Count />
|
|
53
|
-
</span>
|
|
54
|
-
<BranchPickerPrimitive.Next asChild>
|
|
55
|
-
<TooltipIconButton tooltip="Next" size="icon">
|
|
56
|
-
<ChevronRight className="size-4" />
|
|
57
|
-
</TooltipIconButton>
|
|
58
|
-
</BranchPickerPrimitive.Next>
|
|
59
|
-
</BranchPickerPrimitive.Root>
|
|
60
|
-
);
|
|
61
|
-
|
|
62
|
-
const UserMessage: FC = () => {
|
|
63
|
-
const messageId = useAuiState((s) => s.message.id);
|
|
64
|
-
|
|
65
|
-
return (
|
|
66
|
-
<MessagePrimitive.Root className="w-full mb-2 group">
|
|
67
|
-
<div className="flex flex-col items-end gap-1">
|
|
68
|
-
<MessagePrimitive.Attachments components={userAttachmentComponents} />
|
|
69
|
-
<SentContextBadges messageId={messageId} />
|
|
70
|
-
<div className={cn("max-w-[80%]", "bg-muted rounded-2xl", "px-4 py-3", "text-foreground")}>
|
|
71
|
-
<MessagePrimitive.Content />
|
|
72
|
-
</div>
|
|
73
|
-
<div className="flex items-center justify-end gap-2 pr-2">
|
|
74
|
-
<BranchPicker />
|
|
75
|
-
<div className="w-10 flex items-center justify-end">
|
|
76
|
-
<UserActionBar />
|
|
77
|
-
</div>
|
|
78
|
-
</div>
|
|
79
|
-
</div>
|
|
80
|
-
</MessagePrimitive.Root>
|
|
81
|
-
);
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const UserActionBar: FC = () => (
|
|
85
|
-
<ActionBarPrimitive.Root
|
|
86
|
-
hideWhenRunning
|
|
87
|
-
className="flex items-center opacity-0 group-hover:opacity-100 transition-opacity"
|
|
88
|
-
>
|
|
89
|
-
<ActionBarPrimitive.Edit asChild>
|
|
90
|
-
<TooltipIconButton tooltip="Edit" size="icon">
|
|
91
|
-
<PencilIcon className="size-4" />
|
|
92
|
-
</TooltipIconButton>
|
|
93
|
-
</ActionBarPrimitive.Edit>
|
|
94
|
-
</ActionBarPrimitive.Root>
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
const AssistantMessage: FC = () => (
|
|
98
|
-
<MessagePrimitive.Root className="w-full mb-2 group">
|
|
99
|
-
<div className="mx-auto max-w-3xl px-4">
|
|
100
|
-
<div className="text-foreground leading-relaxed flex flex-col gap-4">
|
|
101
|
-
<MessagePrimitive.Parts
|
|
102
|
-
components={{
|
|
103
|
-
Text: MarkdownText,
|
|
104
|
-
tools: { Fallback: ToolFallback },
|
|
105
|
-
}}
|
|
106
|
-
/>
|
|
107
|
-
</div>
|
|
108
|
-
<MessageError />
|
|
109
|
-
|
|
110
|
-
<div className="flex items-center gap-2 mt-1">
|
|
111
|
-
<div className="flex h-8 w-[4.25rem] items-center">
|
|
112
|
-
<AssistantActionBar />
|
|
113
|
-
</div>
|
|
114
|
-
<BranchPicker />
|
|
115
|
-
</div>
|
|
116
|
-
</div>
|
|
117
|
-
</MessagePrimitive.Root>
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
const AssistantActionBar: FC = () => (
|
|
121
|
-
<ActionBarPrimitive.Root
|
|
122
|
-
hideWhenRunning
|
|
123
|
-
className={cn(
|
|
124
|
-
"pointer-events-none flex items-center gap-1 -ml-2 opacity-0 transition-opacity",
|
|
125
|
-
"group-hover:pointer-events-auto group-hover:opacity-100",
|
|
126
|
-
"group-focus-within:pointer-events-auto group-focus-within:opacity-100",
|
|
127
|
-
)}
|
|
128
|
-
>
|
|
129
|
-
<ActionBarPrimitive.Copy asChild>
|
|
130
|
-
<TooltipIconButton tooltip="Copy" size="icon">
|
|
131
|
-
<MessagePrimitive.If copied={false}>
|
|
132
|
-
<Copy className="size-4" />
|
|
133
|
-
</MessagePrimitive.If>
|
|
134
|
-
<MessagePrimitive.If copied>
|
|
135
|
-
<Check className="size-4 text-primary" />
|
|
136
|
-
</MessagePrimitive.If>
|
|
137
|
-
</TooltipIconButton>
|
|
138
|
-
</ActionBarPrimitive.Copy>
|
|
139
|
-
<ActionBarPrimitive.Reload asChild>
|
|
140
|
-
<TooltipIconButton tooltip="Refresh" size="icon">
|
|
141
|
-
<RefreshCw className="size-4" />
|
|
142
|
-
</TooltipIconButton>
|
|
143
|
-
</ActionBarPrimitive.Reload>
|
|
144
|
-
</ActionBarPrimitive.Root>
|
|
145
|
-
);
|
|
146
|
-
|
|
147
|
-
const MessageError: FC = () => (
|
|
148
|
-
<MessagePrimitive.Error>
|
|
149
|
-
<ErrorPrimitive.Root className="mt-2 rounded-lg border border-destructive bg-destructive/10 p-3">
|
|
150
|
-
<div className="flex items-center gap-2">
|
|
151
|
-
<span className="text-sm font-medium text-destructive">Error:</span>
|
|
152
|
-
<ErrorPrimitive.Message className="text-sm text-destructive" />
|
|
153
|
-
</div>
|
|
154
|
-
</ErrorPrimitive.Root>
|
|
155
|
-
</MessagePrimitive.Error>
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
const EditComposer: FC = () => (
|
|
159
|
-
<MessagePrimitive.Root className="w-full mb-2">
|
|
160
|
-
<div className="flex items-start justify-end">
|
|
161
|
-
<div className="w-full max-w-[80%]">
|
|
162
|
-
<ComposerPrimitive.Root
|
|
163
|
-
className={cn(
|
|
164
|
-
"flex flex-col gap-2",
|
|
165
|
-
"rounded-2xl border border-input",
|
|
166
|
-
"bg-background shadow-sm",
|
|
167
|
-
"px-4 py-3",
|
|
168
|
-
)}
|
|
169
|
-
>
|
|
170
|
-
<ComposerPrimitive.Input
|
|
171
|
-
autoFocus
|
|
172
|
-
className={cn(
|
|
173
|
-
"w-full bg-transparent",
|
|
174
|
-
"text-base text-foreground",
|
|
175
|
-
"outline-none resize-none",
|
|
176
|
-
"placeholder:text-muted-foreground",
|
|
177
|
-
)}
|
|
178
|
-
/>
|
|
179
|
-
<div className="flex items-center justify-end gap-2">
|
|
180
|
-
<ComposerPrimitive.Cancel asChild>
|
|
181
|
-
<Button variant="ghost" size="sm">
|
|
182
|
-
Cancel
|
|
183
|
-
</Button>
|
|
184
|
-
</ComposerPrimitive.Cancel>
|
|
185
|
-
<ComposerPrimitive.Send asChild>
|
|
186
|
-
<Button size="sm">Update</Button>
|
|
187
|
-
</ComposerPrimitive.Send>
|
|
188
|
-
</div>
|
|
189
|
-
</ComposerPrimitive.Root>
|
|
190
|
-
</div>
|
|
191
|
-
</div>
|
|
192
|
-
</MessagePrimitive.Root>
|
|
193
|
-
);
|
|
194
|
-
|
|
195
|
-
const ComposerActionButton: FC = () => {
|
|
196
|
-
return (
|
|
197
|
-
<>
|
|
198
|
-
<ThreadPrimitive.If running>
|
|
199
|
-
<ComposerPrimitive.Cancel asChild>
|
|
200
|
-
<Button
|
|
201
|
-
variant="secondary"
|
|
202
|
-
size="icon"
|
|
203
|
-
className="rounded-full size-10 flex-shrink-0"
|
|
204
|
-
aria-label="Stop generating"
|
|
205
|
-
>
|
|
206
|
-
<Square className="size-4" />
|
|
207
|
-
</Button>
|
|
208
|
-
</ComposerPrimitive.Cancel>
|
|
209
|
-
</ThreadPrimitive.If>
|
|
210
|
-
|
|
211
|
-
<ThreadPrimitive.If running={false}>
|
|
212
|
-
<ComposerPrimitive.Send asChild>
|
|
213
|
-
<Button
|
|
214
|
-
size="icon"
|
|
215
|
-
className="rounded-full size-10 flex-shrink-0"
|
|
216
|
-
aria-label="Send message"
|
|
217
|
-
>
|
|
218
|
-
<ArrowUp className="size-5" />
|
|
219
|
-
</Button>
|
|
220
|
-
</ComposerPrimitive.Send>
|
|
221
|
-
</ThreadPrimitive.If>
|
|
222
|
-
</>
|
|
223
|
-
);
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Default starter prompts shown on empty state. Override per-app by passing
|
|
228
|
-
* a `starterSuggestions` prop to `<ChatContent>`. An empty array (`[]`)
|
|
229
|
-
* suppresses the suggestion buttons entirely.
|
|
230
|
-
*/
|
|
231
|
-
export const DEFAULT_STARTER_SUGGESTIONS = [
|
|
232
|
-
"Create a new Contract Space",
|
|
233
|
-
"List all contracts I have access to",
|
|
234
|
-
"Show me what I can do here",
|
|
235
|
-
];
|
|
236
|
-
|
|
237
|
-
const ScrollToBottomButton: FC = () => {
|
|
238
|
-
const isAtBottom = useThreadViewport((s) => s.isAtBottom);
|
|
239
|
-
const scrollToBottom = useThreadViewport((s) => s.scrollToBottom);
|
|
240
|
-
|
|
241
|
-
if (isAtBottom) return null;
|
|
242
|
-
|
|
243
|
-
return (
|
|
244
|
-
<Button
|
|
245
|
-
variant="outline"
|
|
246
|
-
size="icon"
|
|
247
|
-
className="absolute bottom-4 left-1/2 -translate-x-1/2 z-10 rounded-full shadow-md"
|
|
248
|
-
onClick={() => scrollToBottom({ behavior: "smooth" })}
|
|
249
|
-
>
|
|
250
|
-
<ChevronDown className="size-4" />
|
|
251
|
-
</Button>
|
|
252
|
-
);
|
|
253
|
-
};
|
|
254
|
-
|
|
255
|
-
const DropZone: FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
256
|
-
const [isDragging, setIsDragging] = useState(false);
|
|
257
|
-
const dragCounter = useRef(0);
|
|
258
|
-
const composerRuntime = useComposerRuntime();
|
|
259
|
-
|
|
260
|
-
const handleDragEnter = useCallback((e: React.DragEvent) => {
|
|
261
|
-
e.preventDefault();
|
|
262
|
-
dragCounter.current++;
|
|
263
|
-
if (dragCounter.current === 1) setIsDragging(true);
|
|
264
|
-
}, []);
|
|
265
|
-
|
|
266
|
-
const handleDragLeave = useCallback((e: React.DragEvent) => {
|
|
267
|
-
e.preventDefault();
|
|
268
|
-
dragCounter.current--;
|
|
269
|
-
if (dragCounter.current === 0) setIsDragging(false);
|
|
270
|
-
}, []);
|
|
271
|
-
|
|
272
|
-
const handleDragOver = useCallback((e: React.DragEvent) => {
|
|
273
|
-
e.preventDefault();
|
|
274
|
-
}, []);
|
|
275
|
-
|
|
276
|
-
const handleDrop = useCallback(
|
|
277
|
-
async (e: React.DragEvent) => {
|
|
278
|
-
e.preventDefault();
|
|
279
|
-
dragCounter.current = 0;
|
|
280
|
-
setIsDragging(false);
|
|
281
|
-
const files = Array.from(e.dataTransfer.files);
|
|
282
|
-
for (const file of files) {
|
|
283
|
-
await composerRuntime.addAttachment(file);
|
|
284
|
-
}
|
|
285
|
-
},
|
|
286
|
-
[composerRuntime],
|
|
287
|
-
);
|
|
288
|
-
|
|
289
|
-
return (
|
|
290
|
-
<div
|
|
291
|
-
className="relative flex flex-col flex-1 overflow-hidden"
|
|
292
|
-
onDragEnter={handleDragEnter}
|
|
293
|
-
onDragLeave={handleDragLeave}
|
|
294
|
-
onDragOver={handleDragOver}
|
|
295
|
-
onDrop={handleDrop}
|
|
296
|
-
>
|
|
297
|
-
{children}
|
|
298
|
-
{isDragging && (
|
|
299
|
-
<div
|
|
300
|
-
className={cn(
|
|
301
|
-
"absolute inset-0 z-50 flex items-center justify-center pointer-events-none",
|
|
302
|
-
"bg-background/80 backdrop-blur-sm",
|
|
303
|
-
"border-2 border-dashed border-primary rounded-xl",
|
|
304
|
-
)}
|
|
305
|
-
>
|
|
306
|
-
<p className="text-lg text-primary font-medium">Drop files here</p>
|
|
307
|
-
</div>
|
|
308
|
-
)}
|
|
309
|
-
</div>
|
|
310
|
-
);
|
|
311
|
-
};
|
|
312
|
-
|
|
313
|
-
export interface ChatContentProps {
|
|
314
|
-
/**
|
|
315
|
-
* Starter prompts shown when the thread is empty. Defaults to
|
|
316
|
-
* `DEFAULT_STARTER_SUGGESTIONS`. Pass an empty array to hide the
|
|
317
|
-
* suggestion buttons entirely. Customer apps (e.g. ANDRITZ Contracts)
|
|
318
|
-
* can pass a workspace-aware list derived from app context.
|
|
319
|
-
*/
|
|
320
|
-
starterSuggestions?: string[];
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
/**
|
|
324
|
-
* Reusable chat content — used by ChatPage and ChatBubble.
|
|
325
|
-
* Renders inside a ThreadPrimitive.Root context.
|
|
326
|
-
*/
|
|
327
|
-
export function ChatContent({
|
|
328
|
-
starterSuggestions = DEFAULT_STARTER_SUGGESTIONS,
|
|
329
|
-
}: ChatContentProps = {}) {
|
|
330
|
-
const isExpanded = useChatBubbleStore((s) => s.isExpanded);
|
|
331
|
-
const collapseChat = useChatBubbleStore((s) => s.collapse);
|
|
332
|
-
const showPagePanel = useChatBubbleStore((s) => s.showPagePanel);
|
|
333
|
-
const togglePagePanel = useChatBubbleStore((s) => s.togglePagePanel);
|
|
334
|
-
|
|
335
|
-
return (
|
|
336
|
-
<ThreadPrimitive.Root
|
|
337
|
-
className={cn("flex flex-col flex-1", "bg-background text-foreground", "overflow-hidden")}
|
|
338
|
-
>
|
|
339
|
-
{/* Collapse header — only in expanded layout mode */}
|
|
340
|
-
{isExpanded && (
|
|
341
|
-
<div className="shrink-0 flex items-center justify-between px-4 py-2 border-b border-border">
|
|
342
|
-
<span className="text-sm font-medium text-foreground flex items-center gap-2">
|
|
343
|
-
<Bot className="size-4 text-primary" />
|
|
344
|
-
Chat
|
|
345
|
-
</span>
|
|
346
|
-
<div className="flex items-center gap-1">
|
|
347
|
-
<TooltipIconButton
|
|
348
|
-
tooltip={showPagePanel ? "Hide page panel" : "Show page panel"}
|
|
349
|
-
size="icon"
|
|
350
|
-
onClick={togglePagePanel}
|
|
351
|
-
className="hidden xl:inline-flex"
|
|
352
|
-
>
|
|
353
|
-
{showPagePanel ? (
|
|
354
|
-
<PanelRightClose className="size-4" />
|
|
355
|
-
) : (
|
|
356
|
-
<PanelRightOpen className="size-4" />
|
|
357
|
-
)}
|
|
358
|
-
</TooltipIconButton>
|
|
359
|
-
<TooltipIconButton tooltip="Minimize to bubble" size="icon" onClick={collapseChat}>
|
|
360
|
-
<Minimize2 className="size-4" />
|
|
361
|
-
</TooltipIconButton>
|
|
362
|
-
</div>
|
|
363
|
-
</div>
|
|
364
|
-
)}
|
|
365
|
-
<DropZone>
|
|
366
|
-
<div className="relative flex-1 overflow-hidden">
|
|
367
|
-
<ThreadPrimitive.Viewport className="absolute inset-0 overflow-y-auto bg-background">
|
|
368
|
-
<ThreadPrimitive.Empty>
|
|
369
|
-
<div
|
|
370
|
-
className={cn("flex min-h-full flex-col", "items-center justify-center", "px-4")}
|
|
371
|
-
>
|
|
372
|
-
<Bot className="size-16 mb-6 text-primary/70" />
|
|
373
|
-
<h1 className="text-[2rem] font-normal text-foreground text-center mb-6">
|
|
374
|
-
How can I help you today?
|
|
375
|
-
</h1>
|
|
376
|
-
{starterSuggestions.length > 0 && (
|
|
377
|
-
<div className="flex flex-wrap justify-center gap-2 max-w-lg">
|
|
378
|
-
{starterSuggestions.map((prompt) => (
|
|
379
|
-
<ThreadPrimitive.Suggestion key={prompt} prompt={prompt} send asChild>
|
|
380
|
-
<Button variant="outline" className="text-sm">
|
|
381
|
-
{prompt}
|
|
382
|
-
</Button>
|
|
383
|
-
</ThreadPrimitive.Suggestion>
|
|
384
|
-
))}
|
|
385
|
-
</div>
|
|
386
|
-
)}
|
|
387
|
-
</div>
|
|
388
|
-
</ThreadPrimitive.Empty>
|
|
389
|
-
|
|
390
|
-
<ThreadPrimitive.If empty={false}>
|
|
391
|
-
<div className="mx-auto max-w-3xl px-4 pt-8">
|
|
392
|
-
<ThreadPrimitive.Messages
|
|
393
|
-
components={{
|
|
394
|
-
UserMessage,
|
|
395
|
-
EditComposer,
|
|
396
|
-
AssistantMessage,
|
|
397
|
-
}}
|
|
398
|
-
/>
|
|
399
|
-
<ThreadPrimitive.If running>
|
|
400
|
-
<LoadingIndicator />
|
|
401
|
-
</ThreadPrimitive.If>
|
|
402
|
-
</div>
|
|
403
|
-
</ThreadPrimitive.If>
|
|
404
|
-
</ThreadPrimitive.Viewport>
|
|
405
|
-
<ThreadPrimitive.If empty={false}>
|
|
406
|
-
<ScrollToBottomButton />
|
|
407
|
-
</ThreadPrimitive.If>
|
|
408
|
-
</div>
|
|
409
|
-
|
|
410
|
-
<div className="shrink-0 bg-background">
|
|
411
|
-
<ThreadPrimitive.If running={false}>
|
|
412
|
-
<div className="border-t border-border" />
|
|
413
|
-
</ThreadPrimitive.If>
|
|
414
|
-
<ThreadPrimitive.If running>
|
|
415
|
-
<LoadingBar />
|
|
416
|
-
</ThreadPrimitive.If>
|
|
417
|
-
|
|
418
|
-
<div className="mx-auto max-w-3xl px-4 py-4">
|
|
419
|
-
<ComposerPrimitive.Root
|
|
420
|
-
className={cn(
|
|
421
|
-
"flex flex-col gap-2",
|
|
422
|
-
"rounded-3xl border border-input",
|
|
423
|
-
"bg-background shadow-sm",
|
|
424
|
-
"px-4 py-2",
|
|
425
|
-
"focus-within:border-primary/50 focus-within:shadow-md",
|
|
426
|
-
"transition-all duration-300",
|
|
427
|
-
)}
|
|
428
|
-
>
|
|
429
|
-
<ComposerSubmitBridge />
|
|
430
|
-
<ComposerContextBadges />
|
|
431
|
-
<ComposerPrimitive.Attachments components={composerAttachmentComponents} />
|
|
432
|
-
<div className="flex items-center gap-2">
|
|
433
|
-
<div className="flex items-center -space-x-1 shrink-0">
|
|
434
|
-
<ComposerPrimitive.AddAttachment asChild>
|
|
435
|
-
<TooltipIconButton tooltip="Attach file" variant="ghost" className="shrink-0">
|
|
436
|
-
<Paperclip className="size-5" />
|
|
437
|
-
</TooltipIconButton>
|
|
438
|
-
</ComposerPrimitive.AddAttachment>
|
|
439
|
-
<ContextPins showPinButton />
|
|
440
|
-
</div>
|
|
441
|
-
<ComposerPrimitive.Input
|
|
442
|
-
autoFocus
|
|
443
|
-
placeholder="Message Assistant..."
|
|
444
|
-
rows={1}
|
|
445
|
-
className={cn(
|
|
446
|
-
"flex-1 bg-transparent",
|
|
447
|
-
"py-2 text-base",
|
|
448
|
-
"text-foreground outline-none",
|
|
449
|
-
"placeholder:text-muted-foreground",
|
|
450
|
-
"resize-none max-h-32",
|
|
451
|
-
)}
|
|
452
|
-
/>
|
|
453
|
-
<ComposerActionButton />
|
|
454
|
-
</div>
|
|
455
|
-
</ComposerPrimitive.Root>
|
|
456
|
-
</div>
|
|
457
|
-
</div>
|
|
458
|
-
</DropZone>
|
|
459
|
-
</ThreadPrimitive.Root>
|
|
460
|
-
);
|
|
461
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Attachment rendering components for chat messages and composer.
|
|
3
|
-
*
|
|
4
|
-
* Following the official assistant-ui pattern, attachment components
|
|
5
|
-
* live in a separate file from the main thread components.
|
|
6
|
-
*
|
|
7
|
-
* @see https://www.assistant-ui.com/ - assistant-ui Documentation
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { type FC } from "react";
|
|
11
|
-
import { AttachmentPrimitive } from "@assistant-ui/react";
|
|
12
|
-
import { FileText, X } from "lucide-react";
|
|
13
|
-
import { cn } from "@iloveagents/foundry-web-primitives";
|
|
14
|
-
|
|
15
|
-
/** Renders a pending file attachment chip in the composer with a remove button. */
|
|
16
|
-
export const ComposerAttachment: FC = () => (
|
|
17
|
-
<AttachmentPrimitive.Root
|
|
18
|
-
className={cn(
|
|
19
|
-
"inline-flex items-center gap-2 max-w-[250px]",
|
|
20
|
-
"rounded-lg border border-border bg-muted/50",
|
|
21
|
-
"px-3 py-2",
|
|
22
|
-
)}
|
|
23
|
-
>
|
|
24
|
-
<FileText className="size-4 text-muted-foreground flex-shrink-0" />
|
|
25
|
-
<span className="text-sm truncate">
|
|
26
|
-
<AttachmentPrimitive.Name />
|
|
27
|
-
</span>
|
|
28
|
-
<AttachmentPrimitive.Remove asChild>
|
|
29
|
-
<button
|
|
30
|
-
type="button"
|
|
31
|
-
className="p-0.5 rounded hover:bg-muted flex-shrink-0"
|
|
32
|
-
aria-label="Remove attachment"
|
|
33
|
-
>
|
|
34
|
-
<X className="size-3.5" />
|
|
35
|
-
</button>
|
|
36
|
-
</AttachmentPrimitive.Remove>
|
|
37
|
-
</AttachmentPrimitive.Root>
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
/** Renders a file badge on sent user messages. */
|
|
41
|
-
export const UserMessageAttachment: FC = () => (
|
|
42
|
-
<AttachmentPrimitive.Root
|
|
43
|
-
className={cn(
|
|
44
|
-
"inline-flex items-center gap-2 max-w-[250px]",
|
|
45
|
-
"rounded-lg border border-border/50 bg-muted/30",
|
|
46
|
-
"px-3 py-1.5",
|
|
47
|
-
)}
|
|
48
|
-
>
|
|
49
|
-
<FileText className="size-3.5 text-muted-foreground flex-shrink-0" />
|
|
50
|
-
<span className="text-xs truncate">
|
|
51
|
-
<AttachmentPrimitive.Name />
|
|
52
|
-
</span>
|
|
53
|
-
</AttachmentPrimitive.Root>
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
/** Component map for MessagePrimitive.Attachments on user messages. */
|
|
57
|
-
export const userAttachmentComponents = {
|
|
58
|
-
Document: UserMessageAttachment,
|
|
59
|
-
Image: UserMessageAttachment,
|
|
60
|
-
File: UserMessageAttachment,
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
/** Component map for ComposerPrimitive.Attachments in the composer. */
|
|
64
|
-
export const composerAttachmentComponents = {
|
|
65
|
-
Document: ComposerAttachment,
|
|
66
|
-
Image: ComposerAttachment,
|
|
67
|
-
File: ComposerAttachment,
|
|
68
|
-
};
|