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