react-optimistic-chat 2.0.0 → 2.2.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/dist/index.css ADDED
@@ -0,0 +1,214 @@
1
+ /* src/styles/chatMessage.css */
2
+ .roc-chat-message {
3
+ display: flex;
4
+ align-items: flex-start;
5
+ margin-bottom: 1rem;
6
+ width: 100%;
7
+ box-sizing: border-box;
8
+ }
9
+ .roc-chat-message--left {
10
+ justify-content: flex-start;
11
+ }
12
+ .roc-chat-message--right {
13
+ justify-content: flex-end;
14
+ }
15
+ .roc-chat-message__icon {
16
+ width: 40px;
17
+ height: 40px;
18
+ display: flex;
19
+ align-items: center;
20
+ justify-content: center;
21
+ background-color: #f3f4f6;
22
+ border-radius: 9999px;
23
+ border: 2px solid #000;
24
+ flex-shrink: 0;
25
+ margin-right: 0.5rem;
26
+ }
27
+ .roc-chat-message__icon svg {
28
+ display: block;
29
+ }
30
+ .roc-chat-message__bubble {
31
+ padding: 0.75rem;
32
+ max-width: calc(100% - 3rem);
33
+ max-height: 24rem;
34
+ overflow-y: auto;
35
+ white-space: pre-wrap;
36
+ word-break: break-word;
37
+ font-size: 0.875rem;
38
+ line-height: 1.4;
39
+ box-sizing: border-box;
40
+ }
41
+ .roc-chat-message__bubble--ai {
42
+ background-color: #f3f4f6;
43
+ border-radius: 0.75rem;
44
+ }
45
+ .roc-chat-message__bubble--user {
46
+ background-color: #ffffff;
47
+ border: 1px solid #e5e7eb;
48
+ border-radius: 0.75rem 0.75rem 0 0.75rem;
49
+ }
50
+
51
+ /* src/styles/chatList.css */
52
+ .roc-chat-list {
53
+ display: flex;
54
+ flex-direction: column;
55
+ }
56
+
57
+ /* src/styles/chatInput.css */
58
+ .roc-chat-input {
59
+ display: flex;
60
+ border: 1px solid #d1d5db;
61
+ padding: 8px 8px;
62
+ border-radius: 24px;
63
+ }
64
+ .roc-chat-input__textarea {
65
+ width: 100%;
66
+ resize: none;
67
+ border: none;
68
+ font-size: 16px;
69
+ line-height: 2.2;
70
+ outline: none;
71
+ overflow: hidden;
72
+ padding: 0;
73
+ padding-left: 8px;
74
+ }
75
+ .roc-chat-input__textarea::-moz-placeholder {
76
+ color: #9ca3af;
77
+ font-family:
78
+ -apple-system,
79
+ BlinkMacSystemFont,
80
+ "Segoe UI",
81
+ "Apple SD Gothic Neo",
82
+ "Noto Sans KR",
83
+ "Noto Sans",
84
+ system-ui,
85
+ sans-serif;
86
+ }
87
+ .roc-chat-input__textarea::placeholder {
88
+ color: #9ca3af;
89
+ font-family:
90
+ -apple-system,
91
+ BlinkMacSystemFont,
92
+ "Segoe UI",
93
+ "Apple SD Gothic Neo",
94
+ "Noto Sans KR",
95
+ "Noto Sans",
96
+ system-ui,
97
+ sans-serif;
98
+ }
99
+ .roc-chat-input__button {
100
+ position: relative;
101
+ width: 36px;
102
+ height: 36px;
103
+ margin-top: auto;
104
+ flex-shrink: 0;
105
+ background: none;
106
+ border: none;
107
+ margin-left: 8px;
108
+ cursor: pointer;
109
+ }
110
+ .roc-chat-input__layer {
111
+ position: absolute;
112
+ inset: 0;
113
+ display: flex;
114
+ align-items: center;
115
+ justify-content: center;
116
+ border-radius: 24px;
117
+ opacity: 0;
118
+ transition: opacity 150ms ease;
119
+ }
120
+ .roc-chat-input__layer.is-active {
121
+ opacity: 1;
122
+ }
123
+ .roc-chat-input__layer--mic {
124
+ background: #f3f4f6;
125
+ color: #374151;
126
+ }
127
+ .roc-chat-input__layer--recording {
128
+ background: #dc2626;
129
+ color: #ffffff;
130
+ }
131
+ .roc-chat-input__layer--send {
132
+ background: #000000;
133
+ color: #ffffff;
134
+ }
135
+ .roc-chat-input__layer--sending {
136
+ background: #9ca3af;
137
+ color: #ffffff;
138
+ }
139
+
140
+ /* src/styles/chatContainer.css */
141
+ .roc-chat-container {
142
+ display: flex;
143
+ flex-direction: column;
144
+ height: 100%;
145
+ }
146
+ .roc-chat-container__list {
147
+ flex: 1;
148
+ overflow-y: auto;
149
+ padding: 8px;
150
+ }
151
+ .roc-chat-container__loading {
152
+ display: flex;
153
+ justify-content: center;
154
+ padding: 8px 0;
155
+ }
156
+ .roc-chat-container__input {
157
+ position: relative;
158
+ flex-shrink: 0;
159
+ }
160
+ .roc-chat-container__scroll-button {
161
+ position: absolute;
162
+ bottom: 80px;
163
+ left: 50%;
164
+ transform: translateX(-50%);
165
+ width: 40px;
166
+ height: 40px;
167
+ border-radius: 50%;
168
+ background: #ffffff;
169
+ border: 1px solid #e5e7eb;
170
+ display: flex;
171
+ align-items: center;
172
+ justify-content: center;
173
+ cursor: pointer;
174
+ }
175
+
176
+ /* src/styles/loadingSpinner.css */
177
+ .roc-spinner-wrapper {
178
+ display: flex;
179
+ align-items: center;
180
+ justify-content: center;
181
+ }
182
+ .roc-spinner {
183
+ border: 4px solid #e5e7eb;
184
+ border-right-color: transparent;
185
+ border-radius: 50%;
186
+ animation: roc-spin 1s linear infinite;
187
+ }
188
+ @keyframes roc-spin {
189
+ to {
190
+ transform: rotate(1turn);
191
+ }
192
+ }
193
+
194
+ /* src/styles/sendingDots.css */
195
+ .roc-sending-dots {
196
+ display: inline-flex;
197
+ justify-content: space-between;
198
+ align-items: center;
199
+ }
200
+ .roc-sending-dot {
201
+ font-weight: 800;
202
+ line-height: 1;
203
+ animation: roc-sending-bounce 1.4s ease-in-out infinite;
204
+ }
205
+ @keyframes roc-sending-bounce {
206
+ 0%, to {
207
+ opacity: .2;
208
+ transform: translateY(0);
209
+ }
210
+ 50% {
211
+ opacity: 1;
212
+ transform: translateY(-2px);
213
+ }
214
+ }
package/dist/index.d.mts CHANGED
@@ -10,11 +10,21 @@ type BaseMessage = {
10
10
  content: string;
11
11
  isLoading?: boolean;
12
12
  };
