@assistant-ui/react 0.0.1 → 0.0.2

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.mjs CHANGED
@@ -10,137 +10,26 @@ __export(thread_exports, {
10
10
  Empty: () => ThreadEmpty,
11
11
  If: () => ThreadIf,
12
12
  Messages: () => ThreadMessages,
13
- Provider: () => ThreadProvider,
14
13
  Root: () => ThreadRoot,
15
14
  Viewport: () => ThreadViewport
16
15
  });
17
16
 
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;
17
+ // src/primitives/thread/ThreadRoot.tsx
18
+ import { forwardRef } from "react";
19
+ import {
20
+ Primitive
21
+ } from "@radix-ui/react-primitive";
22
+ var ThreadRoot = forwardRef(
23
+ (props, ref) => {
24
+ return /* @__PURE__ */ React.createElement(Primitive.div, { ...props, ref });
43
25
  }
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
- };
26
+ );
138
27
 
139
28
  // src/utils/context/createStoreContext.tsx
140
29
  import {
141
30
  createContext,
142
31
  useContext,
143
- useMemo as useMemo2,
32
+ useMemo,
144
33
  useState
145
34
  } from "react";
146
35
  import { useSyncExternalStoreWithSelector } from "use-sync-external-store/with-selector";
@@ -179,7 +68,9 @@ var createStoreContext = (providerName) => {
179
68
  return () => listeners.delete(cb);
180
69
  },
181
70
  emit: () => {
182
- listeners.forEach((l) => l());
71
+ for (const listener of listeners) {
72
+ listener();
73
+ }
183
74
  },
184
75
  snapshot: () => {
185
76
  return state;
@@ -190,7 +81,7 @@ var createStoreContext = (providerName) => {
190
81
  }
191
82
  };
192
83
  });
