@assistant-ui/react 0.0.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 +212 -0
- package/dist/index.d.ts +212 -0
- package/dist/index.js +874 -0
- package/dist/index.mjs +852 -0
- package/package.json +62 -0
package/dist/index.mjs
ADDED
@@ -0,0 +1,852 @@
|
|
1
|
+
var __defProp = Object.defineProperty;
|
2
|
+
var __export = (target, all) => {
|
3
|
+
for (var name in all)
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
5
|
+
};
|
6
|
+
|
7
|
+
// src/primitives/thread/index.ts
|
8
|
+
var thread_exports = {};
|
9
|
+
__export(thread_exports, {
|
10
|
+
Empty: () => ThreadEmpty,
|
11
|
+
If: () => ThreadIf,
|
12
|
+
Messages: () => ThreadMessages,
|
13
|
+
Provider: () => ThreadProvider,
|
14
|
+
Root: () => ThreadRoot,
|
15
|
+
Viewport: () => ThreadViewport
|
16
|
+
});
|
17
|
+
|
18
|
+
// src/utils/hooks/useBranches.tsx
|
19
|
+
import { useCallback, useMemo, useRef } from "react";
|
20
|
+
var ROOT_ID = "__ROOT_ID__";
|
21
|
+
var UPCOMING_MESSAGE_ID = "__UPCOMING_MESSAGE_ID__";
|
22
|
+
var updateBranchData = (data, messages) => {
|
23
|
+
for (let i = 0; i < messages.length; i++) {
|
24
|
+
const child = messages[i];
|
25
|
+
const childId = child.id;
|
26
|
+
const parentId = messages[i - 1]?.id ?? ROOT_ID;
|
27
|
+
data.parentMap.set(childId, parentId);
|
28
|
+
let parentArray = data.branchMap.get(parentId);
|
29
|
+
if (!parentArray) {
|
30
|
+
data.branchMap.set(parentId, [childId]);
|
31
|
+
} else if (!parentArray.includes(childId)) {
|
32
|
+
parentArray.push(childId);
|
33
|
+
}
|
34
|
+
data.snapshots.set(childId, messages);
|
35
|
+
}
|
36
|
+
};
|
37
|
+
var getParentId = (data, messages, message) => {
|
38
|
+
if (message.id === UPCOMING_MESSAGE_ID) {
|
39
|
+
const parent = messages.at(-1);
|
40
|
+
if (!parent)
|
41
|
+
return ROOT_ID;
|
42
|
+
return parent.id;
|
43
|
+
}
|
44
|
+
const parentId = data.parentMap.get(message.id);
|
45
|
+
if (!parentId)
|
46
|
+
throw new Error("Unexpected: Message parent not found");
|
47
|
+
return parentId;
|
48
|
+
};
|
49
|
+
var getBranchStateImpl = (data, messages, message) => {
|
50
|
+
const parentId = getParentId(data, messages, message);
|
51
|
+
const branches = data.branchMap.get(parentId) ?? [];
|
52
|
+
const branchId = message.id === UPCOMING_MESSAGE_ID ? branches.length : branches.indexOf(message.id);
|
53
|
+
if (branchId === -1)
|
54
|
+
throw new Error("Unexpected: Message not found in parent children");
|
55
|
+
const upcomingOffset = message.id === UPCOMING_MESSAGE_ID ? 1 : 0;
|
56
|
+
return {
|
57
|
+
branchId,
|
58
|
+
branchCount: branches.length + upcomingOffset
|
59
|
+
};
|
60
|
+
};
|
61
|
+
var switchToBranchImpl = (data, messages, message, branchId) => {
|
62
|
+
const parentId = getParentId(data, messages, message);
|
63
|
+
const branches = data.branchMap.get(parentId);
|
64
|
+
if (!branches)
|
65
|
+
throw new Error("Unexpected: Parent children not found");
|
66
|
+
const newMessageId = branches[branchId];
|
67
|
+
if (!newMessageId)
|
68
|
+
throw new Error("Unexpected: Requested branch not found");
|
69
|
+
if (branchId < 0 || branchId >= branches.length)
|
70
|
+
throw new Error("Switch to branch called with a branch index out of range");
|
71
|
+
if (newMessageId === message.id)
|
72
|
+
return messages;
|
73
|
+
const snapshot = data.snapshots.get(newMessageId);
|
74
|
+
if (!snapshot)
|
75
|
+
throw new Error("Unexpected: Branch snapshot not found");
|
76
|
+
return snapshot;
|
77
|
+
};
|
78
|
+
var sliceMessagesUntil = (messages, message) => {
|
79
|
+
if (message.id === UPCOMING_MESSAGE_ID)
|
80
|
+
return messages;
|
81
|
+
const messageIdx = messages.findIndex((m) => m.id === message.id);
|
82
|
+
if (messageIdx === -1)
|
83
|
+
throw new Error("Unexpected: Message not found");
|
84
|
+
return messages.slice(0, messageIdx);
|
85
|
+
};
|
86
|
+
var useChatWithBranches = (chat) => {
|
87
|
+
const data = useRef({
|
88
|
+
parentMap: /* @__PURE__ */ new Map(),
|
89
|
+
branchMap: /* @__PURE__ */ new Map(),
|
90
|
+
snapshots: /* @__PURE__ */ new Map()
|
91
|
+
}).current;
|
92
|
+
updateBranchData(data, chat.messages);
|
93
|
+
const getBranchState = useCallback(
|
94
|
+
(message) => {
|
95
|
+
return getBranchStateImpl(data, chat.messages, message);
|
96
|
+
},
|
97
|
+
[chat.messages]
|
98
|
+
);
|
99
|
+
const switchToBranch = useCallback(
|
100
|
+
(message, branchId) => {
|
101
|
+
const newMessages = switchToBranchImpl(
|
102
|
+
data,
|
103
|
+
chat.messages,
|
104
|
+
message,
|
105
|
+
branchId
|
106
|
+
);
|
107
|
+
chat.setMessages(newMessages);
|
108
|
+
},
|
109
|
+
[chat.messages, chat.setMessages]
|
110
|
+
);
|
111
|
+
const reloadAt = useCallback(
|
112
|
+
async (message) => {
|
113
|
+
const newMessages = sliceMessagesUntil(chat.messages, message);
|
114
|
+
chat.setMessages(newMessages);
|
115
|
+
await chat.reload();
|
116
|
+
},
|
117
|
+
[chat.messages, chat.setMessages, chat.reload]
|
118
|
+
);
|
119
|
+
const editAt = useCallback(
|
120
|
+
async (message, newMessage) => {
|
121
|
+
const newMessages = sliceMessagesUntil(chat.messages, message);
|
122
|
+
chat.setMessages(newMessages);
|
123
|
+
await chat.append(newMessage);
|
124
|
+
},
|
125
|
+
[chat.messages, chat.setMessages, chat.append]
|
126
|
+
);
|
127
|
+
return useMemo(
|
128
|
+
() => ({
|
129
|
+
...chat,
|
130
|
+
getBranchState,
|
131
|
+
switchToBranch,
|
132
|
+
editAt,
|
133
|
+
reloadAt
|
134
|
+
}),
|
135
|
+
[chat, getBranchState, switchToBranch, editAt, reloadAt]
|
136
|
+
);
|
137
|
+
};
|
138
|
+
|
139
|
+
// src/utils/context/createStoreContext.tsx
|
140
|
+
import {
|
141
|
+
createContext,
|
142
|
+
useContext,
|
143
|
+
useMemo as useMemo2,
|
144
|
+
useState
|
145
|
+
} from "react";
|
146
|
+
import { useSyncExternalStoreWithSelector } from "use-sync-external-store/with-selector";
|
147
|
+
|
148
|
+
// src/utils/context/shallow.ts
|
149
|
+
function shallow(objA, objB) {
|
150
|
+
if (Object.is(objA, objB)) {
|
151
|
+
return true;
|
152
|
+
}
|
153
|
+
if (typeof objA !== "object" || objA === null || typeof objB !== "object" || objB === null) {
|
154
|
+
return false;
|
155
|
+
}
|
156
|
+
const keysA = Object.keys(objA);
|
157
|
+
if (keysA.length !== Object.keys(objB).length) {
|
158
|
+
return false;
|
159
|
+
}
|
160
|
+
for (const keyA of keysA) {
|
161
|
+
if (!Object.prototype.hasOwnProperty.call(objB, keyA) || !Object.is(objA[keyA], objB[keyA])) {
|
162
|
+
return false;
|
163
|
+
}
|
164
|
+
}
|
165
|
+
return true;
|
166
|
+
}
|
167
|
+
|
168
|
+
// src/utils/context/createStoreContext.tsx
|
169
|
+
var createStoreContext = (providerName) => {
|
170
|
+
const context = createContext(null);
|
171
|
+
const StoreProvider = ({ children, ...rest }) => {
|
172
|
+
const unstableContext = rest;
|
173
|
+
const [store] = useState(() => {
|
174
|
+
let state = unstableContext;
|
175
|
+
const listeners = /* @__PURE__ */ new Set();
|
176
|
+
return {
|
177
|
+
subscribe: (cb) => {
|
178
|
+
listeners.add(cb);
|
179
|
+
return () => listeners.delete(cb);
|
180
|
+
},
|
181
|
+
emit: () => {
|
182
|
+
listeners.forEach((l) => l());
|
183
|
+
},
|
184
|
+
snapshot: () => {
|
185
|
+
return state;
|
186
|
+
},
|
187
|
+
setState: (value) => {
|
188
|
+
state = value;
|
189
|
+
store.emit();
|
190
|
+
}
|
191
|
+
};
|
192
|
+
});
|
193
|
+
useMemo2(
|
194
|
+
() => store.setState(unstableContext),
|
195
|
+
Object.values(unstableContext)
|
196
|
+
);
|
197
|
+
return /* @__PURE__ */ React.createElement(context.Provider, { value: store }, children);
|
198
|
+
};
|
199
|
+
const useStoreContext = (consumerName, selector) => {
|
200
|
+
const store = useContext(context);
|
201
|
+
if (!store)
|
202
|
+
throw new Error(
|
203
|
+
`${consumerName} can only be used inside ${providerName}.`
|
204
|
+
);
|
205
|
+
return useSyncExternalStoreWithSelector(
|
206
|
+
store.subscribe,
|
207
|
+
store.snapshot,
|
208
|
+
store.snapshot,
|
209
|
+
selector,
|
210
|
+
shallow
|
211
|
+
);
|
212
|
+
};
|
213
|
+
return [StoreProvider, useStoreContext];
|
214
|
+
};
|
215
|
+
|
216
|
+
// src/utils/context/ThreadContext.ts
|
217
|
+
var [ThreadContextProvider, useThreadContext] = createStoreContext("Thread.Provider");
|
218
|
+
|
219
|
+
// src/primitives/thread/ThreadProvider.tsx
|
220
|
+
var ThreadProvider = ({ chat, children }) => {
|
221
|
+
const branches = useChatWithBranches(chat);
|
222
|
+
return /* @__PURE__ */ React.createElement(ThreadContextProvider, { chat: branches }, children);
|
223
|
+
};
|
224
|
+
|
225
|
+
// src/primitives/thread/ThreadRoot.tsx
|
226
|
+
import { forwardRef } from "react";
|
227
|
+
import { Primitive } from "@radix-ui/react-primitive";
|
228
|
+
var ThreadRoot = forwardRef(
|
229
|
+
(props, ref) => {
|
230
|
+
return /* @__PURE__ */ React.createElement(Primitive.div, { ...props, ref });
|
231
|
+
}
|
232
|
+
);
|
233
|
+
|
234
|
+
// src/primitives/thread/ThreadIf.tsx
|
235
|
+
var useThreadIf = (props) => {
|
236
|
+
return useThreadContext("Thread.If", (s) => {
|
237
|
+
const thread = s.chat;
|
238
|
+
if (props.empty === true && thread.messages.length !== 0)
|
239
|
+
return false;
|
240
|
+
if (props.empty === false && thread.messages.length === 0)
|
241
|
+
return false;
|
242
|
+
if (props.busy === true && !thread.isLoading)
|
243
|
+
return false;
|
244
|
+
if (props.busy === false && thread.isLoading)
|
245
|
+
return false;
|
246
|
+
return true;
|
247
|
+
});
|
248
|
+
};
|
249
|
+
var ThreadIf = ({ children, ...query }) => {
|
250
|
+
const result = useThreadIf(query);
|
251
|
+
return result ? children : null;
|
252
|
+
};
|
253
|
+
|
254
|
+
// src/primitives/thread/ThreadEmpty.tsx
|
255
|
+
var ThreadEmpty = ({ children }) => {
|
256
|
+
return /* @__PURE__ */ React.createElement(ThreadIf, { empty: true }, children);
|
257
|
+
};
|
258
|
+
|
259
|
+
// src/primitives/thread/ThreadViewport.tsx
|
260
|
+
import { forwardRef as forwardRef2, useRef as useRef3, useState as useState2 } from "react";
|
261
|
+
import { Primitive as Primitive2 } from "@radix-ui/react-primitive";
|
262
|
+
import { useComposedRefs } from "@radix-ui/react-compose-refs";
|
263
|
+
import { composeEventHandlers } from "@radix-ui/primitive";
|
264
|
+
|
265
|
+
// src/utils/hooks/useOnResizeContent.tsx
|
266
|
+
import { useLayoutEffect, useRef as useRef2 } from "react";
|
267
|
+
var useOnResizeContent = (ref, callback) => {
|
268
|
+
const callbackRef = useRef2(callback);
|
269
|
+
callbackRef.current = callback;
|
270
|
+
useLayoutEffect(() => {
|
271
|
+
const el = ref.current;
|
272
|
+
if (!el)
|
273
|
+
return;
|
274
|
+
const resizeObserver = new ResizeObserver(() => {
|
275
|
+
callbackRef.current();
|
276
|
+
});
|
277
|
+
const mutationObserver = new MutationObserver((mutations) => {
|
278
|
+
mutations.forEach((mutation) => {
|
279
|
+
mutation.addedNodes.forEach((node) => {
|
280
|
+
if (node instanceof HTMLElement) {
|
281
|
+
resizeObserver.observe(node);
|
282
|
+
}
|
283
|
+
});
|
284
|
+
mutation.removedNodes.forEach((node) => {
|
285
|
+
if (node instanceof HTMLElement) {
|
286
|
+
resizeObserver.unobserve(node);
|
287
|
+
}
|
288
|
+
});
|
289
|
+
});
|
290
|
+
callbackRef.current();
|
291
|
+
});
|
292
|
+
mutationObserver.observe(el, { childList: true });
|
293
|
+
return () => {
|
294
|
+
resizeObserver.disconnect();
|
295
|
+
mutationObserver.disconnect();
|
296
|
+
};
|
297
|
+
}, []);
|
298
|
+
};
|
299
|
+
|
300
|
+
// src/primitives/thread/ThreadViewport.tsx
|
301
|
+
var ThreadViewport = forwardRef2(({ onScroll, children, ...rest }, forwardedRef) => {
|
302
|
+
const divRef = useRef3(null);
|
303
|
+
const ref = useComposedRefs(forwardedRef, divRef);
|
304
|
+
const [isAtBottom, setIsAtBottom] = useState2(true);
|
305
|
+
useOnResizeContent(divRef, () => {
|
306
|
+
const div = divRef.current;
|
307
|
+
if (!div || !isAtBottom)
|
308
|
+
return;
|
309
|
+
div.scrollTop = div.scrollHeight;
|
310
|
+
});
|
311
|
+
const handleScroll = () => {
|
312
|
+
const div = divRef.current;
|
313
|
+
if (!div)
|
314
|
+
return;
|
315
|
+
setIsAtBottom(div.scrollHeight - div.scrollTop <= div.clientHeight);
|
316
|
+
};
|
317
|
+
return /* @__PURE__ */ React.createElement(
|
318
|
+
Primitive2.div,
|
319
|
+
{
|
320
|
+
...rest,
|
321
|
+
onScroll: composeEventHandlers(onScroll, handleScroll),
|
322
|
+
ref
|
323
|
+
},
|
324
|
+
children
|
325
|
+
);
|
326
|
+
});
|
327
|
+
|
328
|
+
// src/primitives/message/index.ts
|
329
|
+
var message_exports = {};
|
330
|
+
__export(message_exports, {
|
331
|
+
Content: () => MessageContent,
|
332
|
+
EditableContent: () => MessageEditableContent,
|
333
|
+
If: () => MessageIf,
|
334
|
+
Provider: () => MessageProvider,
|
335
|
+
Root: () => MessageRoot
|
336
|
+
});
|
337
|
+
|
338
|
+
// src/primitives/message/MessageProvider.tsx
|
339
|
+
import { useMemo as useMemo3, useState as useState3 } from "react";
|
340
|
+
|
341
|
+
// src/utils/context/MessageContext.ts
|
342
|
+
var [MessageContextProvider, useMessageContext] = createStoreContext("Thread.Provider");
|
343
|
+
|
344
|
+
// src/primitives/message/MessageProvider.tsx
|
345
|
+
var MessageProvider = ({
|
346
|
+
message,
|
347
|
+
children
|
348
|
+
}) => {
|
349
|
+
const getBranchState = useThreadContext(
|
350
|
+
"Message.Provider",
|
351
|
+
(s) => s.chat.getBranchState
|
352
|
+
);
|
353
|
+
const [editState, setEditState] = useState3({
|
354
|
+
isEditing: false
|
355
|
+
});
|
356
|
+
const [isCopied, setIsCopied] = useState3(false);
|
357
|
+
const [isHovering, setIsHovering] = useState3(false);
|
358
|
+
const branchState = useMemo3(
|
359
|
+
() => getBranchState(message),
|
360
|
+
[getBranchState, message]
|
361
|
+
);
|
362
|
+
return /* @__PURE__ */ React.createElement(
|
363
|
+
MessageContextProvider,
|
364
|
+
{
|
365
|
+
message,
|
366
|
+
editState,
|
367
|
+
setEditState,
|
368
|
+
branchState,
|
369
|
+
isCopied,
|
370
|
+
setIsCopied,
|
371
|
+
isHovering,
|
372
|
+
setIsHovering
|
373
|
+
},
|
374
|
+
children
|
375
|
+
);
|
376
|
+
};
|
377
|
+
|
378
|
+
// src/primitives/message/MessageRoot.tsx
|
379
|
+
import { forwardRef as forwardRef3 } from "react";
|
380
|
+
import { Primitive as Primitive3 } from "@radix-ui/react-primitive";
|
381
|
+
import { composeEventHandlers as composeEventHandlers2 } from "@radix-ui/primitive";
|
382
|
+
var MessageRoot = forwardRef3(
|
383
|
+
({ onMouseEnter, onMouseLeave, ...rest }, ref) => {
|
384
|
+
const setIsHovering = useMessageContext(
|
385
|
+
"Message.Root",
|
386
|
+
(s) => s.setIsHovering
|
387
|
+
);
|
388
|
+
const handleMouseEnter = () => {
|
389
|
+
setIsHovering(true);
|
390
|
+
};
|
391
|
+
const handleMouseLeave = () => {
|
392
|
+
setIsHovering(false);
|
393
|
+
};
|
394
|
+
return /* @__PURE__ */ React.createElement(
|
395
|
+
Primitive3.div,
|
396
|
+
{
|
397
|
+
...rest,
|
398
|
+
ref,
|
399
|
+
onMouseEnter: composeEventHandlers2(onMouseEnter, handleMouseEnter),
|
400
|
+
onMouseLeave: composeEventHandlers2(onMouseLeave, handleMouseLeave)
|
401
|
+
}
|
402
|
+
);
|
403
|
+
}
|
404
|
+
);
|
405
|
+
|
406
|
+
// src/primitives/message/MessageIf.tsx
|
407
|
+
var useMessageIf = (props) => {
|
408
|
+
const thread = useThreadContext("Message.If", (s) => s.chat);
|
409
|
+
return useMessageContext(
|
410
|
+
"Message.If",
|
411
|
+
({ message, editState: { isEditing }, isCopied, isHovering }) => {
|
412
|
+
const { branchCount } = thread.getBranchState(message);
|
413
|
+
if (props.hasBranches === true && branchCount < 2)
|
414
|
+
return false;
|
415
|
+
if (props.user && message.role !== "user")
|
416
|
+
return false;
|
417
|
+
if (props.assistant && message.role !== "assistant")
|
418
|
+
return false;
|
419
|
+
if (props.editing === true && !isEditing)
|
420
|
+
return false;
|
421
|
+
if (props.editing === false && isEditing)
|
422
|
+
return false;
|
423
|
+
if (props.unstable_hoveringOrLast === true && !isHovering && thread.messages[thread.messages.length - 1]?.id !== message.id)
|
424
|
+
return false;
|
425
|
+
if (props.copied === true && !isCopied)
|
426
|
+
return false;
|
427
|
+
if (props.copied === false && isCopied)
|
428
|
+
return false;
|
429
|
+
return true;
|
430
|
+
}
|
431
|
+
);
|
432
|
+
};
|
433
|
+
var MessageIf = ({ children, ...query }) => {
|
434
|
+
const result = useMessageIf(query);
|
435
|
+
return result ? children : null;
|
436
|
+
};
|
437
|
+
|
438
|
+
// src/primitives/message/MessageContent.tsx
|
439
|
+
var MessageContent = () => {
|
440
|
+
const content = useMessageContext(
|
441
|
+
"Message.Content",
|
442
|
+
(s) => s.message.content
|
443
|
+
);
|
444
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, content);
|
445
|
+
};
|
446
|
+
|
447
|
+
// src/primitives/message/MessageEditableContent.tsx
|
448
|
+
import { useComposedRefs as useComposedRefs2 } from "@radix-ui/react-compose-refs";
|
449
|
+
import { forwardRef as forwardRef4, useRef as useRef4 } from "react";
|
450
|
+
|
451
|
+
// src/utils/hooks/useAutosize.tsx
|
452
|
+
import { useLayoutEffect as useLayoutEffect2 } from "react";
|
453
|
+
var useAutosize = (ref) => {
|
454
|
+
const el = ref.current;
|
455
|
+
useLayoutEffect2(() => {
|
456
|
+
const el2 = ref.current;
|
457
|
+
if (!el2)
|
458
|
+
return;
|
459
|
+
const callback = () => {
|
460
|
+
el2.style.height = "0px";
|
461
|
+
el2.style.height = el2.scrollHeight + "px";
|
462
|
+
};
|
463
|
+
el2.addEventListener("input", callback);
|
464
|
+
callback();
|
465
|
+
return () => {
|
466
|
+
el2.removeEventListener("input", callback);
|
467
|
+
};
|
468
|
+
}, [ref, el]);
|
469
|
+
};
|
470
|
+
|
471
|
+
// src/primitives/message/MessageEditableContent.tsx
|
472
|
+
import { composeEventHandlers as composeEventHandlers3 } from "@radix-ui/primitive";
|
473
|
+
var MessageEditableContent = forwardRef4(({ onChange, value, ...rest }, forwardedRef) => {
|
474
|
+
const textareaRef = useRef4(null);
|
475
|
+
const ref = useComposedRefs2(forwardedRef, textareaRef);
|
476
|
+
useAutosize(textareaRef);
|
477
|
+
const [editState, setEditState] = useMessageContext(
|
478
|
+
"Message.EditableContent",
|
479
|
+
(s) => [s.editState, s.setEditState]
|
480
|
+
);
|
481
|
+
const handleChange = (e) => {
|
482
|
+
setEditState({ isEditing: true, value: e.target.value });
|
483
|
+
};
|
484
|
+
if (!editState.isEditing)
|
485
|
+
throw new Error(
|
486
|
+
"Message.EditableContent may only be rendered when edit mode is enabled. Consider wrapping the component in <Message.If editing>."
|
487
|
+
);
|
488
|
+
return /* @__PURE__ */ React.createElement(
|
489
|
+
"textarea",
|
490
|
+
{
|
491
|
+
...rest,
|
492
|
+
ref,
|
493
|
+
onChange: composeEventHandlers3(onChange, handleChange),
|
494
|
+
value: editState.value || value
|
495
|
+
}
|
496
|
+
);
|
497
|
+
});
|
498
|
+
|
499
|
+
// src/primitives/thread/ThreadMessages.tsx
|
500
|
+
var ThreadMessages = ({
|
501
|
+
components: { Message }
|
502
|
+
}) => {
|
503
|
+
const chat = useThreadContext("Thread.Messages", (s) => s.chat);
|
504
|
+
const messages = chat.messages;
|
505
|
+
if (messages.length === 0)
|
506
|
+
return null;
|
507
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, messages.map((message, index) => {
|
508
|
+
return /* @__PURE__ */ React.createElement(MessageProvider, { key: index, message }, /* @__PURE__ */ React.createElement(Message, null));
|
509
|
+
}), chat.isLoading && chat.messages[chat.messages.length - 1]?.role !== "assistant" && /* @__PURE__ */ React.createElement(
|
510
|
+
MessageProvider,
|
511
|
+
{
|
512
|
+
message: {
|
513
|
+
id: UPCOMING_MESSAGE_ID,
|
514
|
+
role: "assistant",
|
515
|
+
content: "..."
|
516
|
+
}
|
517
|
+
},
|
518
|
+
/* @__PURE__ */ React.createElement(Message, null)
|
519
|
+
));
|
520
|
+
};
|
521
|
+
|
522
|
+
// src/primitives/composer/index.ts
|
523
|
+
var composer_exports = {};
|
524
|
+
__export(composer_exports, {
|
525
|
+
Input: () => ComposerInput,
|
526
|
+
Root: () => ComposerRoot,
|
527
|
+
Send: () => ComposerSend,
|
528
|
+
Stop: () => ComposerStop
|
529
|
+
});
|
530
|
+
|
531
|
+
// src/primitives/composer/ComposerRoot.tsx
|
532
|
+
import { createContext as createContext2, forwardRef as forwardRef5, useContext as useContext2, useMemo as useMemo4, useRef as useRef5 } from "react";
|
533
|
+
import { Primitive as Primitive4 } from "@radix-ui/react-primitive";
|
534
|
+
import { composeEventHandlers as composeEventHandlers4 } from "@radix-ui/primitive";
|
535
|
+
import { useComposedRefs as useComposedRefs3 } from "@radix-ui/react-compose-refs";
|
536
|
+
var ComposerContext = createContext2(null);
|
537
|
+
var useComposerContext = () => {
|
538
|
+
const context = useContext2(ComposerContext);
|
539
|
+
if (!context) {
|
540
|
+
throw new Error(
|
541
|
+
"Composer compound components cannot be rendered outside the Composer component"
|
542
|
+
);
|
543
|
+
}
|
544
|
+
return context;
|
545
|
+
};
|
546
|
+
var ComposerRoot = forwardRef5(
|
547
|
+
({ onSubmit, ...rest }, forwardedRef) => {
|
548
|
+
const handleSubmit = useThreadContext(
|
549
|
+
"Composer.Root",
|
550
|
+
(s) => s.chat.handleSubmit
|
551
|
+
);
|
552
|
+
const formRef = useRef5(null);
|
553
|
+
const ref = useComposedRefs3(forwardedRef, formRef);
|
554
|
+
const composerContextValue = useMemo4(
|
555
|
+
() => ({
|
556
|
+
submit: () => formRef.current?.dispatchEvent(
|
557
|
+
new Event("submit", { cancelable: true, bubbles: true })
|
558
|
+
)
|
559
|
+
}),
|
560
|
+
[]
|
561
|
+
);
|
562
|
+
return /* @__PURE__ */ React.createElement(ComposerContext.Provider, { value: composerContextValue }, /* @__PURE__ */ React.createElement(
|
563
|
+
Primitive4.form,
|
564
|
+
{
|
565
|
+
...rest,
|
566
|
+
ref,
|
567
|
+
onSubmit: composeEventHandlers4(onSubmit, handleSubmit)
|
568
|
+
}
|
569
|
+
));
|
570
|
+
}
|
571
|
+
);
|
572
|
+
|
573
|
+
// src/primitives/composer/ComposerInput.tsx
|
574
|
+
import { forwardRef as forwardRef6, useRef as useRef6 } from "react";
|
575
|
+
import { Slot } from "@radix-ui/react-slot";
|
576
|
+
import { composeEventHandlers as composeEventHandlers5 } from "@radix-ui/primitive";
|
577
|
+
import { useComposedRefs as useComposedRefs4 } from "@radix-ui/react-compose-refs";
|
578
|
+
var ComposerInput = forwardRef6(({ asChild, onChange, onKeyDown, ...rest }, forwardedRef) => {
|
579
|
+
const chat = useThreadContext(
|
580
|
+
"Composer.Input",
|
581
|
+
({ chat: { input, handleInputChange, isLoading } }) => ({
|
582
|
+
input,
|
583
|
+
handleInputChange,
|
584
|
+
isLoading
|
585
|
+
})
|
586
|
+
);
|
587
|
+
const Component = asChild ? Slot : "textarea";
|
588
|
+
const textareaRef = useRef6(null);
|
589
|
+
const ref = useComposedRefs4(forwardedRef, textareaRef);
|
590
|
+
useAutosize(textareaRef);
|
591
|
+
const composer = useComposerContext();
|
592
|
+
const handleKeyPress = (e) => {
|
593
|
+
if (chat.isLoading || rest.disabled)
|
594
|
+
return;
|
595
|
+
if (e.key === "Enter" && e.shiftKey == false) {
|
596
|
+
e.preventDefault();
|
597
|
+
composer.submit();
|
598
|
+
}
|
599
|
+
};
|
600
|
+
return /* @__PURE__ */ React.createElement(
|
601
|
+
Component,
|
602
|
+
{
|
603
|
+
value: chat.input,
|
604
|
+
...rest,
|
605
|
+
ref,
|
606
|
+
onChange: composeEventHandlers5(onChange, chat.handleInputChange),
|
607
|
+
onKeyDown: composeEventHandlers5(onKeyDown, handleKeyPress)
|
608
|
+
}
|
609
|
+
);
|
610
|
+
});
|
611
|
+
|
612
|
+
// src/primitives/composer/ComposerSend.tsx
|
613
|
+
import { forwardRef as forwardRef7 } from "react";
|
614
|
+
import { Primitive as Primitive5 } from "@radix-ui/react-primitive";
|
615
|
+
var ComposerSend = forwardRef7(
|
616
|
+
({ disabled, ...rest }, ref) => {
|
617
|
+
const input = useThreadContext("Composer.Send", (s) => s.chat.input);
|
618
|
+
return /* @__PURE__ */ React.createElement(
|
619
|
+
Primitive5.button,
|
620
|
+
{
|
621
|
+
type: "submit",
|
622
|
+
...rest,
|
623
|
+
ref,
|
624
|
+
disabled: disabled || input.length === 0
|
625
|
+
}
|
626
|
+
);
|
627
|
+
}
|
628
|
+
);
|
629
|
+
|
630
|
+
// src/utils/createActionButton.tsx
|
631
|
+
import { forwardRef as forwardRef8 } from "react";
|
632
|
+
import { Primitive as Primitive6 } from "@radix-ui/react-primitive";
|
633
|
+
import { composeEventHandlers as composeEventHandlers6 } from "@radix-ui/primitive";
|
634
|
+
var createActionButton = (useActionButton) => {
|
635
|
+
return forwardRef8(
|
636
|
+
(props, forwardedRef) => {
|
637
|
+
const onClick = useActionButton(props);
|
638
|
+
return /* @__PURE__ */ React.createElement(
|
639
|
+
Primitive6.button,
|
640
|
+
{
|
641
|
+
type: "button",
|
642
|
+
disabled: !onClick,
|
643
|
+
...props,
|
644
|
+
ref: forwardedRef,
|
645
|
+
onClick: composeEventHandlers6(props.onClick, onClick ?? void 0)
|
646
|
+
}
|
647
|
+
);
|
648
|
+
}
|
649
|
+
);
|
650
|
+
};
|
651
|
+
|
652
|
+
// src/primitives/composer/ComposerStop.tsx
|
653
|
+
var useComposerStop = () => {
|
654
|
+
const [isLoading, stop] = useThreadContext("Composer.Stop", (s) => [
|
655
|
+
s.chat.isLoading,
|
656
|
+
s.chat.stop
|
657
|
+
]);
|
658
|
+
if (!isLoading)
|
659
|
+
return null;
|
660
|
+
return stop;
|
661
|
+
};
|
662
|
+
var ComposerStop = createActionButton(useComposerStop);
|
663
|
+
|
664
|
+
// src/primitives/branchPicker/index.ts
|
665
|
+
var branchPicker_exports = {};
|
666
|
+
__export(branchPicker_exports, {
|
667
|
+
Count: () => BranchPickerCount,
|
668
|
+
Next: () => BranchPickerNext,
|
669
|
+
Number: () => BranchPickerNumber,
|
670
|
+
Previous: () => BranchPickerPrevious,
|
671
|
+
Root: () => BranchPickerRoot
|
672
|
+
});
|
673
|
+
|
674
|
+
// src/primitives/branchPicker/BranchPickerNext.tsx
|
675
|
+
var useBranchPickerNext = () => {
|
676
|
+
const switchToBranch = useThreadContext(
|
677
|
+
"BranchPicker.Next",
|
678
|
+
(s) => s.chat.switchToBranch
|
679
|
+
);
|
680
|
+
const [message, { branchId, branchCount }] = useMessageContext(
|
681
|
+
"BranchPicker.Next",
|
682
|
+
(s) => [s.message, s.branchState]
|
683
|
+
);
|
684
|
+
if (branchCount <= 1 || branchId + 1 >= branchCount)
|
685
|
+
return null;
|
686
|
+
return () => {
|
687
|
+
switchToBranch(message, branchId + 1);
|
688
|
+
};
|
689
|
+
};
|
690
|
+
var BranchPickerNext = createActionButton(useBranchPickerNext);
|
691
|
+
|
692
|
+
// src/primitives/branchPicker/BranchPickerPrevious.tsx
|
693
|
+
var useBranchPickerPrevious = () => {
|
694
|
+
const switchToBranch = useThreadContext(
|
695
|
+
"BranchPicker.Previous",
|
696
|
+
(s) => s.chat.switchToBranch
|
697
|
+
);
|
698
|
+
const [message, { branchId, branchCount }] = useMessageContext(
|
699
|
+
"BranchPicker.Previous",
|
700
|
+
(s) => [s.message, s.branchState]
|
701
|
+
);
|
702
|
+
if (branchCount <= 1 || branchId <= 0)
|
703
|
+
return null;
|
704
|
+
return () => {
|
705
|
+
switchToBranch(message, branchId - 1);
|
706
|
+
};
|
707
|
+
};
|
708
|
+
var BranchPickerPrevious = createActionButton(useBranchPickerPrevious);
|
709
|
+
|
710
|
+
// src/primitives/branchPicker/BranchPickerCount.tsx
|
711
|
+
var BranchPickerCount = () => {
|
712
|
+
const branchCount = useMessageContext(
|
713
|
+
"BranchPicker.Count",
|
714
|
+
(s) => s.branchState.branchCount
|
715
|
+
);
|
716
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, branchCount);
|
717
|
+
};
|
718
|
+
|
719
|
+
// src/primitives/branchPicker/BranchPickerNumber.tsx
|
720
|
+
var BranchPickerNumber = () => {
|
721
|
+
const branchId = useMessageContext(
|
722
|
+
"BranchPicker.Number",
|
723
|
+
(s) => s.branchState.branchId
|
724
|
+
);
|
725
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, branchId + 1);
|
726
|
+
};
|
727
|
+
|
728
|
+
// src/primitives/branchPicker/BranchPickerRoot.tsx
|
729
|
+
import { forwardRef as forwardRef9 } from "react";
|
730
|
+
import { Primitive as Primitive7 } from "@radix-ui/react-primitive";
|
731
|
+
var BranchPickerRoot = forwardRef9(({ ...rest }, ref) => {
|
732
|
+
return /* @__PURE__ */ React.createElement(Primitive7.div, { ...rest, ref });
|
733
|
+
});
|
734
|
+
|
735
|
+
// src/primitives/actionBar/index.ts
|
736
|
+
var actionBar_exports = {};
|
737
|
+
__export(actionBar_exports, {
|
738
|
+
Copy: () => ActionBarCopy,
|
739
|
+
Edit: () => ActionBarEdit,
|
740
|
+
Reload: () => ActionBarReload,
|
741
|
+
Root: () => ActionBarRoot
|
742
|
+
});
|
743
|
+
|
744
|
+
// src/primitives/actionBar/ActionBarRoot.tsx
|
745
|
+
import { forwardRef as forwardRef10 } from "react";
|
746
|
+
import { Primitive as Primitive8 } from "@radix-ui/react-primitive";
|
747
|
+
var ActionBarRoot = forwardRef10(
|
748
|
+
({ ...rest }, ref) => {
|
749
|
+
return /* @__PURE__ */ React.createElement(Primitive8.div, { ...rest, ref });
|
750
|
+
}
|
751
|
+
);
|
752
|
+
|
753
|
+
// src/primitives/actionBar/ActionBarCopy.tsx
|
754
|
+
var useActionBarCopy = ({ copiedDuration = 3e3 }) => {
|
755
|
+
const [messageContent, setIsCopied] = useMessageContext(
|
756
|
+
"ActionBar.Copy",
|
757
|
+
(s) => [s.message.content, s.setIsCopied]
|
758
|
+
);
|
759
|
+
return () => {
|
760
|
+
navigator.clipboard.writeText(messageContent);
|
761
|
+
setIsCopied(true);
|
762
|
+
setTimeout(() => setIsCopied(false), copiedDuration);
|
763
|
+
};
|
764
|
+
};
|
765
|
+
var ActionBarCopy = createActionButton(useActionBarCopy);
|
766
|
+
|
767
|
+
// src/primitives/actionBar/ActionBarReload.tsx
|
768
|
+
var useActionBarReload = () => {
|
769
|
+
const chat = useThreadContext("ActionBar.Reload", (s) => s.chat);
|
770
|
+
const message = useMessageContext("ActionBar.Reload", (s) => s.message);
|
771
|
+
if (message.role !== "assistant" || chat.isLoading)
|
772
|
+
return null;
|
773
|
+
return () => chat.reloadAt(message);
|
774
|
+
};
|
775
|
+
var ActionBarReload = createActionButton(useActionBarReload);
|
776
|
+
|
777
|
+
// src/primitives/actionBar/ActionBarEdit.tsx
|
778
|
+
var useActionBarEdit = () => {
|
779
|
+
const [editState, messageContent, setEditState] = useMessageContext(
|
780
|
+
"ActionBar.Edit",
|
781
|
+
(s) => [s.editState, s.message.content, s.setEditState]
|
782
|
+
);
|
783
|
+
if (editState.isEditing)
|
784
|
+
return null;
|
785
|
+
return () => {
|
786
|
+
setEditState({ isEditing: true, value: messageContent });
|
787
|
+
};
|
788
|
+
};
|
789
|
+
var ActionBarEdit = createActionButton(useActionBarEdit);
|
790
|
+
|
791
|
+
// src/primitives/editBar/index.ts
|
792
|
+
var editBar_exports = {};
|
793
|
+
__export(editBar_exports, {
|
794
|
+
Cancel: () => EditBarCancel,
|
795
|
+
Root: () => EditBarRoot,
|
796
|
+
Save: () => EditBarSave
|
797
|
+
});
|
798
|
+
|
799
|
+
// src/primitives/editBar/EditBarRoot.tsx
|
800
|
+
import { forwardRef as forwardRef11 } from "react";
|
801
|
+
import { Primitive as Primitive9 } from "@radix-ui/react-primitive";
|
802
|
+
var EditBarRoot = forwardRef11(
|
803
|
+
({ ...rest }, ref) => {
|
804
|
+
return /* @__PURE__ */ React.createElement(Primitive9.div, { ...rest, ref });
|
805
|
+
}
|
806
|
+
);
|
807
|
+
|
808
|
+
// src/primitives/editBar/EditBarSave.tsx
|
809
|
+
var useEditBarSave = () => {
|
810
|
+
const chat = useThreadContext("EditBar.Save", (s) => s.chat);
|
811
|
+
const [editState, message, setEditState] = useMessageContext(
|
812
|
+
"EditBar.Save",
|
813
|
+
(s) => [s.editState, s.message, s.setEditState]
|
814
|
+
);
|
815
|
+
if (!editState.isEditing)
|
816
|
+
return null;
|
817
|
+
return () => {
|
818
|
+
if (!editState.isEditing)
|
819
|
+
return;
|
820
|
+
chat.editAt(message, {
|
821
|
+
...message,
|
822
|
+
id: void 0,
|
823
|
+
// remove id to create a new message
|
824
|
+
content: editState.value
|
825
|
+
});
|
826
|
+
setEditState({ isEditing: false });
|
827
|
+
};
|
828
|
+
};
|
829
|
+
var EditBarSave = createActionButton(useEditBarSave);
|
830
|
+
|
831
|
+
// src/primitives/editBar/EditBarCancel.tsx
|
832
|
+
var useEditBarCancel = () => {
|
833
|
+
const [isEditing, setEditState] = useMessageContext("EditBar.Cancel", (s) => [
|
834
|
+
s.editState.isEditing,
|
835
|
+
s.setEditState
|
836
|
+
]);
|
837
|
+
if (!isEditing)
|
838
|
+
return null;
|
839
|
+
return () => {
|
840
|
+
setEditState({ isEditing: false });
|
841
|
+
};
|
842
|
+
};
|
843
|
+
var EditBarCancel = createActionButton(useEditBarCancel);
|
844
|
+
export {
|
845
|
+
actionBar_exports as ActionBar,
|
846
|
+
branchPicker_exports as BranchPicker,
|
847
|
+
composer_exports as Composer,
|
848
|
+
editBar_exports as EditBar,
|
849
|
+
message_exports as Message,
|
850
|
+
thread_exports as Thread,
|
851
|
+
useMessageContext as unstable_useMessageContext
|
852
|
+
};
|