13
- type Message<T = {}> = BaseMessage & T;
13
+ type MessageCore = Pick<BaseMessage, "id" | "role" | "content">;
14
+ type Message<TCustom = unknown> = BaseMessage & {
15
+ custom?: TCustom;
16
+ };
17
+
18
+ type VoiceRecognition = {
19
+ start: () => void;
20
+ stop: () => void;
21
+ isRecording: boolean;
22
+ onTranscript?: (text: string) => void;
23
+ };
14
24
 
15
25
  type Size$1 = 'xs' | 'sm' | 'md' | 'lg';
16
26
  type Props$5 = {
17
- size: Size$1;
27
+ size?: Size$1;
18
28
  };
19
29
  declare function LoadingSpinner({ size }: Props$5): react_jsx_runtime.JSX.Element;
20
30
 
@@ -37,28 +47,22 @@ type Props$3 = Message & {
37
47
  };
38
48
  declare function ChatMessage({ id, role, content, isLoading, wrapperClassName, icon, aiIconWrapperClassName, aiIconColor, bubbleClassName, aiBubbleClassName, userBubbleClassName, position, loadingRenderer, }: Props$3): react_jsx_runtime.JSX.Element;
39
49
 
40
- type MessagePatch = Partial<BaseMessage> & Record<string, unknown>;
41
- type Props$2<T extends Message = Message> = {
42
- messages: T[];
43
- messageMapper?: (msg: T) => MessagePatch;
44
- messageRenderer?: (msg: T) => React$1.ReactNode;
50
+ type Props$2<Raw> = {
51
+ messages: Raw[];
52
+ messageMapper?: (msg: Raw) => Message;
53
+ messageRenderer?: (msg: Message) => React$1.ReactNode;
45
54
  className?: string;
46
55
  loadingRenderer?: React$1.ReactNode;
47
56
  };
48
- declare function ChatList<T extends Message>({ messages, messageMapper, messageRenderer, className, loadingRenderer, }: Props$2<T>): react_jsx_runtime.JSX.Element;
57
+ declare function ChatList<Raw>({ messages, messageMapper, messageRenderer, className, loadingRenderer, }: Props$2<Raw>): react_jsx_runtime.JSX.Element;
49
58
 
50
- type VoiceRecognitionController$1 = {
51
- start: () => void;
52
- stop: () => void;
53
- isRecording: boolean;
54
- };
55
59
  type ButtonConfig = {
56
60
  className?: string;
57
61
  icon?: React.ReactNode;
58
62
  };
59
63
  type Props$1 = {
60
64
  onSend: (value: string) => void | Promise<void>;
61
- voice?: boolean | VoiceRecognitionController$1;
65
+ voice?: boolean | VoiceRecognition;
62
66
  placeholder?: string;
63
67
  className?: string;
64
68
  inputClassName?: string;
@@ -78,9 +82,9 @@ type MessageProps = {
78
82
  messages: Message[];
79
83
  messageMapper?: never;
80
84
  };
81
- type RawProps<T> = {
82
- messages: T[];
83
- messageMapper: (msg: T) => Message;
85
+ type RawProps<Raw> = {
86
+ messages: Raw[];
87
+ messageMapper: (msg: Raw) => Message;
84
88
  };
85
89
  type CommonProps = {
86
90
  messageRenderer?: (msg: Message) => React.ReactNode;
@@ -96,32 +100,27 @@ type CommonProps = {
96
100
  isFetchingNextPage?: boolean;
97
101
  className?: string;
98
102
  };
99
- type Props<T> = CommonProps & (MessageProps | RawProps<T>);
100
- declare function ChatContainer<T>(props: Props<T>): react_jsx_runtime.JSX.Element;
103
+ type Props<Raw> = CommonProps & (MessageProps | RawProps<Raw>);
104
+ declare function ChatContainer<Raw>(props: Props<Raw>): react_jsx_runtime.JSX.Element;
101
105
 
102
- type ExtraFromRaw$1<TRaw> = Omit<TRaw, keyof BaseMessage>;
103
- type CustomMessage$1<TCustom> = BaseMessage & {
104
- custom: TCustom;
105
- };
106
- type MessageMapper$1<TRaw> = CustomMessage$1<ExtraFromRaw$1<TRaw>>;
107
- type MessageMapperResult$1 = Pick<BaseMessage, "id" | "role" | "content">;
108
- type Options$2<TRaw> = {
106
+ type ExtractCustom$1<Raw> = Omit<Raw, keyof BaseMessage>;
107
+ type Options$2<Raw> = {
109
108
  queryKey: readonly unknown[];
110
- queryFn: (pageParam: unknown) => Promise<TRaw[]>;
109
+ queryFn: (pageParam: unknown) => Promise<Raw[]>;
111
110
  initialPageParam: unknown;
112
- getNextPageParam: (lastPage: MessageMapper$1<TRaw>[], allPages: MessageMapper$1<TRaw>[][]) => unknown;
113
- mutationFn: (content: string) => Promise<TRaw>;
114
- map: (raw: TRaw) => MessageMapperResult$1;
111
+ getNextPageParam: (lastPage: Message<ExtractCustom$1<Raw>>[], allPages: Message<ExtractCustom$1<Raw>>[][]) => unknown;
112
+ mutationFn: (content: string) => Promise<Raw>;
113
+ map: (raw: Raw) => MessageCore;
115
114
  onError?: (error: unknown) => void;
116
115
  staleTime?: number;
117
116
  gcTime?: number;
118
117
  };
119
- declare function useChat<TRaw extends object>({ queryKey, queryFn, initialPageParam, getNextPageParam, mutationFn, map, onError, staleTime, gcTime, }: Options$2<TRaw>): {
120
- messages: MessageMapper$1<TRaw>[];
118
+ declare function useChat<Raw extends object>({ queryKey, queryFn, initialPageParam, getNextPageParam, mutationFn, map, onError, staleTime, gcTime, }: Options$2<Raw>): {
119
+ messages: Message<ExtractCustom$1<Raw>>[];
121
120
  sendUserMessage: (content: string) => void;
122
121
  isPending: boolean;
123
122
  isInitialLoading: boolean;
124
- fetchNextPage: (options?: _tanstack_query_core.FetchNextPageOptions) => Promise<_tanstack_query_core.InfiniteQueryObserverResult<InfiniteData<MessageMapper$1<TRaw>[], unknown>, Error>>;
123
+ fetchNextPage: (options?: _tanstack_query_core.FetchNextPageOptions) => Promise<_tanstack_query_core.InfiniteQueryObserverResult<InfiniteData<Message<ExtractCustom$1<Raw>>[], unknown>, Error>>;
125
124
  hasNextPage: boolean;
126
125
  isFetchingNextPage: boolean;
127
126
  };
@@ -196,39 +195,28 @@ declare function useBrowserSpeechRecognition({ lang, onStart, onEnd, onError, }?
196
195
  onTranscript: (text: string) => void;
197
196
  };
198
197
 
199
- type VoiceRecognitionController = {
200
- start: () => void;
201
- stop: () => void;
202
- isRecording: boolean;
203
- onTranscript: (text: string) => void;
204
- };
205
- type ExtraFromRaw<TRaw> = Omit<TRaw, keyof BaseMessage>;
206
- type CustomMessage<TCustom> = BaseMessage & {
207
- custom: TCustom;
208
- };
209
- type MessageMapper<TRaw> = CustomMessage<ExtraFromRaw<TRaw>>;
210
- type MessageMapperResult = Pick<BaseMessage, "id" | "role" | "content">;
211
- type Options<TRaw> = {
198
+ type ExtractCustom<Raw> = Omit<Raw, keyof BaseMessage>;
199
+ type Options<Raw> = {
212
200
  queryKey: readonly unknown[];
213
- queryFn: (pageParam: unknown) => Promise<TRaw[]>;
201
+ queryFn: (pageParam: unknown) => Promise<Raw[]>;
214
202
  initialPageParam: unknown;
215
- getNextPageParam: (lastPage: MessageMapper<TRaw>[], allPages: MessageMapper<TRaw>[][]) => unknown;
216
- mutationFn: (content: string) => Promise<TRaw>;
217
- map: (raw: TRaw) => MessageMapperResult;
218
- voice: VoiceRecognitionController;
203
+ getNextPageParam: (lastPage: Message<ExtractCustom<Raw>>[], allPages: Message<ExtractCustom<Raw>>[][]) => unknown;
204
+ mutationFn: (content: string) => Promise<Raw>;
205
+ map: (raw: Raw) => MessageCore;
206
+ voice: VoiceRecognition;
219
207
  onError?: (error: unknown) => void;
220
208
  staleTime?: number;
221
209
  gcTime?: number;
222
210
  };
223
- declare function useVoiceChat<TRaw extends object>({ queryKey, queryFn, initialPageParam, getNextPageParam, mutationFn, map, voice, onError, staleTime, gcTime, }: Options<TRaw>): {
224
- messages: MessageMapper<TRaw>[];
211
+ declare function useVoiceChat<Raw extends object>({ queryKey, queryFn, initialPageParam, getNextPageParam, mutationFn, map, voice, onError, staleTime, gcTime, }: Options<Raw>): {
212
+ messages: Message<ExtractCustom<Raw>>[];
225
213
  isPending: boolean;
226
214
  isInitialLoading: boolean;
227
215
  startRecording: () => Promise<void>;
228
216
  stopRecording: () => void;
229
- fetchNextPage: (options?: _tanstack_query_core.FetchNextPageOptions) => Promise<_tanstack_query_core.InfiniteQueryObserverResult<InfiniteData<MessageMapper<TRaw>[], unknown>, Error>>;
217
+ fetchNextPage: (options?: _tanstack_query_core.FetchNextPageOptions) => Promise<_tanstack_query_core.InfiniteQueryObserverResult<InfiniteData<Message<ExtractCustom<Raw>>[], unknown>, Error>>;
230
218
  hasNextPage: boolean;
231
219
  isFetchingNextPage: boolean;
232
220
  };
233
221
 
234
- export { ChatContainer, ChatInput, ChatList, ChatMessage, LoadingSpinner, type Message, SendingDots, useBrowserSpeechRecognition, useChat, useVoiceChat };
222
+ export { ChatContainer, ChatInput, ChatList, ChatMessage, LoadingSpinner, type Message, SendingDots, type VoiceRecognition, useBrowserSpeechRecognition, useChat, useVoiceChat };
package/dist/index.d.ts CHANGED
@@ -10,11 +10,21 @@ type BaseMessage = {
10
10
  content: string;
11
11
  isLoading?: boolean;
12
12
  };
13
- type Message<T = {}> = BaseMessage & T;
13
+ type MessageCore = Pick<BaseMessage, "id" | "role" | "content">;
14
+ type Message<TCustom = unknown> = BaseMessage & {
15
+ custom?: TCustom;
16
+ };
17
+
18
+ type VoiceRecognition = {
19
+ start: () => void;
20
+ stop: () => void;
21
+ isRecording: boolean;
22
+ onTranscript?: (text: string) => void;
23
+ };
14
24
 
15
25
  type Size$1 = 'xs' | 'sm' | 'md' | 'lg';
16
26
  type Props$5 = {
17
- size: Size$1;
27
+ size?: Size$1;
18
28
  };
19
29
  declare function LoadingSpinner({ size }: Props$5): react_jsx_runtime.JSX.Element;
20
30
 
@@ -37,28 +47,22 @@ type Props$3 = Message & {
37
47
  };
38
48
  declare function ChatMessage({ id, role, content, isLoading, wrapperClassName, icon, aiIconWrapperClassName, aiIconColor, bubbleClassName, aiBubbleClassName, userBubbleClassName, position, loadingRenderer, }: Props$3): react_jsx_runtime.JSX.Element;
39
49
 
40
- type MessagePatch = Partial<BaseMessage> & Record<string, unknown>;
41
- type Props$2<T extends Message = Message> = {
42
- messages: T[];
43
- messageMapper?: (msg: T) => MessagePatch;
44
- messageRenderer?: (msg: T) => React$1.ReactNode;
50
+ type Props$2<Raw> = {
51
+ messages: Raw[];
52
+ messageMapper?: (msg: Raw) => Message;
53
+ messageRenderer?: (msg: Message) => React$1.ReactNode;
45
54
  className?: string;
46
55
  loadingRenderer?: React$1.ReactNode;
47
56
  };
48
- declare function ChatList<T extends Message>({ messages, messageMapper, messageRenderer, className, loadingRenderer, }: Props$2<T>): react_jsx_runtime.JSX.Element;
57
+ declare function ChatList<Raw>({ messages, messageMapper, messageRenderer, className, loadingRenderer, }: Props$2<Raw>): react_jsx_runtime.JSX.Element;
49
58
 
50
- type VoiceRecognitionController$1 = {
51
- start: () => void;
52
- stop: () => void;
53
- isRecording: boolean;
54
- };
55
59
  type ButtonConfig = {
56
60
  className?: string;
57
61
  icon?: React.ReactNode;
58
62
  };
59
63
  type Props$1 = {
60
64
  onSend: (value: string) => void | Promise<void>;
61
- voice?: boolean | VoiceRecognitionController$1;
65
+ voice?: boolean | VoiceRecognition;
62
66
  placeholder?: string;
63
67
  className?: string;
64
68
  inputClassName?: string;
@@ -78,9 +82,9 @@ type MessageProps = {
78
82
  messages: Message[];
79
83
  messageMapper?: never;
80
84
  };
81
- type RawProps<T> = {
82
- messages: T[];
83
- messageMapper: (msg: T) => Message;
85
+ type RawProps<Raw> = {
86
+ messages: Raw[];
87
+ messageMapper: (msg: Raw) => Message;
84
88
  };
85
89
  type CommonProps = {
86
90
  messageRenderer?: (msg: Message) => React.ReactNode;
@@ -96,32 +100,27 @@ type CommonProps = {
96
100
  isFetchingNextPage?: boolean;
97
101
  className?: string;
98
102
  };
99
- type Props<T> = CommonProps & (MessageProps | RawProps<T>);
100
- declare function ChatContainer<T>(props: Props<T>): react_jsx_runtime.JSX.Element;
103
+ type Props<Raw> = CommonProps & (MessageProps | RawProps<Raw>);
104
+ declare function ChatContainer<Raw>(props: Props<Raw>): react_jsx_runtime.JSX.Element;
101
105
 
102
- type ExtraFromRaw$1<TRaw> = Omit<TRaw, keyof BaseMessage>;
103
- type CustomMessage$1<TCustom> = BaseMessage & {
104
- custom: TCustom;
105
- };
106
- type MessageMapper$1<TRaw> = CustomMessage$1<ExtraFromRaw$1<TRaw>>;
107
- type MessageMapperResult$1 = Pick<BaseMessage, "id" | "role" | "content">;
108
- type Options$2<TRaw> = {
106
+ type ExtractCustom$1<Raw> = Omit<Raw, keyof BaseMessage>;
107
+ type Options$2<Raw> = {
109
108
  queryKey: readonly unknown[];
110
- queryFn: (pageParam: unknown) => Promise<TRaw[]>;
109
+ queryFn: (pageParam: unknown) => Promise<Raw[]>;
111
110
  initialPageParam: unknown;
112
- getNextPageParam: (lastPage: MessageMapper$1<TRaw>[], allPages: MessageMapper$1<TRaw>[][]) => unknown;
113
- mutationFn: (content: string) => Promise<TRaw>;
114
- map: (raw: TRaw) => MessageMapperResult$1;
111
+ getNextPageParam: (lastPage: Message<ExtractCustom$1<Raw>>[], allPages: Message<ExtractCustom$1<Raw>>[][]) => unknown;
112
+ mutationFn: (content: string) => Promise<Raw>;
113
+ map: (raw: Raw) => MessageCore;
115
114
  onError?: (error: unknown) => void;
116
115
  staleTime?: number;
117
116
  gcTime?: number;
118
117
  };
119
- declare function useChat<TRaw extends object>({ queryKey, queryFn, initialPageParam, getNextPageParam, mutationFn, map, onError, staleTime, gcTime, }: Options$2<TRaw>): {
120
- messages: MessageMapper$1<TRaw>[];
118
+ declare function useChat<Raw extends object>({ queryKey, queryFn, initialPageParam, getNextPageParam, mutationFn, map, onError, staleTime, gcTime, }: Options$2<Raw>): {
119
+ messages: Message<ExtractCustom$1<Raw>>[];
121
120
  sendUserMessage: (content: string) => void;
122
121
  isPending: boolean;
123
122
  isInitialLoading: boolean;
124
- fetchNextPage: (options?: _tanstack_query_core.FetchNextPageOptions) => Promise<_tanstack_query_core.InfiniteQueryObserverResult<InfiniteData<MessageMapper$1<TRaw>[], unknown>, Error>>;
123
+ fetchNextPage: (options?: _tanstack_query_core.FetchNextPageOptions) => Promise<_tanstack_query_core.InfiniteQueryObserverResult<InfiniteData<Message<ExtractCustom$1<Raw>>[], unknown>, Error>>;
125
124
  hasNextPage: boolean;
126
125
  isFetchingNextPage: boolean;
127
126
  };
@@ -196,39 +195,28 @@ declare function useBrowserSpeechRecognition({ lang, onStart, onEnd, onError, }?
196
195
  onTranscript: (text: string) => void;
197
196
  };
198
197
 
199
- type VoiceRecognitionController = {
200
- start: () => void;
201
- stop: () => void;
202
- isRecording: boolean;
203
- onTranscript: (text: string) => void;
204
- };
205
- type ExtraFromRaw<TRaw> = Omit<TRaw, keyof BaseMessage>;
206
- type CustomMessage<TCustom> = BaseMessage & {
207
- custom: TCustom;
208
- };
209
- type MessageMapper<TRaw> = CustomMessage<ExtraFromRaw<TRaw>>;
210
- type MessageMapperResult = Pick<BaseMessage, "id" | "role" | "content">;
211
- type Options<TRaw> = {
198
+ type ExtractCustom<Raw> = Omit<Raw, keyof BaseMessage>;
199
+ type Options<Raw> = {
212
200
  queryKey: readonly unknown[];
213
- queryFn: (pageParam: unknown) => Promise<TRaw[]>;
201
+ queryFn: (pageParam: unknown) => Promise<Raw[]>;
214
202
  initialPageParam: unknown;
215
- getNextPageParam: (lastPage: MessageMapper<TRaw>[], allPages: MessageMapper<TRaw>[][]) => unknown;
216
- mutationFn: (content: string) => Promise<TRaw>;
217
- map: (raw: TRaw) => MessageMapperResult;
218
- voice: VoiceRecognitionController;
203
+ getNextPageParam: (lastPage: Message<ExtractCustom<Raw>>[], allPages: Message<ExtractCustom<Raw>>[][]) => unknown;
204
+ mutationFn: (content: string) => Promise<Raw>;
205
+ map: (raw: Raw) => MessageCore;
206
+ voice: VoiceRecognition;
219
207
  onError?: (error: unknown) => void;
220
208
  staleTime?: number;
221
209
  gcTime?: number;
222
210
  };
223
- declare function useVoiceChat<TRaw extends object>({ queryKey, queryFn, initialPageParam, getNextPageParam, mutationFn, map, voice, onError, staleTime, gcTime, }: Options<TRaw>): {
224
- messages: MessageMapper<TRaw>[];
211
+ declare function useVoiceChat<Raw extends object>({ queryKey, queryFn, initialPageParam, getNextPageParam, mutationFn, map, voice, onError, staleTime, gcTime, }: Options<Raw>): {
212
+ messages: Message<ExtractCustom<Raw>>[];
225
213
  isPending: boolean;
226
214
  isInitialLoading: boolean;
227
215
  startRecording: () => Promise<void>;
228
216
  stopRecording: () => void;
229
- fetchNextPage: (options?: _tanstack_query_core.FetchNextPageOptions) => Promise<_tanstack_query_core.InfiniteQueryObserverResult<InfiniteData<MessageMapper<TRaw>[], unknown>, Error>>;
217
+ fetchNextPage: (options?: _tanstack_query_core.FetchNextPageOptions) => Promise<_tanstack_query_core.InfiniteQueryObserverResult<InfiniteData<Message<ExtractCustom<Raw>>[], unknown>, Error>>;
230
218
  hasNextPage: boolean;
231
219
  isFetchingNextPage: boolean;
232
220
  };
233
221
 
234
- export { ChatContainer, ChatInput, ChatList, ChatMessage, LoadingSpinner, type Message, SendingDots, useBrowserSpeechRecognition, useChat, useVoiceChat };
222
+ export { ChatContainer, ChatInput, ChatList, ChatMessage, LoadingSpinner, type Message, SendingDots, type VoiceRecognition, useBrowserSpeechRecognition, useChat, useVoiceChat };