@mieweb/ui 0.6.1-dev.148 → 0.6.1-dev.150

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 (82) hide show
  1. package/dist/brands/index.cjs +22 -22
  2. package/dist/brands/index.js +5 -5
  3. package/dist/chunk-2T4JU5RH.cjs +1156 -0
  4. package/dist/chunk-2T4JU5RH.cjs.map +1 -0
  5. package/dist/chunk-3SSXDWD7.js +363 -0
  6. package/dist/chunk-3SSXDWD7.js.map +1 -0
  7. package/dist/{chunk-MARLXJQO.cjs → chunk-6R2ZPDN7.cjs} +7 -7
  8. package/dist/{chunk-MARLXJQO.cjs.map → chunk-6R2ZPDN7.cjs.map} +1 -1
  9. package/dist/{chunk-WHUD3XHR.cjs → chunk-7PA26KBF.cjs} +15 -3
  10. package/dist/chunk-7PA26KBF.cjs.map +1 -0
  11. package/dist/chunk-ASLZUFH4.js +1967 -0
  12. package/dist/chunk-ASLZUFH4.js.map +1 -0
  13. package/dist/chunk-FADQVM4M.cjs +2017 -0
  14. package/dist/chunk-FADQVM4M.cjs.map +1 -0
  15. package/dist/{chunk-DFT7TYKL.cjs → chunk-H4T5T65N.cjs} +6 -3
  16. package/dist/chunk-H4T5T65N.cjs.map +1 -0
  17. package/dist/chunk-I6CY5C6A.js +12 -0
  18. package/dist/chunk-I6CY5C6A.js.map +1 -0
  19. package/dist/chunk-JFLC7SHM.cjs +35 -0
  20. package/dist/chunk-JFLC7SHM.cjs.map +1 -0
  21. package/dist/chunk-LZPPH5BW.cjs +368 -0
  22. package/dist/chunk-LZPPH5BW.cjs.map +1 -0
  23. package/dist/{chunk-3OHVUXDG.js → chunk-M7BLVBL4.js} +6 -3
  24. package/dist/chunk-M7BLVBL4.js.map +1 -0
  25. package/dist/chunk-PM2I3QKM.cjs +1419 -0
  26. package/dist/chunk-PM2I3QKM.cjs.map +1 -0
  27. package/dist/{chunk-TW6DXMSD.js → chunk-R6PBBPU3.js} +2 -2
  28. package/dist/{chunk-TW6DXMSD.js.map → chunk-R6PBBPU3.js.map} +1 -1
  29. package/dist/{chunk-33PO3J4O.js → chunk-RXY5SD3O.js} +15 -3
  30. package/dist/chunk-RXY5SD3O.js.map +1 -0
  31. package/dist/{chunk-AEGYWRSL.js → chunk-TXYTMU3K.js} +3 -3
  32. package/dist/{chunk-AEGYWRSL.js.map → chunk-TXYTMU3K.js.map} +1 -1
  33. package/dist/chunk-UHPQYBXQ.js +1124 -0
  34. package/dist/chunk-UHPQYBXQ.js.map +1 -0
  35. package/dist/chunk-XQE26F3G.js +1383 -0
  36. package/dist/chunk-XQE26F3G.js.map +1 -0
  37. package/dist/{chunk-26YNFCOC.cjs → chunk-Z6NRP4Z5.cjs} +2 -2
  38. package/dist/{chunk-26YNFCOC.cjs.map → chunk-Z6NRP4Z5.cjs.map} +1 -1
  39. package/dist/components/Dropdown/index.cjs +7 -7
  40. package/dist/components/Dropdown/index.d.cts +1 -1
  41. package/dist/components/Dropdown/index.d.ts +1 -1
  42. package/dist/components/Dropdown/index.js +1 -1
  43. package/dist/components/RichTextEditor/index.cjs +5 -5
  44. package/dist/components/RichTextEditor/index.js +2 -2
  45. package/dist/components/SuperChat/index.cjs +1319 -0
  46. package/dist/components/SuperChat/index.cjs.map +1 -0
  47. package/dist/components/SuperChat/index.d.cts +189 -0
  48. package/dist/components/SuperChat/index.d.ts +189 -0
  49. package/dist/components/SuperChat/index.js +1282 -0
  50. package/dist/components/SuperChat/index.js.map +1 -0
  51. package/dist/components/SuperChat/plugins/index.cjs +1221 -0
  52. package/dist/components/SuperChat/plugins/index.cjs.map +1 -0
  53. package/dist/components/SuperChat/plugins/index.d.cts +253 -0
  54. package/dist/components/SuperChat/plugins/index.d.ts +253 -0
  55. package/dist/components/SuperChat/plugins/index.js +1181 -0
  56. package/dist/components/SuperChat/plugins/index.js.map +1 -0
  57. package/dist/datavis.cjs +18 -362
  58. package/dist/datavis.cjs.map +1 -1
  59. package/dist/datavis.js +1 -361
  60. package/dist/datavis.js.map +1 -1
  61. package/dist/index.cjs +1297 -5412
  62. package/dist/index.cjs.map +1 -1
  63. package/dist/index.d.cts +44 -240
  64. package/dist/index.d.ts +44 -240
  65. package/dist/index.js +759 -5037
  66. package/dist/index.js.map +1 -1
  67. package/dist/nitroTableGrid-FWRCDE4N.js +22 -0
  68. package/dist/nitroTableGrid-FWRCDE4N.js.map +1 -0
  69. package/dist/nitroTableGrid-IY75TQJ2.cjs +44 -0
  70. package/dist/nitroTableGrid-IY75TQJ2.cjs.map +1 -0
  71. package/dist/styles.css +1 -1
  72. package/dist/tailwind-preset.cjs +4 -4
  73. package/dist/tailwind-preset.js +1 -1
  74. package/dist/types-BFFgW6qy.d.ts +240 -0
  75. package/dist/types-BzeY_kYO.d.cts +242 -0
  76. package/dist/types-BzeY_kYO.d.ts +242 -0
  77. package/dist/types-CRt5IPNL.d.cts +240 -0
  78. package/package.json +41 -4
  79. package/dist/chunk-33PO3J4O.js.map +0 -1
  80. package/dist/chunk-3OHVUXDG.js.map +0 -1
  81. package/dist/chunk-DFT7TYKL.cjs.map +0 -1
  82. package/dist/chunk-WHUD3XHR.cjs.map +0 -1
