@anvia/react-ui 1.3.0 → 1.3.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.
Files changed (133) hide show
  1. package/dist/attachment/index.d.ts +3 -21
  2. package/dist/attachment/index.js +3 -12
  3. package/dist/attachment-By2pged3.js +91 -0
  4. package/dist/attachment-By2pged3.js.map +1 -0
  5. package/dist/chat/index.d.ts +3 -152
  6. package/dist/chat/index.js +3 -25
  7. package/dist/chat-Dgz8hsVT.js +1210 -0
  8. package/dist/chat-Dgz8hsVT.js.map +1 -0
  9. package/dist/completion/index.d.ts +3 -29
  10. package/dist/completion/index.js +3 -16
  11. package/dist/completion-DDTKoZRJ.js +124 -0
  12. package/dist/completion-DDTKoZRJ.js.map +1 -0
  13. package/dist/connection-DeNq8wHS.js +203 -0
  14. package/dist/connection-DeNq8wHS.js.map +1 -0
  15. package/dist/contexts-B4ijG24z.js +212 -0
  16. package/dist/contexts-B4ijG24z.js.map +1 -0
  17. package/dist/elements-D4vmkkF8.js +19 -0
  18. package/dist/elements-D4vmkkF8.js.map +1 -0
  19. package/dist/graph-explorer/index.d.ts +54 -73
  20. package/dist/graph-explorer/index.d.ts.map +1 -0
  21. package/dist/graph-explorer/index.js +181 -248
  22. package/dist/graph-explorer/index.js.map +1 -1
  23. package/dist/human-input/index.d.ts +3 -78
  24. package/dist/human-input/index.js +3 -21
  25. package/dist/human-input-CsCbZomZ.js +314 -0
  26. package/dist/human-input-CsCbZomZ.js.map +1 -0
  27. package/dist/image/index.d.ts +3 -40
  28. package/dist/image/index.js +3 -12
  29. package/dist/image-aCWm6hFe.js +303 -0
  30. package/dist/image-aCWm6hFe.js.map +1 -0
  31. package/dist/index-B1Qs2Cjv.d.ts +145 -0
  32. package/dist/index-B1Qs2Cjv.d.ts.map +1 -0
  33. package/dist/index-BCBVcl0D.d.ts +277 -0
  34. package/dist/index-BCBVcl0D.d.ts.map +1 -0
  35. package/dist/index-CE22tsua.d.ts +20 -0
  36. package/dist/index-CE22tsua.d.ts.map +1 -0
  37. package/dist/index-CGqtpc6b.d.ts +25 -0
  38. package/dist/index-CGqtpc6b.d.ts.map +1 -0
  39. package/dist/index-DqdyM0Jm.d.ts +7 -0
  40. package/dist/index-DqdyM0Jm.d.ts.map +1 -0
  41. package/dist/index-Mw3ltwSG.d.ts +318 -0
  42. package/dist/index-Mw3ltwSG.d.ts.map +1 -0
  43. package/dist/index.d.ts +7 -40
  44. package/dist/index.js +34 -118
  45. package/dist/index.js.map +1 -1
  46. package/dist/message/index.d.ts +3 -105
  47. package/dist/message/index.js +3 -20
  48. package/dist/message-CElFEKgL.js +783 -0
  49. package/dist/message-CElFEKgL.js.map +1 -0
  50. package/dist/primitives-xfE7zfwJ.js +15 -0
  51. package/dist/primitives-xfE7zfwJ.js.map +1 -0
  52. package/dist/refs-Djj9rSvB.js +10 -0
  53. package/dist/refs-Djj9rSvB.js.map +1 -0
  54. package/dist/sandbox-desktop/index.d.ts +100 -104
  55. package/dist/sandbox-desktop/index.d.ts.map +1 -0
  56. package/dist/sandbox-desktop/index.js +344 -342
  57. package/dist/sandbox-desktop/index.js.map +1 -1
  58. package/dist/sandbox-terminal/index.d.ts +52 -56
  59. package/dist/sandbox-terminal/index.d.ts.map +1 -0
  60. package/dist/sandbox-terminal/index.js +217 -208
  61. package/dist/sandbox-terminal/index.js.map +1 -1
  62. package/dist/selection-toolbar/index.d.ts +3 -21
  63. package/dist/selection-toolbar/index.js +3 -13
  64. package/dist/selection-toolbar-CIkOoM-7.js +171 -0
  65. package/dist/selection-toolbar-CIkOoM-7.js.map +1 -0
  66. package/dist/shared-BSYElFU2.d.ts +2 -0
  67. package/dist/shared.d.ts +4 -14
  68. package/dist/shared.js +1 -43
  69. package/dist/stream/index.d.ts +2 -22
  70. package/dist/stream/index.js +1 -8
  71. package/dist/stream-CAO0x8_1.js +298 -0
  72. package/dist/stream-CAO0x8_1.js.map +1 -0
  73. package/dist/thread-list/index.d.ts +3 -47
  74. package/dist/thread-list/index.js +3 -18
  75. package/dist/thread-list-xJbGXFrE.js +228 -0
  76. package/dist/thread-list-xJbGXFrE.js.map +1 -0
  77. package/dist/ticket-CoJHBpdF.d.ts +32 -0
  78. package/dist/ticket-CoJHBpdF.d.ts.map +1 -0
  79. package/dist/url-CiYZkDks.js +52 -0
  80. package/dist/url-CiYZkDks.js.map +1 -0
  81. package/dist/value-BGGrx72L.js +13 -0
  82. package/dist/value-BGGrx72L.js.map +1 -0
  83. package/package.json +22 -22
  84. package/dist/attachment/index.js.map +0 -1
  85. package/dist/attachment-mbjsroli.d.ts +0 -9
  86. package/dist/chat/index.js.map +0 -1
  87. package/dist/chat-PSj1Fo4W.d.ts +0 -88
  88. package/dist/chunk-22EZJUPM.js +0 -120
  89. package/dist/chunk-22EZJUPM.js.map +0 -1
  90. package/dist/chunk-5FZKTDZR.js +0 -201
  91. package/dist/chunk-5FZKTDZR.js.map +0 -1
  92. package/dist/chunk-6XOJFLX4.js +0 -22
  93. package/dist/chunk-6XOJFLX4.js.map +0 -1
  94. package/dist/chunk-CKA4CE26.js +0 -25
  95. package/dist/chunk-CKA4CE26.js.map +0 -1
  96. package/dist/chunk-DLBNFBXQ.js +0 -425
  97. package/dist/chunk-DLBNFBXQ.js.map +0 -1
  98. package/dist/chunk-E73S3SOF.js +0 -404
  99. package/dist/chunk-E73S3SOF.js.map +0 -1
  100. package/dist/chunk-F6AKBUO3.js +0 -380
  101. package/dist/chunk-F6AKBUO3.js.map +0 -1
  102. package/dist/chunk-HGOPGZNQ.js +0 -195
  103. package/dist/chunk-HGOPGZNQ.js.map +0 -1
  104. package/dist/chunk-KHB5CHAU.js +0 -220
  105. package/dist/chunk-KHB5CHAU.js.map +0 -1
  106. package/dist/chunk-LHABOAOP.js +0 -316
  107. package/dist/chunk-LHABOAOP.js.map +0 -1
  108. package/dist/chunk-N5XQU36W.js +0 -410
  109. package/dist/chunk-N5XQU36W.js.map +0 -1
  110. package/dist/chunk-T3ZFZ3NP.js +0 -30
  111. package/dist/chunk-T3ZFZ3NP.js.map +0 -1
  112. package/dist/chunk-T4IYUEPH.js +0 -1612
  113. package/dist/chunk-T4IYUEPH.js.map +0 -1
  114. package/dist/chunk-W2AHKMRS.js +0 -1092
  115. package/dist/chunk-W2AHKMRS.js.map +0 -1
  116. package/dist/completion/index.js.map +0 -1
  117. package/dist/completion-input-DHlwrhxB.d.ts +0 -24
  118. package/dist/composer-6iCSIq6L.d.ts +0 -111
  119. package/dist/human-input/index.js.map +0 -1
  120. package/dist/human-input-CkLrZ8IC.d.ts +0 -27
  121. package/dist/image/index.js.map +0 -1
  122. package/dist/image-VZv6Ddsn.d.ts +0 -14
  123. package/dist/message/index.js.map +0 -1
  124. package/dist/message-CNRnZQwU.d.ts +0 -14
  125. package/dist/render-CRKWam2v.d.ts +0 -8
  126. package/dist/selection-toolbar/index.js.map +0 -1
  127. package/dist/selection-toolbar-Cwjbuv5S.d.ts +0 -14
  128. package/dist/shared.js.map +0 -1
  129. package/dist/stream/index.js.map +0 -1
  130. package/dist/thread-Bz6-1zaJ.d.ts +0 -12
  131. package/dist/thread-list/index.js.map +0 -1
  132. package/dist/thread-list-On8db4XL.d.ts +0 -34
  133. package/dist/ticket-pexI1zIa.d.ts +0 -33
