@agents24/chat-react 0.1.7 → 0.1.8

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 (42) hide show
  1. package/README.md +25 -12
  2. package/dist/chunk-E3TJ3I6G.js +358 -0
  3. package/dist/chunk-E3TJ3I6G.js.map +1 -0
  4. package/dist/chunk-EWZO4QJI.js +140 -0
  5. package/dist/chunk-EWZO4QJI.js.map +1 -0
  6. package/dist/chunk-UU7OXHL3.js +11 -0
  7. package/dist/chunk-UU7OXHL3.js.map +1 -0
  8. package/dist/context-window.d.ts +38 -0
  9. package/dist/controller.d.ts +22 -0
  10. package/dist/index.cjs +392 -314
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.ts +10 -530
  13. package/dist/index.js +41 -439
  14. package/dist/index.js.map +1 -1
  15. package/dist/latest-thread-scroller.d.ts +54 -0
  16. package/dist/model.d.ts +29 -0
  17. package/dist/renderers.d.ts +10 -0
  18. package/dist/sse.d.ts +3 -0
  19. package/dist/streaming-text.d.ts +24 -0
  20. package/dist/templates/agent-chat-shell.d.ts +25 -0
  21. package/dist/templates/index.cjs +523 -0
  22. package/dist/templates/index.cjs.map +1 -0
  23. package/dist/templates/index.d.ts +1 -0
  24. package/dist/templates/index.js +140 -0
  25. package/dist/templates/index.js.map +1 -0
  26. package/dist/transport.d.ts +29 -0
  27. package/dist/types.d.ts +312 -0
  28. package/dist/ui/adapters.d.ts +36 -0
  29. package/dist/ui/attachment.d.ts +23 -0
  30. package/dist/ui/bubble.d.ts +17 -0
  31. package/dist/ui/index.cjs +943 -0
  32. package/dist/ui/index.cjs.map +1 -0
  33. package/dist/ui/index.d.ts +7 -0
  34. package/dist/ui/index.js +734 -0
  35. package/dist/ui/index.js.map +1 -0
  36. package/dist/ui/marker.d.ts +11 -0
  37. package/dist/ui/message-response.d.ts +7 -0
  38. package/dist/ui/message.d.ts +10 -0
  39. package/dist/ui/utils.d.ts +2 -0
  40. package/dist/viewport.d.ts +2 -0
  41. package/package.json +22 -4
  42. package/dist/index.d.cts +0 -530