@@ -0,0 +1,1319 @@
1
+ 'use strict';
2
+
3
+ var chunkJFLC7SHM_cjs = require('../../chunk-JFLC7SHM.cjs');
4
+ var chunkPM2I3QKM_cjs = require('../../chunk-PM2I3QKM.cjs');
5
+ var chunk2T4JU5RH_cjs = require('../../chunk-2T4JU5RH.cjs');
6
+ var chunkH4T5T65N_cjs = require('../../chunk-H4T5T65N.cjs');
7
+ require('../../chunk-MSRU3XBH.cjs');
8
+ var chunkFQ3UCZUX_cjs = require('../../chunk-FQ3UCZUX.cjs');
9
+ var chunk4FALCEJI_cjs = require('../../chunk-4FALCEJI.cjs');
10
+ require('../../chunk-FHY3K6PL.cjs');
11
+ require('../../chunk-IKMR2ADM.cjs');
12
+ var chunkOR5DRJCW_cjs = require('../../chunk-OR5DRJCW.cjs');
13
+ var React4 = require('react');
14
+ var Markdown = require('react-markdown');
15
+ var remarkGfm = require('remark-gfm');
16
+ var rehypeSanitize = require('rehype-sanitize');
17
+ var jsxRuntime = require('react/jsx-runtime');
18
+ var classVarianceAuthority = require('class-variance-authority');
19
+ var lucideReact = require('lucide-react');
20
+ var reactVirtual = require('@tanstack/react-virtual');
21
+
22
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
23
+
24
+ function _interopNamespace(e) {
25
+ if (e && e.__esModule) return e;
26
+ var n = Object.create(null);
27
+ if (e) {
28
+ Object.keys(e).forEach(function (k) {
29
+ if (k !== 'default') {
30
+ var d = Object.getOwnPropertyDescriptor(e, k);
31
+ Object.defineProperty(n, k, d.get ? d : {
32
+ enumerable: true,
33
+ get: function () { return e[k]; }
34
+ });
35
+ }
36
+ });
37
+ }
38
+ n.default = e;
39
+ return Object.freeze(n);
40
+ }
41
+
42
+ var React4__namespace = /*#__PURE__*/_interopNamespace(React4);
43
+ var Markdown__default = /*#__PURE__*/_interopDefault(Markdown);
44
+ var remarkGfm__default = /*#__PURE__*/_interopDefault(remarkGfm);
45
+ var rehypeSanitize__default = /*#__PURE__*/_interopDefault(rehypeSanitize);
46
+
47
+ function remarkPreserveLineBreaks() {
48
+ const splitNode = (node) => {
49
+ if (!node.children) return;
50
+ const next = [];
51
+ for (const child of node.children) {
52
+ if (child.type === "text" && child.value && child.value.includes("\n")) {
53
+ const segments = child.value.split("\n");
54
+ segments.forEach((segment, i) => {
55
+ if (i > 0) next.push({ type: "break" });
56
+ if (segment) next.push({ type: "text", value: segment });
57
+ });
58
+ } else {
59
+ splitNode(child);
60
+ next.push(child);
61
+ }
62
+ }
63
+ node.children = next;
64
+ };
65
+ return (tree) => splitNode(tree);
66
+ }
67
+ function baseSanitizeSchema() {
68
+ const schema = JSON.parse(JSON.stringify(rehypeSanitize.defaultSchema));
69
+ const attributes = schema.attributes ?? {};
70
+ const allowClass = (tag) => {
71
+ const existing = attributes[tag] ?? [];
72
+ const withoutClass = existing.filter(
73
+ (a) => !(Array.isArray(a) && a[0] === "className")
74
+ );
75
+ attributes[tag] = [...withoutClass, "className"];
76
+ };
77
+ allowClass("code");
78
+ allowClass("pre");
79
+ allowClass("span");
80
+ allowClass("div");
81
+ schema.attributes = attributes;
82
+ return schema;
83
+ }
84
+ function mergeSanitizeSchema(base, extra) {
85
+ if (!extra) return base;
86
+ const out = { ...base };
87
+ if (Array.isArray(extra.tagNames)) {
88
+ const a = base.tagNames ?? [];
89
+ out.tagNames = Array.from(/* @__PURE__ */ new Set([...a, ...extra.tagNames]));
90
+ }
91
+ if (extra.attributes && typeof extra.attributes === "object") {
92
+ const baseAttrs = {
93
+ ...base.attributes ?? {}
94
+ };
95
+ for (const [tag, attrs] of Object.entries(
96
+ extra.attributes
97
+ )) {
98
+ baseAttrs[tag] = [...baseAttrs[tag] ?? [], ...attrs];
99
+ }
100
+ out.attributes = baseAttrs;
101
+ }
102
+ if (extra.protocols && typeof extra.protocols === "object") {
103
+ const baseProtocols = {
104
+ ...base.protocols ?? {}
105
+ };
106
+ for (const [attr, protocols] of Object.entries(
107
+ extra.protocols
108
+ )) {
109
+ baseProtocols[attr] = Array.from(
110
+ /* @__PURE__ */ new Set([...baseProtocols[attr] ?? [], ...protocols])
111
+ );
112
+ }
113
+ out.protocols = baseProtocols;
114
+ }
115
+ for (const [k, v] of Object.entries(extra)) {
116
+ if (k === "tagNames" || k === "attributes" || k === "protocols") continue;
117
+ out[k] = v;
118
+ }
119
+ return out;
120
+ }
121
+ function baseComponents() {
122
+ return {
123
+ a: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
124
+ "a",
125
+ {
126
+ ...props,
127
+ className: chunkOR5DRJCW_cjs.cn(
128
+ "text-primary-700 hover:text-primary-800 dark:text-primary-300 underline underline-offset-2",
129
+ props.className
130
+ ),
131
+ target: props.target ?? "_blank",
132
+ rel: props.rel ?? "noopener noreferrer",
133
+ children
134
+ }
135
+ ),
136
+ pre: ({ node: _node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
137
+ "pre",
138
+ {
139
+ ...props,
140
+ className: chunkOR5DRJCW_cjs.cn(
141
+ "overflow-x-auto rounded-lg bg-neutral-900 p-3 text-sm text-neutral-100 dark:bg-neutral-950",
142
+ props.className
143
+ )
144
+ }
145
+ ),
146
+ code: ({ node: _node, ...props }) => {
147
+ const isBlock = typeof props.className === "string" && props.className.includes("language-");
148
+ return /* @__PURE__ */ jsxRuntime.jsx(
149
+ "code",
150
+ {
151
+ ...props,
152
+ className: chunkOR5DRJCW_cjs.cn(
153
+ !isBlock && "rounded bg-neutral-200 px-1 py-0.5 text-[0.85em] dark:bg-neutral-700",
154
+ props.className
155
+ )
156
+ }
157
+ );
158
+ },
159
+ table: ({ node: _node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "my-2 overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsx(
160
+ "table",
161
+ {
162
+ ...props,
163
+ className: chunkOR5DRJCW_cjs.cn(
164
+ "w-full border-collapse text-sm [&_td]:border [&_td]:border-neutral-200 [&_td]:px-2 [&_td]:py-1 dark:[&_td]:border-neutral-700 [&_th]:border [&_th]:border-neutral-200 [&_th]:px-2 [&_th]:py-1 [&_th]:text-left dark:[&_th]:border-neutral-700",
165
+ props.className
166
+ )
167
+ }
168
+ ) }),
169
+ // Tailwind's preflight resets list markers/padding; restore them explicitly
170
+ // so bullets/numbers show without depending on the typography plugin.
171
+ ul: ({ node: _node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("ul", { ...props, className: chunkOR5DRJCW_cjs.cn("list-disc ps-5", props.className) }),
172
+ ol: ({ node: _node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("ol", { ...props, className: chunkOR5DRJCW_cjs.cn("list-decimal ps-5", props.className) }),
173
+ li: ({ node: _node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("li", { ...props, className: chunkOR5DRJCW_cjs.cn("ps-1", props.className) }),
174
+ // Preflight also flattens headings to body size/weight; restore a sensible
175
+ // hierarchy without depending on the typography plugin.
176
+ h1: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
177
+ "h1",
178
+ {
179
+ ...props,
180
+ className: chunkOR5DRJCW_cjs.cn("mt-3 mb-1 text-xl font-semibold", props.className),
181
+ children
182
+ }
183
+ ),
184
+ h2: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
185
+ "h2",
186
+ {
187
+ ...props,
188
+ className: chunkOR5DRJCW_cjs.cn("mt-3 mb-1 text-lg font-semibold", props.className),
189
+ children
190
+ }
191
+ ),
192
+ h3: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
193
+ "h3",
194
+ {
195
+ ...props,
196
+ className: chunkOR5DRJCW_cjs.cn("mt-2 mb-1 text-base font-semibold", props.className),
197
+ children
198
+ }
199
+ ),
200
+ h4: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
201
+ "h4",
202
+ {
203
+ ...props,
204
+ className: chunkOR5DRJCW_cjs.cn("mt-2 mb-1 text-sm font-semibold", props.className),
205
+ children
206
+ }
207
+ ),
208
+ h5: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
209
+ "h5",
210
+ {
211
+ ...props,
212
+ className: chunkOR5DRJCW_cjs.cn("mt-2 mb-1 text-sm font-semibold", props.className),
213
+ children
214
+ }
215
+ ),
216
+ h6: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
217
+ "h6",
218
+ {
219
+ ...props,
220
+ className: chunkOR5DRJCW_cjs.cn(
221
+ "mt-2 mb-1 text-xs font-semibold tracking-wide uppercase",
222
+ props.className
223
+ ),
224
+ children
225
+ }
226
+ ),
227
+ hr: ({ node: _node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
228
+ "hr",
229
+ {
230
+ ...props,
231
+ className: chunkOR5DRJCW_cjs.cn(
232
+ "my-2 border-neutral-300 dark:border-neutral-600",
233
+ props.className
234
+ )
235
+ }
236
+ )
237
+ };
238
+ }
239
+ function createMarkdownRenderer(options = {}) {
240
+ const { plugins = [], trusted = false } = options;
241
+ const remarkPlugins = [
242
+ remarkGfm__default.default,
243
+ remarkPreserveLineBreaks,
244
+ ...plugins.flatMap((p) => p.remarkPlugins ?? [])
245
+ ];
246
+ const pluginRehype = plugins.flatMap(
247
+ (p) => p.rehypePlugins ?? []
248
+ );
249
+ const sanitizeSchema = plugins.reduce(
250
+ (acc, p) => mergeSanitizeSchema(acc, p.sanitizeSchema),
251
+ baseSanitizeSchema()
252
+ );
253
+ const rehypePlugins = trusted ? pluginRehype : [...pluginRehype, [rehypeSanitize__default.default, sanitizeSchema]];
254
+ const components = plugins.reduce(
255
+ (acc, p) => ({ ...acc, ...p.components }),
256
+ baseComponents()
257
+ );
258
+ const MarkdownRenderer = (text, ctx) => /* @__PURE__ */ jsxRuntime.jsx(
259
+ MarkdownContent,
260
+ {
261
+ text,
262
+ messageId: ctx.messageId,
263
+ streaming: ctx.streaming,
264
+ remarkPlugins,
265
+ rehypePlugins,
266
+ components
267
+ },
268
+ ctx.messageId
269
+ );
270
+ return MarkdownRenderer;
271
+ }
272
+ var transformUrl = (url, key, node) => {
273
+ if (key === "src" && node.tagName === "img" && (/^data:image\//i.test(url) || /^blob:/i.test(url))) {
274
+ return url;
275
+ }
276
+ return Markdown.defaultUrlTransform(url);
277
+ };
278
+ var MarkdownContent = React4__namespace.memo(function MarkdownContent2({
279
+ text,
280
+ messageId,
281
+ streaming,
282
+ remarkPlugins,
283
+ rehypePlugins,
284
+ components
285
+ }) {
286
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkJFLC7SHM_cjs.TextRenderContext.Provider, { value: { messageId, streaming }, children: /* @__PURE__ */ jsxRuntime.jsx(
287
+ Markdown__default.default,
288
+ {
289
+ remarkPlugins,
290
+ rehypePlugins,
291
+ urlTransform: transformUrl,
292
+ components,
293
+ children: text
294
+ }
295
+ ) });
296
+ });
297
+ function formatTime(time) {
298
+ return new Date(time).toLocaleTimeString(void 0, {
299
+ hour: "numeric",
300
+ minute: "2-digit"
301
+ });
302
+ }
303
+ function byTime(a, b) {
304
+ return new Date(a.time).getTime() - new Date(b.time).getTime();
305
+ }
306
+ function lastActivityOf(c) {
307
+ if (c.lastActivity) return new Date(c.lastActivity).getTime();
308
+ const last = lastMessageByTime(c.thread);
309
+ return last ? new Date(last.time).getTime() : 0;
310
+ }
311
+ function escapeRegExp(value) {
312
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
313
+ }
314
+ function detectMentions(text, participants) {
315
+ const ids = [];
316
+ for (const p of participants) {
317
+ if (p.kind === "system") continue;
318
+ const token = "@" + p.name.split(" ")[0];
319
+ const pattern = new RegExp(
320
+ `(?<![\\w@])${escapeRegExp(token)}(?![\\w])`,
321
+ "i"
322
+ );
323
+ if (pattern.test(text)) ids.push(p.id);
324
+ }
325
+ return ids;
326
+ }
327
+ function lastMessageByTime(thread) {
328
+ let latest;
329
+ let latestTime = -Infinity;
330
+ for (const message of thread) {
331
+ const t = new Date(message.time).getTime();
332
+ if (t >= latestTime) {
333
+ latest = message;
334
+ latestTime = t;
335
+ }
336
+ }
337
+ return latest;
338
+ }
339
+ function ParticipantAvatar({
340
+ participant
341
+ }) {
342
+ const isAgent = participant?.kind === "agent";
343
+ const backgroundColor = participant?.color ?? (isAgent ? "var(--mieweb-primary-700, #1f2937)" : "#64748b");
344
+ return /* @__PURE__ */ jsxRuntime.jsx(
345
+ chunkFQ3UCZUX_cjs.Avatar,
346
+ {
347
+ size: "xs",
348
+ src: participant?.avatar,
349
+ alt: "",
350
+ name: participant?.name ?? "?",
351
+ fallback: isAgent ? /* @__PURE__ */ jsxRuntime.jsx(chunkPM2I3QKM_cjs.SparklesIcon, { size: "sm" }) : void 0,
352
+ style: { backgroundColor },
353
+ "aria-hidden": "true",
354
+ className: "shrink-0"
355
+ }
356
+ );
357
+ }
358
+ function ReferenceChip({
359
+ reference,
360
+ linkBuilder,
361
+ onReferenceClick
362
+ }) {
363
+ const href = linkBuilder?.(reference);
364
+ const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
365
+ /* @__PURE__ */ jsxRuntime.jsx(
366
+ chunk4FALCEJI_cjs.Badge,
367
+ {
368
+ variant: "default",
369
+ size: "sm",
370
+ className: "rounded px-1.5 text-[10px] font-semibold tracking-wide uppercase",
371
+ children: reference.refType
372
+ }
373
+ ),
374
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: reference.title })
375
+ ] });
376
+ const className = "inline-flex max-w-full items-center gap-2 rounded-lg border border-neutral-200 bg-white px-3 py-1.5 text-sm text-neutral-700 hover:border-primary-300 dark:border-neutral-700 dark:bg-neutral-800 dark:text-neutral-200";
377
+ if (href) {
378
+ return /* @__PURE__ */ jsxRuntime.jsx(
379
+ "a",
380
+ {
381
+ href,
382
+ className,
383
+ onClick: () => onReferenceClick?.(reference),
384
+ children: content
385
+ }
386
+ );
387
+ }
388
+ return /* @__PURE__ */ jsxRuntime.jsx(
389
+ "button",
390
+ {
391
+ type: "button",
392
+ className,
393
+ onClick: () => onReferenceClick?.(reference),
394
+ children: content
395
+ }
396
+ );
397
+ }
398
+ var ATTACHMENT_KIND_CONFIG = {
399
+ image: { accept: "image/*", match: (t) => t.startsWith("image/") },
400
+ video: { accept: "video/*", match: (t) => t.startsWith("video/") },
401
+ audio: { accept: "audio/*", match: (t) => t.startsWith("audio/") },
402
+ pdf: { accept: "application/pdf", match: (t) => t === "application/pdf" }
403
+ };
404
+ var DEFAULT_ACCEPTED_FILE_TYPES = [
405
+ "image",
406
+ "video",
407
+ "audio",
408
+ "pdf"
409
+ ];
410
+ function acceptTokensFor(kinds = DEFAULT_ACCEPTED_FILE_TYPES) {
411
+ const source = kinds.length > 0 ? kinds : DEFAULT_ACCEPTED_FILE_TYPES;
412
+ return Array.from(
413
+ new Set(source.map((k) => ATTACHMENT_KIND_CONFIG[k].accept))
414
+ );
415
+ }
416
+ function filesToComposerAttachments(files) {
417
+ return Promise.all(
418
+ files.map(
419
+ (file, i) => new Promise((resolve, reject) => {
420
+ const reader = new window.FileReader();
421
+ reader.onload = () => {
422
+ const dataUrl = typeof reader.result === "string" ? reader.result : "";
423
+ resolve({
424
+ id: `att-${Date.now()}-${i}`,
425
+ name: file.name || `attachment-${i}`,
426
+ type: file.type || "application/octet-stream",
427
+ dataUrl
428
+ });
429
+ };
430
+ reader.onerror = () => reject(reader.error);
431
+ reader.readAsDataURL(file);
432
+ })
433
+ )
434
+ );
435
+ }
436
+ function CopyMenu({ isSelf, markdown, getHtml, getText }) {
437
+ const [open, setOpen] = React4__namespace.useState(false);
438
+ const [copied, setCopied] = React4__namespace.useState(false);
439
+ const copiedTimer = React4__namespace.useRef(
440
+ void 0
441
+ );
442
+ React4__namespace.useEffect(() => () => window.clearTimeout(copiedTimer.current), []);
443
+ const flash = () => {
444
+ setCopied(true);
445
+ window.clearTimeout(copiedTimer.current);
446
+ copiedTimer.current = setTimeout(() => setCopied(false), 1200);
447
+ };
448
+ const writeText = async (value) => {
449
+ if (!navigator.clipboard?.writeText) {
450
+ throw new Error("Clipboard API unavailable");
451
+ }
452
+ await navigator.clipboard.writeText(value);
453
+ };
454
+ const writeBoth = async () => {
455
+ const html = getHtml();
456
+ const text = markdown || getText();
457
+ try {
458
+ if (typeof window !== "undefined" && "ClipboardItem" in window && navigator.clipboard?.write) {
459
+ await navigator.clipboard.write([
460
+ new window.ClipboardItem({
461
+ "text/html": new Blob([html], { type: "text/html" }),
462
+ "text/plain": new Blob([text], { type: "text/plain" })
463
+ })
464
+ ]);
465
+ } else {
466
+ await writeText(text);
467
+ }
468
+ } catch {
469
+ await writeText(text);
470
+ }
471
+ };
472
+ const run = (fn) => {
473
+ setOpen(false);
474
+ void fn().then(flash, () => {
475
+ });
476
+ };
477
+ return /* @__PURE__ */ jsxRuntime.jsx(
478
+ "div",
479
+ {
480
+ className: chunkOR5DRJCW_cjs.cn(
481
+ "sticky bottom-2 shrink-0 self-end",
482
+ // Rich content (e.g. NITRO tables) layers internals up to z-50, so the
483
+ // open menu's stacking context must clear that.
484
+ open ? "z-[60]" : "z-10"
485
+ ),
486
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
487
+ chunkH4T5T65N_cjs.Dropdown,
488
+ {
489
+ open,
490
+ onOpenChange: setOpen,
491
+ placement: isSelf ? "top-end" : "top-start",
492
+ trigger: /* @__PURE__ */ jsxRuntime.jsx(
493
+ "button",
494
+ {
495
+ type: "button",
496
+ "data-slot": "superchat-copy-button",
497
+ "aria-label": "Copy message",
498
+ className: "rounded p-1 text-neutral-400 opacity-0 transition-opacity group-focus-within:opacity-100 group-hover:opacity-100 hover:text-neutral-600 focus-visible:opacity-100 dark:hover:text-neutral-200",
499
+ children: copied ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { size: 14, "aria-hidden": "true" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clipboard, { size: 14, "aria-hidden": "true" })
500
+ }
501
+ ),
502
+ children: [
503
+ /* @__PURE__ */ jsxRuntime.jsx(chunkH4T5T65N_cjs.DropdownItem, { onClick: () => run(writeBoth), children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex flex-col items-start", children: [
504
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Copy" }),
505
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-normal text-neutral-400", children: "Rich text + Markdown" })
506
+ ] }) }),
507
+ /* @__PURE__ */ jsxRuntime.jsx(
508
+ chunkH4T5T65N_cjs.DropdownItem,
509
+ {
510
+ onClick: () => run(() => writeText(markdown || getText())),
511
+ children: "Copy as Markdown"
512
+ }
513
+ ),
514
+ /* @__PURE__ */ jsxRuntime.jsx(chunkH4T5T65N_cjs.DropdownItem, { onClick: () => run(() => writeText(getText())), children: "Copy as plain text" })
515
+ ]
516
+ }
517
+ )
518
+ }
519
+ );
520
+ }
521
+ var MessageRow = React4__namespace.memo(function MessageRow2({
522
+ message,
523
+ participant,
524
+ isSelf,
525
+ renderText,
526
+ linkBuilder,
527
+ onReferenceClick,
528
+ editable,
529
+ onMessageEdited
530
+ }) {
531
+ const streaming = message.status === "streaming";
532
+ const hasBody = !!message.text || (message.content?.length ?? 0) > 0;
533
+ const [isEditing, setIsEditing] = React4__namespace.useState(false);
534
+ const [draft, setDraft] = React4__namespace.useState(message.text ?? "");
535
+ const editRef = React4__namespace.useRef(null);
536
+ const bubbleRef = React4__namespace.useRef(null);
537
+ const autosize = React4__namespace.useCallback(() => {
538
+ const el = editRef.current;
539
+ if (!el) return;
540
+ el.style.height = "auto";
541
+ el.style.height = `${el.scrollHeight}px`;
542
+ }, []);
543
+ React4__namespace.useEffect(() => {
544
+ if (!isEditing) return;
545
+ const el = editRef.current;
546
+ if (!el) return;
547
+ el.focus();
548
+ el.setSelectionRange(el.value.length, el.value.length);
549
+ autosize();
550
+ }, [isEditing, autosize]);
551
+ if (message.type === "system") {
552
+ return /* @__PURE__ */ jsxRuntime.jsx(
553
+ "div",
554
+ {
555
+ "data-slot": "superchat-system-message",
556
+ role: "status",
557
+ className: "my-1 text-center text-xs text-neutral-500 dark:text-neutral-400",
558
+ children: message.text
559
+ }
560
+ );
561
+ }
562
+ if (message.type === "ref" && message.ref) {
563
+ return /* @__PURE__ */ jsxRuntime.jsx(
564
+ "div",
565
+ {
566
+ "data-slot": "superchat-reference",
567
+ className: chunkOR5DRJCW_cjs.cn("flex", isSelf && "justify-end"),
568
+ children: /* @__PURE__ */ jsxRuntime.jsx(
569
+ ReferenceChip,
570
+ {
571
+ reference: message.ref,
572
+ linkBuilder,
573
+ onReferenceClick
574
+ }
575
+ )
576
+ }
577
+ );
578
+ }
579
+ const accent = participant?.color;
580
+ const authorName = participant?.name ?? "Unknown";
581
+ const canEdit = !!editable && isSelf && !streaming && typeof message.text === "string" && !message.content?.length;
582
+ const startEdit = () => {
583
+ setDraft(message.text ?? "");
584
+ setIsEditing(true);
585
+ };
586
+ const cancelEdit = () => setIsEditing(false);
587
+ const saveEdit = () => {
588
+ const next = draft.trim();
589
+ if (next && next !== message.text) onMessageEdited?.(message.id, next);
590
+ setIsEditing(false);
591
+ };
592
+ const handleEditPaste = (e) => {
593
+ const files = Array.from(e.clipboardData.items).filter((item) => item.kind === "file" && item.type.startsWith("image/")).map((item) => item.getAsFile()).filter((f) => f !== null);
594
+ if (files.length === 0) return;
595
+ e.preventDefault();
596
+ const el = e.currentTarget;
597
+ const start = el.selectionStart ?? draft.length;
598
+ const end = el.selectionEnd ?? draft.length;
599
+ Promise.all(
600
+ files.map(
601
+ (file, i) => new Promise((resolve) => {
602
+ const reader = new window.FileReader();
603
+ reader.onload = () => {
604
+ const dataUrl = typeof reader.result === "string" ? reader.result : "";
605
+ const name = file.name || `pasted-image-${i + 1}.png`;
606
+ resolve(dataUrl ? `![${name}](${dataUrl})` : "");
607
+ };
608
+ reader.readAsDataURL(file);
609
+ })
610
+ )
611
+ ).then((snippets) => {
612
+ const insert = snippets.filter(Boolean).join("\n");
613
+ if (!insert) return;
614
+ el.focus();
615
+ el.setSelectionRange(start, end);
616
+ const text = `${insert}
617
+ `;
618
+ const inserted = typeof document !== "undefined" && typeof document.execCommand === "function" && document.execCommand("insertText", false, text);
619
+ if (!inserted) {
620
+ setDraft((prev) => `${prev.slice(0, start)}${text}${prev.slice(end)}`);
621
+ }
622
+ requestAnimationFrame(autosize);
623
+ });
624
+ };
625
+ const markdownSource = typeof message.text === "string" && message.text ? message.text : message.content?.map((block) => {
626
+ if (block.type === "code" && block.text) {
627
+ return `\`\`\`${block.language ?? ""}
628
+ ${block.text}
629
+ \`\`\``;
630
+ }
631
+ if ((block.type === "text" || block.type === "thinking") && block.text) {
632
+ return block.text;
633
+ }
634
+ return "";
635
+ }).filter(Boolean).join("\n\n") ?? "";
636
+ const canCopy = !isEditing && (!!message.content?.length || typeof message.text === "string" && message.text.length > 0);
637
+ return /* @__PURE__ */ jsxRuntime.jsxs(
638
+ "div",
639
+ {
640
+ "data-slot": "superchat-message",
641
+ role: "article",
642
+ "aria-label": `${authorName}, ${formatTime(message.time)}`,
643
+ className: chunkOR5DRJCW_cjs.cn(
644
+ "group flex gap-2",
645
+ isSelf ? "flex-row-reverse" : "flex-row"
646
+ ),
647
+ children: [
648
+ /* @__PURE__ */ jsxRuntime.jsx(ParticipantAvatar, { participant }),
649
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkOR5DRJCW_cjs.cn("flex min-w-0 flex-col gap-1", isSelf && "items-end"), children: [
650
+ /* @__PURE__ */ jsxRuntime.jsxs(
651
+ "div",
652
+ {
653
+ "data-slot": "superchat-message-meta",
654
+ className: "flex items-baseline gap-2",
655
+ children: [
656
+ /* @__PURE__ */ jsxRuntime.jsx(
657
+ "span",
658
+ {
659
+ className: "text-xs font-medium",
660
+ style: accent ? { color: accent } : void 0,
661
+ children: authorName
662
+ }
663
+ ),
664
+ participant?.role && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-neutral-400", children: participant.role }),
665
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-neutral-400", children: formatTime(message.time) }),
666
+ message.editedAt && /* @__PURE__ */ jsxRuntime.jsx(
667
+ "span",
668
+ {
669
+ "data-slot": "superchat-edited-indicator",
670
+ className: "text-[10px] text-neutral-400",
671
+ title: `Edited ${formatTime(message.editedAt)}`,
672
+ children: "(edited)"
673
+ }
674
+ ),
675
+ canEdit && !isEditing && /* @__PURE__ */ jsxRuntime.jsx(
676
+ "button",
677
+ {
678
+ type: "button",
679
+ "data-slot": "superchat-edit-button",
680
+ onClick: startEdit,
681
+ "aria-label": "Edit message",
682
+ className: "rounded p-0.5 text-neutral-400 opacity-0 transition-opacity group-focus-within:opacity-100 group-hover:opacity-100 hover:text-neutral-600 focus-visible:opacity-100 dark:hover:text-neutral-200",
683
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { size: 14, "aria-hidden": "true" })
684
+ }
685
+ )
686
+ ]
687
+ }
688
+ ),
689
+ /* @__PURE__ */ jsxRuntime.jsxs(
690
+ "div",
691
+ {
692
+ className: chunkOR5DRJCW_cjs.cn(
693
+ "flex items-center gap-1",
694
+ isSelf ? "flex-row-reverse" : "flex-row"
695
+ ),
696
+ children: [
697
+ canCopy && /* @__PURE__ */ jsxRuntime.jsx(
698
+ CopyMenu,
699
+ {
700
+ isSelf,
701
+ markdown: markdownSource,
702
+ getHtml: () => bubbleRef.current?.innerHTML ?? "",
703
+ getText: () => bubbleRef.current?.textContent ?? ""
704
+ }
705
+ ),
706
+ /* @__PURE__ */ jsxRuntime.jsx(
707
+ chunkPM2I3QKM_cjs.ChatBubble,
708
+ {
709
+ ref: bubbleRef,
710
+ "data-slot": "superchat-bubble",
711
+ variant: isSelf ? "user" : "assistant",
712
+ hasError: message.status === "error",
713
+ className: "text-sm",
714
+ children: isEditing ? /* @__PURE__ */ jsxRuntime.jsxs(
715
+ "div",
716
+ {
717
+ "data-slot": "superchat-message-editor",
718
+ className: "flex w-80 max-w-full flex-col gap-2",
719
+ children: [
720
+ /* @__PURE__ */ jsxRuntime.jsx(
721
+ "textarea",
722
+ {
723
+ value: draft,
724
+ ref: editRef,
725
+ rows: 2,
726
+ onChange: (e) => {
727
+ setDraft(e.target.value);
728
+ autosize();
729
+ },
730
+ onPaste: handleEditPaste,
731
+ onKeyDown: (e) => {
732
+ if (e.key === "Enter" && !e.shiftKey) {
733
+ e.preventDefault();
734
+ saveEdit();
735
+ } else if (e.key === "Escape") {
736
+ e.preventDefault();
737
+ cancelEdit();
738
+ }
739
+ },
740
+ "aria-label": "Edit message",
741
+ className: "focus:ring-primary-500 max-h-60 min-h-16 w-full resize-none rounded-lg border border-neutral-300 bg-white px-3 py-2 text-sm text-neutral-900 focus:ring-1 focus:outline-none dark:border-neutral-600 dark:bg-neutral-900 dark:text-white"
742
+ }
743
+ ),
744
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
745
+ /* @__PURE__ */ jsxRuntime.jsx(
746
+ "button",
747
+ {
748
+ type: "button",
749
+ onClick: cancelEdit,
750
+ className: "rounded-md px-2.5 py-1 text-xs font-medium text-neutral-200 hover:bg-white/10",
751
+ children: "Cancel"
752
+ }
753
+ ),
754
+ /* @__PURE__ */ jsxRuntime.jsx(
755
+ "button",
756
+ {
757
+ type: "button",
758
+ onClick: saveEdit,
759
+ disabled: !draft.trim() || draft.trim() === message.text,
760
+ className: "rounded-md bg-white px-2.5 py-1 text-xs font-medium text-neutral-900 hover:bg-neutral-100 disabled:opacity-40",
761
+ children: "Save"
762
+ }
763
+ )
764
+ ] })
765
+ ]
766
+ }
767
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
768
+ message.content?.map((block, i) => {
769
+ if (block.type === "tool_use" && block.toolCall) {
770
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkPM2I3QKM_cjs.MCPToolCallDisplay, { toolCall: block.toolCall }, i);
771
+ }
772
+ if ((block.type === "text" || block.type === "thinking") && block.text) {
773
+ return /* @__PURE__ */ jsxRuntime.jsx(
774
+ "div",
775
+ {
776
+ className: "prose prose-sm dark:prose-invert max-w-none **:wrap-break-word",
777
+ children: renderText(block.text, {
778
+ messageId: message.id,
779
+ streaming,
780
+ role: participant?.kind === "human" ? "user" : "assistant"
781
+ })
782
+ },
783
+ i
784
+ );
785
+ }
786
+ if (block.type === "code" && block.text) {
787
+ const fenced = `\`\`\`${block.language ?? ""}
788
+ ${block.text}
789
+ \`\`\``;
790
+ return /* @__PURE__ */ jsxRuntime.jsx(
791
+ "div",
792
+ {
793
+ className: "prose prose-sm dark:prose-invert max-w-none **:wrap-break-word",
794
+ children: renderText(fenced, {
795
+ messageId: message.id,
796
+ streaming,
797
+ role: participant?.kind === "human" ? "user" : "assistant"
798
+ })
799
+ },
800
+ i
801
+ );
802
+ }
803
+ return null;
804
+ }),
805
+ message.text && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "prose prose-sm dark:prose-invert max-w-none **:wrap-break-word", children: renderText(message.text, {
806
+ messageId: message.id,
807
+ streaming,
808
+ role: participant?.kind === "human" ? "user" : "assistant"
809
+ }) }),
810
+ streaming && !hasBody && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(chunkPM2I3QKM_cjs.AITypingIndicator, {}) })
811
+ ] })
812
+ }
813
+ )
814
+ ]
815
+ }
816
+ )
817
+ ] })
818
+ ]
819
+ }
820
+ );
821
+ });
822
+ var sidebarItem = classVarianceAuthority.cva(
823
+ "flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-sm transition-colors",
824
+ {
825
+ variants: {
826
+ active: {
827
+ true: "bg-primary-100 text-primary-900 dark:bg-primary-900/40 dark:text-primary-100",
828
+ false: "text-neutral-700 hover:bg-neutral-100 dark:text-neutral-200 dark:hover:bg-neutral-800"
829
+ }
830
+ },
831
+ defaultVariants: { active: false }
832
+ }
833
+ );
834
+ function VirtualThread({
835
+ items,
836
+ participantById,
837
+ currentParticipantId,
838
+ renderText,
839
+ linkBuilder,
840
+ onReferenceClick,
841
+ editable,
842
+ onMessageEdited,
843
+ order,
844
+ conversationId,
845
+ containerProps
846
+ }) {
847
+ const parentRef = React4__namespace.useRef(null);
848
+ const virtualizer = reactVirtual.useVirtualizer({
849
+ count: items.length,
850
+ getScrollElement: () => parentRef.current,
851
+ // Rough first guess; real heights are measured via measureElement.
852
+ estimateSize: () => 88,
853
+ overscan: 10,
854
+ getItemKey: (index) => items[index]?.id ?? index
855
+ });
856
+ const count = items.length;
857
+ React4__namespace.useEffect(() => {
858
+ if (count === 0) return;
859
+ if (order === "desc") {
860
+ virtualizer.scrollToIndex(0, { align: "start" });
861
+ } else {
862
+ virtualizer.scrollToIndex(count - 1, { align: "end" });
863
+ }
864
+ }, [count, conversationId, order]);
865
+ const virtualItems = virtualizer.getVirtualItems();
866
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ...containerProps, ref: parentRef, children: /* @__PURE__ */ jsxRuntime.jsx(
867
+ "div",
868
+ {
869
+ style: {
870
+ height: virtualizer.getTotalSize(),
871
+ position: "relative",
872
+ width: "100%"
873
+ },
874
+ children: virtualItems.map((virtualRow) => {
875
+ const message = items[virtualRow.index];
876
+ if (!message) return null;
877
+ return /* @__PURE__ */ jsxRuntime.jsx(
878
+ "div",
879
+ {
880
+ "data-index": virtualRow.index,
881
+ ref: virtualizer.measureElement,
882
+ style: {
883
+ position: "absolute",
884
+ top: 0,
885
+ left: 0,
886
+ width: "100%",
887
+ transform: `translateY(${virtualRow.start}px)`
888
+ },
889
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pb-4", children: /* @__PURE__ */ jsxRuntime.jsx(
890
+ MessageRow,
891
+ {
892
+ message,
893
+ participant: participantById.get(message.participantId),
894
+ isSelf: !!currentParticipantId && message.participantId === currentParticipantId,
895
+ renderText,
896
+ linkBuilder,
897
+ onReferenceClick,
898
+ editable,
899
+ onMessageEdited
900
+ }
901
+ ) })
902
+ },
903
+ virtualRow.key
904
+ );
905
+ })
906
+ }
907
+ ) });
908
+ }
909
+ function SuperChat({
910
+ conversation,
911
+ currentParticipantId,
912
+ renderPlugins,
913
+ renderTextContent,
914
+ trustedContent,
915
+ readOnly,
916
+ acceptedFileTypes,
917
+ order = "asc",
918
+ virtualized = false,
919
+ linkBuilder,
920
+ className,
921
+ onMessageSent,
922
+ onMessageEdited,
923
+ onConversationClosed,
924
+ onReferenceClick,
925
+ onBack
926
+ }) {
927
+ const headingId = React4__namespace.useId();
928
+ const renderText = React4__namespace.useMemo(
929
+ () => renderTextContent ?? createMarkdownRenderer({
930
+ plugins: renderPlugins,
931
+ trusted: trustedContent
932
+ }),
933
+ [renderTextContent, renderPlugins, trustedContent]
934
+ );
935
+ const threadRef = React4__namespace.useRef(null);
936
+ React4__namespace.useEffect(() => {
937
+ if (virtualized) return;
938
+ const el = threadRef.current;
939
+ if (!el) return;
940
+ el.scrollTop = order === "desc" ? 0 : el.scrollHeight;
941
+ }, [conversation.thread.length, conversation.id, order, virtualized]);
942
+ const participantById = React4__namespace.useMemo(() => {
943
+ const map = /* @__PURE__ */ new Map();
944
+ conversation.participants.forEach((p) => map.set(p.id, p));
945
+ return map;
946
+ }, [conversation]);
947
+ const orderedThread = React4__namespace.useMemo(() => {
948
+ const sorted = [...conversation.thread].sort(byTime);
949
+ return order === "desc" ? sorted.reverse() : sorted;
950
+ }, [conversation, order]);
951
+ const onMessageEditedRef = React4__namespace.useRef(onMessageEdited);
952
+ onMessageEditedRef.current = onMessageEdited;
953
+ const conversationRef = React4__namespace.useRef(conversation);
954
+ conversationRef.current = conversation;
955
+ const handleMessageEdited = React4__namespace.useCallback(
956
+ (messageId, text) => {
957
+ onMessageEditedRef.current?.(messageId, text, {
958
+ conversation: conversationRef.current
959
+ });
960
+ },
961
+ []
962
+ );
963
+ const editable = !readOnly && !!onMessageEdited;
964
+ const mentionOptions = React4__namespace.useMemo(
965
+ () => conversation.participants.filter((p) => p.kind !== "system").map((p) => ({
966
+ id: p.id,
967
+ label: p.name,
968
+ description: p.role,
969
+ meta: p.kind,
970
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ParticipantAvatar, { participant: p })
971
+ })),
972
+ [conversation.participants]
973
+ );
974
+ const composerAccept = React4__namespace.useMemo(
975
+ () => acceptTokensFor(acceptedFileTypes),
976
+ [acceptedFileTypes]
977
+ );
978
+ const handleComposerSend = React4__namespace.useCallback(
979
+ async (message) => {
980
+ const text = message.content;
981
+ const mentions = detectMentions(text, conversation.participants);
982
+ const attachments = await filesToComposerAttachments(
983
+ message.attachments ?? []
984
+ );
985
+ onMessageSent?.(text, { conversation, mentions, attachments });
986
+ },
987
+ [conversation, onMessageSent]
988
+ );
989
+ return /* @__PURE__ */ jsxRuntime.jsxs(
990
+ "section",
991
+ {
992
+ "data-slot": "superchat",
993
+ role: "group",
994
+ "aria-labelledby": headingId,
995
+ className: chunkOR5DRJCW_cjs.cn(
996
+ "flex min-w-0 flex-1 flex-col bg-white dark:bg-neutral-900",
997
+ className
998
+ ),
999
+ children: [
1000
+ /* @__PURE__ */ jsxRuntime.jsxs(
1001
+ "header",
1002
+ {
1003
+ "data-slot": "superchat-header",
1004
+ className: "flex items-center justify-between gap-2 border-b border-neutral-200 p-3 dark:border-neutral-700",
1005
+ children: [
1006
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
1007
+ onBack && /* @__PURE__ */ jsxRuntime.jsx(
1008
+ "button",
1009
+ {
1010
+ type: "button",
1011
+ onClick: onBack,
1012
+ "aria-label": "Back to conversations",
1013
+ className: "-ml-1 shrink-0 rounded-md p-1 text-neutral-500 hover:bg-neutral-100 sm:hidden dark:text-neutral-300 dark:hover:bg-neutral-800",
1014
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1015
+ "svg",
1016
+ {
1017
+ viewBox: "0 0 24 24",
1018
+ width: "20",
1019
+ height: "20",
1020
+ fill: "none",
1021
+ stroke: "currentColor",
1022
+ strokeWidth: "2",
1023
+ strokeLinecap: "round",
1024
+ strokeLinejoin: "round",
1025
+ "aria-hidden": "true",
1026
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m15 18-6-6 6-6" })
1027
+ }
1028
+ )
1029
+ }
1030
+ ),
1031
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
1032
+ /* @__PURE__ */ jsxRuntime.jsx(
1033
+ "h2",
1034
+ {
1035
+ id: headingId,
1036
+ className: "truncate text-sm font-semibold text-neutral-800 dark:text-neutral-100",
1037
+ children: conversation.title
1038
+ }
1039
+ ),
1040
+ /* @__PURE__ */ jsxRuntime.jsx(
1041
+ "div",
1042
+ {
1043
+ "data-slot": "superchat-participants",
1044
+ role: "group",
1045
+ "aria-label": "Participants",
1046
+ className: "mt-0.5 flex items-center gap-1",
1047
+ children: conversation.participants.slice(0, 6).map((p) => /* @__PURE__ */ jsxRuntime.jsx("span", { role: "img", "aria-label": p.name, children: /* @__PURE__ */ jsxRuntime.jsx(ParticipantAvatar, { participant: p }) }, p.id))
1048
+ }
1049
+ )
1050
+ ] })
1051
+ ] }),
1052
+ onConversationClosed && /* @__PURE__ */ jsxRuntime.jsx(
1053
+ "button",
1054
+ {
1055
+ type: "button",
1056
+ onClick: () => onConversationClosed(conversation),
1057
+ "aria-label": "Close conversation",
1058
+ className: "rounded-md p-1 text-neutral-400 hover:bg-neutral-100 dark:hover:bg-neutral-800",
1059
+ children: /* @__PURE__ */ jsxRuntime.jsx(chunkPM2I3QKM_cjs.CloseIcon, {})
1060
+ }
1061
+ )
1062
+ ]
1063
+ }
1064
+ ),
1065
+ virtualized ? /* @__PURE__ */ jsxRuntime.jsx(
1066
+ VirtualThread,
1067
+ {
1068
+ items: orderedThread,
1069
+ participantById,
1070
+ currentParticipantId,
1071
+ renderText,
1072
+ linkBuilder,
1073
+ onReferenceClick,
1074
+ editable,
1075
+ onMessageEdited: handleMessageEdited,
1076
+ order,
1077
+ conversationId: conversation.id,
1078
+ containerProps: {
1079
+ "data-slot": "superchat-thread",
1080
+ role: "log",
1081
+ "aria-label": "Messages",
1082
+ "aria-live": "polite",
1083
+ // Focusable so keyboard-only users can scroll the message history.
1084
+ tabIndex: 0,
1085
+ className: "flex-1 overflow-y-auto p-4"
1086
+ }
1087
+ }
1088
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1089
+ "div",
1090
+ {
1091
+ "data-slot": "superchat-thread",
1092
+ ref: threadRef,
1093
+ role: "log",
1094
+ "aria-label": "Messages",
1095
+ "aria-live": "polite",
1096
+ tabIndex: 0,
1097
+ className: "flex-1 space-y-4 overflow-y-auto p-4",
1098
+ children: orderedThread.map((m) => /* @__PURE__ */ jsxRuntime.jsx(
1099
+ MessageRow,
1100
+ {
1101
+ message: m,
1102
+ participant: participantById.get(m.participantId),
1103
+ isSelf: !!currentParticipantId && m.participantId === currentParticipantId,
1104
+ renderText,
1105
+ linkBuilder,
1106
+ onReferenceClick,
1107
+ editable,
1108
+ onMessageEdited: handleMessageEdited
1109
+ },
1110
+ m.id
1111
+ ))
1112
+ }
1113
+ ),
1114
+ /* @__PURE__ */ jsxRuntime.jsx(
1115
+ chunk2T4JU5RH_cjs.MessageComposer,
1116
+ {
1117
+ onSend: handleComposerSend,
1118
+ disabled: readOnly,
1119
+ placeholder: readOnly ? "Read-only conversation" : "Type a message\u2026 use @ to address an agent",
1120
+ mentionOptions,
1121
+ showAttachmentPicker: !readOnly,
1122
+ showCameraButton: false,
1123
+ acceptedFileTypes: composerAccept,
1124
+ maxLength: 1e5
1125
+ }
1126
+ )
1127
+ ]
1128
+ }
1129
+ );
1130
+ }
1131
+ function SuperChatConversations({
1132
+ conversations,
1133
+ activeConversationId,
1134
+ defaultActiveConversationId,
1135
+ className,
1136
+ onConversationOpened,
1137
+ onNewConversation
1138
+ }) {
1139
+ const [internalActive, setInternalActive] = React4__namespace.useState(
1140
+ defaultActiveConversationId ?? conversations[0]?.id
1141
+ );
1142
+ const requestedId = activeConversationId ?? internalActive;
1143
+ const activeId = conversations.some((c) => c.id === requestedId) ? requestedId : conversations[0]?.id;
1144
+ const sortedConversations = React4__namespace.useMemo(
1145
+ () => [...conversations].sort((a, b) => lastActivityOf(b) - lastActivityOf(a)),
1146
+ [conversations]
1147
+ );
1148
+ const selectConversation = (c) => {
1149
+ if (activeConversationId === void 0) setInternalActive(c.id);
1150
+ onConversationOpened?.(c);
1151
+ };
1152
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1153
+ "aside",
1154
+ {
1155
+ "data-slot": "superchat-conversations",
1156
+ "aria-label": "Conversations",
1157
+ className: chunkOR5DRJCW_cjs.cn(
1158
+ "flex w-64 shrink-0 flex-col border-r border-neutral-200 dark:border-neutral-700",
1159
+ className
1160
+ ),
1161
+ children: [
1162
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-3", children: [
1163
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-neutral-700 dark:text-neutral-200", children: "Conversations" }),
1164
+ onNewConversation && /* @__PURE__ */ jsxRuntime.jsx(
1165
+ "button",
1166
+ {
1167
+ type: "button",
1168
+ onClick: onNewConversation,
1169
+ "aria-label": "New conversation",
1170
+ className: "rounded-md px-2 py-1 text-lg leading-none text-neutral-500 hover:bg-neutral-100 dark:hover:bg-neutral-800",
1171
+ children: "+"
1172
+ }
1173
+ )
1174
+ ] }),
1175
+ /* @__PURE__ */ jsxRuntime.jsx(
1176
+ "div",
1177
+ {
1178
+ "data-slot": "superchat-conversation-list",
1179
+ role: "list",
1180
+ className: "flex-1 space-y-1 overflow-y-auto px-2 pb-2",
1181
+ children: sortedConversations.map((c) => {
1182
+ const last = lastMessageByTime(c.thread);
1183
+ const isActive = c.id === activeId;
1184
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "listitem", children: /* @__PURE__ */ jsxRuntime.jsxs(
1185
+ "button",
1186
+ {
1187
+ type: "button",
1188
+ "aria-current": isActive ? "true" : void 0,
1189
+ onClick: () => selectConversation(c),
1190
+ className: sidebarItem({ active: isActive }),
1191
+ children: [
1192
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex-1 truncate", children: [
1193
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block truncate font-medium", children: c.title }),
1194
+ last?.text && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block truncate text-xs text-neutral-400", children: last.text })
1195
+ ] }),
1196
+ !!c.unread && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "bg-primary-600 ml-1 inline-flex h-5 min-w-5 items-center justify-center rounded-full px-1.5 text-[10px] font-semibold text-white", children: [
1197
+ c.unread,
1198
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: " unread messages" })
1199
+ ] })
1200
+ ]
1201
+ }
1202
+ ) }, c.id);
1203
+ })
1204
+ }
1205
+ )
1206
+ ]
1207
+ }
1208
+ );
1209
+ }
1210
+ function SuperChatInbox({
1211
+ conversations,
1212
+ activeConversationId,
1213
+ defaultActiveConversationId,
1214
+ currentParticipantId,
1215
+ renderPlugins,
1216
+ renderTextContent,
1217
+ trustedContent,
1218
+ readOnly,
1219
+ acceptedFileTypes,
1220
+ order,
1221
+ virtualized,
1222
+ showSidebar = true,
1223
+ linkBuilder,
1224
+ className,
1225
+ onMessageSent,
1226
+ onMessageEdited,
1227
+ onConversationOpened,
1228
+ onConversationClosed,
1229
+ onNewConversation,
1230
+ onReferenceClick
1231
+ }) {
1232
+ const [internalActive, setInternalActive] = React4__namespace.useState(
1233
+ defaultActiveConversationId ?? conversations[0]?.id
1234
+ );
1235
+ const requestedId = activeConversationId ?? internalActive;
1236
+ const active = conversations.find((c) => c.id === requestedId) ?? conversations[0];
1237
+ const activeId = active?.id;
1238
+ const [mobileView, setMobileView] = React4__namespace.useState("list");
1239
+ const handleOpen = (c) => {
1240
+ if (activeConversationId === void 0) setInternalActive(c.id);
1241
+ setMobileView("chat");
1242
+ onConversationOpened?.(c);
1243
+ };
1244
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1245
+ "div",
1246
+ {
1247
+ "data-slot": "superchat-inbox",
1248
+ role: "group",
1249
+ "aria-label": active ? `Chat: ${active.title}` : "Chat",
1250
+ className: chunkOR5DRJCW_cjs.cn(
1251
+ "flex h-full overflow-hidden rounded-xl border border-neutral-200 bg-white dark:border-neutral-700 dark:bg-neutral-900",
1252
+ className
1253
+ ),
1254
+ children: [
1255
+ showSidebar && /* @__PURE__ */ jsxRuntime.jsx(
1256
+ SuperChatConversations,
1257
+ {
1258
+ conversations,
1259
+ activeConversationId: activeId,
1260
+ onConversationOpened: handleOpen,
1261
+ onNewConversation,
1262
+ className: chunkOR5DRJCW_cjs.cn(
1263
+ "w-full sm:w-64",
1264
+ mobileView === "chat" && "hidden sm:flex"
1265
+ )
1266
+ }
1267
+ ),
1268
+ active ? /* @__PURE__ */ jsxRuntime.jsx(
1269
+ SuperChat,
1270
+ {
1271
+ conversation: active,
1272
+ currentParticipantId,
1273
+ renderPlugins,
1274
+ renderTextContent,
1275
+ trustedContent,
1276
+ readOnly,
1277
+ acceptedFileTypes,
1278
+ order,
1279
+ virtualized,
1280
+ linkBuilder,
1281
+ onMessageSent,
1282
+ onMessageEdited,
1283
+ onConversationClosed,
1284
+ onReferenceClick,
1285
+ onBack: showSidebar ? () => setMobileView("list") : void 0,
1286
+ className: chunkOR5DRJCW_cjs.cn(
1287
+ showSidebar && mobileView === "list" && "hidden sm:flex"
1288
+ )
1289
+ }
1290
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1291
+ "section",
1292
+ {
1293
+ "data-slot": "superchat",
1294
+ className: chunkOR5DRJCW_cjs.cn(
1295
+ "min-w-0 flex-1 items-center justify-center text-sm text-neutral-400",
1296
+ showSidebar && mobileView === "list" ? "hidden sm:flex" : "flex"
1297
+ ),
1298
+ children: "No conversation selected"
1299
+ }
1300
+ )
1301
+ ]
1302
+ }
1303
+ );
1304
+ }
1305
+
1306
+ Object.defineProperty(exports, "TextRenderContext", {
1307
+ enumerable: true,
1308
+ get: function () { return chunkJFLC7SHM_cjs.TextRenderContext; }
1309
+ });
1310
+ Object.defineProperty(exports, "useTextRenderContext", {
1311
+ enumerable: true,
1312
+ get: function () { return chunkJFLC7SHM_cjs.useTextRenderContext; }
1313
+ });
1314
+ exports.SuperChat = SuperChat;
1315
+ exports.SuperChatConversations = SuperChatConversations;
1316
+ exports.SuperChatInbox = SuperChatInbox;
1317
+ exports.createMarkdownRenderer = createMarkdownRenderer;
1318
+ //# sourceMappingURL=index.cjs.map
1319
+ //# sourceMappingURL=index.cjs.map