react-optimistic-chat 1.1.0 → 1.2.1
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/index.d.mts +35 -22
- package/dist/index.d.ts +35 -22
- package/dist/index.js +27 -34
- package/dist/index.mjs +27 -34
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -2,12 +2,13 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import React$1 from 'react';
|
|
3
3
|
|
|
4
4
|
type ChatRole = "AI" | "USER";
|
|
5
|
-
type
|
|
5
|
+
type BaseMessage = {
|
|
6
6
|
id: number | string;
|
|
7
7
|
role: ChatRole;
|
|
8
8
|
content: string;
|
|
9
9
|
isLoading?: boolean;
|
|
10
10
|
};
|
|
11
|
+
type Message<T = {}> = BaseMessage & T;
|
|
11
12
|
|
|
12
13
|
type Size$1 = 'xs' | 'sm' | 'md' | 'lg';
|
|
13
14
|
type Props$5 = {
|
|
@@ -34,14 +35,15 @@ type Props$3 = Message & {
|
|
|
34
35
|
};
|
|
35
36
|
declare function ChatMessage({ id, role, content, isLoading, wrapperClassName, icon, aiIconWrapperClassName, aiIconColor, bubbleClassName, aiBubbleClassName, userBubbleClassName, position, loadingRenderer, }: Props$3): react_jsx_runtime.JSX.Element;
|
|
36
37
|
|
|
37
|
-
type
|
|
38
|
+
type MessagePatch = Partial<BaseMessage> & Record<string, unknown>;
|
|
39
|
+
type Props$2<T extends Message = Message> = {
|
|
38
40
|
messages: T[];
|
|
39
|
-
messageMapper?: (msg: T) =>
|
|
40
|
-
messageRenderer?: (msg:
|
|
41
|
+
messageMapper?: (msg: T) => MessagePatch;
|
|
42
|
+
messageRenderer?: (msg: T) => React$1.ReactNode;
|
|
41
43
|
className?: string;
|
|
42
44
|
loadingRenderer?: React$1.ReactNode;
|
|
43
45
|
};
|
|
44
|
-
declare function ChatList<T>({ messages, messageMapper, messageRenderer, className, loadingRenderer, }: Props$2<T>): react_jsx_runtime.JSX.Element;
|
|
46
|
+
declare function ChatList<T extends Message>({ messages, messageMapper, messageRenderer, className, loadingRenderer, }: Props$2<T>): react_jsx_runtime.JSX.Element;
|
|
45
47
|
|
|
46
48
|
type VoiceRecognitionController$1 = {
|
|
47
49
|
start: () => void;
|
|
@@ -70,9 +72,15 @@ type Props$1 = {
|
|
|
70
72
|
};
|
|
71
73
|
declare function ChatInput({ onSend, voice, placeholder, className, inputClassName, micButton, recordingButton, sendButton, sendingButton, maxHeight, value, onChange, isSending, submitOnEnter, }: Props$1): react_jsx_runtime.JSX.Element;
|
|
72
74
|
|
|
73
|
-
type
|
|
75
|
+
type MessageProps = {
|
|
76
|
+
messages: Message[];
|
|
77
|
+
messageMapper?: never;
|
|
78
|
+
};
|
|
79
|
+
type RawProps<T> = {
|
|
74
80
|
messages: T[];
|
|
75
|
-
messageMapper
|
|
81
|
+
messageMapper: (msg: T) => Message;
|
|
82
|
+
};
|
|
83
|
+
type CommonProps = {
|
|
76
84
|
messageRenderer?: (msg: Message) => React.ReactNode;
|
|
77
85
|
loadingRenderer?: React.ReactNode;
|
|
78
86
|
listClassName?: string;
|
|
@@ -83,20 +91,23 @@ type Props<T> = {
|
|
|
83
91
|
inputClassName?: string;
|
|
84
92
|
className?: string;
|
|
85
93
|
};
|
|
86
|
-
|
|
94
|
+
type Props<T> = CommonProps & (MessageProps | RawProps<T>);
|
|
95
|
+
declare function ChatContainer<T>(props: Props<T>): react_jsx_runtime.JSX.Element;
|
|
87
96
|
|
|
88
|
-
type
|
|
89
|
-
type
|
|
97
|
+
type ExtraFromRaw$1<TRaw> = Omit<TRaw, keyof BaseMessage>;
|
|
98
|
+
type MessageMapperResult$1 = Pick<BaseMessage, "id" | "role" | "content">;
|
|
99
|
+
type MessageMapper$1<TRaw> = Message<ExtraFromRaw$1<TRaw>>;
|
|
100
|
+
type Options$2<TRaw> = {
|
|
90
101
|
queryKey: readonly unknown[];
|
|
91
|
-
queryFn: () => Promise<
|
|
92
|
-
mutationFn: (content: string) => Promise<
|
|
93
|
-
map:
|
|
102
|
+
queryFn: () => Promise<TRaw[]>;
|
|
103
|
+
mutationFn: (content: string) => Promise<TRaw>;
|
|
104
|
+
map: (raw: TRaw) => MessageMapperResult$1;
|
|
94
105
|
onError?: (error: unknown) => void;
|
|
95
106
|
staleTime?: number;
|
|
96
107
|
gcTime?: number;
|
|
97
108
|
};
|
|
98
|
-
declare function useOptimisticChat<
|
|
99
|
-
messages:
|
|
109
|
+
declare function useOptimisticChat<TRaw>({ queryKey, queryFn, mutationFn, map, onError, staleTime, gcTime, }: Options$2<TRaw>): {
|
|
110
|
+
messages: MessageMapper$1<TRaw>[];
|
|
100
111
|
sendUserMessage: (content: string) => void;
|
|
101
112
|
isPending: boolean;
|
|
102
113
|
isInitialLoading: boolean;
|
|
@@ -172,25 +183,27 @@ declare function useBrowserSpeechRecognition({ lang, onStart, onEnd, onError, }?
|
|
|
172
183
|
onTranscript: (text: string) => void;
|
|
173
184
|
};
|
|
174
185
|
|
|
175
|
-
type MessageMapper<TRaw> = (raw: TRaw) => Message;
|
|
176
186
|
type VoiceRecognitionController = {
|
|
177
187
|
start: () => void;
|
|
178
188
|
stop: () => void;
|
|
179
189
|
isRecording: boolean;
|
|
180
190
|
onTranscript: (text: string) => void;
|
|
181
191
|
};
|
|
182
|
-
type
|
|
192
|
+
type ExtraFromRaw<TRaw> = Omit<TRaw, keyof BaseMessage>;
|
|
193
|
+
type MessageMapperResult = Pick<BaseMessage, "id" | "role" | "content">;
|
|
194
|
+
type MessageMapper<TRaw> = Message<ExtraFromRaw<TRaw>>;
|
|
195
|
+
type Options<TRaw> = {
|
|
183
196
|
queryKey: readonly unknown[];
|
|
184
|
-
queryFn: () => Promise<
|
|
185
|
-
mutationFn: (content: string) => Promise<
|
|
186
|
-
map:
|
|
197
|
+
queryFn: () => Promise<TRaw[]>;
|
|
198
|
+
mutationFn: (content: string) => Promise<TRaw>;
|
|
199
|
+
map: (raw: TRaw) => MessageMapperResult;
|
|
187
200
|
voice: VoiceRecognitionController;
|
|
188
201
|
onError?: (error: unknown) => void;
|
|
189
202
|
staleTime?: number;
|
|
190
203
|
gcTime?: number;
|
|
191
204
|
};
|
|
192
|
-
declare function useVoiceOptimisticChat<
|
|
193
|
-
messages:
|
|
205
|
+
declare function useVoiceOptimisticChat<TRaw>({ queryKey, queryFn, mutationFn, map, voice, onError, staleTime, gcTime, }: Options<TRaw>): {
|
|
206
|
+
messages: MessageMapper<TRaw>[];
|
|
194
207
|
isPending: boolean;
|
|
195
208
|
isInitialLoading: boolean;
|
|
196
209
|
startRecording: () => Promise<void>;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,12 +2,13 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import React$1 from 'react';
|
|
3
3
|
|
|
4
4
|
type ChatRole = "AI" | "USER";
|
|
5
|
-
type
|
|
5
|
+
type BaseMessage = {
|
|
6
6
|
id: number | string;
|
|
7
7
|
role: ChatRole;
|
|
8
8
|
content: string;
|
|
9
9
|
isLoading?: boolean;
|
|
10
10
|
};
|
|
11
|
+
type Message<T = {}> = BaseMessage & T;
|
|
11
12
|
|
|
12
13
|
type Size$1 = 'xs' | 'sm' | 'md' | 'lg';
|
|
13
14
|
type Props$5 = {
|
|
@@ -34,14 +35,15 @@ type Props$3 = Message & {
|
|
|
34
35
|
};
|
|
35
36
|
declare function ChatMessage({ id, role, content, isLoading, wrapperClassName, icon, aiIconWrapperClassName, aiIconColor, bubbleClassName, aiBubbleClassName, userBubbleClassName, position, loadingRenderer, }: Props$3): react_jsx_runtime.JSX.Element;
|
|
36
37
|
|
|
37
|
-
type
|
|
38
|
+
type MessagePatch = Partial<BaseMessage> & Record<string, unknown>;
|
|
39
|
+
type Props$2<T extends Message = Message> = {
|
|
38
40
|
messages: T[];
|
|
39
|
-
messageMapper?: (msg: T) =>
|
|
40
|
-
messageRenderer?: (msg:
|
|
41
|
+
messageMapper?: (msg: T) => MessagePatch;
|
|
42
|
+
messageRenderer?: (msg: T) => React$1.ReactNode;
|
|
41
43
|
className?: string;
|
|
42
44
|
loadingRenderer?: React$1.ReactNode;
|
|
43
45
|
};
|
|
44
|
-
declare function ChatList<T>({ messages, messageMapper, messageRenderer, className, loadingRenderer, }: Props$2<T>): react_jsx_runtime.JSX.Element;
|
|
46
|
+
declare function ChatList<T extends Message>({ messages, messageMapper, messageRenderer, className, loadingRenderer, }: Props$2<T>): react_jsx_runtime.JSX.Element;
|
|
45
47
|
|
|
46
48
|
type VoiceRecognitionController$1 = {
|
|
47
49
|
start: () => void;
|
|
@@ -70,9 +72,15 @@ type Props$1 = {
|
|
|
70
72
|
};
|
|
71
73
|
declare function ChatInput({ onSend, voice, placeholder, className, inputClassName, micButton, recordingButton, sendButton, sendingButton, maxHeight, value, onChange, isSending, submitOnEnter, }: Props$1): react_jsx_runtime.JSX.Element;
|
|
72
74
|
|
|
73
|
-
type
|
|
75
|
+
type MessageProps = {
|
|
76
|
+
messages: Message[];
|
|
77
|
+
messageMapper?: never;
|
|
78
|
+
};
|
|
79
|
+
type RawProps<T> = {
|
|
74
80
|
messages: T[];
|
|
75
|
-
messageMapper
|
|
81
|
+
messageMapper: (msg: T) => Message;
|
|
82
|
+
};
|
|
83
|
+
type CommonProps = {
|
|
76
84
|
messageRenderer?: (msg: Message) => React.ReactNode;
|
|
77
85
|
loadingRenderer?: React.ReactNode;
|
|
78
86
|
listClassName?: string;
|
|
@@ -83,20 +91,23 @@ type Props<T> = {
|
|
|
83
91
|
inputClassName?: string;
|
|
84
92
|
className?: string;
|
|
85
93
|
};
|
|
86
|
-
|
|
94
|
+
type Props<T> = CommonProps & (MessageProps | RawProps<T>);
|
|
95
|
+
declare function ChatContainer<T>(props: Props<T>): react_jsx_runtime.JSX.Element;
|
|
87
96
|
|
|
88
|
-
type
|
|
89
|
-
type
|
|
97
|
+
type ExtraFromRaw$1<TRaw> = Omit<TRaw, keyof BaseMessage>;
|
|
98
|
+
type MessageMapperResult$1 = Pick<BaseMessage, "id" | "role" | "content">;
|
|
99
|
+
type MessageMapper$1<TRaw> = Message<ExtraFromRaw$1<TRaw>>;
|
|
100
|
+
type Options$2<TRaw> = {
|
|
90
101
|
queryKey: readonly unknown[];
|
|
91
|
-
queryFn: () => Promise<
|
|
92
|
-
mutationFn: (content: string) => Promise<
|
|
93
|
-
map:
|
|
102
|
+
queryFn: () => Promise<TRaw[]>;
|
|
103
|
+
mutationFn: (content: string) => Promise<TRaw>;
|
|
104
|
+
map: (raw: TRaw) => MessageMapperResult$1;
|
|
94
105
|
onError?: (error: unknown) => void;
|
|
95
106
|
staleTime?: number;
|
|
96
107
|
gcTime?: number;
|
|
97
108
|
};
|
|
98
|
-
declare function useOptimisticChat<
|
|
99
|
-
messages:
|
|
109
|
+
declare function useOptimisticChat<TRaw>({ queryKey, queryFn, mutationFn, map, onError, staleTime, gcTime, }: Options$2<TRaw>): {
|
|
110
|
+
messages: MessageMapper$1<TRaw>[];
|
|
100
111
|
sendUserMessage: (content: string) => void;
|
|
101
112
|
isPending: boolean;
|
|
102
113
|
isInitialLoading: boolean;
|
|
@@ -172,25 +183,27 @@ declare function useBrowserSpeechRecognition({ lang, onStart, onEnd, onError, }?
|
|
|
172
183
|
onTranscript: (text: string) => void;
|
|
173
184
|
};
|
|
174
185
|
|
|
175
|
-
type MessageMapper<TRaw> = (raw: TRaw) => Message;
|
|
176
186
|
type VoiceRecognitionController = {
|
|
177
187
|
start: () => void;
|
|
178
188
|
stop: () => void;
|
|
179
189
|
isRecording: boolean;
|
|
180
190
|
onTranscript: (text: string) => void;
|
|
181
191
|
};
|
|
182
|
-
type
|
|
192
|
+
type ExtraFromRaw<TRaw> = Omit<TRaw, keyof BaseMessage>;
|
|
193
|
+
type MessageMapperResult = Pick<BaseMessage, "id" | "role" | "content">;
|
|
194
|
+
type MessageMapper<TRaw> = Message<ExtraFromRaw<TRaw>>;
|
|
195
|
+
type Options<TRaw> = {
|
|
183
196
|
queryKey: readonly unknown[];
|
|
184
|
-
queryFn: () => Promise<
|
|
185
|
-
mutationFn: (content: string) => Promise<
|
|
186
|
-
map:
|
|
197
|
+
queryFn: () => Promise<TRaw[]>;
|
|
198
|
+
mutationFn: (content: string) => Promise<TRaw>;
|
|
199
|
+
map: (raw: TRaw) => MessageMapperResult;
|
|
187
200
|
voice: VoiceRecognitionController;
|
|
188
201
|
onError?: (error: unknown) => void;
|
|
189
202
|
staleTime?: number;
|
|
190
203
|
gcTime?: number;
|
|
191
204
|
};
|
|
192
|
-
declare function useVoiceOptimisticChat<
|
|
193
|
-
messages:
|
|
205
|
+
declare function useVoiceOptimisticChat<TRaw>({ queryKey, queryFn, mutationFn, map, voice, onError, staleTime, gcTime, }: Options<TRaw>): {
|
|
206
|
+
messages: MessageMapper<TRaw>[];
|
|
194
207
|
isPending: boolean;
|
|
195
208
|
isInitialLoading: boolean;
|
|
196
209
|
startRecording: () => Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -206,7 +206,7 @@ function ChatList({
|
|
|
206
206
|
className,
|
|
207
207
|
loadingRenderer
|
|
208
208
|
}) {
|
|
209
|
-
const mappedMessages = messageMapper ? messages.map(messageMapper) : messages;
|
|
209
|
+
const mappedMessages = messageMapper ? messages.map((msg) => __spreadValues(__spreadValues({}, msg), messageMapper(msg))) : messages;
|
|
210
210
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: `flex flex-col ${className}`, children: mappedMessages.map((msg) => {
|
|
211
211
|
if (messageRenderer) {
|
|
212
212
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react2.default.Fragment, { children: messageRenderer(msg) }, msg.id);
|
|
@@ -518,21 +518,22 @@ function ChatInput({
|
|
|
518
518
|
// src/components/ChatContainer.tsx
|
|
519
519
|
var import_react5 = require("react");
|
|
520
520
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
521
|
-
function ChatContainer({
|
|
522
|
-
messages,
|
|
523
|
-
messageMapper,
|
|
524
|
-
messageRenderer,
|
|
525
|
-
loadingRenderer,
|
|
526
|
-
listClassName,
|
|
527
|
-
onSend,
|
|
528
|
-
isSending,
|
|
529
|
-
disableVoice,
|
|
530
|
-
placeholder,
|
|
531
|
-
inputClassName,
|
|
532
|
-
className
|
|
533
|
-
}) {
|
|
521
|
+
function ChatContainer(props) {
|
|
534
522
|
const [isAtBottom, setIsAtBottom] = (0, import_react5.useState)(true);
|
|
535
523
|
const scrollRef = (0, import_react5.useRef)(null);
|
|
524
|
+
const {
|
|
525
|
+
messages,
|
|
526
|
+
messageRenderer,
|
|
527
|
+
loadingRenderer,
|
|
528
|
+
listClassName,
|
|
529
|
+
onSend,
|
|
530
|
+
isSending,
|
|
531
|
+
disableVoice,
|
|
532
|
+
placeholder,
|
|
533
|
+
inputClassName,
|
|
534
|
+
className
|
|
535
|
+
} = props;
|
|
536
|
+
const mappedMessages = typeof props.messageMapper === "function" ? props.messages.map(props.messageMapper) : messages;
|
|
536
537
|
(0, import_react5.useEffect)(() => {
|
|
537
538
|
const el = scrollRef.current;
|
|
538
539
|
if (!el) return;
|
|
@@ -578,9 +579,9 @@ function ChatContainer({
|
|
|
578
579
|
className: `flex-1 overflow-y-auto chatContainer-scroll p-2`,
|
|
579
580
|
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
580
581
|
ChatList,
|
|
581
|
-
__spreadValues(__spreadValues(__spreadValues(
|
|
582
|
-
messages
|
|
583
|
-
},
|
|
582
|
+
__spreadValues(__spreadValues(__spreadValues({
|
|
583
|
+
messages: mappedMessages
|
|
584
|
+
}, messageRenderer && { messageRenderer }), loadingRenderer && { loadingRenderer }), listClassName && { className: listClassName })
|
|
584
585
|
)
|
|
585
586
|
}
|
|
586
587
|
),
|
|
@@ -644,8 +645,8 @@ function useOptimisticChat({
|
|
|
644
645
|
} = (0, import_react_query.useQuery)({
|
|
645
646
|
queryKey,
|
|
646
647
|
queryFn: async () => {
|
|
647
|
-
const
|
|
648
|
-
return
|
|
648
|
+
const raw = await queryFn();
|
|
649
|
+
return raw.map((r) => __spreadValues(__spreadValues({}, map(r)), r));
|
|
649
650
|
},
|
|
650
651
|
staleTime,
|
|
651
652
|
gcTime
|
|
@@ -678,10 +679,10 @@ function useOptimisticChat({
|
|
|
678
679
|
}
|
|
679
680
|
];
|
|
680
681
|
});
|
|
681
|
-
return { prev };
|
|
682
|
+
return prev ? { prev } : {};
|
|
682
683
|
},
|
|
683
684
|
onSuccess: (rawAiResponse) => {
|
|
684
|
-
const aiMessage = map(rawAiResponse);
|
|
685
|
+
const aiMessage = __spreadValues(__spreadValues({}, map(rawAiResponse)), rawAiResponse);
|
|
685
686
|
queryClient.setQueryData(queryKey, (old) => {
|
|
686
687
|
if (!old || old.length === 0) {
|
|
687
688
|
return [aiMessage];
|
|
@@ -701,10 +702,6 @@ function useOptimisticChat({
|
|
|
701
702
|
queryClient.setQueryData(queryKey, context.prev);
|
|
702
703
|
}
|
|
703
704
|
onError == null ? void 0 : onError(error);
|
|
704
|
-
},
|
|
705
|
-
// mutation 이후 서버 기준 최신 데이터 재동기화
|
|
706
|
-
onSettled: () => {
|
|
707
|
-
queryClient.invalidateQueries({ queryKey });
|
|
708
705
|
}
|
|
709
706
|
});
|
|
710
707
|
const sendUserMessage = (content) => {
|
|
@@ -746,8 +743,8 @@ function useVoiceOptimisticChat({
|
|
|
746
743
|
} = (0, import_react_query2.useQuery)({
|
|
747
744
|
queryKey,
|
|
748
745
|
queryFn: async () => {
|
|
749
|
-
const
|
|
750
|
-
return
|
|
746
|
+
const raw = await queryFn();
|
|
747
|
+
return raw.map((r) => __spreadValues(__spreadValues({}, map(r)), r));
|
|
751
748
|
},
|
|
752
749
|
staleTime,
|
|
753
750
|
gcTime
|
|
@@ -774,10 +771,10 @@ function useVoiceOptimisticChat({
|
|
|
774
771
|
}
|
|
775
772
|
];
|
|
776
773
|
});
|
|
777
|
-
return { prev };
|
|
774
|
+
return prev ? { prev } : {};
|
|
778
775
|
},
|
|
779
776
|
onSuccess: (rawAiResponse) => {
|
|
780
|
-
const aiMessage = map(rawAiResponse);
|
|
777
|
+
const aiMessage = __spreadValues(__spreadValues({}, map(rawAiResponse)), rawAiResponse);
|
|
781
778
|
queryClient.setQueryData(queryKey, (old) => {
|
|
782
779
|
if (!old || old.length === 0) {
|
|
783
780
|
return [aiMessage];
|
|
@@ -797,10 +794,6 @@ function useVoiceOptimisticChat({
|
|
|
797
794
|
queryClient.setQueryData(queryKey, context.prev);
|
|
798
795
|
}
|
|
799
796
|
onError == null ? void 0 : onError(error);
|
|
800
|
-
},
|
|
801
|
-
// mutation 이후 서버 기준 최신 데이터 재동기화
|
|
802
|
-
onSettled: () => {
|
|
803
|
-
queryClient.invalidateQueries({ queryKey });
|
|
804
797
|
}
|
|
805
798
|
});
|
|
806
799
|
const startRecording = async () => {
|
|
@@ -850,7 +843,7 @@ function useVoiceOptimisticChat({
|
|
|
850
843
|
};
|
|
851
844
|
return {
|
|
852
845
|
messages,
|
|
853
|
-
// Message[]
|
|
846
|
+
// Message<TExtra>[]
|
|
854
847
|
isPending,
|
|
855
848
|
// 사용자가 채팅 전송 후 AI 응답이 올 때까지의 로딩
|
|
856
849
|
isInitialLoading,
|
package/dist/index.mjs
CHANGED
|
@@ -165,7 +165,7 @@ function ChatList({
|
|
|
165
165
|
className,
|
|
166
166
|
loadingRenderer
|
|
167
167
|
}) {
|
|
168
|
-
const mappedMessages = messageMapper ? messages.map(messageMapper) : messages;
|
|
168
|
+
const mappedMessages = messageMapper ? messages.map((msg) => __spreadValues(__spreadValues({}, msg), messageMapper(msg))) : messages;
|
|
169
169
|
return /* @__PURE__ */ jsx4("div", { className: `flex flex-col ${className}`, children: mappedMessages.map((msg) => {
|
|
170
170
|
if (messageRenderer) {
|
|
171
171
|
return /* @__PURE__ */ jsx4(React2.Fragment, { children: messageRenderer(msg) }, msg.id);
|
|
@@ -477,21 +477,22 @@ function ChatInput({
|
|
|
477
477
|
// src/components/ChatContainer.tsx
|
|
478
478
|
import { useEffect as useEffect3, useRef as useRef3, useState as useState3 } from "react";
|
|
479
479
|
import { Fragment, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
480
|
-
function ChatContainer({
|
|
481
|
-
messages,
|
|
482
|
-
messageMapper,
|
|
483
|
-
messageRenderer,
|
|
484
|
-
loadingRenderer,
|
|
485
|
-
listClassName,
|
|
486
|
-
onSend,
|
|
487
|
-
isSending,
|
|
488
|
-
disableVoice,
|
|
489
|
-
placeholder,
|
|
490
|
-
inputClassName,
|
|
491
|
-
className
|
|
492
|
-
}) {
|
|
480
|
+
function ChatContainer(props) {
|
|
493
481
|
const [isAtBottom, setIsAtBottom] = useState3(true);
|
|
494
482
|
const scrollRef = useRef3(null);
|
|
483
|
+
const {
|
|
484
|
+
messages,
|
|
485
|
+
messageRenderer,
|
|
486
|
+
loadingRenderer,
|
|
487
|
+
listClassName,
|
|
488
|
+
onSend,
|
|
489
|
+
isSending,
|
|
490
|
+
disableVoice,
|
|
491
|
+
placeholder,
|
|
492
|
+
inputClassName,
|
|
493
|
+
className
|
|
494
|
+
} = props;
|
|
495
|
+
const mappedMessages = typeof props.messageMapper === "function" ? props.messages.map(props.messageMapper) : messages;
|
|
495
496
|
useEffect3(() => {
|
|
496
497
|
const el = scrollRef.current;
|
|
497
498
|
if (!el) return;
|
|
@@ -537,9 +538,9 @@ function ChatContainer({
|
|
|
537
538
|
className: `flex-1 overflow-y-auto chatContainer-scroll p-2`,
|
|
538
539
|
children: /* @__PURE__ */ jsx6(
|
|
539
540
|
ChatList,
|
|
540
|
-
__spreadValues(__spreadValues(__spreadValues(
|
|
541
|
-
messages
|
|
542
|
-
},
|
|
541
|
+
__spreadValues(__spreadValues(__spreadValues({
|
|
542
|
+
messages: mappedMessages
|
|
543
|
+
}, messageRenderer && { messageRenderer }), loadingRenderer && { loadingRenderer }), listClassName && { className: listClassName })
|
|
543
544
|
)
|
|
544
545
|
}
|
|
545
546
|
),
|
|
@@ -603,8 +604,8 @@ function useOptimisticChat({
|
|
|
603
604
|
} = useQuery({
|
|
604
605
|
queryKey,
|
|
605
606
|
queryFn: async () => {
|
|
606
|
-
const
|
|
607
|
-
return
|
|
607
|
+
const raw = await queryFn();
|
|
608
|
+
return raw.map((r) => __spreadValues(__spreadValues({}, map(r)), r));
|
|
608
609
|
},
|
|
609
610
|
staleTime,
|
|
610
611
|
gcTime
|
|
@@ -637,10 +638,10 @@ function useOptimisticChat({
|
|
|
637
638
|
}
|
|
638
639
|
];
|
|
639
640
|
});
|
|
640
|
-
return { prev };
|
|
641
|
+
return prev ? { prev } : {};
|
|
641
642
|
},
|
|
642
643
|
onSuccess: (rawAiResponse) => {
|
|
643
|
-
const aiMessage = map(rawAiResponse);
|
|
644
|
+
const aiMessage = __spreadValues(__spreadValues({}, map(rawAiResponse)), rawAiResponse);
|
|
644
645
|
queryClient.setQueryData(queryKey, (old) => {
|
|
645
646
|
if (!old || old.length === 0) {
|
|
646
647
|
return [aiMessage];
|
|
@@ -660,10 +661,6 @@ function useOptimisticChat({
|
|
|
660
661
|
queryClient.setQueryData(queryKey, context.prev);
|
|
661
662
|
}
|
|
662
663
|
onError == null ? void 0 : onError(error);
|
|
663
|
-
},
|
|
664
|
-
// mutation 이후 서버 기준 최신 데이터 재동기화
|
|
665
|
-
onSettled: () => {
|
|
666
|
-
queryClient.invalidateQueries({ queryKey });
|
|
667
664
|
}
|
|
668
665
|
});
|
|
669
666
|
const sendUserMessage = (content) => {
|
|
@@ -705,8 +702,8 @@ function useVoiceOptimisticChat({
|
|
|
705
702
|
} = useQuery2({
|
|
706
703
|
queryKey,
|
|
707
704
|
queryFn: async () => {
|
|
708
|
-
const
|
|
709
|
-
return
|
|
705
|
+
const raw = await queryFn();
|
|
706
|
+
return raw.map((r) => __spreadValues(__spreadValues({}, map(r)), r));
|
|
710
707
|
},
|
|
711
708
|
staleTime,
|
|
712
709
|
gcTime
|
|
@@ -733,10 +730,10 @@ function useVoiceOptimisticChat({
|
|
|
733
730
|
}
|
|
734
731
|
];
|
|
735
732
|
});
|
|
736
|
-
return { prev };
|
|
733
|
+
return prev ? { prev } : {};
|
|
737
734
|
},
|
|
738
735
|
onSuccess: (rawAiResponse) => {
|
|
739
|
-
const aiMessage = map(rawAiResponse);
|
|
736
|
+
const aiMessage = __spreadValues(__spreadValues({}, map(rawAiResponse)), rawAiResponse);
|
|
740
737
|
queryClient.setQueryData(queryKey, (old) => {
|
|
741
738
|
if (!old || old.length === 0) {
|
|
742
739
|
return [aiMessage];
|
|
@@ -756,10 +753,6 @@ function useVoiceOptimisticChat({
|
|
|
756
753
|
queryClient.setQueryData(queryKey, context.prev);
|
|
757
754
|
}
|
|
758
755
|
onError == null ? void 0 : onError(error);
|
|
759
|
-
},
|
|
760
|
-
// mutation 이후 서버 기준 최신 데이터 재동기화
|
|
761
|
-
onSettled: () => {
|
|
762
|
-
queryClient.invalidateQueries({ queryKey });
|
|
763
756
|
}
|
|
764
757
|
});
|
|
765
758
|
const startRecording = async () => {
|
|
@@ -809,7 +802,7 @@ function useVoiceOptimisticChat({
|
|
|
809
802
|
};
|
|
810
803
|
return {
|
|
811
804
|
messages,
|
|
812
|
-
// Message[]
|
|
805
|
+
// Message<TExtra>[]
|
|
813
806
|
isPending,
|
|
814
807
|
// 사용자가 채팅 전송 후 AI 응답이 올 때까지의 로딩
|
|
815
808
|
isInitialLoading,
|