@@ -0,0 +1,734 @@
1
+ import {
2
+ useStreamingText
3
+ } from "../chunk-EWZO4QJI.js";
4
+ import {
5
+ cn
6
+ } from "../chunk-UU7OXHL3.js";
7
+
8
+ // src/ui/adapters.ts
9
+ import * as React from "react";
10
+
11
+ // src/ui/attachment.tsx
12
+ import { cva } from "class-variance-authority";
13
+ import { Slot } from "@radix-ui/react-slot";
14
+ import { jsx } from "react/jsx-runtime";
15
+ var attachmentVariants = cva(
16
+ "group/attachment relative flex w-fit max-w-full min-w-0 shrink-0 flex-wrap rounded-xl border bg-card text-card-foreground transition-colors focus-within:ring-1 focus-within:ring-ring/50 has-[>a,>button]:hover:bg-muted/50 data-[state=error]:border-destructive/30 data-[state=idle]:border-dashed",
17
+ {
18
+ variants: {
19
+ size: {
20
+ default: "gap-2 text-sm has-data-[slot=attachment-content]:px-2.5 has-data-[slot=attachment-content]:py-2 has-data-[slot=attachment-media]:p-2",
21
+ sm: "gap-2.5 text-xs has-data-[slot=attachment-content]:px-2 has-data-[slot=attachment-content]:py-1.5 has-data-[slot=attachment-media]:p-1.5",
22
+ xs: "gap-1.5 rounded-lg text-xs has-data-[slot=attachment-content]:px-1.5 has-data-[slot=attachment-content]:py-1 has-data-[slot=attachment-media]:p-1"
23
+ },
24
+ orientation: {
25
+ horizontal: "min-w-40 items-center",
26
+ vertical: "w-24 flex-col has-data-[slot=attachment-content]:w-30"
27
+ }
28
+ }
29
+ }
30
+ );
31
+ function Attachment({
32
+ className,
33
+ state = "done",
34
+ size = "default",
35
+ orientation = "horizontal",
36
+ ...props
37
+ }) {
38
+ return /* @__PURE__ */ jsx(
39
+ "div",
40
+ {
41
+ "data-slot": "attachment",
42
+ "data-state": state,
43
+ "data-size": size,
44
+ "data-orientation": orientation,
45
+ className: cn(attachmentVariants({ size, orientation }), className),
46
+ ...props
47
+ }
48
+ );
49
+ }
50
+ var attachmentMediaVariants = cva(
51
+ "relative flex aspect-square w-10 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-muted text-foreground group-data-[orientation=vertical]/attachment:w-full group-data-[size=sm]/attachment:w-8 group-data-[size=xs]/attachment:w-7 group-data-[size=xs]/attachment:rounded-md group-data-[state=error]/attachment:bg-destructive/10 group-data-[state=error]/attachment:text-destructive group-data-[orientation=vertical]/attachment:*:data-[slot=spinner]:size-6! [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 group-data-[orientation=vertical]/attachment:[&_svg:not([class*='size-'])]:size-6 group-data-[size=xs]/attachment:[&_svg:not([class*='size-'])]:size-3.5",
52
+ {
53
+ variants: {
54
+ variant: {
55
+ icon: "",
56
+ image: "opacity-60 group-data-[state=done]/attachment:opacity-100 group-data-[state=idle]/attachment:opacity-100 *:[img]:aspect-square *:[img]:w-full *:[img]:object-cover"
57
+ }
58
+ },
59
+ defaultVariants: {
60
+ variant: "icon"
61
+ }
62
+ }
63
+ );
64
+ function AttachmentMedia({
65
+ className,
66
+ variant = "icon",
67
+ ...props
68
+ }) {
69
+ return /* @__PURE__ */ jsx(
70
+ "div",
71
+ {
72
+ "data-slot": "attachment-media",
73
+ "data-variant": variant,
74
+ className: cn(attachmentMediaVariants({ variant }), className),
75
+ ...props
76
+ }
77
+ );
78
+ }
79
+ function AttachmentContent({
80
+ className,
81
+ ...props
82
+ }) {
83
+ return /* @__PURE__ */ jsx(
84
+ "div",
85
+ {
86
+ "data-slot": "attachment-content",
87
+ className: cn(
88
+ "max-w-full min-w-0 flex-1 leading-tight group-data-[orientation=vertical]/attachment:px-1",
89
+ className
90
+ ),
91
+ ...props
92
+ }
93
+ );
94
+ }
95
+ function AttachmentTitle({
96
+ className,
97
+ ...props
98
+ }) {
99
+ return /* @__PURE__ */ jsx(
100
+ "span",
101
+ {
102
+ "data-slot": "attachment-title",
103
+ className: cn(
104
+ "block max-w-full min-w-0 truncate font-medium group-data-[state=processing]/attachment:shimmer group-data-[state=uploading]/attachment:shimmer",
105
+ className
106
+ ),
107
+ ...props
108
+ }
109
+ );
110
+ }
111
+ function AttachmentDescription({
112
+ className,
113
+ ...props
114
+ }) {
115
+ return /* @__PURE__ */ jsx(
116
+ "span",
117
+ {
118
+ "data-slot": "attachment-description",
119
+ className: cn(
120
+ "mt-0.5 block min-w-0 truncate text-xs text-muted-foreground group-data-[state=error]/attachment:text-destructive/80",
121
+ "max-w-full",
122
+ className
123
+ ),
124
+ ...props
125
+ }
126
+ );
127
+ }
128
+ function AttachmentActions({
129
+ className,
130
+ ...props
131
+ }) {
132
+ return /* @__PURE__ */ jsx(
133
+ "div",
134
+ {
135
+ "data-slot": "attachment-actions",
136
+ className: cn(
137
+ "relative z-20 flex shrink-0 items-center group-data-[orientation=vertical]/attachment:absolute group-data-[orientation=vertical]/attachment:top-3 group-data-[orientation=vertical]/attachment:right-3 group-data-[orientation=vertical]/attachment:gap-1",
138
+ className
139
+ ),
140
+ ...props
141
+ }
142
+ );
143
+ }
144
+ function AttachmentAction({
145
+ className,
146
+ type = "button",
147
+ ...props
148
+ }) {
149
+ return /* @__PURE__ */ jsx(
150
+ "button",
151
+ {
152
+ "data-slot": "attachment-action",
153
+ type,
154
+ className: cn(
155
+ "inline-flex size-6 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
156
+ className
157
+ ),
158
+ ...props
159
+ }
160
+ );
161
+ }
162
+ function AttachmentTrigger({
163
+ className,
164
+ asChild = false,
165
+ type,
166
+ ...props
167
+ }) {
168
+ const Comp = asChild ? Slot : "button";
169
+ return /* @__PURE__ */ jsx(
170
+ Comp,
171
+ {
172
+ "data-slot": "attachment-trigger",
173
+ type: asChild ? void 0 : type ?? "button",
174
+ className: cn("absolute inset-0 z-10 outline-none", className),
175
+ ...props
176
+ }
177
+ );
178
+ }
179
+ function AttachmentGroup({ className, ...props }) {
180
+ return /* @__PURE__ */ jsx(
181
+ "div",
182
+ {
183
+ "data-slot": "attachment-group",
184
+ className: cn(
185
+ "flex min-w-0 scroll-fade-x snap-x snap-mandatory scroll-px-1 scrollbar-none gap-3 overflow-x-auto overscroll-x-contain py-1 *:data-[slot=attachment]:flex-none *:data-[slot=attachment]:snap-start",
186
+ className
187
+ ),
188
+ ...props
189
+ }
190
+ );
191
+ }
192
+
193
+ // src/ui/bubble.tsx
194
+ import { cva as cva2 } from "class-variance-authority";
195
+ import { Slot as Slot2 } from "@radix-ui/react-slot";
196
+ import { jsx as jsx2 } from "react/jsx-runtime";
197
+ function BubbleGroup({ className, ...props }) {
198
+ return /* @__PURE__ */ jsx2(
199
+ "div",
200
+ {
201
+ "data-slot": "bubble-group",
202
+ className: cn("flex min-w-0 flex-col gap-2", className),
203
+ ...props
204
+ }
205
+ );
206
+ }
207
+ var bubbleVariants = cva2(
208
+ "group/bubble relative flex w-fit max-w-[80%] min-w-0 flex-col gap-1 group-data-[align=end]/message:self-end data-[align=end]:self-end data-[variant=ghost]:max-w-full",
209
+ {
210
+ variants: {
211
+ variant: {
212
+ default: "*:data-[slot=bubble-content]:bg-primary *:data-[slot=bubble-content]:text-primary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-primary/80",
213
+ secondary: "*:data-[slot=bubble-content]:bg-secondary *:data-[slot=bubble-content]:text-secondary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)]",
214
+ muted: "*:data-[slot=bubble-content]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--muted),var(--foreground)_5%)]",
215
+ tinted: "*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.93_calc(c*0.4)_h)] *:data-[slot=bubble-content]:text-foreground dark:*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.3_calc(c*0.4)_h)] [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.88_calc(c*0.5)_h)] dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.35_calc(c*0.5)_h)]",
216
+ outline: "*:data-[slot=bubble-content]:border-border *:data-[slot=bubble-content]:bg-background [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-input/30",
217
+ ghost: "border-none *:data-[slot=bubble-content]:rounded-none *:data-[slot=bubble-content]:bg-transparent *:data-[slot=bubble-content]:p-0 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted/50",
218
+ destructive: "*:data-[slot=bubble-content]:bg-destructive/10 *:data-[slot=bubble-content]:text-destructive dark:*:data-[slot=bubble-content]:bg-destructive/20 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/20 dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/30"
219
+ }
220
+ },
221
+ defaultVariants: {
222
+ variant: "default"
223
+ }
224
+ }
225
+ );
226
+ function Bubble({
227
+ variant = "default",
228
+ align = "start",
229
+ className,
230
+ ...props
231
+ }) {
232
+ return /* @__PURE__ */ jsx2(
233
+ "div",
234
+ {
235
+ "data-slot": "bubble",
236
+ "data-variant": variant,
237
+ "data-align": align,
238
+ className: cn(bubbleVariants({ variant }), className),
239
+ ...props
240
+ }
241
+ );
242
+ }
243
+ function BubbleContent({
244
+ asChild = false,
245
+ className,
246
+ ...props
247
+ }) {
248
+ const Comp = asChild ? Slot2 : "div";
249
+ return /* @__PURE__ */ jsx2(
250
+ Comp,
251
+ {
252
+ "data-slot": "bubble-content",
253
+ className: cn(
254
+ "w-fit max-w-full min-w-0 overflow-hidden rounded-xl border border-transparent px-3 py-2 text-sm leading-relaxed wrap-break-word group-data-[align=end]/bubble:self-end [button]:text-left [button,a]:transition-colors [button,a]:outline-none [button,a]:focus-visible:border-ring [button,a]:focus-visible:ring-3 [button,a]:focus-visible:ring-ring/50",
255
+ className
256
+ ),
257
+ ...props
258
+ }
259
+ );
260
+ }
261
+ var bubbleReactionsVariants = cva2(
262
+ "absolute z-10 flex w-fit shrink-0 items-center justify-center gap-1 rounded-full bg-muted px-1.5 py-0.5 text-sm ring-3 ring-card has-[button]:p-0",
263
+ {
264
+ variants: {
265
+ side: {
266
+ top: "top-0 -translate-y-3/4",
267
+ bottom: "bottom-0 translate-y-3/4"
268
+ },
269
+ align: {
270
+ start: "left-3",
271
+ end: "right-3"
272
+ }
273
+ },
274
+ defaultVariants: {
275
+ side: "bottom",
276
+ align: "end"
277
+ }
278
+ }
279
+ );
280
+ function BubbleReactions({
281
+ side = "bottom",
282
+ align = "end",
283
+ className,
284
+ ...props
285
+ }) {
286
+ return /* @__PURE__ */ jsx2(
287
+ "div",
288
+ {
289
+ "data-slot": "bubble-reactions",
290
+ "data-align": align,
291
+ "data-side": side,
292
+ className: cn(bubbleReactionsVariants({ side, align }), className),
293
+ ...props
294
+ }
295
+ );
296
+ }
297
+
298
+ // src/ui/message.tsx
299
+ import { jsx as jsx3 } from "react/jsx-runtime";
300
+ function MessageGroup({ className, ...props }) {
301
+ return /* @__PURE__ */ jsx3(
302
+ "div",
303
+ {
304
+ "data-slot": "message-group",
305
+ className: cn("flex min-w-0 flex-col gap-2", className),
306
+ ...props
307
+ }
308
+ );
309
+ }
310
+ function Message({
311
+ className,
312
+ align = "start",
313
+ ...props
314
+ }) {
315
+ return /* @__PURE__ */ jsx3(
316
+ "div",
317
+ {
318
+ "data-slot": "message",
319
+ "data-align": align,
320
+ className: cn(
321
+ "group/message relative flex w-full min-w-0 gap-2 text-sm data-[align=end]:flex-row-reverse",
322
+ className
323
+ ),
324
+ ...props
325
+ }
326
+ );
327
+ }
328
+ function MessageAvatar({ className, ...props }) {
329
+ return /* @__PURE__ */ jsx3(
330
+ "div",
331
+ {
332
+ "data-slot": "message-avatar",
333
+ className: cn(
334
+ "flex w-fit min-w-8 shrink-0 items-center justify-center self-end overflow-hidden rounded-full bg-muted group-has-data-[slot=message-footer]/message:-translate-y-8",
335
+ className
336
+ ),
337
+ ...props
338
+ }
339
+ );
340
+ }
341
+ function MessageContent({ className, ...props }) {
342
+ return /* @__PURE__ */ jsx3(
343
+ "div",
344
+ {
345
+ "data-slot": "message-content",
346
+ className: cn(
347
+ "flex w-full min-w-0 flex-col gap-2.5 wrap-break-word group-data-[align=end]/message:*:data-slot:self-end",
348
+ className
349
+ ),
350
+ ...props
351
+ }
352
+ );
353
+ }
354
+ function MessageHeader({ className, ...props }) {
355
+ return /* @__PURE__ */ jsx3(
356
+ "div",
357
+ {
358
+ "data-slot": "message-header",
359
+ className: cn(
360
+ "flex max-w-full min-w-0 items-center px-3 text-xs font-medium text-muted-foreground group-has-data-[variant=ghost]/message:px-0",
361
+ className
362
+ ),
363
+ ...props
364
+ }
365
+ );
366
+ }
367
+ function MessageFooter({ className, ...props }) {
368
+ return /* @__PURE__ */ jsx3(
369
+ "div",
370
+ {
371
+ "data-slot": "message-footer",
372
+ className: cn(
373
+ "flex max-w-full min-w-0 items-center px-3 text-xs font-medium text-muted-foreground group-has-data-[variant=ghost]/message:px-0 group-data-[align=end]/message:justify-end",
374
+ className
375
+ ),
376
+ ...props
377
+ }
378
+ );
379
+ }
380
+
381
+ // src/ui/adapters.ts
382
+ function ChatMessage(input) {
383
+ const { className, from, align, ...props } = input;
384
+ const isUser = from === "user";
385
+ const isRtl = props.dir === "rtl";
386
+ const resolvedAlign = align || "start";
387
+ const messageProps = Object.assign({}, props);
388
+ messageProps.align = resolvedAlign;
389
+ messageProps.className = cn(
390
+ "group flex w-full flex-col gap-2 overflow-visible",
391
+ isUser ? cn("is-user max-w-[80%] justify-end", isRtl ? "mr-auto" : "ml-auto") : "is-assistant max-w-full",
392
+ className
393
+ );
394
+ return React.createElement(Message, messageProps);
395
+ }
396
+ function ChatMessageContent({
397
+ className,
398
+ ...props
399
+ }) {
400
+ return React.createElement(BubbleContent, {
401
+ className: cn(
402
+ "flex w-full max-w-full min-w-0 flex-col gap-2 text-sm",
403
+ "group-[.is-user]:w-fit group-[.is-user]:overflow-visible group-[.is-user]:rounded-lg group-[.is-user]:bg-secondary group-[.is-user]:px-4 group-[.is-user]:py-3 group-[.is-user]:text-foreground",
404
+ "group-[.is-assistant]:w-full group-[.is-assistant]:max-w-full group-[.is-assistant]:overflow-hidden group-[.is-assistant]:text-foreground",
405
+ props.dir === "rtl" ? "group-[.is-assistant]:pr-0" : "group-[.is-assistant]:pl-0",
406
+ props.dir === "rtl" ? "group-[.is-user]:mr-auto" : "group-[.is-user]:ml-auto",
407
+ className
408
+ ),
409
+ ...props
410
+ });
411
+ }
412
+ function ChatMessageActions({
413
+ className,
414
+ ...props
415
+ }) {
416
+ return React.createElement("div", {
417
+ className: cn("flex items-center gap-1", className),
418
+ "data-slot": "message-actions",
419
+ ...props
420
+ });
421
+ }
422
+ function ChatMessageAction({
423
+ children,
424
+ className,
425
+ label,
426
+ tooltip,
427
+ type = "button",
428
+ ...props
429
+ }) {
430
+ const tooltipLabel = typeof tooltip === "string" ? tooltip : void 0;
431
+ return React.createElement(
432
+ "button",
433
+ {
434
+ "aria-label": label || tooltipLabel,
435
+ className: cn(
436
+ "inline-flex size-8 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
437
+ className
438
+ ),
439
+ title: tooltipLabel,
440
+ type,
441
+ ...props
442
+ },
443
+ children,
444
+ React.createElement(
445
+ "span",
446
+ { className: "sr-only" },
447
+ label || tooltipLabel
448
+ )
449
+ );
450
+ }
451
+ function ChatAttachment({
452
+ data,
453
+ onRemove,
454
+ orientation,
455
+ ...props
456
+ }) {
457
+ const mediaType = data.mediaType || data.contentType || String(data.type || "application/octet-stream");
458
+ const filename = data.filename || data.name || "Attachment";
459
+ const isImage = mediaType.startsWith("image/") && Boolean(data.url);
460
+ return React.createElement(
461
+ Attachment,
462
+ {
463
+ orientation: orientation || (isImage ? "vertical" : "horizontal"),
464
+ ...props
465
+ },
466
+ React.createElement(
467
+ AttachmentMedia,
468
+ { variant: isImage ? "image" : "icon" },
469
+ isImage ? React.createElement("img", {
470
+ alt: filename,
471
+ className: "size-full object-cover",
472
+ src: data.url
473
+ }) : React.createElement(
474
+ "span",
475
+ { "aria-hidden": "true", className: "text-sm" },
476
+ filename.slice(0, 1).toUpperCase()
477
+ )
478
+ ),
479
+ React.createElement(
480
+ AttachmentContent,
481
+ null,
482
+ React.createElement(AttachmentTitle, null, filename),
483
+ React.createElement(AttachmentDescription, null, mediaType)
484
+ ),
485
+ onRemove ? React.createElement(
486
+ "button",
487
+ {
488
+ "aria-label": "Remove attachment",
489
+ className: "relative z-20 mr-1 inline-flex size-6 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-muted hover:text-foreground",
490
+ onClick: (event) => {
491
+ event.stopPropagation();
492
+ onRemove();
493
+ },
494
+ type: "button"
495
+ },
496
+ React.createElement("span", { "aria-hidden": "true" }, "x")
497
+ ) : null
498
+ );
499
+ }
500
+ function ChatAttachments({
501
+ children,
502
+ className,
503
+ ...props
504
+ }) {
505
+ if (!children) return null;
506
+ return React.createElement(
507
+ AttachmentGroup,
508
+ {
509
+ className: cn(
510
+ props.dir === "rtl" ? "mr-auto" : "ml-auto",
511
+ "w-fit flex-wrap overflow-visible",
512
+ className
513
+ ),
514
+ ...props
515
+ },
516
+ children
517
+ );
518
+ }
519
+
520
+ // src/ui/marker.tsx
521
+ import { cva as cva3 } from "class-variance-authority";
522
+ import { Slot as Slot3 } from "@radix-ui/react-slot";
523
+ import { jsx as jsx4 } from "react/jsx-runtime";
524
+ var markerVariants = cva3(
525
+ "group/marker relative flex min-h-4 w-full items-center gap-2 text-left text-sm text-muted-foreground [&_svg:not([class*='size-'])]:size-4 [a]:underline [a]:underline-offset-3 [a]:hover:text-foreground",
526
+ {
527
+ variants: {
528
+ variant: {
529
+ default: "",
530
+ separator: "before:mr-1 before:h-px before:min-w-0 before:flex-1 before:bg-border after:ml-1 after:h-px after:min-w-0 after:flex-1 after:bg-border",
531
+ border: "border-b border-border pb-2"
532
+ }
533
+ }
534
+ }
535
+ );
536
+ function Marker({
537
+ className,
538
+ variant = "default",
539
+ asChild = false,
540
+ ...props
541
+ }) {
542
+ const Comp = asChild ? Slot3 : "div";
543
+ return /* @__PURE__ */ jsx4(
544
+ Comp,
545
+ {
546
+ "data-slot": "marker",
547
+ "data-variant": variant,
548
+ className: cn(markerVariants({ variant, className })),
549
+ ...props
550
+ }
551
+ );
552
+ }
553
+ function MarkerIcon({ className, ...props }) {
554
+ return /* @__PURE__ */ jsx4(
555
+ "span",
556
+ {
557
+ "data-slot": "marker-icon",
558
+ "aria-hidden": "true",
559
+ className: cn(
560
+ "size-4 shrink-0 [&_svg:not([class*='size-'])]:size-4",
561
+ className
562
+ ),
563
+ ...props
564
+ }
565
+ );
566
+ }
567
+ function MarkerContent({ className, ...props }) {
568
+ return /* @__PURE__ */ jsx4(
569
+ "span",
570
+ {
571
+ "data-slot": "marker-content",
572
+ className: cn(
573
+ "min-w-0 wrap-break-word group-data-[variant=separator]/marker:flex-none group-data-[variant=separator]/marker:text-center *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
574
+ className
575
+ ),
576
+ ...props
577
+ }
578
+ );
579
+ }
580
+
581
+ // src/ui/message-response.tsx
582
+ import * as React2 from "react";
583
+ import { defaultRehypePlugins, Streamdown } from "streamdown";
584
+ import { Fragment, jsx as jsx5 } from "react/jsx-runtime";
585
+ var BLOCK_MARKDOWN_TAGS = /* @__PURE__ */ new Set([
586
+ "blockquote",
587
+ "div",
588
+ "h1",
589
+ "h2",
590
+ "h3",
591
+ "h4",
592
+ "h5",
593
+ "h6",
594
+ "hr",
595
+ "ol",
596
+ "pre",
597
+ "table",
598
+ "ul"
599
+ ]);
600
+ function isMultilineCodeNode(node) {
601
+ return node?.tagName === "code" && node.position?.start?.line !== void 0 && node.position?.end?.line !== void 0 && node.position.start.line !== node.position.end.line;
602
+ }
603
+ function hasBlockMarkdownChild(child) {
604
+ if (!React2.isValidElement(child)) {
605
+ return false;
606
+ }
607
+ if (typeof child.type === "string" && BLOCK_MARKDOWN_TAGS.has(child.type)) {
608
+ return true;
609
+ }
610
+ const props = child.props;
611
+ if (BLOCK_MARKDOWN_TAGS.has(props.node?.tagName || "") || isMultilineCodeNode(props.node)) {
612
+ return true;
613
+ }
614
+ return React2.Children.toArray(props.children).some(hasBlockMarkdownChild);
615
+ }
616
+ function MessageMarkdownParagraph({
617
+ children,
618
+ ...props
619
+ }) {
620
+ const domProps = { ...props };
621
+ delete domProps.node;
622
+ const childArray = React2.Children.toArray(children).filter(
623
+ (child) => child !== null && child !== ""
624
+ );
625
+ const isImageOnly = childArray.length === 1 && React2.isValidElement(childArray[0]) && childArray[0].props.node?.tagName === "img";
626
+ if (isImageOnly) {
627
+ return /* @__PURE__ */ jsx5(Fragment, { children });
628
+ }
629
+ if (childArray.some(hasBlockMarkdownChild)) {
630
+ return /* @__PURE__ */ jsx5("div", { ...domProps, children });
631
+ }
632
+ return /* @__PURE__ */ jsx5("p", { ...domProps, children });
633
+ }
634
+ var MESSAGE_RESPONSE_COMPONENTS = {
635
+ p: MessageMarkdownParagraph
636
+ };
637
+ var streamdownDefaultRehypePlugins = defaultRehypePlugins || {};
638
+ var streamdownHardenPlugin = Array.isArray(
639
+ streamdownDefaultRehypePlugins.harden
640
+ ) ? streamdownDefaultRehypePlugins.harden[0] : streamdownDefaultRehypePlugins.harden;
641
+ var MESSAGE_RESPONSE_REHYPE_PLUGINS = [
642
+ ...Object.entries(streamdownDefaultRehypePlugins).filter(([key]) => key !== "harden").map(([, plugin]) => plugin),
643
+ ...streamdownHardenPlugin ? [
644
+ [
645
+ streamdownHardenPlugin,
646
+ {
647
+ allowDataImages: true,
648
+ allowedImagePrefixes: ["*"],
649
+ allowedLinkPrefixes: ["*"],
650
+ allowedProtocols: ["*", "reshet:", "source:"],
651
+ defaultOrigin: void 0
652
+ }
653
+ ]
654
+ ] : []
655
+ ];
656
+ var MessageResponse = React2.memo(
657
+ ({
658
+ children,
659
+ className,
660
+ components,
661
+ rehypePlugins,
662
+ streaming = false,
663
+ streamingId,
664
+ ...props
665
+ }) => {
666
+ const text = typeof children === "string" || typeof children === "number" ? String(children) : "";
667
+ const streamingText = useStreamingText({
668
+ charsPerSecond: 120,
669
+ id: streamingId || text,
670
+ isStreaming: streaming && text.length > 0,
671
+ maxCatchupChars: 32,
672
+ text
673
+ });
674
+ const streamdownComponents = React2.useMemo(
675
+ () => ({ ...MESSAGE_RESPONSE_COMPONENTS, ...components }),
676
+ [components]
677
+ );
678
+ return /* @__PURE__ */ jsx5(
679
+ Streamdown,
680
+ {
681
+ className: cn("size-full [&>*:first-child]:mt-0 [&>*:last-child]:mb-0", className),
682
+ components: streamdownComponents,
683
+ rehypePlugins: rehypePlugins || MESSAGE_RESPONSE_REHYPE_PLUGINS,
684
+ ...props,
685
+ children: text ? streamingText.displayedText : children
686
+ }
687
+ );
688
+ },
689
+ (prevProps, nextProps) => prevProps.children === nextProps.children && prevProps.className === nextProps.className && prevProps.streaming === nextProps.streaming && prevProps.streamingId === nextProps.streamingId && prevProps.components === nextProps.components
690
+ );
691
+ MessageResponse.displayName = "MessageResponse";
692
+ export {
693
+ Attachment,
694
+ AttachmentAction,
695
+ AttachmentActions,
696
+ AttachmentContent,
697
+ AttachmentDescription,
698
+ AttachmentGroup,
699
+ AttachmentMedia,
700
+ AttachmentTitle,
701
+ AttachmentTrigger,
702
+ Bubble,
703
+ BubbleContent,
704
+ BubbleGroup,
705
+ BubbleReactions,
706
+ ChatAttachment,
707
+ ChatAttachments,
708
+ ChatMessage,
709
+ ChatMessageAction,
710
+ ChatMessageActions,
711
+ ChatMessageContent,
712
+ Marker,
713
+ MarkerContent,
714
+ MarkerIcon,
715
+ ChatMessage as Message,
716
+ ChatMessageAction as MessageAction,
717
+ ChatMessageActions as MessageActions,
718
+ ChatAttachment as MessageAttachment,
719
+ ChatAttachments as MessageAttachments,
720
+ MessageAvatar,
721
+ ChatMessageContent as MessageContent,
722
+ MessageFooter,
723
+ MessageGroup,
724
+ MessageHeader,
725
+ MessageResponse,
726
+ Message as ShadcnMessage,
727
+ MessageContent as ShadcnMessageContent,
728
+ attachmentMediaVariants,
729
+ attachmentVariants,
730
+ bubbleVariants,
731
+ cn,
732
+ markerVariants
733
+ };
734
+ //# sourceMappingURL=index.js.map