@assistant-ui/react 0.7.44 → 0.7.46
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/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 }} />
|