@assistant-ui/react 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ });