@melony/react 0.1.21 → 0.1.23
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.cjs +140 -107
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +142 -109
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
package/dist/index.d.cts
CHANGED
|
@@ -2,6 +2,7 @@ import * as React$1 from 'react';
|
|
|
2
2
|
import React__default, { ReactNode } from 'react';
|
|
3
3
|
import { ClientState, MelonyClient } from 'melony/client';
|
|
4
4
|
import { Role, Event, UINode } from 'melony';
|
|
5
|
+
import { QueryClient } from '@tanstack/react-query';
|
|
5
6
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
6
7
|
|
|
7
8
|
interface User {
|
|
@@ -41,6 +42,7 @@ interface ComposerOptionGroup {
|
|
|
41
42
|
label: string;
|
|
42
43
|
options: ComposerOption[];
|
|
43
44
|
type?: "single" | "multiple";
|
|
45
|
+
defaultSelectedIds?: string[];
|
|
44
46
|
}
|
|
45
47
|
interface AuthService {
|
|
46
48
|
getMe: () => Promise<User | null>;
|
|
@@ -63,12 +65,18 @@ interface MelonyContextValue extends ClientState {
|
|
|
63
65
|
}) => Promise<void>;
|
|
64
66
|
reset: (events?: Event[]) => void;
|
|
65
67
|
client: MelonyClient;
|
|
68
|
+
config?: {
|
|
69
|
+
starterPrompts: any[];
|
|
70
|
+
options: any[];
|
|
71
|
+
};
|
|
66
72
|
}
|
|
67
73
|
declare const MelonyContext: React__default.Context<MelonyContextValue | undefined>;
|
|
68
74
|
interface MelonyClientProviderProps {
|
|
69
75
|
children: ReactNode;
|
|
70
76
|
client: MelonyClient;
|
|
71
77
|
initialEvents?: Event[];
|
|
78
|
+
queryClient?: QueryClient;
|
|
79
|
+
configApi?: string;
|
|
72
80
|
}
|
|
73
81
|
declare const MelonyClientProvider: React__default.FC<MelonyClientProviderProps>;
|
|
74
82
|
|
|
@@ -136,7 +144,7 @@ interface ThreadProps {
|
|
|
136
144
|
autoFocus?: boolean;
|
|
137
145
|
defaultSelectedIds?: string[];
|
|
138
146
|
}
|
|
139
|
-
declare function Thread({ className, placeholder, starterPrompts, onStarterPromptClick, options, autoFocus, defaultSelectedIds, }: ThreadProps): react_jsx_runtime.JSX.Element;
|
|
147
|
+
declare function Thread({ className, placeholder, starterPrompts: localStarterPrompts, onStarterPromptClick, options: localOptions, autoFocus, defaultSelectedIds, }: ThreadProps): react_jsx_runtime.JSX.Element;
|
|
140
148
|
|
|
141
149
|
interface ComposerProps {
|
|
142
150
|
value: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import * as React$1 from 'react';
|
|
|
2
2
|
import React__default, { ReactNode } from 'react';
|
|
3
3
|
import { ClientState, MelonyClient } from 'melony/client';
|
|
4
4
|
import { Role, Event, UINode } from 'melony';
|
|
5
|
+
import { QueryClient } from '@tanstack/react-query';
|
|
5
6
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
6
7
|
|
|
7
8
|
interface User {
|
|
@@ -41,6 +42,7 @@ interface ComposerOptionGroup {
|
|
|
41
42
|
label: string;
|
|
42
43
|
options: ComposerOption[];
|
|
43
44
|
type?: "single" | "multiple";
|
|
45
|
+
defaultSelectedIds?: string[];
|
|
44
46
|
}
|
|
45
47
|
interface AuthService {
|
|
46
48
|
getMe: () => Promise<User | null>;
|
|
@@ -63,12 +65,18 @@ interface MelonyContextValue extends ClientState {
|
|
|
63
65
|
}) => Promise<void>;
|
|
64
66
|
reset: (events?: Event[]) => void;
|
|
65
67
|
client: MelonyClient;
|
|
68
|
+
config?: {
|
|
69
|
+
starterPrompts: any[];
|
|
70
|
+
options: any[];
|
|
71
|
+
};
|
|
66
72
|
}
|
|
67
73
|
declare const MelonyContext: React__default.Context<MelonyContextValue | undefined>;
|
|
68
74
|
interface MelonyClientProviderProps {
|
|
69
75
|
children: ReactNode;
|
|
70
76
|
client: MelonyClient;
|
|
71
77
|
initialEvents?: Event[];
|
|
78
|
+
queryClient?: QueryClient;
|
|
79
|
+
configApi?: string;
|
|
72
80
|
}
|
|
73
81
|
declare const MelonyClientProvider: React__default.FC<MelonyClientProviderProps>;
|
|
74
82
|
|
|
@@ -136,7 +144,7 @@ interface ThreadProps {
|
|
|
136
144
|
autoFocus?: boolean;
|
|
137
145
|
defaultSelectedIds?: string[];
|
|
138
146
|
}
|
|
139
|
-
declare function Thread({ className, placeholder, starterPrompts, onStarterPromptClick, options, autoFocus, defaultSelectedIds, }: ThreadProps): react_jsx_runtime.JSX.Element;
|
|
147
|
+
declare function Thread({ className, placeholder, starterPrompts: localStarterPrompts, onStarterPromptClick, options: localOptions, autoFocus, defaultSelectedIds, }: ThreadProps): react_jsx_runtime.JSX.Element;
|
|
140
148
|
|
|
141
149
|
interface ComposerProps {
|
|
142
150
|
value: string;
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import * as React10 from 'react';
|
|
2
|
-
import React10__default, { createContext, useState,
|
|
2
|
+
import React10__default, { createContext, useState, useCallback, useEffect, useMemo, useContext, useRef } from 'react';
|
|
3
|
+
import { NuqsAdapter } from 'nuqs/adapters/react';
|
|
4
|
+
import { QueryClient, QueryClientProvider, useQueryClient, useQuery, useMutation } from '@tanstack/react-query';
|
|
3
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
6
|
import { generateId } from 'melony/client';
|
|
7
|
+
import { useQueryState, parseAsString } from 'nuqs';
|
|
5
8
|
import { clsx } from 'clsx';
|
|
6
9
|
import { twMerge } from 'tailwind-merge';
|
|
7
10
|
import { Button as Button$1 } from '@base-ui/react/button';
|
|
8
11
|
import { cva } from 'class-variance-authority';
|
|
9
12
|
import * as ICONS from '@tabler/icons-react';
|
|
10
|
-
import { IconChevronDown, IconLoader2, IconArrowUp, IconPlus, IconMessage, IconTrash, IconHistory, IconX, IconArrowLeft, IconChevronLeft, IconChevronRight, IconUser, IconLogout, IconBrandGoogle, IconDeviceDesktop, IconMoon, IconSun, IconCheck,
|
|
13
|
+
import { IconChevronDown, IconLoader2, IconArrowUp, IconPlus, IconMessage, IconTrash, IconHistory, IconX, IconArrowLeft, IconChevronLeft, IconChevronRight, IconUser, IconLogout, IconBrandGoogle, IconDeviceDesktop, IconMoon, IconSun, IconCheck, IconChevronUp, IconSelector } from '@tabler/icons-react';
|
|
11
14
|
import { Menu } from '@base-ui/react/menu';
|
|
12
15
|
import { Separator as Separator$1 } from '@base-ui/react/separator';
|
|
13
16
|
import { Dialog as Dialog$1 } from '@base-ui/react/dialog';
|
|
@@ -48,12 +51,28 @@ function groupEventsToMessages(events) {
|
|
|
48
51
|
var MelonyContext = createContext(
|
|
49
52
|
void 0
|
|
50
53
|
);
|
|
51
|
-
var
|
|
54
|
+
var defaultQueryClient = new QueryClient({
|
|
55
|
+
defaultOptions: {
|
|
56
|
+
queries: {
|
|
57
|
+
retry: false,
|
|
58
|
+
refetchOnWindowFocus: false
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
var MelonyContextProviderInner = ({
|
|
52
63
|
children,
|
|
53
64
|
client,
|
|
54
|
-
initialEvents
|
|
65
|
+
initialEvents,
|
|
66
|
+
configApi,
|
|
67
|
+
setContextValue
|
|
55
68
|
}) => {
|
|
56
69
|
const [state, setState] = useState(client.getState());
|
|
70
|
+
const { data: config } = useQuery({
|
|
71
|
+
queryKey: ["melony-config", configApi],
|
|
72
|
+
queryFn: () => client.getConfig(configApi),
|
|
73
|
+
enabled: !!configApi,
|
|
74
|
+
staleTime: Infinity
|
|
75
|
+
});
|
|
57
76
|
useEffect(() => {
|
|
58
77
|
if (initialEvents && initialEvents.length > 0 && client.getState().events.length === 0) {
|
|
59
78
|
client.reset(initialEvents);
|
|
@@ -84,11 +103,34 @@ var MelonyClientProvider = ({
|
|
|
84
103
|
messages: groupEventsToMessages(state.events),
|
|
85
104
|
sendEvent,
|
|
86
105
|
reset,
|
|
87
|
-
client
|
|
106
|
+
client,
|
|
107
|
+
config
|
|
88
108
|
}),
|
|
89
|
-
[state, sendEvent, reset, client]
|
|
109
|
+
[state, sendEvent, reset, client, config]
|
|
90
110
|
);
|
|
91
|
-
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
setContextValue(value);
|
|
113
|
+
}, [value, setContextValue]);
|
|
114
|
+
return /* @__PURE__ */ jsx(NuqsAdapter, { children });
|
|
115
|
+
};
|
|
116
|
+
var MelonyClientProvider = ({
|
|
117
|
+
children,
|
|
118
|
+
client,
|
|
119
|
+
initialEvents,
|
|
120
|
+
queryClient = defaultQueryClient,
|
|
121
|
+
configApi
|
|
122
|
+
}) => {
|
|
123
|
+
const [contextValue, setContextValue] = useState(void 0);
|
|
124
|
+
return /* @__PURE__ */ jsx(MelonyContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx(
|
|
125
|
+
MelonyContextProviderInner,
|
|
126
|
+
{
|
|
127
|
+
client,
|
|
128
|
+
initialEvents,
|
|
129
|
+
configApi,
|
|
130
|
+
setContextValue,
|
|
131
|
+
children
|
|
132
|
+
}
|
|
133
|
+
) }) });
|
|
92
134
|
};
|
|
93
135
|
var AuthContext = createContext(
|
|
94
136
|
void 0
|
|
@@ -161,111 +203,75 @@ var ThreadProvider = ({
|
|
|
161
203
|
service,
|
|
162
204
|
initialThreadId: providedInitialThreadId
|
|
163
205
|
}) => {
|
|
206
|
+
const queryClient = useQueryClient();
|
|
164
207
|
const defaultInitialThreadId = useMemo(() => generateId(), []);
|
|
165
208
|
const initialThreadId = providedInitialThreadId || defaultInitialThreadId;
|
|
166
|
-
const [
|
|
167
|
-
|
|
168
|
-
initialThreadId
|
|
209
|
+
const [activeThreadId, setActiveThreadId] = useQueryState(
|
|
210
|
+
"threadId",
|
|
211
|
+
parseAsString.withDefault(initialThreadId)
|
|
169
212
|
);
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
213
|
+
const {
|
|
214
|
+
data: threads = [],
|
|
215
|
+
isLoading,
|
|
216
|
+
error: threadsError,
|
|
217
|
+
refetch: refreshThreads
|
|
218
|
+
} = useQuery({
|
|
219
|
+
queryKey: ["threads"],
|
|
220
|
+
queryFn: () => service.getThreads()
|
|
221
|
+
});
|
|
222
|
+
const { data: threadEvents = [], isLoading: isLoadingEvents } = useQuery({
|
|
223
|
+
queryKey: ["threads", activeThreadId, "events"],
|
|
224
|
+
queryFn: () => service.getEvents(activeThreadId),
|
|
225
|
+
enabled: !!activeThreadId
|
|
226
|
+
});
|
|
227
|
+
const createMutation = useMutation({
|
|
228
|
+
mutationFn: async () => {
|
|
229
|
+
const newId = service.createThread ? await service.createThread() : generateId();
|
|
230
|
+
return newId;
|
|
231
|
+
},
|
|
232
|
+
onSuccess: async (newId) => {
|
|
233
|
+
await queryClient.invalidateQueries({ queryKey: ["threads"] });
|
|
234
|
+
await setActiveThreadId(newId);
|
|
186
235
|
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
236
|
+
});
|
|
237
|
+
const deleteMutation = useMutation({
|
|
238
|
+
mutationFn: (threadId) => service.deleteThread(threadId),
|
|
239
|
+
onSuccess: async (_, threadId) => {
|
|
240
|
+
await queryClient.invalidateQueries({ queryKey: ["threads"] });
|
|
241
|
+
if (activeThreadId === threadId) {
|
|
242
|
+
const remainingThreads = threads.filter((t) => t.id !== threadId);
|
|
243
|
+
const nextId = remainingThreads.length > 0 ? remainingThreads[0].id : null;
|
|
244
|
+
await setActiveThreadId(nextId);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
const selectThread = useCallback(
|
|
249
|
+
(threadId) => {
|
|
250
|
+
setActiveThreadId(threadId);
|
|
251
|
+
},
|
|
252
|
+
[setActiveThreadId]
|
|
253
|
+
);
|
|
194
254
|
const createThread = useCallback(async () => {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
id: newId,
|
|
198
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
199
|
-
};
|
|
200
|
-
setThreads((prev) => [newThread, ...prev]);
|
|
201
|
-
setActiveThreadId(newId);
|
|
202
|
-
return newId;
|
|
203
|
-
}, [service]);
|
|
255
|
+
return createMutation.mutateAsync();
|
|
256
|
+
}, [createMutation]);
|
|
204
257
|
const deleteThread = useCallback(
|
|
205
258
|
async (threadId) => {
|
|
206
|
-
|
|
207
|
-
await service.deleteThread(threadId);
|
|
208
|
-
setThreads((prev) => {
|
|
209
|
-
const remainingThreads = prev.filter((t) => t.id !== threadId);
|
|
210
|
-
setActiveThreadId((current) => {
|
|
211
|
-
if (current === threadId) {
|
|
212
|
-
return remainingThreads.length > 0 ? remainingThreads[0].id : null;
|
|
213
|
-
}
|
|
214
|
-
return current;
|
|
215
|
-
});
|
|
216
|
-
return remainingThreads;
|
|
217
|
-
});
|
|
218
|
-
} catch (err) {
|
|
219
|
-
const error2 = err instanceof Error ? err : new Error("Failed to delete thread");
|
|
220
|
-
setError(error2);
|
|
221
|
-
throw error2;
|
|
222
|
-
}
|
|
259
|
+
return deleteMutation.mutateAsync(threadId);
|
|
223
260
|
},
|
|
224
|
-
[
|
|
261
|
+
[deleteMutation]
|
|
225
262
|
);
|
|
226
|
-
const refreshThreads = useCallback(async () => {
|
|
227
|
-
await fetchThreads();
|
|
228
|
-
}, [fetchThreads]);
|
|
229
|
-
useEffect(() => {
|
|
230
|
-
if (!activeThreadId) {
|
|
231
|
-
setThreadEvents([]);
|
|
232
|
-
setIsLoadingEvents(false);
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
let cancelled = false;
|
|
236
|
-
const fetchEvents = async () => {
|
|
237
|
-
setIsLoadingEvents(true);
|
|
238
|
-
try {
|
|
239
|
-
const events = await service.getEvents(activeThreadId);
|
|
240
|
-
if (!cancelled) {
|
|
241
|
-
setThreadEvents(events);
|
|
242
|
-
}
|
|
243
|
-
} catch (err) {
|
|
244
|
-
if (!cancelled) {
|
|
245
|
-
console.error("Failed to fetch events:", err);
|
|
246
|
-
setThreadEvents([]);
|
|
247
|
-
}
|
|
248
|
-
} finally {
|
|
249
|
-
if (!cancelled) {
|
|
250
|
-
setIsLoadingEvents(false);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
};
|
|
254
|
-
fetchEvents();
|
|
255
|
-
return () => {
|
|
256
|
-
cancelled = true;
|
|
257
|
-
};
|
|
258
|
-
}, [activeThreadId, service]);
|
|
259
263
|
const value = useMemo(
|
|
260
264
|
() => ({
|
|
261
265
|
threads,
|
|
262
266
|
activeThreadId,
|
|
263
267
|
isLoading,
|
|
264
|
-
error,
|
|
268
|
+
error: threadsError || null,
|
|
265
269
|
selectThread,
|
|
266
270
|
createThread,
|
|
267
271
|
deleteThread,
|
|
268
|
-
refreshThreads
|
|
272
|
+
refreshThreads: async () => {
|
|
273
|
+
await refreshThreads();
|
|
274
|
+
},
|
|
269
275
|
threadEvents,
|
|
270
276
|
isLoadingEvents
|
|
271
277
|
}),
|
|
@@ -273,7 +279,7 @@ var ThreadProvider = ({
|
|
|
273
279
|
threads,
|
|
274
280
|
activeThreadId,
|
|
275
281
|
isLoading,
|
|
276
|
-
|
|
282
|
+
threadsError,
|
|
277
283
|
selectThread,
|
|
278
284
|
createThread,
|
|
279
285
|
deleteThread,
|
|
@@ -343,9 +349,16 @@ var useMelony = (options) => {
|
|
|
343
349
|
}
|
|
344
350
|
const { client, reset } = context;
|
|
345
351
|
const { initialEvents } = options || {};
|
|
352
|
+
const prevInitialEventsRef = useRef(void 0);
|
|
346
353
|
useEffect(() => {
|
|
347
|
-
|
|
348
|
-
|
|
354
|
+
const currentSerialized = initialEvents ? JSON.stringify(initialEvents) : void 0;
|
|
355
|
+
if (currentSerialized !== prevInitialEventsRef.current) {
|
|
356
|
+
if (initialEvents) {
|
|
357
|
+
reset(initialEvents);
|
|
358
|
+
} else {
|
|
359
|
+
reset([]);
|
|
360
|
+
}
|
|
361
|
+
prevInitialEventsRef.current = currentSerialized;
|
|
349
362
|
}
|
|
350
363
|
}, [client, initialEvents, reset]);
|
|
351
364
|
return context;
|
|
@@ -2316,13 +2329,26 @@ function MessageList({
|
|
|
2316
2329
|
function Thread({
|
|
2317
2330
|
className,
|
|
2318
2331
|
placeholder = "Type a message...",
|
|
2319
|
-
starterPrompts,
|
|
2332
|
+
starterPrompts: localStarterPrompts,
|
|
2320
2333
|
onStarterPromptClick,
|
|
2321
|
-
options,
|
|
2334
|
+
options: localOptions,
|
|
2322
2335
|
autoFocus = false,
|
|
2323
2336
|
defaultSelectedIds
|
|
2324
2337
|
}) {
|
|
2325
|
-
const {
|
|
2338
|
+
const { activeThreadId, threadEvents, isLoadingEvents } = useThreads();
|
|
2339
|
+
const { messages, isLoading, error, sendEvent, loadingStatus, config } = useMelony({
|
|
2340
|
+
initialEvents: threadEvents
|
|
2341
|
+
});
|
|
2342
|
+
const starterPrompts = localStarterPrompts ?? config?.starterPrompts;
|
|
2343
|
+
const options = localOptions ?? config?.options;
|
|
2344
|
+
const allDefaultSelectedIds = useMemo(() => {
|
|
2345
|
+
const defaultSelectedIdsFromOptions = options?.flatMap(
|
|
2346
|
+
(group) => group.defaultSelectedIds ?? []
|
|
2347
|
+
) ?? [];
|
|
2348
|
+
return [
|
|
2349
|
+
.../* @__PURE__ */ new Set([...defaultSelectedIdsFromOptions, ...defaultSelectedIds ?? []])
|
|
2350
|
+
];
|
|
2351
|
+
}, [options, defaultSelectedIds]);
|
|
2326
2352
|
const [input, setInput] = useState("");
|
|
2327
2353
|
const messagesEndRef = useRef(null);
|
|
2328
2354
|
useEffect(() => {
|
|
@@ -2338,7 +2364,7 @@ function Thread({
|
|
|
2338
2364
|
role: "user",
|
|
2339
2365
|
data: { content: text }
|
|
2340
2366
|
},
|
|
2341
|
-
{ state }
|
|
2367
|
+
{ state: { ...state, threadId: activeThreadId ?? void 0 } }
|
|
2342
2368
|
);
|
|
2343
2369
|
};
|
|
2344
2370
|
const handleStarterPromptClick = (prompt) => {
|
|
@@ -2348,21 +2374,21 @@ function Thread({
|
|
|
2348
2374
|
handleSubmit(void 0, prompt);
|
|
2349
2375
|
}
|
|
2350
2376
|
};
|
|
2351
|
-
const showStarterPrompts = messages.length === 0 && starterPrompts && starterPrompts.length > 0;
|
|
2377
|
+
const showStarterPrompts = messages.length === 0 && starterPrompts && starterPrompts.length > 0 && !isLoadingEvents;
|
|
2352
2378
|
return /* @__PURE__ */ jsxs(
|
|
2353
2379
|
"div",
|
|
2354
2380
|
{
|
|
2355
2381
|
className: cn("relative flex flex-col h-full bg-background", className),
|
|
2356
2382
|
children: [
|
|
2357
2383
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto p-4 pb-36", children: [
|
|
2358
|
-
/* @__PURE__ */
|
|
2384
|
+
/* @__PURE__ */ jsx(
|
|
2359
2385
|
"div",
|
|
2360
2386
|
{
|
|
2361
2387
|
className: cn(
|
|
2362
2388
|
"max-w-4xl mx-auto w-full p-4",
|
|
2363
2389
|
showStarterPrompts && "min-h-full flex flex-col"
|
|
2364
2390
|
),
|
|
2365
|
-
children: [
|
|
2391
|
+
children: isLoadingEvents && messages.length === 0 ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ jsx(LoadingIndicator, { status: { message: "Loading messages..." } }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2366
2392
|
showStarterPrompts && /* @__PURE__ */ jsx(
|
|
2367
2393
|
StarterPrompts,
|
|
2368
2394
|
{
|
|
@@ -2379,7 +2405,7 @@ function Thread({
|
|
|
2379
2405
|
loadingStatus
|
|
2380
2406
|
}
|
|
2381
2407
|
)
|
|
2382
|
-
]
|
|
2408
|
+
] })
|
|
2383
2409
|
}
|
|
2384
2410
|
),
|
|
2385
2411
|
/* @__PURE__ */ jsx("div", { ref: messagesEndRef })
|
|
@@ -2394,7 +2420,7 @@ function Thread({
|
|
|
2394
2420
|
isLoading,
|
|
2395
2421
|
options,
|
|
2396
2422
|
autoFocus,
|
|
2397
|
-
defaultSelectedIds
|
|
2423
|
+
defaultSelectedIds: allDefaultSelectedIds
|
|
2398
2424
|
}
|
|
2399
2425
|
) }) })
|
|
2400
2426
|
]
|
|
@@ -2422,7 +2448,14 @@ var ThreadList = ({
|
|
|
2422
2448
|
emptyState,
|
|
2423
2449
|
onThreadSelect
|
|
2424
2450
|
}) => {
|
|
2425
|
-
const {
|
|
2451
|
+
const {
|
|
2452
|
+
threads,
|
|
2453
|
+
activeThreadId,
|
|
2454
|
+
selectThread,
|
|
2455
|
+
createThread,
|
|
2456
|
+
deleteThread,
|
|
2457
|
+
isLoading
|
|
2458
|
+
} = useThreads();
|
|
2426
2459
|
const handleThreadClick = (threadId) => {
|
|
2427
2460
|
if (threadId !== activeThreadId) {
|
|
2428
2461
|
selectThread(threadId);
|
|
@@ -2473,7 +2506,7 @@ var ThreadList = ({
|
|
|
2473
2506
|
]
|
|
2474
2507
|
}
|
|
2475
2508
|
) }),
|
|
2476
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto", children: threads.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center text-muted-foreground", children: emptyState || /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
2509
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto", children: isLoading && threads.length === 0 ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsx(IconLoader2, { className: "size-5 animate-spin text-muted-foreground" }) }) : threads.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center text-muted-foreground", children: emptyState || /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
2477
2510
|
/* @__PURE__ */ jsx(IconMessage, { className: "size-8 mx-auto opacity-50" }),
|
|
2478
2511
|
/* @__PURE__ */ jsx("p", { className: "text-sm", children: "No threads yet" }),
|
|
2479
2512
|
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: handleNewThread, children: "Start a conversation" })
|