@assistant-ui/react 0.7.44 → 0.7.46
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/runtimes/remote-thread-list/OptimisticState.d.ts +1 -1
- package/dist/runtimes/remote-thread-list/OptimisticState.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/OptimisticState.js +7 -5
- package/dist/runtimes/remote-thread-list/OptimisticState.js.map +1 -1
- package/dist/runtimes/remote-thread-list/OptimisticState.mjs +7 -5
- package/dist/runtimes/remote-thread-list/OptimisticState.mjs.map +1 -1
- package/dist/runtimes/remote-thread-list/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/RemoteThreadListHookInstanceManager.js +9 -1
- package/dist/runtimes/remote-thread-list/RemoteThreadListHookInstanceManager.js.map +1 -1
- package/dist/runtimes/remote-thread-list/RemoteThreadListHookInstanceManager.mjs +13 -2
- package/dist/runtimes/remote-thread-list/RemoteThreadListHookInstanceManager.mjs.map +1 -1
- package/dist/runtimes/remote-thread-list/RemoteThreadListThreadListRuntimeCore.d.ts +10 -2
- package/dist/runtimes/remote-thread-list/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/RemoteThreadListThreadListRuntimeCore.js +35 -9
- package/dist/runtimes/remote-thread-list/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
- package/dist/runtimes/remote-thread-list/RemoteThreadListThreadListRuntimeCore.mjs +35 -9
- package/dist/runtimes/remote-thread-list/RemoteThreadListThreadListRuntimeCore.mjs.map +1 -1
- package/dist/ui/assistant-message.d.ts.map +1 -1
- package/dist/ui/assistant-message.js +14 -10
- package/dist/ui/assistant-message.js.map +1 -1
- package/dist/ui/assistant-message.mjs +14 -10
- package/dist/ui/assistant-message.mjs.map +1 -1
- package/dist/ui/thread-config.d.ts +2 -0
- package/dist/ui/thread-config.d.ts.map +1 -1
- package/dist/ui/thread-config.js.map +1 -1
- package/dist/ui/thread-config.mjs.map +1 -1
- package/dist/ui/thread.d.ts +2 -1
- package/dist/ui/thread.d.ts.map +1 -1
- package/dist/ui/thread.js +15 -2
- package/dist/ui/thread.js.map +1 -1
- package/dist/ui/thread.mjs +15 -2
- package/dist/ui/thread.mjs.map +1 -1
- package/package.json +3 -3
- package/src/runtimes/remote-thread-list/OptimisticState.ts +15 -8
- package/src/runtimes/remote-thread-list/RemoteThreadListHookInstanceManager.tsx +15 -2
- package/src/runtimes/remote-thread-list/RemoteThreadListThreadListRuntimeCore.tsx +47 -9
- package/src/ui/assistant-message.tsx +2 -0
- package/src/ui/thread-config.tsx +2 -0
- package/src/ui/thread.tsx +14 -3
package/dist/ui/thread.mjs.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/ui/thread.tsx"],"sourcesContent":["\"use client\";\n\nimport { forwardRef, type FC } from \"react\";\nimport { ArrowDownIcon } from \"lucide-react\";\n\nimport { withDefaults } from \"./utils/withDefaults\";\nimport Composer from \"./composer\";\nimport ThreadWelcome from \"./thread-welcome\";\nimport { TooltipIconButton } from \"./base/tooltip-icon-button\";\nimport AssistantMessage from \"./assistant-message\";\nimport UserMessage from \"./user-message\";\nimport EditComposer from \"./edit-composer\";\nimport {\n ThreadConfig,\n ThreadConfigProvider,\n ThreadConfigProviderProps,\n useThreadConfig,\n} from \"./thread-config\";\nimport { ThreadPrimitive } from \"../primitives\";\nimport { useThread } from \"../context\";\n\nconst Thread: FC<ThreadConfig> = (config) => {\n const {\n components: {\n Composer: ComposerComponent = Composer,\n ThreadWelcome: ThreadWelcomeComponent = ThreadWelcome,\n ...messageComponents\n } = {},\n } = config;\n return (\n <ThreadRoot config={config}>\n <ThreadViewport>\n <ThreadWelcomeComponent />\n <ThreadMessages
|
1
|
+
{"version":3,"sources":["../../src/ui/thread.tsx"],"sourcesContent":["\"use client\";\n\nimport { ComponentType, forwardRef, type FC } from \"react\";\nimport { ArrowDownIcon } from \"lucide-react\";\n\nimport { withDefaults } from \"./utils/withDefaults\";\nimport Composer from \"./composer\";\nimport ThreadWelcome from \"./thread-welcome\";\nimport { TooltipIconButton } from \"./base/tooltip-icon-button\";\nimport AssistantMessage from \"./assistant-message\";\nimport UserMessage from \"./user-message\";\nimport EditComposer from \"./edit-composer\";\nimport {\n ThreadConfig,\n ThreadConfigProvider,\n ThreadConfigProviderProps,\n useThreadConfig,\n} from \"./thread-config\";\nimport { ThreadPrimitive } from \"../primitives\";\nimport { useThread } from \"../context\";\n\nconst Thread: FC<ThreadConfig> = (config) => {\n const {\n components: {\n Composer: ComposerComponent = Composer,\n ThreadWelcome: ThreadWelcomeComponent = ThreadWelcome,\n MessagesFooter,\n ...messageComponents\n } = {},\n } = config;\n return (\n <ThreadRoot config={config}>\n <ThreadViewport>\n <ThreadWelcomeComponent />\n <ThreadMessages\n MessagesFooter={MessagesFooter}\n components={messageComponents}\n />\n <ThreadFollowupSuggestions />\n <ThreadViewportFooter>\n <ThreadScrollToBottom />\n <ComposerComponent />\n </ThreadViewportFooter>\n </ThreadViewport>\n </ThreadRoot>\n );\n};\n\nnamespace ThreadRoot {\n export type Element = HTMLDivElement;\n export type Props = ThreadPrimitive.Root.Props & ThreadConfigProviderProps;\n}\n\nconst ThreadRootStyled = withDefaults(ThreadPrimitive.Root, {\n className: \"aui-root aui-thread-root\",\n});\n\nconst ThreadRoot = forwardRef<ThreadRoot.Element, ThreadRoot.Props>(\n ({ config, ...props }, ref) => {\n return (\n <ThreadConfigProvider config={config}>\n <ThreadRootStyled {...props} ref={ref} />\n </ThreadConfigProvider>\n );\n },\n);\n\nThreadRoot.displayName = \"ThreadRoot\";\n\nconst ThreadViewport = withDefaults(ThreadPrimitive.Viewport, {\n className: \"aui-thread-viewport\",\n});\n\nThreadViewport.displayName = \"ThreadViewport\";\n\nconst ThreadViewportFooter = withDefaults(\"div\", {\n className: \"aui-thread-viewport-footer\",\n});\n\nThreadViewportFooter.displayName = \"ThreadViewportFooter\";\n\nconst ThreadMessages: FC<{\n unstable_flexGrowDiv?: boolean;\n components?: Partial<ThreadPrimitive.Messages.Props[\"components\"]>;\n MessagesFooter?: ComponentType | undefined;\n}> = ({\n components,\n MessagesFooter,\n unstable_flexGrowDiv: flexGrowDiv = true,\n ...rest\n}) => {\n return (\n <>\n <ThreadPrimitive.Messages\n components={{\n ...components,\n UserMessage: components?.UserMessage ?? UserMessage,\n AssistantMessage: components?.AssistantMessage ?? AssistantMessage,\n EditComposer: components?.EditComposer ?? EditComposer,\n }}\n {...rest}\n />\n {MessagesFooter && <MessagesFooter />}\n {flexGrowDiv && (\n <ThreadPrimitive.If empty={false}>\n <div style={{ flexGrow: 1 }} />\n </ThreadPrimitive.If>\n )}\n </>\n );\n};\n\nThreadMessages.displayName = \"ThreadMessages\";\n\nconst ThreadFollowupSuggestions: FC = () => {\n const suggestions = useThread((t) => t.suggestions);\n\n return (\n <ThreadPrimitive.If empty={false} running={false}>\n <div className=\"aui-thread-followup-suggestions\">\n {suggestions?.map((suggestion, idx) => (\n <ThreadPrimitive.Suggestion\n key={idx}\n className=\"aui-thread-followup-suggestion\"\n prompt={suggestion.prompt}\n method=\"replace\"\n autoSend\n >\n {suggestion.prompt}\n </ThreadPrimitive.Suggestion>\n ))}\n </div>\n </ThreadPrimitive.If>\n );\n};\n\nconst ThreadScrollToBottomIconButton = withDefaults(TooltipIconButton, {\n variant: \"outline\",\n className: \"aui-thread-scroll-to-bottom\",\n});\n\nnamespace ThreadScrollToBottom {\n export type Element = HTMLButtonElement;\n export type Props = Partial<TooltipIconButton.Props>;\n}\n\nconst ThreadScrollToBottom = forwardRef<\n ThreadScrollToBottom.Element,\n ThreadScrollToBottom.Props\n>((props, ref) => {\n const {\n strings: {\n thread: { scrollToBottom: { tooltip = \"Scroll to bottom\" } = {} } = {},\n } = {},\n } = useThreadConfig();\n return (\n <ThreadPrimitive.ScrollToBottom asChild>\n <ThreadScrollToBottomIconButton tooltip={tooltip} {...props} ref={ref}>\n {props.children ?? <ArrowDownIcon />}\n </ThreadScrollToBottomIconButton>\n </ThreadPrimitive.ScrollToBottom>\n );\n});\n\nThreadScrollToBottom.displayName = \"ThreadScrollToBottom\";\n\nconst exports = {\n Root: ThreadRoot,\n Viewport: ThreadViewport,\n Messages: ThreadMessages,\n FollowupSuggestions: ThreadFollowupSuggestions,\n ScrollToBottom: ThreadScrollToBottom,\n ViewportFooter: ThreadViewportFooter,\n};\n\nexport default Object.assign(Thread, exports) as typeof Thread & typeof exports;\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
@@ -29,7 +29,7 @@
|
|
29
29
|
"conversational-ui",
|
30
30
|
"conversational-ai"
|
31
31
|
],
|
32
|
-
"version": "0.7.
|
32
|
+
"version": "0.7.46",
|
33
33
|
"license": "MIT",
|
34
34
|
"exports": {
|
35
35
|
".": {
|
@@ -117,9 +117,9 @@
|
|
117
117
|
"tailwindcss": "^3.4.17",
|
118
118
|
"tailwindcss-animate": "^1.0.7",
|
119
119
|
"tsx": "^4.19.2",
|
120
|
-
"@assistant-ui/tailwindcss-transformer": "0.1.0",
|
121
120
|
"@assistant-ui/tsbuildutils": "^0.0.1",
|
122
|
-
"@assistant-ui/tsconfig": "0.0.0"
|
121
|
+
"@assistant-ui/tsconfig": "0.0.0",
|
122
|
+
"@assistant-ui/tailwindcss-transformer": "0.1.0"
|
123
123
|
},
|
124
124
|
"publishConfig": {
|
125
125
|
"access": "public",
|
@@ -10,7 +10,11 @@ type Transform<TState, TResult> = {
|
|
10
10
|
optimistic?: (state: TState) => TState;
|
11
11
|
|
12
12
|
/** transform the state only while loading */
|
13
|
-
loading?: (state: TState) => TState;
|
13
|
+
loading?: (state: TState, task: Promise<TResult>) => TState;
|
14
|
+
};
|
15
|
+
|
16
|
+
type PendingTransform<TState, TResult> = Transform<TState, TResult> & {
|
17
|
+
task: Promise<TResult>;
|
14
18
|
};
|
15
19
|
|
16
20
|
const pipeTransforms = <TState, TExtra>(
|
@@ -24,7 +28,8 @@ const pipeTransforms = <TState, TExtra>(
|
|
24
28
|
};
|
25
29
|
|
26
30
|
export class OptimisticState<TState> extends BaseSubscribable {
|
27
|
-
private readonly _pendingTransforms: Array<
|
31
|
+
private readonly _pendingTransforms: Array<PendingTransform<TState, any>> =
|
32
|
+
[];
|
28
33
|
private _baseValue: TState;
|
29
34
|
private _cachedValue: TState;
|
30
35
|
|
@@ -36,7 +41,7 @@ export class OptimisticState<TState> extends BaseSubscribable {
|
|
36
41
|
|
37
42
|
private _updateState(): void {
|
38
43
|
this._cachedValue = this._pendingTransforms.reduce((state, transform) => {
|
39
|
-
return pipeTransforms(state,
|
44
|
+
return pipeTransforms(state, transform.task, [
|
40
45
|
transform.loading,
|
41
46
|
transform.optimistic,
|
42
47
|
]);
|
@@ -61,18 +66,20 @@ export class OptimisticState<TState> extends BaseSubscribable {
|
|
61
66
|
public async optimisticUpdate<TResult>(
|
62
67
|
transform: Transform<TState, TResult>,
|
63
68
|
): Promise<TResult> {
|
64
|
-
|
65
|
-
|
66
|
-
|
69
|
+
const task = transform.execute();
|
70
|
+
const pendingTransform = { ...transform, task };
|
67
71
|
try {
|
68
|
-
|
72
|
+
this._pendingTransforms.push(pendingTransform);
|
73
|
+
this._updateState();
|
74
|
+
|
75
|
+
const result = await task;
|
69
76
|
this._baseValue = pipeTransforms(this._baseValue, result, [
|
70
77
|
transform.optimistic,
|
71
78
|
transform.then,
|
72
79
|
]);
|
73
80
|
return result;
|
74
81
|
} finally {
|
75
|
-
const index = this._pendingTransforms.indexOf(
|
82
|
+
const index = this._pendingTransforms.indexOf(pendingTransform);
|
76
83
|
if (index > -1) {
|
77
84
|
this._pendingTransforms.splice(index, 1);
|
78
85
|
}
|
@@ -13,7 +13,10 @@ import {
|
|
13
13
|
import { UseBoundStore, StoreApi, create } from "zustand";
|
14
14
|
import { useAssistantRuntime } from "../../context";
|
15
15
|
import { ThreadListItemRuntimeProvider } from "../../context/providers/ThreadListItemRuntimeProvider";
|
16
|
-
import {
|
16
|
+
import {
|
17
|
+
useThreadListItem,
|
18
|
+
useThreadListItemRuntime,
|
19
|
+
} from "../../context/react/ThreadListItemContext";
|
17
20
|
import { ThreadRuntimeCore, ThreadRuntimeImpl } from "../../internal";
|
18
21
|
import { BaseSubscribable } from "./BaseSubscribable";
|
19
22
|
import { AssistantRuntime } from "../../api";
|
@@ -112,6 +115,16 @@ export class RemoteThreadListHookInstanceManager extends BaseSubscribable {
|
|
112
115
|
return threadBinding.outerSubscribe(updateRuntime);
|
113
116
|
}, [threadBinding]);
|
114
117
|
|
118
|
+
// auto initialize thread
|
119
|
+
const threadListItemRuntime = useThreadListItemRuntime();
|
120
|
+
useEffect(() => {
|
121
|
+
return runtime.threads.main.unstable_on("initialize", () => {
|
122
|
+
if (threadListItemRuntime.getState().status === "new") {
|
123
|
+
threadListItemRuntime.initialize();
|
124
|
+
}
|
125
|
+
});
|
126
|
+
}, [runtime, threadListItemRuntime]);
|
127
|
+
|
115
128
|
return null;
|
116
129
|
};
|
117
130
|
|
@@ -121,7 +134,7 @@ export class RemoteThreadListHookInstanceManager extends BaseSubscribable {
|
|
121
134
|
}> = memo(({ threadId, provider: Provider }) => {
|
122
135
|
const assistantRuntime = useAssistantRuntime();
|
123
136
|
const threadListItemRuntime = useMemo(
|
124
|
-
() => assistantRuntime.
|
137
|
+
() => assistantRuntime.threads.getItemById(threadId),
|
125
138
|
[assistantRuntime, threadId],
|
126
139
|
);
|
127
140
|
|
@@ -2,7 +2,10 @@
|
|
2
2
|
|
3
3
|
import { ThreadListRuntimeCore } from "../core/ThreadListRuntimeCore";
|
4
4
|
import { generateId } from "../../internal";
|
5
|
-
import {
|
5
|
+
import {
|
6
|
+
RemoteThreadInitializeResponse,
|
7
|
+
RemoteThreadListAdapter,
|
8
|
+
} from "./types";
|
6
9
|
import { RemoteThreadListHookInstanceManager } from "./RemoteThreadListHookInstanceManager";
|
7
10
|
import { BaseSubscribable } from "./BaseSubscribable";
|
8
11
|
import { EMPTY_THREAD_CORE } from "./EMPTY_THREAD_CORE";
|
@@ -21,6 +24,15 @@ type RemoteThreadData =
|
|
21
24
|
}
|
22
25
|
| {
|
23
26
|
readonly threadId: string;
|
27
|
+
readonly initializeTask: Promise<RemoteThreadInitializeResponse>;
|
28
|
+
readonly remoteId?: undefined;
|
29
|
+
readonly externalId?: undefined;
|
30
|
+
readonly status: "regular" | "archived";
|
31
|
+
readonly title?: string | undefined;
|
32
|
+
}
|
33
|
+
| {
|
34
|
+
readonly threadId: string;
|
35
|
+
readonly initializeTask: Promise<RemoteThreadInitializeResponse>;
|
24
36
|
readonly remoteId: string;
|
25
37
|
readonly externalId: string | undefined;
|
26
38
|
readonly status: "regular" | "archived";
|
@@ -185,6 +197,10 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
185
197
|
externalId: thread.externalId,
|
186
198
|
status: thread.status,
|
187
199
|
title: thread.title,
|
200
|
+
initializeTask: Promise.resolve({
|
201
|
+
remoteId: thread.remoteId,
|
202
|
+
externalId: thread.externalId,
|
203
|
+
}),
|
188
204
|
};
|
189
205
|
}
|
190
206
|
|
@@ -338,8 +354,12 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
338
354
|
}
|
339
355
|
|
340
356
|
public initialize = async (threadId: string) => {
|
341
|
-
if (this._state.value.newThreadId !== threadId)
|
342
|
-
|
357
|
+
if (this._state.value.newThreadId !== threadId) {
|
358
|
+
const data = this.getItemById(threadId);
|
359
|
+
if (!data) throw new Error("Thread not found");
|
360
|
+
if (data.status === "new") throw new Error("Unexpected new state");
|
361
|
+
return data.initializeTask;
|
362
|
+
}
|
343
363
|
|
344
364
|
return this._state.optimisticUpdate({
|
345
365
|
execute: () => {
|
@@ -348,6 +368,19 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
348
368
|
optimistic: (state) => {
|
349
369
|
return updateStatusReducer(state, threadId, "regular");
|
350
370
|
},
|
371
|
+
loading: (state, task) => {
|
372
|
+
const mappingId = createThreadMappingId(threadId);
|
373
|
+
return {
|
374
|
+
...state,
|
375
|
+
threadData: {
|
376
|
+
...state.threadData,
|
377
|
+
[mappingId]: {
|
378
|
+
...state.threadData[mappingId],
|
379
|
+
initializeTask: task,
|
380
|
+
},
|
381
|
+
},
|
382
|
+
};
|
383
|
+
},
|
351
384
|
then: (state, { remoteId, externalId }) => {
|
352
385
|
const data = getThreadData(state, threadId);
|
353
386
|
if (!data) return state;
|
@@ -361,8 +394,9 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
361
394
|
},
|
362
395
|
threadData: {
|
363
396
|
...state.threadData,
|
364
|
-
[
|
397
|
+
[mappingId]: {
|
365
398
|
...data,
|
399
|
+
initializeTask: Promise.resolve({ remoteId, externalId }),
|
366
400
|
remoteId,
|
367
401
|
externalId,
|
368
402
|
},
|
@@ -406,8 +440,9 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
406
440
|
if (data.status === "new") throw new Error("Thread is not yet initialized");
|
407
441
|
|
408
442
|
return this._state.optimisticUpdate({
|
409
|
-
execute: () => {
|
410
|
-
|
443
|
+
execute: async () => {
|
444
|
+
const { remoteId } = await data.initializeTask;
|
445
|
+
return this._adapter.rename(remoteId, newTitle);
|
411
446
|
},
|
412
447
|
optimistic: (state) => {
|
413
448
|
const data = getThreadData(state, threadIdOrRemoteId);
|
@@ -448,7 +483,8 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
448
483
|
return this._state.optimisticUpdate({
|
449
484
|
execute: async () => {
|
450
485
|
await this._ensureThreadIsNotMain(data.threadId);
|
451
|
-
|
486
|
+
const { remoteId } = await data.initializeTask;
|
487
|
+
return this._adapter.archive(remoteId);
|
452
488
|
},
|
453
489
|
optimistic: (state) => {
|
454
490
|
return updateStatusReducer(state, data.threadId, "archived");
|
@@ -464,7 +500,8 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
464
500
|
return this._state.optimisticUpdate({
|
465
501
|
execute: async () => {
|
466
502
|
try {
|
467
|
-
|
503
|
+
const { remoteId } = await data.initializeTask;
|
504
|
+
return await this._adapter.unarchive(remoteId);
|
468
505
|
} catch (error) {
|
469
506
|
await this._ensureThreadIsNotMain(data.threadId);
|
470
507
|
throw error;
|
@@ -485,7 +522,8 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
485
522
|
return this._state.optimisticUpdate({
|
486
523
|
execute: async () => {
|
487
524
|
await this._ensureThreadIsNotMain(data.threadId);
|
488
|
-
|
525
|
+
const { remoteId } = await data.initializeTask;
|
526
|
+
return await this._adapter.delete(remoteId);
|
489
527
|
},
|
490
528
|
optimistic: (state) => {
|
491
529
|
return updateStatusReducer(state, data.threadId, "deleted");
|
@@ -65,6 +65,7 @@ const AssistantMessageContent = forwardRef<
|
|
65
65
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
66
66
|
[...(tools ?? []), components.ToolFallback],
|
67
67
|
);
|
68
|
+
const Footer = components.Footer;
|
68
69
|
|
69
70
|
return (
|
70
71
|
<AssistantMessageContentWrapper {...rest} ref={ref}>
|
@@ -76,6 +77,7 @@ const AssistantMessageContent = forwardRef<
|
|
76
77
|
tools: toolsComponents,
|
77
78
|
}}
|
78
79
|
/>
|
80
|
+
{Footer && <Footer />}
|
79
81
|
</AssistantMessageContentWrapper>
|
80
82
|
);
|
81
83
|
});
|
package/src/ui/thread-config.tsx
CHANGED
@@ -45,6 +45,7 @@ export type AssistantMessageConfig = {
|
|
45
45
|
Text?: TextContentPartComponent | undefined;
|
46
46
|
Empty?: EmptyContentPartComponent | undefined;
|
47
47
|
ToolFallback?: ComponentType<ToolCallContentPartProps> | undefined;
|
48
|
+
Footer?: ComponentType | undefined;
|
48
49
|
}
|
49
50
|
| undefined;
|
50
51
|
};
|
@@ -192,6 +193,7 @@ export type ThreadConfig = {
|
|
192
193
|
EditComposer?: ComponentType | undefined;
|
193
194
|
Composer?: ComponentType | undefined;
|
194
195
|
ThreadWelcome?: ComponentType | undefined;
|
196
|
+
MessagesFooter?: ComponentType | undefined;
|
195
197
|
}
|
196
198
|
| undefined;
|
197
199
|
};
|
package/src/ui/thread.tsx
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
"use client";
|
2
2
|
|
3
|
-
import { forwardRef, type FC } from "react";
|
3
|
+
import { ComponentType, forwardRef, type FC } from "react";
|
4
4
|
import { ArrowDownIcon } from "lucide-react";
|
5
5
|
|
6
6
|
import { withDefaults } from "./utils/withDefaults";
|
@@ -24,6 +24,7 @@ const Thread: FC<ThreadConfig> = (config) => {
|
|
24
24
|
components: {
|
25
25
|
Composer: ComposerComponent = Composer,
|
26
26
|
ThreadWelcome: ThreadWelcomeComponent = ThreadWelcome,
|
27
|
+
MessagesFooter,
|
27
28
|
...messageComponents
|
28
29
|
} = {},
|
29
30
|
} = config;
|
@@ -31,7 +32,10 @@ const Thread: FC<ThreadConfig> = (config) => {
|
|
31
32
|
<ThreadRoot config={config}>
|
32
33
|
<ThreadViewport>
|
33
34
|
<ThreadWelcomeComponent />
|
34
|
-
<ThreadMessages
|
35
|
+
<ThreadMessages
|
36
|
+
MessagesFooter={MessagesFooter}
|
37
|
+
components={messageComponents}
|
38
|
+
/>
|
35
39
|
<ThreadFollowupSuggestions />
|
36
40
|
<ThreadViewportFooter>
|
37
41
|
<ThreadScrollToBottom />
|
@@ -78,7 +82,13 @@ ThreadViewportFooter.displayName = "ThreadViewportFooter";
|
|
78
82
|
const ThreadMessages: FC<{
|
79
83
|
unstable_flexGrowDiv?: boolean;
|
80
84
|
components?: Partial<ThreadPrimitive.Messages.Props["components"]>;
|
81
|
-
|
85
|
+
MessagesFooter?: ComponentType | undefined;
|
86
|
+
}> = ({
|
87
|
+
components,
|
88
|
+
MessagesFooter,
|
89
|
+
unstable_flexGrowDiv: flexGrowDiv = true,
|
90
|
+
...rest
|
91
|
+
}) => {
|
82
92
|
return (
|
83
93
|
<>
|
84
94
|
<ThreadPrimitive.Messages
|
@@ -90,6 +100,7 @@ const ThreadMessages: FC<{
|
|
90
100
|
}}
|
91
101
|
{...rest}
|
92
102
|
/>
|
103
|
+
{MessagesFooter && <MessagesFooter />}
|
93
104
|
{flexGrowDiv && (
|
94
105
|
<ThreadPrimitive.If empty={false}>
|
95
106
|
<div style={{ flexGrow: 1 }} />
|