193
- useMemo2(
84
+ useMemo(
194
85
  () => store.setState(unstableContext),
195
86
  Object.values(unstableContext)
196
87
  );
@@ -216,21 +107,6 @@ var createStoreContext = (providerName) => {
216
107
  // src/utils/context/ThreadContext.ts
217
108
  var [ThreadContextProvider, useThreadContext] = createStoreContext("Thread.Provider");
218
109
 
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
110
  // src/primitives/thread/ThreadIf.tsx
235
111
  var useThreadIf = (props) => {
236
112
  return useThreadContext("Thread.If", (s) => {
@@ -257,15 +133,17 @@ var ThreadEmpty = ({ children }) => {
257
133
  };
258
134
 
259
135
  // 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";
136
+ import { forwardRef as forwardRef2, useRef as useRef2, useState as useState2 } from "react";
137
+ import {
138
+ Primitive as Primitive2
139
+ } from "@radix-ui/react-primitive";
262
140
  import { useComposedRefs } from "@radix-ui/react-compose-refs";
263
141
  import { composeEventHandlers } from "@radix-ui/primitive";
264
142
 
265
143
  // src/utils/hooks/useOnResizeContent.tsx
266
- import { useLayoutEffect, useRef as useRef2 } from "react";
144
+ import { useLayoutEffect, useRef } from "react";
267
145
  var useOnResizeContent = (ref, callback) => {
268
- const callbackRef = useRef2(callback);
146
+ const callbackRef = useRef(callback);
269
147
  callbackRef.current = callback;
270
148
  useLayoutEffect(() => {
271
149
  const el = ref.current;
@@ -273,33 +151,39 @@ var useOnResizeContent = (ref, callback) => {
273
151
  return;
274
152
  const resizeObserver = new ResizeObserver(() => {
275
153
  callbackRef.current();
154
+ console.log("resize observed");
276
155
  });
277
156
  const mutationObserver = new MutationObserver((mutations) => {
278
- mutations.forEach((mutation) => {
279
- mutation.addedNodes.forEach((node) => {
280
- if (node instanceof HTMLElement) {
157
+ for (const mutation of mutations) {
158
+ for (const node of mutation.addedNodes) {
159
+ if (node instanceof Element) {
281
160
  resizeObserver.observe(node);
282
161
  }
283
- });
284
- mutation.removedNodes.forEach((node) => {
285
- if (node instanceof HTMLElement) {
162
+ }
163
+ for (const node of mutation.removedNodes) {
164
+ if (node instanceof Element) {
286
165
  resizeObserver.unobserve(node);
287
166
  }
288
- });
289
- });
167
+ }
168
+ }
290
169
  callbackRef.current();
291
170
  });
292
171
  mutationObserver.observe(el, { childList: true });
172
+ for (const child of el.children) {
173
+ resizeObserver.observe(child);
174
+ console.log("observing child", child);
175
+ }
293
176
  return () => {
177
+ console.log("disconnecting");
294
178
  resizeObserver.disconnect();
295
179
  mutationObserver.disconnect();
296
180
  };
297
- }, []);
181
+ }, [ref.current]);
298
182
  };
299
183
 
300
184
  // src/primitives/thread/ThreadViewport.tsx
301
185
  var ThreadViewport = forwardRef2(({ onScroll, children, ...rest }, forwardedRef) => {
302
- const divRef = useRef3(null);
186
+ const divRef = useRef2(null);
303
187
  const ref = useComposedRefs(forwardedRef, divRef);
304
188
  const [isAtBottom, setIsAtBottom] = useState2(true);
305
189
  useOnResizeContent(divRef, () => {
@@ -312,8 +196,9 @@ var ThreadViewport = forwardRef2(({ onScroll, children, ...rest }, forwardedRef)
312
196
  const div = divRef.current;
313
197
  if (!div)
314
198
  return;
315
- setIsAtBottom(div.scrollHeight - div.scrollTop <= div.clientHeight);
199
+ setIsAtBottom(div.scrollHeight - div.scrollTop <= div.clientHeight + 50);
316
200
  };
201
+ console.log(isAtBottom);
317
202
  return /* @__PURE__ */ React.createElement(
318
203
  Primitive2.div,
319
204
  {
@@ -325,6 +210,127 @@ var ThreadViewport = forwardRef2(({ onScroll, children, ...rest }, forwardedRef)
325
210
  );
326
211
  });
327
212
 
213
+ // src/utils/hooks/useBranches.tsx
214
+ import { useCallback, useMemo as useMemo2, useRef as useRef3 } from "react";
215
+ var ROOT_ID = "__ROOT_ID__";
216
+ var UPCOMING_MESSAGE_ID = "__UPCOMING_MESSAGE_ID__";
217
+ var updateBranchData = (data, messages) => {
218
+ for (let i = 0; i < messages.length; i++) {
219
+ const child = messages[i];
220
+ const childId = child.id;
221
+ const parentId = messages[i - 1]?.id ?? ROOT_ID;
222
+ data.parentMap.set(childId, parentId);
223
+ const parentArray = data.branchMap.get(parentId);
224
+ if (!parentArray) {
225
+ data.branchMap.set(parentId, [childId]);
226
+ } else if (!parentArray.includes(childId)) {
227
+ parentArray.push(childId);
228
+ }
229
+ data.snapshots.set(childId, messages);
230
+ }
231
+ };
232
+ var getParentId = (data, messages, message) => {
233
+ if (message.id === UPCOMING_MESSAGE_ID) {
234
+ const parent = messages.at(-1);
235
+ if (!parent)
236
+ return ROOT_ID;
237
+ return parent.id;
238
+ }
239
+ const parentId = data.parentMap.get(message.id);
240
+ if (!parentId)
241
+ throw new Error("Unexpected: Message parent not found");
242
+ return parentId;
243
+ };
244
+ var getBranchStateImpl = (data, messages, message) => {
245
+ const parentId = getParentId(data, messages, message);
246
+ const branches = data.branchMap.get(parentId) ?? [];
247
+ const branchId = message.id === UPCOMING_MESSAGE_ID ? branches.length : branches.indexOf(message.id);
248
+ if (branchId === -1)
249
+ throw new Error("Unexpected: Message not found in parent children");
250
+ const upcomingOffset = message.id === UPCOMING_MESSAGE_ID ? 1 : 0;
251
+ return {
252
+ branchId,
253
+ branchCount: branches.length + upcomingOffset
254
+ };
255
+ };
256
+ var switchToBranchImpl = (data, messages, message, branchId) => {
257
+ const parentId = getParentId(data, messages, message);
258
+ const branches = data.branchMap.get(parentId);
259
+ if (!branches)
260
+ throw new Error("Unexpected: Parent children not found");
261
+ const newMessageId = branches[branchId];
262
+ if (!newMessageId)
263
+ throw new Error("Unexpected: Requested branch not found");
264
+ if (branchId < 0 || branchId >= branches.length)
265
+ throw new Error("Switch to branch called with a branch index out of range");
266
+ if (newMessageId === message.id)
267
+ return messages;
268
+ const snapshot = data.snapshots.get(newMessageId);
269
+ if (!snapshot)
270
+ throw new Error("Unexpected: Branch snapshot not found");
271
+ return snapshot;
272
+ };
273
+ var sliceMessagesUntil = (messages, message) => {
274
+ if (message.id === UPCOMING_MESSAGE_ID)
275
+ return messages;
276
+ const messageIdx = messages.findIndex((m) => m.id === message.id);
277
+ if (messageIdx === -1)
278
+ throw new Error("Unexpected: Message not found");
279
+ return messages.slice(0, messageIdx);
280
+ };
281
+ var useChatWithBranches = (chat) => {
282
+ const data = useRef3({
283
+ parentMap: /* @__PURE__ */ new Map(),
284
+ branchMap: /* @__PURE__ */ new Map(),
285
+ snapshots: /* @__PURE__ */ new Map()
286
+ }).current;
287
+ updateBranchData(data, chat.messages);
288
+ const getBranchState = useCallback(
289
+ (message) => {
290
+ return getBranchStateImpl(data, chat.messages, message);
291
+ },
292
+ [data, chat.messages]
293
+ );
294
+ const switchToBranch = useCallback(
295
+ (message, branchId) => {
296
+ const newMessages = switchToBranchImpl(
297
+ data,
298
+ chat.messages,
299
+ message,
300
+ branchId
301
+ );
302
+ chat.setMessages(newMessages);
303
+ },
304
+ [data, chat.messages, chat.setMessages]
305
+ );
306
+ const reloadAt = useCallback(
307
+ async (message) => {
308
+ const newMessages = sliceMessagesUntil(chat.messages, message);
309
+ chat.setMessages(newMessages);
310
+ await chat.reload();
311
+ },
312
+ [chat.messages, chat.setMessages, chat.reload]
313
+ );
314
+ const editAt = useCallback(
315
+ async (message, newMessage) => {
316
+ const newMessages = sliceMessagesUntil(chat.messages, message);
317
+ chat.setMessages(newMessages);
318
+ await chat.append(newMessage);
319
+ },
320
+ [chat.messages, chat.setMessages, chat.append]
321
+ );
322
+ return useMemo2(
323
+ () => ({
324
+ ...chat,
325
+ getBranchState,
326
+ switchToBranch,
327
+ editAt,
328
+ reloadAt
329
+ }),
330
+ [chat, getBranchState, switchToBranch, editAt, reloadAt]
331
+ );
332
+ };
333
+
328
334
  // src/primitives/message/index.ts
329
335
  var message_exports = {};
330
336
  __export(message_exports, {
@@ -377,7 +383,9 @@ var MessageProvider = ({
377
383
 
378
384
  // src/primitives/message/MessageRoot.tsx
379
385
  import { forwardRef as forwardRef3 } from "react";
380
- import { Primitive as Primitive3 } from "@radix-ui/react-primitive";
386
+ import {
387
+ Primitive as Primitive3
388
+ } from "@radix-ui/react-primitive";
381
389
  import { composeEventHandlers as composeEventHandlers2 } from "@radix-ui/primitive";
382
390
  var MessageRoot = forwardRef3(
383
391
  ({ onMouseEnter, onMouseLeave, ...rest }, ref) => {
@@ -445,35 +453,10 @@ var MessageContent = () => {
445
453
  };
446
454
 
447
455
  // 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
456
+ import { forwardRef as forwardRef4 } from "react";
472
457
  import { composeEventHandlers as composeEventHandlers3 } from "@radix-ui/primitive";
458
+ import TextareaAutosize from "react-textarea-autosize";
473
459
  var MessageEditableContent = forwardRef4(({ onChange, value, ...rest }, forwardedRef) => {
474
- const textareaRef = useRef4(null);
475
- const ref = useComposedRefs2(forwardedRef, textareaRef);
476
- useAutosize(textareaRef);
477
460
  const [editState, setEditState] = useMessageContext(
478
461
  "Message.EditableContent",
479
462
  (s) => [s.editState, s.setEditState]
@@ -486,10 +469,10 @@ var MessageEditableContent = forwardRef4(({ onChange, value, ...rest }, forwarde
486
469
  "Message.EditableContent may only be rendered when edit mode is enabled. Consider wrapping the component in <Message.If editing>."
487
470
  );
488
471
  return /* @__PURE__ */ React.createElement(
489
- "textarea",
472
+ TextareaAutosize,
490
473
  {
491
474
  ...rest,
492
- ref,
475
+ ref: forwardedRef,
493
476
  onChange: composeEventHandlers3(onChange, handleChange),
494
477
  value: editState.value || value
495
478
  }
@@ -497,15 +480,23 @@ var MessageEditableContent = forwardRef4(({ onChange, value, ...rest }, forwarde
497
480
  });
498
481
 
499
482
  // src/primitives/thread/ThreadMessages.tsx
500
- var ThreadMessages = ({
501
- components: { Message }
502
- }) => {
483
+ var getComponents = (components) => {
484
+ if ("Message" in components) {
485
+ return {
486
+ UserMessage: components.Message,
487
+ AssistantMessage: components.Message
488
+ };
489
+ }
490
+ return components;
491
+ };
492
+ var ThreadMessages = ({ components }) => {
503
493
  const chat = useThreadContext("Thread.Messages", (s) => s.chat);
504
494
  const messages = chat.messages;
495
+ const { UserMessage, AssistantMessage } = getComponents(components);
505
496
  if (messages.length === 0)
506
497
  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));
498
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, messages.map((message) => {
499
+ return /* @__PURE__ */ React.createElement(MessageProvider, { key: message.id, message }, message.role === "assistant" ? /* @__PURE__ */ React.createElement(AssistantMessage, null) : /* @__PURE__ */ React.createElement(UserMessage, null));
509
500
  }), chat.isLoading && chat.messages[chat.messages.length - 1]?.role !== "assistant" && /* @__PURE__ */ React.createElement(
510
501
  MessageProvider,
511
502
  {
@@ -515,7 +506,7 @@ var ThreadMessages = ({
515
506
  content: "..."
516
507
  }
517
508
  },
518
- /* @__PURE__ */ React.createElement(Message, null)
509
+ /* @__PURE__ */ React.createElement(AssistantMessage, null)
519
510
  ));
520
511
  };
521
512
 
@@ -529,10 +520,12 @@ __export(composer_exports, {
529
520
  });
530
521
 
531
522
  // 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";
523
+ import { createContext as createContext2, forwardRef as forwardRef5, useContext as useContext2, useMemo as useMemo4, useRef as useRef4 } from "react";
524
+ import {
525
+ Primitive as Primitive4
526
+ } from "@radix-ui/react-primitive";
534
527
  import { composeEventHandlers as composeEventHandlers4 } from "@radix-ui/primitive";
535
- import { useComposedRefs as useComposedRefs3 } from "@radix-ui/react-compose-refs";
528
+ import { useComposedRefs as useComposedRefs2 } from "@radix-ui/react-compose-refs";
536
529
  var ComposerContext = createContext2(null);
537
530
  var useComposerContext = () => {
538
531
  const context = useContext2(ComposerContext);
@@ -549,8 +542,8 @@ var ComposerRoot = forwardRef5(
549
542
  "Composer.Root",
550
543
  (s) => s.chat.handleSubmit
551
544
  );
552
- const formRef = useRef5(null);
553
- const ref = useComposedRefs3(forwardedRef, formRef);
545
+ const formRef = useRef4(null);
546
+ const ref = useComposedRefs2(forwardedRef, formRef);
554
547
  const composerContextValue = useMemo4(
555
548
  () => ({
556
549
  submit: () => formRef.current?.dispatchEvent(
@@ -571,10 +564,10 @@ var ComposerRoot = forwardRef5(
571
564
  );
572
565
 
573
566
  // src/primitives/composer/ComposerInput.tsx
574
- import { forwardRef as forwardRef6, useRef as useRef6 } from "react";
567
+ import { forwardRef as forwardRef6 } from "react";
575
568
  import { Slot } from "@radix-ui/react-slot";
576
569
  import { composeEventHandlers as composeEventHandlers5 } from "@radix-ui/primitive";
577
- import { useComposedRefs as useComposedRefs4 } from "@radix-ui/react-compose-refs";
570
+ import TextareaAutosize2 from "react-textarea-autosize";
578
571
  var ComposerInput = forwardRef6(({ asChild, onChange, onKeyDown, ...rest }, forwardedRef) => {
579
572
  const chat = useThreadContext(
580
573
  "Composer.Input",
@@ -584,15 +577,12 @@ var ComposerInput = forwardRef6(({ asChild, onChange, onKeyDown, ...rest }, forw
584
577
  isLoading
585
578
  })
586
579
  );
587
- const Component = asChild ? Slot : "textarea";
588
- const textareaRef = useRef6(null);
589
- const ref = useComposedRefs4(forwardedRef, textareaRef);
590
- useAutosize(textareaRef);
580
+ const Component = asChild ? Slot : TextareaAutosize2;
591
581
  const composer = useComposerContext();
592
582
  const handleKeyPress = (e) => {
593
583
  if (chat.isLoading || rest.disabled)
594
584
  return;
595
- if (e.key === "Enter" && e.shiftKey == false) {
585
+ if (e.key === "Enter" && e.shiftKey === false) {
596
586
  e.preventDefault();
597
587
  composer.submit();
598
588
  }
@@ -602,7 +592,7 @@ var ComposerInput = forwardRef6(({ asChild, onChange, onKeyDown, ...rest }, forw
602
592
  {
603
593
  value: chat.input,
604
594
  ...rest,
605
- ref,
595
+ ref: forwardedRef,
606
596
  onChange: composeEventHandlers5(onChange, chat.handleInputChange),
607
597
  onKeyDown: composeEventHandlers5(onKeyDown, handleKeyPress)
608
598
  }
@@ -611,7 +601,9 @@ var ComposerInput = forwardRef6(({ asChild, onChange, onKeyDown, ...rest }, forw
611
601
 
612
602
  // src/primitives/composer/ComposerSend.tsx
613
603
  import { forwardRef as forwardRef7 } from "react";
614
- import { Primitive as Primitive5 } from "@radix-ui/react-primitive";
604
+ import {
605
+ Primitive as Primitive5
606
+ } from "@radix-ui/react-primitive";
615
607
  var ComposerSend = forwardRef7(
616
608
  ({ disabled, ...rest }, ref) => {
617
609
  const input = useThreadContext("Composer.Send", (s) => s.chat.input);
@@ -629,7 +621,9 @@ var ComposerSend = forwardRef7(
629
621
 
630
622
  // src/utils/createActionButton.tsx
631
623
  import { forwardRef as forwardRef8 } from "react";
632
- import { Primitive as Primitive6 } from "@radix-ui/react-primitive";
624
+ import {
625
+ Primitive as Primitive6
626
+ } from "@radix-ui/react-primitive";
633
627
  import { composeEventHandlers as composeEventHandlers6 } from "@radix-ui/primitive";
634
628
  var createActionButton = (useActionButton) => {
635
629
  return forwardRef8(
@@ -671,8 +665,8 @@ __export(branchPicker_exports, {
671
665
  Root: () => BranchPickerRoot
672
666
  });
673
667
 
674
- // src/primitives/branchPicker/BranchPickerNext.tsx
675
- var useBranchPickerNext = () => {
668
+ // src/actions/useGoToNextBranch.tsx
669
+ var useGoToNextBranch = () => {
676
670
  const switchToBranch = useThreadContext(
677
671
  "BranchPicker.Next",
678
672
  (s) => s.chat.switchToBranch
@@ -687,10 +681,12 @@ var useBranchPickerNext = () => {
687
681
  switchToBranch(message, branchId + 1);
688
682
  };
689
683
  };
690
- var BranchPickerNext = createActionButton(useBranchPickerNext);
691
684
 
692
- // src/primitives/branchPicker/BranchPickerPrevious.tsx
693
- var useBranchPickerPrevious = () => {
685
+ // src/primitives/branchPicker/BranchPickerNext.tsx
686
+ var BranchPickerNext = createActionButton(useGoToNextBranch);
687
+
688
+ // src/actions/useGoToPreviousBranch.tsx
689
+ var useGoToPreviousBranch = () => {
694
690
  const switchToBranch = useThreadContext(
695
691
  "BranchPicker.Previous",
696
692
  (s) => s.chat.switchToBranch
@@ -705,7 +701,9 @@ var useBranchPickerPrevious = () => {
705
701
  switchToBranch(message, branchId - 1);
706
702
  };
707
703
  };
708
- var BranchPickerPrevious = createActionButton(useBranchPickerPrevious);
704
+
705
+ // src/primitives/branchPicker/BranchPickerPrevious.tsx
706
+ var BranchPickerPrevious = createActionButton(useGoToPreviousBranch);
709
707
 
710
708
  // src/primitives/branchPicker/BranchPickerCount.tsx
711
709
  var BranchPickerCount = () => {
@@ -726,10 +724,12 @@ var BranchPickerNumber = () => {
726
724
  };
727
725
 
728
726
  // src/primitives/branchPicker/BranchPickerRoot.tsx
727
+ import {
728
+ Primitive as Primitive7
729
+ } from "@radix-ui/react-primitive";
729
730
  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 });
731
+ var BranchPickerRoot = forwardRef9(({ hideWhenSingleBranch, ...rest }, ref) => {
732
+ return /* @__PURE__ */ React.createElement(MessageIf, { hasBranches: hideWhenSingleBranch ? true : void 0 }, /* @__PURE__ */ React.createElement(Primitive7.div, { ...rest, ref }));
733
733
  });
734
734
 
735
735
  // src/primitives/actionBar/index.ts
@@ -742,16 +742,16 @@ __export(actionBar_exports, {
742
742
  });
743
743
 
744
744
  // src/primitives/actionBar/ActionBarRoot.tsx
745
+ import {
746
+ Primitive as Primitive8
747
+ } from "@radix-ui/react-primitive";
745
748
  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
- );
749
+ var ActionBarRoot = forwardRef10(({ hideWhenEditing = false, ...rest }, ref) => {
750
+ return /* @__PURE__ */ React.createElement(MessageIf, { editing: hideWhenEditing ? false : void 0 }, /* @__PURE__ */ React.createElement(Primitive8.div, { ...rest, ref }));
751
+ });
752
752
 
753
- // src/primitives/actionBar/ActionBarCopy.tsx
754
- var useActionBarCopy = ({ copiedDuration = 3e3 }) => {
753
+ // src/actions/useCopyMessage.tsx
754
+ var useCopyMessage = ({ copiedDuration = 3e3 }) => {
755
755
  const [messageContent, setIsCopied] = useMessageContext(
756
756
  "ActionBar.Copy",
757
757
  (s) => [s.message.content, s.setIsCopied]
@@ -762,20 +762,27 @@ var useActionBarCopy = ({ copiedDuration = 3e3 }) => {
762
762
  setTimeout(() => setIsCopied(false), copiedDuration);
763
763
  };
764
764
  };
765
- var ActionBarCopy = createActionButton(useActionBarCopy);
766
765
 
767
- // src/primitives/actionBar/ActionBarReload.tsx
768
- var useActionBarReload = () => {
769
- const chat = useThreadContext("ActionBar.Reload", (s) => s.chat);
766
+ // src/primitives/actionBar/ActionBarCopy.tsx
767
+ var ActionBarCopy = createActionButton(useCopyMessage);
768
+
769
+ // src/actions/useReloadMessage.tsx
770
+ var useReloadMessage = () => {
771
+ const [isLoading, reloadAt] = useThreadContext("ActionBar.Reload", (s) => [
772
+ s.chat.isLoading,
773
+ s.chat.reloadAt
774
+ ]);
770
775
  const message = useMessageContext("ActionBar.Reload", (s) => s.message);
771
- if (message.role !== "assistant" || chat.isLoading)
776
+ if (message.role !== "assistant" || isLoading)
772
777
  return null;
773
- return () => chat.reloadAt(message);
778
+ return () => reloadAt(message);
774
779
  };
775
- var ActionBarReload = createActionButton(useActionBarReload);
776
780
 
777
- // src/primitives/actionBar/ActionBarEdit.tsx
778
- var useActionBarEdit = () => {
781
+ // src/primitives/actionBar/ActionBarReload.tsx
782
+ var ActionBarReload = createActionButton(useReloadMessage);
783
+
784
+ // src/actions/useBeginMessageEdit.tsx
785
+ var useBeginMessageEdit = () => {
779
786
  const [editState, messageContent, setEditState] = useMessageContext(
780
787
  "ActionBar.Edit",
781
788
  (s) => [s.editState, s.message.content, s.setEditState]
@@ -786,7 +793,9 @@ var useActionBarEdit = () => {
786
793
  setEditState({ isEditing: true, value: messageContent });
787
794
  };
788
795
  };
789
- var ActionBarEdit = createActionButton(useActionBarEdit);
796
+
797
+ // src/primitives/actionBar/ActionBarEdit.tsx
798
+ var ActionBarEdit = createActionButton(useBeginMessageEdit);
790
799
 
791
800
  // src/primitives/editBar/index.ts
792
801
  var editBar_exports = {};
@@ -797,16 +806,18 @@ __export(editBar_exports, {
797
806
  });
798
807
 
799
808
  // src/primitives/editBar/EditBarRoot.tsx
809
+ import {
810
+ Primitive as Primitive9
811
+ } from "@radix-ui/react-primitive";
800
812
  import { forwardRef as forwardRef11 } from "react";
801
- import { Primitive as Primitive9 } from "@radix-ui/react-primitive";
802
813
  var EditBarRoot = forwardRef11(
803
- ({ ...rest }, ref) => {
804
- return /* @__PURE__ */ React.createElement(Primitive9.div, { ...rest, ref });
814
+ ({ hideWhenNotEditing, ...rest }, ref) => {
815
+ return /* @__PURE__ */ React.createElement(MessageIf, { editing: hideWhenNotEditing ? true : void 0 }, /* @__PURE__ */ React.createElement(Primitive9.div, { ...rest, ref }));
805
816
  }
806
817
  );
807
818
 
808
- // src/primitives/editBar/EditBarSave.tsx
809
- var useEditBarSave = () => {
819
+ // src/actions/useSaveMessageEdit.tsx
820
+ var useSaveMessageEdit = () => {
810
821
  const chat = useThreadContext("EditBar.Save", (s) => s.chat);
811
822
  const [editState, message, setEditState] = useMessageContext(
812
823
  "EditBar.Save",
@@ -826,10 +837,12 @@ var useEditBarSave = () => {
826
837
  setEditState({ isEditing: false });
827
838
  };
828
839
  };
829
- var EditBarSave = createActionButton(useEditBarSave);
830
840
 
831
- // src/primitives/editBar/EditBarCancel.tsx
832
- var useEditBarCancel = () => {
841
+ // src/primitives/editBar/EditBarSave.tsx
842
+ var EditBarSave = createActionButton(useSaveMessageEdit);
843
+
844
+ // src/actions/useCancelMessageEdit.tsx
845
+ var useCancelMessageEdit = () => {
833
846
  const [isEditing, setEditState] = useMessageContext("EditBar.Cancel", (s) => [
834
847
  s.editState.isEditing,
835
848
  s.setEditState
@@ -840,13 +853,32 @@ var useEditBarCancel = () => {
840
853
  setEditState({ isEditing: false });
841
854
  };
842
855
  };
843
- var EditBarCancel = createActionButton(useEditBarCancel);
856
+
857
+ // src/primitives/editBar/EditBarCancel.tsx
858
+ var EditBarCancel = createActionButton(useCancelMessageEdit);
859
+
860
+ // src/vercel/VercelAIThreadProvider.tsx
861
+ var VercelAIThreadProvider = ({
862
+ chat,
863
+ children
864
+ }) => {
865
+ const branches = useChatWithBranches(chat);
866
+ return /* @__PURE__ */ React.createElement(ThreadContextProvider, { chat: branches }, children);
867
+ };
844
868
  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
869
+ actionBar_exports as ActionBarPrimitive,
870
+ branchPicker_exports as BranchPickerPrimitive,
871
+ composer_exports as ComposerPrimitive,
872
+ editBar_exports as EditBarPrimitive,
873
+ message_exports as MessagePrimitive,
874
+ thread_exports as ThreadPrimitive,
875
+ VercelAIThreadProvider,
876
+ useMessageContext as unstable_useMessageContext,
877
+ useBeginMessageEdit,
878
+ useCancelMessageEdit,
879
+ useCopyMessage,
880
+ useGoToNextBranch,
881
+ useGoToPreviousBranch,
882
+ useReloadMessage,
883
+ useSaveMessageEdit
852
884
  };