@@ -1,1612 +0,0 @@
1
- import {
2
- MessagePrimitive,
3
- isComposerEntityData,
4
- shiftComposerEntityRanges
5
- } from "./chunk-W2AHKMRS.js";
6
- import {
7
- AttachmentPrimitive
8
- } from "./chunk-22EZJUPM.js";
9
- import {
10
- composeRefs,
11
- renderPrimitive
12
- } from "./chunk-T3ZFZ3NP.js";
13
- import {
14
- InternalAttachmentProvider,
15
- InternalComposerProvider,
16
- InternalMessageProvider,
17
- InternalThreadProvider,
18
- useChatContext,
19
- useComposer,
20
- useThread
21
- } from "./chunk-E73S3SOF.js";
22
-
23
- // src/chat/composer.tsx
24
- import { mergeAttributes } from "@tiptap/core";
25
- import Document from "@tiptap/extension-document";
26
- import HardBreak from "@tiptap/extension-hard-break";
27
- import Mention from "@tiptap/extension-mention";
28
- import Paragraph from "@tiptap/extension-paragraph";
29
- import Placeholder from "@tiptap/extension-placeholder";
30
- import Text from "@tiptap/extension-text";
31
- import { PluginKey } from "@tiptap/pm/state";
32
- import {
33
- EditorContent,
34
- NodeViewWrapper,
35
- ReactNodeViewRenderer,
36
- useEditor
37
- } from "@tiptap/react";
38
- import {
39
- forwardRef,
40
- useCallback,
41
- useEffect,
42
- useMemo,
43
- useRef,
44
- useState
45
- } from "react";
46
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
47
- var ComposerRoot = forwardRef(function ComposerRoot2({
48
- attachments: attachmentsProp,
49
- defaultAttachments,
50
- defaultEntities,
51
- defaultInput = "",
52
- defaultQuote,
53
- entities: entitiesProp,
54
- input: inputProp,
55
- onAttachmentsChange,
56
- onEntitiesChange,
57
- onInputChange,
58
- onQuoteChange,
59
- quote: quoteProp,
60
- submitMessage,
61
- triggers: triggersProp,
62
- onSubmit,
63
- ...props
64
- }, ref) {
65
- const chat = useChatContext();
66
- const [uncontrolledInput, setUncontrolledInput] = useState(defaultInput);
67
- const [uncontrolledAttachments, setUncontrolledAttachments] = useState(() => [
68
- ...defaultAttachments ?? []
69
- ]);
70
- const [uncontrolledEntities, setUncontrolledEntities] = useState(() => [
71
- ...defaultEntities ?? []
72
- ]);
73
- const [uncontrolledQuote, setUncontrolledQuote] = useState(
74
- defaultQuote
75
- );
76
- const [activeTrigger, setActiveTriggerState] = useState();
77
- const input = inputProp ?? uncontrolledInput;
78
- const attachments = attachmentsProp ?? uncontrolledAttachments;
79
- const entities = entitiesProp ?? uncontrolledEntities;
80
- const triggers = triggersProp ?? EMPTY_COMPOSER_TRIGGERS;
81
- const rawQuote = quoteProp ?? uncontrolledQuote;
82
- const rawQuoteMessageId = rawQuote?.messageId;
83
- const rawQuoteText = rawQuote?.text;
84
- const quote = useMemo(
85
- () => rawQuoteMessageId === void 0 || rawQuoteText === void 0 ? void 0 : { messageId: rawQuoteMessageId, text: rawQuoteText },
86
- [rawQuoteMessageId, rawQuoteText]
87
- );
88
- const attachmentsRef = useRef(attachments);
89
- attachmentsRef.current = attachments;
90
- const entitiesRef = useRef(entities);
91
- entitiesRef.current = entities;
92
- const defaultSubmissionInFlightRef = useRef(false);
93
- const inputControlled = inputProp !== void 0;
94
- const attachmentsControlled = attachmentsProp !== void 0;
95
- const entitiesControlled = entitiesProp !== void 0;
96
- const quoteControlled = quoteProp !== void 0;
97
- const hasMessageContent = input.trim().length > 0 || attachments.length > 0 || entities.length > 0 || quote !== void 0;
98
- const active = chat.status === "submitted" || chat.status === "streaming";
99
- const canSubmit = hasMessageContent && !active;
100
- const canStop = active;
101
- const setInput = useCallback(
102
- (nextInput) => {
103
- if (!inputControlled) {
104
- setUncontrolledInput(nextInput);
105
- }
106
- onInputChange?.(nextInput);
107
- },
108
- [inputControlled, onInputChange]
109
- );
110
- const setAttachments = useCallback(
111
- (update) => {
112
- const nextAttachments = typeof update === "function" ? update(attachmentsRef.current) : update;
113
- attachmentsRef.current = nextAttachments;
114
- if (!attachmentsControlled) {
115
- setUncontrolledAttachments(nextAttachments);
116
- }
117
- onAttachmentsChange?.(nextAttachments);
118
- },
119
- [attachmentsControlled, onAttachmentsChange]
120
- );
121
- const setEntities = useCallback(
122
- (update) => {
123
- const nextEntities = typeof update === "function" ? update(entitiesRef.current) : update;
124
- entitiesRef.current = nextEntities;
125
- if (!entitiesControlled) {
126
- setUncontrolledEntities(nextEntities);
127
- }
128
- onEntitiesChange?.(nextEntities);
129
- },
130
- [entitiesControlled, onEntitiesChange]
131
- );
132
- const setQuote = useCallback(
133
- (nextQuote) => {
134
- const normalizedQuote = normalizeQuote(nextQuote);
135
- if (!quoteControlled) {
136
- setUncontrolledQuote(normalizedQuote);
137
- }
138
- onQuoteChange?.(normalizedQuote);
139
- },
140
- [onQuoteChange, quoteControlled]
141
- );
142
- const addAttachment = useCallback(
143
- async (attachment) => {
144
- const normalized = isFileAttachmentInput(attachment) ? await attachmentFromFile(attachment) : createAttachment(attachment);
145
- setAttachments((current) => [...current, normalized]);
146
- },
147
- [setAttachments]
148
- );
149
- const removeAttachment = useCallback(
150
- (id) => {
151
- setAttachments((current) => current.filter((attachment) => attachment.id !== id));
152
- },
153
- [setAttachments]
154
- );
155
- const clearAttachments = useCallback(() => {
156
- setAttachments([]);
157
- }, [setAttachments]);
158
- const clearQuote = useCallback(() => {
159
- setQuote(void 0);
160
- }, [setQuote]);
161
- const clear = useCallback(() => {
162
- setInput("");
163
- setAttachments([]);
164
- setEntities([]);
165
- setActiveTriggerState(void 0);
166
- clearQuote();
167
- }, [clearQuote, setAttachments, setEntities, setInput]);
168
- const submit = useCallback(async () => {
169
- const prompt = input;
170
- if (prompt.trim().length === 0 && attachments.length === 0 && entities.length === 0 && quote === void 0 || chat.status === "submitted" || chat.status === "streaming") {
171
- return;
172
- }
173
- assertComposerEntitiesData(entities);
174
- if (submitMessage !== void 0) {
175
- await submitMessage({
176
- input: prompt,
177
- attachments,
178
- entities,
179
- chat,
180
- quote,
181
- clear
182
- });
183
- return;
184
- }
185
- if (defaultSubmissionInFlightRef.current) {
186
- return;
187
- }
188
- const submittedAttachments = [...attachments];
189
- const submittedQuote = quote === void 0 ? void 0 : { ...quote };
190
- const formattedPrompt = submittedQuote === void 0 ? { text: prompt, prefixLength: 0 } : promptWithQuote(prompt, submittedQuote);
191
- const submittedEntities = shiftComposerEntityRanges(
192
- [...entities],
193
- formattedPrompt.prefixLength
194
- );
195
- const submittedText = formattedPrompt.text;
196
- const metadata = composerSubmitMetadata(submittedQuote, submittedEntities);
197
- let payload;
198
- if (submittedAttachments.length === 0) {
199
- payload = metadata === void 0 ? { text: submittedText } : { text: submittedText, metadata };
200
- } else {
201
- const attachmentPayload = {
202
- text: submittedText,
203
- attachments: submittedAttachments
204
- };
205
- if (metadata !== void 0) attachmentPayload.metadata = metadata;
206
- payload = attachmentPayload;
207
- }
208
- defaultSubmissionInFlightRef.current = true;
209
- try {
210
- const submission = chat.sendMessage(payload);
211
- clear();
212
- await submission;
213
- } finally {
214
- defaultSubmissionInFlightRef.current = false;
215
- }
216
- }, [attachments, chat, clear, entities, input, quote, submitMessage]);
217
- const setActiveTrigger = useCallback((update) => {
218
- setActiveTriggerState(update);
219
- }, []);
220
- const value = useMemo(
221
- () => ({
222
- input,
223
- setInput,
224
- attachments,
225
- setAttachments,
226
- addAttachment,
227
- removeAttachment,
228
- clearAttachments,
229
- entities,
230
- setEntities,
231
- quote,
232
- setQuote,
233
- clearQuote,
234
- triggers,
235
- activeTrigger,
236
- setActiveTrigger,
237
- submit,
238
- stop: chat.stop,
239
- status: chat.status,
240
- canSubmit,
241
- canStop
242
- }),
243
- [
244
- addAttachment,
245
- attachments,
246
- activeTrigger,
247
- canStop,
248
- canSubmit,
249
- chat.status,
250
- chat.stop,
251
- clearAttachments,
252
- clearQuote,
253
- entities,
254
- input,
255
- quote,
256
- removeAttachment,
257
- setAttachments,
258
- setActiveTrigger,
259
- setEntities,
260
- setInput,
261
- setQuote,
262
- submit,
263
- triggers
264
- ]
265
- );
266
- const handleSubmit = useCallback(
267
- (event) => {
268
- onSubmit?.(event);
269
- if (event.defaultPrevented) {
270
- return;
271
- }
272
- event.preventDefault();
273
- void submit();
274
- },
275
- [onSubmit, submit]
276
- );
277
- return /* @__PURE__ */ jsx(InternalComposerProvider, { value, children: renderPrimitive(
278
- "form",
279
- {
280
- ...props,
281
- onSubmit: handleSubmit,
282
- "data-state": chat.status
283
- },
284
- ref
285
- ) });
286
- });
287
- var ComposerQuotePreview = forwardRef(
288
- function ComposerQuotePreview2({ children, ...props }, ref) {
289
- const composer = useComposer();
290
- const quote = composer.quote;
291
- if (quote === void 0) {
292
- return null;
293
- }
294
- const renderedChildren = typeof children === "function" ? children(quote) : children ?? quote.text;
295
- return renderPrimitive(
296
- "blockquote",
297
- {
298
- ...props,
299
- children: renderedChildren
300
- },
301
- ref
302
- );
303
- }
304
- );
305
- var ComposerClearQuote = forwardRef(
306
- function ComposerClearQuote2({ onClick, ...props }, ref) {
307
- const composer = useComposer();
308
- const disabled = props.disabled ?? composer.quote === void 0;
309
- const handleClick = useCallback(
310
- (event) => {
311
- onClick?.(event);
312
- if (event.defaultPrevented || disabled) {
313
- return;
314
- }
315
- composer.clearQuote();
316
- },
317
- [composer, disabled, onClick]
318
- );
319
- return renderPrimitive(
320
- "button",
321
- {
322
- ...props,
323
- children: props.children ?? "Clear quote",
324
- disabled,
325
- onClick: handleClick,
326
- type: props.type ?? "button",
327
- "data-state": disabled ? "disabled" : "enabled"
328
- },
329
- ref
330
- );
331
- }
332
- );
333
- var ComposerInput = forwardRef(function ComposerInput2({
334
- autoResize = true,
335
- disabled,
336
- maxRows: maxRowsProp,
337
- minRows: minRowsProp,
338
- onKeyDown,
339
- placeholder,
340
- renderEntity,
341
- style,
342
- ...props
343
- }, ref) {
344
- const composer = useComposer();
345
- const composerRef = useRef(composer);
346
- composerRef.current = composer;
347
- const renderEntityRef = useRef(renderEntity);
348
- renderEntityRef.current = renderEntity;
349
- const customEntityView = renderEntity !== void 0;
350
- const editorReadyRef = useRef(false);
351
- const syncingFromEditorRef = useRef(false);
352
- const triggers = composer.triggers;
353
- const minRows = normalizeRows(minRowsProp ?? 1, 1);
354
- const maxRows = normalizeRows(maxRowsProp ?? 6, minRows);
355
- const extensions = useMemo(
356
- () => composerInputExtensions({
357
- composerRef,
358
- placeholder,
359
- renderEntityRef: customEntityView ? renderEntityRef : void 0,
360
- triggers
361
- }),
362
- [customEntityView, placeholder, triggers]
363
- );
364
- const editor = useEditor(
365
- {
366
- extensions,
367
- content: plainTextToComposerContent(composer.input),
368
- editable: composer.status !== "submitted" && composer.status !== "streaming",
369
- editorProps: {
370
- attributes: {
371
- "aria-label": props["aria-label"] ?? "Message",
372
- "aria-multiline": "true",
373
- role: "textbox"
374
- },
375
- handleKeyDown: (_view, event) => submitComposerFromEditorKeyDown(event, composerRef)
376
- },
377
- onUpdate: ({ editor: updatedEditor }) => {
378
- if (!editorReadyRef.current) {
379
- return;
380
- }
381
- const snapshot = composerSnapshotFromEditor(
382
- updatedEditor,
383
- composerRef.current.entities,
384
- composerRef.current.triggers
385
- );
386
- syncingFromEditorRef.current = true;
387
- composerRef.current.setInput(snapshot.input);
388
- composerRef.current.setEntities(snapshot.entities);
389
- }
390
- },
391
- [extensions]
392
- );
393
- const ariaDisabled = props["aria-disabled"] === true || props["aria-disabled"] === "true";
394
- const composerDisabled = disabled === true || ariaDisabled || composer.status === "submitted" || composer.status === "streaming";
395
- const inputStyle = useMemo(() => {
396
- if (!autoResize) {
397
- return style;
398
- }
399
- const rowsStyle = {
400
- ["--anvia-composer-min-rows"]: minRows,
401
- ["--anvia-composer-max-rows"]: maxRows
402
- };
403
- return style === void 0 ? rowsStyle : { ...rowsStyle, ...style };
404
- }, [autoResize, maxRows, minRows, style]);
405
- const handleKeyDown = useCallback(
406
- (event) => {
407
- onKeyDown?.(event);
408
- if (event.defaultPrevented || event.key !== "Enter" || event.shiftKey || event.nativeEvent.isComposing) {
409
- return;
410
- }
411
- event.preventDefault();
412
- void composerRef.current.submit();
413
- },
414
- [onKeyDown]
415
- );
416
- useEffect(() => {
417
- if (editor === null) {
418
- return;
419
- }
420
- editor.setEditable(!composerDisabled, false);
421
- }, [composerDisabled, editor]);
422
- useEffect(() => {
423
- if (editor === null) {
424
- return;
425
- }
426
- editor.commands.setContent(plainTextToComposerContent(composerRef.current.input), {
427
- emitUpdate: false
428
- });
429
- editorReadyRef.current = true;
430
- return () => {
431
- editorReadyRef.current = false;
432
- };
433
- }, [editor]);
434
- useEffect(() => {
435
- if (editor === null || !editorReadyRef.current) {
436
- return;
437
- }
438
- if (syncingFromEditorRef.current) {
439
- syncingFromEditorRef.current = false;
440
- return;
441
- }
442
- const snapshot = composerSnapshotFromEditor(editor, composer.entities, composer.triggers);
443
- if (snapshot.input === composer.input) {
444
- return;
445
- }
446
- editor.commands.setContent(plainTextToComposerContent(composer.input), {
447
- emitUpdate: false
448
- });
449
- }, [composer, editor]);
450
- return renderPrimitive(
451
- "div",
452
- {
453
- ...props,
454
- children: /* @__PURE__ */ jsx(EditorContent, { editor }),
455
- "aria-disabled": composerDisabled ? true : props["aria-disabled"],
456
- "data-role": "editor",
457
- "data-state": composerDisabled ? "disabled" : "enabled",
458
- onKeyDown: handleKeyDown,
459
- style: inputStyle
460
- },
461
- ref
462
- );
463
- });
464
- var ComposerTextareaInput = forwardRef(
465
- function ComposerTextareaInput2({
466
- autoResize = true,
467
- maxRows: maxRowsProp,
468
- minRows: minRowsProp,
469
- onChange,
470
- onKeyDown,
471
- rows,
472
- ...props
473
- }, ref) {
474
- const composer = useComposer();
475
- const inputRef = useRef(null);
476
- const wasAutoResizeRef = useRef(autoResize);
477
- const composedInputRef = useMemo(() => composeRefs(inputRef, ref), [ref]);
478
- const minRows = normalizeRows(minRowsProp ?? rows ?? 1, 1);
479
- const maxRows = normalizeRows(maxRowsProp ?? 6, minRows);
480
- useEffect(() => {
481
- const wasAutoResize = wasAutoResizeRef.current;
482
- wasAutoResizeRef.current = autoResize;
483
- if (!autoResize) {
484
- if (wasAutoResize) {
485
- resetComposerInputSize(inputRef.current);
486
- }
487
- return;
488
- }
489
- resizeComposerInput(inputRef.current, { maxRows, minRows });
490
- });
491
- const handleChange = useCallback(
492
- (event) => {
493
- onChange?.(event);
494
- if (!event.defaultPrevented) {
495
- composer.setInput(event.currentTarget.value);
496
- composer.setEntities([]);
497
- if (autoResize) {
498
- resizeComposerInput(event.currentTarget, { maxRows, minRows });
499
- }
500
- }
501
- },
502
- [autoResize, composer, maxRows, minRows, onChange]
503
- );
504
- const handleKeyDown = useCallback(
505
- (event) => {
506
- onKeyDown?.(event);
507
- if (event.defaultPrevented || event.key !== "Enter" || event.shiftKey || event.nativeEvent.isComposing) {
508
- return;
509
- }
510
- event.preventDefault();
511
- void composer.submit();
512
- },
513
- [composer, onKeyDown]
514
- );
515
- return renderPrimitive(
516
- "textarea",
517
- {
518
- ...props,
519
- "aria-label": props["aria-label"] ?? "Message",
520
- disabled: props.disabled ?? (composer.status === "submitted" || composer.status === "streaming"),
521
- onChange: handleChange,
522
- onKeyDown: handleKeyDown,
523
- rows: autoResize ? minRows : rows,
524
- value: composer.input
525
- },
526
- composedInputRef
527
- );
528
- }
529
- );
530
- var COMPOSER_ENTITY_NODE = "composerEntity";
531
- var EMPTY_COMPOSER_TRIGGERS = [];
532
- var ComposerEntityExtension = Mention.extend({
533
- name: COMPOSER_ENTITY_NODE,
534
- addAttributes() {
535
- return {
536
- id: {
537
- default: null,
538
- parseHTML: (element) => element.getAttribute("data-id"),
539
- renderHTML: (attributes) => attributes.id === void 0 || attributes.id === null ? {} : { "data-id": String(attributes.id) }
540
- },
541
- label: {
542
- default: null,
543
- parseHTML: (element) => element.getAttribute("data-label"),
544
- renderHTML: (attributes) => attributes.label === void 0 || attributes.label === null ? {} : { "data-label": String(attributes.label) }
545
- },
546
- mentionSuggestionChar: {
547
- default: "@",
548
- parseHTML: (element) => element.getAttribute("data-mention-suggestion-char"),
549
- renderHTML: (attributes) => ({
550
- "data-mention-suggestion-char": attributes.mentionSuggestionChar
551
- })
552
- },
553
- triggerId: {
554
- default: null,
555
- parseHTML: (element) => element.getAttribute("data-trigger-id"),
556
- renderHTML: (attributes) => attributes.triggerId === void 0 || attributes.triggerId === null ? {} : { "data-trigger-id": String(attributes.triggerId) }
557
- },
558
- text: {
559
- default: null,
560
- parseHTML: (element) => element.getAttribute("data-text"),
561
- renderHTML: (attributes) => attributes.text === void 0 || attributes.text === null ? {} : { "data-text": String(attributes.text) }
562
- },
563
- data: {
564
- default: void 0,
565
- parseHTML: (element) => dataFromAttribute(element.getAttribute("data-entity-data")),
566
- renderHTML: (attributes) => {
567
- if (attributes.data === void 0) return {};
568
- if (!isComposerEntityData(attributes.data)) {
569
- throw new TypeError("Composer entity data must be a JSON value.");
570
- }
571
- return { "data-entity-data": JSON.stringify(attributes.data) };
572
- }
573
- }
574
- };
575
- }
576
- });
577
- function composerEntityView(renderEntityRef, composerRef) {
578
- return function ComposerEntityView({ node }) {
579
- const attrs = node.attrs;
580
- const { range: _range, ...entity } = composerEntityFromAttrs(
581
- attrs,
582
- 0,
583
- composerRef.current.entities,
584
- composerRef.current.triggers
585
- );
586
- return /* @__PURE__ */ jsx(NodeViewWrapper, { as: "span", children: renderEntityRef.current?.(entity) ?? entity.text });
587
- };
588
- }
589
- function composerInputExtensions({
590
- composerRef,
591
- placeholder,
592
- renderEntityRef,
593
- triggers
594
- }) {
595
- const EntityExtension = renderEntityRef === void 0 ? ComposerEntityExtension : ComposerEntityExtension.extend({
596
- addNodeView() {
597
- return ReactNodeViewRenderer(composerEntityView(renderEntityRef, composerRef), {
598
- as: "span"
599
- });
600
- }
601
- });
602
- return [
603
- Document,
604
- Paragraph,
605
- Text,
606
- HardBreak,
607
- Placeholder.configure(placeholder === void 0 ? {} : { placeholder }),
608
- EntityExtension.configure({
609
- HTMLAttributes: {},
610
- deleteTriggerWithBackspace: true,
611
- renderText: ({ node }) => composerEntityText(node.attrs),
612
- renderHTML: ({ node, options }) => [
613
- "span",
614
- mergeAttributes(options.HTMLAttributes, {}),
615
- composerEntityText(node.attrs)
616
- ],
617
- suggestions: triggers.map((trigger) => composerSuggestion(trigger, composerRef))
618
- })
619
- ];
620
- }
621
- function submitComposerFromEditorKeyDown(event, composerRef) {
622
- if (event.defaultPrevented || event.key !== "Enter" || event.shiftKey || event.isComposing || composerRef.current.activeTrigger !== void 0) {
623
- return false;
624
- }
625
- event.preventDefault();
626
- void composerRef.current.submit();
627
- return true;
628
- }
629
- function composerSuggestion(trigger, composerRef) {
630
- const pluginKey = new PluginKey(`anvia-composer-trigger-${trigger.id}`);
631
- const suggestion = {
632
- pluginKey,
633
- char: trigger.char,
634
- items: ({ query, signal }) => resolveTriggerItems(trigger, query, composerRef.current, signal),
635
- command: ({
636
- editor,
637
- range,
638
- props
639
- }) => {
640
- const nodeAfter = editor.state.selection.$to.nodeAfter;
641
- const overrideSpace = nodeAfter?.text?.startsWith(" ");
642
- const insertRange = {
643
- from: range.from,
644
- to: overrideSpace ? range.to + 1 : range.to
645
- };
646
- editor.chain().focus().insertContentAt(insertRange, [
647
- {
648
- type: COMPOSER_ENTITY_NODE,
649
- attrs: props
650
- },
651
- {
652
- type: "text",
653
- text: " "
654
- }
655
- ]).run();
656
- composerEditorOwnerDocument(editor)?.defaultView?.getSelection()?.collapseToEnd();
657
- composerRef.current.setActiveTrigger(void 0);
658
- },
659
- render: () => ({
660
- onStart: (props) => {
661
- updateComposerTriggerState(trigger, props, composerRef);
662
- },
663
- onUpdate: (props) => {
664
- updateComposerTriggerState(trigger, props, composerRef);
665
- },
666
- onExit: () => {
667
- composerRef.current.setActiveTrigger(
668
- (current) => current?.trigger.id === trigger.id ? void 0 : current
669
- );
670
- },
671
- onKeyDown: (props) => handleComposerTriggerKeyDown(trigger, props, composerRef)
672
- })
673
- };
674
- if (trigger.allowSpaces !== void 0) suggestion.allowSpaces = trigger.allowSpaces;
675
- if (trigger.allowedPrefixes !== void 0) {
676
- suggestion.allowedPrefixes = trigger.allowedPrefixes;
677
- }
678
- if (trigger.startOfLine !== void 0) suggestion.startOfLine = trigger.startOfLine;
679
- if (trigger.minQueryLength !== void 0) {
680
- suggestion.minQueryLength = trigger.minQueryLength;
681
- }
682
- return suggestion;
683
- }
684
- function resolveTriggerItems(trigger, query, composer, signal) {
685
- if (Array.isArray(trigger.items)) {
686
- const normalizedQuery = query.toLowerCase();
687
- return trigger.items.filter((item) => item.label.toLowerCase().includes(normalizedQuery));
688
- }
689
- return trigger.items({
690
- trigger,
691
- query,
692
- input: composer.input,
693
- entities: composer.entities,
694
- signal
695
- });
696
- }
697
- function composerEditorOwnerDocument(editor) {
698
- const element = editor.options.element;
699
- if (element === null || typeof element === "function") {
700
- return void 0;
701
- }
702
- return "mount" in element ? element.mount.ownerDocument : element.ownerDocument;
703
- }
704
- function updateComposerTriggerState(trigger, props, composerRef) {
705
- const current = composerRef.current.activeTrigger;
706
- const selectedIndex = current?.trigger.id === trigger.id ? clampIndex(current.selectedIndex, props.items.length) : 0;
707
- const rect = rectFromSuggestion(props);
708
- const state = {
709
- trigger,
710
- query: props.query,
711
- items: props.items,
712
- loading: props.loading,
713
- selectedIndex,
714
- selectItem: (item) => {
715
- if (item.disabled) {
716
- return;
717
- }
718
- props.command(triggerItemToEntityAttrs(trigger, item));
719
- },
720
- setSelectedIndex: (index) => {
721
- composerRef.current.setActiveTrigger(
722
- (active) => active?.trigger.id === trigger.id ? { ...active, selectedIndex: clampIndex(index, active.items.length) } : active
723
- );
724
- }
725
- };
726
- if (rect !== void 0) state.rect = rect;
727
- composerRef.current.setActiveTrigger(state);
728
- }
729
- function handleComposerTriggerKeyDown(trigger, { event }, composerRef) {
730
- const activeTrigger = composerRef.current.activeTrigger;
731
- if (activeTrigger?.trigger.id !== trigger.id) {
732
- return false;
733
- }
734
- if (event.key === "ArrowDown") {
735
- event.preventDefault();
736
- activeTrigger.setSelectedIndex(activeTrigger.selectedIndex + 1);
737
- return true;
738
- }
739
- if (event.key === "ArrowUp") {
740
- event.preventDefault();
741
- activeTrigger.setSelectedIndex(activeTrigger.selectedIndex - 1);
742
- return true;
743
- }
744
- if (event.key === "Enter" || event.key === "Tab") {
745
- event.preventDefault();
746
- const item = activeTrigger.items[activeTrigger.selectedIndex];
747
- if (item !== void 0) {
748
- activeTrigger.selectItem(item);
749
- }
750
- return true;
751
- }
752
- if (event.key === "Escape") {
753
- composerRef.current.setActiveTrigger(void 0);
754
- return false;
755
- }
756
- return false;
757
- }
758
- function triggerItemToEntityAttrs(trigger, item) {
759
- if (item.data !== void 0 && !isComposerEntityData(item.data)) {
760
- throw new TypeError("Composer trigger item data must be a JSON value.");
761
- }
762
- return {
763
- id: item.id,
764
- label: item.label,
765
- mentionSuggestionChar: trigger.char,
766
- triggerId: trigger.id,
767
- text: triggerItemText(trigger, item),
768
- data: item.data
769
- };
770
- }
771
- function triggerItemText(trigger, item) {
772
- return item.text ?? `${trigger.char}${item.label}`;
773
- }
774
- function rectFromSuggestion(props) {
775
- const rect = props.clientRect?.();
776
- if (rect === void 0 || rect === null) {
777
- return void 0;
778
- }
779
- return {
780
- top: rect.top,
781
- right: rect.right,
782
- bottom: rect.bottom,
783
- left: rect.left,
784
- width: rect.width,
785
- height: rect.height
786
- };
787
- }
788
- function clampIndex(index, length) {
789
- if (length <= 0) {
790
- return 0;
791
- }
792
- return (index + length) % length;
793
- }
794
- function plainTextToComposerContent(input) {
795
- const lines = input.length === 0 ? [""] : input.split(/\r?\n/);
796
- return {
797
- type: "doc",
798
- content: lines.map((line) => {
799
- const paragraph = { type: "paragraph" };
800
- if (line.length > 0) {
801
- paragraph.content = [{ type: "text", text: line }];
802
- }
803
- return paragraph;
804
- })
805
- };
806
- }
807
- function composerSnapshotFromEditor(editor, previousEntities, triggers) {
808
- return composerSnapshotFromContent(editor.getJSON(), previousEntities, triggers);
809
- }
810
- function composerSnapshotFromContent(content, previousEntities, triggers) {
811
- const entities = [];
812
- let input = "";
813
- let blockIndex = 0;
814
- const appendNode = (node) => {
815
- if (node.type === "doc") {
816
- for (const child of node.content ?? []) {
817
- appendNode(child);
818
- }
819
- return;
820
- }
821
- if (node.type === "paragraph") {
822
- if (blockIndex > 0) {
823
- input += "\n";
824
- }
825
- blockIndex += 1;
826
- for (const child of node.content ?? []) {
827
- appendNode(child);
828
- }
829
- return;
830
- }
831
- if (node.type === "text") {
832
- input += node.text ?? "";
833
- return;
834
- }
835
- if (node.type === "hardBreak") {
836
- input += "\n";
837
- return;
838
- }
839
- if (node.type === COMPOSER_ENTITY_NODE) {
840
- const attrs = node.attrs;
841
- const entity = composerEntityFromAttrs(attrs, input.length, previousEntities, triggers);
842
- input += entity.text;
843
- entities.push(entity);
844
- return;
845
- }
846
- for (const child of node.content ?? []) {
847
- appendNode(child);
848
- }
849
- };
850
- appendNode(content);
851
- return { input, entities };
852
- }
853
- function composerEntityFromAttrs(attrs, from, previousEntities, triggers) {
854
- const id = stringAttr(attrs?.id) ?? "";
855
- const trigger = stringAttr(attrs?.mentionSuggestionChar) ?? "@";
856
- const triggerId = stringAttr(attrs?.triggerId) ?? triggers.find((candidate) => candidate.char === trigger)?.id ?? trigger;
857
- const label = stringAttr(attrs?.label) ?? id;
858
- const text = composerEntityText(attrs);
859
- const previous = previousEntities.find(
860
- (entity2) => entity2.id === id && entity2.triggerId === triggerId && entity2.trigger === trigger
861
- );
862
- const data = attrs?.data === void 0 ? previous?.data : attrs.data;
863
- const entity = {
864
- id,
865
- triggerId,
866
- trigger,
867
- label,
868
- text,
869
- range: {
870
- from,
871
- to: from + text.length
872
- }
873
- };
874
- if (data !== void 0) entity.data = data;
875
- return entity;
876
- }
877
- function composerEntityText(attrs) {
878
- const text = stringAttr(attrs?.text);
879
- if (text !== void 0) {
880
- return text;
881
- }
882
- const trigger = stringAttr(attrs?.mentionSuggestionChar) ?? "@";
883
- return `${trigger}${stringAttr(attrs?.label) ?? stringAttr(attrs?.id) ?? ""}`;
884
- }
885
- function stringAttr(value) {
886
- return typeof value === "string" ? value : void 0;
887
- }
888
- function dataFromAttribute(value) {
889
- if (value === null) {
890
- return void 0;
891
- }
892
- try {
893
- const parsed = JSON.parse(value);
894
- return isComposerEntityData(parsed) ? parsed : void 0;
895
- } catch {
896
- return void 0;
897
- }
898
- }
899
- function resizeComposerInput(input, { maxRows, minRows }) {
900
- if (input === null) {
901
- return;
902
- }
903
- const style = getComputedStyle(input);
904
- const lineHeight = lineHeightFromStyle(style);
905
- const paddingHeight = pixelValue(style.paddingTop) + pixelValue(style.paddingBottom);
906
- const borderHeight = pixelValue(style.borderTopWidth) + pixelValue(style.borderBottomWidth);
907
- const minContentHeight = lineHeight * minRows;
908
- const maxContentHeight = Math.max(minContentHeight, lineHeight * maxRows);
909
- input.style.height = "auto";
910
- const scrollContentHeight = Math.max(input.scrollHeight - paddingHeight, 0);
911
- const contentHeight = clamp(scrollContentHeight, minContentHeight, maxContentHeight);
912
- const nextHeight = style.boxSizing === "border-box" ? contentHeight + paddingHeight + borderHeight : contentHeight;
913
- input.style.height = `${Math.ceil(nextHeight)}px`;
914
- input.style.overflowY = scrollContentHeight > maxContentHeight ? "auto" : "hidden";
915
- }
916
- function resetComposerInputSize(input) {
917
- if (input === null) {
918
- return;
919
- }
920
- input.style.height = "";
921
- input.style.overflowY = "";
922
- }
923
- function normalizeRows(value, min) {
924
- if (!Number.isFinite(value)) {
925
- return min;
926
- }
927
- return Math.max(min, Math.floor(value));
928
- }
929
- function lineHeightFromStyle(style) {
930
- return pixelValue(style.lineHeight) || (pixelValue(style.fontSize) || 16) * 1.2;
931
- }
932
- function pixelValue(value) {
933
- const parsed = Number.parseFloat(value);
934
- return Number.isFinite(parsed) ? parsed : 0;
935
- }
936
- function clamp(value, min, max) {
937
- return Math.min(Math.max(value, min), max);
938
- }
939
- function promptWithQuote(prompt, quote) {
940
- const quotedText = quote.text.split(/\r?\n/).map((line) => `> ${line}`).join("\n");
941
- if (prompt.trim().length === 0) {
942
- return { text: quotedText, prefixLength: 0 };
943
- }
944
- const prefix = `${quotedText}
945
-
946
- `;
947
- return { text: `${prefix}${prompt}`, prefixLength: prefix.length };
948
- }
949
- function normalizeQuote(quote) {
950
- if (quote === void 0) {
951
- return void 0;
952
- }
953
- return {
954
- text: quote.text,
955
- messageId: quote.messageId
956
- };
957
- }
958
- function composerSubmitMetadata(quote, entities) {
959
- if (quote === void 0 && entities.length === 0) {
960
- return void 0;
961
- }
962
- const metadata = {};
963
- if (quote !== void 0) metadata.quote = quote;
964
- if (entities.length > 0) {
965
- metadata.composer = { entities: entities.map(composerEntityMetadata) };
966
- }
967
- return metadata;
968
- }
969
- function assertComposerEntitiesData(entities) {
970
- for (const entity of entities) {
971
- if (entity.data !== void 0 && !isComposerEntityData(entity.data)) {
972
- throw new TypeError("Composer entity data must be a JSON value.");
973
- }
974
- }
975
- }
976
- function composerEntityMetadata(entity) {
977
- const metadata = {
978
- id: entity.id,
979
- triggerId: entity.triggerId,
980
- trigger: entity.trigger,
981
- label: entity.label,
982
- text: entity.text,
983
- range: { from: entity.range.from, to: entity.range.to }
984
- };
985
- if (entity.data !== void 0) {
986
- metadata.data = entity.data;
987
- }
988
- return metadata;
989
- }
990
- var ComposerSubmit = forwardRef(
991
- function ComposerSubmit2(props, ref) {
992
- const composer = useComposer();
993
- const disabled = props.disabled ?? !composer.canSubmit;
994
- return renderPrimitive(
995
- "button",
996
- {
997
- ...props,
998
- children: props.children ?? "Send",
999
- disabled,
1000
- type: props.type ?? "submit",
1001
- "data-state": disabled ? "disabled" : "enabled"
1002
- },
1003
- ref
1004
- );
1005
- }
1006
- );
1007
- var ComposerStop = forwardRef(function ComposerStop2({ onClick, ...props }, ref) {
1008
- const composer = useComposer();
1009
- const disabled = props.disabled ?? !composer.canStop;
1010
- const handleClick = useCallback(
1011
- (event) => {
1012
- onClick?.(event);
1013
- if (event.defaultPrevented || disabled) {
1014
- return;
1015
- }
1016
- composer.stop();
1017
- },
1018
- [composer, disabled, onClick]
1019
- );
1020
- return renderPrimitive(
1021
- "button",
1022
- {
1023
- ...props,
1024
- children: props.children ?? "Stop",
1025
- disabled,
1026
- onClick: handleClick,
1027
- type: props.type ?? "button",
1028
- "data-state": disabled ? "disabled" : "enabled"
1029
- },
1030
- ref
1031
- );
1032
- });
1033
- var ComposerTriggerMenu = forwardRef(
1034
- function ComposerTriggerMenu2({ children, keepMounted = false, style, ...props }, ref) {
1035
- const composer = useComposer();
1036
- const activeTrigger = composer.activeTrigger;
1037
- const empty = activeTrigger === void 0;
1038
- if (empty && !keepMounted) {
1039
- return null;
1040
- }
1041
- const menuStyle = activeTrigger?.rect === void 0 ? style : {
1042
- position: "fixed",
1043
- top: activeTrigger.rect.bottom,
1044
- left: activeTrigger.rect.left,
1045
- ...style
1046
- };
1047
- const renderedChildren = activeTrigger === void 0 ? typeof children === "function" ? null : children : typeof children === "function" ? children(activeTrigger) : children ?? activeTrigger.items.map((item, index) => /* @__PURE__ */ jsx(ComposerTriggerItem, { index }, `${item.id}:${index.toString()}`));
1048
- return renderPrimitive(
1049
- "div",
1050
- {
1051
- ...props,
1052
- children: renderedChildren,
1053
- role: props.role ?? "listbox",
1054
- style: menuStyle,
1055
- "data-state": activeTrigger === void 0 ? "closed" : activeTrigger.loading ? "loading" : empty ? "empty" : "open"
1056
- },
1057
- ref
1058
- );
1059
- }
1060
- );
1061
- var ComposerTriggerItem = forwardRef(
1062
- function ComposerTriggerItem2({ children, index, item: itemProp, onClick, onMouseEnter, ...props }, ref) {
1063
- const composer = useComposer();
1064
- const activeTrigger = composer.activeTrigger;
1065
- const itemIndex = index ?? 0;
1066
- const item = itemProp ?? activeTrigger?.items[itemIndex];
1067
- if (activeTrigger === void 0 || item === void 0) {
1068
- return null;
1069
- }
1070
- const selected = activeTrigger.selectedIndex === itemIndex;
1071
- const disabled = props.disabled ?? item.disabled ?? false;
1072
- const renderedChildren = typeof children === "function" ? children(item, activeTrigger) : children ?? item.label;
1073
- const handleMouseEnter = (event) => {
1074
- onMouseEnter?.(event);
1075
- if (!event.defaultPrevented && !disabled) {
1076
- activeTrigger.setSelectedIndex(itemIndex);
1077
- }
1078
- };
1079
- const handleClick = (event) => {
1080
- onClick?.(event);
1081
- if (!event.defaultPrevented && !disabled) {
1082
- activeTrigger.selectItem(item);
1083
- }
1084
- };
1085
- return renderPrimitive(
1086
- "button",
1087
- {
1088
- ...props,
1089
- children: renderedChildren,
1090
- disabled,
1091
- onClick: handleClick,
1092
- onMouseEnter: handleMouseEnter,
1093
- role: props.role ?? "option",
1094
- type: props.type ?? "button",
1095
- "aria-selected": selected,
1096
- "data-state": disabled ? "disabled" : selected ? "selected" : "idle"
1097
- },
1098
- ref
1099
- );
1100
- }
1101
- );
1102
- var ComposerAttachments = forwardRef(
1103
- function ComposerAttachments2({ children, keepMounted = false, ...props }, ref) {
1104
- const composer = useComposer();
1105
- const empty = composer.attachments.length === 0;
1106
- if (empty && !keepMounted) {
1107
- return null;
1108
- }
1109
- return renderPrimitive(
1110
- "div",
1111
- {
1112
- ...props,
1113
- children: composer.attachments.map((attachment) => /* @__PURE__ */ jsx(
1114
- InternalAttachmentProvider,
1115
- {
1116
- value: {
1117
- attachment,
1118
- remove: () => {
1119
- composer.removeAttachment(attachment.id);
1120
- }
1121
- },
1122
- children: typeof children === "function" ? children(attachment) : children ?? /* @__PURE__ */ jsx(AttachmentPrimitive.Root, {})
1123
- },
1124
- attachment.id
1125
- )),
1126
- "data-role": "attachments",
1127
- "data-state": empty ? "empty" : "populated"
1128
- },
1129
- ref
1130
- );
1131
- }
1132
- );
1133
- var ComposerAttachmentInput = forwardRef(
1134
- function ComposerAttachmentInput2({ onChange, ...props }, ref) {
1135
- const composer = useComposer();
1136
- const disabled = props.disabled ?? (composer.status === "submitted" || composer.status === "streaming");
1137
- const handleChange = useCallback(
1138
- async (event) => {
1139
- onChange?.(event);
1140
- if (event.defaultPrevented) {
1141
- return;
1142
- }
1143
- const files = Array.from(event.currentTarget.files ?? []);
1144
- event.currentTarget.value = "";
1145
- for (const file of files) {
1146
- await composer.addAttachment(file);
1147
- }
1148
- },
1149
- [composer, onChange]
1150
- );
1151
- return renderPrimitive(
1152
- "input",
1153
- {
1154
- ...props,
1155
- disabled,
1156
- onChange: (event) => {
1157
- void handleChange(event);
1158
- },
1159
- type: "file",
1160
- "data-state": disabled ? "disabled" : "enabled"
1161
- },
1162
- ref
1163
- );
1164
- }
1165
- );
1166
- var ComposerAddAttachment = forwardRef(
1167
- function ComposerAddAttachment2({ accept, multiple = false, onClick, ...props }, ref) {
1168
- const composer = useComposer();
1169
- const inputRef = useRef(null);
1170
- const disabled = props.disabled ?? (composer.status === "submitted" || composer.status === "streaming");
1171
- const handleClick = useCallback(
1172
- (event) => {
1173
- onClick?.(event);
1174
- if (event.defaultPrevented || disabled) {
1175
- return;
1176
- }
1177
- inputRef.current?.click();
1178
- },
1179
- [disabled, onClick]
1180
- );
1181
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1182
- renderPrimitive(
1183
- "button",
1184
- {
1185
- ...props,
1186
- children: props.children ?? "Attach",
1187
- disabled,
1188
- onClick: handleClick,
1189
- type: props.type ?? "button",
1190
- "data-state": disabled ? "disabled" : "enabled"
1191
- },
1192
- ref
1193
- ),
1194
- /* @__PURE__ */ jsx(
1195
- ComposerAttachmentInput,
1196
- {
1197
- accept,
1198
- "aria-hidden": "true",
1199
- hidden: true,
1200
- multiple,
1201
- ref: inputRef,
1202
- tabIndex: -1
1203
- }
1204
- )
1205
- ] });
1206
- }
1207
- );
1208
- var ComposerAttachmentDropzone = forwardRef(
1209
- function ComposerAttachmentDropzone2({ disabled: disabledProp = false, onDragLeave, onDragOver, onDrop, ...props }, ref) {
1210
- const composer = useComposer();
1211
- const [dragging, setDragging] = useState(false);
1212
- const disabled = disabledProp || composer.status === "submitted" || composer.status === "streaming";
1213
- const handleDragOver = useCallback(
1214
- (event) => {
1215
- onDragOver?.(event);
1216
- if (event.defaultPrevented || disabled) {
1217
- return;
1218
- }
1219
- event.preventDefault();
1220
- setDragging(true);
1221
- },
1222
- [disabled, onDragOver]
1223
- );
1224
- const handleDragLeave = useCallback(
1225
- (event) => {
1226
- onDragLeave?.(event);
1227
- if (!event.defaultPrevented) {
1228
- setDragging(false);
1229
- }
1230
- },
1231
- [onDragLeave]
1232
- );
1233
- const handleDrop = useCallback(
1234
- (event) => {
1235
- onDrop?.(event);
1236
- if (event.defaultPrevented || disabled) {
1237
- return;
1238
- }
1239
- event.preventDefault();
1240
- setDragging(false);
1241
- const files = Array.from(event.dataTransfer.files);
1242
- void Promise.all(files.map((file) => composer.addAttachment(file)));
1243
- },
1244
- [composer, disabled, onDrop]
1245
- );
1246
- return renderPrimitive(
1247
- "div",
1248
- {
1249
- ...props,
1250
- onDragLeave: handleDragLeave,
1251
- onDragOver: handleDragOver,
1252
- onDrop: handleDrop,
1253
- "data-state": disabled ? "disabled" : dragging ? "dragging" : "enabled"
1254
- },
1255
- ref
1256
- );
1257
- }
1258
- );
1259
- function createAttachment(attachment) {
1260
- return {
1261
- ...attachment,
1262
- id: attachment.id ?? createAttachmentId()
1263
- };
1264
- }
1265
- function isFileAttachmentInput(attachment) {
1266
- return typeof File !== "undefined" && attachment instanceof File;
1267
- }
1268
- async function attachmentFromFile(file) {
1269
- return {
1270
- id: createAttachmentId(),
1271
- type: file.type.startsWith("image/") ? "image" : "document",
1272
- name: file.name,
1273
- mediaType: file.type.length > 0 ? file.type : "application/octet-stream",
1274
- data: await readFileData(file)
1275
- };
1276
- }
1277
- async function readFileData(file) {
1278
- const dataUrl = await new Promise((resolve, reject) => {
1279
- const reader = new FileReader();
1280
- reader.addEventListener("load", () => {
1281
- resolve(String(reader.result ?? ""));
1282
- });
1283
- reader.addEventListener("error", () => {
1284
- reject(reader.error ?? new Error("Failed to read attachment."));
1285
- });
1286
- reader.readAsDataURL(file);
1287
- });
1288
- return dataUrl.includes(",") ? dataUrl.slice(dataUrl.indexOf(",") + 1) : dataUrl;
1289
- }
1290
- var nextAttachmentId = 0;
1291
- function createAttachmentId() {
1292
- const random = globalThis.crypto?.randomUUID?.();
1293
- if (random !== void 0) {
1294
- return `attachment_${random}`;
1295
- }
1296
- nextAttachmentId += 1;
1297
- return `attachment_${nextAttachmentId.toString(36)}`;
1298
- }
1299
- var ComposerPrimitive = {
1300
- Root: ComposerRoot,
1301
- Quote: ComposerQuotePreview,
1302
- ClearQuote: ComposerClearQuote,
1303
- Input: ComposerInput,
1304
- TextareaInput: ComposerTextareaInput,
1305
- TriggerMenu: ComposerTriggerMenu,
1306
- TriggerItem: ComposerTriggerItem,
1307
- Attachments: ComposerAttachments,
1308
- AddAttachment: ComposerAddAttachment,
1309
- AttachmentInput: ComposerAttachmentInput,
1310
- AttachmentDropzone: ComposerAttachmentDropzone,
1311
- Submit: ComposerSubmit,
1312
- Stop: ComposerStop
1313
- };
1314
-
1315
- // src/chat/thread.tsx
1316
- import {
1317
- Fragment as Fragment2,
1318
- forwardRef as forwardRef2,
1319
- useCallback as useCallback2,
1320
- useEffect as useEffect2,
1321
- useMemo as useMemo2,
1322
- useRef as useRef2,
1323
- useState as useState2
1324
- } from "react";
1325
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1326
- var ThreadRoot = forwardRef2(
1327
- function ThreadRoot2(props, ref) {
1328
- const chat = useChatContext();
1329
- const viewportRef = useRef2(null);
1330
- const messagesRef = useRef2(null);
1331
- const [atBottom, setAtBottom] = useState2(true);
1332
- const scrollToBottom = useCallback2((behavior = "smooth") => {
1333
- const viewport = viewportRef.current;
1334
- if (viewport === null) {
1335
- return;
1336
- }
1337
- viewport.scrollTo({ top: viewport.scrollHeight, behavior });
1338
- }, []);
1339
- const thread = useMemo2(
1340
- () => ({ viewportRef, messagesRef, atBottom, setAtBottom, scrollToBottom }),
1341
- [atBottom, scrollToBottom]
1342
- );
1343
- return /* @__PURE__ */ jsx2(InternalThreadProvider, { value: thread, children: renderPrimitive(
1344
- "div",
1345
- {
1346
- ...props,
1347
- "data-state": chat.status
1348
- },
1349
- ref
1350
- ) });
1351
- }
1352
- );
1353
- var ThreadViewport = forwardRef2(function ThreadViewport2({ autoScroll = true, onScroll, ...props }, ref) {
1354
- const chat = useChatContext();
1355
- const thread = useThread();
1356
- const messages = chat.messages;
1357
- const composedRef = useMemo2(
1358
- () => composeRefs(ref, (node) => {
1359
- thread.viewportRef.current = node;
1360
- }),
1361
- [ref, thread.viewportRef]
1362
- );
1363
- useEffect2(() => {
1364
- const hasMessages = messages.length > 0;
1365
- if (autoScroll && (thread.atBottom || !hasMessages)) {
1366
- thread.scrollToBottom("auto");
1367
- }
1368
- }, [autoScroll, messages, thread]);
1369
- useEffect2(() => {
1370
- const viewport = thread.viewportRef.current;
1371
- if (viewport === null || !autoScroll || typeof ResizeObserver !== "function") {
1372
- return;
1373
- }
1374
- const content = thread.messagesRef.current;
1375
- if (content === null) {
1376
- return;
1377
- }
1378
- const observer = new ResizeObserver(() => {
1379
- if (thread.atBottom) {
1380
- thread.scrollToBottom("auto");
1381
- }
1382
- });
1383
- observer.observe(viewport);
1384
- observer.observe(content);
1385
- return () => observer.disconnect();
1386
- }, [autoScroll, thread]);
1387
- const handleScroll = useCallback2(
1388
- (event) => {
1389
- onScroll?.(event);
1390
- const node = event.currentTarget;
1391
- const distanceFromBottom = node.scrollHeight - node.scrollTop - node.clientHeight;
1392
- thread.setAtBottom(distanceFromBottom < 80);
1393
- },
1394
- [onScroll, thread]
1395
- );
1396
- return renderPrimitive(
1397
- "div",
1398
- {
1399
- ...props,
1400
- onScroll: handleScroll,
1401
- "data-state": thread.atBottom ? "bottom" : "away"
1402
- },
1403
- composedRef
1404
- );
1405
- });
1406
- var ThreadViewportFooter = forwardRef2(
1407
- function ThreadViewportFooter2(props, ref) {
1408
- return renderPrimitive(
1409
- "div",
1410
- {
1411
- ...props
1412
- },
1413
- ref
1414
- );
1415
- }
1416
- );
1417
- var ThreadEmpty = forwardRef2(
1418
- function ThreadEmpty2(props, ref) {
1419
- const chat = useChatContext();
1420
- if (chat.messages.length > 0) {
1421
- return null;
1422
- }
1423
- return renderPrimitive(
1424
- "div",
1425
- {
1426
- ...props
1427
- },
1428
- ref
1429
- );
1430
- }
1431
- );
1432
- var ThreadStatus = forwardRef2(function ThreadStatus2({ children, ...props }, ref) {
1433
- const chat = useChatContext();
1434
- const renderedChildren = typeof children === "function" ? children(chat.status) : children;
1435
- return renderPrimitive(
1436
- "div",
1437
- {
1438
- ...props,
1439
- children: renderedChildren ?? chat.status,
1440
- "data-state": chat.status
1441
- },
1442
- ref
1443
- );
1444
- });
1445
- var ThreadLoading = forwardRef2(
1446
- function ThreadLoading2(props, ref) {
1447
- const chat = useChatContext();
1448
- if (chat.status !== "submitted" && chat.status !== "streaming") {
1449
- return null;
1450
- }
1451
- return renderPrimitive(
1452
- "div",
1453
- {
1454
- ...props,
1455
- children: props.children ?? "Loading"
1456
- },
1457
- ref
1458
- );
1459
- }
1460
- );
1461
- var ThreadError = forwardRef2(function ThreadError2({ children, ...props }, ref) {
1462
- const chat = useChatContext();
1463
- if (chat.status !== "error" && chat.error === void 0) {
1464
- return null;
1465
- }
1466
- const renderedChildren = typeof children === "function" ? children(chat.error) : children;
1467
- return renderPrimitive(
1468
- "div",
1469
- {
1470
- ...props,
1471
- children: renderedChildren ?? errorMessage(chat.error),
1472
- role: props.role ?? "alert"
1473
- },
1474
- ref
1475
- );
1476
- });
1477
- var ThreadMessages = forwardRef2(function ThreadMessages2({ children, keepMounted = true, ...props }, ref) {
1478
- const chat = useChatContext();
1479
- const thread = useThread();
1480
- const composedRef = useMemo2(
1481
- () => composeRefs(ref, (node) => {
1482
- thread.messagesRef.current = node;
1483
- }),
1484
- [ref, thread.messagesRef]
1485
- );
1486
- const empty = chat.messages.length === 0;
1487
- if (empty && !keepMounted) {
1488
- return null;
1489
- }
1490
- return renderPrimitive(
1491
- "div",
1492
- {
1493
- ...props,
1494
- children: chat.messages.map((message) => /* @__PURE__ */ jsx2(InternalMessageProvider, { message, children: typeof children === "function" ? children(message) : children ?? defaultMessage() }, message.id)),
1495
- "data-state": empty ? "empty" : "populated"
1496
- },
1497
- composedRef
1498
- );
1499
- });
1500
- var ThreadSuggestions = forwardRef2(
1501
- function ThreadSuggestions2({ children, keepMounted = false, ...props }, ref) {
1502
- const chat = useChatContext();
1503
- const suggestions = chat.suggestions ?? [];
1504
- const empty = suggestions.length === 0;
1505
- if (empty && !keepMounted) {
1506
- return null;
1507
- }
1508
- return renderPrimitive(
1509
- "div",
1510
- {
1511
- ...props,
1512
- children: suggestions.map(
1513
- (suggestion) => typeof children === "function" ? /* @__PURE__ */ jsx2(Fragment2, { children: children(suggestion) }, suggestion.id) : /* @__PURE__ */ jsx2(ThreadSuggestion, { suggestion, children }, suggestion.id)
1514
- ),
1515
- "data-role": "suggestions",
1516
- "data-state": empty ? "empty" : "populated"
1517
- },
1518
- ref
1519
- );
1520
- }
1521
- );
1522
- var ThreadSuggestion = forwardRef2(
1523
- function ThreadSuggestion2({ onClick, prompt, suggestion, ...props }, ref) {
1524
- const chat = useChatContext();
1525
- const suggestionPrompt = prompt ?? suggestion?.prompt ?? "";
1526
- const disabled = props.disabled ?? (suggestionPrompt.length === 0 || chat.status === "submitted" || chat.status === "streaming");
1527
- const handleClick = useCallback2(
1528
- (event) => {
1529
- onClick?.(event);
1530
- if (event.defaultPrevented || disabled) {
1531
- return;
1532
- }
1533
- void chat.sendMessage({ text: suggestionPrompt });
1534
- },
1535
- [chat, disabled, onClick, suggestionPrompt]
1536
- );
1537
- return renderPrimitive(
1538
- "button",
1539
- {
1540
- ...props,
1541
- children: props.children ?? suggestion?.label ?? suggestionPrompt,
1542
- disabled,
1543
- onClick: handleClick,
1544
- type: props.type ?? "button",
1545
- "data-state": disabled ? "disabled" : "enabled"
1546
- },
1547
- ref
1548
- );
1549
- }
1550
- );
1551
- var ThreadScrollToBottom = forwardRef2(
1552
- function ThreadScrollToBottom2({ onClick, ...props }, ref) {
1553
- const thread = useThread();
1554
- const disabled = props.disabled ?? thread.atBottom;
1555
- const handleClick = useCallback2(
1556
- (event) => {
1557
- onClick?.(event);
1558
- if (event.defaultPrevented || disabled) {
1559
- return;
1560
- }
1561
- thread.scrollToBottom();
1562
- },
1563
- [disabled, onClick, thread]
1564
- );
1565
- return renderPrimitive(
1566
- "button",
1567
- {
1568
- ...props,
1569
- children: props.children ?? "Scroll to bottom",
1570
- disabled,
1571
- onClick: handleClick,
1572
- type: props.type ?? "button",
1573
- "data-state": thread.atBottom ? "bottom" : "away"
1574
- },
1575
- ref
1576
- );
1577
- }
1578
- );
1579
- function defaultMessage() {
1580
- return /* @__PURE__ */ jsxs2(MessagePrimitive.Root, { children: [
1581
- /* @__PURE__ */ jsx2(MessagePrimitive.Content, { children: /* @__PURE__ */ jsx2(MessagePrimitive.Parts, {}) }),
1582
- /* @__PURE__ */ jsx2(MessagePrimitive.Actions, {})
1583
- ] });
1584
- }
1585
- function errorMessage(error) {
1586
- if (error instanceof Error) {
1587
- return error.message;
1588
- }
1589
- if (typeof error === "string") {
1590
- return error;
1591
- }
1592
- return "Something went wrong.";
1593
- }
1594
- var ThreadPrimitive = {
1595
- Root: ThreadRoot,
1596
- Viewport: ThreadViewport,
1597
- ViewportFooter: ThreadViewportFooter,
1598
- Messages: ThreadMessages,
1599
- Empty: ThreadEmpty,
1600
- Status: ThreadStatus,
1601
- Loading: ThreadLoading,
1602
- Error: ThreadError,
1603
- Suggestions: ThreadSuggestions,
1604
- Suggestion: ThreadSuggestion,
1605
- ScrollToBottom: ThreadScrollToBottom
1606
- };
1607
-
1608
- export {
1609
- ComposerPrimitive,
1610
- ThreadPrimitive
1611
- };
1612
- //# sourceMappingURL=chunk-T4IYUEPH.js.map